summaryrefslogtreecommitdiff
path: root/support/cpp/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'support/cpp/gcc')
-rw-r--r--support/cpp/gcc/BASE-VER1
-rw-r--r--support/cpp/gcc/DATESTAMP1
-rw-r--r--support/cpp/gcc/DEV-PHASE0
-rw-r--r--support/cpp/gcc/Makefile.in4044
-rw-r--r--support/cpp/gcc/acinclude.m4539
-rw-r--r--support/cpp/gcc/aclocal.m442
-rw-r--r--support/cpp/gcc/alias.h50
-rw-r--r--support/cpp/gcc/align.h83
-rw-r--r--support/cpp/gcc/alloc-pool.h576
-rw-r--r--support/cpp/gcc/analyzer/analyzer.opt257
-rw-r--r--support/cpp/gcc/array-traits.h48
-rw-r--r--support/cpp/gcc/asan.h263
-rw-r--r--support/cpp/gcc/attribs.h346
-rw-r--r--support/cpp/gcc/backend.h35
-rw-r--r--support/cpp/gcc/basic-block.h650
-rw-r--r--support/cpp/gcc/bitmap.h1089
-rw-r--r--support/cpp/gcc/builtin-attrs.def427
-rw-r--r--support/cpp/gcc/builtin-types.def874
-rw-r--r--support/cpp/gcc/builtins.def1073
-rw-r--r--support/cpp/gcc/c-family/c-ada-spec.h44
-rw-r--r--support/cpp/gcc/c-family/c-common.cc9583
-rw-r--r--support/cpp/gcc/c-family/c-common.def89
-rw-r--r--support/cpp/gcc/c-family/c-common.h1541
-rw-r--r--support/cpp/gcc/c-family/c-cppbuiltin.cc2053
-rw-r--r--support/cpp/gcc/c-family/c-dump.cc91
-rw-r--r--support/cpp/gcc/c-family/c-format.h354
-rw-r--r--support/cpp/gcc/c-family/c-indentation.cc815
-rw-r--r--support/cpp/gcc/c-family/c-indentation.h54
-rw-r--r--support/cpp/gcc/c-family/c-lex.cc1518
-rw-r--r--support/cpp/gcc/c-family/c-objc.h183
-rw-r--r--support/cpp/gcc/c-family/c-opts.cc1902
-rw-r--r--support/cpp/gcc/c-family/c-ppoutput.cc843
-rw-r--r--support/cpp/gcc/c-family/c-pragma.cc1701
-rw-r--r--support/cpp/gcc/c-family/c-pragma.h270
-rw-r--r--support/cpp/gcc/c-family/c-pretty-print.h143
-rw-r--r--support/cpp/gcc/c-family/c-spellcheck.h53
-rw-r--r--support/cpp/gcc/c-family/c-target-def.h21
-rw-r--r--support/cpp/gcc/c-family/c-target-hooks-def.h0
-rw-r--r--support/cpp/gcc/c-family/c-target.def116
-rw-r--r--support/cpp/gcc/c-family/c-target.h35
-rw-r--r--support/cpp/gcc/c-family/c-ubsan.h34
-rw-r--r--support/cpp/gcc/c-family/c.opt2503
-rw-r--r--support/cpp/gcc/c-family/cppspec.cc200
-rw-r--r--support/cpp/gcc/c-family/known-headers.h44
-rw-r--r--support/cpp/gcc/c-family/name-hint.h128
-rw-r--r--support/cpp/gcc/c/Make-lang.in219
-rw-r--r--support/cpp/gcc/c/c-convert.cc214
-rw-r--r--support/cpp/gcc/c/c-errors.cc164
-rw-r--r--support/cpp/gcc/c/c-lang.cc154
-rw-r--r--support/cpp/gcc/c/c-lang.h67
-rw-r--r--support/cpp/gcc/c/c-objc-common.cc405
-rw-r--r--support/cpp/gcc/c/c-objc-common.h127
-rw-r--r--support/cpp/gcc/c/c-parser.h200
-rw-r--r--support/cpp/gcc/c/c-tree.h857
-rw-r--r--support/cpp/gcc/c/config-lang.in32
-rw-r--r--support/cpp/gcc/c/gimple-parser.cc1
-rw-r--r--support/cpp/gcc/cc1_dummies.cc318
-rw-r--r--support/cpp/gcc/cfg-flags.def191
-rw-r--r--support/cpp/gcc/cfg.h188
-rw-r--r--support/cpp/gcc/cfgloop.h944
-rw-r--r--support/cpp/gcc/cgraph.h3579
-rw-r--r--support/cpp/gcc/cif-code.def144
-rw-r--r--support/cpp/gcc/color-macros.h108
-rw-r--r--support/cpp/gcc/common.md95
-rw-r--r--support/cpp/gcc/common.opt3617
-rw-r--r--support/cpp/gcc/common/common-target-def.h20
-rw-r--r--support/cpp/gcc/common/common-target-hooks-def.h0
-rw-r--r--support/cpp/gcc/common/common-target.def111
-rw-r--r--support/cpp/gcc/common/common-target.h71
-rw-r--r--support/cpp/gcc/common/common-targhooks.cc92
-rw-r--r--support/cpp/gcc/common/common-targhooks.h35
-rw-r--r--support/cpp/gcc/common/config/default-common.cc33
-rw-r--r--support/cpp/gcc/common/config/dummy/dummy-cpuinfo.h255
-rw-r--r--support/cpp/gcc/config.build87
-rw-r--r--support/cpp/gcc/config.gcc5918
-rw-r--r--support/cpp/gcc/config.host301
-rw-r--r--support/cpp/gcc/config.in2734
-rw-r--r--support/cpp/gcc/config/darwin-protos.h132
-rw-r--r--support/cpp/gcc/config/darwin.h1244
-rw-r--r--support/cpp/gcc/config/dbxcoff.h56
-rw-r--r--support/cpp/gcc/config/dbxelf.h68
-rw-r--r--support/cpp/gcc/config/dragonfly-stdint.h56
-rw-r--r--support/cpp/gcc/config/dragonfly.h125
-rw-r--r--support/cpp/gcc/config/dummy/dummy-opts.h131
-rw-r--r--support/cpp/gcc/config/dummy/dummy-protos.h412
-rw-r--r--support/cpp/gcc/config/dummy/dummy.h2600
-rw-r--r--support/cpp/gcc/config/dummy/dummy.opt1144
-rw-r--r--support/cpp/gcc/config/dummy/linux-common.h71
-rw-r--r--support/cpp/gcc/config/dummy/unix.h80
-rw-r--r--support/cpp/gcc/config/elfos.h490
-rw-r--r--support/cpp/gcc/config/flat.h22
-rw-r--r--support/cpp/gcc/config/fuchsia.h70
-rw-r--r--support/cpp/gcc/config/fused-madd.opt24
-rw-r--r--support/cpp/gcc/config/glibc-stdint.h64
-rw-r--r--support/cpp/gcc/config/gnu-user.h158
-rw-r--r--support/cpp/gcc/config/gnu-user.opt38
-rw-r--r--support/cpp/gcc/config/gnu.h39
-rw-r--r--support/cpp/gcc/config/host-darwin.h27
-rw-r--r--support/cpp/gcc/config/hpux-stdint.h34
-rw-r--r--support/cpp/gcc/config/i386/cpuid.h336
-rw-r--r--support/cpp/gcc/config/initfini-array.h45
-rw-r--r--support/cpp/gcc/config/kfreebsd-gnu.h41
-rw-r--r--support/cpp/gcc/config/kopensolaris-gnu.h40
-rw-r--r--support/cpp/gcc/config/linux-android.h65
-rw-r--r--support/cpp/gcc/config/linux-android.opt30
-rw-r--r--support/cpp/gcc/config/linux-protos.h22
-rw-r--r--support/cpp/gcc/config/linux.h228
-rw-r--r--support/cpp/gcc/config/linux.opt36
-rw-r--r--support/cpp/gcc/config/lynx.h163
-rw-r--r--support/cpp/gcc/config/netbsd-elf.h107
-rw-r--r--support/cpp/gcc/config/netbsd-protos.h20
-rw-r--r--support/cpp/gcc/config/netbsd-stdint.h71
-rw-r--r--support/cpp/gcc/config/netbsd.h168
-rw-r--r--support/cpp/gcc/config/newlib-stdint.h69
-rw-r--r--support/cpp/gcc/config/openbsd-libpthread.h22
-rw-r--r--support/cpp/gcc/config/openbsd-stdint.h34
-rw-r--r--support/cpp/gcc/config/openbsd.h289
-rw-r--r--support/cpp/gcc/config/phoenix.h33
-rw-r--r--support/cpp/gcc/config/rtems.h58
-rw-r--r--support/cpp/gcc/config/sol2-protos.h33
-rw-r--r--support/cpp/gcc/config/sol2.h521
-rw-r--r--support/cpp/gcc/config/t-glibc25
-rw-r--r--support/cpp/gcc/config/tm-dwarf2.h4
-rw-r--r--support/cpp/gcc/config/usegas.h20
-rw-r--r--support/cpp/gcc/config/usegld.h1
-rw-r--r--support/cpp/gcc/config/vx-common.h127
-rw-r--r--support/cpp/gcc/config/vxworks-dummy.h48
-rw-r--r--support/cpp/gcc/config/vxworks-stdint.h53
-rw-r--r--support/cpp/gcc/config/vxworks.h381
-rw-r--r--support/cpp/gcc/config/vxworksae.h96
-rwxr-xr-xsupport/cpp/gcc/configure33719
-rw-r--r--support/cpp/gcc/configure.ac7821
-rw-r--r--support/cpp/gcc/context.cc45
-rw-r--r--support/cpp/gcc/context.h69
-rw-r--r--support/cpp/gcc/convert.h45
-rw-r--r--support/cpp/gcc/coretypes.h495
-rw-r--r--support/cpp/gcc/coroutine-builtins.def53
-rw-r--r--support/cpp/gcc/cppbuiltin.h33
-rw-r--r--support/cpp/gcc/cppdefault.cc138
-rw-r--r--support/cpp/gcc/cppdefault.h70
-rw-r--r--support/cpp/gcc/cselib.h142
-rw-r--r--support/cpp/gcc/ctfc.h448
-rw-r--r--support/cpp/gcc/data-streamer.h353
-rw-r--r--support/cpp/gcc/dbgcnt.def216
-rw-r--r--support/cpp/gcc/dbgcnt.h40
-rw-r--r--support/cpp/gcc/debug.cc166
-rw-r--r--support/cpp/gcc/debug.h284
-rw-r--r--support/cpp/gcc/defaults.h1459
-rw-r--r--support/cpp/gcc/df.h1252
-rw-r--r--support/cpp/gcc/diagnostic-color.cc348
-rw-r--r--support/cpp/gcc/diagnostic-color.h65
-rw-r--r--support/cpp/gcc/diagnostic-core.h128
-rw-r--r--support/cpp/gcc/diagnostic-event-id.h61
-rw-r--r--support/cpp/gcc/diagnostic-format-json.cc391
-rw-r--r--support/cpp/gcc/diagnostic-metadata.h42
-rw-r--r--support/cpp/gcc/diagnostic-path.h149
-rw-r--r--support/cpp/gcc/diagnostic-show-locus.cc5703
-rw-r--r--support/cpp/gcc/diagnostic-spec.cc205
-rw-r--r--support/cpp/gcc/diagnostic-spec.h140
-rw-r--r--support/cpp/gcc/diagnostic-url.h52
-rw-r--r--support/cpp/gcc/diagnostic.cc2494
-rw-r--r--support/cpp/gcc/diagnostic.def55
-rw-r--r--support/cpp/gcc/diagnostic.h590
-rw-r--r--support/cpp/gcc/dominance.h94
-rw-r--r--support/cpp/gcc/double-int.h472
-rw-r--r--support/cpp/gcc/dummies.cc31
-rw-r--r--support/cpp/gcc/dumpfile.h776
-rw-r--r--support/cpp/gcc/dwarf2out.h470
-rw-r--r--support/cpp/gcc/edit-context.cc1813
-rw-r--r--support/cpp/gcc/edit-context.h67
-rw-r--r--support/cpp/gcc/emit-rtl.h548
-rw-r--r--support/cpp/gcc/errors.cc134
-rw-r--r--support/cpp/gcc/errors.h40
-rw-r--r--support/cpp/gcc/escaped_string.h43
-rw-r--r--support/cpp/gcc/except.h334
-rw-r--r--support/cpp/gcc/exec-tool.in116
-rw-r--r--support/cpp/gcc/explow.h143
-rw-r--r--support/cpp/gcc/expmed.h726
-rw-r--r--support/cpp/gcc/expr.h352
-rw-r--r--support/cpp/gcc/file-find.cc210
-rw-r--r--support/cpp/gcc/file-find.h47
-rw-r--r--support/cpp/gcc/file-prefix-map.cc149
-rw-r--r--support/cpp/gcc/file-prefix-map.h30
-rw-r--r--support/cpp/gcc/fixed-value.h111
-rw-r--r--support/cpp/gcc/flag-types.h514
-rw-r--r--support/cpp/gcc/flags.h115
-rw-r--r--support/cpp/gcc/fold-const.h270
-rw-r--r--support/cpp/gcc/function-abi.h320
-rw-r--r--support/cpp/gcc/function.h733
-rw-r--r--support/cpp/gcc/gcc-main.cc48
-rw-r--r--support/cpp/gcc/gcc-rich-location.h226
-rw-r--r--support/cpp/gcc/gcc.cc11295
-rw-r--r--support/cpp/gcc/gcc.h100
-rw-r--r--support/cpp/gcc/gen-pass-instances.awk234
-rw-r--r--support/cpp/gcc/genchecksum.cc120
-rw-r--r--support/cpp/gcc/gengenrtl.cc358
-rw-r--r--support/cpp/gcc/gengtype-lex.l221
-rw-r--r--support/cpp/gcc/gengtype.h521
-rw-r--r--support/cpp/gcc/genmultilib552
-rw-r--r--support/cpp/gcc/gensupport.h228
-rw-r--r--support/cpp/gcc/genversion.cc89
-rw-r--r--support/cpp/gcc/ggc-common.cc1307
-rw-r--r--support/cpp/gcc/ggc-internal.h115
-rw-r--r--support/cpp/gcc/ggc-none.cc81
-rw-r--r--support/cpp/gcc/ggc-page.cc2694
-rw-r--r--support/cpp/gcc/ggc.h369
-rw-r--r--support/cpp/gcc/gimplify-me.h37
-rw-r--r--support/cpp/gcc/gimplify.h92
-rw-r--r--support/cpp/gcc/gsstruct.def53
-rw-r--r--support/cpp/gcc/gtm-builtins.def212
-rw-r--r--support/cpp/gcc/hard-reg-set.h527
-rw-r--r--support/cpp/gcc/hash-map-traits.h190
-rw-r--r--support/cpp/gcc/hash-map.h390
-rw-r--r--support/cpp/gcc/hash-set.h215
-rw-r--r--support/cpp/gcc/hash-table.cc138
-rw-r--r--support/cpp/gcc/hash-table.h1231
-rw-r--r--support/cpp/gcc/hash-traits.h406
-rw-r--r--support/cpp/gcc/highlev-plugin-common.h33
-rw-r--r--support/cpp/gcc/hooks.cc573
-rw-r--r--support/cpp/gcc/hooks.h140
-rw-r--r--support/cpp/gcc/hosthooks.h50
-rw-r--r--support/cpp/gcc/hwint.h378
-rw-r--r--support/cpp/gcc/inchash.h213
-rw-r--r--support/cpp/gcc/incpath.cc537
-rw-r--r--support/cpp/gcc/incpath.h46
-rw-r--r--support/cpp/gcc/input.cc3932
-rw-r--r--support/cpp/gcc/input.h285
-rw-r--r--support/cpp/gcc/insn-addr.h63
-rw-r--r--support/cpp/gcc/insn-attr-common.h8
-rw-r--r--support/cpp/gcc/insn-attr.h6
-rw-r--r--support/cpp/gcc/insn-codes.h4
-rw-r--r--support/cpp/gcc/insn-config.h7
-rw-r--r--support/cpp/gcc/insn-constants.h306
-rw-r--r--support/cpp/gcc/insn-flags.h5
-rw-r--r--support/cpp/gcc/insn-modes-inline.h24
-rw-r--r--support/cpp/gcc/insn-modes.h43
-rw-r--r--support/cpp/gcc/insn-notes.def98
-rw-r--r--support/cpp/gcc/int-vector-builder.h93
-rw-r--r--support/cpp/gcc/internal-fn.def441
-rw-r--r--support/cpp/gcc/internal-fn.h257
-rw-r--r--support/cpp/gcc/intl.cc150
-rw-r--r--support/cpp/gcc/intl.h73
-rw-r--r--support/cpp/gcc/ira.h242
-rw-r--r--support/cpp/gcc/is-a.h284
-rw-r--r--support/cpp/gcc/iterator-utils.h203
-rw-r--r--support/cpp/gcc/json.cc375
-rw-r--r--support/cpp/gcc/json.h191
-rw-r--r--support/cpp/gcc/langhooks-def.h399
-rw-r--r--support/cpp/gcc/langhooks.h666
-rw-r--r--support/cpp/gcc/libfuncs.h84
-rw-r--r--support/cpp/gcc/lto-streamer.h1246
-rw-r--r--support/cpp/gcc/machmode.def283
-rw-r--r--support/cpp/gcc/machmode.h1217
-rw-r--r--support/cpp/gcc/main.cc45
-rw-r--r--support/cpp/gcc/match.pd7748
-rw-r--r--support/cpp/gcc/mem-stats-traits.h41
-rw-r--r--support/cpp/gcc/mem-stats.h658
-rw-r--r--support/cpp/gcc/memmodel.h116
-rw-r--r--support/cpp/gcc/memory-block.cc86
-rw-r--r--support/cpp/gcc/memory-block.h84
-rw-r--r--support/cpp/gcc/min-insn-modes.cc53
-rw-r--r--support/cpp/gcc/mkconfig.sh125
-rw-r--r--support/cpp/gcc/mode-classes.def40
-rw-r--r--support/cpp/gcc/omp-builtins.def469
-rw-r--r--support/cpp/gcc/omp-general.h0
-rw-r--r--support/cpp/gcc/omp-offload.h35
-rw-r--r--support/cpp/gcc/opt-functions.awk389
-rw-r--r--support/cpp/gcc/opt-gather.awk54
-rw-r--r--support/cpp/gcc/opt-include.awk29
-rw-r--r--support/cpp/gcc/opt-read.awk128
-rw-r--r--support/cpp/gcc/opt-suggestions.h71
-rw-r--r--support/cpp/gcc/optabs-query.h216
-rw-r--r--support/cpp/gcc/optabs-tree.h51
-rw-r--r--support/cpp/gcc/optabs.def475
-rw-r--r--support/cpp/gcc/optabs.h383
-rw-r--r--support/cpp/gcc/optc-gen.awk674
-rw-r--r--support/cpp/gcc/optc-save-gen.awk1471
-rw-r--r--support/cpp/gcc/opth-gen.awk575
-rw-r--r--support/cpp/gcc/optinfo.h170
-rw-r--r--support/cpp/gcc/opts-common.cc2017
-rw-r--r--support/cpp/gcc/opts-diagnostic.h28
-rw-r--r--support/cpp/gcc/opts-global.cc496
-rw-r--r--support/cpp/gcc/opts-sdcc.h110
-rw-r--r--support/cpp/gcc/opts.cc3798
-rw-r--r--support/cpp/gcc/opts.h529
-rw-r--r--support/cpp/gcc/output.h635
-rw-r--r--support/cpp/gcc/params.opt1204
-rw-r--r--support/cpp/gcc/pass_manager.h148
-rw-r--r--support/cpp/gcc/passes.def538
-rw-r--r--support/cpp/gcc/plugin.def112
-rw-r--r--support/cpp/gcc/plugin.h205
-rw-r--r--support/cpp/gcc/poly-int-types.h103
-rw-r--r--support/cpp/gcc/poly-int.h2735
-rw-r--r--support/cpp/gcc/predict.def238
-rw-r--r--support/cpp/gcc/predict.h110
-rw-r--r--support/cpp/gcc/prefix.cc355
-rw-r--r--support/cpp/gcc/prefix.h40
-rw-r--r--support/cpp/gcc/pretty-print.cc2629
-rw-r--r--support/cpp/gcc/pretty-print.h436
-rw-r--r--support/cpp/gcc/print-rtl.h165
-rw-r--r--support/cpp/gcc/print-tree.h50
-rw-r--r--support/cpp/gcc/profile-count.h1250
-rw-r--r--support/cpp/gcc/range-op.h115
-rw-r--r--support/cpp/gcc/range.h28
-rw-r--r--support/cpp/gcc/read-md.h408
-rw-r--r--support/cpp/gcc/real.h545
-rw-r--r--support/cpp/gcc/recog.h565
-rw-r--r--support/cpp/gcc/reg-notes.def249
-rw-r--r--support/cpp/gcc/regs.h392
-rw-r--r--support/cpp/gcc/regset.h123
-rw-r--r--support/cpp/gcc/reload.h466
-rw-r--r--support/cpp/gcc/resource.h55
-rw-r--r--support/cpp/gcc/rtl-iter.h292
-rw-r--r--support/cpp/gcc/rtl.def1368
-rw-r--r--support/cpp/gcc/rtl.h4623
-rw-r--r--support/cpp/gcc/sanitizer.def669
-rw-r--r--support/cpp/gcc/sbitmap.cc1007
-rw-r--r--support/cpp/gcc/sbitmap.h321
-rw-r--r--support/cpp/gcc/selftest-diagnostic.cc64
-rw-r--r--support/cpp/gcc/selftest-diagnostic.h49
-rw-r--r--support/cpp/gcc/selftest.cc426
-rw-r--r--support/cpp/gcc/selftest.h491
-rw-r--r--support/cpp/gcc/signop.h33
-rw-r--r--support/cpp/gcc/sort.cc310
-rw-r--r--support/cpp/gcc/spellcheck-tree.h51
-rw-r--r--support/cpp/gcc/spellcheck.cc529
-rw-r--r--support/cpp/gcc/spellcheck.h221
-rw-r--r--support/cpp/gcc/ssa-iterators.h1013
-rw-r--r--support/cpp/gcc/ssa.h34
-rw-r--r--support/cpp/gcc/statistics.h71
-rw-r--r--support/cpp/gcc/stmt.h53
-rw-r--r--support/cpp/gcc/stor-layout.h117
-rw-r--r--support/cpp/gcc/stringpool.h43
-rw-r--r--support/cpp/gcc/substring-locations.h126
-rw-r--r--support/cpp/gcc/symtab-clones.h77
-rw-r--r--support/cpp/gcc/symtab-thunks.h173
-rw-r--r--support/cpp/gcc/sync-builtins.def614
-rw-r--r--support/cpp/gcc/system.h1320
-rw-r--r--support/cpp/gcc/target-globals.h95
-rw-r--r--support/cpp/gcc/target-hooks-macros.h80
-rw-r--r--support/cpp/gcc/target-insns.def108
-rw-r--r--support/cpp/gcc/target.def7116
-rw-r--r--support/cpp/gcc/target.h322
-rw-r--r--support/cpp/gcc/timevar.cc817
-rw-r--r--support/cpp/gcc/timevar.def343
-rw-r--r--support/cpp/gcc/timevar.h301
-rw-r--r--support/cpp/gcc/tm-preds.h5
-rw-r--r--support/cpp/gcc/tm.h37
-rw-r--r--support/cpp/gcc/tm_p.h6
-rw-r--r--support/cpp/gcc/toplev.cc2487
-rw-r--r--support/cpp/gcc/toplev.h102
-rw-r--r--support/cpp/gcc/tree-core.h2331
-rw-r--r--support/cpp/gcc/tree-diagnostic.h68
-rw-r--r--support/cpp/gcc/tree-inline.h256
-rw-r--r--support/cpp/gcc/tree-iterator.h150
-rw-r--r--support/cpp/gcc/tree-pass.h680
-rw-r--r--support/cpp/gcc/tree-pretty-print.h60
-rw-r--r--support/cpp/gcc/tree-ssa-alias.h211
-rw-r--r--support/cpp/gcc/tree-vrp.h70
-rw-r--r--support/cpp/gcc/tree.def1480
-rw-r--r--support/cpp/gcc/tree.h6643
-rw-r--r--support/cpp/gcc/treestruct.def71
-rw-r--r--support/cpp/gcc/typed-splay-tree.h652
-rw-r--r--support/cpp/gcc/value-query.h149
-rw-r--r--support/cpp/gcc/value-range.h715
-rw-r--r--support/cpp/gcc/value-relation.h245
-rw-r--r--support/cpp/gcc/varasm.h82
-rw-r--r--support/cpp/gcc/vec-perm-indices.h153
-rw-r--r--support/cpp/gcc/vec.cc595
-rw-r--r--support/cpp/gcc/vec.h2356
-rw-r--r--support/cpp/gcc/vector-builder.h612
-rw-r--r--support/cpp/gcc/warning-control.cc294
372 files changed, 246051 insertions, 0 deletions
diff --git a/support/cpp/gcc/BASE-VER b/support/cpp/gcc/BASE-VER
new file mode 100644
index 000000000..77903b35f
--- /dev/null
+++ b/support/cpp/gcc/BASE-VER
@@ -0,0 +1 @@
+12.1.0
diff --git a/support/cpp/gcc/DATESTAMP b/support/cpp/gcc/DATESTAMP
new file mode 100644
index 000000000..50478337b
--- /dev/null
+++ b/support/cpp/gcc/DATESTAMP
@@ -0,0 +1 @@
+20220506
diff --git a/support/cpp/gcc/DEV-PHASE b/support/cpp/gcc/DEV-PHASE
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/support/cpp/gcc/DEV-PHASE
diff --git a/support/cpp/gcc/Makefile.in b/support/cpp/gcc/Makefile.in
new file mode 100644
index 000000000..ba6723b7f
--- /dev/null
+++ b/support/cpp/gcc/Makefile.in
@@ -0,0 +1,4044 @@
+# Makefile for GNU Compiler Collection
+# Run 'configure' to generate Makefile from Makefile.in
+
+# 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/>.
+
+# The targets for external use include:
+# all, doc, install, install-cross, install-cross-rest, install-strip,
+# uninstall, TAGS, mostlyclean, clean, distclean, maintainer-clean.
+
+# This is the default target.
+# Set by autoconf to "all.internal" for a native build, or
+# "all.cross" to build a cross compiler.
+all: all.internal # @ALL@
+
+# Depend on this to specify a phony target portably.
+force:
+
+# This tells GNU make version 3 not to export the variables
+# defined in this file into the environment (and thus recursive makes).
+.NOEXPORT:
+.DELETE_ON_ERROR:
+# And this tells it not to automatically pass command-line variables
+# to recursive makes.
+MAKEOVERRIDES =
+
+# Suppress smart makes who think they know how to automake yacc and flex file
+.y.c:
+.l.c:
+
+# The only suffixes we want for implicit rules are .c and .o, so clear
+# the list and add them. This speeds up GNU Make, and allows -r to work.
+# For i18n support, we also need .gmo, .po, .pox.
+# This must come before the language makefile fragments to allow them to
+# add suffixes and rules of their own.
+.SUFFIXES:
+.SUFFIXES: .c .cc .o .po .pox .gmo
+
+# -------------------------------
+# Standard autoconf-set variables
+# -------------------------------
+
+build=@build@
+host=@host@
+host_noncanonical=@host_noncanonical@
+host_os=@host_os@
+target=@target@
+target_noncanonical:=@target_noncanonical@
+
+# Normally identical to target_noncanonical, except for compilers built
+# as accelerator targets.
+real_target_noncanonical:=@real_target_noncanonical@
+accel_dir_suffix = @accel_dir_suffix@
+
+# Sed command to transform gcc to installed name.
+program_transform_name := s,^,sd, # @program_transform_name@
+
+# -----------------------------
+# Directories used during build
+# -----------------------------
+
+# Directory where sources are, from where we are.
+srcdir = @srcdir@
+gcc_docdir = @srcdir@/doc
+
+# Directory where sources are, absolute.
+abs_srcdir = @abs_srcdir@
+abs_docdir = @abs_srcdir@/doc
+
+# Directory where sources are, relative to here.
+top_srcdir = @top_srcdir@
+
+# Top build directory for this package, relative to here.
+top_builddir = .
+
+# The absolute path to the current directory.
+objdir := $(shell pwd)
+
+host_subdir=@host_subdir@
+build_subdir=@build_subdir@
+target_subdir=@target_subdir@
+build_libsubdir=@build_libsubdir@
+
+# Top build directory for the "Cygnus tree", relative to $(top_builddir).
+ifeq ($(host_subdir),.)
+toplevel_builddir := ..
+else
+toplevel_builddir := ../..
+endif
+
+build_objdir := $(toplevel_builddir)/$(build_subdir)
+build_libobjdir := $(toplevel_builddir)/$(build_libsubdir)
+target_objdir := $(toplevel_builddir)/$(target_subdir)
+
+# --------
+# Defined vpaths
+# --------
+
+# Directory where sources are, from where we are.
+VPATH = @srcdir@
+
+# We define a vpath for the sources of the .texi files here because they
+# are split between multiple directories and we would rather use one implicit
+# pattern rule for everything.
+# This vpath could be extended within the Make-lang fragments.
+
+vpath %.texi $(gcc_docdir)
+vpath %.texi $(gcc_docdir)/include
+
+# --------
+# UNSORTED
+# --------
+
+# Extra flags to pass to indicate cross compilation, which
+# might be used or tested by Make-lang fragments.
+CROSS=@CROSS@
+
+# Variables that exist for you to override.
+# See below for how to change them for certain systems.
+
+# List of language subdirectories.
+SUBDIRS =@subdirs@ build
+
+# Selection of languages to be made.
+CONFIG_LANGUAGES = @all_selected_languages@
+LANGUAGES = c $(CONFIG_LANGUAGES)
+ifeq (@enable_gcov@,yes)
+# LANGUAGES += gcov$(exeext) gcov-dump$(exeext) gcov-tool$(exeext)
+endif
+
+# Default values for variables overridden in Makefile fragments.
+# CFLAGS is for the user to override to, e.g., do a cross build with -O2.
+# TCFLAGS is used for compilations with the GCC just built.
+# T_CFLAGS is used for all compilations and is overridden by t-* files.
+T_CFLAGS =
+TCFLAGS =
+CFLAGS = @CFLAGS@
+CXXFLAGS = @CXXFLAGS@
+LDFLAGS = @LDFLAGS@
+
+# Should we build position-independent host code?
+PICFLAG = @PICFLAG@
+
+# Flags to determine code coverage. When coverage is disabled, this will
+# contain the optimization flags, as you normally want code coverage
+# without optimization.
+COVERAGE_FLAGS = @coverage_flags@
+coverageexts = .{gcda,gcno}
+
+# The warning flags are separate from CFLAGS because people tend to
+# override optimization flags and we'd like them to still have warnings
+# turned on. These flags are also used to pass other stage dependent
+# flags from configure. The user is free to explicitly turn these flags
+# off if they wish.
+# LOOSE_WARN are the warning flags to use when compiling something
+# which is only compiled with gcc, such as libgcc.
+# C_LOOSE_WARN is similar, but with C-only warnings.
+# STRICT_WARN are the additional warning flags to
+# apply to the back end and some front ends, which may be compiled
+# with other compilers.
+# C_STRICT_WARN is similar, with C-only warnings.
+LOOSE_WARN = @loose_warn@
+C_LOOSE_WARN = @c_loose_warn@
+STRICT_WARN = @strict_warn@
+C_STRICT_WARN = @c_strict_warn@
+
+# This is set by --enable-checking. The idea is to catch forgotten
+# "extern" tags in header files.
+NOCOMMON_FLAG = @nocommon_flag@
+
+NOEXCEPTION_FLAGS = @noexception_flags@
+
+ALIASING_FLAGS = @aliasing_flags@
+
+# This is set by --disable-maintainer-mode (default) to "#"
+# FIXME: 'MAINT' will always be set to an empty string, no matter if
+# --disable-maintainer-mode is used or not. This is because the
+# following will expand to "MAINT := " in maintainer mode, and to
+# "MAINT := #" in non-maintainer mode, but because '#' starts a comment,
+# they mean exactly the same thing for make.
+MAINT := @MAINT@
+
+# The following provides the variable ENABLE_MAINTAINER_RULES that can
+# be used in language Make-lang.in makefile fragments to enable
+# maintainer rules. So, ENABLE_MAINTAINER_RULES is 'true' in
+# maintainer mode, and '' otherwise.
+@MAINT@ ENABLE_MAINTAINER_RULES = true
+
+# These are set by --enable-checking=valgrind.
+RUN_GEN = @valgrind_command@
+VALGRIND_DRIVER_DEFINES = @valgrind_path_defines@
+
+# This is how we control whether or not the additional warnings are applied.
+.-warn = $(STRICT_WARN)
+build-warn = $(STRICT_WARN)
+rtl-ssa-warn = $(STRICT_WARN)
+GCC_WARN_CFLAGS = $(LOOSE_WARN) $(C_LOOSE_WARN) $($(@D)-warn) $(if $(filter-out $(STRICT_WARN),$($(@D)-warn)),,$(C_STRICT_WARN)) $(NOCOMMON_FLAG) $($@-warn)
+GCC_WARN_CXXFLAGS = $(LOOSE_WARN) $($(@D)-warn) $(NOCOMMON_FLAG) $($@-warn)
+
+# These files are to have specific diagnostics suppressed, or are not to
+# be subject to -Werror:
+# flex output may yield harmless "no previous prototype" warnings
+build/gengtype-lex.o-warn = -Wno-error
+gengtype-lex.o-warn = -Wno-error
+libgcov-util.o-warn = -Wno-error
+libgcov-driver-tool.o-warn = -Wno-error
+libgcov-merge-tool.o-warn = -Wno-error
+gimple-match.o-warn = -Wno-unused
+generic-match.o-warn = -Wno-unused
+dfp.o-warn = -Wno-strict-aliasing
+
+# All warnings have to be shut off in stage1 if the compiler used then
+# isn't gcc; configure determines that. WARN_CFLAGS will be either
+# $(GCC_WARN_CFLAGS), or nothing. Similarly, WARN_CXXFLAGS will be
+# either $(GCC_WARN_CXXFLAGS), or nothing.
+WARN_CFLAGS = @warn_cflags@
+WARN_CXXFLAGS = @warn_cxxflags@
+
+CPPFLAGS = @CPPFLAGS@
+
+AWK = @AWK@
+CC = @CC@
+CXX = @CXX@
+BISON = @BISON@
+BISONFLAGS =
+FLEX = @FLEX@
+FLEXFLAGS =
+AR = @AR@
+AR_FLAGS = rc
+NM = @NM@
+RANLIB = @RANLIB@
+RANLIB_FLAGS = @ranlib_flags@
+
+# Libraries to use on the host.
+HOST_LIBS = @HOST_LIBS@
+
+# The name of the compiler to use.
+COMPILER = $(CXX)
+COMPILER_FLAGS = $(CXXFLAGS)
+# If HOST_LIBS is set, then the user is controlling the libraries to
+# link against. In that case, link with $(CC) so that the -lstdc++
+# library is not introduced. If HOST_LIBS is not set, link with
+# $(CXX) to pick up -lstdc++.
+ifeq ($(HOST_LIBS),)
+LINKER = $(CXX)
+LINKER_FLAGS = $(CXXFLAGS)
+else
+LINKER = $(CC)
+LINKER_FLAGS = $(CFLAGS)
+endif
+
+# Enable Intel CET on Intel CET enabled host if needed.
+CET_HOST_FLAGS = @CET_HOST_FLAGS@
+COMPILER += $(CET_HOST_FLAGS)
+
+NO_PIE_CFLAGS = @NO_PIE_CFLAGS@
+NO_PIE_FLAG = @NO_PIE_FLAG@
+
+# We don't want to compile the compilers with -fPIE, it make PCH fail.
+COMPILER += $(NO_PIE_CFLAGS)
+
+# Link with -no-pie since we compile the compiler with -fno-PIE.
+LINKER += $(NO_PIE_FLAG)
+
+# Like LINKER, but use a mutex for serializing front end links.
+ifeq (@DO_LINK_MUTEX@,true)
+LLINKER = $(SHELL) $(srcdir)/lock-and-run.sh linkfe.lck $(LINKER)
+else
+LLINKER = $(LINKER)
+endif
+
+THIN_ARCHIVE_SUPPORT = @thin_archive_support@
+
+USE_THIN_ARCHIVES = no
+ifeq ($(THIN_ARCHIVE_SUPPORT),yes)
+ifeq ($(AR_FLAGS),rc)
+ifeq ($(RANLIB_FLAGS),)
+USE_THIN_ARCHIVES = yes
+endif
+endif
+endif
+
+# -------------------------------------------
+# Programs which operate on the build machine
+# -------------------------------------------
+
+SHELL = @SHELL@
+# pwd command to use. Allow user to override default by setting PWDCMD in
+# the environment to account for automounters. The make variable must not
+# be called PWDCMD, otherwise the value set here is passed to make
+# subprocesses and overrides the setting from the user's environment.
+# Don't use PWD since it is a common shell environment variable and we
+# don't want to corrupt it.
+PWD_COMMAND = $${PWDCMD-pwd}
+# on sysV, define this as cp.
+INSTALL = @INSTALL@
+# Some systems may be missing symbolic links, regular links, or both.
+# Allow configure to check this and use "ln -s", "ln", or "cp" as appropriate.
+LN=@LN@
+LN_S=@LN_S@
+# These permit overriding just for certain files.
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL@
+install_sh = $(SHELL) $(srcdir)/../install-sh
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+MAKEINFO = @MAKEINFO@
+MAKEINFOFLAGS = --no-split
+TEXI2DVI = texi2dvi
+TEXI2PDF = texi2pdf
+TEXI2HTML = $(MAKEINFO) --html
+TEXI2POD = perl $(srcdir)/../contrib/texi2pod.pl
+POD2MAN = pod2man --center="GNU" --release="gcc-$(version)" --date=$(shell sed 's/\(....\)\(..\)\(..\)/\1-\2-\3/' <$(DATESTAMP))
+# Some versions of `touch' (such as the version on Solaris 2.8)
+# do not correctly set the timestamp due to buggy versions of `utime'
+# in the kernel. So, we use `echo' instead.
+STAMP = echo timestamp >
+# If necessary (e.g., when using the MSYS shell on Microsoft Windows)
+# translate the shell's notion of absolute pathnames to the native
+# spelling.
+build_file_translate = @build_file_translate@
+
+# Make sure the $(MAKE) variable is defined.
+@SET_MAKE@
+
+# Locate mkinstalldirs.
+mkinstalldirs=$(SHELL) $(srcdir)/../mkinstalldirs
+
+# write_entries_to_file - writes each entry in a list
+# to the specified file. Entries are written in chunks of
+# $(write_entries_to_file_split) to accommodate systems with
+# severe command-line-length limitations.
+# Parameters:
+# $(1): variable containing entries to iterate over
+# $(2): output file
+write_entries_to_file_split = 50
+write_entries_to_file = $(shell rm -f $(2) || :) $(shell touch $(2)) \
+ $(foreach range, \
+ $(shell i=1; while test $$i -le $(words $(1)); do \
+ echo $$i; i=`expr $$i + $(write_entries_to_file_split)`; done), \
+ $(shell echo "$(wordlist $(range), \
+ $(shell expr $(range) + $(write_entries_to_file_split) - 1), $(1))" \
+ | tr ' ' '\012' >> $(2)))
+
+# The jit documentation looks better if built with sphinx, but can be
+# built with texinfo if sphinx is not available.
+# configure sets "doc_build_sys" to "sphinx" or "texinfo" accordingly
+doc_build_sys=@doc_build_sys@
+
+# --------
+# UNSORTED
+# --------
+
+# Dependency tracking stuff.
+CXXDEPMODE = @CXXDEPMODE@
+DEPDIR = @DEPDIR@
+depcomp = $(SHELL) $(srcdir)/../depcomp
+
+# In the past we used AC_PROG_CC_C_O and set this properly, but
+# it was discovered that this hadn't worked in a long time, so now
+# we just hard-code.
+OUTPUT_OPTION = -o $@
+
+# This is where we get zlib from. zlibdir is -L../zlib and zlibinc is
+# -I../zlib, unless we were configured with --with-system-zlib, in which
+# case both are empty.
+ZLIB = @zlibdir@ -lz
+ZLIBINC = @zlibinc@
+
+# How to find GMP
+GMPLIBS = # @GMPLIBS@
+GMPINC = @GMPINC@
+
+# How to find isl.
+ISLLIBS = @ISLLIBS@
+ISLINC = @ISLINC@
+
+# Set to 'yes' if the LTO front end is enabled.
+enable_lto = @enable_lto@
+
+# Compiler and flags needed for plugin support
+PLUGINCC = @CXX@
+PLUGINCFLAGS = @CXXFLAGS@
+
+# Libs and linker options needed for plugin support
+PLUGINLIBS = @pluginlibs@
+
+enable_plugin = @enable_plugin@
+
+# On MinGW plugin installation involves installing import libraries.
+ifeq ($(enable_plugin),yes)
+ plugin_implib := $(if $(strip $(filter mingw%,$(host_os))),yes,no)
+endif
+
+enable_host_shared = @enable_host_shared@
+
+enable_as_accelerator = @enable_as_accelerator@
+
+CPPLIB = ../libcpp/libcpp.a
+CPPINC = -I$(srcdir)/../libcpp/include
+
+CODYLIB = ../libcody/libcody.a
+CODYINC = -I$(srcdir)/../libcody
+NETLIBS = @NETLIBS@
+
+# Where to find decNumber
+enable_decimal_float = @enable_decimal_float@
+DECNUM = $(srcdir)/../libdecnumber
+DECNUMFMT = $(srcdir)/../libdecnumber/$(enable_decimal_float)
+DECNUMINC = -I$(DECNUM) -I$(DECNUMFMT) -I../libdecnumber
+LIBDECNUMBER = # ../libdecnumber/libdecnumber.a
+
+# The backtrace library.
+BACKTRACE = $(srcdir)/../libbacktrace
+BACKTRACEINC = -I$(BACKTRACE)
+LIBBACKTRACE = ../libbacktrace/.libs/libbacktrace.a
+
+# Target to use when installing include directory. Either
+# install-headers-tar, install-headers-cpio or install-headers-cp.
+INSTALL_HEADERS_DIR = @build_install_headers_dir@
+
+# Header files that are made available under the same name
+# to programs compiled with GCC.
+USER_H_ = $(srcdir)/ginclude/float.h \
+ $(srcdir)/ginclude/iso646.h \
+ $(srcdir)/ginclude/stdarg.h \
+ $(srcdir)/ginclude/stdbool.h \
+ $(srcdir)/ginclude/stddef.h \
+ $(srcdir)/ginclude/varargs.h \
+ $(srcdir)/ginclude/stdfix.h \
+ $(srcdir)/ginclude/stdnoreturn.h \
+ $(srcdir)/ginclude/stdalign.h \
+ $(srcdir)/ginclude/stdatomic.h \
+ $(EXTRA_HEADERS)
+
+USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
+USER_H_INC_NEXT_POST = @user_headers_inc_next_post@
+
+# Enable target overriding of this fragment, as in config/t-vxworks.
+T_GLIMITS_H = # $(srcdir)/glimits.h
+T_STDINT_GCC_H = # $(srcdir)/ginclude/stdint-gcc.h
+
+# The GCC to use for compiling crt*.o.
+# Usually the one we just built.
+# Don't use this as a dependency--use $(GCC_PASSES).
+GCC_FOR_TARGET = $(STAGE_CC_WRAPPER) ./xgcc -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include -isystem $(build_tooldir)/sys-include -L$(objdir)/../ld
+
+# Set if the compiler was configured with --with-build-sysroot.
+SYSROOT_CFLAGS_FOR_TARGET = @SYSROOT_CFLAGS_FOR_TARGET@
+
+# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
+# It specifies -B./.
+# It also specifies -isystem ./include to find, e.g., stddef.h.
+GCC_CFLAGS=$(CFLAGS_FOR_TARGET) $(INTERNAL_CFLAGS) $(T_CFLAGS) $(LOOSE_WARN) $(C_LOOSE_WARN) -Wold-style-definition $($@-warn) -isystem ./include $(TCFLAGS)
+
+# ---------------------------------------------------
+# Programs which produce files for the target machine
+# ---------------------------------------------------
+
+AR_FOR_TARGET := $(shell \
+ if [ -f $(objdir)/../binutils/ar ] ; then \
+ echo $(objdir)/../binutils/ar ; \
+ else \
+ if [ "$(host)" = "$(target)" ] ; then \
+ echo $(AR); \
+ else \
+ t='$(program_transform_name)'; echo ar | sed -e "$$t" ; \
+ fi; \
+ fi)
+AR_FLAGS_FOR_TARGET =
+AR_CREATE_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) rc
+AR_EXTRACT_FOR_TARGET = $(AR_FOR_TARGET) $(AR_FLAGS_FOR_TARGET) x
+LIPO_FOR_TARGET = lipo
+ORIGINAL_AS_FOR_TARGET = @ORIGINAL_AS_FOR_TARGET@
+RANLIB_FOR_TARGET := $(shell \
+ if [ -f $(objdir)/../binutils/ranlib ] ; then \
+ echo $(objdir)/../binutils/ranlib ; \
+ else \
+ if [ "$(host)" = "$(target)" ] ; then \
+ echo $(RANLIB); \
+ else \
+ t='$(program_transform_name)'; echo ranlib | sed -e "$$t" ; \
+ fi; \
+ fi)
+ORIGINAL_LD_FOR_TARGET = @ORIGINAL_LD_FOR_TARGET@
+ORIGINAL_NM_FOR_TARGET = @ORIGINAL_NM_FOR_TARGET@
+NM_FOR_TARGET = ./nm
+STRIP_FOR_TARGET := $(shell \
+ if [ -f $(objdir)/../binutils/strip-new ] ; then \
+ echo $(objdir)/../binutils/strip-new ; \
+ else \
+ if [ "$(host)" = "$(target)" ] ; then \
+ echo strip; \
+ else \
+ t='$(program_transform_name)'; echo strip | sed -e "$$t" ; \
+ fi; \
+ fi)
+
+# --------
+# UNSORTED
+# --------
+
+# Where to find some libiberty headers.
+HASHTAB_H = $(srcdir)/../include/hashtab.h
+OBSTACK_H = $(srcdir)/../include/obstack.h
+SPLAY_TREE_H= $(srcdir)/../include/splay-tree.h
+MD5_H = $(srcdir)/../include/md5.h
+XREGEX_H = $(srcdir)/../include/xregex.h
+FNMATCH_H = $(srcdir)/../include/fnmatch.h
+
+# Linker plugin API headers
+LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h
+
+# Default native SYSTEM_HEADER_DIR, to be overridden by targets.
+NATIVE_SYSTEM_HEADER_DIR = @NATIVE_SYSTEM_HEADER_DIR@
+# Default cross SYSTEM_HEADER_DIR, to be overridden by targets.
+CROSS_SYSTEM_HEADER_DIR = @CROSS_SYSTEM_HEADER_DIR@
+
+# autoconf sets SYSTEM_HEADER_DIR to one of the above.
+# Purge it of unnecessary internal relative paths
+# to directories that might not exist yet.
+# The sed idiom for this is to repeat the search-and-replace until it doesn't match, using :a ... ta.
+# Use single quotes here to avoid nested double- and backquotes, this
+# macro is also used in a double-quoted context.
+SYSTEM_HEADER_DIR = `echo @SYSTEM_HEADER_DIR@ | sed -e :a -e 's,[^/]*/\.\.\/,,' -e ta`
+
+# Path to the system headers on the build machine.
+BUILD_SYSTEM_HEADER_DIR = `echo @BUILD_SYSTEM_HEADER_DIR@ | sed -e :a -e 's,[^/]*/\.\.\/,,' -e ta`
+
+# Control whether to run fixincludes.
+STMP_FIXINC = # @STMP_FIXINC@
+
+# Test to see whether <limits.h> exists in the system header files.
+LIMITS_H_TEST = [ -f $(BUILD_SYSTEM_HEADER_DIR)/limits.h ]
+
+# Directory for prefix to system directories, for
+# each of $(system_prefix)/usr/include, $(system_prefix)/usr/lib, etc.
+TARGET_SYSTEM_ROOT = @TARGET_SYSTEM_ROOT@
+TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@
+
+xmake_file=# @xmake_file@
+tmake_file=# @tmake_file@
+TM_ENDIAN_CONFIG=@TM_ENDIAN_CONFIG@
+TM_MULTILIB_CONFIG=@TM_MULTILIB_CONFIG@
+TM_MULTILIB_EXCEPTIONS_CONFIG=@TM_MULTILIB_EXCEPTIONS_CONFIG@
+out_file=$(srcdir)/config/@out_file@
+out_object_file=@out_object_file@
+common_out_file=$(srcdir)/common/config/@common_out_file@
+common_out_object_file=@common_out_object_file@
+EXTRA_GTYPE_DEPS=
+md_file=$(srcdir)/common.md $(srcdir)/config/@md_file@
+tm_file_list=@tm_file_list@
+tm_include_list=@tm_include_list@
+tm_defines=@tm_defines@
+tm_p_file_list=@tm_p_file_list@
+tm_p_include_list=@tm_p_include_list@
+tm_d_file_list=@tm_d_file_list@
+tm_d_include_list=@tm_d_include_list@
+tm_file_list=options.h $(srcdir)/config/dummy/dummy.h $(srcdir)/config/dummy/unix.h $(srcdir)/config/gnu-user.h $(srcdir)/config/glibc-stdint.h $(srcdir)/config/linux.h $(srcdir)/config/dummy/linux-common.h $(srcdir)/defaults.h
+tm_include_list=options.h insn-constants.h config/dummy/dummy.h config/dummy/unix.h config/gnu-user.h config/glibc-stdint.h config/linux.h config/dummy/linux-common.h defaults.h
+tm_p_file_list= $(srcdir)/config/dummy/dummy-protos.h $(srcdir)/config/linux-protos.h tm-preds.h
+tm_p_include_list= config/dummy/dummy-protos.h config/linux-protos.h tm-preds.h
+tm_d_file_list= $(srcdir)/config/dummy/dummy.h $(srcdir)/config/dummy/dummy-protos.h $(srcdir)/defaults.h
+tm_d_include_list=options.h insn-constants.h config/dummy/dummy.h config/dummy/dummy-protos.h defaults.h
+build_xm_file_list=@build_xm_file_list@
+build_xm_include_list=@build_xm_include_list@
+build_xm_defines=@build_xm_defines@
+host_xm_file_list=@host_xm_file_list@
+host_xm_include_list=@host_xm_include_list@
+host_xm_defines=@host_xm_defines@
+xm_file_list=@xm_file_list@
+xm_include_list=@xm_include_list@
+xm_defines=@xm_defines@
+lang_checks=
+lang_checks_parallelized=
+lang_opt_files=@lang_opt_files@ $(srcdir)/c-family/c.opt $(srcdir)/common.opt $(srcdir)/params.opt $(srcdir)/analyzer/analyzer.opt
+lang_specs_files=@lang_specs_files@
+lang_tree_files=@lang_tree_files@
+target_cpu_default=@target_cpu_default@
+OBJC_BOEHM_GC=@objc_boehm_gc@
+extra_modes_file=@extra_modes_file@
+extra_opt_files=@extra_opt_files@
+extra_opt_files= $(srcdir)/config/fused-madd.opt $(srcdir)/config/dummy/dummy.opt $(srcdir)/config/gnu-user.opt $(srcdir)/config/linux.opt
+host_hook_obj=@out_host_hook_obj@
+
+# Multiarch support
+enable_multiarch = @enable_multiarch@
+with_cpu = @with_cpu@
+with_float = @with_float@
+ifeq ($(enable_multiarch),yes)
+ if_multiarch = $(1)
+else
+ ifeq ($(enable_multiarch),auto)
+ # SYSTEM_HEADER_DIR is makefile syntax, cannot be evaluated in configure.ac
+ if_multiarch = $(if $(wildcard $(shell echo $(BUILD_SYSTEM_HEADER_DIR))/../../usr/lib/*/crti.o),$(1))
+ else
+ if_multiarch =
+ endif
+endif
+
+# ------------------------
+# Installation directories
+# ------------------------
+
+# Common prefix for installation directories.
+# NOTE: This directory must exist when you start installation.
+prefix = @prefix@
+# Directory in which to put localized header files. On the systems with
+# gcc as the native cc, `local_prefix' may not be `prefix' which is
+# `/usr'.
+# NOTE: local_prefix *should not* default from prefix.
+local_prefix = @local_prefix@
+# Directory in which to put host dependent programs and libraries
+exec_prefix = @exec_prefix@
+# Directory in which to put the executable for the command `gcc'
+bindir = @bindir@
+# Directory in which to put the directories used by the compiler.
+libdir = @libdir@
+# Directory in which GCC puts its executables.
+libexecdir = @libexecdir@
+
+# --------
+# UNSORTED
+# --------
+
+# Directory in which the compiler finds libraries etc.
+libsubdir = $(libdir)/sdcc/$(real_target_noncanonical)/$(version)$(accel_dir_suffix)
+# Directory in which the compiler finds executables
+libexecsubdir = $(libexecdir)/sdcc/$(real_target_noncanonical)/$(version)$(accel_dir_suffix)
+# Directory in which all plugin resources are installed
+plugin_resourcesdir = $(libsubdir)/plugin
+ # Directory in which plugin headers are installed
+plugin_includedir = $(plugin_resourcesdir)/include
+# Directory in which plugin specific executables are installed
+plugin_bindir = $(libexecsubdir)/plugin
+# Used to produce a relative $(gcc_tooldir) in gcc.o
+ifeq ($(enable_as_accelerator),yes)
+unlibsubdir = ../../../../..
+else
+unlibsubdir = ../../..
+endif
+# $(prefix), expressed as a path relative to $(libsubdir).
+#
+# An explanation of the sed strings:
+# -e 's|^$(prefix)||' matches and eliminates 'prefix' from 'exec_prefix'
+# -e 's|/$$||' match a trailing forward slash and eliminates it
+# -e 's|^[^/]|/|' forces the string to start with a forward slash (*)
+# -e 's|/[^/]*|../|g' replaces each occurrence of /<directory> with ../
+#
+# (*) Note this pattern overwrites the first character of the string
+# with a forward slash if one is not already present. This is not a
+# problem because the exact names of the sub-directories concerned is
+# unimportant, just the number of them matters.
+#
+# The practical upshot of these patterns is like this:
+#
+# prefix exec_prefix result
+# ------ ----------- ------
+# /foo /foo/bar ../
+# /foo/ /foo/bar ../
+# /foo /foo/bar/ ../
+# /foo/ /foo/bar/ ../
+# /foo /foo/bar/ugg ../../
+libsubdir_to_prefix := \
+ $(unlibsubdir)/$(shell echo "$(libdir)" | \
+ sed -e 's|^$(prefix)||' -e 's|/$$||' -e 's|^[^/]|/|' \
+ -e 's|/[^/]*|../|g')
+# $(exec_prefix), expressed as a path relative to $(prefix).
+prefix_to_exec_prefix := \
+ $(shell echo "$(exec_prefix)" | \
+ sed -e 's|^$(prefix)||' -e 's|^/||' -e '/./s|$$|/|')
+# Directory in which to find other cross-compilation tools and headers.
+dollar = @dollar@
+# Used in install-cross.
+gcc_tooldir = @gcc_tooldir@
+# Since gcc_tooldir does not exist at build-time, use -B$(build_tooldir)/bin/
+build_tooldir = $(exec_prefix)/$(target_noncanonical)
+# Directory in which the compiler finds target-independent g++ includes.
+gcc_gxx_include_dir = @gcc_gxx_include_dir@
+gcc_gxx_include_dir_add_sysroot = @gcc_gxx_include_dir_add_sysroot@
+# Directory in which the compiler finds libc++ includes.
+gcc_gxx_libcxx_include_dir = @gcc_gxx_libcxx_include_dir@
+gcc_gxx_libcxx_include_dir_add_sysroot = @gcc_gxx_libcxx_include_dir_add_sysroot@
+# Directory to search for site-specific includes.
+local_includedir = $(local_prefix)/include
+includedir = $(prefix)/include
+# where the info files go
+infodir = @infodir@
+# Where cpp should go besides $prefix/bin if necessary
+cpp_install_dir = @cpp_install_dir@
+# where the locale files go
+datadir = @datadir@
+localedir = $(datadir)/locale
+# Extension (if any) to put in installed man-page filename.
+man1ext = .1
+man7ext = .7
+objext = .o
+exeext = @host_exeext@
+build_exeext = @build_exeext@
+
+# Directory in which to put man pages.
+mandir = @mandir@
+man1dir = $(mandir)/man1
+man7dir = $(mandir)/man7
+# Dir for temp files.
+tmpdir = /tmp
+
+datarootdir = @datarootdir@
+docdir = @docdir@
+# Directory in which to put DVIs
+dvidir = @dvidir@
+# Directory in which to build HTML
+build_htmldir = $(objdir)/HTML/gcc-$(version)
+# Directory in which to put HTML
+htmldir = @htmldir@
+
+# Whether we were configured with NLS.
+USE_NLS = @USE_NLS@
+
+# Internationalization library.
+LIBINTL = @LIBINTL@
+LIBINTL_DEP = @LIBINTL_DEP@
+
+# Character encoding conversion library.
+LIBICONV = @LIBICONV@
+LIBICONV_DEP = @LIBICONV_DEP@
+
+# If a supplementary library is being used for the GC.
+GGC_LIB=
+
+# "true" if the target C library headers are unavailable; "false"
+# otherwise.
+inhibit_libc = @inhibit_libc@
+ifeq ($(inhibit_libc),true)
+INHIBIT_LIBC_CFLAGS = -Dinhibit_libc
+endif
+
+# List of extra executables that should be compiled for this target machine
+# that are used when linking.
+# The rules for compiling them should be in the t-* file for the machine.
+EXTRA_PROGRAMS = @extra_programs@
+
+# List of extra object files that should be compiled and linked with
+# compiler proper (cc1, cc1obj, cc1plus).
+EXTRA_OBJS = @extra_objs@
+
+# List of extra object files that should be compiled and linked with
+# the gcc driver.
+EXTRA_GCC_OBJS =@extra_gcc_objs@
+
+# List of extra libraries that should be linked with the gcc driver.
+EXTRA_GCC_LIBS = @EXTRA_GCC_LIBS@
+
+# List of additional header files to install.
+EXTRA_HEADERS =@extra_headers_list@
+
+# How to handle <stdint.h>.
+USE_GCC_STDINT = no # @use_gcc_stdint@
+
+# The configure script will set this to collect2$(exeext), except on a
+# (non-Unix) host which cannot build collect2, for which it will be
+# set to empty.
+COLLECT2 = # @collect2@
+
+# Program to convert libraries.
+LIBCONVERT =
+
+# Control whether header files are installed.
+INSTALL_HEADERS= # install-headers install-mkheaders
+
+# Control whether Info documentation is built and installed.
+BUILD_INFO = @BUILD_INFO@
+
+# Control whether manpages generated by texi2pod.pl can be rebuilt.
+GENERATED_MANPAGES = # @GENERATED_MANPAGES@
+
+# Additional directories of header files to run fixincludes on.
+# These should be directories searched automatically by default
+# just as /usr/include is.
+# *Do not* use this for directories that happen to contain
+# header files, but are not searched automatically by default.
+# On most systems, this is empty.
+OTHER_FIXINCLUDES_DIRS=
+
+# A list of all the language-specific executables.
+COMPILERS = @all_compilers@
+
+# List of things which should already be built whenever we try to use xgcc
+# to compile anything (without linking).
+GCC_PASSES=xgcc$(exeext) specs
+
+# Directory to link to, when using the target `maketest'.
+DIR = ../gcc
+
+# Native compiler for the build machine and its switches.
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CXX_FOR_BUILD = @CXX_FOR_BUILD@
+BUILD_CFLAGS= @BUILD_CFLAGS@ $(GENERATOR_CFLAGS) -DGENERATOR_FILE
+BUILD_CXXFLAGS = @BUILD_CXXFLAGS@ $(GENERATOR_CFLAGS) -DGENERATOR_FILE
+
+# Native compiler that we use. This may be C++ some day.
+COMPILER_FOR_BUILD = $(CXX_FOR_BUILD)
+BUILD_COMPILERFLAGS = $(BUILD_CXXFLAGS)
+
+# Native linker that we use.
+LINKER_FOR_BUILD = $(CXX_FOR_BUILD)
+BUILD_LINKERFLAGS = $(BUILD_CXXFLAGS)
+
+# Native linker and preprocessor flags. For x-fragment overrides.
+BUILD_LDFLAGS=@BUILD_LDFLAGS@
+BUILD_CPPFLAGS= -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
+ -I$(srcdir)/../include @INCINTL@ $(CPPINC) $(CPPFLAGS)
+
+# Actual name to use when installing a native compiler.
+GCC_INSTALL_NAME := $(shell echo gcc|sed '$(program_transform_name)')
+GCC_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gcc|sed '$(program_transform_name)')
+CPP_INSTALL_NAME := $(shell echo cpp|sed '$(program_transform_name)')
+GCOV_INSTALL_NAME := $(shell echo gcov|sed '$(program_transform_name)')
+GCOV_TOOL_INSTALL_NAME := $(shell echo gcov-tool|sed '$(program_transform_name)')
+GCOV_DUMP_INSTALL_NAME := $(shell echo gcov-dump|sed '$(program_transform_name)')
+
+# Setup the testing framework, if you have one
+EXPECT = `if [ -f $${rootme}/../expect/expect ] ; then \
+ echo $${rootme}/../expect/expect ; \
+ else echo expect ; fi`
+
+RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
+ echo $${srcdir}/../dejagnu/runtest ; \
+ else echo runtest; fi`
+RUNTESTFLAGS =
+
+# This should name the specs file that we're going to install. Target
+# Makefiles may override it and name another file to be generated from
+# the built-in specs and installed as the default spec, as long as
+# they also introduce a rule to generate a file name specs, to be used
+# at build time.
+SPECS = # specs
+
+# Extra include files that are defined by HeaderInclude directives in
+# the .opt files
+OPTIONS_H_EXTRA =
+
+# Extra include files that are defined by SourceInclude directives in
+# the .opt files
+OPTIONS_C_EXTRA = $(PRETTY_PRINT_H)
+
+@option_includes@
+
+# End of variables for you to override.
+
+# GTM_H lists the config files that the generator files depend on,
+# while TM_H lists the ones ordinary gcc files depend on, which
+# includes several files generated by those generators.
+BCONFIG_H = bconfig.h $(build_xm_file_list)
+CONFIG_H = config.h $(host_xm_file_list)
+TCONFIG_H = tconfig.h $(xm_file_list)
+TM_P_H = tm_p.h $(tm_p_file_list)
+TM_D_H = tm_d.h $(tm_d_file_list)
+GTM_H = tm.h $(tm_file_list) # insn-constants.h
+TM_H = $(GTM_H) # insn-flags.h $(OPTIONS_H)
+
+# Variables for version information.
+BASEVER := $(srcdir)/BASE-VER # 4.x.y
+DEVPHASE := $(srcdir)/DEV-PHASE # experimental, prerelease, ""
+DATESTAMP := $(srcdir)/DATESTAMP # YYYYMMDD or empty
+REVISION := $(srcdir)/REVISION # [BRANCH revision XXXXXX]
+
+BASEVER_c := $(shell cat $(BASEVER))
+DEVPHASE_c := $(shell cat $(DEVPHASE))
+DATESTAMP_c := $(shell cat $(DATESTAMP))
+
+ifeq (,$(wildcard $(REVISION)))
+REVISION_c :=
+REVISION :=
+else
+REVISION_c := $(shell cat $(REVISION))
+endif
+
+version := $(shell @get_gcc_base_ver@ $(BASEVER))
+
+PATCHLEVEL_c := \
+ $(shell echo $(BASEVER_c) | sed -e 's/^[0-9]*\.[0-9]*\.\([0-9]*\)$$/\1/')
+
+
+# For use in version.cc - double quoted strings, with appropriate
+# surrounding punctuation and spaces, and with the datestamp and
+# development phase collapsed to the empty string in release mode
+# (i.e. if DEVPHASE_c is empty and PATCHLEVEL_c is 0). The space
+# immediately after the comma in the $(if ...) constructs is
+# significant - do not remove it.
+BASEVER_s := "\"$(BASEVER_c)\""
+DEVPHASE_s := "\"$(if $(DEVPHASE_c), ($(DEVPHASE_c)))\""
+DATESTAMP_s := \
+ "\"$(if $(DEVPHASE_c)$(filter-out 0,$(PATCHLEVEL_c)), $(DATESTAMP_c))\""
+PKGVERSION_s:= "\"@PKGVERSION@\""
+BUGURL_s := "\"@REPORT_BUGS_TO@\""
+
+PKGVERSION := @PKGVERSION@
+BUGURL_TEXI := @REPORT_BUGS_TEXI@
+
+ifdef REVISION_c
+REVISION_s := \
+ "\"$(if $(DEVPHASE_c)$(filter-out 0,$(PATCHLEVEL_c)), $(REVISION_c))\""
+else
+REVISION_s := "\"\""
+endif
+
+# Shorthand variables for dependency lists.
+DUMPFILE_H = $(srcdir)/../libcpp/include/line-map.h dumpfile.h
+VEC_H = vec.h statistics.h $(GGC_H)
+HASH_TABLE_H = $(HASHTAB_H) hash-table.h $(GGC_H)
+EXCEPT_H = except.h $(HASHTAB_H)
+TARGET_DEF = target.def target-hooks-macros.h target-insns.def
+C_TARGET_DEF = c-family/c-target.def target-hooks-macros.h
+COMMON_TARGET_DEF = common/common-target.def target-hooks-macros.h
+# D_TARGET_DEF = d/d-target.def target-hooks-macros.h
+TARGET_H = $(TM_H) target.h $(TARGET_DEF) insn-modes.h insn-codes.h
+C_TARGET_H = c-family/c-target.h $(C_TARGET_DEF)
+COMMON_TARGET_H = common/common-target.h $(INPUT_H) $(COMMON_TARGET_DEF)
+# D_TARGET_H = d/d-target.h $(D_TARGET_DEF)
+MACHMODE_H = machmode.h mode-classes.def
+HOOKS_H = hooks.h
+HOSTHOOKS_DEF_H = hosthooks-def.h $(HOOKS_H)
+LANGHOOKS_DEF_H = langhooks-def.h $(HOOKS_H)
+TARGET_DEF_H = target-def.h target-hooks-def.h $(HOOKS_H) targhooks.h
+C_TARGET_DEF_H = c-family/c-target-def.h c-family/c-target-hooks-def.h \
+ $(TREE_H) $(C_COMMON_H) $(HOOKS_H) common/common-targhooks.h
+CORETYPES_H = coretypes.h insn-modes.h signop.h wide-int.h wide-int-print.h \
+ insn-modes-inline.h $(MACHMODE_H) double-int.h
+RTL_BASE_H = $(CORETYPES_H) rtl.h rtl.def reg-notes.def \
+ insn-notes.def $(INPUT_H) $(REAL_H) statistics.h $(VEC_H) \
+ $(FIXED_VALUE_H) alias.h $(HASHTAB_H)
+FIXED_VALUE_H = fixed-value.h
+RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h
+READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h
+BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \
+ gtm-builtins.def sanitizer.def
+INTERNAL_FN_DEF = internal-fn.def
+INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF)
+TREE_CORE_H = tree-core.h $(CORETYPES_H) all-tree.def tree.def \
+ c-family/c-common.def $(lang_tree_files) \
+ $(BUILTINS_DEF) $(INPUT_H) statistics.h \
+ $(VEC_H) treestruct.def $(HASHTAB_H) \
+ alias.h $(SYMTAB_H) $(FLAGS_H) \
+ $(REAL_H) $(FIXED_VALUE_H)
+TREE_H = tree.h $(TREE_CORE_H) tree-check.h
+REGSET_H = regset.h $(BITMAP_H) hard-reg-set.h
+# BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) \
+# cfg-flags.def cfghooks.h profile-count.h
+GIMPLE_H = gimple.h gimple.def gsstruct.def $(VEC_H) \
+ $(GGC_H) $(BASIC_BLOCK_H) $(TREE_H) tree-ssa-operands.h \
+ tree-ssa-alias.h $(INTERNAL_FN_H) $(HASH_TABLE_H) is-a.h
+GCOV_IO_H = gcov-io.h version.h auto-host.h gcov-counter.def
+RECOG_H = recog.h
+EMIT_RTL_H = emit-rtl.h
+FLAGS_H = flags.h flag-types.h $(OPTIONS_H)
+OPTIONS_H = options.h flag-types.h $(OPTIONS_H_EXTRA)
+FUNCTION_H = function.h $(HASHTAB_H) $(TM_H) hard-reg-set.h \
+ $(VEC_H) $(INPUT_H)
+EXPR_H = expr.h insn-config.h $(FUNCTION_H) $(RTL_H) $(FLAGS_H) $(TREE_H) \
+ $(EMIT_RTL_H)
+OPTABS_H = optabs.h insn-codes.h insn-opinit.h
+REGS_H = regs.h hard-reg-set.h
+CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(BITMAP_H) sbitmap.h
+IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
+IPA_REFERENCE_H = ipa-reference.h $(BITMAP_H) $(TREE_H)
+CGRAPH_H = cgraph.h $(VEC_H) $(TREE_H) $(BASIC_BLOCK_H) $(FUNCTION_H) \
+ cif-code.def ipa-ref.h $(LINKER_PLUGIN_API_H) is-a.h
+DF_H = df.h $(BITMAP_H) $(REGSET_H) sbitmap.h $(BASIC_BLOCK_H) \
+ alloc-pool.h $(TIMEVAR_H)
+RESOURCE_H = resource.h hard-reg-set.h $(DF_H)
+GCC_H = gcc.h version.h $(DIAGNOSTIC_CORE_H)
+GGC_H = ggc.h gtype-desc.h statistics.h
+TIMEVAR_H = timevar.h timevar.def
+INSN_ATTR_H = insn-attr.h insn-attr-common.h $(INSN_ADDR_H)
+INSN_ADDR_H = $(srcdir)/insn-addr.h
+C_COMMON_H = c-family/c-common.h c-family/c-common.def $(TREE_H) \
+ $(SPLAY_TREE_H) $(CPPLIB_H) $(GGC_H) $(DIAGNOSTIC_CORE_H)
+C_PRAGMA_H = c-family/c-pragma.h $(CPPLIB_H)
+C_TREE_H = c/c-tree.h $(C_COMMON_H) $(DIAGNOSTIC_H)
+SYSTEM_H = system.h hwint.h $(srcdir)/../../sdbinutils/include/libiberty.h \
+ $(srcdir)/../include/safe-ctype.h $(srcdir)/../include/filenames.h
+PREDICT_H = predict.h predict.def
+CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
+ $(srcdir)/../libcpp/include/cpplib.h
+CODYLIB_H = $(srcdir)/../libcody/cody.hh
+INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h
+OPTS_H = $(INPUT_H) $(VEC_H) opts.h $(OBSTACK_H)
+SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
+CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h
+TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) $(DUMPFILE_H)
+TREE_PASS_H = tree-pass.h $(TIMEVAR_H) $(DUMPFILE_H)
+TREE_SSA_H = tree-ssa.h tree-ssa-operands.h \
+ $(BITMAP_H) sbitmap.h $(BASIC_BLOCK_H) $(GIMPLE_H) \
+ $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \
+ tree-ssa-alias.h
+PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H) wide-int-print.h
+TREE_PRETTY_PRINT_H = tree-pretty-print.h $(PRETTY_PRINT_H)
+GIMPLE_PRETTY_PRINT_H = gimple-pretty-print.h $(TREE_PRETTY_PRINT_H)
+DIAGNOSTIC_CORE_H = diagnostic-core.h $(INPUT_H) bversion.h diagnostic.def
+DIAGNOSTIC_H = diagnostic.h $(DIAGNOSTIC_CORE_H) $(PRETTY_PRINT_H)
+C_PRETTY_PRINT_H = c-family/c-pretty-print.h $(PRETTY_PRINT_H) \
+ $(C_COMMON_H) $(TREE_H)
+TREE_INLINE_H = tree-inline.h
+REAL_H = real.h
+LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
+ $(CGRAPH_H) $(VEC_H) $(HASH_TABLE_H) $(TREE_H) $(GIMPLE_H) \
+ $(GCOV_IO_H) $(DIAGNOSTIC_H) alloc-pool.h
+IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
+BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
+GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h plugin.def \
+ $(CONFIG_H) $(SYSTEM_H) $(HASHTAB_H)
+PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
+PLUGIN_VERSION_H = plugin-version.h configargs.h
+CONTEXT_H = context.h
+GENSUPPORT_H = gensupport.h read-md.h optabs.def
+RTL_SSA_H = $(PRETTY_PRINT_H) insn-config.h splay-tree-utils.h \
+ $(RECOG_H) $(REGS_H) function-abi.h obstack-utils.h \
+ mux-utils.h rtlanal.h memmodel.h $(EMIT_RTL_H) \
+ rtl-ssa/accesses.h rtl-ssa/insns.h rtl-ssa/blocks.h \
+ rtl-ssa/changes.h rtl-ssa/functions.h rtl-ssa/is-a.inl \
+ rtl-ssa/access-utils.h rtl-ssa/insn-utils.h rtl-ssa/movement.h \
+ rtl-ssa/change-utils.h rtl-ssa/member-fns.inl
+
+#
+# Now figure out from those variables how to compile and link.
+
+# IN_GCC distinguishes between code compiled into GCC itself and other
+# programs built during a bootstrap.
+# autoconf inserts -DCROSS_DIRECTORY_STRUCTURE if we are building a
+# cross compiler which does not use the native headers and libraries.
+INTERNAL_CFLAGS = -DIN_GCC $(PICFLAG) @CROSS@
+
+# This is the variable actually used when we compile. If you change this,
+# you probably want to update BUILD_CFLAGS in configure.ac
+ALL_CFLAGS = $(T_CFLAGS) $(CFLAGS-$@) \
+ $(CFLAGS) $(INTERNAL_CFLAGS) $(COVERAGE_FLAGS) $(WARN_CFLAGS) @DEFS@
+
+# The C++ version.
+ALL_CXXFLAGS = $(T_CFLAGS) $(CFLAGS-$@) $(CXXFLAGS) $(INTERNAL_CFLAGS) \
+ $(COVERAGE_FLAGS) $(ALIASING_FLAGS) $(NOEXCEPTION_FLAGS) \
+ $(WARN_CXXFLAGS) @DEFS@
+
+# Likewise. Put INCLUDES at the beginning: this way, if some autoconf macro
+# puts -I options in CPPFLAGS, our include files in the srcdir will always
+# win against random include files in /usr/include.
+ALL_CPPFLAGS = $(INCLUDES) $(CPPFLAGS)
+
+# This is the variable to use when using $(COMPILER).
+ALL_COMPILERFLAGS = $(ALL_CXXFLAGS)
+
+# This is the variable to use when using $(LINKER).
+ALL_LINKERFLAGS = $(ALL_CXXFLAGS)
+
+# Build and host support libraries.
+
+# Use the "pic" build of libiberty if --enable-host-shared, unless we are
+# building for mingw.
+LIBIBERTY_PICDIR=$(if $(findstring mingw,$(target)),,pic)
+ifeq ($(enable_host_shared),yes)
+LIBIBERTY = ../libiberty/$(LIBIBERTY_PICDIR)/libiberty.a
+BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/$(LIBIBERTY_PICDIR)/libiberty.a
+else
+LIBIBERTY = ../../sdbinutils/libiberty/libiberty.a
+BUILD_LIBIBERTY = ../../sdbinutils/libiberty/libiberty.a
+endif
+
+# Dependencies on the intl and portability libraries.
+LIBDEPS= libcommon.a $(CPPLIB) $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) \
+ $(LIBDECNUMBER) $(LIBBACKTRACE)
+
+# Likewise, for use in the tools that must run on this machine
+# even if we are cross-building GCC.
+BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
+
+# How to link with both our special library facilities
+# and the system's installed libraries.
+LIBS = @LIBS@ libcommon.a $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBBACKTRACE) \
+ $(LIBIBERTY) $(LIBDECNUMBER) $(HOST_LIBS)
+BACKENDLIBS = $(ISLLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
+ $(ZLIB) $(ZSTD_LIB)
+# Any system libraries needed just for GNAT.
+SYSLIBS = @GNAT_LIBEXC@
+
+# Used from ada/gcc-interface/Make-lang.in
+GNATBIND = @GNATBIND@
+GNATMAKE = @GNATMAKE@
+
+# Used from d/Make-lang.in
+GDC = @GDC@
+GDCFLAGS = @GDCFLAGS@
+
+# Libs needed (at present) just for jcf-dump.
+LDEXP_LIB = @LDEXP_LIB@
+
+ZSTD_INC = @ZSTD_CPPFLAGS@
+ZSTD_LIB = @ZSTD_LDFLAGS@ @ZSTD_LIB@
+
+# Likewise, for use in the tools that must run on this machine
+# even if we are cross-building GCC.
+BUILD_LIBS = $(BUILD_LIBIBERTY)
+
+BUILD_RTL = build/rtl.o build/read-rtl.o build/ggc-none.o \
+ build/vec.o build/min-insn-modes.o build/gensupport.o \
+ build/print-rtl.o build/hash-table.o build/sort.o
+BUILD_MD = build/read-md.o
+BUILD_ERRORS = build/errors.o
+
+# sdcc hack
+LIBIBERTY_DIR = $(srcdir)/../sdbinutils/include
+
+# Specify the directories to be searched for header files.
+# Both . and srcdir are used, in that order,
+# so that *config.h will be found in the compilation
+# subdirectory rather than in the source directory.
+# -I$(@D) and -I$(srcdir)/$(@D) cause the subdirectory of the file
+# currently being compiled, in both source trees, to be examined as well.
+# libintl.h will be found in ../intl if we are using the included libintl.
+INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
+ -I$(srcdir)/../include @INCINTL@ \
+ -I${LIBIBERTY_DIR} \
+ $(CPPINC) $(CODYINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \
+ $(ISLINC)
+
+COMPILE.base = $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) -o $@
+ifeq ($(CXXDEPMODE),depmode=gcc3)
+# Note a subtlety here: we use $(@D) for the directory part, to make
+# things like the go/%.o rule work properly; but we use $(*F) for the
+# file part, as we just want the file part of the stem, not the entire
+# file name.
+COMPILE = $(COMPILE.base) -MT $@ -MMD -MP -MF $(@D)/$(DEPDIR)/$(*F).TPo
+POSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(*F).TPo $(@D)/$(DEPDIR)/$(*F).Po
+else
+COMPILE = source='$<' object='$@' libtool=no \
+ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) $(COMPILE.base)
+POSTCOMPILE =
+endif
+
+.cc.o .c.o:
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+#
+# Support for additional languages (other than C).
+# C can be supported this way too (leave for later).
+
+LANG_CONFIGUREFRAGS = @all_lang_configurefrags@
+LANG_MAKEFRAGS = @all_lang_makefrags@
+
+# Used by gcc/jit/Make-lang.in
+LD_VERSION_SCRIPT_OPTION = @ld_version_script_option@
+LD_SONAME_OPTION = @ld_soname_option@
+
+# Flags to pass to recursive makes.
+# CC is set by configure.
+# ??? The choices here will need some experimenting with.
+
+export AR_FOR_TARGET
+export AR_CREATE_FOR_TARGET
+export AR_FLAGS_FOR_TARGET
+export AR_EXTRACT_FOR_TARGET
+export AWK
+export DESTDIR
+export GCC_FOR_TARGET
+export INCLUDES
+export INSTALL_DATA
+export LIPO_FOR_TARGET
+export MACHMODE_H
+export NM_FOR_TARGET
+export STRIP_FOR_TARGET
+export RANLIB_FOR_TARGET
+export libsubdir
+
+FLAGS_TO_PASS = \
+ "ADA_CFLAGS=$(ADA_CFLAGS)" \
+ "BISON=$(BISON)" \
+ "BISONFLAGS=$(BISONFLAGS)" \
+ "CFLAGS=$(CFLAGS) $(WARN_CFLAGS)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "FLEX=$(FLEX)" \
+ "FLEXFLAGS=$(FLEXFLAGS)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_SCRIPT=$(INSTALL_SCRIPT)" \
+ "LN=$(LN)" \
+ "LN_S=$(LN_S)" \
+ "RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "MAKEINFOFLAGS=$(MAKEINFOFLAGS)" \
+ "MAKEOVERRIDES=" \
+ "SHELL=$(SHELL)" \
+ "exeext=$(exeext)" \
+ "build_exeext=$(build_exeext)" \
+ "objext=$(objext)" \
+ "exec_prefix=$(exec_prefix)" \
+ "prefix=$(prefix)" \
+ "local_prefix=$(local_prefix)" \
+ "gxx_include_dir=$(gcc_gxx_include_dir)" \
+ "gxx_libcxx_include_dir=$(gcc_gxx_libcxx_include_dir)" \
+ "build_tooldir=$(build_tooldir)" \
+ "gcc_tooldir=$(gcc_tooldir)" \
+ "bindir=$(bindir)" \
+ "libexecsubdir=$(libexecsubdir)" \
+ "datarootdir=$(datarootdir)" \
+ "datadir=$(datadir)" \
+ "libsubdir=$(libsubdir)" \
+ "localedir=$(localedir)"
+#
+# Lists of files for various purposes.
+
+# All option source files
+ALL_OPT_FILES=$(lang_opt_files) $(extra_opt_files)
+
+# Target specific, C specific object file
+C_TARGET_OBJS=@c_target_objs@
+
+# Target specific, C++ specific object file
+CXX_TARGET_OBJS=@cxx_target_objs@
+
+# Target specific, D specific object file
+D_TARGET_OBJS=@d_target_objs@
+
+# Target specific, Fortran specific object file
+FORTRAN_TARGET_OBJS=@fortran_target_objs@
+
+# Object files for gcc many-languages driver.
+GCC_OBJS = gcc.o gcc-main.o ggc-none.o dummies.o
+
+c-family-warn = $(STRICT_WARN)
+
+# Language-specific object files shared by all C-family front ends.
+C_COMMON_OBJS = c-family/c-cppbuiltin.o c-family/c-dump.o \
+ c-family/c-indentation.o \
+ c-family/c-opts.o \
+ c-family/c-ppoutput.o \
+ c-family/c-pragma.o \
+ c-family/c-lex.o
+
+C_COMMON_OBJS += cc1_dummies.o
+cc1_dummies.o: dummies.cc cc1_dummies.cc
+
+# Analyzer object files
+ANALYZER_OBJS = \
+ analyzer/analysis-plan.o \
+ analyzer/analyzer.o \
+ analyzer/analyzer-logging.o \
+ analyzer/analyzer-pass.o \
+ analyzer/analyzer-selftests.o \
+ analyzer/bar-chart.o \
+ analyzer/call-info.o \
+ analyzer/call-string.o \
+ analyzer/checker-path.o \
+ analyzer/complexity.o \
+ analyzer/constraint-manager.o \
+ analyzer/diagnostic-manager.o \
+ analyzer/engine.o \
+ analyzer/feasible-graph.o \
+ analyzer/function-set.o \
+ analyzer/pending-diagnostic.o \
+ analyzer/program-point.o \
+ analyzer/program-state.o \
+ analyzer/region.o \
+ analyzer/region-model.o \
+ analyzer/region-model-asm.o \
+ analyzer/region-model-impl-calls.o \
+ analyzer/region-model-manager.o \
+ analyzer/region-model-reachability.o \
+ analyzer/sm.o \
+ analyzer/sm-file.o \
+ analyzer/sm-malloc.o \
+ analyzer/sm-pattern-test.o \
+ analyzer/sm-sensitive.o \
+ analyzer/sm-signal.o \
+ analyzer/sm-taint.o \
+ analyzer/state-purge.o \
+ analyzer/store.o \
+ analyzer/supergraph.o \
+ analyzer/svalue.o \
+ analyzer/trimmed-graph.o
+
+# Language-independent object files.
+# We put the *-match.o and insn-*.o files first so that a parallel make
+# will build them sooner, because they are large and otherwise tend to be
+# the last objects to finish building.
+OBJS = \
+ hooks.o \
+ warning-control.o \
+ debug.o \
+ context.o \
+ file-prefix-map.o \
+ ggc-page.o \
+ ggc-common.o \
+ min-insn-modes.o \
+ hash-table.o \
+ opts-global.o \
+ timevar.o \
+ toplev.o \
+ cppdefault.o \
+ pretty-print.o \
+ options-save.o \
+ sort.o \
+ incpath.o \
+ input.o
+
+#sdcc hack
+version.o: version.h
+c-family/c-opts.o: bversion.h
+c-family/c-common.o: bversion.h
+c-family/c-common.o: all-tree.def
+
+# sometimes need insn-attr-common.h
+
+# Objects in libcommon.a, potentially used by all host binaries and with
+# no target dependencies.
+OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+ diagnostic-show-locus.o diagnostic-format-json.o json.o \
+ edit-context.o \
+ pretty-print.o intl.o \
+ sbitmap.o \
+ vec.o input.o hash-table.o ggc-none.o memory-block.o \
+ selftest.o selftest-diagnostic.o sort.o
+
+# Objects in libcommon-target.a, used by drivers and by the core
+# compiler and containing target-dependent code.
+OBJS-libcommon-target = $(common_out_object_file) prefix.o \
+ opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \
+ hash-table.o file-find.o spellcheck.o # selftest.o # opt-suggestions.o
+
+# This lists all host objects for the front ends.
+ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
+
+ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \
+ $(OBJS-libcommon-target) main.o c-family/cppspec.o \
+ $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \
+ $(GCOV_TOOL_OBJS) $(GENGTYPE_OBJS) gcc-ar.o gcc-nm.o gcc-ranlib.o \
+ lto-wrapper.o collect-utils.o
+
+# for anything that is shared use the cc1plus profile data, as that
+# is likely the most exercised during the build
+ifeq ($(if $(wildcard ../stage_current),$(shell cat \
+ ../stage_current)),stageautofeedback)
+$(ALL_HOST_BACKEND_OBJS): ALL_COMPILERFLAGS += -fauto-profile=cc1plus.fda
+$(ALL_HOST_BACKEND_OBJS): cc1plus.fda
+endif
+
+# This lists all host object files, whether they are included in this
+# compilation or not.
+ALL_HOST_OBJS = $(ALL_HOST_FRONTEND_OBJS) $(ALL_HOST_BACKEND_OBJS)
+
+BACKEND = libbackend.a main.o libcommon-target.a libcommon.a \
+ $(CPPLIB) $(LIBDECNUMBER)
+
+# This is defined to "yes" if Tree checking is enabled, which roughly means
+# front-end checking.
+TREECHECKING = @TREECHECKING@
+
+# The full name of the driver on installation
+FULL_DRIVER_NAME=$(target_noncanonical)-gcc-$(version)$(exeext)
+
+MOSTLYCLEANFILES = \
+ insn-output.cc insn-recog.cc insn-emit.cc insn-extract.cc insn-peep.cc \
+ insn-attrtab.cc insn-dfatab.cc \
+ insn-latencytab.cc insn-opinit.cc insn-opinit.h insn-preds.cc \
+ tm-preds.h tm-constrs.h checksum-options gimple-match.cc generic-match.cc \
+ tree-check.h insn-modes.cc insn-modes.h insn-modes-inline.h \
+ genrtl.h gt-*.h gtype-*.h gtype-desc.cc gtyp-input.list \
+ case-cfn-macros.h cfn-operators.pd \
+ xgcc$(exeext) cpp$(exeext) $(FULL_DRIVER_NAME) \
+ $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
+ $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \
+ gcc-ranlib$(exeext) \
+ genversion$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
+ gcov-tool$(exeect) \
+ gengtype$(exeext) *.[0-9][0-9].* *.[si] *-checksum.cc libbackend.a \
+ libcommon-target.a libcommon.a libgcc.mk perf.data
+
+# This symlink makes the full installation name of the driver be available
+# from within the *build* directory, for use when running the JIT library
+# from there (e.g. when running its testsuite).
+$(FULL_DRIVER_NAME): ./xgcc$(exeext)
+ rm -f $@
+ $(LN_S) $< $@
+
+#
+# SELFTEST_DEPS need to be set before including language makefile fragments.
+# Otherwise $(SELFTEST_DEPS) is empty when used from <LANG>/Make-lang.in.
+SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
+
+DO_LINK_SERIALIZATION = @DO_LINK_SERIALIZATION@
+
+# Language makefile fragments.
+
+# The following targets define the interface between us and the languages.
+#
+# all.cross, start.encap, rest.encap,
+# install-common, install-info, install-man,
+# uninstall,
+# mostlyclean, clean, distclean, maintainer-clean,
+#
+# Each language is linked in with a series of hooks. The name of each
+# hooked is "lang.${target_name}" (eg: lang.info). Configure computes
+# and adds these here. We use double-colon rules for some of the hooks;
+# double-colon rules should be preferred for any new hooks.
+
+# language hooks, generated by configure
+@language_hooks@
+
+ifeq ($(DO_LINK_SERIALIZATION),)
+LINK_PROGRESS = :
+else
+LINK_PROGRESS = msg="Linking $@ |"; cnt=0; if test "$(2)" = start; then \
+ idx=0; cnt2=$(DO_LINK_SERIALIZATION); \
+ while test $$cnt2 -le $(1); do msg="$${msg}=="; cnt2=`expr $$cnt2 + 1`; idx=`expr $$idx + 1`; done; \
+ cnt=$$idx; \
+ while test $$cnt -lt $(1); do msg="$${msg}>>"; cnt=`expr $$cnt + 1`; done; \
+ msg="$${msg}--"; cnt=`expr $$cnt + 1`; \
+ else \
+ idx=`expr $(1) + 1`; \
+ while test $$cnt -le $(1); do msg="$${msg}=="; cnt=`expr $$cnt + 1`; done; \
+ fi; \
+ while test $$cnt -lt $(SERIAL_COUNT); do msg="$${msg} "; cnt=`expr $$cnt + 1`; done; \
+ msg="$${msg}| `expr 100 \* $$idx / $(SERIAL_COUNT)`%"; echo "$$msg"
+endif
+
+# Wire in install-gnatlib invocation with `make install' for a configuration
+# with top-level libada disabled.
+gnat_install_lib = @gnat_install_lib@
+
+# per-language makefile fragments
+-include $(LANG_MAKEFRAGS)
+
+# target and host overrides must follow the per-language makefile fragments
+# so they can override or augment language-specific variables
+
+# target overrides
+-include $(tmake_file)
+
+# host overrides
+-include $(xmake_file)
+
+# all-tree.def includes all the tree.def files.
+all-tree.def: s-alltree; @true
+s-alltree: Makefile
+ rm -f tmp-all-tree.def
+ echo '#include "tree.def"' > tmp-all-tree.def
+ echo 'END_OF_BASE_TREE_CODES' >> tmp-all-tree.def
+ echo '#include "c-family/c-common.def"' >> tmp-all-tree.def
+ ltf="$(lang_tree_files)"; for f in $$ltf; do \
+ echo "#include \"$$f\""; \
+ done | sed 's|$(srcdir)/||' >> tmp-all-tree.def
+ $(SHELL) $(srcdir)/../move-if-change tmp-all-tree.def all-tree.def
+ $(STAMP) s-alltree
+
+# Now that LANG_MAKEFRAGS are included, we can add special flags to the
+# objects that belong to the front ends. We add an extra define that
+# causes back-end specific include files to be poisoned, in the hope that
+# we can avoid introducing dependencies of the front ends on things that
+# no front end should ever look at (e.g. everything RTL related).
+$(foreach file,$(ALL_HOST_FRONTEND_OBJS),$(eval CFLAGS-$(file) += -DIN_GCC_FRONTEND))
+
+#
+
+# -----------------------------
+# Rebuilding this configuration
+# -----------------------------
+
+# On the use of stamps:
+# Consider the example of tree-check.h. It is constructed with build/gencheck.
+# A simple rule to build tree-check.h would be
+# tree-check.h: build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tree-check.h
+#
+# but tree-check.h doesn't change every time gencheck changes. It would the
+# nice if targets that depend on tree-check.h wouldn't be rebuild
+# unnecessarily when tree-check.h is unchanged. To make this, tree-check.h
+# must not be overwritten with a identical copy. One solution is to use a
+# temporary file
+# tree-check.h: build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+# $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+#
+# This solution has a different problem. Since the time stamp of tree-check.h
+# is unchanged, make will try to update tree-check.h every time it runs.
+# To prevent this, one can add a stamp
+# tree-check.h: s-check
+# s-check : build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+# $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+# $(STAMP) s-check
+#
+# The problem with this solution is that make thinks that tree-check.h is
+# always unchanged. Make must be deceived into thinking that tree-check.h is
+# rebuild by the "tree-check.h: s-check" rule. To do this, add a dummy command:
+# tree-check.h: s-check; @true
+# s-check : build/gencheck$(build_exeext)
+# $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+# $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+# $(STAMP) s-check
+#
+# This is what is done in this makefile. Note that mkconfig.sh has a
+# move-if-change built-in
+
+Makefile: config.status $(srcdir)/Makefile.in $(LANG_MAKEFRAGS)
+ LANGUAGES="$(CONFIG_LANGUAGES)" \
+ CONFIG_HEADERS= \
+ CONFIG_SHELL="$(SHELL)" \
+ CONFIG_FILES=$@ $(SHELL) config.status
+
+config.h: cs-config.h ; @true
+bconfig.h: cs-bconfig.h ; @true
+tconfig.h: cs-tconfig.h ; @true
+tm.h: # cs-tm.h ; @true
+tm_p.h: # cs-tm_p.h ; @true
+tm_d.h: # cs-tm_d.h ; @true
+
+cs-config.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+ HEADERS="$(host_xm_include_list)" DEFINES="$(host_xm_defines)" \
+ $(SHELL) $(srcdir)/mkconfig.sh config.h
+
+cs-bconfig.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+ HEADERS="$(build_xm_include_list)" DEFINES="$(build_xm_defines)" \
+ $(SHELL) $(srcdir)/mkconfig.sh bconfig.h
+
+cs-tconfig.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+ HEADERS="$(xm_include_list)" DEFINES="USED_FOR_TARGET $(xm_defines)" \
+ $(SHELL) $(srcdir)/mkconfig.sh tconfig.h
+
+cs-tm.h: Makefile
+ TARGET_CPU_DEFAULT="$(target_cpu_default)" \
+ HEADERS="$(tm_include_list)" DEFINES="$(tm_defines)" \
+ $(SHELL) $(srcdir)/mkconfig.sh tm.h
+
+cs-tm_p.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+ HEADERS="$(tm_p_include_list)" DEFINES="" \
+ $(SHELL) $(srcdir)/mkconfig.sh tm_p.h
+
+cs-tm_d.h: Makefile
+ TARGET_CPU_DEFAULT="" \
+ HEADERS="$(tm_d_include_list)" DEFINES="" \
+ $(SHELL) $(srcdir)/mkconfig.sh tm_d.h
+
+# Don't automatically run autoconf, since configure.ac might be accidentally
+# newer than configure. Also, this writes into the source directory which
+# might be on a read-only file system. If configured for maintainer mode
+# then do allow autoconf to be run.
+
+AUTOCONF = autoconf
+ACLOCAL = aclocal
+ACLOCAL_AMFLAGS = -I ../config -I ..
+aclocal_deps = \
+ $(srcdir)/../libtool.m4 \
+ $(srcdir)/../ltoptions.m4 \
+ $(srcdir)/../ltsugar.m4 \
+ $(srcdir)/../ltversion.m4 \
+ $(srcdir)/../lt~obsolete.m4 \
+ $(srcdir)/../config/acx.m4 \
+ $(srcdir)/../config/codeset.m4 \
+ $(srcdir)/../config/depstand.m4 \
+ $(srcdir)/../config/dfp.m4 \
+ $(srcdir)/../config/gcc-plugin.m4 \
+ $(srcdir)/../config/gettext-sister.m4 \
+ $(srcdir)/../config/iconv.m4 \
+ $(srcdir)/../config/lcmessage.m4 \
+ $(srcdir)/../config/lead-dot.m4 \
+ $(srcdir)/../config/lib-ld.m4 \
+ $(srcdir)/../config/lib-link.m4 \
+ $(srcdir)/../config/lib-prefix.m4 \
+ $(srcdir)/../config/mmap.m4 \
+ $(srcdir)/../config/override.m4 \
+ $(srcdir)/../config/picflag.m4 \
+ $(srcdir)/../config/progtest.m4 \
+ $(srcdir)/../config/stdint.m4 \
+ $(srcdir)/../config/warnings.m4 \
+ $(srcdir)/../config/zlib.m4 \
+ $(srcdir)/acinclude.m4
+
+$(srcdir)/configure: @MAINT@ $(srcdir)/configure.ac $(srcdir)/aclocal.m4
+ (cd $(srcdir) && $(AUTOCONF))
+
+$(srcdir)/aclocal.m4 : @MAINT@ $(aclocal_deps)
+ (cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS))
+
+# cstamp-h.in controls rebuilding of config.in.
+# It is named cstamp-h.in and not stamp-h.in so the mostlyclean rule doesn't
+# delete it. A stamp file is needed as autoheader won't update the file if
+# nothing has changed.
+# It remains in the source directory and is part of the distribution.
+# This follows what is done in shellutils, fileutils, etc.
+# "echo timestamp" is used instead of touch to be consistent with other
+# packages that use autoconf (??? perhaps also to avoid problems with patch?).
+# ??? Newer versions have a maintainer mode that may be useful here.
+
+# Don't run autoheader automatically either.
+# Only run it if maintainer mode is enabled.
+@MAINT@ AUTOHEADER = autoheader
+@MAINT@ $(srcdir)/config.in: $(srcdir)/cstamp-h.in
+@MAINT@ $(srcdir)/cstamp-h.in: $(srcdir)/configure.ac
+@MAINT@ (cd $(srcdir) && $(AUTOHEADER))
+@MAINT@ @rm -f $(srcdir)/cstamp-h.in
+@MAINT@ echo timestamp > $(srcdir)/cstamp-h.in
+auto-host.h: cstamp-h ; @true
+cstamp-h: config.in config.status
+ CONFIG_HEADERS=auto-host.h:config.in \
+ CONFIG_FILES= \
+ LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status
+
+# On configurations that require auto-build.h, it is created while
+# running configure, so make config.status depend on it, so that
+# config.status --recheck runs and updates or creates it.
+@HAVE_AUTO_BUILD@auto-build.h: $(srcdir)/configure $(srcdir)/config.gcc
+@HAVE_AUTO_BUILD@ @if test -f $@; then echo rerunning config.status to update $@; \
+@HAVE_AUTO_BUILD@ else echo rerunning config.status to update $@; fi
+@HAVE_AUTO_BUILD@config.status: auto-build.h
+
+# Really, really stupid make features, such as SUN's KEEP_STATE, may force
+# a target to build even if it is up-to-date. So we must verify that
+# config.status does not exist before failing.
+config.status: $(srcdir)/configure $(srcdir)/config.gcc $(LANG_CONFIGUREFRAGS)
+ @if [ ! -f config.status ] ; then \
+ echo You must configure gcc. Look at http://gcc.gnu.org/install/ for details.; \
+ false; \
+ else \
+ LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.status --recheck; \
+ fi
+
+# --------
+# UNSORTED
+# --------
+
+# Provide quickstrap as a target that people can type into the gcc directory,
+# and that fails if you're not into it.
+quickstrap: all
+ cd $(toplevel_builddir) && $(MAKE) all-target-libgcc
+
+all.internal: cc1 cpp # start.encap rest.encap doc selftest
+# This is what to compile if making a cross-compiler.
+all.cross: cc1 cpp$(exeext) specs
+ # libgcc-support lang.all.cross doc selftest @GENINSRC@ srcextra
+# This is what must be made before installing GCC and converting libraries.
+start.encap: cpp$(exeext) specs \
+ # libgcc-support lang.start.encap @GENINSRC@ srcextra
+# These can't be made until after GCC can run.
+rest.encap: lang.rest.encap
+# This is what is made with the host's compiler
+# whether making a cross compiler or not.
+native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
+ $(EXTRA_PROGRAMS) $(COLLECT2) \
+ # gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
+
+ifeq ($(enable_plugin),yes)
+native: gengtype$(exeext)
+endif
+
+# On the target machine, finish building a cross compiler.
+# This does the things that can't be done on the host machine.
+rest.cross: specs
+
+# GCC's selftests.
+# Specify a dummy input file to placate the driver.
+# Specify -nostdinc to work around missing WIND_BASE environment variable
+# required for *-wrs-vxworks-* targets.
+# Specify -o /dev/null so the output of -S is discarded. More importantly
+# It does not try to create a file with the name "null.s" on POSIX and
+# "nul.s" on Windows. Because on Windows "nul" is a reserved file name.
+# Beware that /dev/null is not available to mingw tools, so directly use
+# "nul" instead of "/dev/null" if we're building on a mingw machine.
+# Specify the path to gcc/testsuite/selftests within the srcdir
+# as an argument to -fself-test.
+DEVNULL=$(if $(findstring mingw,$(build)),nul,/dev/null)
+SELFTEST_FLAGS = -nostdinc $(DEVNULL) -S -o $(DEVNULL) \
+ -fself-test=$(srcdir)/testsuite/selftests
+
+# Run the selftests during the build once we have a driver and the frontend,
+# so that self-test failures are caught as early as possible.
+# Use "s-selftest-FE" to ensure that we only run the selftests if the
+# driver, frontend, or selftest data change.
+.PHONY: selftest
+
+# Potentially run all selftest-<LANG>. The various <LANG>/Make-lang.in can
+# require the selftests to be run by defining their selftest-<LANG> as
+# s-selftest-<LANG>. Otherwise, they should define it as empty.
+
+SELFTEST_TARGETS = @selftest_languages@
+selftest: $(SELFTEST_TARGETS)
+
+# Recompile all the language-independent object files.
+# This is used only if the user explicitly asks for it.
+compilations: $(BACKEND)
+
+# This archive is strictly for the host.
+libbackend.a: $(OBJS)
+ -rm -rf libbackend.a
+ @# Build libbackend.a as a thin archive if possible, as doing so
+ @# significantly reduces build times.
+ifeq ($(USE_THIN_ARCHIVES),yes)
+ $(AR) $(AR_FLAGS)T libbackend.a $(OBJS)
+else
+ $(AR) $(AR_FLAGS) libbackend.a $(OBJS)
+ -$(RANLIB) $(RANLIB_FLAGS) libbackend.a
+endif
+
+libcommon-target.a: $(OBJS-libcommon-target)
+ -rm -rf libcommon-target.a
+ $(AR) $(AR_FLAGS) libcommon-target.a $(OBJS-libcommon-target)
+ -$(RANLIB) $(RANLIB_FLAGS) libcommon-target.a
+
+libcommon.a: $(OBJS-libcommon)
+ -rm -rf libcommon.a
+ $(AR) $(AR_FLAGS) libcommon.a $(OBJS-libcommon)
+ -$(RANLIB) $(RANLIB_FLAGS) libcommon.a
+
+# We call this executable `xgcc' rather than `gcc'
+# to avoid confusion if the current directory is in the path
+# and CC is `gcc'. It is renamed to `gcc' when it is installed.
+xgcc$(exeext): $(GCC_OBJS) c/gccspec.o libcommon-target.a $(LIBDEPS) \
+ $(EXTRA_GCC_OBJS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
+ c/gccspec.o $(EXTRA_GCC_OBJS) libcommon-target.a \
+ $(EXTRA_GCC_LIBS) $(LIBS)
+
+# cpp is to cpp0 as e.g. g++ is to cc1plus: Just another driver.
+# It is part of c-family because the handled extensions are hard-coded
+# and only contain c-family extensions (see known_suffixes).
+cpp$(exeext): $(GCC_OBJS) $(SDCPP_OBJS) c-family/cppspec.o ${LIBDEPS} \
+ libcommon-target.a
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) $(SDCPP_OBJS) \
+ libcommon-target.a c-family/cppspec.o \
+ $(EXTRA_GCC_LIBS) $(LIBS) # cpp rule
+
+# Dump a specs file to make -B./ read these specs over installed ones.
+$(SPECS): # xgcc$(exeext)
+ $(GCC_FOR_TARGET) -dumpspecs > tmp-specs
+ mv tmp-specs $(SPECS)
+
+# We do want to create an executable named `xgcc', so we can use it to
+# compile libgcc2.a.
+# Also create gcc-cross, so that install-common will install properly.
+gcc-cross$(exeext): xgcc$(exeext)
+ cp xgcc$(exeext) gcc-cross$(exeext)
+
+checksum-options:
+ echo "$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS)" > checksum-options.tmp \
+ && $(srcdir)/../move-if-change checksum-options.tmp checksum-options
+
+#
+# Build libgcc.a.
+
+libgcc-support: libgcc.mvars stmp-int-hdrs $(TCONFIG_H) \
+ $(MACHMODE_H) version.h
+
+libgcc.mvars: config.status Makefile specs xgcc$(exeext)
+ : > tmp-libgcc.mvars
+ echo GCC_CFLAGS = '$(GCC_CFLAGS)' >> tmp-libgcc.mvars
+ echo INHIBIT_LIBC_CFLAGS = '$(INHIBIT_LIBC_CFLAGS)' >> tmp-libgcc.mvars
+ echo TARGET_SYSTEM_ROOT = '$(TARGET_SYSTEM_ROOT)' >> tmp-libgcc.mvars
+ if test @enable_default_pie@ = yes; then \
+ NO_PIE_CFLAGS="-fno-PIE"; \
+ else \
+ NO_PIE_CFLAGS=; \
+ fi; \
+ echo NO_PIE_CFLAGS = "$$NO_PIE_CFLAGS" >> tmp-libgcc.mvars
+
+ mv tmp-libgcc.mvars libgcc.mvars
+
+# Use the genmultilib shell script to generate the information the gcc
+# driver program needs to select the library directory based on the
+# switches.
+multilib.h: s-mlib; @true
+s-mlib: $(srcdir)/genmultilib Makefile
+ if test @enable_multilib@ = yes \
+ || test -n "$(MULTILIB_OSDIRNAMES)"; then \
+ $(SHELL) $(srcdir)/genmultilib \
+ "$(MULTILIB_OPTIONS)" \
+ "$(MULTILIB_DIRNAMES)" \
+ "$(MULTILIB_MATCHES)" \
+ "$(MULTILIB_EXCEPTIONS)" \
+ "$(MULTILIB_EXTRA_OPTS)" \
+ "$(MULTILIB_EXCLUSIONS)" \
+ "$(MULTILIB_OSDIRNAMES)" \
+ "$(MULTILIB_REQUIRED)" \
+ "$(if $(MULTILIB_OSDIRNAMES),,$(MULTIARCH_DIRNAME))" \
+ "$(MULTILIB_REUSE)" \
+ "@enable_multilib@" \
+ > tmp-mlib.h; \
+ else \
+ $(SHELL) $(srcdir)/genmultilib '' '' '' '' '' '' '' '' \
+ "$(MULTIARCH_DIRNAME)" '' no \
+ > tmp-mlib.h; \
+ fi
+ $(SHELL) $(srcdir)/../move-if-change tmp-mlib.h multilib.h
+ $(STAMP) s-mlib
+#
+# Compiling object files from source files.
+
+# Note that dependencies on obstack.h are not written
+# because that file is not part of GCC.
+
+srcextra: gcc.srcextra lang.srcextra
+
+gcc.srcextra: gengtype-lex.cc
+ -cp -p $^ $(srcdir)
+
+AR_OBJS = file-find.o
+AR_LIBS = @COLLECT2_LIBS@
+
+gcc-ar$(exeext): gcc-ar.o $(AR_OBJS) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ar.o -o $@ \
+ $(AR_OBJS) $(LIBS) $(AR_LIBS)
+
+gcc-nm$(exeext): gcc-nm.o $(AR_OBJS) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-nm.o -o $@ \
+ $(AR_OBJS) $(LIBS) $(AR_LIBS)
+
+gcc-ranlib$(exeext): gcc-ranlib.o $(AR_OBJS) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ranlib.o -o $@ \
+ $(AR_OBJS) $(LIBS) $(AR_LIBS)
+
+CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
+ -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ar\"
+
+CFLAGS-gcc-ranlib.o += $(DRIVER_DEFINES) \
+ -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ranlib\"
+
+CFLAGS-gcc-nm.o += $(DRIVER_DEFINES) \
+ -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"nm\"
+
+# ??? the implicit rules dont trigger if the source file has a different name
+# so copy instead
+gcc-ranlib.cc: gcc-ar.cc
+ cp $^ $@
+
+gcc-nm.cc: gcc-ar.cc
+ cp $^ $@
+
+COLLECT2_OBJS = collect2.o collect2-aix.o vec.o ggc-none.o \
+ collect-utils.o file-find.o hash-table.o selftest.o
+COLLECT2_LIBS = @COLLECT2_LIBS@
+collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
+# Don't try modifying collect2 (aka ld) in place--it might be linking this.
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o T$@ \
+ $(COLLECT2_OBJS) $(LIBS) $(COLLECT2_LIBS)
+ mv -f T$@ $@
+
+CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@
+
+LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o
+lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o T$@ \
+ $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS)
+ mv -f T$@ $@
+
+# Files used by all variants of C or by the stand-alone pre-processor.
+
+CFLAGS-c-family/c-opts.o += @TARGET_SYSTEM_ROOT_DEFINE@
+
+CFLAGS-c-family/c-pch.o += -DHOST_MACHINE=\"$(host)\" \
+ -DTARGET_MACHINE=\"$(target)\"
+
+default-c.o: config/default-c.cc options.h
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+# Files used by all variants of C and some other languages.
+
+CFLAGS-prefix.o += -DPREFIX=\"$(prefix)\" -DBASEVER=$(BASEVER_s)
+prefix.o: $(BASEVER)
+
+# Files used by the D language front end.
+
+default-d.o: config/default-d.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+# Language-independent files.
+
+DRIVER_DEFINES = \
+ -DSTANDARD_STARTFILE_PREFIX=\"$(unlibsubdir)/\" \
+ -DSTANDARD_EXEC_PREFIX=\"$(libdir)/sdcc/\" \
+ -DSTANDARD_LIBEXEC_PREFIX=\"$(libexecdir)/sdcc/\" \
+ -DDEFAULT_TARGET_VERSION=\"$(version)\" \
+ -DDEFAULT_REAL_TARGET_MACHINE=\"$(real_target_noncanonical)\" \
+ -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" \
+ -DSTANDARD_BINDIR_PREFIX=\"$(bindir)/\" \
+ -DTOOLDIR_BASE_PREFIX=\"$(libsubdir_to_prefix)$(prefix_to_exec_prefix)\" \
+ -DACCEL_DIR_SUFFIX=\"$(accel_dir_suffix)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ \
+ $(VALGRIND_DRIVER_DEFINES) \
+ $(if $(SHLIB),$(if $(filter yes,@enable_shared@),-DENABLE_SHARED_LIBGCC)) \
+ -DCONFIGURE_SPECS="\"@CONFIGURE_SPECS@\"" \
+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
+ -DNATIVE_SYSTEM_HEADER_DIR=\"$(NATIVE_SYSTEM_HEADER_DIR)\"
+
+CFLAGS-gcc.o += $(DRIVER_DEFINES) -DBASEVER=$(BASEVER_s)
+gcc.o: $(BASEVER)
+
+specs.h : s-specs ; @true
+s-specs : Makefile
+ lsf="$(lang_specs_files)"; for f in $$lsf; do \
+ echo "#include \"$$f\""; \
+ done | sed 's|$(srcdir)/||' > tmp-specs.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-specs.h specs.h
+ $(STAMP) s-specs
+
+optionlist: s-options ; @true
+s-options: $(ALL_OPT_FILES) Makefile $(srcdir)/opt-gather.awk
+ LC_ALL=C ; export LC_ALL ; \
+ $(AWK) -f $(srcdir)/opt-gather.awk $(ALL_OPT_FILES) > tmp-optionlist
+ $(SHELL) $(srcdir)/../move-if-change tmp-optionlist optionlist
+ $(STAMP) s-options
+
+options.cc: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opt-read.awk \
+ $(srcdir)/optc-gen.awk
+ $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/opt-read.awk \
+ -f $(srcdir)/optc-gen.awk \
+ -v header_name="config.h system.h coretypes.h options.h tm.h" < $< > $@
+
+options-save.cc: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opt-read.awk \
+ $(srcdir)/optc-save-gen.awk
+ $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/opt-read.awk \
+ -f $(srcdir)/optc-save-gen.awk \
+ -v header_name="config.h system.h coretypes.h tm.h" < $< > $@
+
+options.h: s-options-h ; @true
+s-options-h: optionlist $(srcdir)/opt-functions.awk $(srcdir)/opt-read.awk \
+ $(srcdir)/opth-gen.awk
+ $(AWK) -f $(srcdir)/opt-functions.awk -f $(srcdir)/opt-read.awk \
+ -f $(srcdir)/opth-gen.awk \
+ < $< > tmp-options.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-options.h options.h
+ $(STAMP) $@
+
+dumpvers: dumpvers.cc
+
+# lto-compress.o needs $(ZLIBINC) added to the include flags.
+CFLAGS-lto-compress.o += $(ZLIBINC) $(ZSTD_INC)
+
+CFLAGS-lto-streamer-in.o += -DTARGET_MACHINE=\"$(target_noncanonical)\"
+
+bversion.h: s-bversion; @true
+s-bversion: BASE-VER
+ echo "#define BUILDING_GCC_MAJOR `echo $(BASEVER_c) | sed -e 's/^\([0-9]*\).*$$/\1/'`" > bversion.h
+ echo "#define BUILDING_GCC_MINOR `echo $(BASEVER_c) | sed -e 's/^[0-9]*\.\([0-9]*\).*$$/\1/'`" >> bversion.h
+ echo "#define BUILDING_GCC_PATCHLEVEL `echo $(BASEVER_c) | sed -e 's/^[0-9]*\.[0-9]*\.\([0-9]*\)$$/\1/'`" >> bversion.h
+ echo "#define BUILDING_GCC_VERSION (BUILDING_GCC_MAJOR * 1000 + BUILDING_GCC_MINOR)" >> bversion.h
+ $(STAMP) s-bversion
+
+CFLAGS-toplev.o += -DTARGET_NAME=\"$(target_noncanonical)\"
+CFLAGS-optinfo-emit-json.o += -DTARGET_NAME=\"$(target_noncanonical)\" $(ZLIBINC)
+CFLAGS-analyzer/engine.o += $(ZLIBINC)
+
+pass-instances.def: $(srcdir)/passes.def $(PASSES_EXTRA) \
+ $(srcdir)/gen-pass-instances.awk
+ $(AWK) -f $(srcdir)/gen-pass-instances.awk \
+ $(srcdir)/passes.def $(PASSES_EXTRA) > pass-instances.def
+
+$(out_object_file): $(out_file)
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+$(common_out_object_file): $(common_out_file)
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+#
+# Generate header and source files from the machine description,
+# and compile them.
+
+.PRECIOUS: insn-config.h insn-flags.h insn-codes.h insn-constants.h \
+ insn-emit.cc insn-recog.cc insn-extract.cc insn-output.cc insn-peep.cc \
+ insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \
+ insn-latencytab.cc insn-preds.cc gimple-match.cc generic-match.cc \
+ insn-target-def.h
+
+# Dependencies for the md file. The first time through, we just assume
+# the md file itself and the generated dependency file (in order to get
+# it built). The second time through we have the dependency file.
+-include mddeps.mk
+MD_DEPS = # s-mddeps $(md_file) $(MD_INCLUDES)
+
+s-mddeps: $(md_file) $(MD_INCLUDES) build/genmddeps$(build_exeext)
+ $(RUN_GEN) build/genmddeps$(build_exeext) $(md_file) > tmp-mddeps
+ $(SHELL) $(srcdir)/../move-if-change tmp-mddeps mddeps.mk
+ $(STAMP) s-mddeps
+
+# For each of the files generated by running a generator program over
+# the machine description, the following static pattern rules run the
+# generator program only if the machine description has changed,
+# but touch the target file only when its contents actually change.
+# The "; @true" construct forces Make to recheck the timestamp on
+# the target file.
+
+simple_rtl_generated_h = # insn-attr.h insn-attr-common.h insn-codes.h \
+ # insn-config.h insn-flags.h insn-target-def.h
+
+simple_rtl_generated_c = insn-automata.cc insn-emit.cc \
+ insn-extract.cc insn-output.cc \
+ insn-peep.cc insn-recog.cc
+
+simple_generated_h = $(simple_rtl_generated_h) # insn-constants.h
+
+simple_generated_c = $(simple_rtl_generated_c) insn-enums.cc
+
+$(simple_generated_h:insn-%.h=s-%) \
+$(simple_generated_c:insn-%.cc=s-%): s-%: $(MD_DEPS)
+
+$(simple_rtl_generated_h:insn-%.h=s-%) \
+$(simple_rtl_generated_c:insn-%.cc=s-%): s-%: insn-conditions.md
+
+$(simple_generated_h): insn-%.h: s-%; @true
+
+ $(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
+ $(filter insn-conditions.md,$^) > tmp-$*.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-$*.h insn-$*.h
+ $(STAMP) s-$*
+
+$(simple_generated_c): insn-%.cc: s-%; @true
+$(simple_generated_c:insn-%.cc=s-%): s-%: build/gen%$(build_exeext)
+ $(RUN_GEN) build/gen$*$(build_exeext) $(md_file) \
+ $(filter insn-conditions.md,$^) > tmp-$*.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-$*.cc insn-$*.cc
+ $(STAMP) s-$*
+
+# gencheck doesn't read the machine description, and the file produced
+# doesn't use the insn-* convention.
+tree-check.h: # s-check ; @true
+s-check : build/gencheck$(build_exeext)
+ $(RUN_GEN) build/gencheck$(build_exeext) > tmp-check.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-check.h tree-check.h
+ $(STAMP) s-check
+
+# genattrtab produces three files: tmp-{attrtab.cc,dfatab.cc,latencytab.cc}
+insn-attrtab.cc insn-dfatab.cc insn-latencytab.cc: s-attrtab ; @true
+s-attrtab : $(MD_DEPS) build/genattrtab$(build_exeext) \
+ insn-conditions.md
+ $(RUN_GEN) build/genattrtab$(build_exeext) $(md_file) insn-conditions.md \
+ -Atmp-attrtab.cc -Dtmp-dfatab.cc -Ltmp-latencytab.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-attrtab.cc insn-attrtab.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-dfatab.cc insn-dfatab.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-latencytab.cc insn-latencytab.cc
+ $(STAMP) s-attrtab
+
+# genopinit produces two files.
+insn-opinit.cc insn-opinit.h: # s-opinit ; @true
+s-opinit: $(MD_DEPS) build/genopinit$(build_exeext) insn-conditions.md
+ $(RUN_GEN) build/genopinit$(build_exeext) $(md_file) \
+ insn-conditions.md -htmp-opinit.h -ctmp-opinit.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-opinit.h insn-opinit.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-opinit.cc insn-opinit.cc
+ $(STAMP) s-opinit
+
+# gencondmd doesn't use the standard naming convention.
+build/gencondmd.cc: s-conditions; @true
+s-conditions: $(MD_DEPS) build/genconditions$(build_exeext)
+ $(RUN_GEN) build/genconditions$(build_exeext) $(md_file) > tmp-condmd.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-condmd.cc build/gencondmd.cc
+ $(STAMP) s-conditions
+
+insn-conditions.md: # s-condmd; @true
+s-condmd: build/gencondmd$(build_exeext)
+ $(RUN_GEN) build/gencondmd$(build_exeext) > tmp-cond.md
+ $(SHELL) $(srcdir)/../move-if-change tmp-cond.md insn-conditions.md
+ $(STAMP) s-condmd
+
+
+# These files are generated by running the same generator more than
+# once with different options, so they have custom rules. The
+# stampfile idiom is the same.
+genrtl.h: s-genrtl-h; @true
+
+s-genrtl-h: build/gengenrtl$(build_exeext)
+ $(RUN_GEN) build/gengenrtl$(build_exeext) > tmp-genrtl.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-genrtl.h genrtl.h
+ $(STAMP) s-genrtl-h
+
+insn-modes.cc: # s-modes; @true
+insn-modes.h: # s-modes-h; @true
+insn-modes-inline.h: # s-modes-inline-h; @true
+min-insn-modes.cc: # s-modes-m; @true
+
+s-modes: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) > tmp-modes.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-modes.cc insn-modes.cc
+ $(STAMP) s-modes
+
+s-modes-h: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) -h > tmp-modes.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-modes.h insn-modes.h
+ $(STAMP) s-modes-h
+
+s-modes-inline-h: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) -i > tmp-modes-inline.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-modes-inline.h \
+ insn-modes-inline.h
+ $(STAMP) s-modes-inline-h
+
+s-modes-m: build/genmodes$(build_exeext)
+ $(RUN_GEN) build/genmodes$(build_exeext) -m > tmp-min-modes.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-min-modes.cc min-insn-modes.cc
+ $(STAMP) s-modes-m
+
+insn-preds.cc: # s-preds; @true
+tm-preds.h: # s-preds-h; @true
+tm-constrs.h: # s-constrs-h; @true
+
+.PHONY: mddump
+mddump: $(BUILD_RTL) $(MD_DEPS) build/genmddump$(build_exeext)
+ $(RUN_GEN) build/genmddump$(build_exeext) $(md_file) > tmp-mddump.md
+
+s-preds: $(MD_DEPS) build/genpreds$(build_exeext)
+ $(RUN_GEN) build/genpreds$(build_exeext) $(md_file) > tmp-preds.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-preds.cc insn-preds.cc
+ $(STAMP) s-preds
+
+s-preds-h: $(MD_DEPS) build/genpreds$(build_exeext)
+ $(RUN_GEN) build/genpreds$(build_exeext) -h $(md_file) > tmp-preds.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-preds.h tm-preds.h
+ $(STAMP) s-preds-h
+
+s-constrs-h: $(MD_DEPS) build/genpreds$(build_exeext)
+ $(RUN_GEN) build/genpreds$(build_exeext) -c $(md_file) > tmp-constrs.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-constrs.h tm-constrs.h
+ $(STAMP) s-constrs-h
+
+s-case-cfn-macros: build/gencfn-macros$(build_exeext)
+ $(RUN_GEN) build/gencfn-macros$(build_exeext) -c \
+ > tmp-case-cfn-macros.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-case-cfn-macros.h \
+ case-cfn-macros.h
+ $(STAMP) s-case-cfn-macros
+case-cfn-macros.h: # s-case-cfn-macros; @true
+
+s-cfn-operators: # build/gencfn-macros$(build_exeext)
+ $(RUN_GEN) build/gencfn-macros$(build_exeext) -o \
+ > tmp-cfn-operators.pd
+ $(SHELL) $(srcdir)/../move-if-change tmp-cfn-operators.pd \
+ cfn-operators.pd
+ $(STAMP) s-cfn-operators
+cfn-operators.pd: # s-cfn-operators; @true
+
+target-hooks-def.h: # s-target-hooks-def-h; @true
+# make sure that when we build info files, the used tm.texi is up to date.
+$(srcdir)/doc/tm.texi: s-tm-texi; @true
+
+s-target-hooks-def-h: # build/genhooks$(build_exeext)
+ $(RUN_GEN) build/genhooks$(build_exeext) "Target Hook" \
+ > tmp-target-hooks-def.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-target-hooks-def.h \
+ target-hooks-def.h
+ $(STAMP) s-target-hooks-def-h
+
+c-family/c-target-hooks-def.h: # s-c-target-hooks-def-h; @true
+
+s-c-target-hooks-def-h: # build/genhooks$(build_exeext)
+ $(RUN_GEN) build/genhooks$(build_exeext) "C Target Hook" \
+ > tmp-c-target-hooks-def.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-c-target-hooks-def.h \
+ c-family/c-target-hooks-def.h
+ $(STAMP) s-c-target-hooks-def-h
+
+common/common-target-hooks-def.h: # s-common-target-hooks-def-h; @true
+
+s-common-target-hooks-def-h: # build/genhooks$(build_exeext)
+ $(RUN_GEN) build/genhooks$(build_exeext) "Common Target Hook" \
+ > tmp-common-target-hooks-def.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-common-target-hooks-def.h \
+ common/common-target-hooks-def.h
+ $(STAMP) s-common-target-hooks-def-h
+
+d/d-target-hooks-def.h: # s-d-target-hooks-def-h; @true
+
+s-d-target-hooks-def-h: build/genhooks$(build_exeext)
+ $(RUN_GEN) build/genhooks$(build_exeext) "D Target Hook" \
+ > tmp-d-target-hooks-def.h
+ mkdir -p d
+ $(SHELL) $(srcdir)/../move-if-change tmp-d-target-hooks-def.h \
+ d/d-target-hooks-def.h
+ $(STAMP) s-d-target-hooks-def-h
+
+# check if someone mistakenly only changed tm.texi.
+# We use a different pathname here to avoid a circular dependency.
+s-tm-texi: $(srcdir)/doc/../doc/tm.texi
+
+# The tm.texi we want to compare against / check into svn should have
+# unix-style line endings. To make this work on MinGW, remove \r.
+# \r is not portable to Solaris tr, therefore we have a special
+# case for ASCII. We use \r for other encodings like EBCDIC.
+s-tm-texi: build/genhooks$(build_exeext) $(srcdir)/doc/tm.texi.in
+ $(RUN_GEN) build/genhooks$(build_exeext) -d \
+ $(srcdir)/doc/tm.texi.in > tmp-tm.texi
+ case `echo X|tr X '\101'` in \
+ A) tr -d '\015' < tmp-tm.texi > tmp2-tm.texi ;; \
+ *) tr -d '\r' < tmp-tm.texi > tmp2-tm.texi ;; \
+ esac
+ mv tmp2-tm.texi tmp-tm.texi
+ $(SHELL) $(srcdir)/../move-if-change tmp-tm.texi tm.texi
+ @if cmp -s $(srcdir)/doc/tm.texi tm.texi; then \
+ $(STAMP) $@; \
+ elif test $(srcdir)/doc/tm.texi -nt $(srcdir)/doc/tm.texi.in \
+ && ( test $(srcdir)/doc/tm.texi -nt $(srcdir)/target.def \
+ || test $(srcdir)/doc/tm.texi -nt $(srcdir)/c-family/c-target.def \
+ || test $(srcdir)/doc/tm.texi -nt $(srcdir)/common/common-target.def \
+ || test $(srcdir)/doc/tm.texi -nt $(srcdir)/d/d-target.def \
+ ); then \
+ echo >&2 ; \
+ echo You should edit $(srcdir)/doc/tm.texi.in rather than $(srcdir)/doc/tm.texi . >&2 ; \
+ false; \
+ else \
+ echo >&2 ; \
+ echo Verify that you have permission to grant a GFDL license for all >&2 ; \
+ echo new text in $(objdir)/tm.texi, then copy it to $(srcdir)/doc/tm.texi. >&2 ; \
+ false; \
+ fi
+
+gimple-match.cc: # s-match gimple-match-head.cc ; @true
+generic-match.cc: # s-match generic-match-head.cc ; @true
+
+s-match: build/genmatch$(build_exeext) $(srcdir)/match.pd cfn-operators.pd
+ $(RUN_GEN) build/genmatch$(build_exeext) --gimple $(srcdir)/match.pd \
+ > tmp-gimple-match.cc
+ $(RUN_GEN) build/genmatch$(build_exeext) --generic $(srcdir)/match.pd \
+ > tmp-generic-match.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-gimple-match.cc \
+ gimple-match.cc
+ $(SHELL) $(srcdir)/../move-if-change tmp-generic-match.cc \
+ generic-match.cc
+ $(STAMP) s-match
+
+GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
+ $(host_xm_file_list) \
+ $(tm_file_list) $(HASHTAB_H) $(SPLAY_TREE_H) $(srcdir)/bitmap.h \
+ $(srcdir)/wide-int.h $(srcdir)/alias.h \
+ $(srcdir)/coverage.cc $(srcdir)/rtl.h \
+ $(srcdir)/optabs.h $(srcdir)/tree.h $(srcdir)/tree-core.h \
+ $(srcdir)/libfuncs.h $(SYMTAB_H) \
+ $(srcdir)/real.h $(srcdir)/function.h $(srcdir)/insn-addr.h $(srcdir)/hwint.h \
+ $(srcdir)/fixed-value.h \
+ $(srcdir)/function-abi.h \
+ $(srcdir)/output.h $(srcdir)/cfgloop.h $(srcdir)/cfg.h $(srcdir)/profile-count.h \
+ $(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
+ $(srcdir)/symtab-thunks.h $(srcdir)/symtab-thunks.cc \
+ $(srcdir)/symtab-clones.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-modref.h $(srcdir)/ipa-modref.cc \
+ $(srcdir)/ipa-modref-tree.h \
+ $(srcdir)/signop.h \
+ $(srcdir)/diagnostic-spec.h $(srcdir)/diagnostic-spec.cc \
+ $(srcdir)/dwarf2out.h \
+ $(srcdir)/dwarf2asm.cc \
+ $(srcdir)/dwarf2cfi.cc \
+ $(srcdir)/dwarf2ctf.cc \
+ $(srcdir)/dwarf2out.cc \
+ $(srcdir)/ctfc.h \
+ $(srcdir)/ctfout.cc \
+ $(srcdir)/btfout.cc \
+ $(srcdir)/tree-vect-generic.cc \
+ $(srcdir)/gimple-isel.cc \
+ $(srcdir)/dojump.cc $(srcdir)/emit-rtl.h \
+ $(srcdir)/emit-rtl.cc $(srcdir)/except.h $(srcdir)/explow.cc $(srcdir)/expr.cc \
+ $(srcdir)/expr.h \
+ $(srcdir)/function.cc $(srcdir)/except.cc \
+ $(srcdir)/ggc-tests.cc \
+ $(srcdir)/gcse.cc $(srcdir)/godump.cc \
+ $(srcdir)/lists.cc $(srcdir)/optabs-libfuncs.cc \
+ $(srcdir)/profile.cc $(srcdir)/mcf.cc \
+ $(srcdir)/reg-stack.cc $(srcdir)/cfgrtl.cc \
+ $(srcdir)/stor-layout.cc \
+ $(srcdir)/stringpool.cc $(srcdir)/tree.cc $(srcdir)/varasm.cc \
+ $(srcdir)/gimple.h \
+ $(srcdir)/gimple-ssa.h \
+ $(srcdir)/tree-ssanames.cc $(srcdir)/tree-eh.cc $(srcdir)/tree-ssa-address.cc \
+ $(srcdir)/tree-cfg.cc $(srcdir)/tree-ssa-loop-ivopts.cc \
+ $(srcdir)/tree-dfa.cc \
+ $(srcdir)/tree-iterator.cc $(srcdir)/gimple-expr.cc \
+ $(srcdir)/tree-chrec.h \
+ $(srcdir)/tree-scalar-evolution.cc \
+ $(srcdir)/tree-ssa-operands.h \
+ $(srcdir)/tree-profile.cc $(srcdir)/tree-nested.cc \
+ $(srcdir)/omp-offload.h \
+ $(srcdir)/omp-general.cc \
+ $(srcdir)/omp-low.cc \
+ $(srcdir)/targhooks.cc $(out_file) $(srcdir)/passes.cc \
+ $(srcdir)/cgraphclones.cc \
+ $(srcdir)/tree-phinodes.cc \
+ $(srcdir)/tree-ssa-alias.h \
+ $(srcdir)/tree-ssanames.h \
+ $(srcdir)/tree-vrp.h \
+ $(srcdir)/value-range.h \
+ $(srcdir)/ipa-prop.h \
+ $(srcdir)/trans-mem.cc \
+ $(srcdir)/lto-streamer.h \
+ $(srcdir)/target-globals.h \
+ $(srcdir)/ipa-predicate.h \
+ $(srcdir)/ipa-fnsummary.h \
+ $(srcdir)/vtable-verify.cc \
+ $(srcdir)/asan.cc \
+ $(srcdir)/ubsan.cc \
+ $(srcdir)/tsan.cc \
+ $(srcdir)/sanopt.cc \
+ $(srcdir)/sancov.cc \
+ $(srcdir)/ipa-devirt.cc \
+ $(srcdir)/internal-fn.h \
+ $(srcdir)/calls.cc \
+ $(srcdir)/omp-general.h \
+ @all_gtfiles@
+
+# Compute the list of GT header files from the corresponding C sources,
+# possibly nested within config or language subdirectories. Match gengtype's
+# behavior in this respect: gt-LANG-file.h for "file" anywhere within a LANG
+# language subdir, gt-file.h otherwise (no subdir indication for config/
+# related sources).
+
+GTFILES_H = $(subst /,-, \
+ $(shell echo $(patsubst $(srcdir)/%,gt-%, \
+ $(patsubst %.cc,%.h, \
+ $(filter %.cc, $(GTFILES)))) \
+ | sed -e "s|/[^ ]*/|/|g" -e "s|gt-config/|gt-|g"))
+
+GTFILES_LANG_H = $(patsubst [%], gtype-%.h, $(filter [%], $(GTFILES)))
+ALL_GTFILES_H := $(sort $(GTFILES_H) $(GTFILES_LANG_H))
+
+# $(GTFILES) may be too long to put on a command line, so we have to
+# write it out to a file (taking care not to do that in a way that
+# overflows a command line!) and then have gengtype read the file in.
+
+$(ALL_GTFILES_H) gtype-desc.cc gtype-desc.h gtype.state: # s-gtype ; @true
+
+### Common flags to gengtype [e.g. -v or -B backupdir]
+GENGTYPE_FLAGS=
+
+gtyp-input.list: s-gtyp-input ; @true
+s-gtyp-input: Makefile
+ @: $(call write_entries_to_file,$(GTFILES),tmp-gi.list)
+ $(SHELL) $(srcdir)/../move-if-change tmp-gi.list gtyp-input.list
+ $(STAMP) s-gtyp-input
+
+s-gtype: $(EXTRA_GTYPE_DEPS) build/gengtype$(build_exeext) \
+ $(filter-out [%], $(GTFILES)) gtyp-input.list
+# First, parse all files and save a state file.
+ $(RUN_GEN) build/gengtype$(build_exeext) $(GENGTYPE_FLAGS) \
+ -S $(srcdir) -I gtyp-input.list -w tmp-gtype.state
+# Second, read the state file and generate all files. This ensure that
+# gtype.state is correctly read:
+ $(SHELL) $(srcdir)/../move-if-change tmp-gtype.state gtype.state
+ $(RUN_GEN) build/gengtype$(build_exeext) $(GENGTYPE_FLAGS) \
+ -r gtype.state
+ $(STAMP) s-gtype
+
+generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_H) multilib.h \
+ $(simple_generated_h) specs.h \
+ tree-check.h genrtl.h \
+ tm-preds.h tm-constrs.h \
+ $(ALL_GTFILES_H) gtype-desc.cc gtype-desc.h version.h \
+ options.h target-hooks-def.h insn-opinit.h \
+ common/common-target-hooks-def.h pass-instances.def \
+ gimple-match.cc generic-match.cc \
+ c-family/c-target-hooks-def.h d/d-target-hooks-def.h \
+ case-cfn-macros.h \
+ cfn-operators.pd omp-device-properties.h
+
+#
+# How to compile object files to run on the build machine.
+
+build/%.o : # dependencies provided by explicit rule later
+ $(COMPILER_FOR_BUILD) -c $(BUILD_COMPILERFLAGS) $(BUILD_CPPFLAGS) \
+ -o $@ $<
+
+# Header dependencies for the programs that generate source code.
+# These are library modules...
+build/errors.o : errors.cc $(BCONFIG_H) $(SYSTEM_H) errors.h
+build/gensupport.o: gensupport.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) errors.h \
+ $(HASHTAB_H) $(READ_MD_H) $(GENSUPPORT_H) $(HASH_TABLE_H)
+build/ggc-none.o : ggc-none.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ $(GGC_H)
+build/min-insn-modes.o : min-insn-modes.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H)
+build/print-rtl.o: print-rtl.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ $(GTM_H) $(RTL_BASE_H)
+build/read-md.o: read-md.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ $(HASHTAB_H) errors.h $(READ_MD_H)
+build/read-rtl.o: read-rtl.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H) $(READ_MD_H) \
+ $(GENSUPPORT_H)
+build/rtl.o: rtl.cc $(BCONFIG_H) $(CORETYPES_H) $(GTM_H) $(SYSTEM_H) \
+ $(RTL_H) $(GGC_H) errors.h
+build/vec.o : vec.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(VEC_H) \
+ $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H) $(HASH_TABLE_H)
+build/hash-table.o : hash-table.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(HASH_TABLE_H) $(GGC_H) toplev.h $(DIAGNOSTIC_CORE_H)
+build/sort.o : sort.cc $(BCONFIG_H) $(SYSTEM_H)
+build/inchash.o : inchash.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ $(HASHTAB_H) inchash.h
+build/gencondmd.o : build/gencondmd.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) insn-constants.h \
+ $(filter-out insn-flags.h, $(RTL_H) $(TM_P_H) $(FUNCTION_H) $(REGS_H) \
+ $(RECOG_H) output.h $(FLAGS_H) $(RESOURCE_H) toplev.h $(DIAGNOSTIC_CORE_H) reload.h \
+ $(EXCEPT_H) tm-constrs.h)
+# This pulls in tm-pred.h which contains inline functions wrapping up
+# predicates from the back-end so those functions must be discarded.
+# No big deal since gencondmd.cc is a dummy file for non-GCC compilers.
+build/gencondmd.o : \
+ BUILD_CFLAGS := $(filter-out -fkeep-inline-functions, $(BUILD_CFLAGS))
+
+# ...these are the programs themselves.
+build/genattr.o : genattr.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/genattr-common.o : genattr-common.cc $(RTL_BASE_H) $(BCONFIG_H) \
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/genattrtab.o : genattrtab.cc $(RTL_BASE_H) $(OBSTACK_H) \
+ $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(GGC_H) \
+ $(READ_MD_H) $(GENSUPPORT_H) $(FNMATCH_H)
+build/genautomata.o : genautomata.cc $(RTL_BASE_H) $(OBSTACK_H) \
+ $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(VEC_H) \
+ $(HASHTAB_H) $(GENSUPPORT_H) $(FNMATCH_H)
+build/gencheck.o : gencheck.cc all-tree.def $(BCONFIG_H) $(GTM_H) \
+ $(SYSTEM_H) $(CORETYPES_H) tree.def c-family/c-common.def \
+ $(lang_tree_files) gimple.def
+build/genchecksum.o : genchecksum.cc $(BCONFIG_H) $(SYSTEM_H) $(MD5_H)
+build/gencodes.o : gencodes.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H)
+build/genconditions.o : genconditions.cc $(RTL_BASE_H) $(BCONFIG_H) \
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(HASHTAB_H) \
+ $(READ_MD_H) $(GENSUPPORT_H)
+build/genconfig.o : genconfig.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H)
+build/genconstants.o : genconstants.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) errors.h $(READ_MD_H)
+build/genemit.o : genemit.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) internal-fn.def
+build/genenums.o : genenums.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) errors.h $(READ_MD_H)
+build/genextract.o : genextract.cc $(RTL_BASE_H) $(BCONFIG_H) \
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/genflags.o : genflags.cc $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H) \
+ $(SYSTEM_H) $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/gentarget-def.o : gentarget-def.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) \
+ $(GENSUPPORT_H) $(HASH_TABLE_H) target-insns.def
+build/gengenrtl.o : gengenrtl.cc $(BCONFIG_H) $(SYSTEM_H) rtl.def
+
+# The gengtype generator program is special: Two versions are built.
+# One is for the build machine, and one is for the host to allow
+# plugins to define their types and generate the supporting GGC
+# datastructures and routines with GTY markers.
+# The host object files depend on CONFIG_H, and the build objects
+# on BCONFIG_H. For the build objects, add -DGENERATOR_FILE manually,
+# the build-%: rule doesn't apply to them.
+
+GENGTYPE_OBJS = gengtype.o gengtype-parse.o gengtype-state.o \
+ gengtype-lex.o errors.o
+
+gengtype-lex.o build/gengtype-lex.o : gengtype-lex.cc gengtype.h $(SYSTEM_H)
+CFLAGS-gengtype-lex.o += -DHOST_GENERATOR_FILE
+build/gengtype-lex.o: $(BCONFIG_H)
+
+gengtype-parse.o build/gengtype-parse.o : gengtype-parse.cc gengtype.h \
+ $(SYSTEM_H)
+CFLAGS-gengtype-parse.o += -DHOST_GENERATOR_FILE
+build/gengtype-parse.o: $(BCONFIG_H)
+
+gengtype-state.o build/gengtype-state.o: gengtype-state.cc $(SYSTEM_H) \
+ gengtype.h errors.h version.h $(HASHTAB_H) $(OBSTACK_H) \
+ $(XREGEX_H)
+CFLAGS-gengtype-state.o += -DHOST_GENERATOR_FILE
+build/gengtype-state.o: $(BCONFIG_H)
+gengtype.o build/gengtype.o : gengtype.cc $(SYSTEM_H) gengtype.h \
+ rtl.def insn-notes.def errors.h version.h \
+ $(HASHTAB_H) $(OBSTACK_H) $(XREGEX_H)
+CFLAGS-gengtype.o += -DHOST_GENERATOR_FILE
+build/gengtype.o: $(BCONFIG_H)
+
+CFLAGS-errors.o += -DHOST_GENERATOR_FILE
+
+build/genmddeps.o: genmddeps.cc $(BCONFIG_H) $(SYSTEM_H) $(CORETYPES_H) \
+ errors.h $(READ_MD_H)
+build/genmodes.o : genmodes.cc $(BCONFIG_H) $(SYSTEM_H) errors.h \
+ $(HASHTAB_H) machmode.def $(extra_modes_file)
+build/genopinit.o : genopinit.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def
+build/genoutput.o : genoutput.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/genpeep.o : genpeep.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h \
+ $(DIAGNOSTIC_CORE_H)
+build/genpreds.o : genpreds.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H)
+build/genrecog.o : genrecog.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) \
+ $(HASH_TABLE_H) inchash.h
+build/genhooks.o : genhooks.cc $(TARGET_DEF) $(C_TARGET_DEF) \
+ $(COMMON_TARGET_DEF) $(D_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
+build/genmddump.o : genmddump.cc $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
+build/genmatch.o : genmatch.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \
+ tree.def builtins.def internal-fn.def case-cfn-macros.h $(CPPLIB_H)
+build/gencfn-macros.o : gencfn-macros.cc $(BCONFIG_H) $(SYSTEM_H) \
+ $(CORETYPES_H) errors.h $(HASH_TABLE_H) hash-set.h builtins.def \
+ internal-fn.def
+
+# Compile the programs that generate insn-* from the machine description.
+# They are compiled with $(COMPILER_FOR_BUILD), and associated libraries,
+# since they need to run on this machine
+# even if GCC is being compiled to run on some other machine.
+
+# All these programs use the RTL reader ($(BUILD_RTL)).
+genprogrtl = attr attr-common attrtab automata codes conditions config emit \
+ extract flags mddump opinit output peep preds recog target-def
+$(genprogrtl:%=build/gen%$(build_exeext)): $(BUILD_RTL)
+
+# All these programs use the MD reader ($(BUILD_MD)).
+genprogmd = $(genprogrtl) mddeps constants enums
+$(genprogmd:%=build/gen%$(build_exeext)): $(BUILD_MD)
+
+# All these programs need to report errors.
+genprogerr = $(genprogmd) genrtl modes gtype hooks cfn-macros condmd
+$(genprogerr:%=build/gen%$(build_exeext)): $(BUILD_ERRORS)
+
+# Remaining build programs.
+genprog = # $(genprogerr) check checksum match
+genprog = checksum
+
+# These programs need libs over and above what they get from the above list.
+build/genautomata$(build_exeext) : BUILD_LIBS += -lm
+
+build/genrecog$(build_exeext) : build/hash-table.o build/inchash.o
+build/gencfn-macros$(build_exeext) : build/hash-table.o build/vec.o \
+ build/ggc-none.o build/sort.o
+
+# For stage1 and when cross-compiling use the build libcpp which is
+# built with NLS disabled. For stage2+ use the host library and
+# its dependencies.
+ifeq ($(build_objdir),$(build_libobjdir))
+BUILD_CPPLIB = $(build_libobjdir)/libcpp/libcpp.a
+
+# SDCC hack:
+BUILD_CPPLIB = ../libcpp/libcpp.a
+
+else
+BUILD_CPPLIB = $(CPPLIB) $(LIBIBERTY)
+build/genmatch$(build_exeext): BUILD_LIBDEPS += $(LIBINTL_DEP) $(LIBICONV_DEP)
+build/genmatch$(build_exeext): BUILD_LIBS += $(LIBINTL) $(LIBICONV)
+endif
+
+build/genmatch$(build_exeext) : $(BUILD_CPPLIB) \
+ $(BUILD_ERRORS) build/vec.o build/hash-table.o build/sort.o
+
+# These programs are not linked with the MD reader.
+build/gengtype$(build_exeext) : build/gengtype-lex.o build/gengtype-parse.o \
+ build/gengtype-state.o build/errors.o
+
+gengtype$(exeext) : gengtype.o gengtype-lex.o gengtype-parse.o \
+ gengtype-state.o errors.o $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
+ $(filter-out $(LIBDEPS), $^) $(LIBS)
+
+# Rule for the generator programs:
+$(genprog:%=build/gen%$(build_exeext)): build/gen%$(build_exeext): build/gen%.o $(BUILD_LIBDEPS)
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
+ $(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
+
+omp-general.o: omp-device-properties.h
+
+omp_device_properties = @omp_device_properties@
+omp-device-properties.h: s-omp-device-properties-h ; @true
+s-omp-device-properties-h: @omp_device_property_deps@
+ -rm -f tmp-omp-device-properties.h; \
+ for kind in kind arch isa; do \
+ echo 'const char omp_offload_device_'$${kind}'[] = ' \
+ >> tmp-omp-device-properties.h; \
+ for prop in none $(omp_device_properties); do \
+ [ "$$prop" = "none" ] && continue; \
+ tgt=`echo "$$prop" | sed 's/=.*$$//'`; \
+ props=`echo "$$prop" | sed 's/.*=//'`; \
+ echo "\"$$tgt\\0\"" >> tmp-omp-device-properties.h; \
+ sed -n 's/^'$${kind}': //p' $${props} \
+ | sed 's/[[:blank:]]/ /g;s/ */ /g;s/^ //;s/ $$//;s/ /\\0/g;s/^/"/;s/$$/\\0\\0"/' \
+ >> tmp-omp-device-properties.h; \
+ done; \
+ echo '"";' >> tmp-omp-device-properties.h; \
+ done; \
+ $(SHELL) $(srcdir)/../move-if-change tmp-omp-device-properties.h \
+ omp-device-properties.h
+ $(STAMP) s-omp-device-properties-h
+
+# Generated source files for gengtype. Prepend inclusion of
+# config.h/bconfig.h because AIX requires _LARGE_FILES to be defined before
+# any system header is included.
+gengtype-lex.cc : gengtype-lex.l
+ -$(FLEX) $(FLEXFLAGS) -o$@ $< && { \
+ echo '#ifdef HOST_GENERATOR_FILE' > $@.tmp; \
+ echo '#include "config.h"' >> $@.tmp; \
+ echo '#else' >> $@.tmp; \
+ echo '#include "bconfig.h"' >> $@.tmp; \
+ echo '#endif' >> $@.tmp; \
+ cat $@ >> $@.tmp; \
+ mv $@.tmp $@; \
+ }
+
+#
+# Remake internationalization support.
+CFLAGS-intl.o += -DLOCALEDIR=\"$(localedir)\"
+
+#
+# Remake cpp.
+
+PREPROCESSOR_DEFINES = \
+ -DGCC_INCLUDE_DIR=\"$(libsubdir)/include\" \
+ -DFIXED_INCLUDE_DIR=\"$(libsubdir)/include-fixed\" \
+ -DGPLUSPLUS_INCLUDE_DIR=\"$(gcc_gxx_include_dir)\" \
+ -DGPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_include_dir_add_sysroot) \
+ -DGPLUSPLUS_TOOL_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/$(target_noncanonical)\" \
+ -DGPLUSPLUS_BACKWARD_INCLUDE_DIR=\"$(gcc_gxx_include_dir)/backward\" \
+ -DGPLUSPLUS_LIBCXX_INCLUDE_DIR=\"$(gcc_gxx_libcxx_include_dir)\" \
+ -DGPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT=$(gcc_gxx_libcxx_include_dir_add_sysroot) \
+ -DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
+ -DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
+ -DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
+ -DNATIVE_SYSTEM_HEADER_DIR=\"$(NATIVE_SYSTEM_HEADER_DIR)\" \
+ -DPREFIX=\"$(prefix)/\" \
+ -DSTANDARD_EXEC_PREFIX=\"$(libdir)/sdcc/\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@
+
+CFLAGS-cppbuiltin.o += $(PREPROCESSOR_DEFINES) -DBASEVER=$(BASEVER_s)
+cppbuiltin.o: $(BASEVER)
+
+CFLAGS-cppdefault.o += $(PREPROCESSOR_DEFINES)
+
+# Note for the stamp targets, we run the program `true' instead of
+# having an empty command (nothing following the semicolon).
+
+# genversion.cc is run on the build machine to generate version.h
+CFLAGS-build/genversion.o += -DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \
+ -DREVISION=$(REVISION_s) \
+ -DDEVPHASE=$(DEVPHASE_s) -DPKGVERSION=$(PKGVERSION_s) \
+ -DBUGURL=$(BUGURL_s)
+
+build/genversion.o: genversion.cc $(BCONFIG_H) $(SYSTEM_H) $(srcdir)/DATESTAMP
+
+build/genversion$(build_exeext): build/genversion.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) \
+ build/genversion.o -o $@
+
+version.h: s-version; @true
+s-version: build/genversion$(build_exeext)
+ build/genversion$(build_exeext) > tmp-version.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-version.h version.h
+ $(STAMP) s-version
+
+# gcov.o needs $(ZLIBINC) added to the include flags.
+CFLAGS-gcov.o += $(ZLIBINC)
+
+GCOV_OBJS = gcov.o json.o
+gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_OBJS) \
+ hash-table.o ggc-none.o $(LIBS) $(ZLIB) -o $@
+GCOV_DUMP_OBJS = gcov-dump.o
+gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) \
+ hash-table.o ggc-none.o\
+ $(LIBS) -o $@
+
+GCOV_TOOL_DEP_FILES = $(srcdir)/../libgcc/libgcov-util.c gcov-io.cc $(GCOV_IO_H) \
+ $(srcdir)/../libgcc/libgcov-driver.c $(srcdir)/../libgcc/libgcov-driver-system.c \
+ $(srcdir)/../libgcc/libgcov-merge.c $(srcdir)/../libgcc/libgcov.h \
+ $(SYSTEM_H) coretypes.h $(TM_H) $(CONFIG_H) version.h intl.h $(DIAGNOSTIC_H)
+libgcov-util.o: $(srcdir)/../libgcc/libgcov-util.c $(GCOV_TOOL_DEP_FILES)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) -o $@ $<
+libgcov-driver-tool.o: $(srcdir)/../libgcc/libgcov-driver.c $(GCOV_TOOL_DEP_FILES)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ -DIN_GCOV_TOOL=1 -o $@ $<
+libgcov-merge-tool.o: $(srcdir)/../libgcc/libgcov-merge.c $(GCOV_TOOL_DEP_FILES)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ -DIN_GCOV_TOOL=1 -o $@ $<
+GCOV_TOOL_OBJS = gcov-tool.o libgcov-util.o libgcov-driver-tool.o libgcov-merge-tool.o
+gcov-tool$(exeext): $(GCOV_TOOL_OBJS) $(LIBDEPS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_TOOL_OBJS) $(LIBS) -o $@
+#
+# Build the include directories. The stamp files are stmp-* rather than
+# s-* so that mostlyclean does not force the include directory to
+# be rebuilt.
+
+# Build the include directories.
+stmp-int-hdrs: # $(STMP_FIXINC) $(T_GLIMITS_H) $(T_STDINT_GCC_H) $(USER_H) fixinc_list
+# Copy in the headers provided with gcc.
+#
+# The sed command gets just the last file name component;
+# this is necessary because VPATH could add a dirname.
+# Using basename would be simpler, but some systems don't have it.
+#
+# The touch command is here to workaround an AIX/Linux NFS bug.
+#
+# The move-if-change + cp -p twists for limits.h are intended to preserve
+# the time stamp when we regenerate, to prevent pointless rebuilds during
+# e.g. install-no-fixedincludes.
+ -if [ -d include ] ; then true; else mkdir include; chmod a+rx include; fi
+ -if [ -d include-fixed ] ; then true; else mkdir include-fixed; chmod a+rx include-fixed; fi
+ for file in .. $(USER_H); do \
+ if [ X$$file != X.. ]; then \
+ realfile=`echo $$file | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
+ $(STAMP) include/$$realfile; \
+ rm -f include/$$realfile; \
+ cp $$file include; \
+ chmod a+r include/$$realfile; \
+ fi; \
+ done
+ for file in .. $(USER_H_INC_NEXT_PRE); do \
+ if [ X$$file != X.. ]; then \
+ mv include/$$file include/x_$$file; \
+ echo "#include_next <$$file>" >include/$$file; \
+ cat include/x_$$file >>include/$$file; \
+ rm -f include/x_$$file; \
+ chmod a+r include/$$file; \
+ fi; \
+ done
+ for file in .. $(USER_H_INC_NEXT_POST); do \
+ if [ X$$file != X.. ]; then \
+ echo "#include_next <$$file>" >>include/$$file; \
+ chmod a+r include/$$file; \
+ fi; \
+ done
+ rm -f include/stdint.h
+ if [ $(USE_GCC_STDINT) = wrap ]; then \
+ rm -f include/stdint-gcc.h; \
+ cp $(srcdir)/ginclude/stdint-gcc.h include/stdint-gcc.h; \
+ chmod a+r include/stdint-gcc.h; \
+ cp $(srcdir)/ginclude/stdint-wrap.h include/stdint.h; \
+ chmod a+r include/stdint.h; \
+ elif [ $(USE_GCC_STDINT) = provide ]; then \
+ cp $(T_STDINT_GCC_H) include/stdint.h; \
+ chmod a+r include/stdint.h; \
+ fi
+ 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}; \
+ 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; \
+ $(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; \
+ done
+# Install the README
+ rm -f include-fixed/README
+ cp $(srcdir)/../fixincludes/README-fixinc include-fixed/README
+ chmod a+r include-fixed/README
+ $(STAMP) $@
+
+.PHONY: install-gcc-tooldir
+install-gcc-tooldir:
+ $(mkinstalldirs) $(DESTDIR)$(gcc_tooldir)
+
+macro_list: # s-macro_list; @true
+s-macro_list : $(GCC_PASSES) cc1$(exeext)
+ echo | $(GCC_FOR_TARGET) -E -dM - | \
+ sed -n -e 's/^#define \([^_][a-zA-Z0-9_]*\).*/\1/p' \
+ -e 's/^#define \(_[^_A-Z][a-zA-Z0-9_]*\).*/\1/p' | \
+ sort -u > tmp-macro_list
+ $(SHELL) $(srcdir)/../move-if-change tmp-macro_list macro_list
+ $(STAMP) s-macro_list
+
+fixinc_list: # s-fixinc_list; @true
+s-fixinc_list : $(GCC_PASSES)
+# Build up a list of multilib directories and corresponding sysroot
+# suffixes, in form sysroot;multilib.
+ if $(GCC_FOR_TARGET) -print-sysroot-headers-suffix > /dev/null 2>&1; then \
+ set -e; for ml in `$(GCC_FOR_TARGET) -print-multi-lib`; do \
+ multi_dir=`echo $${ml} | sed -e 's/;.*$$//'`; \
+ flags=`echo $${ml} | sed -e 's/^[^;]*;//' -e 's/@/ -/g'`; \
+ sfx=`$(GCC_FOR_TARGET) $${flags} -print-sysroot-headers-suffix`; \
+ if [ "$${multi_dir}" = "." ]; \
+ then multi_dir=""; \
+ else \
+ multi_dir=/$${multi_dir}; \
+ fi; \
+ echo "$${sfx};$${multi_dir}"; \
+ done; \
+ else \
+ echo ";"; \
+ fi > tmp-fixinc_list
+ $(SHELL) $(srcdir)/../move-if-change tmp-fixinc_list fixinc_list
+ $(STAMP) s-fixinc_list
+
+# The line below is supposed to avoid accidentally matching the
+# built-in suffix rule `.o:' to build fixincl out of fixincl.o. You'd
+# expect fixincl to be newer than fixincl.o, such that this situation
+# would never come up. As it turns out, if you use ccache with
+# CCACHE_HARDLINK enabled, the compiler doesn't embed the current
+# working directory in object files (-g absent, or -fno-working-dir
+# present), and build and host are the same, fixincl for the host will
+# build after fixincl for the build machine, getting a cache hit,
+# thereby updating the timestamp of fixincl.o in the host tree.
+# Because of CCACHE_HARDLINK, this will also update the timestamp in
+# the build tree, and so fixincl in the build tree will appear to be
+# out of date. Yuck.
+../$(build_subdir)/fixincludes/fixincl: ; @ :
+
+# Build fixed copies of system files.
+# Abort if no system headers available, unless building a crosscompiler.
+# FIXME: abort unless building --without-headers would be more accurate and less ugly
+stmp-fixinc: gsyslimits.h macro_list fixinc_list \
+ $(build_objdir)/fixincludes/fixincl \
+ $(build_objdir)/fixincludes/fixinc.sh
+ rm -rf include-fixed; mkdir include-fixed
+ -chmod a+rx include-fixed
+ if [ -d ../prev-gcc ]; then \
+ cd ../prev-gcc && \
+ $(MAKE) real-$(INSTALL_HEADERS_DIR) DESTDIR=`pwd`/../sdcc/ \
+ libsubdir=. ; \
+ else \
+ 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}; \
+ if ! $(inhibit_libc) && test ! -d ${BUILD_SYSTEM_HEADER_DIR}; then \
+ echo The directory that should contain system headers does not exist: >&2 ; \
+ echo " ${BUILD_SYSTEM_HEADER_DIR}" >&2 ; \
+ tooldir_sysinc=`echo "${gcc_tooldir}/sys-include" | sed -e :a -e "s,[^/]*/\.\.\/,," -e ta`; \
+ if test "x${BUILD_SYSTEM_HEADER_DIR}" = "x$${tooldir_sysinc}"; \
+ then sleep 1; else exit 1; fi; \
+ fi; \
+ $(mkinstalldirs) $${fix_dir}; \
+ chmod a+rx $${fix_dir} || true; \
+ (TARGET_MACHINE='$(target)'; srcdir=`cd $(srcdir); ${PWD_COMMAND}`; \
+ SHELL='$(SHELL)'; MACRO_LIST=`${PWD_COMMAND}`/macro_list ; \
+ gcc_dir=`${PWD_COMMAND}` ; \
+ export TARGET_MACHINE srcdir SHELL MACRO_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
+#
+
+# Install with the gcc headers files, not the fixed include files, which we
+# are typically not allowed to distribute. The general idea is to:
+# - Get to "install" with a bare set of internal headers, not the
+# fixed system ones,
+# - Prevent rebuilds of what normally depends on the headers, which is
+# useless for installation purposes and would rely on improper headers.
+# - Restore as much of the original state as possible.
+
+.PHONY: install-no-fixedincludes
+
+install-no-fixedincludes:
+ # Stash the current set of headers away, save stamps we're going to
+ # alter explicitly, and arrange for fixincludes not to run next time
+ # we trigger a headers rebuild.
+ -rm -rf tmp-include
+ -mv include tmp-include 2>/dev/null
+ -mv include-fixed tmp-include-fixed 2>/dev/null
+ -mv stmp-int-hdrs tmp-stmp-int-hdrs 2>/dev/null
+ -mv stmp-fixinc tmp-stmp-fixinc 2>/dev/null
+ -mkdir include
+ -cp -p $(srcdir)/gsyslimits.h include/syslimits.h
+ -touch stmp-fixinc
+
+ # Rebuild our internal headers, restore the original stamps so that
+ # "install" doesn't trigger pointless rebuilds because of that update,
+ # then do install
+ $(MAKE) $(FLAGS_TO_PASS) stmp-int-hdrs
+ -mv tmp-stmp-int-hdrs stmp-int-hdrs 2>/dev/null
+ -mv tmp-stmp-fixinc stmp-fixinc 2>/dev/null
+ $(MAKE) $(FLAGS_TO_PASS) install
+
+ # Restore the original set of maybe-fixed headers
+ -rm -rf include; mv tmp-include include 2>/dev/null
+ -rm -rf include-fixed; mv tmp-include-fixed include-fixed 2>/dev/null
+
+# Remake the info files.
+
+doc: # $(BUILD_INFO) $(GENERATED_MANPAGES)
+
+INFOFILES = doc/cpp.info doc/gcc.info doc/gccint.info \
+ doc/gccinstall.info doc/cppinternals.info
+
+info: $(INFOFILES) lang.info @GENINSRC@ srcinfo lang.srcinfo
+
+srcinfo: $(INFOFILES)
+ -cp -p $^ $(srcdir)/doc
+
+TEXI_CPP_FILES_ = cpp.texi fdl.texi cppenv.texi cppopts.texi \
+ gcc-common.texi gcc-vers.texi
+
+TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi \
+ standards.texi invoke.texi extend.texi md.texi objc.texi \
+ gcov.texi trouble.texi bugreport.texi service.texi \
+ contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi \
+ fdl.texi contrib.texi cppenv.texi cppopts.texi avr-mmcu.texi \
+ implement-c.texi implement-cxx.texi gcov-tool.texi gcov-dump.texi \
+ lto-dump.texi
+
+# we explicitly use $(srcdir)/doc/tm.texi here to avoid confusion with
+# the generated tm.texi; the latter might have a more recent timestamp,
+# but we don't want to rebuild the info files unless the contents of
+# the *.texi files have changed.
+TEXI_GCCINT_FILES = gccint.texi gcc-common.texi gcc-vers.texi \
+ contribute.texi makefile.texi configterms.texi options.texi \
+ portability.texi interface.texi passes.texi rtl.texi md.texi \
+ $(srcdir)/doc/tm.texi hostconfig.texi fragments.texi \
+ configfiles.texi collect2.texi headerdirs.texi funding.texi \
+ gnu.texi gpl_v3.texi fdl.texi contrib.texi languages.texi \
+ sourcebuild.texi gty.texi libgcc.texi cfg.texi tree-ssa.texi \
+ loop.texi generic.texi gimple.texi plugins.texi optinfo.texi \
+ match-and-simplify.texi analyzer.texi ux.texi poly-int.texi
+
+TEXI_GCCINSTALL_FILES = install.texi fdl.texi \
+ gcc-common.texi gcc-vers.texi
+
+TEXI_CPPINT_FILES = cppinternals.texi gcc-common.texi gcc-vers.texi
+
+# gcc-vers.texi is generated from the version files.
+gcc-vers.texi: $(BASEVER) $(DEVPHASE)
+ (echo "@set version-GCC $(BASEVER_c)"; \
+ if [ "$(DEVPHASE_c)" = "experimental" ]; \
+ then echo "@set DEVELOPMENT"; \
+ else echo "@clear DEVELOPMENT"; \
+ fi) > $@T
+ $(build_file_translate) echo @set srcdir `echo $(abs_srcdir) | sed -e 's|\\([@{}]\\)|@\\1|g'` >> $@T
+ if [ -n "$(PKGVERSION)" ]; then \
+ echo "@set VERSION_PACKAGE $(PKGVERSION)" >> $@T; \
+ fi
+ echo "@set BUGURL $(BUGURL_TEXI)" >> $@T; \
+ mv -f $@T $@
+
+
+# The *.1, *.7, *.info, *.dvi, and *.pdf files are being generated from implicit
+# patterns. To use them, put each of the specific targets with its
+# specific dependencies but no build commands.
+
+doc/cpp.info: $(TEXI_CPP_FILES)
+doc/gcc.info: $(TEXI_GCC_FILES)
+doc/gccint.info: $(TEXI_GCCINT_FILES)
+doc/cppinternals.info: $(TEXI_CPPINT_FILES)
+
+doc/%.info: %.texi
+ if [ x$(BUILD_INFO) = xinfo ]; then \
+ $(MAKEINFO) $(MAKEINFOFLAGS) -I . -I $(gcc_docdir) \
+ -I $(gcc_docdir)/include -o $@ $<; \
+ fi
+
+# Duplicate entry to handle renaming of gccinstall.info
+doc/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
+ if [ x$(BUILD_INFO) = xinfo ]; then \
+ $(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
+ -I $(gcc_docdir)/include -o $@ $<; \
+ fi
+
+doc/cpp.dvi: $(TEXI_CPP_FILES)
+doc/gcc.dvi: $(TEXI_GCC_FILES)
+doc/gccint.dvi: $(TEXI_GCCINT_FILES)
+doc/cppinternals.dvi: $(TEXI_CPPINT_FILES)
+
+doc/cpp.pdf: $(TEXI_CPP_FILES)
+doc/gcc.pdf: $(TEXI_GCC_FILES)
+doc/gccint.pdf: $(TEXI_GCCINT_FILES)
+doc/cppinternals.pdf: $(TEXI_CPPINT_FILES)
+
+$(build_htmldir)/cpp/index.html: $(TEXI_CPP_FILES)
+$(build_htmldir)/gcc/index.html: $(TEXI_GCC_FILES)
+$(build_htmldir)/gccint/index.html: $(TEXI_GCCINT_FILES)
+$(build_htmldir)/cppinternals/index.html: $(TEXI_CPPINT_FILES)
+
+DVIFILES = doc/gcc.dvi doc/gccint.dvi doc/gccinstall.dvi doc/cpp.dvi \
+ doc/cppinternals.dvi
+
+dvi:: $(DVIFILES) lang.dvi
+
+doc/%.dvi: %.texi
+ $(TEXI2DVI) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+# Duplicate entry to handle renaming of gccinstall.dvi
+doc/gccinstall.dvi: $(TEXI_GCCINSTALL_FILES)
+ $(TEXI2DVI) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+PDFFILES = doc/gcc.pdf doc/gccint.pdf doc/gccinstall.pdf doc/cpp.pdf \
+ doc/cppinternals.pdf
+
+pdf:: $(PDFFILES) lang.pdf
+
+doc/%.pdf: %.texi
+ $(TEXI2PDF) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+# Duplicate entry to handle renaming of gccinstall.pdf
+doc/gccinstall.pdf: $(TEXI_GCCINSTALL_FILES)
+ $(TEXI2PDF) -I . -I $(abs_docdir) -I $(abs_docdir)/include -o $@ $<
+
+# List the directories or single hmtl files which are installed by
+# install-html. The lang.html file triggers language fragments to build
+# html documentation.
+HTMLS_INSTALL=$(build_htmldir)/cpp $(build_htmldir)/gcc \
+ $(build_htmldir)/gccinstall $(build_htmldir)/gccint \
+ $(build_htmldir)/cppinternals
+
+# List the html file targets.
+HTMLS_BUILD=$(build_htmldir)/cpp/index.html $(build_htmldir)/gcc/index.html \
+ $(build_htmldir)/gccinstall/index.html $(build_htmldir)/gccint/index.html \
+ $(build_htmldir)/cppinternals/index.html lang.html
+
+html:: $(HTMLS_BUILD)
+
+$(build_htmldir)/%/index.html: %.texi
+ $(mkinstalldirs) $(@D)
+ rm -f $(@D)/*
+ $(TEXI2HTML) -I $(abs_docdir) -I $(abs_docdir)/include -o $(@D) $<
+
+# Duplicate entry to handle renaming of gccinstall
+$(build_htmldir)/gccinstall/index.html: $(TEXI_GCCINSTALL_FILES)
+ $(mkinstalldirs) $(@D)
+ echo rm -f $(@D)/*
+ SOURCEDIR=$(abs_docdir) \
+ DESTDIR=$(@D) \
+ $(SHELL) $(srcdir)/doc/install.texi2html
+
+MANFILES = doc/gcov.1 doc/cpp.1 doc/gcc.1 doc/gfdl.7 doc/gpl.7 \
+ doc/fsf-funding.7 doc/gcov-tool.1 doc/gcov-dump.1 \
+ $(if $(filter yes,@enable_lto@),doc/lto-dump.1)
+
+generated-manpages: man
+
+man: $(MANFILES) lang.man @GENINSRC@ srcman lang.srcman
+
+srcman: $(MANFILES)
+ -cp -p $^ $(srcdir)/doc
+
+doc/%.1: %.pod
+ $(STAMP) $@
+ -($(POD2MAN) --section=1 $< > $(@).T$$$$ && \
+ mv -f $(@).T$$$$ $@) || \
+ (rm -f $(@).T$$$$ && exit 1)
+
+doc/%.7: %.pod
+ $(STAMP) $@
+ -($(POD2MAN) --section=7 $< > $(@).T$$$$ && \
+ mv -f $(@).T$$$$ $@) || \
+ (rm -f $(@).T$$$$ && exit 1)
+
+%.pod: %.texi
+ $(STAMP) $@
+ -$(TEXI2POD) -DBUGURL="$(BUGURL_TEXI)" $< > $@
+
+.INTERMEDIATE: # cpp.pod gcc.pod gfdl.pod fsf-funding.pod gpl.pod
+cpp.pod: cpp.texi cppenv.texi cppopts.texi
+
+# These next rules exist because the output name is not the same as
+# the input name, so our implicit %.pod rule will not work.
+
+gcc.pod: invoke.texi cppenv.texi cppopts.texi gcc-vers.texi
+ $(STAMP) $@
+ -$(TEXI2POD) $< > $@
+gfdl.pod: fdl.texi
+ $(STAMP) $@
+ -$(TEXI2POD) $< > $@
+fsf-funding.pod: funding.texi
+ $(STAMP) $@
+ -$(TEXI2POD) $< > $@
+gpl.pod: gpl_v3.texi
+ $(STAMP) $@
+ -$(TEXI2POD) $< > $@
+
+#
+# Deletion of files made during compilation.
+# There are four levels of this:
+# `mostlyclean', `clean', `distclean' and `maintainer-clean'.
+# `mostlyclean' is useful while working on a particular type of machine.
+# It deletes most, but not all, of the files made by compilation.
+# It does not delete libgcc.a or its parts, so it won't have to be recompiled.
+# `clean' deletes everything made by running `make all'.
+# `distclean' also deletes the files made by config.
+# `maintainer-clean' also deletes everything that could be regenerated
+# automatically, except for `configure'.
+# We remove as much from the language subdirectories as we can
+# (less duplicated code).
+
+mostlyclean: lang.mostlyclean
+ -rm -f $(MOSTLYCLEANFILES)
+ -rm -f *$(objext) c-family/*$(objext)
+ -rm -f *$(coverageexts)
+# Delete build programs
+ -rm -f build/*
+ -rm -f mddeps.mk
+# Delete other built files.
+ -rm -f specs.h options.cc options.h options-save.cc
+# Delete the stamp and temporary files.
+ -rm -f s-* tmp-* stamp-* stmp-*
+ -rm -f */stamp-* */tmp-*
+# Delete debugging dump files.
+ -rm -f *.[0-9][0-9].* */*.[0-9][0-9].*
+# Delete some files made during installation.
+ -rm -f specs $(SPECS)
+ -rm -f collect collect2 mips-tfile mips-tdump
+# Delete unwanted output files from TeX.
+ -rm -f *.toc *.log *.vr *.fn *.cp *.tp *.ky *.pg
+ -rm -f */*.toc */*.log */*.vr */*.fn */*.cp */*.tp */*.ky */*.pg
+# Delete sorted indices we don't actually use.
+ -rm -f gcc.vrs gcc.kys gcc.tps gcc.pgs gcc.fns
+# Delete core dumps.
+ -rm -f core */core
+# Delete file generated for gengtype
+ -rm -f gtyp-input.list
+# Delete files generated by gengtype
+ -rm -f gtype-*
+ -rm -f gt-*
+ -rm -f gtype.state
+# Delete genchecksum outputs
+ -rm -f *-checksum.cc
+# Delete lock-and-run bits
+ -rm -rf linkfe.lck lock-stamp.*
+
+# Delete all files made by compilation
+# that don't exist in the distribution.
+clean: mostlyclean lang.clean
+ -rm -f libgcc.a libgcc_eh.a libgcov.a
+ -rm -f common/common-targhooks.o
+ -rm -f libgcc_s*
+ -rm -f libunwind*
+ -rm -f config.h tconfig.h bconfig.h tm_p.h tm.h
+ -rm -f options.cc options.h optionlist
+ -rm -f cs-*
+ -rm -f doc/*.dvi
+ -rm -f doc/*.pdf
+# Delete the include directories.
+ -rm -rf include include-fixed
+# Delete files used by the "multilib" facility (including libgcc subdirs).
+ -rm -f multilib.h tmpmultilib*
+ -if [ "x$(MULTILIB_DIRNAMES)" != x ] ; then \
+ rm -rf $(MULTILIB_DIRNAMES); \
+ else if [ "x$(MULTILIB_OPTIONS)" != x ] ; then \
+ rm -rf `echo $(MULTILIB_OPTIONS) | sed -e 's/\// /g'`; \
+ fi ; fi
+
+# Delete all files that users would normally create
+# while building and installing GCC.
+distclean: clean lang.distclean
+ -rm -f auto-host.h auto-build.h
+ -rm -f cstamp-h
+ -rm -f config.status config.run config.cache config.bak
+ -rm -f Make-lang Make-hooks Make-host Make-target
+ -rm -f Makefile *.oaux
+ -rm -f gthr-default.h
+ -rm -f TAGS */TAGS
+ -rm -f *.asm
+ -rm -f site.exp site.bak testsuite/site.exp testsuite/site.bak
+ -rm -f testsuite/*.log testsuite/*.sum
+ -cd testsuite && rm -f x *.x *.x? *.exe *.rpo *.o *.s *.S *.cc
+ -cd testsuite && rm -f *.out *.gcov *$(coverageexts)
+ -rm -rf ${QMTEST_DIR} stamp-qmtest
+ -rm -f .gdbinit configargs.h
+ -rm -f gcov.pod
+# Delete po/*.gmo only if we are not building in the source directory.
+ -if [ ! -f po/exgettext ]; then rm -f po/*.gmo; fi
+ -rmdir ada cp f java objc intl po testsuite plugin 2>/dev/null
+
+# Get rid of every file that's generated from some other file, except for `configure'.
+# Most of these files ARE PRESENT in the GCC distribution.
+maintainer-clean:
+ @echo 'This command is intended for maintainers to use; it'
+ @echo 'deletes files that may need special tools to rebuild.'
+ $(MAKE) lang.maintainer-clean distclean
+ -rm -f cpp.??s cpp.*aux
+ -rm -f gcc.??s gcc.*aux
+ -rm -f $(gcc_docdir)/*.info $(gcc_docdir)/*.1 $(gcc_docdir)/*.7 $(gcc_docdir)/*.dvi $(gcc_docdir)/*.pdf
+#
+# Entry points `install', `install-strip', and `uninstall'.
+# Also use `install-collect2' to install collect2 when the config files don't.
+
+# Copy the compiler files into directories where they will be run.
+# Install the driver last so that the window when things are
+# broken is small.
+install: install-common $(INSTALL_HEADERS) \
+ install-cpp # install-man install-info install-@POSUB@ \
+ install-driver install-lto-wrapper install-gcc-ar
+
+ifeq ($(enable_plugin),yes)
+install: install-plugin
+endif
+
+install-strip: override INSTALL_PROGRAM = $(INSTALL_STRIP_PROGRAM)
+ifneq ($(STRIP),)
+install-strip: STRIPPROG = $(STRIP)
+export STRIPPROG
+endif
+install-strip: install
+
+# Handle cpp installation. adopted for sdcpp
+install-cpp: installdirs cpp$(exeext)
+ -if test "$(enable_as_accelerator)" != "yes" ; then \
+ rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext); \
+ if [ x$(cpp_install_dir) != x ]; then \
+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) -m 755 cpp$(exeext) $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
+ else true; fi; \
+ fi
+
+# Create the installation directories.
+# $(libdir)/gcc/include isn't currently searched by cpp.
+installdirs:
+ # $(mkinstalldirs) $(DESTDIR)$(libsubdir)
+ $(mkinstalldirs) $(DESTDIR)$(libexecsubdir)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+
+more_installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(includedir)
+ $(mkinstalldirs) $(DESTDIR)$(infodir)
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ $(mkinstalldirs) $(DESTDIR)$(man7dir)
+
+PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(HASH_TABLE_H) \
+ tree-ssa-alias.h $(INTERNAL_FN_H) gimple-fold.h tree-eh.h gimple-expr.h \
+ gimple.h is-a.h memmodel.h $(TREE_PASS_H) $(GCC_PLUGIN_H) \
+ $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) $(OPTS_H) $(PARAMS_H) \
+ $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \
+ $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \
+ intl.h $(PLUGIN_VERSION_H) $(DIAGNOSTIC_H) ${C_TREE_H} \
+ $(C_COMMON_H) c-family/c-objc.h $(C_PRETTY_PRINT_H) \
+ tree-iterator.h $(PLUGIN_H) $(TREE_SSA_H) langhooks.h incpath.h debug.h \
+ $(EXCEPT_H) tree-ssa-sccvn.h real.h output.h $(IPA_UTILS_H) \
+ ipa-param-manipulation.h $(C_PRAGMA_H) $(CPPLIB_H) $(FUNCTION_H) \
+ cppdefault.h flags.h $(MD5_H) params.def params.h params-enum.h \
+ prefix.h tree-inline.h $(GIMPLE_PRETTY_PRINT_H) realmpfr.h \
+ $(IPA_PROP_H) $(TARGET_H) $(RTL_H) $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) \
+ version.h stringpool.h gimplify.h gimple-iterator.h gimple-ssa.h \
+ fold-const.h fold-const-call.h tree-cfg.h tree-into-ssa.h tree-ssanames.h \
+ print-tree.h varasm.h context.h tree-phinodes.h stor-layout.h \
+ ssa-iterators.h $(RESOURCE_H) tree-cfgcleanup.h attribs.h calls.h \
+ cfgexpand.h diagnostic-color.h gcc-symtab.h gimple-builder.h gimple-low.h \
+ gimple-walk.h gimplify-me.h pass_manager.h print-rtl.h stmt.h \
+ tree-dfa.h tree-hasher.h tree-nested.h tree-object-size.h tree-outof-ssa.h \
+ tree-parloops.h tree-ssa-address.h tree-ssa-coalesce.h tree-ssa-dom.h \
+ tree-ssa-loop.h tree-ssa-loop-ivopts.h tree-ssa-loop-manip.h \
+ tree-ssa-loop-niter.h tree-ssa-ter.h tree-ssa-threadedge.h \
+ tree-ssa-threadupdate.h inchash.h wide-int.h signop.h hash-map.h \
+ hash-set.h dominance.h cfg.h cfgrtl.h cfganal.h cfgbuild.h cfgcleanup.h \
+ lcm.h cfgloopmanip.h file-prefix-map.h builtins.def $(INSN_ATTR_H) \
+ pass-instances.def params.list $(srcdir)/../include/gomp-constants.h \
+ $(EXPR_H)
+
+# generate the 'build fragment' b-header-vars
+s-header-vars: Makefile
+ rm -f tmp-header-vars
+# The first sed gets the list "header variables" as the list variables
+# assigned in Makefile and having _H at the end of the name. "sed -n" proved
+# more portable than a trailing "-e d" to filter out the uninteresting lines,
+# in particular on ia64-hpux where "s/.../p" only prints if -n was requested
+# as well.
+ $(foreach header_var,$(shell sed < Makefile -n -e 's/^\([A-Z0-9_]*_H\)[ ]*=.*/\1/p'),echo $(header_var)=$(shell echo $($(header_var):$(srcdir)/%=.../%) | sed -e 's~\.\.\./config/~config/~' -e 's~\.\.\./common/config/~common/config/~' -e 's~\.\.\.[^ ]*/~~g') >> tmp-header-vars;)
+ $(SHELL) $(srcdir)/../move-if-change tmp-header-vars b-header-vars
+ $(STAMP) s-header-vars
+
+# Install gengtype
+install-gengtype: installdirs gengtype$(exeext) gtype.state
+ $(mkinstalldirs) $(DESTDIR)$(plugin_resourcesdir)
+ $(INSTALL_DATA) gtype.state $(DESTDIR)$(plugin_resourcesdir)/gtype.state
+ $(mkinstalldirs) $(DESTDIR)$(plugin_bindir)
+ $(INSTALL_PROGRAM) gengtype$(exeext) $(DESTDIR)$(plugin_bindir)/gengtype$(exeext)
+
+# Install the headers needed to build a plugin.
+install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype
+# We keep the directory structure for files in config, common/config or
+# c-family and .def files. All other files are flattened to a single directory.
+ $(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
+ headers=`echo $(sort $(PLUGIN_HEADERS)) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`; \
+ for file in $$headers; do \
+ if [ -f $$file ] ; then \
+ path=$$file; \
+ elif [ -f $(srcdir)/$$file ]; then \
+ path=$(srcdir)/$$file; \
+ else continue; \
+ fi; \
+ case $$path in \
+ "$(srcdir)"/config/* | "$(srcdir)"/common/config/* \
+ | "$(srcdir)"/c-family/* | "$(srcdir)"/*.def ) \
+ base=`echo "$$path" | sed -e "s|$$srcdirstrip/||"`;; \
+ *) base=`basename $$path` ;; \
+ esac; \
+ dest=$(plugin_includedir)/$$base; \
+ echo $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
+ dir=`dirname $$dest`; \
+ $(mkinstalldirs) $(DESTDIR)$$dir; \
+ $(INSTALL_DATA) $$path $(DESTDIR)$$dest; \
+ done
+ $(INSTALL_DATA) b-header-vars $(DESTDIR)$(plugin_includedir)/b-header-vars
+
+# Install the compiler executables built during cross compilation.
+install-common: native lang.install-common installdirs
+ for file in $(COMPILERS); do \
+ if [ -f $$file ] ; then \
+ rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
+ $(INSTALL_PROGRAM) $$file $(DESTDIR)$(libexecsubdir)/$$file; \
+ else true; \
+ fi; \
+ done
+ for file in $(EXTRA_PROGRAMS) $(COLLECT2) ..; do \
+ if [ x"$$file" != x.. ]; then \
+ rm -f $(DESTDIR)$(libexecsubdir)/$$file; \
+ $(INSTALL_PROGRAM) $$file $(DESTDIR)$(libexecsubdir)/$$file; \
+ else true; fi; \
+ done
+# We no longer install the specs file because its presence makes the
+# driver slower, and because people who need it can recreate it by
+# using -dumpspecs. We remove any old version because it would
+# otherwise override the specs built into the driver.
+ rm -f $(DESTDIR)$(libsubdir)/specs
+# Install gcov if it was compiled.
+ -if test "$(enable_as_accelerator)" != "yes" ; then \
+ if [ -f gcov$(exeext) ]; \
+ then \
+ rm -f $(DESTDIR)$(bindir)/$(GCOV_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) gcov$(exeext) $(DESTDIR)$(bindir)/$(GCOV_INSTALL_NAME)$(exeext); \
+ fi; \
+ fi
+# Install gcov-tool if it was compiled.
+ -if test "$(enable_as_accelerator)" != "yes" ; then \
+ if [ -f gcov-tool$(exeext) ]; \
+ then \
+ rm -f $(DESTDIR)$(bindir)/$(GCOV_TOOL_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) \
+ gcov-tool$(exeext) $(DESTDIR)$(bindir)/$(GCOV_TOOL_INSTALL_NAME)$(exeext); \
+ fi; \
+ fi
+# Install gcov-dump if it was compiled.
+ -if test "$(enable_as_accelerator)" != "yes" ; then \
+ if [ -f gcov-dump$(exeext) ]; \
+ then \
+ rm -f $(DESTDIR)$(bindir)/$(GCOV_DUMP_INSTALL_NAME)$(exeext); \
+ $(INSTALL_PROGRAM) \
+ gcov-dump$(exeext) $(DESTDIR)$(bindir)/$(GCOV_DUMP_INSTALL_NAME)$(exeext); \
+ fi; \
+ fi
+
+# Install the driver program as $(target_noncanonical)-gcc,
+# $(target_noncanonical)-gcc-$(version), and also as gcc if native.
+install-driver: installdirs xgcc$(exeext)
+ -rm -f $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
+ -$(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
+ -if test "$(enable_as_accelerator)" != "yes" ; then \
+ if [ "$(GCC_INSTALL_NAME)" != "$(target_noncanonical)-gcc-$(version)" ]; then \
+ rm -f $(DESTDIR)$(bindir)/$(FULL_DRIVER_NAME); \
+ ( cd $(DESTDIR)$(bindir) && \
+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(FULL_DRIVER_NAME) ); \
+ fi; \
+ if [ ! -f gcc-cross$(exeext) ] \
+ && [ "$(GCC_INSTALL_NAME)" != "$(GCC_TARGET_INSTALL_NAME)" ]; then \
+ rm -f $(DESTDIR)$(bindir)/$(target_noncanonical)-gcc-tmp$(exeext); \
+ ( cd $(DESTDIR)$(bindir) && \
+ $(LN) $(GCC_INSTALL_NAME)$(exeext) $(target_noncanonical)-gcc-tmp$(exeext) && \
+ mv -f $(target_noncanonical)-gcc-tmp$(exeext) $(GCC_TARGET_INSTALL_NAME)$(exeext) ); \
+ fi; \
+ fi
+
+# Install the info files.
+# $(INSTALL_DATA) might be a relative pathname, so we can't cd into srcdir
+# to do the install.
+install-info:: # doc installdirs \
+ $(DESTDIR)$(infodir)/cpp.info \
+ $(DESTDIR)$(infodir)/gcc.info \
+ $(DESTDIR)$(infodir)/cppinternals.info \
+ $(DESTDIR)$(infodir)/gccinstall.info \
+ $(DESTDIR)$(infodir)/gccint.info \
+ lang.install-info
+
+$(DESTDIR)$(infodir)/%.info: doc/%.info installdirs
+ rm -f $@
+ if [ -f $< ]; then \
+ for f in $(<)*; do \
+ realfile=`echo $$f | sed -e 's|.*/\([^/]*\)$$|\1|'`; \
+ $(INSTALL_DATA) $$f $(DESTDIR)$(infodir)/$$realfile; \
+ chmod a-x $(DESTDIR)$(infodir)/$$realfile; \
+ done; \
+ else true; fi
+ -if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \
+ if [ -f $@ ]; then \
+ install-info --dir-file=$(DESTDIR)$(infodir)/dir $@; \
+ else true; fi; \
+ else true; fi;
+
+dvi__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+
+install-dvi: $(DVIFILES) lang.install-dvi
+ @$(NORMAL_INSTALL)
+ test -z "$(dvidir)/gcc" || $(mkinstalldirs) "$(DESTDIR)$(dvidir)/gcc"
+ @list='$(DVIFILES)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(dvi__strip_dir) \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(dvidir)/gcc/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(dvidir)/gcc/$$f"; \
+ done
+
+pdf__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+
+install-pdf: $(PDFFILES) lang.install-pdf
+ @$(NORMAL_INSTALL)
+ test -z "$(pdfdir)/gcc" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)/gcc"
+ @list='$(PDFFILES)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(pdf__strip_dir) \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/gcc/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/gcc/$$f"; \
+ done
+
+html__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+
+install-html: $(HTMLS_BUILD) lang.install-html
+ @$(NORMAL_INSTALL)
+ test -z "$(htmldir)" || $(mkinstalldirs) "$(DESTDIR)$(htmldir)"
+ @list='$(HTMLS_INSTALL)'; for p in $$list; do \
+ if test -f "$$p" || test -d "$$p"; then d=""; else d="$(srcdir)/"; fi; \
+ f=$(html__strip_dir) \
+ if test -d "$$d$$p"; then \
+ echo " $(mkinstalldirs) '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(mkinstalldirs) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \
+ echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \
+ else \
+ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \
+ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \
+ fi; \
+ done
+
+# Install the man pages.
+install-man: # lang.install-man \
+ $(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext) \
+ $(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext) \
+ $(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext) \
+ $(DESTDIR)$(man1dir)/$(GCOV_TOOL_INSTALL_NAME)$(man1ext) \
+ $(DESTDIR)$(man1dir)/$(GCOV_DUMP_INSTALL_NAME)$(man1ext) \
+ $(if $(filter yes,@enable_lto@),$(DESTDIR)$(man1dir)/$(LTO_DUMP_INSTALL_NAME)$(man1ext)) \
+ $(DESTDIR)$(man7dir)/fsf-funding$(man7ext) \
+ $(DESTDIR)$(man7dir)/gfdl$(man7ext) \
+ $(DESTDIR)$(man7dir)/gpl$(man7ext)
+
+$(DESTDIR)$(man7dir)/%$(man7ext): doc/%.7 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+$(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext): doc/gcc.1 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+$(DESTDIR)$(man1dir)/$(CPP_INSTALL_NAME)$(man1ext): doc/cpp.1 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+$(DESTDIR)$(man1dir)/$(GCOV_INSTALL_NAME)$(man1ext): doc/gcov.1 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+$(DESTDIR)$(man1dir)/$(GCOV_TOOL_INSTALL_NAME)$(man1ext): doc/gcov-tool.1 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+$(DESTDIR)$(man1dir)/$(GCOV_DUMP_INSTALL_NAME)$(man1ext): doc/gcov-dump.1 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+$(DESTDIR)$(man1dir)/$(LTO_DUMP_INSTALL_NAME)$(man1ext): doc/lto-dump.1 installdirs
+ -rm -f $@
+ -$(INSTALL_DATA) $< $@
+ -chmod a-x $@
+
+# Install all the header files built in the include subdirectory.
+install-headers: $(INSTALL_HEADERS_DIR)
+# Fix symlinks to absolute paths in the installed include directory to
+# point to the installed directory, not the build directory.
+# Don't need to use LN_S here since we really do need ln -s and no substitutes.
+ -files=`cd $(DESTDIR)$(libsubdir)/include-fixed; find . -type l -print 2>/dev/null`; \
+ if [ $$? -eq 0 ]; then \
+ dir=`cd include-fixed; ${PWD_COMMAND}`; \
+ for i in $$files; do \
+ dest=`ls -ld $(DESTDIR)$(libsubdir)/include-fixed/$$i | sed -n 's/.*-> //p'`; \
+ if expr "$$dest" : "$$dir.*" > /dev/null; then \
+ rm -f $(DESTDIR)$(libsubdir)/include-fixed/$$i; \
+ ln -s `echo $$i | sed "s|/[^/]*|/..|g" | sed 's|/..$$||'``echo "$$dest" | sed "s|$$dir||"` $(DESTDIR)$(libsubdir)/include-fixed/$$i; \
+ fi; \
+ done; \
+ fi
+
+# Create or recreate the gcc private include file directory.
+install-include-dir: installdirs
+ $(mkinstalldirs) $(DESTDIR)$(libsubdir)/include
+ -rm -rf $(DESTDIR)$(libsubdir)/include-fixed
+ mkdir $(DESTDIR)$(libsubdir)/include-fixed
+ -chmod a+rx $(DESTDIR)$(libsubdir)/include-fixed
+
+# Create or recreate the install-tools include file directory.
+itoolsdir = $(libexecsubdir)/install-tools
+itoolsdatadir = $(libsubdir)/install-tools
+install-itoolsdirs: installdirs
+ $(mkinstalldirs) $(DESTDIR)$(itoolsdatadir)/include
+ $(mkinstalldirs) $(DESTDIR)$(itoolsdir)
+
+# Install the include directory using tar.
+install-headers-tar: # stmp-int-hdrs install-include-dir
+# We use `pwd`/include instead of just include to problems with CDPATH
+# Unless a full pathname is provided, some shells would print the new CWD,
+# found in CDPATH, corrupting the output. We could just redirect the
+# output of `cd', but some shells lose on redirection within `()'s
+ (cd `${PWD_COMMAND}`/include ; \
+ tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include; tar xpf - )
+ (cd `${PWD_COMMAND}`/include-fixed ; \
+ tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include-fixed; tar xpf - )
+# /bin/sh on some systems returns the status of the first tar,
+# and that can lose with GNU tar which always writes a full block.
+# So use `exit 0' to ignore its exit status.
+
+# Install the include directory using cpio.
+install-headers-cpio: # stmp-int-hdrs install-include-dir
+# See discussion about the use of `pwd` above
+ cd `${PWD_COMMAND}`/include ; \
+ find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include
+ cd `${PWD_COMMAND}`/include-fixed ; \
+ find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include-fixed
+
+# Install the include directory using cp.
+install-headers-cp: # stmp-int-hdrs install-include-dir
+ cp -p -r include $(DESTDIR)$(libsubdir)
+ cp -p -r include-fixed $(DESTDIR)$(libsubdir)
+
+# Targets without dependencies, for use in prev-gcc during bootstrap.
+real-install-headers-tar:
+ (cd `${PWD_COMMAND}`/include-fixed ; \
+ tar -cf - .; exit 0) | (cd $(DESTDIR)$(libsubdir)/include-fixed; tar xpf - )
+
+real-install-headers-cpio:
+ cd `${PWD_COMMAND}`/include-fixed ; \
+ find . -print | cpio -pdum $(DESTDIR)$(libsubdir)/include-fixed
+
+real-install-headers-cp:
+ cp -p -r include-fixed $(DESTDIR)$(libsubdir)
+
+# Install supporting files for fixincludes to be run later.
+install-mkheaders: # stmp-int-hdrs install-itoolsdirs \
+ macro_list fixinc_list
+ $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
+ $(DESTDIR)$(itoolsdatadir)/gsyslimits.h
+ $(INSTALL_DATA) macro_list $(DESTDIR)$(itoolsdatadir)/macro_list
+ $(INSTALL_DATA) fixinc_list $(DESTDIR)$(itoolsdatadir)/fixinc_list
+ 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; \
+ done
+ $(INSTALL_SCRIPT) $(srcdir)/../mkinstalldirs \
+ $(DESTDIR)$(itoolsdir)/mkinstalldirs ; \
+ sysroot_headers_suffix='$${sysroot_headers_suffix}'; \
+ echo 'SYSTEM_HEADER_DIR="'"$(SYSTEM_HEADER_DIR)"'"' \
+ > $(DESTDIR)$(itoolsdatadir)/mkheaders.conf
+ echo 'OTHER_FIXINCLUDES_DIRS="$(OTHER_FIXINCLUDES_DIRS)"' \
+ >> $(DESTDIR)$(itoolsdatadir)/mkheaders.conf
+ echo 'STMP_FIXINC="$(STMP_FIXINC)"' \
+ >> $(DESTDIR)$(itoolsdatadir)/mkheaders.conf
+
+# Use this target to install the program `collect2' under the name `collect2'.
+install-collect2: collect2 installdirs
+ $(INSTALL_PROGRAM) collect2$(exeext) $(DESTDIR)$(libexecsubdir)/collect2$(exeext)
+# Install the driver program as $(libsubdir)/gcc for collect2.
+ $(INSTALL_PROGRAM) xgcc$(exeext) $(DESTDIR)$(libexecsubdir)/gcc$(exeext)
+
+# Install lto-wrapper.
+install-lto-wrapper: lto-wrapper$(exeext)
+ $(INSTALL_PROGRAM) lto-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext)
+
+install-gcc-ar: installdirs gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
+ if test "$(enable_as_accelerator)" != "yes" ; then \
+ for i in gcc-ar gcc-nm gcc-ranlib; do \
+ install_name=`echo $$i|sed '$(program_transform_name)'` ;\
+ target_install_name=$(target_noncanonical)-`echo $$i|sed '$(program_transform_name)'` ; \
+ rm -f $(DESTDIR)$(bindir)/$$install_name$(exeext) ; \
+ $(INSTALL_PROGRAM) $$i$(exeext) $(DESTDIR)$(bindir)/$$install_name$(exeext) ;\
+ if test -f gcc-cross$(exeext); then \
+ :; \
+ else \
+ rm -f $(DESTDIR)$(bindir)/$$target_install_name$(exeext); \
+ ( cd $(DESTDIR)$(bindir) && \
+ $(LN) $$install_name$(exeext) $$target_install_name$(exeext) ) ; \
+ fi ; \
+ done; \
+ fi
+
+# Cancel installation by deleting the installed files.
+uninstall: lang.uninstall
+ -rm -rf $(DESTDIR)$(libsubdir)
+ -rm -rf $(DESTDIR)$(libexecsubdir)
+ -rm -rf $(DESTDIR)$(bindir)/$(GCC_INSTALL_NAME)$(exeext)
+ -rm -f $(DESTDIR)$(bindir)/$(CPP_INSTALL_NAME)$(exeext)
+ -if [ x$(cpp_install_dir) != x ]; then \
+ rm -f $(DESTDIR)$(prefix)/$(cpp_install_dir)/$(CPP_INSTALL_NAME)$(exeext); \
+ else true; fi
+ -rm -rf $(DESTDIR)$(bindir)/$(GCOV_INSTALL_NAME)$(exeext)
+ -rm -rf $(DESTDIR)$(man1dir)/$(GCC_INSTALL_NAME)$(man1ext)
+ -rm -rf $(DESTDIR)$(man1dir)/cpp$(man1ext)
+ -rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
+ -rm -f $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
+ for i in ar nm ranlib ; do \
+ install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
+ target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
+ rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+ rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+ done
+#
+# These targets are for the dejagnu testsuites. The file site.exp
+# contains global variables that all the testsuites will use.
+
+target_subdir = @target_subdir@
+
+site.exp: ./config.status Makefile
+ @echo "Making a new config file..."
+ -@rm -f ./site.tmp
+ @$(STAMP) site.exp
+ -@mv site.exp site.bak
+ @echo "## these variables are automatically generated by make ##" > ./site.tmp
+ @echo "# Do not edit here. If you wish to override these values" >> ./site.tmp
+ @echo "# add them to the last section" >> ./site.tmp
+ @echo "set rootme \"`${PWD_COMMAND}`\"" >> ./site.tmp
+ @echo "set srcdir \"`cd ${srcdir}; ${PWD_COMMAND}`\"" >> ./site.tmp
+ @echo "set host_triplet $(host)" >> ./site.tmp
+ @echo "set build_triplet $(build)" >> ./site.tmp
+ @echo "set target_triplet $(target)" >> ./site.tmp
+ @echo "set target_alias $(target_noncanonical)" >> ./site.tmp
+ @echo "set libiconv \"$(LIBICONV)\"" >> ./site.tmp
+# CFLAGS is set even though it's empty to show we reserve the right to set it.
+ @echo "set CFLAGS \"\"" >> ./site.tmp
+ @echo "set CXXFLAGS \"\"" >> ./site.tmp
+ @echo "set HOSTCC \"$(CC)\"" >> ./site.tmp
+ @echo "set HOSTCXX \"$(CXX)\"" >> ./site.tmp
+ @echo "set HOSTCFLAGS \"$(CFLAGS)\"" >> ./site.tmp
+ @echo "set HOSTCXXFLAGS \"$(CXXFLAGS)\"" >> ./site.tmp
+# TEST_ALWAYS_FLAGS are flags that should be passed to every compilation.
+# They are passed first to allow individual tests to override them.
+ @echo "set TEST_ALWAYS_FLAGS \"$(SYSROOT_CFLAGS_FOR_TARGET)\"" >> ./site.tmp
+# When running the tests we set GCC_EXEC_PREFIX to the install tree so that
+# files that have already been installed there will be found. The -B option
+# overrides it, so use of GCC_EXEC_PREFIX will not result in using GCC files
+# from the install tree.
+ @echo "set TEST_GCC_EXEC_PREFIX \"$(libdir)/sdcc/\"" >> ./site.tmp
+ @echo "set TESTING_IN_BUILD_TREE 1" >> ./site.tmp
+ @echo "set HAVE_LIBSTDCXX_V3 1" >> ./site.tmp
+ @if test "@enable_plugin@" = "yes" ; then \
+ echo "set ENABLE_PLUGIN 1" >> ./site.tmp; \
+ echo "set PLUGINCC \"$(PLUGINCC)\"" >> ./site.tmp; \
+ echo "set PLUGINCFLAGS \"$(PLUGINCFLAGS)\"" >> ./site.tmp; \
+ echo "set GMPINC \"$(GMPINC)\"" >> ./site.tmp; \
+ fi
+# If newlib has been configured, we need to pass -B to gcc so it can find
+# newlib's crt0.o if it exists. This will cause a "path prefix not used"
+# message if it doesn't, but the testsuite is supposed to ignore the message -
+# it's too difficult to tell when to and when not to pass -B (not all targets
+# have crt0's). We could only add the -B if ../newlib/crt0.o exists, but that
+# seems like too selective a test.
+# ??? Another way to solve this might be to rely on linker scripts. Then
+# theoretically the -B won't be needed.
+# We also need to pass -L ../ld so that the linker can find ldscripts.
+ @if [ -d $(objdir)/../$(target_subdir)/newlib ] \
+ && [ "${host}" != "${target}" ]; then \
+ echo "set newlib_cflags \"-I$(objdir)/../$(target_subdir)/newlib/targ-include -I\$$srcdir/../newlib/libc/include\"" >> ./site.tmp; \
+ echo "set newlib_ldflags \"-B$(objdir)/../$(target_subdir)/newlib/\"" >> ./site.tmp; \
+ echo "append CFLAGS \" \$$newlib_cflags\"" >> ./site.tmp; \
+ echo "append CXXFLAGS \" \$$newlib_cflags\"" >> ./site.tmp; \
+ echo "append LDFLAGS \" \$$newlib_ldflags\"" >> ./site.tmp; \
+ else true; \
+ fi
+ @if [ -d $(objdir)/../ld ] ; then \
+ echo "append LDFLAGS \" -L$(objdir)/../ld\"" >> ./site.tmp; \
+ else true; \
+ fi
+ echo "set tmpdir $(objdir)/testsuite" >> ./site.tmp
+ @echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./site.tmp
+ @if [ "X$(ALT_CC_UNDER_TEST)" != "X" ] ; then \
+ echo "set ALT_CC_UNDER_TEST \"$(ALT_CC_UNDER_TEST)\"" >> ./site.tmp; \
+ else true; \
+ fi
+ @if [ "X$(ALT_CXX_UNDER_TEST)" != "X" ] ; then \
+ echo "set ALT_CXX_UNDER_TEST \"$(ALT_CXX_UNDER_TEST)\"" >> ./site.tmp; \
+ else true; \
+ fi
+ @if [ "X$(COMPAT_OPTIONS)" != "X" ] ; then \
+ echo "set COMPAT_OPTIONS \"$(COMPAT_OPTIONS)\"" >> ./site.tmp; \
+ else true; \
+ fi
+ @echo "## All variables above are generated by configure. Do Not Edit ##" >> ./site.tmp
+ @cat ./site.tmp > site.exp
+ @cat site.bak | sed \
+ -e '1,/^## All variables above are.*##/ d' >> site.exp
+ -@rm -f ./site.tmp
+
+CHECK_TARGETS = @check_languages@
+
+check: $(CHECK_TARGETS)
+
+check-subtargets: $(patsubst %,%-subtargets,$(CHECK_TARGETS))
+
+# The idea is to parallelize testing of multilibs, for example:
+# make -j3 check-gcc//sh-hms-sim/{-m1,-m2,-m3,-m3e,-m4}/{,-nofpu}
+# will run 3 concurrent sessions of check-gcc, eventually testing
+# all 10 combinations. GNU make is required, as is a shell that expands
+# alternations within braces.
+lang_checks_parallel = $(lang_checks:=//%)
+$(lang_checks_parallel): site.exp
+ target=`echo "$@" | sed 's,//.*,,'`; \
+ variant=`echo "$@" | sed 's,^[^/]*//,,'`; \
+ vardots=`echo "$$variant" | sed 's,/,.,g'`; \
+ $(MAKE) TESTSUITEDIR="testsuite.$$vardots" \
+ RUNTESTFLAGS="--target_board=$$variant $(RUNTESTFLAGS)" \
+ "$$target"
+
+TESTSUITEDIR = testsuite
+
+$(TESTSUITEDIR)/site.exp: site.exp
+ -test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
+ -rm -f $@
+ sed '/set tmpdir/ s|testsuite$$|$(TESTSUITEDIR)|' < site.exp > $@
+
+# This is only used for check-% targets that aren't parallelized.
+$(filter-out $(lang_checks_parallelized),$(lang_checks)): check-% : site.exp
+ -test -d plugin || mkdir plugin
+ -test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
+ test -d $(TESTSUITEDIR)/$* || mkdir $(TESTSUITEDIR)/$*
+ -(rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
+ cd $(TESTSUITEDIR)/$*; \
+ rm -f tmp-site.exp; \
+ sed '/set tmpdir/ s|testsuite$$|$(TESTSUITEDIR)/$*|' \
+ < ../../site.exp > tmp-site.exp; \
+ $(SHELL) $${srcdir}/../move-if-change tmp-site.exp site.exp; \
+ EXPECT=${EXPECT} ; export EXPECT ; \
+ if [ -f $${rootme}/../expect/expect ] ; then \
+ TCL_LIBRARY=`cd .. ; cd $${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
+ export TCL_LIBRARY ; fi ; \
+ $(RUNTEST) --tool $* $(RUNTESTFLAGS))
+
+$(patsubst %,%-subtargets,$(lang_checks)): check-%-subtargets:
+ @echo check-$*
+
+check_p_tool=$(firstword $(subst _, ,$*))
+check_p_count=$(check_$(check_p_tool)_parallelize)
+check_p_subno=$(word 2,$(subst _, ,$*))
+check_p_numbers0:=1 2 3 4 5 6 7 8 9
+check_p_numbers1:=0 $(check_p_numbers0)
+check_p_numbers2:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers1)))
+check_p_numbers3:=$(addprefix 0,$(check_p_numbers1)) $(check_p_numbers2)
+check_p_numbers4:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers3)))
+check_p_numbers5:=$(addprefix 0,$(check_p_numbers3)) $(check_p_numbers4)
+check_p_numbers6:=$(foreach i,$(check_p_numbers0),$(addprefix $(i),$(check_p_numbers5)))
+check_p_numbers:=$(check_p_numbers0) $(check_p_numbers2) $(check_p_numbers4) $(check_p_numbers6)
+check_p_subdir=$(subst _,,$*)
+check_p_subdirs=$(wordlist 1,$(check_p_count),$(wordlist 1, \
+ $(if $(GCC_TEST_PARALLEL_SLOTS),$(GCC_TEST_PARALLEL_SLOTS),128), \
+ $(check_p_numbers)))
+
+# For parallelized check-% targets, this decides whether parallelization
+# is desirable (if -jN is used). If desirable, recursive make is run with
+# check-parallel-$lang{,1,2,3,4,5} etc. goals, which can be executed in
+# parallel, as they are run in separate directories.
+# check-parallel-$lang{,1,2,3,4,5} etc. goals invoke runtest with
+# GCC_RUNTEST_PARALLELIZE_DIR var in the environment and runtest_file_p
+# dejaGNU procedure is overridden to additionally synchronize through
+# a $lang-parallel directory which tests will be run by which runtest instance.
+# Afterwards contrib/dg-extract-results.sh is used to merge the sum and log
+# files. If parallelization isn't desirable, only one recursive make
+# is run with check-parallel-$lang goal and check_$lang_parallelize variable
+# cleared to say that no additional arguments beyond $(RUNTESTFLAGS)
+# should be passed to runtest.
+#
+# To parallelize some language check, add the corresponding check-$lang
+# to lang_checks_parallelized variable and define check_$lang_parallelize
+# variable. This is the upper limit to which it is useful to parallelize the
+# check-$lang target. It doesn't make sense to try e.g. 128 goals for small
+# testsuites like objc or go.
+$(lang_checks_parallelized): check-% : site.exp
+ -rm -rf $(TESTSUITEDIR)/$*-parallel
+ @if [ -n "$(filter -j%, $(MFLAGS))" ]; then \
+ test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR) || true; \
+ test -d $(TESTSUITEDIR)/$*-parallel || mkdir $(TESTSUITEDIR)/$*-parallel || true; \
+ GCC_RUNTEST_PARALLELIZE_DIR=`${PWD_COMMAND}`/$(TESTSUITEDIR)/$(check_p_tool)-parallel ; \
+ export GCC_RUNTEST_PARALLELIZE_DIR ; \
+ $(MAKE) TESTSUITEDIR="$(TESTSUITEDIR)" RUNTESTFLAGS="$(RUNTESTFLAGS)" \
+ check-parallel-$* \
+ $(patsubst %,check-parallel-$*_%, $(check_p_subdirs)); \
+ sums= ; logs= ; \
+ for dir in $(TESTSUITEDIR)/$* \
+ $(patsubst %,$(TESTSUITEDIR)/$*%,$(check_p_subdirs));\
+ do \
+ if [ -d $$dir ]; then \
+ mv -f $$dir/$*.sum $$dir/$*.sum.sep; mv -f $$dir/$*.log $$dir/$*.log.sep; \
+ sums="$$sums $$dir/$*.sum.sep"; logs="$$logs $$dir/$*.log.sep"; \
+ fi; \
+ done; \
+ $(SHELL) $(srcdir)/../contrib/dg-extract-results.sh $$sums \
+ > $(TESTSUITEDIR)/$*/$*.sum; \
+ $(SHELL) $(srcdir)/../contrib/dg-extract-results.sh -L $$logs \
+ > $(TESTSUITEDIR)/$*/$*.log; \
+ rm -rf $(TESTSUITEDIR)/$*-parallel || true; \
+ else \
+ $(MAKE) TESTSUITEDIR="$(TESTSUITEDIR)" RUNTESTFLAGS="$(RUNTESTFLAGS)" \
+ check_$*_parallelize= check-parallel-$*; \
+ fi
+
+check-parallel-% : site.exp
+ -@test -d plugin || mkdir plugin
+ -@test -d $(TESTSUITEDIR) || mkdir $(TESTSUITEDIR)
+ @test -d $(TESTSUITEDIR)/$(check_p_subdir) || mkdir $(TESTSUITEDIR)/$(check_p_subdir)
+ -$(if $(check_p_subno),@)(rootme=`${PWD_COMMAND}`; export rootme; \
+ srcdir=`cd ${srcdir}; ${PWD_COMMAND}` ; export srcdir ; \
+ if [ -n "$(check_p_subno)" ] \
+ && [ -n "$$GCC_RUNTEST_PARALLELIZE_DIR" ] \
+ && [ -f $(TESTSUITEDIR)/$(check_p_tool)-parallel/finished ]; then \
+ rm -rf $(TESTSUITEDIR)/$(check_p_subdir); \
+ else \
+ cd $(TESTSUITEDIR)/$(check_p_subdir); \
+ rm -f tmp-site.exp; \
+ sed '/set tmpdir/ s|testsuite$$|$(TESTSUITEDIR)/$(check_p_subdir)|' \
+ < ../../site.exp > tmp-site.exp; \
+ $(SHELL) $${srcdir}/../move-if-change tmp-site.exp site.exp; \
+ EXPECT=${EXPECT} ; export EXPECT ; \
+ if [ -f $${rootme}/../expect/expect ] ; then \
+ TCL_LIBRARY=`cd .. ; cd $${srcdir}/../tcl/library ; ${PWD_COMMAND}` ; \
+ export TCL_LIBRARY ; \
+ fi ; \
+ $(RUNTEST) --tool $(check_p_tool) $(RUNTESTFLAGS); \
+ if [ -n "$$GCC_RUNTEST_PARALLELIZE_DIR" ] ; then \
+ touch $${rootme}/$(TESTSUITEDIR)/$(check_p_tool)-parallel/finished; \
+ fi ; \
+ fi )
+
+# QMTest targets
+
+# The path to qmtest.
+QMTEST_PATH=qmtest
+
+# The flags to pass to qmtest.
+QMTESTFLAGS=
+
+# The flags to pass to "qmtest run".
+QMTESTRUNFLAGS=-f none --result-stream dejagnu_stream.DejaGNUStream
+
+# The command to use to invoke qmtest.
+QMTEST=${QMTEST_PATH} ${QMTESTFLAGS}
+
+# The tests (or suites) to run.
+QMTEST_GPP_TESTS=g++
+
+# The subdirectory of the OBJDIR that will be used to store the QMTest
+# test database configuration and that will be used for temporary
+# scratch space during QMTest's execution.
+QMTEST_DIR=qmtestsuite
+
+# Create the QMTest database configuration.
+${QMTEST_DIR} stamp-qmtest:
+ ${QMTEST} -D ${QMTEST_DIR} create-tdb \
+ -c gcc_database.GCCDatabase \
+ -a srcdir=`cd ${srcdir}/testsuite && ${PWD_COMMAND}` && \
+ $(STAMP) stamp-qmtest
+
+# Create the QMTest context file.
+${QMTEST_DIR}/context: stamp-qmtest
+ rm -f $@
+ echo "CompilerTable.languages=c cplusplus" >> $@
+ echo "CompilerTable.c_kind=GCC" >> $@
+ echo "CompilerTable.c_path=${objdir}/xgcc" >> $@
+ echo "CompilerTable.c_options=-B${objdir}/" >> $@
+ echo "CompilerTable.cplusplus_kind=GCC" >> $@
+ echo "CompilerTable.cplusplus_path=${objdir}/xg++" >> $@
+ echo "CompilerTable.cplusplus_options=-B${objdir}/" >> $@
+ echo "DejaGNUTest.target=${target_noncanonical}" >> $@
+
+# Run the G++ testsuite using QMTest.
+qmtest-g++: ${QMTEST_DIR}/context
+ cd ${QMTEST_DIR} && ${QMTEST} run ${QMTESTRUNFLAGS} -C context \
+ -o g++.qmr ${QMTEST_GPP_TESTS}
+
+# Use the QMTest GUI.
+qmtest-gui: ${QMTEST_DIR}/context
+ cd ${QMTEST_DIR} && ${QMTEST} gui -C context
+
+.PHONY: qmtest-g++
+
+# Run Paranoia on real.cc.
+
+paranoia.o: $(srcdir)/../contrib/paranoia.cc $(CONFIG_H) $(SYSTEM_H) $(TREE_H)
+ g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
+
+paranoia: paranoia.o real.o $(LIBIBERTY)
+ g++ -o $@ paranoia.o real.o $(LIBIBERTY)
+
+# These exist for maintenance purposes.
+
+CTAGS=@CTAGS@
+ETAGS=@ETAGS@
+CSCOPE=@CSCOPE@
+
+# Update the tags table.
+TAGS: lang.tags
+ (cd $(srcdir); \
+ incs= ; \
+ list='$(SUBDIRS)'; for dir in $$list; do \
+ if test -f $$dir/TAGS; then \
+ incs="$$incs --include $$dir/TAGS.sub"; \
+ fi; \
+ done; \
+ $(ETAGS) -o TAGS.sub c-family/*.h c-family/*.cc c-family/*.cc \
+ *.h *.c *.cc \
+ ../include/*.h ../libiberty/*.c \
+ ../libcpp/*.c ../libcpp/include/*.h \
+ --language=none --regex="/\(char\|unsigned int\|int\|bool\|void\|HOST_WIDE_INT\|enum [A-Za-z_0-9]+\) [*]?\([A-Za-z_0-9]+\)/\2/" common.opt \
+ --language=none --regex="/\(DEF_RTL_EXPR\|DEFTREECODE\|DEFGSCODE\|DEFTIMEVAR\|DEFPARAM\|DEFPARAMENUM5\)[ ]?(\([A-Za-z_0-9]+\)/\2/" rtl.def tree.def gimple.def timevar.def \
+ ; \
+ $(ETAGS) --include TAGS.sub $$incs)
+
+# -----------------------------------------------------
+# Rules for generating translated message descriptions.
+# Disabled by autoconf if the tools are not available.
+# -----------------------------------------------------
+
+XGETTEXT = @XGETTEXT@
+GMSGFMT = @GMSGFMT@
+MSGMERGE = msgmerge
+CATALOGS = $(patsubst %,po/%,@CATALOGS@)
+
+.PHONY: build- install- build-po install-po update-po
+
+# Dummy rules to deal with dependencies produced by use of
+# "build-@POSUB@" and "install-@POSUB@" above, when NLS is disabled.
+build-: ; @true
+install-: ; @true
+
+build-po: $(CATALOGS)
+
+# This notation should be acceptable to all Make implementations used
+# by people who are interested in updating .po files.
+update-po: $(CATALOGS:.gmo=.pox)
+
+# N.B. We do not attempt to copy these into $(srcdir). The snapshot
+# script does that.
+.po.gmo:
+ $(mkinstalldirs) po
+ $(GMSGFMT) --statistics -o $@ $<
+
+# The new .po has to be gone over by hand, so we deposit it into
+# build/po with a different extension.
+# If build/po/gcc.pot exists, use it (it was just created),
+# else use the one in srcdir.
+.po.pox:
+ $(mkinstalldirs) po
+ $(MSGMERGE) $< `if test -f po/gcc.pot; \
+ then echo po/gcc.pot; \
+ else echo $(srcdir)/po/gcc.pot; fi` -o $@
+
+# This rule has to look for .gmo modules in both srcdir and
+# the cwd, and has to check that we actually have a catalog
+# for each language, in case they weren't built or included
+# with the distribution.
+install-po:
+ $(mkinstalldirs) $(DESTDIR)$(datadir)
+ cats="$(CATALOGS)"; for cat in $$cats; do \
+ lang=`basename $$cat | sed 's/\.gmo$$//'`; \
+ if [ -f $$cat ]; then :; \
+ elif [ -f $(srcdir)/$$cat ]; then cat=$(srcdir)/$$cat; \
+ else continue; \
+ fi; \
+ dir=$(localedir)/$$lang/LC_MESSAGES; \
+ echo $(mkinstalldirs) $(DESTDIR)$$dir; \
+ $(mkinstalldirs) $(DESTDIR)$$dir || exit 1; \
+ echo $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/gcc.mo; \
+ $(INSTALL_DATA) $$cat $(DESTDIR)$$dir/gcc.mo; \
+ done
+
+# Rule for regenerating the message template (gcc.pot).
+# Instead of forcing everyone to edit POTFILES.in, which proved impractical,
+# this rule has no dependencies and always regenerates gcc.pot. This is
+# relatively harmless since the .po files do not directly depend on it.
+# Note that exgettext has an awk script embedded in it which requires a
+# fairly modern (POSIX-compliant) awk.
+# The .pot file is left in the build directory.
+gcc.pot: po/gcc.pot
+po/gcc.pot: force
+ $(mkinstalldirs) po
+ $(MAKE) srcextra
+ AWK=$(AWK) $(SHELL) $(srcdir)/po/exgettext \
+ $(XGETTEXT) gcc $(srcdir)
+
+#
+
+# Dependency information.
+
+# In order for parallel make to really start compiling the expensive
+# objects from $(OBJS) as early as possible, build all their
+# prerequisites strictly before all objects.
+$(ALL_HOST_OBJS) : | $(generated_files)
+
+# Include the auto-generated dependencies for all host objects.
+DEPFILES = \
+ $(foreach obj,$(ALL_HOST_OBJS),\
+ $(dir $(obj))$(DEPDIR)/$(patsubst %.o,%.Po,$(notdir $(obj))))
+-include $(DEPFILES)
diff --git a/support/cpp/gcc/acinclude.m4 b/support/cpp/gcc/acinclude.m4
new file mode 100644
index 000000000..39ad1139a
--- /dev/null
+++ b/support/cpp/gcc/acinclude.m4
@@ -0,0 +1,539 @@
+dnl Copyright (C) 2005-2022 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GCC.
+dnl
+dnl GCC is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GCC is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GCC; see the file COPYING3. If not see
+dnl <http://www.gnu.org/licenses/>.
+
+dnl See whether we need a declaration for a function.
+dnl The result is highly dependent on the INCLUDES passed in, so make sure
+dnl to use a different cache variable name in this macro if it is invoked
+dnl in a different context somewhere else.
+dnl gcc_AC_CHECK_DECL(SYMBOL,
+dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
+AC_DEFUN([gcc_AC_CHECK_DECL],
+[AC_MSG_CHECKING([whether $1 is declared])
+AC_CACHE_VAL(gcc_cv_have_decl_$1,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$4],
+[#ifndef $1
+char *(*pfn) = (char *(*)) $1 ;
+#endif])], eval "gcc_cv_have_decl_$1=yes", eval "gcc_cv_have_decl_$1=no")])
+if eval "test \"`echo '$gcc_cv_have_decl_'$1`\" = yes"; then
+ AC_MSG_RESULT(yes) ; ifelse([$2], , :, [$2])
+else
+ AC_MSG_RESULT(no) ; ifelse([$3], , :, [$3])
+fi
+])dnl
+
+dnl Check multiple functions to see whether each needs a declaration.
+dnl Arrange to define HAVE_DECL_<FUNCTION> to 0 or 1 as appropriate.
+dnl gcc_AC_CHECK_DECLS(SYMBOLS,
+dnl [ACTION-IF-NEEDED [, ACTION-IF-NOT-NEEDED [, INCLUDES]]])
+AC_DEFUN([gcc_AC_CHECK_DECLS],
+[AC_FOREACH([gcc_AC_Func], [$1],
+ [AH_TEMPLATE(AS_TR_CPP(HAVE_DECL_[]gcc_AC_Func),
+ [Define to 1 if we found a declaration for ']gcc_AC_Func[', otherwise
+ define to 0.])])dnl
+for ac_func in $1
+do
+ ac_tr_decl=AS_TR_CPP([HAVE_DECL_$ac_func])
+gcc_AC_CHECK_DECL($ac_func,
+ [AC_DEFINE_UNQUOTED($ac_tr_decl, 1) $2],
+ [AC_DEFINE_UNQUOTED($ac_tr_decl, 0) $3],
+dnl It is possible that the include files passed in here are local headers
+dnl which supply a backup declaration for the relevant prototype based on
+dnl the definition of (or lack of) the HAVE_DECL_ macro. If so, this test
+dnl will always return success. E.g. see libiberty.h's handling of
+dnl `basename'. To avoid this, we define the relevant HAVE_DECL_ macro to
+dnl 1 so that any local headers used do not provide their own prototype
+dnl during this test.
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+ $4
+)
+done
+])
+
+dnl 'make compare' can be significantly faster, if cmp itself can
+dnl skip bytes instead of using tail. The test being performed is
+dnl "if cmp --ignore-initial=2 t1 t2 && ! cmp --ignore-initial=1 t1 t2"
+dnl but we need to sink errors and handle broken shells. We also test
+dnl for the parameter format "cmp file1 file2 skip1 skip2" which is
+dnl accepted by cmp on some systems.
+AC_DEFUN([gcc_AC_PROG_CMP_IGNORE_INITIAL],
+[AC_CACHE_CHECK([for cmp's capabilities], gcc_cv_prog_cmp_skip,
+[ echo abfoo >t1
+ echo cdfoo >t2
+ gcc_cv_prog_cmp_skip=slowcompare
+ if cmp --ignore-initial=2 t1 t2 > /dev/null 2>&1; then
+ if cmp --ignore-initial=1 t1 t2 > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_prog_cmp_skip=gnucompare
+ fi
+ fi
+ if test $gcc_cv_prog_cmp_skip = slowcompare ; then
+ if cmp t1 t2 2 2 > /dev/null 2>&1; then
+ if cmp t1 t2 1 1 > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_prog_cmp_skip=fastcompare
+ fi
+ fi
+ fi
+ rm t1 t2
+])
+make_compare_target=$gcc_cv_prog_cmp_skip
+AC_SUBST(make_compare_target)
+])
+
+dnl See if symbolic links work and if not, try to substitute either hard links or simple copy.
+AC_DEFUN([gcc_AC_PROG_LN_S],
+[AC_MSG_CHECKING(whether ln -s works)
+AC_CACHE_VAL(gcc_cv_prog_LN_S,
+[rm -f conftestdata_t
+echo >conftestdata_f
+if ln -s conftestdata_f conftestdata_t 2>/dev/null
+then
+ gcc_cv_prog_LN_S="ln -s"
+else
+ if ln conftestdata_f conftestdata_t 2>/dev/null
+ then
+ gcc_cv_prog_LN_S=ln
+ else
+ if cp -p conftestdata_f conftestdata_t 2>/dev/null
+ then
+ gcc_cv_prog_LN_S="cp -p"
+ else
+ gcc_cv_prog_LN_S=cp
+ fi
+ fi
+fi
+rm -f conftestdata_f conftestdata_t
+])dnl
+LN_S="$gcc_cv_prog_LN_S"
+if test "$gcc_cv_prog_LN_S" = "ln -s"; then
+ AC_MSG_RESULT(yes)
+else
+ if test "$gcc_cv_prog_LN_S" = "ln"; then
+ AC_MSG_RESULT([no, using ln])
+ else
+ AC_MSG_RESULT([no, and neither does ln, so using $gcc_cv_prog_LN_S])
+ fi
+fi
+AC_SUBST(LN_S)dnl
+])
+
+dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
+dnl of the usual 2.
+AC_DEFUN([gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG],
+[AC_CACHE_CHECK([if mkdir takes one argument], gcc_cv_mkdir_takes_one_arg,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif], [mkdir ("foo", 0);])],
+ gcc_cv_mkdir_takes_one_arg=no, gcc_cv_mkdir_takes_one_arg=yes)])
+if test $gcc_cv_mkdir_takes_one_arg = yes ; then
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG, 1, [Define if host mkdir takes a single argument.])
+fi
+])
+
+AC_DEFUN([gcc_AC_PROG_INSTALL],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+AC_MSG_CHECKING(for a BSD compatible install)
+if test -z "$INSTALL"; then
+AC_CACHE_VAL(ac_cv_path_install,
+[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+])dnl
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+dnl We do special magic for INSTALL instead of AC_SUBST, to get
+dnl relative paths right.
+AC_MSG_RESULT($INSTALL)
+AC_SUBST(INSTALL)dnl
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+AC_SUBST(INSTALL_PROGRAM)dnl
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+AC_SUBST(INSTALL_DATA)dnl
+])
+
+dnl Determine if enumerated bitfields are unsigned. ISO C says they can
+dnl be either signed or unsigned.
+dnl
+AC_DEFUN([gcc_AC_C_ENUM_BF_UNSIGNED],
+[AC_CACHE_CHECK(for unsigned enumerated bitfields, gcc_cv_enum_bf_unsigned,
+[AC_RUN_IFELSE([AC_LANG_SOURCE([#include <stdlib.h>
+enum t { BLAH = 128 } ;
+struct s_t { enum t member : 8; } s ;
+int main(void)
+{
+ s.member = BLAH;
+ if (s.member < 0) exit(1);
+ exit(0);
+
+}])], gcc_cv_enum_bf_unsigned=yes, gcc_cv_enum_bf_unsigned=no, gcc_cv_enum_bf_unsigned=yes)])
+if test $gcc_cv_enum_bf_unsigned = yes; then
+ AC_DEFINE(ENUM_BITFIELDS_ARE_UNSIGNED, 1,
+ [Define if enumerated bitfields are treated as unsigned values.])
+fi])
+
+dnl Probe number of bits in a byte.
+dnl Note C89 requires CHAR_BIT >= 8.
+dnl
+AC_DEFUN([gcc_AC_C_CHAR_BIT],
+[AC_CACHE_CHECK(for CHAR_BIT, gcc_cv_decl_char_bit,
+[AC_EGREP_CPP(found,
+[#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef CHAR_BIT
+found
+#endif], gcc_cv_decl_char_bit=yes, gcc_cv_decl_char_bit=no)
+])
+if test $gcc_cv_decl_char_bit = no; then
+ AC_CACHE_CHECK(number of bits in a byte, gcc_cv_c_nbby,
+[i=8
+ gcc_cv_c_nbby=
+ while test $i -lt 65; do
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
+ [switch(0) {
+ case (unsigned char)((unsigned long)1 << $i) == ((unsigned long)1 << $i):
+ case (unsigned char)((unsigned long)1<<($i-1)) == ((unsigned long)1<<($i-1)):
+ ; }])],
+ [gcc_cv_c_nbby=$i; break])
+ i=`expr $i + 1`
+ done
+ test -z "$gcc_cv_c_nbby" && gcc_cv_c_nbby=failed
+])
+if test $gcc_cv_c_nbby = failed; then
+ AC_MSG_ERROR(cannot determine number of bits in a byte)
+else
+ AC_DEFINE_UNQUOTED(CHAR_BIT, $gcc_cv_c_nbby,
+ [Define as the number of bits in a byte, if `limits.h' doesn't.])
+fi
+fi])
+
+AC_DEFUN([gcc_AC_INITFINI_ARRAY],
+[AC_ARG_ENABLE(initfini-array,
+ [ --enable-initfini-array use .init_array/.fini_array sections],
+ [], [
+AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
+ gcc_cv_initfini_array, [dnl
+ if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
+ case "${target}" in
+ ia64-*)
+ AC_RUN_IFELSE([AC_LANG_SOURCE([
+#ifndef __ELF__
+#error Not an ELF OS
+#endif
+/* We turn on .preinit_array/.init_array/.fini_array support for ia64
+ if it can be used. */
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
+])],
+ [gcc_cv_initfini_array=yes], [gcc_cv_initfini_array=no],
+ [gcc_cv_initfini_array=no]);;
+ *)
+ gcc_cv_initfini_array=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 \
+ -a "$gcc_cv_gld_minor_version" -ge 22 \
+ -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_initfini_array=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ case $target:$gas in
+ *:yes)
+ sh_flags='"a"'
+ sh_type='%progbits'
+ ;;
+ i?86-*-solaris2*:no | x86_64-*-solaris2*:no)
+ sh_flags='"a"'
+ sh_type='@progbits'
+ ;;
+ sparc*-*-solaris2*:no)
+ sh_flags='#alloc'
+ sh_type='#progbits'
+ sh_quote='"'
+ ;;
+ esac
+ case "$target:$gnu_ld" in
+ *:yes)
+ cat > conftest.s <<EOF
+.section .dtors,$sh_flags,$sh_type
+.balign 4
+.byte 'A', 'A', 'A', 'A'
+.section .ctors,$sh_flags,$sh_type
+.balign 4
+.byte 'B', 'B', 'B', 'B'
+.section .fini_array.65530,$sh_flags,$sh_type
+.balign 4
+.byte 'C', 'C', 'C', 'C'
+.section .init_array.65530,$sh_flags,$sh_type
+.balign 4
+.byte 'D', 'D', 'D', 'D'
+.section .dtors.64528,$sh_flags,$sh_type
+.balign 4
+.byte 'E', 'E', 'E', 'E'
+.section .ctors.64528,$sh_flags,$sh_type
+.balign 4
+.byte 'F', 'F', 'F', 'F'
+.section .fini_array.01005,$sh_flags,$sh_type
+.balign 4
+.byte 'G', 'G', 'G', 'G'
+.section .init_array.01005,$sh_flags,$sh_type
+.balign 4
+.byte 'H', 'H', 'H', 'H'
+.text
+.globl _start
+_start:
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ *-*-solaris2*:no)
+ # When Solaris ld added constructor priority support, it was
+ # decided to only handle .init_array.N/.fini_array.N since
+ # there was no need for backwards compatibility with
+ # .ctors.N/.dtors.N. .ctors/.dtors remain as separate
+ # sections with correct execution order resp. to
+ # .init_array/.fini_array, while gld merges them into
+ # .init_array/.fini_array.
+ cat > conftest.s <<EOF
+.section $sh_quote.fini_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'
+.section $sh_quote.init_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D'
+.section $sh_quote.fini_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'
+.section $sh_quote.init_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H'
+.text
+.globl _start
+_start:
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHHHHHDDDDDDDD > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGGGGGCCCCCCCC > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ esac
+changequote(,)dnl
+ rm -f conftest conftest.*
+changequote([,])dnl
+ fi
+ AC_PREPROC_IFELSE([AC_LANG_SOURCE([
+#ifndef __ELF__
+# error Not an ELF OS
+#endif
+#include <stdlib.h>
+#if defined __GLIBC_PREREQ
+# if __GLIBC_PREREQ (2, 4)
+# else
+# error GLIBC 2.4 required
+# endif
+#else
+# if defined __sun__ && defined __svr4__
+ /* Solaris ld.so.1 supports .init_array/.fini_array since Solaris 8. */
+# else
+# error The C library not known to support .init_array/.fini_array
+# endif
+#endif
+])],, [gcc_cv_initfini_array=no]);;
+ esac
+ else
+ case "${target}" in
+ aarch64*-linux-gnu*)
+ # AArch64 postdates glibc support for .init_array/.fini_array,
+ # so we don't need the preprocessor test above.
+ gcc_cv_initfini_array=yes
+ ;;
+
+ *)
+ AC_MSG_CHECKING(cross compile... guessing)
+ gcc_cv_initfini_array=no
+ ;;
+ esac
+ fi])
+ enable_initfini_array=$gcc_cv_initfini_array
+])
+AC_DEFINE_UNQUOTED(HAVE_INITFINI_ARRAY_SUPPORT,
+ [`if test $enable_initfini_array = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if .init_array/.fini_array sections are available and working.])
+])
+
+dnl # gcc_GAS_FLAGS
+dnl # Used by gcc_GAS_CHECK_FEATURE
+dnl #
+AC_DEFUN([gcc_GAS_FLAGS],
+[AC_CACHE_CHECK([assembler flags], gcc_cv_as_flags,
+[ case "$target" in
+ i[[34567]]86-*-linux*)
+ dnl Override the default, which may be incompatible.
+ gcc_cv_as_flags=--32
+ ;;
+ x86_64-*-linux-gnux32)
+ dnl Override the default, which may be incompatible.
+ gcc_cv_as_flags=--x32
+ ;;
+ x86_64-*-linux*)
+ dnl Override the default, which may be incompatible.
+ gcc_cv_as_flags=--64
+ ;;
+ powerpc*-*-darwin*)
+ dnl Always pass -arch ppc to assembler.
+ gcc_cv_as_flags="-arch ppc"
+ ;;
+ *)
+ gcc_cv_as_flags=" "
+ ;;
+ esac])
+])
+
+dnl gcc_GAS_CHECK_FEATURE(description, cv,
+dnl [extra switches to as], [assembler input],
+dnl [extra testing logic], [command if feature available])
+dnl
+dnl Checks for an assembler feature.
+dnl ASSEMBLER INPUT is fed to the assembler and the feature is available
+dnl if assembly succeeds. If EXTRA TESTING LOGIC is not the empty string,
+dnl then it is run instead of simply setting CV to "yes" - it is responsible
+dnl for doing so, if appropriate.
+AC_DEFUN([gcc_GAS_CHECK_FEATURE],
+[AC_REQUIRE([gcc_GAS_FLAGS])dnl
+AC_CACHE_CHECK([assembler for $1], [$2],
+ [[$2]=no
+ if test x$gcc_cv_as != x; then
+ AS_ECHO([ifelse(m4_substr([$4],0,1),[$], "[$4]", '[$4]')]) > conftest.s
+ if AC_TRY_COMMAND([$gcc_cv_as $gcc_cv_as_flags $3 -o conftest.o conftest.s >&AS_MESSAGE_LOG_FD])
+ then
+ ifelse([$5],, [$2]=yes, [$5])
+ else
+ echo "configure: failed program was" >&AS_MESSAGE_LOG_FD
+ cat conftest.s >&AS_MESSAGE_LOG_FD
+ fi
+ rm -f conftest.o conftest.s
+ fi])
+ifelse([$6],,,[dnl
+if test $[$2] = yes; then
+ $6
+fi])
+ifelse([$7],,,[dnl
+if test $[$2] != yes; then
+ $7
+fi])])
+
+dnl GCC_TARGET_TEMPLATE(KEY)
+dnl ------------------------
+dnl Define KEY as a valid configure key on the target machine.
+
+m4_define([GCC_TARGET_TEMPLATE],
+[m4_define([GCC_TARGET_TEMPLATE($1)],[])])
+
+dnl AH_TEMPLATE(KEY, DESCRIPTION)
+dnl -----------------------------
+dnl Issue an autoheader template for KEY, i.e., a comment composed of
+dnl DESCRIPTION (properly wrapped), and then #undef KEY. Redefinition
+dnl of the macro in autoheader.m4, to support definition of only a few
+dnl keys while compiling target libraries.
+
+m4_define([AH_TEMPLATE],
+[AH_VERBATIM([$1],m4_text_wrap([$2 */], [ ], [/* ])
+m4_ifdef([GCC_TARGET_TEMPLATE($1)],[],[#ifndef USED_FOR_TARGET
+])[#undef $1]m4_ifdef([GCC_TARGET_TEMPLATE($1)],[],[
+#endif
+]))])
+
+dnl Make sure that build_exeext is looked for
+AC_DEFUN([gcc_AC_BUILD_EXEEXT], [
+ac_executable_extensions="$build_exeext"])
+
+dnl GCC_GLIBC_VERSION_GTE_IFELSE(MAJOR, MINOR, IF-TRUE, IF-FALSE)
+dnl -------------------------------------------------------------
+dnl If the target glibc version ($glibc_version_major.$glibc_version_minor)
+dnl is at least MAJOR.MINOR, call IF-TRUE, otherwise call IF-FALSE.
+AC_DEFUN([GCC_GLIBC_VERSION_GTE_IFELSE],
+[
+AS_IF([test $glibc_version_major -gt $1 \
+ || ( test $glibc_version_major -eq $1 && test $glibc_version_minor -ge $2 )],
+[$3], [$4])])
diff --git a/support/cpp/gcc/aclocal.m4 b/support/cpp/gcc/aclocal.m4
new file mode 100644
index 000000000..6be36df51
--- /dev/null
+++ b/support/cpp/gcc/aclocal.m4
@@ -0,0 +1,42 @@
+# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_include([../libtool.m4])
+m4_include([../ltoptions.m4])
+m4_include([../ltsugar.m4])
+m4_include([../ltversion.m4])
+m4_include([../lt~obsolete.m4])
+m4_include([../config/acx.m4])
+m4_include([../config/ax_lib_socket_nsl.m4])
+m4_include([../config/cet.m4])
+m4_include([../config/codeset.m4])
+m4_include([../config/depstand.m4])
+m4_include([../config/dfp.m4])
+m4_include([../config/enable.m4])
+m4_include([../config/gcc-plugin.m4])
+m4_include([../config/gettext-sister.m4])
+m4_include([../config/iconv.m4])
+m4_include([../config/lcmessage.m4])
+m4_include([../config/lead-dot.m4])
+m4_include([../config/lib-ld.m4])
+m4_include([../config/lib-link.m4])
+m4_include([../config/lib-prefix.m4])
+m4_include([../config/mmap.m4])
+m4_include([../config/override.m4])
+m4_include([../config/picflag.m4])
+m4_include([../config/progtest.m4])
+m4_include([../config/stdint.m4])
+m4_include([../config/warnings.m4])
+m4_include([../config/zlib.m4])
+m4_include([acinclude.m4])
diff --git a/support/cpp/gcc/alias.h b/support/cpp/gcc/alias.h
new file mode 100644
index 000000000..b2596518a
--- /dev/null
+++ b/support/cpp/gcc/alias.h
@@ -0,0 +1,50 @@
+/* Exported functions from alias.cc
+ Copyright (C) 2004-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_ALIAS_H
+#define GCC_ALIAS_H
+
+extern alias_set_type new_alias_set (void);
+extern alias_set_type get_alias_set (tree);
+extern alias_set_type get_deref_alias_set (tree);
+extern alias_set_type get_varargs_alias_set (void);
+extern alias_set_type get_frame_alias_set (void);
+extern tree component_uses_parent_alias_set_from (const_tree);
+extern bool ends_tbaa_access_path_p (const_tree);
+extern bool alias_set_subset_of (alias_set_type, alias_set_type);
+extern void record_alias_subset (alias_set_type, alias_set_type);
+extern void record_component_aliases (tree);
+extern int alias_sets_conflict_p (alias_set_type, alias_set_type);
+extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
+extern int objects_must_conflict_p (tree, tree);
+extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool);
+extern void dump_alias_stats_in_alias_c (FILE *s);
+tree reference_alias_ptr_type (tree);
+tree reference_alias_ptr_type_1 (tree *);
+bool alias_ptr_types_compatible_p (tree, tree);
+int compare_base_decls (tree, tree);
+bool refs_same_for_tbaa_p (tree, tree);
+
+/* This alias set can be used to force a memory to conflict with all
+ other memories, creating a barrier across which no memory reference
+ can move. Note that there are other legacy ways to create such
+ memory barriers, including an address of SCRATCH. */
+#define ALIAS_SET_MEMORY_BARRIER ((alias_set_type) -1)
+
+#endif /* GCC_ALIAS_H */
diff --git a/support/cpp/gcc/align.h b/support/cpp/gcc/align.h
new file mode 100644
index 000000000..a51b5c66f
--- /dev/null
+++ b/support/cpp/gcc/align.h
@@ -0,0 +1,83 @@
+/* Alignment-related classes.
+ Copyright (C) 2018-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/>. */
+
+/* Align flags tuple with alignment in log form and with a maximum skip. */
+
+struct align_flags_tuple
+{
+ /* Values of the -falign-* flags: how much to align labels in code.
+ log is "align to 2^log" (so 0 means no alignment).
+ maxskip is the maximum allowed amount of padding to insert. */
+ int log;
+ int maxskip;
+
+ /* Normalize filled values so that maxskip is not bigger than 1 << log. */
+ void normalize ()
+ {
+ int n = (1 << log);
+ if (maxskip > n)
+ maxskip = n - 1;
+ }
+
+ /* Return original value of an alignment flag. */
+ int get_value ()
+ {
+ return maxskip + 1;
+ }
+};
+
+/* Alignment flags is structure used as value of -align-* options.
+ It's used in target-dependant code. */
+
+class align_flags
+{
+public:
+ /* Default constructor. */
+ align_flags (int log0 = 0, int maxskip0 = 0, int log1 = 0, int maxskip1 = 0)
+ {
+ levels[0].log = log0;
+ levels[0].maxskip = maxskip0;
+ levels[1].log = log1;
+ levels[1].maxskip = maxskip1;
+ normalize ();
+ }
+
+ /* Normalize both components of align_flags. */
+ void normalize ()
+ {
+ for (unsigned i = 0; i < 2; i++)
+ levels[i].normalize ();
+ }
+
+ /* Get alignment that is common bigger alignment of alignments F0 and F1. */
+ static align_flags max (const align_flags f0, const align_flags f1)
+ {
+ int log0 = MAX (f0.levels[0].log, f1.levels[0].log);
+ int maxskip0 = MAX (f0.levels[0].maxskip, f1.levels[0].maxskip);
+ int log1 = MAX (f0.levels[1].log, f1.levels[1].log);
+ int maxskip1 = MAX (f0.levels[1].maxskip, f1.levels[1].maxskip);
+ return align_flags (log0, maxskip0, log1, maxskip1);
+ }
+
+ align_flags_tuple levels[2];
+};
+
+/* Define maximum supported code alignment. */
+#define MAX_CODE_ALIGN 16
+#define MAX_CODE_ALIGN_VALUE (1 << MAX_CODE_ALIGN)
diff --git a/support/cpp/gcc/alloc-pool.h b/support/cpp/gcc/alloc-pool.h
new file mode 100644
index 000000000..3963596ea
--- /dev/null
+++ b/support/cpp/gcc/alloc-pool.h
@@ -0,0 +1,576 @@
+/* Functions to support a pool of allocatable objects
+ Copyright (C) 1997-2022 Free Software Foundation, Inc.
+ Contributed by Daniel Berlin <dan@cgsoftware.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.
+
+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 ALLOC_POOL_H
+#define ALLOC_POOL_H
+
+#include "memory-block.h"
+#include "options.h" // for flag_checking
+
+extern void dump_alloc_pool_statistics (void);
+
+/* Flag indicates whether memory statistics are gathered any longer. */
+extern bool after_memory_report;
+
+typedef unsigned long ALLOC_POOL_ID_TYPE;
+
+/* Last used ID. */
+extern ALLOC_POOL_ID_TYPE last_id;
+
+/* Pool allocator memory usage. */
+class pool_usage: public mem_usage
+{
+public:
+ /* Default contructor. */
+ pool_usage (): m_element_size (0), m_pool_name ("") {}
+ /* Constructor. */
+ pool_usage (size_t allocated, size_t times, size_t peak,
+ size_t instances, size_t element_size,
+ const char *pool_name)
+ : mem_usage (allocated, times, peak, instances),
+ m_element_size (element_size),
+ m_pool_name (pool_name) {}
+
+ /* Sum the usage with SECOND usage. */
+ pool_usage
+ operator+ (const pool_usage &second)
+ {
+ return pool_usage (m_allocated + second.m_allocated,
+ m_times + second.m_times,
+ m_peak + second.m_peak,
+ m_instances + second.m_instances,
+ m_element_size, m_pool_name);
+ }
+
+ /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
+ inline void
+ dump (mem_location *loc, const mem_usage &total) const
+ {
+ char *location_string = loc->to_string ();
+
+ fprintf (stderr, "%-32s%-48s " PRsa(5) PRsa(9) ":%5.1f%%"
+ PRsa(9) PRsa(9) ":%5.1f%%%12" PRIu64 "\n",
+ m_pool_name, location_string,
+ SIZE_AMOUNT (m_instances),
+ SIZE_AMOUNT (m_allocated),
+ get_percent (m_allocated, total.m_allocated),
+ SIZE_AMOUNT (m_peak),
+ SIZE_AMOUNT (m_times),
+ get_percent (m_times, total.m_times),
+ (uint64_t)m_element_size);
+
+ free (location_string);
+ }
+
+ /* Dump header with NAME. */
+ static inline void
+ dump_header (const char *name)
+ {
+ fprintf (stderr, "%-32s%-48s %6s%11s%16s%17s%12s\n", "Pool name", name,
+ "Pools", "Leak", "Peak", "Times", "Elt size");
+ }
+
+ /* Dump footer. */
+ inline void
+ dump_footer ()
+ {
+ fprintf (stderr, "%s" PRsa(82) PRsa(10) "\n", "Total",
+ SIZE_AMOUNT (m_instances), SIZE_AMOUNT (m_allocated));
+ }
+
+ /* Element size. */
+ size_t m_element_size;
+ /* Pool name. */
+ const char *m_pool_name;
+};
+
+extern mem_alloc_description<pool_usage> pool_allocator_usage;
+
+#if 0
+/* If a pool with custom block size is needed, one might use the following
+ template. An instance of this template can be used as a parameter for
+ instantiating base_pool_allocator template:
+
+ typedef custom_block_allocator <128*1024> huge_block_allocator;
+ ...
+ static base_pool_allocator <huge_block_allocator>
+ value_pool ("value", 16384);
+
+ Right now it's not used anywhere in the code, and is given here as an
+ example). */
+
+template <size_t BlockSize>
+class custom_block_allocator
+{
+public:
+ static const size_t block_size = BlockSize;
+
+ static inline void *
+ allocate () ATTRIBUTE_MALLOC
+ {
+ return XNEWVEC (char, BlockSize);
+ }
+
+ static inline void
+ release (void *block)
+ {
+ XDELETEVEC (block);
+ }
+};
+#endif
+
+/* Generic pool allocator. */
+
+template <typename TBlockAllocator>
+class base_pool_allocator
+{
+public:
+ /* Default constructor for pool allocator called NAME. */
+ base_pool_allocator (const char *name, size_t size CXX_MEM_STAT_INFO);
+ ~base_pool_allocator ();
+ void release ();
+ void release_if_empty ();
+ void *allocate () ATTRIBUTE_MALLOC;
+ void remove (void *object);
+ size_t num_elts_current ();
+
+private:
+ struct allocation_pool_list
+ {
+ allocation_pool_list *next;
+ };
+
+ /* Initialize a pool allocator. */
+ void initialize ();
+
+ struct allocation_object
+ {
+#if CHECKING_P
+ /* The ID of alloc pool which the object was allocated from. */
+ ALLOC_POOL_ID_TYPE id;
+#endif
+
+ union
+ {
+ /* The data of the object. */
+ char data[1];
+
+ /* Because we want any type of data to be well aligned after the ID,
+ the following elements are here. They are never accessed so
+ the allocated object may be even smaller than this structure.
+ We do not care about alignment for floating-point types. */
+ char *align_p;
+ int64_t align_i;
+ } u;
+
+#if CHECKING_P
+ static inline allocation_object*
+ get_instance (void *data_ptr)
+ {
+ return (allocation_object *)(((char *)(data_ptr))
+ - offsetof (allocation_object,
+ u.data));
+ }
+#endif
+
+ static inline void*
+ get_data (void *instance_ptr)
+ {
+ return (void*)(((allocation_object *) instance_ptr)->u.data);
+ }
+ };
+
+ /* Align X to 8. */
+ static inline size_t
+ align_eight (size_t x)
+ {
+ return (((x+7) >> 3) << 3);
+ }
+
+ const char *m_name;
+ ALLOC_POOL_ID_TYPE m_id;
+ size_t m_elts_per_block;
+
+ /* These are the elements that have been allocated at least once
+ and freed. */
+ allocation_pool_list *m_returned_free_list;
+
+ /* These are the elements that have not yet been allocated out of
+ the last block obtained from XNEWVEC. */
+ char* m_virgin_free_list;
+
+ /* The number of elements in the virgin_free_list that can be
+ allocated before needing another block. */
+ size_t m_virgin_elts_remaining;
+ /* The number of elements that are allocated. */
+ size_t m_elts_allocated;
+ /* The number of elements that are released. */
+ size_t m_elts_free;
+ /* The number of allocated blocks. */
+ size_t m_blocks_allocated;
+ /* List of blocks that are used to allocate new objects. */
+ allocation_pool_list *m_block_list;
+ /* Size of a pool elements in bytes. */
+ size_t m_elt_size;
+ /* Size in bytes that should be allocated for each element. */
+ size_t m_size;
+ /* Flag if a pool allocator is initialized. */
+ bool m_initialized;
+ /* Memory allocation location. */
+ mem_location m_location;
+};
+
+template <typename TBlockAllocator>
+inline
+base_pool_allocator <TBlockAllocator>::base_pool_allocator (
+ const char *name, size_t size MEM_STAT_DECL):
+ m_name (name), m_id (0), m_elts_per_block (0), m_returned_free_list (NULL),
+ m_virgin_free_list (NULL), m_virgin_elts_remaining (0), m_elts_allocated (0),
+ m_elts_free (0), m_blocks_allocated (0), m_block_list (NULL), m_elt_size (0),
+ m_size (size), m_initialized (false),
+ m_location (ALLOC_POOL_ORIGIN, false PASS_MEM_STAT) {}
+
+/* Initialize a pool allocator. */
+
+template <typename TBlockAllocator>
+inline void
+base_pool_allocator <TBlockAllocator>::initialize ()
+{
+ gcc_checking_assert (!m_initialized);
+ m_initialized = true;
+
+ size_t size = m_size;
+
+ gcc_checking_assert (m_name);
+ gcc_checking_assert (m_size);
+
+ /* Make size large enough to store the list header. */
+ if (size < sizeof (allocation_pool_list*))
+ size = sizeof (allocation_pool_list*);
+
+ /* Now align the size to a multiple of 8. */
+ size = align_eight (size);
+
+ /* Add the aligned size of ID. */
+ size += offsetof (allocation_object, u.data);
+
+ m_elt_size = size;
+
+ if (GATHER_STATISTICS)
+ {
+ pool_usage *u = pool_allocator_usage.register_descriptor
+ (this, new mem_location (m_location));
+
+ u->m_element_size = m_elt_size;
+ u->m_pool_name = m_name;
+ }
+
+ /* List header size should be a multiple of 8. */
+ size_t header_size = align_eight (sizeof (allocation_pool_list));
+
+ m_elts_per_block = (TBlockAllocator::block_size - header_size) / size;
+ gcc_checking_assert (m_elts_per_block != 0);
+
+ /* Increase the last used ID and use it for this pool.
+ ID == 0 is used for free elements of pool so skip it. */
+ last_id++;
+ if (last_id == 0)
+ last_id++;
+
+ m_id = last_id;
+}
+
+/* Free all memory allocated for the given memory pool. */
+template <typename TBlockAllocator>
+inline void
+base_pool_allocator <TBlockAllocator>::release ()
+{
+ if (!m_initialized)
+ return;
+
+ allocation_pool_list *block, *next_block;
+
+ /* Free each block allocated to the pool. */
+ for (block = m_block_list; block != NULL; block = next_block)
+ {
+ next_block = block->next;
+ TBlockAllocator::release (block);
+ }
+
+ if (GATHER_STATISTICS && !after_memory_report)
+ {
+ pool_allocator_usage.release_instance_overhead
+ (this, (m_elts_allocated - m_elts_free) * m_elt_size);
+ }
+
+ m_returned_free_list = NULL;
+ m_virgin_free_list = NULL;
+ m_virgin_elts_remaining = 0;
+ m_elts_allocated = 0;
+ m_elts_free = 0;
+ m_blocks_allocated = 0;
+ m_block_list = NULL;
+}
+
+template <typename TBlockAllocator>
+inline void
+base_pool_allocator <TBlockAllocator>::release_if_empty ()
+{
+ if (m_elts_free == m_elts_allocated)
+ release ();
+}
+
+template <typename TBlockAllocator>
+inline base_pool_allocator <TBlockAllocator>::~base_pool_allocator ()
+{
+ release ();
+}
+
+/* Allocates one element from the pool specified. */
+template <typename TBlockAllocator>
+inline void*
+base_pool_allocator <TBlockAllocator>::allocate ()
+{
+ if (!m_initialized)
+ initialize ();
+
+ allocation_pool_list *header;
+#ifdef ENABLE_VALGRIND_ANNOTATIONS
+ int size;
+#endif
+
+ if (GATHER_STATISTICS)
+ {
+ pool_allocator_usage.register_instance_overhead (m_elt_size, this);
+ }
+
+#ifdef ENABLE_VALGRIND_ANNOTATIONS
+ size = m_elt_size - offsetof (allocation_object, u.data);
+#endif
+
+ /* If there are no more free elements, make some more!. */
+ if (!m_returned_free_list)
+ {
+ char *block;
+ if (!m_virgin_elts_remaining)
+ {
+ allocation_pool_list *block_header;
+
+ /* Make the block. */
+ block = reinterpret_cast<char *> (TBlockAllocator::allocate ());
+ block_header = new (block) allocation_pool_list;
+ block += align_eight (sizeof (allocation_pool_list));
+
+ /* Throw it on the block list. */
+ block_header->next = m_block_list;
+ m_block_list = block_header;
+
+ /* Make the block available for allocation. */
+ m_virgin_free_list = block;
+ m_virgin_elts_remaining = m_elts_per_block;
+
+ /* Also update the number of elements we have free/allocated, and
+ increment the allocated block count. */
+ m_elts_allocated += m_elts_per_block;
+ m_elts_free += m_elts_per_block;
+ m_blocks_allocated += 1;
+ }
+
+ /* We now know that we can take the first elt off the virgin list and
+ put it on the returned list. */
+ block = m_virgin_free_list;
+ header = (allocation_pool_list*) allocation_object::get_data (block);
+ header->next = NULL;
+
+ /* Mark the element to be free. */
+#if CHECKING_P
+ ((allocation_object*) block)->id = 0;
+#endif
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (header,size));
+ m_returned_free_list = header;
+ m_virgin_free_list += m_elt_size;
+ m_virgin_elts_remaining--;
+
+ }
+
+ /* Pull the first free element from the free list, and return it. */
+ header = m_returned_free_list;
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (header, sizeof (*header)));
+ m_returned_free_list = header->next;
+ m_elts_free--;
+
+ /* Set the ID for element. */
+#if CHECKING_P
+ allocation_object::get_instance (header)->id = m_id;
+#endif
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (header, size));
+
+ return (void *)(header);
+}
+
+/* Puts PTR back on POOL's free list. */
+template <typename TBlockAllocator>
+inline void
+base_pool_allocator <TBlockAllocator>::remove (void *object)
+{
+ int size = m_elt_size - offsetof (allocation_object, u.data);
+
+ if (flag_checking)
+ {
+ gcc_assert (m_initialized);
+ gcc_assert (object
+ /* Check if we free more than we allocated. */
+ && m_elts_free < m_elts_allocated);
+#if CHECKING_P
+ /* Check whether the PTR was allocated from POOL. */
+ gcc_assert (m_id == allocation_object::get_instance (object)->id);
+#endif
+
+ memset (object, 0xaf, size);
+ }
+
+#if CHECKING_P
+ /* Mark the element to be free. */
+ allocation_object::get_instance (object)->id = 0;
+#endif
+
+ allocation_pool_list *header = new (object) allocation_pool_list;
+ header->next = m_returned_free_list;
+ m_returned_free_list = header;
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (object, size));
+ m_elts_free++;
+
+ if (GATHER_STATISTICS)
+ {
+ pool_allocator_usage.release_instance_overhead (this, m_elt_size);
+ }
+}
+
+/* Number of elements currently active (not returned to pool). Used for cheap
+ consistency checks. */
+template <typename TBlockAllocator>
+inline size_t
+base_pool_allocator <TBlockAllocator>::num_elts_current ()
+{
+ return m_elts_allocated - m_elts_free;
+}
+
+/* Specialization of base_pool_allocator which should be used in most cases.
+ Another specialization may be needed, if object size is greater than
+ memory_block_pool::block_size (64 KB). */
+typedef base_pool_allocator <memory_block_pool> pool_allocator;
+
+/* Type based memory pool allocator. */
+template <typename T>
+class object_allocator
+{
+public:
+ /* Default constructor for pool allocator called NAME. */
+ object_allocator (const char *name CXX_MEM_STAT_INFO):
+ m_allocator (name, sizeof (T) PASS_MEM_STAT) {}
+
+ inline void
+ release ()
+ {
+ m_allocator.release ();
+ }
+
+ inline void release_if_empty ()
+ {
+ m_allocator.release_if_empty ();
+ }
+
+
+ /* Allocate memory for instance of type T and call a default constructor. */
+
+ inline T *
+ allocate () ATTRIBUTE_MALLOC
+ {
+ return ::new (m_allocator.allocate ()) T;
+ }
+
+ /* Allocate memory for instance of type T and return void * that
+ could be used in situations where a default constructor is not provided
+ by the class T. */
+
+ inline void *
+ allocate_raw () ATTRIBUTE_MALLOC
+ {
+ return m_allocator.allocate ();
+ }
+
+ inline void
+ remove (T *object)
+ {
+ /* Call destructor. */
+ object->~T ();
+
+ m_allocator.remove (object);
+ }
+
+ inline void
+ remove_raw (void *object)
+ {
+ m_allocator.remove (object);
+ }
+
+ inline size_t
+ num_elts_current ()
+ {
+ return m_allocator.num_elts_current ();
+ }
+
+private:
+ pool_allocator m_allocator;
+};
+
+/* Store information about each particular alloc_pool. Note that this
+ will underestimate the amount the amount of storage used by a small amount:
+ 1) The overhead in a pool is not accounted for.
+ 2) The unallocated elements in a block are not accounted for. Note
+ that this can at worst case be one element smaller that the block
+ size for that pool. */
+struct alloc_pool_descriptor
+{
+ /* Number of pools allocated. */
+ unsigned long created;
+ /* Gross allocated storage. */
+ unsigned long allocated;
+ /* Amount of currently active storage. */
+ unsigned long current;
+ /* Peak amount of storage used. */
+ unsigned long peak;
+ /* Size of element in the pool. */
+ int elt_size;
+};
+
+/* Helper for classes that do not provide default ctor. */
+
+template <typename T>
+inline void *
+operator new (size_t, object_allocator<T> &a)
+{
+ return a.allocate_raw ();
+}
+
+/* Hashtable mapping alloc_pool names to descriptors. */
+extern hash_map<const char *, alloc_pool_descriptor> *alloc_pool_hash;
+
+
+#endif
diff --git a/support/cpp/gcc/analyzer/analyzer.opt b/support/cpp/gcc/analyzer/analyzer.opt
new file mode 100644
index 000000000..a0ba2c94f
--- /dev/null
+++ b/support/cpp/gcc/analyzer/analyzer.opt
@@ -0,0 +1,257 @@
+; analyzer.opt -- Options for the analyzer.
+
+; Copyright (C) 2019-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/>.
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+-param=analyzer-bb-explosion-factor=
+Common Joined UInteger Var(param_analyzer_bb_explosion_factor) Init(5) Param
+The maximum number of 'after supernode' exploded nodes within the analyzer per supernode, before terminating analysis.
+
+-param=analyzer-max-enodes-per-program-point=
+Common Joined UInteger Var(param_analyzer_max_enodes_per_program_point) Init(8) Param
+The maximum number of exploded nodes per program point within the analyzer, before terminating analysis of that point.
+
+-param=analyzer-max-constraints=
+Common Joined UInteger Var(param_analyzer_max_constraints) Init(20) Param
+The maximum number of constraints per state.
+
+-param=analyzer-max-infeasible-edges=
+Common Joined UInteger Var(param_analyzer_max_infeasible_edges) Init(10) Param
+The maximum number of infeasible edges to reject before declaring a diagnostic as infeasible.
+
+-param=analyzer-max-recursion-depth=
+Common Joined UInteger Var(param_analyzer_max_recursion_depth) Init(2) Param
+The maximum number of times a callsite can appear in a call stack within the analyzer, before terminating analysis of a call that would recurse deeper.
+
+-param=analyzer-max-svalue-depth=
+Common Joined UInteger Var(param_analyzer_max_svalue_depth) Init(12) Param
+The maximum depth of a symbolic value, before approximating the value as unknown.
+
+-param=analyzer-min-snodes-for-call-summary=
+Common Joined UInteger Var(param_analyzer_min_snodes_for_call_summary) Init(10) Param
+The minimum number of supernodes within a function for the analyzer to consider summarizing its effects at call sites.
+
+-param=analyzer-max-enodes-for-full-dump=
+Common Joined UInteger Var(param_analyzer_max_enodes_for_full_dump) Init(200) Param
+The maximum depth of exploded nodes that should appear in a dot dump before switching to a less verbose format.
+
+Wanalyzer-double-fclose
+Common Var(warn_analyzer_double_fclose) Init(1) Warning
+Warn about code paths in which a stdio FILE can be closed more than once.
+
+Wanalyzer-double-free
+Common Var(warn_analyzer_double_free) Init(1) Warning
+Warn about code paths in which a pointer can be freed more than once.
+
+Wanalyzer-exposure-through-output-file
+Common Var(warn_analyzer_exposure_through_output_file) Init(1) Warning
+Warn about code paths in which sensitive data is written to a file.
+
+Wanalyzer-file-leak
+Common Var(warn_analyzer_file_leak) Init(1) Warning
+Warn about code paths in which a stdio FILE is not closed.
+
+Wanalyzer-free-of-non-heap
+Common Var(warn_analyzer_free_of_non_heap) Init(1) Warning
+Warn about code paths in which a non-heap pointer is freed.
+
+Wanalyzer-malloc-leak
+Common Var(warn_analyzer_malloc_leak) Init(1) Warning
+Warn about code paths in which a heap-allocated pointer leaks.
+
+Wanalyzer-mismatching-deallocation
+Common Var(warn_analyzer_mismatching_deallocation) Init(1) Warning
+Warn about code paths in which the wrong deallocation function is called.
+
+Wanalyzer-possible-null-argument
+Common Var(warn_analyzer_possible_null_argument) Init(1) Warning
+Warn about code paths in which a possibly-NULL value is passed to a must-not-be-NULL function argument.
+
+Wanalyzer-possible-null-dereference
+Common Var(warn_analyzer_possible_null_dereference) Init(1) Warning
+Warn about code paths in which a possibly-NULL pointer is dereferenced.
+
+Wanalyzer-unsafe-call-within-signal-handler
+Common Var(warn_analyzer_unsafe_call_within_signal_handler) Init(1) Warning
+Warn about code paths in which an async-signal-unsafe function is called from a signal handler.
+
+Wanalyzer-null-argument
+Common Var(warn_analyzer_null_argument) Init(1) Warning
+Warn about code paths in which NULL is passed to a must-not-be-NULL function argument.
+
+Wanalyzer-null-dereference
+Common Var(warn_analyzer_null_dereference) Init(1) Warning
+Warn about code paths in which a NULL pointer is dereferenced.
+
+Wanalyzer-shift-count-negative
+Common Var(warn_analyzer_shift_count_negative) Init(1) Warning
+Warn about code paths in which a shift with negative count is attempted.
+
+Wanalyzer-shift-count-overflow
+Common Var(warn_analyzer_shift_count_overflow) Init(1) Warning
+Warn about code paths in which a shift with count >= width of type is attempted.
+
+Wanalyzer-stale-setjmp-buffer
+Common Var(warn_analyzer_stale_setjmp_buffer) Init(1) Warning
+Warn about code paths in which a longjmp rewinds to a jmp_buf saved in a stack frame that has returned.
+
+Wanalyzer-tainted-allocation-size
+Common Var(warn_analyzer_tainted_allocation_size) Init(1) Warning
+Warn about code paths in which an unsanitized value is used as an allocation size.
+
+Wanalyzer-tainted-array-index
+Common Var(warn_analyzer_tainted_array_index) Init(1) Warning
+Warn about code paths in which an unsanitized value is used as an array index.
+
+Wanalyzer-tainted-divisor
+Common Var(warn_analyzer_tainted_divisor) Init(1) Warning
+Warn about code paths in which an unsanitized value is used as a divisor.
+
+Wanalyzer-tainted-offset
+Common Var(warn_analyzer_tainted_offset) Init(1) Warning
+Warn about code paths in which an unsanitized value is used as a pointer offset.
+
+Wanalyzer-tainted-size
+Common Var(warn_analyzer_tainted_size) Init(1) Warning
+Warn about code paths in which an unsanitized value is used as a size.
+
+Wanalyzer-use-after-free
+Common Var(warn_analyzer_use_after_free) Init(1) Warning
+Warn about code paths in which a freed value is used.
+
+Wanalyzer-use-of-pointer-in-stale-stack-frame
+Common Var(warn_analyzer_use_of_pointer_in_stale_stack_frame) Init(1) Warning
+Warn about code paths in which a pointer to a stale stack frame is used.
+
+Wanalyzer-write-to-const
+Common Var(warn_analyzer_write_to_const) Init(1) Warning
+Warn about code paths which attempt to write to a const object.
+
+Wanalyzer-write-to-string-literal
+Common Var(warn_analyzer_write_to_string_literal) Init(1) Warning
+Warn about code paths which attempt to write to a string literal.
+
+Wanalyzer-use-of-uninitialized-value
+Common Var(warn_analyzer_use_of_uninitialized_value) Init(1) Warning
+Warn about code paths in which an uninitialized value is used.
+
+Wanalyzer-too-complex
+Common Var(warn_analyzer_too_complex) Init(0) Warning
+Warn if the code is too complicated for the analyzer to fully explore.
+
+fanalyzer-checker=
+Common Joined RejectNegative Var(flag_analyzer_checker)
+Restrict the analyzer to run just the named checker.
+
+fanalyzer-fine-grained
+Common Var(flag_analyzer_fine_grained) Init(0)
+Avoid combining multiple statements into one exploded edge.
+
+fanalyzer-feasibility
+Common Var(flag_analyzer_feasibility) Init(1)
+Verify that paths are feasible when emitting diagnostics.
+
+fanalyzer-show-duplicate-count
+Common Var(flag_analyzer_show_duplicate_count) Init(0)
+Issue a note when diagnostics are deduplicated.
+
+fanalyzer-state-purge
+Common Var(flag_analyzer_state_purge) Init(1)
+Purge unneeded state during analysis.
+
+fanalyzer-state-merge
+Common Var(flag_analyzer_state_merge) Init(1)
+Merge similar-enough states during analysis.
+
+fanalyzer-transitivity
+Common Var(flag_analyzer_transitivity) Init(0)
+Enable transitivity of constraints during analysis.
+
+fanalyzer-call-summaries
+Common Var(flag_analyzer_call_summaries) Init(0)
+Approximate the effect of function calls to simplify analysis.
+
+fanalyzer-verbose-edges
+Common Var(flag_analyzer_verbose_edges) Init(0)
+Emit more verbose descriptions of control flow in diagnostics.
+
+fanalyzer-verbose-state-changes
+Common Var(flag_analyzer_verbose_state_changes) Init(0)
+Emit more verbose descriptions of state changes in diagnostics.
+
+fanalyzer-verbosity=
+Common Joined UInteger Var(analyzer_verbosity) Init(2)
+Control which events are displayed in diagnostic paths.
+
+fdump-analyzer
+Common RejectNegative Var(flag_dump_analyzer)
+Dump various analyzer internals to SRCFILE.analyzer.txt.
+
+fdump-analyzer-stderr
+Common RejectNegative Var(flag_dump_analyzer_stderr)
+Dump various analyzer internals to stderr.
+
+fdump-analyzer-callgraph
+Common RejectNegative Var(flag_dump_analyzer_callgraph)
+Dump analyzer-specific call graph information to a SRCFILE.callgraph.dot file.
+
+fdump-analyzer-exploded-graph
+Common RejectNegative Var(flag_dump_analyzer_exploded_graph)
+Dump the analyzer exploded graph to a SRCFILE.eg.dot file.
+
+fdump-analyzer-exploded-nodes
+Common RejectNegative Var(flag_dump_analyzer_exploded_nodes)
+Emit diagnostics showing the location of nodes in the exploded graph.
+
+fdump-analyzer-exploded-nodes-2
+Common RejectNegative Var(flag_dump_analyzer_exploded_nodes_2)
+Dump a textual representation of the exploded graph to SRCFILE.eg.txt.
+
+fdump-analyzer-exploded-nodes-3
+Common RejectNegative Var(flag_dump_analyzer_exploded_nodes_3)
+Dump a textual representation of the exploded graph to SRCFILE.eg-ID.txt.
+
+fdump-analyzer-exploded-paths
+Common RejectNegative Var(flag_dump_analyzer_exploded_paths)
+Dump a textual representation of each diagnostic's exploded path to SRCFILE.IDX.KIND.epath.txt.
+
+fdump-analyzer-feasibility
+Common RejectNegative Var(flag_dump_analyzer_feasibility)
+Dump various analyzer internals to SRCFILE.*.fg.dot and SRCFILE.*.tg.dot.
+
+fdump-analyzer-json
+Common RejectNegative Var(flag_dump_analyzer_json)
+Dump analyzer-specific data to a SRCFILE.analyzer.json.gz file.
+
+fdump-analyzer-state-purge
+Common RejectNegative Var(flag_dump_analyzer_state_purge)
+Dump state-purging information to a SRCFILE.state-purge.dot file.
+
+fdump-analyzer-supergraph
+Common RejectNegative Var(flag_dump_analyzer_supergraph)
+Dump the analyzer supergraph to a SRCFILE.supergraph.dot file.
+
+fdump-analyzer-untracked
+Common RejectNegative Var(flag_dump_analyzer_untracked)
+Emit custom warnings with internal details intended for analyzer developers.
+
+; This comment is to ensure we retain the blank line above.
diff --git a/support/cpp/gcc/array-traits.h b/support/cpp/gcc/array-traits.h
new file mode 100644
index 000000000..3741777e0
--- /dev/null
+++ b/support/cpp/gcc/array-traits.h
@@ -0,0 +1,48 @@
+/* Descriptions of array-like objects.
+ Copyright (C) 2019-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_ARRAY_TRAITS_H
+#define GCC_ARRAY_TRAITS_H
+
+/* Implementation for single integers (and similar types). */
+template<typename T, T zero = T (0)>
+struct scalar_array_traits
+{
+ typedef T element_type;
+ static const bool has_constant_size = true;
+ static const size_t constant_size = 1;
+ static const T *base (const T &x) { return &x; }
+ static size_t size (const T &) { return 1; }
+};
+
+template<typename T>
+struct array_traits : scalar_array_traits<T> {};
+
+/* Implementation for arrays with a static size. */
+template<typename T, size_t N>
+struct array_traits<T[N]>
+{
+ typedef T element_type;
+ static const bool has_constant_size = true;
+ static const size_t constant_size = N;
+ static const T *base (const T (&x)[N]) { return x; }
+ static size_t size (const T (&)[N]) { return N; }
+};
+
+#endif
diff --git a/support/cpp/gcc/asan.h b/support/cpp/gcc/asan.h
new file mode 100644
index 000000000..1164f10ae
--- /dev/null
+++ b/support/cpp/gcc/asan.h
@@ -0,0 +1,263 @@
+/* AddressSanitizer, a fast memory error detector.
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+ Contributed by Kostya Serebryany <kcc@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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/>. */
+
+#if 0 // sdcpp ndef TREE_ASAN
+#define TREE_ASAN
+
+extern void asan_function_start (void);
+extern void asan_finish_file (void);
+extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int,
+ HOST_WIDE_INT *, tree *, int);
+extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *);
+extern bool asan_protect_global (tree, bool ignore_decl_rtl_set_p = false);
+extern void initialize_sanitizer_builtins (void);
+extern tree asan_dynamic_init_call (bool);
+extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool);
+extern bool asan_expand_mark_ifn (gimple_stmt_iterator *);
+extern bool asan_expand_poison_ifn (gimple_stmt_iterator *, bool *,
+ hash_map<tree, tree> &);
+
+extern void hwasan_record_frame_init ();
+// sdcpp extern void hwasan_record_stack_var (rtx, rtx, poly_int64, poly_int64);
+extern void hwasan_emit_prologue ();
+extern rtx_insn *hwasan_emit_untag_frame (rtx, rtx);
+extern rtx hwasan_get_frame_extent ();
+extern rtx hwasan_frame_base ();
+extern void hwasan_maybe_emit_frame_base_init (void);
+extern bool stack_vars_base_reg_p (rtx);
+extern uint8_t hwasan_current_frame_tag ();
+extern void hwasan_increment_frame_tag ();
+extern rtx hwasan_truncate_to_tag_size (rtx, rtx);
+extern void hwasan_finish_file (void);
+extern bool hwasan_sanitize_p (void);
+extern bool hwasan_sanitize_stack_p (void);
+extern bool hwasan_sanitize_allocas_p (void);
+extern bool hwasan_expand_check_ifn (gimple_stmt_iterator *, bool);
+extern bool hwasan_expand_mark_ifn (gimple_stmt_iterator *);
+extern bool gate_hwasan (void);
+
+extern gimple_stmt_iterator create_cond_insert_point
+ (gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *);
+
+/* Alias set for accessing the shadow memory. */
+extern alias_set_type asan_shadow_set;
+
+/* Hash set of labels that are either used in a goto, or their address
+ has been taken. */
+extern hash_set <tree> *asan_used_labels;
+
+/* Shadow memory is found at
+ (address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset (). */
+#define ASAN_SHADOW_SHIFT 3
+#define ASAN_SHADOW_GRANULARITY (1UL << ASAN_SHADOW_SHIFT)
+
+/* Red zone size, stack and global variables are padded by ASAN_RED_ZONE_SIZE
+ up to 2 * ASAN_RED_ZONE_SIZE - 1 bytes. */
+#define ASAN_RED_ZONE_SIZE 32
+
+/* Stack variable use more compact red zones. The size includes also
+ size of variable itself. */
+
+#define ASAN_MIN_RED_ZONE_SIZE 16
+
+/* Shadow memory values for stack protection. Left is below protected vars,
+ the first pointer in stack corresponding to that offset contains
+ ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing
+ the frame. Middle is for padding in between variables, right is
+ above the last protected variable and partial immediately after variables
+ up to ASAN_RED_ZONE_SIZE alignment. */
+#define ASAN_STACK_MAGIC_LEFT 0xf1
+#define ASAN_STACK_MAGIC_MIDDLE 0xf2
+#define ASAN_STACK_MAGIC_RIGHT 0xf3
+#define ASAN_STACK_MAGIC_USE_AFTER_RET 0xf5
+#define ASAN_STACK_MAGIC_USE_AFTER_SCOPE 0xf8
+
+#define ASAN_STACK_FRAME_MAGIC 0x41b58ab3
+#define ASAN_STACK_RETIRED_MAGIC 0x45e0360e
+
+#define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory"
+
+/* NOTE: The values below and the hooks under targetm.memtag define an ABI and
+ are hard-coded to these values in libhwasan, hence they can't be changed
+ independently here. */
+/* How many bits are used to store a tag in a pointer.
+ The default version uses the entire top byte of a pointer (i.e. 8 bits). */
+#define HWASAN_TAG_SIZE targetm.memtag.tag_size ()
+/* Tag Granule of HWASAN shadow stack.
+ This is the size in real memory that each byte in the shadow memory refers
+ to. I.e. if a variable is X bytes long in memory then its tag in shadow
+ memory will span X / HWASAN_TAG_GRANULE_SIZE bytes.
+ Most variables will need to be aligned to this amount since two variables
+ that are neighbors in memory and share a tag granule would need to share the
+ same tag (the shared tag granule can only store one tag). */
+#define HWASAN_TAG_GRANULE_SIZE targetm.memtag.granule_size ()
+/* Define the tag for the stack background.
+ This defines what tag the stack pointer will be and hence what tag all
+ variables that are not given special tags are (e.g. spilled registers,
+ and parameters passed on the stack). */
+#define HWASAN_STACK_BACKGROUND gen_int_mode (0, QImode)
+
+/* Various flags for Asan builtins. */
+enum asan_check_flags
+{
+ ASAN_CHECK_STORE = 1 << 0,
+ ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
+ ASAN_CHECK_NON_ZERO_LEN = 1 << 2,
+ ASAN_CHECK_LAST = 1 << 3
+};
+
+/* Flags for Asan check builtins. */
+#define IFN_ASAN_MARK_FLAGS DEF(POISON), DEF(UNPOISON)
+
+enum asan_mark_flags
+{
+#define DEF(X) ASAN_MARK_##X
+ IFN_ASAN_MARK_FLAGS
+#undef DEF
+};
+
+/* Return true if STMT is ASAN_MARK with FLAG as first argument. */
+extern bool asan_mark_p (gimple *stmt, enum asan_mark_flags flag);
+
+/* Return the size of padding needed to insert after a protected
+ decl of SIZE. */
+
+static inline unsigned int
+asan_red_zone_size (unsigned int size)
+{
+ unsigned int c = size & (ASAN_RED_ZONE_SIZE - 1);
+ return c ? 2 * ASAN_RED_ZONE_SIZE - c : ASAN_RED_ZONE_SIZE;
+}
+
+/* Return how much a stack variable occupis on a stack
+ including a space for red zone. */
+
+static inline unsigned HOST_WIDE_INT
+asan_var_and_redzone_size (unsigned HOST_WIDE_INT size)
+{
+ if (size <= 4)
+ return 16;
+ else if (size <= 16)
+ return 32;
+ else if (size <= 128)
+ return size + 32;
+ else if (size <= 512)
+ return size + 64;
+ else if (size <= 4096)
+ return size + 128;
+ else
+ return size + 256;
+}
+
+extern bool set_asan_shadow_offset (const char *);
+
+extern bool asan_shadow_offset_set_p ();
+
+extern void set_sanitized_sections (const char *);
+
+extern bool asan_sanitize_stack_p (void);
+
+extern bool asan_sanitize_allocas_p (void);
+
+extern hash_set<tree> *asan_handled_variables;
+
+/* Return TRUE if builtin with given FCODE will be intercepted by
+ libasan. */
+
+static inline bool
+asan_intercepted_p (enum built_in_function fcode)
+{
+ if (hwasan_sanitize_p ())
+ return false;
+
+ return fcode == BUILT_IN_INDEX
+ || fcode == BUILT_IN_MEMCHR
+ || fcode == BUILT_IN_MEMCMP
+ || fcode == BUILT_IN_MEMCPY
+ || fcode == BUILT_IN_MEMMOVE
+ || fcode == BUILT_IN_MEMSET
+ || fcode == BUILT_IN_STRCASECMP
+ || fcode == BUILT_IN_STRCAT
+ || fcode == BUILT_IN_STRCHR
+ || fcode == BUILT_IN_STRCMP
+ || fcode == BUILT_IN_STRCPY
+ || fcode == BUILT_IN_STRDUP
+ || fcode == BUILT_IN_STRLEN
+ || fcode == BUILT_IN_STRNCASECMP
+ || fcode == BUILT_IN_STRNCAT
+ || fcode == BUILT_IN_STRNCMP
+ || fcode == BUILT_IN_STRCSPN
+ || fcode == BUILT_IN_STRPBRK
+ || fcode == BUILT_IN_STRSPN
+ || fcode == BUILT_IN_STRSTR
+ || fcode == BUILT_IN_STRNCPY;
+}
+
+/* Return TRUE if we should instrument for use-after-scope sanity checking. */
+
+static inline bool
+asan_sanitize_use_after_scope (void)
+{
+ return (flag_sanitize_address_use_after_scope
+ && (asan_sanitize_stack_p () || hwasan_sanitize_stack_p ()));
+}
+
+/* Return true if DECL should be guarded on the stack. */
+
+static inline bool
+asan_protect_stack_decl (tree decl)
+{
+ return DECL_P (decl)
+ && (!DECL_ARTIFICIAL (decl)
+ || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl)));
+}
+
+/* Return true when flag_sanitize & FLAG is non-zero. If FN is non-null,
+ remove all flags mentioned in "no_sanitize" of DECL_ATTRIBUTES. */
+
+static inline bool
+sanitize_flags_p (unsigned int flag, const_tree fn = current_function_decl)
+{
+ unsigned int result_flags = flag_sanitize & flag;
+ if (result_flags == 0)
+ return false;
+
+ if (fn != NULL_TREE)
+ {
+ tree value = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (fn));
+ if (value)
+ result_flags &= ~tree_to_uhwi (TREE_VALUE (value));
+ }
+
+ return result_flags;
+}
+
+/* Return true when coverage sanitization should happend for FN function. */
+
+static inline bool
+sanitize_coverage_p (const_tree fn = current_function_decl)
+{
+ return (flag_sanitize_coverage
+ && (fn == NULL_TREE
+ || lookup_attribute ("no_sanitize_coverage",
+ DECL_ATTRIBUTES (fn)) == NULL_TREE));
+}
+
+#endif /* TREE_ASAN */
diff --git a/support/cpp/gcc/attribs.h b/support/cpp/gcc/attribs.h
new file mode 100644
index 000000000..7993715ea
--- /dev/null
+++ b/support/cpp/gcc/attribs.h
@@ -0,0 +1,346 @@
+/* Declarations and definitions dealing with attribute handling.
+ Copyright (C) 2013-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/>. */
+
+#if 0 // sdcpp GCC_ATTRIBS_H
+#define GCC_ATTRIBS_H
+
+extern const struct attribute_spec *lookup_attribute_spec (const_tree);
+extern void free_attr_data ();
+extern void init_attributes (void);
+
+/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
+ which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
+ it should be modified in place; if a TYPE, a copy should be created
+ unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further
+ information, in the form of a bitwise OR of flags in enum attribute_flags
+ from tree.h. Depending on these flags, some attributes may be
+ returned to be applied at a later stage (for example, to apply
+ a decl attribute to the declaration rather than to its type). */
+extern tree decl_attributes (tree *, tree, int, tree = NULL_TREE);
+
+extern bool cxx11_attribute_p (const_tree);
+extern tree get_attribute_name (const_tree);
+extern tree get_attribute_namespace (const_tree);
+extern void apply_tm_attr (tree, tree);
+extern tree make_attribute (const char *, const char *, tree);
+extern bool attribute_ignored_p (tree);
+extern bool attribute_ignored_p (const attribute_spec *const);
+
+extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
+ const char *,
+ bool = false);
+
+extern char *sorted_attr_string (tree);
+extern bool common_function_versions (tree, tree);
+extern tree make_dispatcher_decl (const tree);
+extern bool is_function_default_version (const tree);
+extern void handle_ignored_attributes_option (vec<char *> *);
+
+/* Return a type like TTYPE except that its TYPE_ATTRIBUTES
+ is ATTRIBUTE.
+
+ Such modified types already made are recorded so that duplicates
+ are not made. */
+
+extern tree build_type_attribute_variant (tree, tree);
+extern tree build_decl_attribute_variant (tree, tree);
+extern tree build_type_attribute_qual_variant (tree, tree, int);
+
+extern bool simple_cst_list_equal (const_tree, const_tree);
+extern bool attribute_value_equal (const_tree, const_tree);
+
+/* Return 0 if the attributes for two types are incompatible, 1 if they
+ are compatible, and 2 if they are nearly compatible (which causes a
+ warning to be generated). */
+extern int comp_type_attributes (const_tree, const_tree);
+
+extern tree affects_type_identity_attributes (tree, bool = true);
+extern tree restrict_type_identity_attributes_to (tree, tree);
+
+/* Default versions of target-overridable functions. */
+extern tree merge_decl_attributes (tree, tree);
+extern tree merge_type_attributes (tree, tree);
+
+/* Remove any instances of attribute ATTR_NAME in LIST and return the
+ modified list. */
+
+extern tree remove_attribute (const char *, tree);
+
+/* Given two attributes lists, return a list of their union. */
+
+extern tree merge_attributes (tree, tree);
+
+/* Duplicate all attributes with name NAME in ATTR list to *ATTRS if
+ they are missing there. */
+
+extern void duplicate_one_attribute (tree *, tree, const char *);
+
+/* Duplicate all attributes from user DECL to the corresponding
+ builtin that should be propagated. */
+
+extern void copy_attributes_to_builtin (tree);
+
+/* Given two Windows decl attributes lists, possibly including
+ dllimport, return a list of their union . */
+extern tree merge_dllimport_decl_attributes (tree, tree);
+
+/* Handle a "dllimport" or "dllexport" attribute. */
+extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+
+extern int attribute_list_equal (const_tree, const_tree);
+extern int attribute_list_contained (const_tree, const_tree);
+
+/* The backbone of lookup_attribute(). ATTR_LEN is the string length
+ of ATTR_NAME, and LIST is not NULL_TREE.
+
+ The function is called from lookup_attribute in order to optimize
+ for size. */
+extern tree private_lookup_attribute (const char *attr_name, size_t attr_len,
+ tree list);
+
+extern unsigned decls_mismatched_attributes (tree, tree, tree,
+ const char* const[],
+ pretty_printer*);
+
+extern void maybe_diag_alias_attributes (tree, tree);
+
+/* For a given string S of length L, strip leading and trailing '_' characters
+ so that we have a canonical form of attribute names. NB: This function may
+ change S and L. */
+
+template <typename T>
+inline bool
+canonicalize_attr_name (const char *&s, T &l)
+{
+ if (l > 4 && s[0] == '_' && s[1] == '_' && s[l - 1] == '_' && s[l - 2] == '_')
+ {
+ s += 2;
+ l -= 4;
+ return true;
+ }
+ return false;
+}
+
+/* For a given IDENTIFIER_NODE, strip leading and trailing '_' characters
+ so that we have a canonical form of attribute names. */
+
+static inline tree
+canonicalize_attr_name (tree attr_name)
+{
+ size_t l = IDENTIFIER_LENGTH (attr_name);
+ const char *s = IDENTIFIER_POINTER (attr_name);
+
+ if (canonicalize_attr_name (s, l))
+ return get_identifier_with_length (s, l);
+
+ return attr_name;
+}
+
+/* Compare attribute identifiers ATTR1 and ATTR2 with length ATTR1_LEN and
+ ATTR2_LEN. */
+
+static inline bool
+cmp_attribs (const char *attr1, size_t attr1_len,
+ const char *attr2, size_t attr2_len)
+{
+ return attr1_len == attr2_len && strncmp (attr1, attr2, attr1_len) == 0;
+}
+
+/* Compare attribute identifiers ATTR1 and ATTR2. */
+
+static inline bool
+cmp_attribs (const char *attr1, const char *attr2)
+{
+ return cmp_attribs (attr1, strlen (attr1), attr2, strlen (attr2));
+}
+
+/* Given an identifier node IDENT and a string ATTR_NAME, return true
+ if the identifier node is a valid attribute name for the string. */
+
+static inline bool
+is_attribute_p (const char *attr_name, const_tree ident)
+{
+ return cmp_attribs (attr_name, strlen (attr_name),
+ IDENTIFIER_POINTER (ident), IDENTIFIER_LENGTH (ident));
+}
+
+/* Given an attribute name ATTR_NAME and a list of attributes LIST,
+ return a pointer to the attribute's list element if the attribute
+ is part of the list, or NULL_TREE if not found. If the attribute
+ appears more than once, this only returns the first occurrence; the
+ TREE_CHAIN of the return value should be passed back in if further
+ occurrences are wanted. ATTR_NAME must be in the form 'text' (not
+ '__text__'). */
+
+static inline tree
+lookup_attribute (const char *attr_name, tree list)
+{
+ if (CHECKING_P && attr_name[0] != '_')
+ {
+ size_t attr_len = strlen (attr_name);
+ gcc_checking_assert (!canonicalize_attr_name (attr_name, attr_len));
+ }
+ /* In most cases, list is NULL_TREE. */
+ if (list == NULL_TREE)
+ return NULL_TREE;
+ else
+ {
+ size_t attr_len = strlen (attr_name);
+ /* Do the strlen() before calling the out-of-line implementation.
+ In most cases attr_name is a string constant, and the compiler
+ will optimize the strlen() away. */
+ return private_lookup_attribute (attr_name, attr_len, list);
+ }
+}
+
+/* Given an attribute name ATTR_NAME and a list of attributes LIST,
+ return a pointer to the attribute's list first element if the attribute
+ starts with ATTR_NAME. ATTR_NAME must be in the form 'text' (not
+ '__text__'). */
+
+static inline tree
+lookup_attribute_by_prefix (const char *attr_name, tree list)
+{
+ gcc_checking_assert (attr_name[0] != '_');
+ /* In most cases, list is NULL_TREE. */
+ if (list == NULL_TREE)
+ return NULL_TREE;
+ else
+ {
+ size_t attr_len = strlen (attr_name);
+ while (list)
+ {
+ tree name = get_attribute_name (list);
+ size_t ident_len = IDENTIFIER_LENGTH (name);
+
+ if (attr_len > ident_len)
+ {
+ list = TREE_CHAIN (list);
+ continue;
+ }
+
+ const char *p = IDENTIFIER_POINTER (name);
+ gcc_checking_assert (attr_len == 0 || p[0] != '_');
+
+ if (strncmp (attr_name, p, attr_len) == 0)
+ break;
+
+ list = TREE_CHAIN (list);
+ }
+
+ return list;
+ }
+}
+
+/* Description of a function argument declared with attribute access.
+ Used as an "iterator" over all such arguments in a function declaration
+ or call. */
+
+struct attr_access
+{
+ /* The beginning and end of the internal string representation. */
+ const char *str, *end;
+ /* The attribute pointer argument. */
+ tree ptr;
+ /* For a declaration, a TREE_CHAIN of VLA bound expressions stored
+ in TREE_VALUE and their positions in the argument list (stored
+ in TREE_PURPOSE). Each expression may be a PARM_DECL or some
+ other DECL (for ordinary variables), or an EXPR for other
+ expressions (e.g., funcion calls). */
+ tree size;
+
+ /* The zero-based position of each of the formal function arguments.
+ For the optional SIZARG, UINT_MAX when not specified. For VLAs
+ with multiple variable bounds, SIZARG is the position corresponding
+ to the most significant bound in the argument list. Positions of
+ subsequent bounds are in the TREE_PURPOSE field of the SIZE chain. */
+ unsigned ptrarg;
+ unsigned sizarg;
+ /* For internal specifications only, the constant minimum size of
+ the array, zero if not specified, and HWI_M1U for the unspecified
+ VLA [*] notation. Meaningless for external (explicit) access
+ specifications. */
+ unsigned HOST_WIDE_INT minsize;
+
+ /* The access mode. */
+ access_mode mode;
+
+ /* Set for an attribute added internally rather than by an explicit
+ declaration. */
+ bool internal_p;
+ /* Set for the T[static MINSIZE] array notation for nonzero MINSIZE
+ less than HWI_M1U. */
+ bool static_p;
+
+ /* Return the number of specified VLA bounds. */
+ unsigned vla_bounds (unsigned *) const;
+
+ /* Return internal representation as STRING_CST. */
+ tree to_internal_string () const;
+
+ /* Return the human-readable representation of the external attribute
+ specification (as it might appear in the source code) as STRING_CST. */
+ tree to_external_string () const;
+
+ /* Return argument of array type formatted as a readable string. */
+ std::string array_as_string (tree) const;
+
+ /* Return the access mode corresponding to the character code. */
+ static access_mode from_mode_char (char);
+
+ /* Reset front end-specific attribute access data from attributes. */
+ static void free_lang_data (tree);
+
+ /* The character codes corresponding to all the access modes. */
+ static constexpr char mode_chars[5] = { '-', 'r', 'w', 'x', '^' };
+
+ /* The strings corresponding to just the external access modes. */
+ static constexpr char mode_names[4][11] =
+ {
+ "none", "read_only", "write_only", "read_write"
+ };
+};
+
+inline access_mode
+attr_access::from_mode_char (char c)
+{
+ switch (c)
+ {
+ case mode_chars[access_none]: return access_none;
+ case mode_chars[access_read_only]: return access_read_only;
+ case mode_chars[access_write_only]: return access_write_only;
+ case mode_chars[access_read_write]: return access_read_write;
+ case mode_chars[access_deferred]: return access_deferred;
+ }
+ gcc_unreachable ();
+}
+
+/* Used to define rdwr_map below. */
+struct rdwr_access_hash: int_hash<int, -1> { };
+
+/* A mapping between argument number corresponding to attribute access
+ mode (read_only, write_only, or read_write) and operands. */
+struct attr_access;
+typedef hash_map<rdwr_access_hash, attr_access> rdwr_map;
+
+extern void init_attr_rdwr_indices (rdwr_map *, tree);
+extern attr_access *get_parm_access (rdwr_map &, tree,
+ tree = current_function_decl);
+
+#endif // GCC_ATTRIBS_H
diff --git a/support/cpp/gcc/backend.h b/support/cpp/gcc/backend.h
new file mode 100644
index 000000000..7ff5405e7
--- /dev/null
+++ b/support/cpp/gcc/backend.h
@@ -0,0 +1,35 @@
+/* Common Backend requirements.
+
+ Copyright (C) 2015-2022 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.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.
+
+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_BACKEND_H
+#define GCC_BACKEND_H
+
+/* This is an aggregation header file. This means it should contain only
+ other include files. */
+
+#include "tm.h"
+#include "function.h"
+#include "bitmap.h"
+#include "sbitmap.h"
+#include "basic-block.h"
+#include "cfg.h"
+
+#endif /*GCC_BACKEND_H */
diff --git a/support/cpp/gcc/basic-block.h b/support/cpp/gcc/basic-block.h
new file mode 100644
index 000000000..e3fff1f69
--- /dev/null
+++ b/support/cpp/gcc/basic-block.h
@@ -0,0 +1,650 @@
+/* Define control flow data structures for the CFG.
+ 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/>. */
+
+#ifndef GCC_BASIC_BLOCK_H
+#define GCC_BASIC_BLOCK_H
+
+#include <profile-count.h>
+
+/* Control flow edge information. */
+class GTY((user)) edge_def {
+public:
+ /* The two blocks at the ends of the edge. */
+ basic_block src;
+ basic_block dest;
+
+ /* Instructions queued on the edge. */
+ union edge_def_insns {
+ gimple_seq g;
+ rtx_insn *r;
+ } insns;
+
+ /* Auxiliary info specific to a pass. */
+ PTR aux;
+
+ /* Location of any goto implicit in the edge. */
+ location_t goto_locus;
+
+ /* The index number corresponding to this edge in the edge vector
+ dest->preds. */
+ unsigned int dest_idx;
+
+ int flags; /* see cfg-flags.def */
+ profile_probability probability;
+
+ /* Return count of edge E. */
+ inline profile_count count () const;
+};
+
+/* Masks for edge.flags. */
+#define DEF_EDGE_FLAG(NAME,IDX) EDGE_##NAME = 1 << IDX ,
+enum cfg_edge_flags {
+#include "cfg-flags.def"
+ LAST_CFG_EDGE_FLAG /* this is only used for EDGE_ALL_FLAGS */
+};
+#undef DEF_EDGE_FLAG
+
+/* Bit mask for all edge flags. */
+#define EDGE_ALL_FLAGS ((LAST_CFG_EDGE_FLAG - 1) * 2 - 1)
+
+/* The following four flags all indicate something special about an edge.
+ Test the edge flags on EDGE_COMPLEX to detect all forms of "strange"
+ control flow transfers. */
+#define EDGE_COMPLEX \
+ (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE)
+
+struct GTY(()) rtl_bb_info {
+ /* The first insn of the block is embedded into bb->il.x. */
+ /* The last insn of the block. */
+ rtx_insn *end_;
+
+ /* In CFGlayout mode points to insn notes/jumptables to be placed just before
+ and after the block. */
+ rtx_insn *header_;
+ rtx_insn *footer_;
+};
+
+struct GTY(()) gimple_bb_info {
+ /* Sequence of statements in this block. */
+ gimple_seq seq;
+
+ /* PHI nodes for this block. */
+ gimple_seq phi_nodes;
+};
+
+/* A basic block is a sequence of instructions with only one entry and
+ only one exit. If any one of the instructions are executed, they
+ will all be executed, and in sequence from first to last.
+
+ There may be COND_EXEC instructions in the basic block. The
+ COND_EXEC *instructions* will be executed -- but if the condition
+ is false the conditionally executed *expressions* will of course
+ not be executed. We don't consider the conditionally executed
+ expression (which might have side-effects) to be in a separate
+ basic block because the program counter will always be at the same
+ location after the COND_EXEC instruction, regardless of whether the
+ condition is true or not.
+
+ Basic blocks need not start with a label nor end with a jump insn.
+ For example, a previous basic block may just "conditionally fall"
+ into the succeeding basic block, and the last basic block need not
+ end with a jump insn. Block 0 is a descendant of the entry block.
+
+ A basic block beginning with two labels cannot have notes between
+ the labels.
+
+ Data for jump tables are stored in jump_insns that occur in no
+ basic block even though these insns can follow or precede insns in
+ basic blocks. */
+
+/* Basic block information indexed by block number. */
+struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_def {
+ /* The edges into and out of the block. */
+ vec<edge, va_gc> *preds;
+ vec<edge, va_gc> *succs;
+
+ /* Auxiliary info specific to a pass. */
+ PTR GTY ((skip (""))) aux;
+
+ /* Innermost loop containing the block. */
+ class loop *loop_father;
+
+ /* The dominance and postdominance information node. */
+ struct et_node * GTY ((skip (""))) dom[2];
+
+ /* Previous and next blocks in the chain. */
+ basic_block prev_bb;
+ basic_block next_bb;
+
+ union basic_block_il_dependent {
+ struct gimple_bb_info GTY ((tag ("0"))) gimple;
+ struct {
+ rtx_insn *head_;
+ struct rtl_bb_info * rtl;
+ } GTY ((tag ("1"))) x;
+ } GTY ((desc ("((%1.flags & BB_RTL) != 0)"))) il;
+
+ /* Various flags. See cfg-flags.def. */
+ int flags;
+
+ /* The index of this block. */
+ int index;
+
+ /* Expected number of executions: calculated in profile.cc. */
+ profile_count count;
+
+ /* The discriminator for this block. The discriminator distinguishes
+ among several basic blocks that share a common locus, allowing for
+ more accurate sample-based profiling. */
+ int discriminator;
+};
+
+/* This ensures that struct gimple_bb_info is smaller than
+ struct rtl_bb_info, so that inlining the former into basic_block_def
+ is the better choice. */
+typedef int __assert_gimple_bb_smaller_rtl_bb
+ [(int) sizeof (struct rtl_bb_info)
+ - (int) sizeof (struct gimple_bb_info)];
+
+
+#define BB_FREQ_MAX 10000
+
+/* Masks for basic_block.flags. */
+#define DEF_BASIC_BLOCK_FLAG(NAME,IDX) BB_##NAME = 1 << IDX ,
+enum cfg_bb_flags
+{
+#include "cfg-flags.def"
+ LAST_CFG_BB_FLAG /* this is only used for BB_ALL_FLAGS */
+};
+#undef DEF_BASIC_BLOCK_FLAG
+
+/* Bit mask for all basic block flags. */
+#define BB_ALL_FLAGS ((LAST_CFG_BB_FLAG - 1) * 2 - 1)
+
+/* Bit mask for all basic block flags that must be preserved. These are
+ the bit masks that are *not* cleared by clear_bb_flags. */
+#define BB_FLAGS_TO_PRESERVE \
+ (BB_DISABLE_SCHEDULE | BB_RTL | BB_NON_LOCAL_GOTO_TARGET \
+ | BB_HOT_PARTITION | BB_COLD_PARTITION)
+
+/* Dummy bitmask for convenience in the hot/cold partitioning code. */
+#define BB_UNPARTITIONED 0
+
+/* Partitions, to be used when partitioning hot and cold basic blocks into
+ separate sections. */
+#define BB_PARTITION(bb) ((bb)->flags & (BB_HOT_PARTITION|BB_COLD_PARTITION))
+#define BB_SET_PARTITION(bb, part) do { \
+ basic_block bb_ = (bb); \
+ bb_->flags = ((bb_->flags & ~(BB_HOT_PARTITION|BB_COLD_PARTITION)) \
+ | (part)); \
+} while (0)
+
+#define BB_COPY_PARTITION(dstbb, srcbb) \
+ BB_SET_PARTITION (dstbb, BB_PARTITION (srcbb))
+
+/* Defines for accessing the fields of the CFG structure for function FN. */
+#define ENTRY_BLOCK_PTR_FOR_FN(FN) ((FN)->cfg->x_entry_block_ptr)
+#define EXIT_BLOCK_PTR_FOR_FN(FN) ((FN)->cfg->x_exit_block_ptr)
+#define basic_block_info_for_fn(FN) ((FN)->cfg->x_basic_block_info)
+#define n_basic_blocks_for_fn(FN) ((FN)->cfg->x_n_basic_blocks)
+#define n_edges_for_fn(FN) ((FN)->cfg->x_n_edges)
+#define last_basic_block_for_fn(FN) ((FN)->cfg->x_last_basic_block)
+#define label_to_block_map_for_fn(FN) ((FN)->cfg->x_label_to_block_map)
+#define profile_status_for_fn(FN) ((FN)->cfg->x_profile_status)
+
+#define BASIC_BLOCK_FOR_FN(FN,N) \
+ ((*basic_block_info_for_fn (FN))[(N)])
+#define SET_BASIC_BLOCK_FOR_FN(FN,N,BB) \
+ ((*basic_block_info_for_fn (FN))[(N)] = (BB))
+
+/* For iterating over basic blocks. */
+#define FOR_BB_BETWEEN(BB, FROM, TO, DIR) \
+ for (BB = FROM; BB != TO; BB = BB->DIR)
+
+#define FOR_EACH_BB_FN(BB, FN) \
+ FOR_BB_BETWEEN (BB, (FN)->cfg->x_entry_block_ptr->next_bb, (FN)->cfg->x_exit_block_ptr, next_bb)
+
+#define FOR_EACH_BB_REVERSE_FN(BB, FN) \
+ FOR_BB_BETWEEN (BB, (FN)->cfg->x_exit_block_ptr->prev_bb, (FN)->cfg->x_entry_block_ptr, prev_bb)
+
+/* For iterating over insns in basic block. */
+#define FOR_BB_INSNS(BB, INSN) \
+ for ((INSN) = BB_HEAD (BB); \
+ (INSN) && (INSN) != NEXT_INSN (BB_END (BB)); \
+ (INSN) = NEXT_INSN (INSN))
+
+/* For iterating over insns in basic block when we might remove the
+ current insn. */
+#define FOR_BB_INSNS_SAFE(BB, INSN, CURR) \
+ for ((INSN) = BB_HEAD (BB), (CURR) = (INSN) ? NEXT_INSN ((INSN)): NULL; \
+ (INSN) && (INSN) != NEXT_INSN (BB_END (BB)); \
+ (INSN) = (CURR), (CURR) = (INSN) ? NEXT_INSN ((INSN)) : NULL)
+
+#define FOR_BB_INSNS_REVERSE(BB, INSN) \
+ for ((INSN) = BB_END (BB); \
+ (INSN) && (INSN) != PREV_INSN (BB_HEAD (BB)); \
+ (INSN) = PREV_INSN (INSN))
+
+#define FOR_BB_INSNS_REVERSE_SAFE(BB, INSN, CURR) \
+ for ((INSN) = BB_END (BB),(CURR) = (INSN) ? PREV_INSN ((INSN)) : NULL; \
+ (INSN) && (INSN) != PREV_INSN (BB_HEAD (BB)); \
+ (INSN) = (CURR), (CURR) = (INSN) ? PREV_INSN ((INSN)) : NULL)
+
+/* Cycles through _all_ basic blocks, even the fake ones (entry and
+ exit block). */
+
+#define FOR_ALL_BB_FN(BB, FN) \
+ for (BB = ENTRY_BLOCK_PTR_FOR_FN (FN); BB; BB = BB->next_bb)
+
+
+/* Stuff for recording basic block info. */
+
+/* For now, these will be functions (so that they can include checked casts
+ to rtx_insn. Once the underlying fields are converted from rtx
+ to rtx_insn, these can be converted back to macros. */
+
+#define BB_HEAD(B) (B)->il.x.head_
+#define BB_END(B) (B)->il.x.rtl->end_
+#define BB_HEADER(B) (B)->il.x.rtl->header_
+#define BB_FOOTER(B) (B)->il.x.rtl->footer_
+
+/* Special block numbers [markers] for entry and exit.
+ Neither of them is supposed to hold actual statements. */
+#define ENTRY_BLOCK (0)
+#define EXIT_BLOCK (1)
+
+/* The two blocks that are always in the cfg. */
+#define NUM_FIXED_BLOCKS (2)
+
+/* This is the value which indicates no edge is present. */
+#define EDGE_INDEX_NO_EDGE -1
+
+/* EDGE_INDEX returns an integer index for an edge, or EDGE_INDEX_NO_EDGE
+ if there is no edge between the 2 basic blocks. */
+#define EDGE_INDEX(el, pred, succ) (find_edge_index ((el), (pred), (succ)))
+
+/* INDEX_EDGE_PRED_BB and INDEX_EDGE_SUCC_BB return a pointer to the basic
+ block which is either the pred or succ end of the indexed edge. */
+#define INDEX_EDGE_PRED_BB(el, index) ((el)->index_to_edge[(index)]->src)
+#define INDEX_EDGE_SUCC_BB(el, index) ((el)->index_to_edge[(index)]->dest)
+
+/* INDEX_EDGE returns a pointer to the edge. */
+#define INDEX_EDGE(el, index) ((el)->index_to_edge[(index)])
+
+/* Number of edges in the compressed edge list. */
+#define NUM_EDGES(el) ((el)->num_edges)
+
+/* BB is assumed to contain conditional jump. Return the fallthru edge. */
+#define FALLTHRU_EDGE(bb) (EDGE_SUCC ((bb), 0)->flags & EDGE_FALLTHRU \
+ ? EDGE_SUCC ((bb), 0) : EDGE_SUCC ((bb), 1))
+
+/* BB is assumed to contain conditional jump. Return the branch edge. */
+#define BRANCH_EDGE(bb) (EDGE_SUCC ((bb), 0)->flags & EDGE_FALLTHRU \
+ ? EDGE_SUCC ((bb), 1) : EDGE_SUCC ((bb), 0))
+
+/* Return expected execution frequency of the edge E. */
+#define EDGE_FREQUENCY(e) e->count ().to_frequency (cfun)
+
+/* Compute a scale factor (or probability) suitable for scaling of
+ gcov_type values via apply_probability() and apply_scale(). */
+#define GCOV_COMPUTE_SCALE(num,den) \
+ ((den) ? RDIV ((num) * REG_BR_PROB_BASE, (den)) : REG_BR_PROB_BASE)
+
+/* Return nonzero if edge is critical. */
+#define EDGE_CRITICAL_P(e) (EDGE_COUNT ((e)->src->succs) >= 2 \
+ && EDGE_COUNT ((e)->dest->preds) >= 2)
+
+#define EDGE_COUNT(ev) vec_safe_length (ev)
+#define EDGE_I(ev,i) (*ev)[(i)]
+#define EDGE_PRED(bb,i) (*(bb)->preds)[(i)]
+#define EDGE_SUCC(bb,i) (*(bb)->succs)[(i)]
+
+/* Returns true if BB has precisely one successor. */
+
+static inline bool
+single_succ_p (const_basic_block bb)
+{
+ return EDGE_COUNT (bb->succs) == 1;
+}
+
+/* Returns true if BB has precisely one predecessor. */
+
+static inline bool
+single_pred_p (const_basic_block bb)
+{
+ return EDGE_COUNT (bb->preds) == 1;
+}
+
+/* Returns the single successor edge of basic block BB. Aborts if
+ BB does not have exactly one successor. */
+
+static inline edge
+single_succ_edge (const_basic_block bb)
+{
+ gcc_checking_assert (single_succ_p (bb));
+ return EDGE_SUCC (bb, 0);
+}
+
+/* Returns the single predecessor edge of basic block BB. Aborts
+ if BB does not have exactly one predecessor. */
+
+static inline edge
+single_pred_edge (const_basic_block bb)
+{
+ gcc_checking_assert (single_pred_p (bb));
+ return EDGE_PRED (bb, 0);
+}
+
+/* Returns the single successor block of basic block BB. Aborts
+ if BB does not have exactly one successor. */
+
+static inline basic_block
+single_succ (const_basic_block bb)
+{
+ return single_succ_edge (bb)->dest;
+}
+
+/* Returns the single predecessor block of basic block BB. Aborts
+ if BB does not have exactly one predecessor.*/
+
+static inline basic_block
+single_pred (const_basic_block bb)
+{
+ return single_pred_edge (bb)->src;
+}
+
+/* Iterator object for edges. */
+
+struct edge_iterator {
+ unsigned index;
+ vec<edge, va_gc> **container;
+};
+
+static inline vec<edge, va_gc> *
+ei_container (edge_iterator i)
+{
+ gcc_checking_assert (i.container);
+ return *i.container;
+}
+
+#define ei_start(iter) ei_start_1 (&(iter))
+#define ei_last(iter) ei_last_1 (&(iter))
+
+/* Return an iterator pointing to the start of an edge vector. */
+static inline edge_iterator
+ei_start_1 (vec<edge, va_gc> **ev)
+{
+ edge_iterator i;
+
+ i.index = 0;
+ i.container = ev;
+
+ return i;
+}
+
+/* Return an iterator pointing to the last element of an edge
+ vector. */
+static inline edge_iterator
+ei_last_1 (vec<edge, va_gc> **ev)
+{
+ edge_iterator i;
+
+ i.index = EDGE_COUNT (*ev) - 1;
+ i.container = ev;
+
+ return i;
+}
+
+/* Is the iterator `i' at the end of the sequence? */
+static inline bool
+ei_end_p (edge_iterator i)
+{
+ return (i.index == EDGE_COUNT (ei_container (i)));
+}
+
+/* Is the iterator `i' at one position before the end of the
+ sequence? */
+static inline bool
+ei_one_before_end_p (edge_iterator i)
+{
+ return (i.index + 1 == EDGE_COUNT (ei_container (i)));
+}
+
+/* Advance the iterator to the next element. */
+static inline void
+ei_next (edge_iterator *i)
+{
+ gcc_checking_assert (i->index < EDGE_COUNT (ei_container (*i)));
+ i->index++;
+}
+
+/* Move the iterator to the previous element. */
+static inline void
+ei_prev (edge_iterator *i)
+{
+ gcc_checking_assert (i->index > 0);
+ i->index--;
+}
+
+/* Return the edge pointed to by the iterator `i'. */
+static inline edge
+ei_edge (edge_iterator i)
+{
+ return EDGE_I (ei_container (i), i.index);
+}
+
+/* Return an edge pointed to by the iterator. Do it safely so that
+ NULL is returned when the iterator is pointing at the end of the
+ sequence. */
+static inline edge
+ei_safe_edge (edge_iterator i)
+{
+ return !ei_end_p (i) ? ei_edge (i) : NULL;
+}
+
+/* Return 1 if we should continue to iterate. Return 0 otherwise.
+ *Edge P is set to the next edge if we are to continue to iterate
+ and NULL otherwise. */
+
+static inline bool
+ei_cond (edge_iterator ei, edge *p)
+{
+ if (!ei_end_p (ei))
+ {
+ *p = ei_edge (ei);
+ return 1;
+ }
+ else
+ {
+ *p = NULL;
+ return 0;
+ }
+}
+
+/* This macro serves as a convenient way to iterate each edge in a
+ vector of predecessor or successor edges. It must not be used when
+ an element might be removed during the traversal, otherwise
+ elements will be missed. Instead, use a for-loop like that shown
+ in the following pseudo-code:
+
+ FOR (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+ {
+ IF (e != taken_edge)
+ remove_edge (e);
+ ELSE
+ ei_next (&ei);
+ }
+*/
+
+#define FOR_EACH_EDGE(EDGE,ITER,EDGE_VEC) \
+ for ((ITER) = ei_start ((EDGE_VEC)); \
+ ei_cond ((ITER), &(EDGE)); \
+ ei_next (&(ITER)))
+
+#define CLEANUP_EXPENSIVE 1 /* Do relatively expensive optimizations
+ except for edge forwarding */
+#define CLEANUP_CROSSJUMP 2 /* Do crossjumping. */
+#define CLEANUP_POST_REGSTACK 4 /* We run after reg-stack and need
+ to care REG_DEAD notes. */
+#define CLEANUP_THREADING 8 /* Do jump threading. */
+#define CLEANUP_NO_INSN_DEL 16 /* Do not try to delete trivially dead
+ insns. */
+#define CLEANUP_CFGLAYOUT 32 /* Do cleanup in cfglayout mode. */
+#define CLEANUP_CFG_CHANGED 64 /* The caller changed the CFG. */
+#define CLEANUP_NO_PARTITIONING 128 /* Do not try to fix partitions. */
+#define CLEANUP_FORCE_FAST_DCE 0x100 /* Force run_fast_dce to be called
+ at least once. */
+
+/* Return true if BB is in a transaction. */
+
+static inline bool
+bb_in_transaction (basic_block bb)
+{
+ return bb->flags & BB_IN_TRANSACTION;
+}
+
+/* Return true when one of the predecessor edges of BB is marked with EDGE_EH. */
+static inline bool
+bb_has_eh_pred (basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e->flags & EDGE_EH)
+ return true;
+ }
+ return false;
+}
+
+/* Return true when one of the predecessor edges of BB is marked with EDGE_ABNORMAL. */
+static inline bool
+bb_has_abnormal_pred (basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (e->flags & EDGE_ABNORMAL)
+ return true;
+ }
+ return false;
+}
+
+/* Return the fallthru edge in EDGES if it exists, NULL otherwise. */
+static inline edge
+find_fallthru_edge (vec<edge, va_gc> *edges)
+{
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, edges)
+ if (e->flags & EDGE_FALLTHRU)
+ break;
+
+ return e;
+}
+
+/* Check tha probability is sane. */
+
+static inline void
+check_probability (int prob)
+{
+ gcc_checking_assert (prob >= 0 && prob <= REG_BR_PROB_BASE);
+}
+
+/* Given PROB1 and PROB2, return PROB1*PROB2/REG_BR_PROB_BASE.
+ Used to combine BB probabilities. */
+
+static inline int
+combine_probabilities (int prob1, int prob2)
+{
+ check_probability (prob1);
+ check_probability (prob2);
+ return RDIV (prob1 * prob2, REG_BR_PROB_BASE);
+}
+
+/* Apply scale factor SCALE on frequency or count FREQ. Use this
+ interface when potentially scaling up, so that SCALE is not
+ constrained to be < REG_BR_PROB_BASE. */
+
+static inline gcov_type
+apply_scale (gcov_type freq, gcov_type scale)
+{
+ return RDIV (freq * scale, REG_BR_PROB_BASE);
+}
+
+/* Apply probability PROB on frequency or count FREQ. */
+
+static inline gcov_type
+apply_probability (gcov_type freq, int prob)
+{
+ check_probability (prob);
+ return apply_scale (freq, prob);
+}
+
+/* Return inverse probability for PROB. */
+
+static inline int
+inverse_probability (int prob1)
+{
+ check_probability (prob1);
+ return REG_BR_PROB_BASE - prob1;
+}
+
+/* Return true if BB has at least one abnormal outgoing edge. */
+
+static inline bool
+has_abnormal_or_eh_outgoing_edge_p (basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & (EDGE_ABNORMAL | EDGE_EH))
+ return true;
+
+ return false;
+}
+
+/* Return true when one of the predecessor edges of BB is marked with
+ EDGE_ABNORMAL_CALL or EDGE_EH. */
+
+static inline bool
+has_abnormal_call_or_eh_pred_edge_p (basic_block bb)
+{
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
+ return true;
+
+ return false;
+}
+
+/* Return count of edge E. */
+inline profile_count edge_def::count () const
+{
+ return src->count.apply_probability (probability);
+}
+
+#endif /* GCC_BASIC_BLOCK_H */
diff --git a/support/cpp/gcc/bitmap.h b/support/cpp/gcc/bitmap.h
new file mode 100644
index 000000000..7fba443af
--- /dev/null
+++ b/support/cpp/gcc/bitmap.h
@@ -0,0 +1,1089 @@
+/* Functions to support general ended bitmaps.
+ 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_BITMAP_H
+#define GCC_BITMAP_H
+
+/* Implementation of sparse integer sets as a linked list or tree.
+
+ This sparse set representation is suitable for sparse sets with an
+ unknown (a priori) universe.
+
+ Sets are represented as double-linked lists of container nodes of
+ type "struct bitmap_element" or as a binary trees of the same
+ container nodes. Each container node consists of an index for the
+ first member that could be held in the container, a small array of
+ integers that represent the members in the container, and pointers
+ to the next and previous element in the linked list, or left and
+ right children in the tree. In linked-list form, the container
+ nodes in the list are sorted in ascending order, i.e. the head of
+ the list holds the element with the smallest member of the set.
+ In tree form, nodes to the left have a smaller container index.
+
+ For a given member I in the set:
+ - the element for I will have index is I / (bits per element)
+ - the position for I within element is I % (bits per element)
+
+ This representation is very space-efficient for large sparse sets, and
+ the size of the set can be changed dynamically without much overhead.
+ An important parameter is the number of bits per element. In this
+ implementation, there are 128 bits per element. This results in a
+ high storage overhead *per element*, but a small overall overhead if
+ the set is very sparse.
+
+ The storage requirements for linked-list sparse sets are O(E), with E->N
+ in the worst case (a sparse set with large distances between the values
+ of the set members).
+
+ This representation also works well for data flow problems where the size
+ of the set may grow dynamically, but care must be taken that the member_p,
+ add_member, and remove_member operations occur with a suitable access
+ pattern.
+
+ The linked-list set representation works well for problems involving very
+ sparse sets. The canonical example in GCC is, of course, the "set of
+ sets" for some CFG-based data flow problems (liveness analysis, dominance
+ frontiers, etc.).
+
+ For random-access sparse sets of unknown universe, the binary tree
+ representation is likely to be a more suitable choice. Theoretical
+ access times for the binary tree representation are better than those
+ for the linked-list, but in practice this is only true for truely
+ random access.
+
+ Often the most suitable representation during construction of the set
+ is not the best choice for the usage of the set. For such cases, the
+ "view" of the set can be changed from one representation to the other.
+ This is an O(E) operation:
+
+ * from list to tree view : bitmap_tree_view
+ * from tree to list view : bitmap_list_view
+
+ Traversing linked lists or trees can be cache-unfriendly. Performance
+ can be improved by keeping container nodes in the set grouped together
+ in memory, using a dedicated obstack for a set (or group of related
+ sets). Elements allocated on obstacks are released to a free-list and
+ taken off the free list. If multiple sets are allocated on the same
+ obstack, elements freed from one set may be re-used for one of the other
+ sets. This usually helps avoid cache misses.
+
+ A single free-list is used for all sets allocated in GGC space. This is
+ bad for persistent sets, so persistent sets should be allocated on an
+ obstack whenever possible.
+
+ For random-access sets with a known, relatively small universe size, the
+ SparseSet or simple bitmap representations may be more efficient than a
+ linked-list set.
+
+
+ LINKED LIST FORM
+ ================
+
+ In linked-list form, in-order iterations of the set can be executed
+ efficiently. The downside is that many random-access operations are
+ relatively slow, because the linked list has to be traversed to test
+ membership (i.e. member_p/ add_member/remove_member).
+
+ To improve the performance of this set representation, the last
+ accessed element and its index are cached. For membership tests on
+ members close to recently accessed members, the cached last element
+ improves membership test to a constant-time operation.
+
+ The following operations can always be performed in O(1) time in
+ list view:
+
+ * clear : bitmap_clear
+ * smallest_member : bitmap_first_set_bit
+ * choose_one : (not implemented, but could be
+ in constant time)
+
+ The following operations can be performed in O(E) time worst-case in
+ list view (with E the number of elements in the linked list), but in
+ O(1) time with a suitable access patterns:
+
+ * member_p : bitmap_bit_p
+ * add_member : bitmap_set_bit / bitmap_set_range
+ * remove_member : bitmap_clear_bit / bitmap_clear_range
+
+ The following operations can be performed in O(E) time in list view:
+
+ * cardinality : bitmap_count_bits
+ * largest_member : bitmap_last_set_bit (but this could
+ in constant time with a pointer to
+ the last element in the chain)
+ * set_size : bitmap_last_set_bit
+
+ In tree view the following operations can all be performed in O(log E)
+ amortized time with O(E) worst-case behavior.
+
+ * smallest_member
+ * largest_member
+ * set_size
+ * member_p
+ * add_member
+ * remove_member
+
+ Additionally, the linked-list sparse set representation supports
+ enumeration of the members in O(E) time:
+
+ * forall : EXECUTE_IF_SET_IN_BITMAP
+ * set_copy : bitmap_copy
+ * set_intersection : bitmap_intersect_p /
+ bitmap_and / bitmap_and_into /
+ EXECUTE_IF_AND_IN_BITMAP
+ * set_union : bitmap_ior / bitmap_ior_into
+ * set_difference : bitmap_intersect_compl_p /
+ bitmap_and_comp / bitmap_and_comp_into /
+ EXECUTE_IF_AND_COMPL_IN_BITMAP
+ * set_disjuction : bitmap_xor_comp / bitmap_xor_comp_into
+ * set_compare : bitmap_equal_p
+
+ Some operations on 3 sets that occur frequently in data flow problems
+ are also implemented:
+
+ * A | (B & C) : bitmap_ior_and_into
+ * A | (B & ~C) : bitmap_ior_and_compl /
+ bitmap_ior_and_compl_into
+
+
+ BINARY TREE FORM
+ ================
+ An alternate "view" of a bitmap is its binary tree representation.
+ For this representation, splay trees are used because they can be
+ implemented using the same data structures as the linked list, with
+ no overhead for meta-data (like color, or rank) on the tree nodes.
+
+ In binary tree form, random-access to the set is much more efficient
+ than for the linked-list representation. Downsides are the high cost
+ of clearing the set, and the relatively large number of operations
+ necessary to balance the tree. Also, iterating the set members is
+ not supported.
+
+ As for the linked-list representation, the last accessed element and
+ its index are cached, so that membership tests on the latest accessed
+ members is a constant-time operation. Other lookups take O(logE)
+ time amortized (but O(E) time worst-case).
+
+ The following operations can always be performed in O(1) time:
+
+ * choose_one : (not implemented, but could be
+ implemented in constant time)
+
+ The following operations can be performed in O(logE) time amortized
+ but O(E) time worst-case, but in O(1) time if the same element is
+ accessed.
+
+ * member_p : bitmap_bit_p
+ * add_member : bitmap_set_bit
+ * remove_member : bitmap_clear_bit
+
+ The following operations can be performed in O(logE) time amortized
+ but O(E) time worst-case:
+
+ * smallest_member : bitmap_first_set_bit
+ * largest_member : bitmap_last_set_bit
+ * set_size : bitmap_last_set_bit
+
+ The following operations can be performed in O(E) time:
+
+ * clear : bitmap_clear
+
+ The binary tree sparse set representation does *not* support any form
+ of enumeration, and does also *not* support logical operations on sets.
+ The binary tree representation is only supposed to be used for sets
+ on which many random-access membership tests will happen. */
+
+#include "obstack.h"
+#include "array-traits.h"
+
+/* Bitmap memory usage. */
+class bitmap_usage: public mem_usage
+{
+public:
+ /* Default contructor. */
+ bitmap_usage (): m_nsearches (0), m_search_iter (0) {}
+ /* Constructor. */
+ bitmap_usage (size_t allocated, size_t times, size_t peak,
+ uint64_t nsearches, uint64_t search_iter)
+ : mem_usage (allocated, times, peak),
+ m_nsearches (nsearches), m_search_iter (search_iter) {}
+
+ /* Sum the usage with SECOND usage. */
+ bitmap_usage
+ operator+ (const bitmap_usage &second)
+ {
+ return bitmap_usage (m_allocated + second.m_allocated,
+ m_times + second.m_times,
+ m_peak + second.m_peak,
+ m_nsearches + second.m_nsearches,
+ m_search_iter + second.m_search_iter);
+ }
+
+ /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
+ inline void
+ dump (mem_location *loc, const mem_usage &total) const
+ {
+ char *location_string = loc->to_string ();
+
+ fprintf (stderr, "%-48s " PRsa (9) ":%5.1f%%"
+ PRsa (9) PRsa (9) ":%5.1f%%"
+ PRsa (11) PRsa (11) "%10s\n",
+ location_string, SIZE_AMOUNT (m_allocated),
+ get_percent (m_allocated, total.m_allocated),
+ SIZE_AMOUNT (m_peak), SIZE_AMOUNT (m_times),
+ get_percent (m_times, total.m_times),
+ SIZE_AMOUNT (m_nsearches), SIZE_AMOUNT (m_search_iter),
+ loc->m_ggc ? "ggc" : "heap");
+
+ free (location_string);
+ }
+
+ /* Dump header with NAME. */
+ static inline void
+ dump_header (const char *name)
+ {
+ fprintf (stderr, "%-48s %11s%16s%17s%12s%12s%10s\n", name, "Leak", "Peak",
+ "Times", "N searches", "Search iter", "Type");
+ }
+
+ /* Number search operations. */
+ uint64_t m_nsearches;
+ /* Number of search iterations. */
+ uint64_t m_search_iter;
+};
+
+/* Bitmap memory description. */
+extern mem_alloc_description<bitmap_usage> bitmap_mem_desc;
+
+/* Fundamental storage type for bitmap. */
+
+typedef unsigned long BITMAP_WORD;
+/* BITMAP_WORD_BITS needs to be unsigned, but cannot contain casts as
+ it is used in preprocessor directives -- hence the 1u. */
+#define BITMAP_WORD_BITS (CHAR_BIT * SIZEOF_LONG * 1u)
+
+/* Number of words to use for each element in the linked list. */
+
+#ifndef BITMAP_ELEMENT_WORDS
+#define BITMAP_ELEMENT_WORDS ((128 + BITMAP_WORD_BITS - 1) / BITMAP_WORD_BITS)
+#endif
+
+/* Number of bits in each actual element of a bitmap. */
+
+#define BITMAP_ELEMENT_ALL_BITS (BITMAP_ELEMENT_WORDS * BITMAP_WORD_BITS)
+
+/* Obstack for allocating bitmaps and elements from. */
+struct bitmap_obstack {
+ struct bitmap_element *elements;
+ bitmap_head *heads;
+ struct obstack obstack;
+};
+
+/* Bitmap set element. We use a linked list to hold only the bits that
+ are set. This allows for use to grow the bitset dynamically without
+ having to realloc and copy a giant bit array.
+
+ The free list is implemented as a list of lists. There is one
+ outer list connected together by prev fields. Each element of that
+ outer is an inner list (that may consist only of the outer list
+ element) that are connected by the next fields. The prev pointer
+ is undefined for interior elements. This allows
+ bitmap_elt_clear_from to be implemented in unit time rather than
+ linear in the number of elements to be freed. */
+
+struct GTY((chain_next ("%h.next"))) bitmap_element {
+ /* In list form, the next element in the linked list;
+ in tree form, the left child node in the tree. */
+ struct bitmap_element *next;
+ /* In list form, the previous element in the linked list;
+ in tree form, the right child node in the tree. */
+ struct bitmap_element *prev;
+ /* regno/BITMAP_ELEMENT_ALL_BITS. */
+ unsigned int indx;
+ /* Bits that are set, counting from INDX, inclusive */
+ BITMAP_WORD bits[BITMAP_ELEMENT_WORDS];
+};
+
+/* Head of bitmap linked list. The 'current' member points to something
+ already pointed to by the chain started by first, so GTY((skip)) it. */
+
+class GTY(()) bitmap_head {
+public:
+ static bitmap_obstack crashme;
+ /* Poison obstack to not make it not a valid initialized GC bitmap. */
+ CONSTEXPR bitmap_head()
+ : indx (0), tree_form (false), padding (0), alloc_descriptor (0), first (NULL),
+ current (NULL), obstack (&crashme)
+ {}
+ /* Index of last element looked at. */
+ unsigned int indx;
+ /* False if the bitmap is in list form; true if the bitmap is in tree form.
+ Bitmap iterators only work on bitmaps in list form. */
+ unsigned tree_form: 1;
+ /* Next integer is shifted, so padding is needed. */
+ unsigned padding: 2;
+ /* Bitmap UID used for memory allocation statistics. */
+ unsigned alloc_descriptor: 29;
+ /* In list form, the first element in the linked list;
+ in tree form, the root of the tree. */
+ bitmap_element *first;
+ /* Last element looked at. */
+ bitmap_element * GTY((skip(""))) current;
+ /* Obstack to allocate elements from. If NULL, then use GGC allocation. */
+ bitmap_obstack * GTY((skip(""))) obstack;
+
+ /* Dump bitmap. */
+ void dump ();
+
+ /* Get bitmap descriptor UID casted to an unsigned integer pointer.
+ Shift the descriptor because pointer_hash<Type>::hash is
+ doing >> 3 shift operation. */
+ unsigned *get_descriptor ()
+ {
+ return (unsigned *)(ptrdiff_t)(alloc_descriptor << 3);
+ }
+};
+
+/* Global data */
+extern bitmap_element bitmap_zero_bits; /* Zero bitmap element */
+extern bitmap_obstack bitmap_default_obstack; /* Default bitmap obstack */
+
+/* Change the view of the bitmap to list, or tree. */
+void bitmap_list_view (bitmap);
+void bitmap_tree_view (bitmap);
+
+/* Clear a bitmap by freeing up the linked list. */
+extern void bitmap_clear (bitmap);
+
+/* Copy a bitmap to another bitmap. */
+extern void bitmap_copy (bitmap, const_bitmap);
+
+/* Move a bitmap to another bitmap. */
+extern void bitmap_move (bitmap, bitmap);
+
+/* True if two bitmaps are identical. */
+extern bool bitmap_equal_p (const_bitmap, const_bitmap);
+
+/* True if the bitmaps intersect (their AND is non-empty). */
+extern bool bitmap_intersect_p (const_bitmap, const_bitmap);
+
+/* True if the complement of the second intersects the first (their
+ AND_COMPL is non-empty). */
+extern bool bitmap_intersect_compl_p (const_bitmap, const_bitmap);
+
+/* True if MAP is an empty bitmap. */
+inline bool bitmap_empty_p (const_bitmap map)
+{
+ return !map->first;
+}
+
+/* True if the bitmap has only a single bit set. */
+extern bool bitmap_single_bit_set_p (const_bitmap);
+
+/* Count the number of bits set in the bitmap. */
+extern unsigned long bitmap_count_bits (const_bitmap);
+
+/* Count the number of unique bits set across the two bitmaps. */
+extern unsigned long bitmap_count_unique_bits (const_bitmap, const_bitmap);
+
+/* Boolean operations on bitmaps. The _into variants are two operand
+ versions that modify the first source operand. The other variants
+ are three operand versions that to not destroy the source bitmaps.
+ The operations supported are &, & ~, |, ^. */
+extern void bitmap_and (bitmap, const_bitmap, const_bitmap);
+extern bool bitmap_and_into (bitmap, const_bitmap);
+extern bool bitmap_and_compl (bitmap, const_bitmap, const_bitmap);
+extern bool bitmap_and_compl_into (bitmap, const_bitmap);
+#define bitmap_compl_and(DST, A, B) bitmap_and_compl (DST, B, A)
+extern void bitmap_compl_and_into (bitmap, const_bitmap);
+extern void bitmap_clear_range (bitmap, unsigned int, unsigned int);
+extern void bitmap_set_range (bitmap, unsigned int, unsigned int);
+extern bool bitmap_ior (bitmap, const_bitmap, const_bitmap);
+extern bool bitmap_ior_into (bitmap, const_bitmap);
+extern bool bitmap_ior_into_and_free (bitmap, bitmap *);
+extern void bitmap_xor (bitmap, const_bitmap, const_bitmap);
+extern void bitmap_xor_into (bitmap, const_bitmap);
+
+/* DST = A | (B & C). Return true if DST changes. */
+extern bool bitmap_ior_and_into (bitmap DST, const_bitmap B, const_bitmap C);
+/* DST = A | (B & ~C). Return true if DST changes. */
+extern bool bitmap_ior_and_compl (bitmap DST, const_bitmap A,
+ const_bitmap B, const_bitmap C);
+/* A |= (B & ~C). Return true if A changes. */
+extern bool bitmap_ior_and_compl_into (bitmap A,
+ const_bitmap B, const_bitmap C);
+
+/* Clear a single bit in a bitmap. Return true if the bit changed. */
+extern bool bitmap_clear_bit (bitmap, int);
+
+/* Set a single bit in a bitmap. Return true if the bit changed. */
+extern bool bitmap_set_bit (bitmap, int);
+
+/* Return true if a bit is set in a bitmap. */
+extern bool bitmap_bit_p (const_bitmap, int);
+
+/* Set and get multiple bit values in a sparse bitmap. This allows a bitmap to
+ function as a sparse array of bit patterns where the patterns are
+ multiples of power of 2. This is more efficient than performing this as
+ multiple individual operations. */
+void bitmap_set_aligned_chunk (bitmap, unsigned int, unsigned int, BITMAP_WORD);
+BITMAP_WORD bitmap_get_aligned_chunk (const_bitmap, unsigned int, unsigned int);
+
+/* Debug functions to print a bitmap. */
+extern void debug_bitmap (const_bitmap);
+extern void debug_bitmap_file (FILE *, const_bitmap);
+
+/* Print a bitmap. */
+extern void bitmap_print (FILE *, const_bitmap, const char *, const char *);
+
+/* Initialize and release a bitmap obstack. */
+extern void bitmap_obstack_initialize (bitmap_obstack *);
+extern void bitmap_obstack_release (bitmap_obstack *);
+extern void bitmap_register (bitmap MEM_STAT_DECL);
+extern void dump_bitmap_statistics (void);
+
+/* Initialize a bitmap header. OBSTACK indicates the bitmap obstack
+ to allocate from, NULL for GC'd bitmap. */
+
+static inline void
+bitmap_initialize (bitmap head, bitmap_obstack *obstack CXX_MEM_STAT_INFO)
+{
+ head->first = head->current = NULL;
+ head->indx = head->tree_form = 0;
+ head->padding = 0;
+ head->alloc_descriptor = 0;
+ head->obstack = obstack;
+ if (GATHER_STATISTICS)
+ bitmap_register (head PASS_MEM_STAT);
+}
+
+/* Release a bitmap (but not its head). This is suitable for pairing with
+ bitmap_initialize. */
+
+static inline void
+bitmap_release (bitmap head)
+{
+ bitmap_clear (head);
+ /* Poison the obstack pointer so the obstack can be safely released.
+ Do not zero it as the bitmap then becomes initialized GC. */
+ head->obstack = &bitmap_head::crashme;
+}
+
+/* Allocate and free bitmaps from obstack, malloc and gc'd memory. */
+extern bitmap bitmap_alloc (bitmap_obstack *obstack CXX_MEM_STAT_INFO);
+#define BITMAP_ALLOC bitmap_alloc
+extern bitmap bitmap_gc_alloc (ALONE_CXX_MEM_STAT_INFO);
+#define BITMAP_GGC_ALLOC bitmap_gc_alloc
+extern void bitmap_obstack_free (bitmap);
+
+/* A few compatibility/functions macros for compatibility with sbitmaps */
+inline void dump_bitmap (FILE *file, const_bitmap map)
+{
+ bitmap_print (file, map, "", "\n");
+}
+extern void debug (const bitmap_head &ref);
+extern void debug (const bitmap_head *ptr);
+
+extern unsigned bitmap_first_set_bit (const_bitmap);
+extern unsigned bitmap_last_set_bit (const_bitmap);
+
+/* Compute bitmap hash (for purposes of hashing etc.) */
+extern hashval_t bitmap_hash (const_bitmap);
+
+/* Do any cleanup needed on a bitmap when it is no longer used. */
+#define BITMAP_FREE(BITMAP) \
+ ((void) (bitmap_obstack_free ((bitmap) BITMAP), (BITMAP) = (bitmap) NULL))
+
+/* Iterator for bitmaps. */
+
+struct bitmap_iterator
+{
+ /* Pointer to the current bitmap element. */
+ bitmap_element *elt1;
+
+ /* Pointer to 2nd bitmap element when two are involved. */
+ bitmap_element *elt2;
+
+ /* Word within the current element. */
+ unsigned word_no;
+
+ /* Contents of the actually processed word. When finding next bit
+ it is shifted right, so that the actual bit is always the least
+ significant bit of ACTUAL. */
+ BITMAP_WORD bits;
+};
+
+/* Initialize a single bitmap iterator. START_BIT is the first bit to
+ iterate from. */
+
+static inline void
+bmp_iter_set_init (bitmap_iterator *bi, const_bitmap map,
+ unsigned start_bit, unsigned *bit_no)
+{
+ bi->elt1 = map->first;
+ bi->elt2 = NULL;
+
+ gcc_checking_assert (!map->tree_form);
+
+ /* Advance elt1 until it is not before the block containing start_bit. */
+ while (1)
+ {
+ if (!bi->elt1)
+ {
+ bi->elt1 = &bitmap_zero_bits;
+ break;
+ }
+
+ if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS)
+ break;
+ bi->elt1 = bi->elt1->next;
+ }
+
+ /* We might have gone past the start bit, so reinitialize it. */
+ if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS)
+ start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
+
+ /* Initialize for what is now start_bit. */
+ bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
+ bi->bits = bi->elt1->bits[bi->word_no];
+ bi->bits >>= start_bit % BITMAP_WORD_BITS;
+
+ /* If this word is zero, we must make sure we're not pointing at the
+ first bit, otherwise our incrementing to the next word boundary
+ will fail. It won't matter if this increment moves us into the
+ next word. */
+ start_bit += !bi->bits;
+
+ *bit_no = start_bit;
+}
+
+/* Initialize an iterator to iterate over the intersection of two
+ bitmaps. START_BIT is the bit to commence from. */
+
+static inline void
+bmp_iter_and_init (bitmap_iterator *bi, const_bitmap map1, const_bitmap map2,
+ unsigned start_bit, unsigned *bit_no)
+{
+ bi->elt1 = map1->first;
+ bi->elt2 = map2->first;
+
+ gcc_checking_assert (!map1->tree_form && !map2->tree_form);
+
+ /* Advance elt1 until it is not before the block containing
+ start_bit. */
+ while (1)
+ {
+ if (!bi->elt1)
+ {
+ bi->elt2 = NULL;
+ break;
+ }
+
+ if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS)
+ break;
+ bi->elt1 = bi->elt1->next;
+ }
+
+ /* Advance elt2 until it is not before elt1. */
+ while (1)
+ {
+ if (!bi->elt2)
+ {
+ bi->elt1 = bi->elt2 = &bitmap_zero_bits;
+ break;
+ }
+
+ if (bi->elt2->indx >= bi->elt1->indx)
+ break;
+ bi->elt2 = bi->elt2->next;
+ }
+
+ /* If we're at the same index, then we have some intersecting bits. */
+ if (bi->elt1->indx == bi->elt2->indx)
+ {
+ /* We might have advanced beyond the start_bit, so reinitialize
+ for that. */
+ if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS)
+ start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
+
+ bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
+ bi->bits = bi->elt1->bits[bi->word_no] & bi->elt2->bits[bi->word_no];
+ bi->bits >>= start_bit % BITMAP_WORD_BITS;
+ }
+ else
+ {
+ /* Otherwise we must immediately advance elt1, so initialize for
+ that. */
+ bi->word_no = BITMAP_ELEMENT_WORDS - 1;
+ bi->bits = 0;
+ }
+
+ /* If this word is zero, we must make sure we're not pointing at the
+ first bit, otherwise our incrementing to the next word boundary
+ will fail. It won't matter if this increment moves us into the
+ next word. */
+ start_bit += !bi->bits;
+
+ *bit_no = start_bit;
+}
+
+/* Initialize an iterator to iterate over the bits in MAP1 & ~MAP2. */
+
+static inline void
+bmp_iter_and_compl_init (bitmap_iterator *bi,
+ const_bitmap map1, const_bitmap map2,
+ unsigned start_bit, unsigned *bit_no)
+{
+ bi->elt1 = map1->first;
+ bi->elt2 = map2->first;
+
+ gcc_checking_assert (!map1->tree_form && !map2->tree_form);
+
+ /* Advance elt1 until it is not before the block containing start_bit. */
+ while (1)
+ {
+ if (!bi->elt1)
+ {
+ bi->elt1 = &bitmap_zero_bits;
+ break;
+ }
+
+ if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS)
+ break;
+ bi->elt1 = bi->elt1->next;
+ }
+
+ /* Advance elt2 until it is not before elt1. */
+ while (bi->elt2 && bi->elt2->indx < bi->elt1->indx)
+ bi->elt2 = bi->elt2->next;
+
+ /* We might have advanced beyond the start_bit, so reinitialize for
+ that. */
+ if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS)
+ start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
+
+ bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
+ bi->bits = bi->elt1->bits[bi->word_no];
+ if (bi->elt2 && bi->elt1->indx == bi->elt2->indx)
+ bi->bits &= ~bi->elt2->bits[bi->word_no];
+ bi->bits >>= start_bit % BITMAP_WORD_BITS;
+
+ /* If this word is zero, we must make sure we're not pointing at the
+ first bit, otherwise our incrementing to the next word boundary
+ will fail. It won't matter if this increment moves us into the
+ next word. */
+ start_bit += !bi->bits;
+
+ *bit_no = start_bit;
+}
+
+/* Advance to the next bit in BI. We don't advance to the next
+ nonzero bit yet. */
+
+static inline void
+bmp_iter_next (bitmap_iterator *bi, unsigned *bit_no)
+{
+ bi->bits >>= 1;
+ *bit_no += 1;
+}
+
+/* Advance to first set bit in BI. */
+
+static inline void
+bmp_iter_next_bit (bitmap_iterator * bi, unsigned *bit_no)
+{
+#if (GCC_VERSION >= 3004)
+ {
+ unsigned int n = __builtin_ctzl (bi->bits);
+ gcc_assert (sizeof (unsigned long) == sizeof (BITMAP_WORD));
+ bi->bits >>= n;
+ *bit_no += n;
+ }
+#else
+ while (!(bi->bits & 1))
+ {
+ bi->bits >>= 1;
+ *bit_no += 1;
+ }
+#endif
+}
+
+/* Advance to the next nonzero bit of a single bitmap, we will have
+ already advanced past the just iterated bit. Return true if there
+ is a bit to iterate. */
+
+static inline bool
+bmp_iter_set (bitmap_iterator *bi, unsigned *bit_no)
+{
+ /* If our current word is nonzero, it contains the bit we want. */
+ if (bi->bits)
+ {
+ next_bit:
+ bmp_iter_next_bit (bi, bit_no);
+ return true;
+ }
+
+ /* Round up to the word boundary. We might have just iterated past
+ the end of the last word, hence the -1. It is not possible for
+ bit_no to point at the beginning of the now last word. */
+ *bit_no = ((*bit_no + BITMAP_WORD_BITS - 1)
+ / BITMAP_WORD_BITS * BITMAP_WORD_BITS);
+ bi->word_no++;
+
+ while (1)
+ {
+ /* Find the next nonzero word in this elt. */
+ while (bi->word_no != BITMAP_ELEMENT_WORDS)
+ {
+ bi->bits = bi->elt1->bits[bi->word_no];
+ if (bi->bits)
+ goto next_bit;
+ *bit_no += BITMAP_WORD_BITS;
+ bi->word_no++;
+ }
+
+ /* Make sure we didn't remove the element while iterating. */
+ gcc_checking_assert (bi->elt1->indx != -1U);
+
+ /* Advance to the next element. */
+ bi->elt1 = bi->elt1->next;
+ if (!bi->elt1)
+ return false;
+ *bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
+ bi->word_no = 0;
+ }
+}
+
+/* Advance to the next nonzero bit of an intersecting pair of
+ bitmaps. We will have already advanced past the just iterated bit.
+ Return true if there is a bit to iterate. */
+
+static inline bool
+bmp_iter_and (bitmap_iterator *bi, unsigned *bit_no)
+{
+ /* If our current word is nonzero, it contains the bit we want. */
+ if (bi->bits)
+ {
+ next_bit:
+ bmp_iter_next_bit (bi, bit_no);
+ return true;
+ }
+
+ /* Round up to the word boundary. We might have just iterated past
+ the end of the last word, hence the -1. It is not possible for
+ bit_no to point at the beginning of the now last word. */
+ *bit_no = ((*bit_no + BITMAP_WORD_BITS - 1)
+ / BITMAP_WORD_BITS * BITMAP_WORD_BITS);
+ bi->word_no++;
+
+ while (1)
+ {
+ /* Find the next nonzero word in this elt. */
+ while (bi->word_no != BITMAP_ELEMENT_WORDS)
+ {
+ bi->bits = bi->elt1->bits[bi->word_no] & bi->elt2->bits[bi->word_no];
+ if (bi->bits)
+ goto next_bit;
+ *bit_no += BITMAP_WORD_BITS;
+ bi->word_no++;
+ }
+
+ /* Advance to the next identical element. */
+ do
+ {
+ /* Make sure we didn't remove the element while iterating. */
+ gcc_checking_assert (bi->elt1->indx != -1U);
+
+ /* Advance elt1 while it is less than elt2. We always want
+ to advance one elt. */
+ do
+ {
+ bi->elt1 = bi->elt1->next;
+ if (!bi->elt1)
+ return false;
+ }
+ while (bi->elt1->indx < bi->elt2->indx);
+
+ /* Make sure we didn't remove the element while iterating. */
+ gcc_checking_assert (bi->elt2->indx != -1U);
+
+ /* Advance elt2 to be no less than elt1. This might not
+ advance. */
+ while (bi->elt2->indx < bi->elt1->indx)
+ {
+ bi->elt2 = bi->elt2->next;
+ if (!bi->elt2)
+ return false;
+ }
+ }
+ while (bi->elt1->indx != bi->elt2->indx);
+
+ *bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
+ bi->word_no = 0;
+ }
+}
+
+/* Advance to the next nonzero bit in the intersection of
+ complemented bitmaps. We will have already advanced past the just
+ iterated bit. */
+
+static inline bool
+bmp_iter_and_compl (bitmap_iterator *bi, unsigned *bit_no)
+{
+ /* If our current word is nonzero, it contains the bit we want. */
+ if (bi->bits)
+ {
+ next_bit:
+ bmp_iter_next_bit (bi, bit_no);
+ return true;
+ }
+
+ /* Round up to the word boundary. We might have just iterated past
+ the end of the last word, hence the -1. It is not possible for
+ bit_no to point at the beginning of the now last word. */
+ *bit_no = ((*bit_no + BITMAP_WORD_BITS - 1)
+ / BITMAP_WORD_BITS * BITMAP_WORD_BITS);
+ bi->word_no++;
+
+ while (1)
+ {
+ /* Find the next nonzero word in this elt. */
+ while (bi->word_no != BITMAP_ELEMENT_WORDS)
+ {
+ bi->bits = bi->elt1->bits[bi->word_no];
+ if (bi->elt2 && bi->elt2->indx == bi->elt1->indx)
+ bi->bits &= ~bi->elt2->bits[bi->word_no];
+ if (bi->bits)
+ goto next_bit;
+ *bit_no += BITMAP_WORD_BITS;
+ bi->word_no++;
+ }
+
+ /* Make sure we didn't remove the element while iterating. */
+ gcc_checking_assert (bi->elt1->indx != -1U);
+
+ /* Advance to the next element of elt1. */
+ bi->elt1 = bi->elt1->next;
+ if (!bi->elt1)
+ return false;
+
+ /* Make sure we didn't remove the element while iterating. */
+ gcc_checking_assert (! bi->elt2 || bi->elt2->indx != -1U);
+
+ /* Advance elt2 until it is no less than elt1. */
+ while (bi->elt2 && bi->elt2->indx < bi->elt1->indx)
+ bi->elt2 = bi->elt2->next;
+
+ *bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
+ bi->word_no = 0;
+ }
+}
+
+/* If you are modifying a bitmap you are currently iterating over you
+ have to ensure to
+ - never remove the current bit;
+ - if you set or clear a bit before the current bit this operation
+ will not affect the set of bits you are visiting during the iteration;
+ - if you set or clear a bit after the current bit it is unspecified
+ whether that affects the set of bits you are visiting during the
+ iteration.
+ If you want to remove the current bit you can delay this to the next
+ iteration (and after the iteration in case the last iteration is
+ affected). */
+
+/* Loop over all bits set in BITMAP, starting with MIN and setting
+ BITNUM to the bit number. ITER is a bitmap iterator. BITNUM
+ should be treated as a read-only variable as it contains loop
+ state. */
+
+#ifndef EXECUTE_IF_SET_IN_BITMAP
+/* See sbitmap.h for the other definition of EXECUTE_IF_SET_IN_BITMAP. */
+#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, ITER) \
+ for (bmp_iter_set_init (&(ITER), (BITMAP), (MIN), &(BITNUM)); \
+ bmp_iter_set (&(ITER), &(BITNUM)); \
+ bmp_iter_next (&(ITER), &(BITNUM)))
+#endif
+
+/* Loop over all the bits set in BITMAP1 & BITMAP2, starting with MIN
+ and setting BITNUM to the bit number. ITER is a bitmap iterator.
+ BITNUM should be treated as a read-only variable as it contains
+ loop state. */
+
+#define EXECUTE_IF_AND_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, ITER) \
+ for (bmp_iter_and_init (&(ITER), (BITMAP1), (BITMAP2), (MIN), \
+ &(BITNUM)); \
+ bmp_iter_and (&(ITER), &(BITNUM)); \
+ bmp_iter_next (&(ITER), &(BITNUM)))
+
+/* Loop over all the bits set in BITMAP1 & ~BITMAP2, starting with MIN
+ and setting BITNUM to the bit number. ITER is a bitmap iterator.
+ BITNUM should be treated as a read-only variable as it contains
+ loop state. */
+
+#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, ITER) \
+ for (bmp_iter_and_compl_init (&(ITER), (BITMAP1), (BITMAP2), (MIN), \
+ &(BITNUM)); \
+ bmp_iter_and_compl (&(ITER), &(BITNUM)); \
+ bmp_iter_next (&(ITER), &(BITNUM)))
+
+/* A class that ties the lifetime of a bitmap to its scope. */
+class auto_bitmap
+{
+ public:
+ auto_bitmap (ALONE_CXX_MEM_STAT_INFO)
+ { bitmap_initialize (&m_bits, &bitmap_default_obstack PASS_MEM_STAT); }
+ explicit auto_bitmap (bitmap_obstack *o CXX_MEM_STAT_INFO)
+ { bitmap_initialize (&m_bits, o PASS_MEM_STAT); }
+ ~auto_bitmap () { bitmap_clear (&m_bits); }
+ // Allow calling bitmap functions on our bitmap.
+ operator bitmap () { return &m_bits; }
+
+ private:
+ // Prevent making a copy that references our bitmap.
+ auto_bitmap (const auto_bitmap &);
+ auto_bitmap &operator = (const auto_bitmap &);
+ auto_bitmap (auto_bitmap &&);
+ auto_bitmap &operator = (auto_bitmap &&);
+
+ bitmap_head m_bits;
+};
+
+extern void debug (const auto_bitmap &ref);
+extern void debug (const auto_bitmap *ptr);
+
+/* Base class for bitmap_view; see there for details. */
+template<typename T, typename Traits = array_traits<T> >
+class base_bitmap_view
+{
+public:
+ typedef typename Traits::element_type array_element_type;
+
+ base_bitmap_view (const T &, bitmap_element *);
+ operator const_bitmap () const { return &m_head; }
+
+private:
+ base_bitmap_view (const base_bitmap_view &);
+
+ bitmap_head m_head;
+};
+
+/* Provides a read-only bitmap view of a single integer bitmask or a
+ constant-sized array of integer bitmasks, or of a wrapper around such
+ bitmasks. */
+template<typename T, typename Traits>
+class bitmap_view<T, Traits, true> : public base_bitmap_view<T, Traits>
+{
+public:
+ bitmap_view (const T &array)
+ : base_bitmap_view<T, Traits> (array, m_bitmap_elements) {}
+
+private:
+ /* How many bitmap_elements we need to hold a full T. */
+ static const size_t num_bitmap_elements
+ = CEIL (CHAR_BIT
+ * sizeof (typename Traits::element_type)
+ * Traits::constant_size,
+ BITMAP_ELEMENT_ALL_BITS);
+ bitmap_element m_bitmap_elements[num_bitmap_elements];
+};
+
+/* Initialize the view for array ARRAY, using the array of bitmap
+ elements in BITMAP_ELEMENTS (which is known to contain enough
+ entries). */
+template<typename T, typename Traits>
+base_bitmap_view<T, Traits>::base_bitmap_view (const T &array,
+ bitmap_element *bitmap_elements)
+{
+ m_head.obstack = NULL;
+
+ /* The code currently assumes that each element of ARRAY corresponds
+ to exactly one bitmap_element. */
+ const size_t array_element_bits = CHAR_BIT * sizeof (array_element_type);
+ STATIC_ASSERT (BITMAP_ELEMENT_ALL_BITS % array_element_bits == 0);
+ size_t array_step = BITMAP_ELEMENT_ALL_BITS / array_element_bits;
+ size_t array_size = Traits::size (array);
+
+ /* Process each potential bitmap_element in turn. The loop is written
+ this way rather than per array element because usually there are
+ only a small number of array elements per bitmap element (typically
+ two or four). The inner loops should therefore unroll completely. */
+ const array_element_type *array_elements = Traits::base (array);
+ unsigned int indx = 0;
+ for (size_t array_base = 0;
+ array_base < array_size;
+ array_base += array_step, indx += 1)
+ {
+ /* How many array elements are in this particular bitmap_element. */
+ unsigned int array_count
+ = (STATIC_CONSTANT_P (array_size % array_step == 0)
+ ? array_step : MIN (array_step, array_size - array_base));
+
+ /* See whether we need this bitmap element. */
+ array_element_type ior = array_elements[array_base];
+ for (size_t i = 1; i < array_count; ++i)
+ ior |= array_elements[array_base + i];
+ if (ior == 0)
+ continue;
+
+ /* Grab the next bitmap element and chain it. */
+ bitmap_element *bitmap_element = bitmap_elements++;
+ if (m_head.current)
+ m_head.current->next = bitmap_element;
+ else
+ m_head.first = bitmap_element;
+ bitmap_element->prev = m_head.current;
+ bitmap_element->next = NULL;
+ bitmap_element->indx = indx;
+ m_head.current = bitmap_element;
+ m_head.indx = indx;
+
+ /* Fill in the bits of the bitmap element. */
+ if (array_element_bits < BITMAP_WORD_BITS)
+ {
+ /* Multiple array elements fit in one element of
+ bitmap_element->bits. */
+ size_t array_i = array_base;
+ for (unsigned int word_i = 0; word_i < BITMAP_ELEMENT_WORDS;
+ ++word_i)
+ {
+ BITMAP_WORD word = 0;
+ for (unsigned int shift = 0;
+ shift < BITMAP_WORD_BITS && array_i < array_size;
+ shift += array_element_bits)
+ word |= array_elements[array_i++] << shift;
+ bitmap_element->bits[word_i] = word;
+ }
+ }
+ else
+ {
+ /* Array elements are the same size as elements of
+ bitmap_element->bits, or are an exact multiple of that size. */
+ unsigned int word_i = 0;
+ for (unsigned int i = 0; i < array_count; ++i)
+ for (unsigned int shift = 0; shift < array_element_bits;
+ shift += BITMAP_WORD_BITS)
+ bitmap_element->bits[word_i++]
+ = array_elements[array_base + i] >> shift;
+ while (word_i < BITMAP_ELEMENT_WORDS)
+ bitmap_element->bits[word_i++] = 0;
+ }
+ }
+}
+
+#endif /* GCC_BITMAP_H */
diff --git a/support/cpp/gcc/builtin-attrs.def b/support/cpp/gcc/builtin-attrs.def
new file mode 100644
index 000000000..f03dfecc1
--- /dev/null
+++ b/support/cpp/gcc/builtin-attrs.def
@@ -0,0 +1,427 @@
+/* Copyright (C) 2001-2022 Free Software Foundation, Inc.
+ Contributed by Joseph Myers <jsm28@cam.ac.uk>.
+
+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 header provides a declarative way of describing the attributes
+ that are applied to some built-in functions by default. Attributes
+ that are meant to be used by user-defined functions but aren't used
+ by any built-ins, or attributes that apply to types or variables
+ but not to functions need not and should not be defined here.
+
+ Before including this header, you must define the following macros.
+ In each case where there is an ENUM, it is an identifier used to
+ reference the tree in subsequent definitions.
+
+ DEF_ATTR_NULL_TREE (ENUM)
+
+ Constructs a NULL_TREE.
+
+ DEF_ATTR_INT (ENUM, VALUE)
+
+ Constructs an INTEGER_CST with value VALUE (an integer representable
+ in HOST_WIDE_INT).
+
+ DEF_ATTR_IDENT (ENUM, STRING)
+
+ Constructs an IDENTIFIER_NODE for STRING.
+
+ DEF_ATTR_TREE_LIST (ENUM, PURPOSE, VALUE, CHAIN)
+
+ Constructs a TREE_LIST with given PURPOSE, VALUE and CHAIN (given
+ as previous ENUM names). */
+
+DEF_ATTR_NULL_TREE (ATTR_NULL)
+
+/* Construct a tree for a given integer and a list containing it. */
+#define DEF_ATTR_FOR_INT(VALUE) \
+ DEF_ATTR_INT (ATTR_##VALUE, VALUE) \
+ DEF_ATTR_TREE_LIST (ATTR_LIST_##VALUE, ATTR_NULL, \
+ ATTR_##VALUE, ATTR_NULL)
+DEF_ATTR_FOR_INT (0)
+DEF_ATTR_FOR_INT (1)
+DEF_ATTR_FOR_INT (2)
+DEF_ATTR_FOR_INT (3)
+DEF_ATTR_FOR_INT (4)
+DEF_ATTR_FOR_INT (5)
+DEF_ATTR_FOR_INT (6)
+#undef DEF_ATTR_FOR_INT
+
+/* Construct a tree for a given string and a list containing it. */
+#define DEF_ATTR_FOR_STRING(ENUM, VALUE) \
+ DEF_ATTR_STRING (ATTR_##ENUM, VALUE) \
+ DEF_ATTR_TREE_LIST (ATTR_LIST_##ENUM, ATTR_NULL, \
+ ATTR_##ENUM, ATTR_NULL)
+DEF_ATTR_FOR_STRING (STR1, "1 ")
+DEF_ATTR_FOR_STRING (STRERRNOC, ".C")
+DEF_ATTR_FOR_STRING (STRERRNOP, ".P")
+#undef DEF_ATTR_FOR_STRING
+
+/* Construct a tree for a list of two integers. */
+#define DEF_LIST_INT_INT(VALUE1, VALUE2) \
+ DEF_ATTR_TREE_LIST (ATTR_LIST_##VALUE1##_##VALUE2, ATTR_NULL, \
+ ATTR_##VALUE1, ATTR_LIST_##VALUE2)
+DEF_LIST_INT_INT (1,0)
+DEF_LIST_INT_INT (1,2)
+DEF_LIST_INT_INT (1,3)
+DEF_LIST_INT_INT (1,4)
+DEF_LIST_INT_INT (1,5)
+DEF_LIST_INT_INT (2,0)
+DEF_LIST_INT_INT (2,3)
+DEF_LIST_INT_INT (3,0)
+DEF_LIST_INT_INT (3,4)
+DEF_LIST_INT_INT (4,0)
+DEF_LIST_INT_INT (4,5)
+DEF_LIST_INT_INT (5,0)
+DEF_LIST_INT_INT (5,6)
+#undef DEF_LIST_INT_INT
+
+/* Construct trees for identifiers used in built-in function attributes.
+ The construction contributes to startup costs so only attributes that
+ are used to define built-ins should be defined here. */
+DEF_ATTR_IDENT (ATTR_ALLOC_SIZE, "alloc_size")
+DEF_ATTR_IDENT (ATTR_COLD, "cold")
+DEF_ATTR_IDENT (ATTR_CONST, "const")
+DEF_ATTR_IDENT (ATTR_FORMAT, "format")
+DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg")
+DEF_ATTR_IDENT (ATTR_MALLOC, "malloc")
+DEF_ATTR_IDENT (ATTR_NONNULL, "nonnull")
+DEF_ATTR_IDENT (ATTR_NORETURN, "noreturn")
+DEF_ATTR_IDENT (ATTR_NOTHROW, "nothrow")
+DEF_ATTR_IDENT (ATTR_LEAF, "leaf")
+DEF_ATTR_IDENT (ATTR_FNSPEC, "fn spec")
+DEF_ATTR_IDENT (ATTR_PRINTF, "printf")
+DEF_ATTR_IDENT (ATTR_ASM_FPRINTF, "asm_fprintf")
+DEF_ATTR_IDENT (ATTR_GCC_DIAG, "gcc_diag")
+DEF_ATTR_IDENT (ATTR_GCC_CDIAG, "gcc_cdiag")
+DEF_ATTR_IDENT (ATTR_GCC_CXXDIAG, "gcc_cxxdiag")
+DEF_ATTR_IDENT (ATTR_PURE, "pure")
+DEF_ATTR_IDENT (ATTR_NOVOPS, "no vops")
+DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
+DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
+DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
+DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
+DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic")
+DEF_ATTR_IDENT (ATTR_TM_REGPARM, "*tm regparm")
+DEF_ATTR_IDENT (ATTR_TM_TMPURE, "transaction_pure")
+DEF_ATTR_IDENT (ATTR_RETURNS_TWICE, "returns_twice")
+DEF_ATTR_IDENT (ATTR_RETURNS_NONNULL, "returns_nonnull")
+DEF_ATTR_IDENT (ATTR_WARN_UNUSED_RESULT, "warn_unused_result")
+
+DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
+
+DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NOVOPS_LIST)
+
+DEF_ATTR_TREE_LIST (ATTR_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NULL)
+
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL)
+
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NOTHROW_LIST)
+
+DEF_ATTR_TREE_LIST (ATTR_NOVOPS_NOTHROW_LEAF_LIST, ATTR_NOVOPS, \
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LEAF_LIST, ATTR_CONST, \
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ERRNOCONST_NOTHROW_LEAF_LIST, ATTR_FNSPEC,\
+ ATTR_LIST_STRERRNOC, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ERRNOPURE_NOTHROW_LEAF_LIST, ATTR_FNSPEC,\
+ ATTR_LIST_STRERRNOP, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LIST, ATTR_PURE, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LEAF_LIST, ATTR_PURE, \
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LIST, ATTR_NORETURN, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LEAF_LIST, ATTR_NORETURN,\
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LEAF_COLD_LIST, ATTR_COLD,\
+ ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_RT_NOTHROW_LEAF_LIST, ATTR_RETURNS_TWICE,\
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_COLD_NOTHROW_LEAF_LIST, ATTR_COLD,\
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST, ATTR_COLD,\
+ ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST, ATTR_CONST,\
+ ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST, ATTR_COLD,\
+ ATTR_NULL, ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST, ATTR_WARN_UNUSED_RESULT, \
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST, ATTR_MALLOC, \
+ ATTR_NULL, ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL, \
+ ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LEAF_LIST, ATTR_SENTINEL, \
+ ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST, ATTR_CONST,\
+ ATTR_NULL, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+
+/* Allocation functions like malloc and realloc whose first argument
+ with _SIZE_1, or second argument with _SIZE_2, specifies the size
+ of the allocated object. */
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_SIZE_1_NOTHROW_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_1, ATTR_MALLOC_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LIST, ATTR_WARN_UNUSED_RESULT, \
+ ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_2, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_1, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
+/* Alloca is just like malloc except that it never returns null. */
+DEF_ATTR_TREE_LIST (ATTR_ALLOCA_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST, ATTR_RETURNS_NONNULL,
+ ATTR_NULL, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST)
+
+/* Allocation functions like calloc the product of whose first two arguments
+ specifies the size of the allocated object. */
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_1_2, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
+
+/* Allocation functions like realloc whose second argument specifies
+ the size of the allocated object. */
+DEF_ATTR_TREE_LIST (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST, ATTR_ALLOC_SIZE, \
+ ATTR_LIST_2, ATTR_WARN_UNUSED_RESULT_NOTHROW_LEAF_LIST)
+
+/* Functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_LIST, ATTR_NONNULL, ATTR_NULL, ATTR_NULL)
+/* Functions whose first parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
+/* Functions whose second parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, ATTR_NULL)
+/* Functions whose third parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, ATTR_NULL)
+/* Nothrow functions with the sentinel(1) attribute. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_SENTINEL_1, ATTR_SENTINEL, ATTR_LIST_1, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL, ATTR_NONNULL, ATTR_NULL, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow leaf functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_LEAF, ATTR_NONNULL, ATTR_NULL, \
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_LEAF_LIST, ATTR_LEAF, ATTR_NULL, ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow functions whose first parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions whose second parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions whose third parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions whose fourth parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_4, ATTR_NONNULL, ATTR_LIST_4, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions whose fifth parameter is a nonnull pointer. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_5, ATTR_NONNULL, ATTR_LIST_5, \
+ ATTR_NOTHROW_LIST)
+
+/* Same as ATTR_NONNULL_1. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
+/* Functions like {v,}fprintf whose first and second parameters are
+ nonnull pointers. As cancellation points the functions are not
+ nothrow. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_1_2, ATTR_NULL)
+/* The following don't have {v,}fprintf forms. They exist only to
+ make it possible to declare {v,}{f,s}printf attributes using
+ the same macro. */
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_3, ATTR_NONNULL, ATTR_LIST_1_3, ATTR_NULL)
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_1_4, ATTR_NULL)
+DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_5, ATTR_NONNULL, ATTR_LIST_1_5, ATTR_NULL)
+
+/* Same as ATTR_NOTHROW_NONNULL_1. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_1, ATTR_NONNULL, ATTR_LIST_1,
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions like {v,}sprintf whose first and second parameters
+ are nonnull pointers. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_1_2, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions like {v,}snprintf whose first and third parameters
+ are nonnull pointers. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_3, ATTR_NONNULL, ATTR_LIST_1_3, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions like {v,}sprintf_chk whose first and fourth parameters
+ are nonnull pointers. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_1_4, \
+ ATTR_NOTHROW_LIST)
+/* Nothrow functions like {v,}snprintf_chk whose first and fifth parameters
+ are nonnull pointers. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_5, ATTR_NONNULL, ATTR_LIST_1_5, \
+ ATTR_NOTHROW_LIST)
+
+/* Nothrow leaf functions which are type-generic. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_TYPEGENERIC_LEAF, ATTR_TYPEGENERIC, ATTR_NULL, \
+ ATTR_NOTHROW_LEAF_LIST)
+/* Nothrow nonnull leaf functions that are type-generic. */
+DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF,
+ ATTR_TYPEGENERIC, ATTR_NULL,
+ ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow const functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL, ATTR_CONST, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL)
+/* Nothrow leaf functions whose pointer parameter(s) are all nonnull,
+ and which return their first argument. */
+DEF_ATTR_TREE_LIST (ATTR_RET1_NOTHROW_NONNULL_LEAF, ATTR_FNSPEC, ATTR_LIST_STR1, \
+ ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow leaf functions whose pointer parameter(s) are all nonnull,
+ and return value is also nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_RETNONNULL_NOTHROW_LEAF, ATTR_RETURNS_NONNULL, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow const leaf functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL_LEAF, ATTR_CONST, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow const functions which are type-generic. */
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_TYPEGENERIC, ATTR_TYPEGENERIC, ATTR_NULL, \
+ ATTR_CONST_NOTHROW_LIST)
+/* Nothrow const leaf functions which are type-generic. */
+DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF, ATTR_TYPEGENERIC, ATTR_NULL, \
+ ATTR_CONST_NOTHROW_LEAF_LIST)
+/* Nothrow pure functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL, ATTR_PURE, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL)
+/* Nothrow pure leaf functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_LEAF, ATTR_PURE, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL_LEAF)
+/* Nothrow malloc functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL, ATTR_WARN_UNUSED_RESULT, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL, ATTR_MALLOC, ATTR_NULL, \
+ ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL)
+/* Nothrow malloc leaf functions whose pointer parameter(s) are all nonnull. */
+DEF_ATTR_TREE_LIST (ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF, ATTR_WARN_UNUSED_RESULT, ATTR_NULL, \
+ ATTR_NOTHROW_NONNULL_LEAF)
+DEF_ATTR_TREE_LIST (ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF, ATTR_MALLOC, ATTR_NULL, \
+ ATTR_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+
+/* Construct a tree for the format attribute (and implicitly nonnull). */
+#define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL, \
+ ATTR_##TYPE, ATTR_LIST_##VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_##VALUES, ATTR_FORMAT, \
+ ATTR_##TYPE##_##VALUES, ATTR_NONNULL_##FA)
+
+/* Construct a tree for the format and nothrow attributes (format
+ implies nonnull). */
+#define DEF_FORMAT_ATTRIBUTE_NOTHROW(TYPE, FA, VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL, \
+ ATTR_##TYPE, ATTR_LIST_##VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_NOTHROW_##VALUES, ATTR_FORMAT,\
+ ATTR_##TYPE##_##VALUES, ATTR_NOTHROW_NONNULL_##FA)
+
+/* Construct one tree for the format attribute and another for the format
+ and nothrow attributes (in both cases format implies nonnull). */
+#define DEF_FORMAT_ATTRIBUTE_BOTH(TYPE, FA, VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_##TYPE##_##VALUES, ATTR_NULL, \
+ ATTR_##TYPE, ATTR_LIST_##VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_##VALUES, ATTR_FORMAT, \
+ ATTR_##TYPE##_##VALUES, ATTR_NONNULL_##FA) \
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_##TYPE##_NOTHROW_##VALUES, ATTR_FORMAT,\
+ ATTR_##TYPE##_##VALUES, ATTR_NOTHROW_NONNULL_##FA)
+
+/* Construct a pair of trees for the nonnull attribute for the first
+ argument, plus format printf attribute (format implies nonnull):
+ the first ordinary and the second nothrow. */
+#define DEF_FORMAT_ATTRIBUTE_NONNULL(TYPE, FA, VALUES) \
+ DEF_ATTR_TREE_LIST (ATTR_NONNULL_1_FORMAT_##TYPE##_##VALUES, \
+ ATTR_FORMAT, ATTR_##TYPE##_##VALUES, \
+ ATTR_NONNULL_1_##FA) \
+ DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_FORMAT_##TYPE##_##VALUES, \
+ ATTR_FORMAT, ATTR_##TYPE##_##VALUES, \
+ ATTR_NOTHROW_NONNULL_1_##FA)
+
+DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_0)
+DEF_FORMAT_ATTRIBUTE(PRINTF,1,1_2)
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,2,2_0)
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,2,2_3)
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,3,3_0)
+DEF_FORMAT_ATTRIBUTE_BOTH(PRINTF,3,3_4)
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,4,4_0)
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,4,4_5)
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,5,5_0)
+DEF_FORMAT_ATTRIBUTE_NOTHROW(PRINTF,5,5_6)
+
+/* Attributes for fprintf(f, f, va). */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,1,1_2)
+/* Attributes for v{f,s}printf(d, f, va). vsprintf is nothrow, vfprintf
+ is not. */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,2,2_0)
+/* Attributes for {f,s}printf(d, f, ...). sprintf is nothrow, fprintf
+ is not. */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,2,2_3)
+/* Attributes for vprintf_chk. */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,3,3_0)
+/* Attributes for printf_chk. */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,3,3_4)
+/* Attributes for v{f,s}printf_chk(d, t, bos, f, va). vsprintf_chk is
+ nothrow, vfprintf_chk is not. */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,4,4_0)
+/* Attributes for {f,s}printf_chk(d, t, bos, f, ...). sprintf_chk is
+ nothrow, fprintf_chk is not. */
+DEF_FORMAT_ATTRIBUTE_NONNULL(PRINTF,4,4_5)
+
+DEF_FORMAT_ATTRIBUTE(SCANF,1,1_0)
+DEF_FORMAT_ATTRIBUTE(SCANF,1,1_2)
+DEF_FORMAT_ATTRIBUTE_BOTH(SCANF,2,2_0)
+DEF_FORMAT_ATTRIBUTE_BOTH(SCANF,2,2_3)
+DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFTIME,3,3_0)
+DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3_4)
+#undef DEF_FORMAT_ATTRIBUTE
+#undef DEF_FORMAT_ATTRIBUTE_NOTHROW
+#undef DEF_FORMAT_ATTRIBUTE_BOTH
+
+/* Transactional memory variants of the above. */
+
+DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_TMPURE_NOTHROW_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_TM_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_PURE_TMPURE_NOTHROW_LIST,
+ ATTR_PURE, ATTR_NULL, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_NORETURN_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_NORETURN_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_CONST_NOTHROW_LIST,
+ ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_RT_LIST,
+ ATTR_RETURNS_TWICE, ATTR_NULL, ATTR_TM_NOTHROW_LIST)
+
+/* Same attributes used for BUILT_IN_MALLOC except with TM_PURE thrown in. */
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_NOTHROW_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST)
+/* Same attributes used for BUILT_IN_FREE except with TM_PURE thrown in. */
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LIST)
+
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LEAF_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST,
+ ATTR_TM_TMPURE, ATTR_NULL, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_ATTR_TREE_LIST (ATTR_TMPURE_NORETURN_NOTHROW_LEAF_COLD_LIST,
+ ATTR_COLD, ATTR_NULL,
+ ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+
+/* Construct a tree for a format_arg attribute. */
+#define DEF_FORMAT_ARG_ATTRIBUTE(FA) \
+ DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG, \
+ ATTR_LIST_##FA, ATTR_NOTHROW_NONNULL_##FA)
+DEF_FORMAT_ARG_ATTRIBUTE(1)
+DEF_FORMAT_ARG_ATTRIBUTE(2)
+#undef DEF_FORMAT_ARG_ATTRIBUTE
+
diff --git a/support/cpp/gcc/builtin-types.def b/support/cpp/gcc/builtin-types.def
new file mode 100644
index 000000000..3a7cecdf0
--- /dev/null
+++ b/support/cpp/gcc/builtin-types.def
@@ -0,0 +1,874 @@
+/* Copyright (C) 2001-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 header provides a declarative way of describing the types that
+ are used when declaring builtin functions.
+
+ Before including this header, you must define the following macros:
+
+ DEF_PRIMITIVE_TYPE (ENUM, TYPE)
+
+ The ENUM is an identifier indicating which type is being defined.
+ TYPE is an expression for a `tree' that represents the type.
+
+ DEF_FUNCTION_TYPE_0 (ENUM, RETURN)
+ DEF_FUNCTION_TYPE_1 (ENUM, RETURN, ARG1)
+ DEF_FUNCTION_TYPE_2 (ENUM, RETURN, ARG1, ARG2)
+ [...]
+
+ These macros describe function types. ENUM is as above. The
+ RETURN type is one of the enumerals already defined. ARG1, ARG2,
+ etc, give the types of the arguments, similarly.
+
+ DEF_FUNCTION_TYPE_VAR_0 (ENUM, RETURN)
+ DEF_FUNCTION_TYPE_VAR_1 (ENUM, RETURN, ARG1)
+ DEF_FUNCTION_TYPE_VAR_2 (ENUM, RETURN, ARG1, ARG2)
+ [...]
+
+ Similar, but for function types that take variable arguments.
+ For example:
+
+ DEF_FUNCTION_TYPE_1 (BT_INT_DOUBLE, BT_INT, BT_DOUBLE)
+
+ describes the type `int ()(double)', using the enumeral
+ BT_INT_DOUBLE, whereas:
+
+ DEF_FUNCTION_TYPE_VAR_1 (BT_INT_DOUBLE_VAR, BT_INT, BT_DOUBLE)
+
+ describes the type `int ()(double, ...)'.
+
+ DEF_POINTER_TYPE (ENUM, TYPE)
+
+ This macro describes a pointer type. ENUM is as above; TYPE is
+ the type pointed to. */
+
+DEF_PRIMITIVE_TYPE (BT_VOID, void_type_node)
+DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_type_node)
+DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
+DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
+DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
+DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
+DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
+DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
+DEF_PRIMITIVE_TYPE (BT_INT8, signed_char_type_node)
+DEF_PRIMITIVE_TYPE (BT_INT16, short_integer_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT8, unsigned_char_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT16, uint16_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT32, uint32_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT64, uint64_type_node)
+DEF_PRIMITIVE_TYPE (BT_UINT128, uint128_type_node
+ ? uint128_type_node
+ : error_mark_node)
+DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 1))
+DEF_PRIMITIVE_TYPE (BT_UNWINDWORD, (*lang_hooks.types.type_for_mode)
+ (targetm.unwind_word_mode (), 1))
+DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node)
+DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node)
+DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE, long_double_type_node)
+DEF_PRIMITIVE_TYPE (BT_FLOAT16, (float16_type_node
+ ? float16_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT32, (float32_type_node
+ ? float32_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT64, (float64_type_node
+ ? float64_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT128, (float128_type_node
+ ? float128_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT32X, (float32x_type_node
+ ? float32x_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT64X, (float64x_type_node
+ ? float64x_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_FLOAT128X, (float128x_type_node
+ ? float128x_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT, complex_float_type_node)
+DEF_PRIMITIVE_TYPE (BT_COMPLEX_DOUBLE, complex_double_type_node)
+DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONGDOUBLE, complex_long_double_type_node)
+
+DEF_PRIMITIVE_TYPE (BT_PTR, ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_FILEPTR, fileptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_TM_PTR, const_tm_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_FENV_T_PTR, fenv_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_FENV_T_PTR, const_fenv_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_FEXCEPT_T_PTR, fexcept_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_FEXCEPT_T_PTR, const_fexcept_t_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_PTR, const_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_VOLATILE_PTR,
+ build_pointer_type
+ (build_qualified_type (void_type_node,
+ TYPE_QUAL_VOLATILE)))
+DEF_PRIMITIVE_TYPE (BT_CONST_VOLATILE_PTR,
+ build_pointer_type
+ (build_qualified_type (void_type_node,
+ TYPE_QUAL_VOLATILE|TYPE_QUAL_CONST)))
+DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
+DEF_PRIMITIVE_TYPE (BT_INT_PTR, integer_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_FLOAT_PTR, float_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_DOUBLE_PTR, double_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_DOUBLE_PTR,
+ build_pointer_type
+ (build_qualified_type (double_type_node,
+ TYPE_QUAL_CONST)))
+DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE_PTR, long_double_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_PID, pid_type_node)
+DEF_PRIMITIVE_TYPE (BT_SIZE, size_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_SIZE,
+ build_qualified_type (size_type_node, TYPE_QUAL_CONST))
+DEF_PRIMITIVE_TYPE (BT_SSIZE, signed_size_type_node)
+DEF_PRIMITIVE_TYPE (BT_WINT, wint_type_node)
+DEF_PRIMITIVE_TYPE (BT_STRING, string_type_node)
+DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node)
+
+DEF_PRIMITIVE_TYPE (BT_DFLOAT32, (dfloat32_type_node
+ ? dfloat32_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_DFLOAT64, (dfloat64_type_node
+ ? dfloat64_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_DFLOAT128, (dfloat128_type_node
+ ? dfloat128_type_node
+ : error_mark_node))
+
+DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node)
+DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
+
+DEF_PRIMITIVE_TYPE (BT_I1, builtin_type_for_size (BITS_PER_UNIT*1, 1))
+DEF_PRIMITIVE_TYPE (BT_I2, builtin_type_for_size (BITS_PER_UNIT*2, 1))
+DEF_PRIMITIVE_TYPE (BT_I4, builtin_type_for_size (BITS_PER_UNIT*4, 1))
+DEF_PRIMITIVE_TYPE (BT_I8, builtin_type_for_size (BITS_PER_UNIT*8, 1))
+DEF_PRIMITIVE_TYPE (BT_I16, builtin_type_for_size (BITS_PER_UNIT*16, 1))
+
+/* The C type `char * const *'. */
+DEF_PRIMITIVE_TYPE (BT_PTR_CONST_STRING,
+ build_pointer_type
+ (build_qualified_type (string_type_node,
+ TYPE_QUAL_CONST)))
+
+DEF_POINTER_TYPE (BT_PTR_UINT, BT_UINT)
+DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
+DEF_POINTER_TYPE (BT_PTR_ULONG, BT_ULONG)
+DEF_POINTER_TYPE (BT_PTR_LONGLONG, BT_LONGLONG)
+DEF_POINTER_TYPE (BT_PTR_ULONGLONG, BT_ULONGLONG)
+DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
+
+DEF_FUNCTION_TYPE_0 (BT_FN_VOID, BT_VOID)
+DEF_FUNCTION_TYPE_0 (BT_FN_BOOL, BT_BOOL)
+DEF_FUNCTION_TYPE_0 (BT_FN_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_0 (BT_FN_CONST_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_0 (BT_FN_PID, BT_PID)
+DEF_FUNCTION_TYPE_0 (BT_FN_INT, BT_INT)
+DEF_FUNCTION_TYPE_0 (BT_FN_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_0 (BT_FN_ULONG, BT_ULONG)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE)
+/* For "long double" we use LONGDOUBLE (not LONG_DOUBLE) to
+ distinguish it from two types in sequence, "long" followed by
+ "double". */
+DEF_FUNCTION_TYPE_0 (BT_FN_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT128X, BT_FLOAT128X)
+DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT32, BT_DFLOAT32)
+DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT64, BT_DFLOAT64)
+DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT128, BT_DFLOAT128)
+
+DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONG, BT_LONG, BT_LONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGLONG, BT_LONGLONG, BT_LONGLONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_INTMAX_INTMAX, BT_INTMAX, BT_INTMAX)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_FLOAT, BT_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_DOUBLE, BT_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_LONGDOUBLE,
+ BT_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT16_FLOAT16, BT_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32_FLOAT32, BT_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64_FLOAT64, BT_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128_FLOAT128, BT_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32X_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64X_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128X_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT,
+ BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
+ BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE,
+ BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_COMPLEX_FLOAT,
+ BT_FLOAT, BT_COMPLEX_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_COMPLEX_DOUBLE,
+ BT_DOUBLE, BT_COMPLEX_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE,
+ BT_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_FLOAT,
+ BT_COMPLEX_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_DOUBLE,
+ BT_COMPLEX_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE,
+ BT_COMPLEX_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_PTR_UINT, BT_PTR, BT_UINT)
+DEF_FUNCTION_TYPE_1 (BT_FN_PTR_SIZE, BT_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_INT, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_UINT, BT_INT, BT_UINT)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONG, BT_INT, BT_LONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_ULONG, BT_INT, BT_ULONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONGLONG, BT_INT, BT_LONGLONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_ULONGLONG, BT_INT, BT_ULONGLONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_INTMAX, BT_INT, BT_INTMAX)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_UINTMAX, BT_INT, BT_UINTMAX)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_PTR, BT_INT, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT, BT_INT, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_DOUBLE, BT_INT, BT_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONGDOUBLE, BT_INT, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT32, BT_INT, BT_DFLOAT32)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT64, BT_INT, BT_DFLOAT64)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT128, BT_INT, BT_DFLOAT128)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT, BT_LONG, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONG_DOUBLE, BT_LONG, BT_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONGDOUBLE, BT_LONG, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_FLOAT, BT_LONGLONG, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_DOUBLE, BT_LONGLONG, BT_DOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGDOUBLE, BT_LONGLONG, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTR, BT_VOID, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_SIZE_CONST_STRING, BT_SIZE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_CONST_STRING, BT_INT, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VALIST_REF, BT_VOID, BT_VALIST_REF)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_BOOL, BT_VOID, BT_BOOL)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_CONST_STRING,
+ BT_LONGDOUBLE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT16_CONST_STRING, BT_FLOAT16, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32_CONST_STRING, BT_FLOAT32, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64_CONST_STRING, BT_FLOAT64, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128_CONST_STRING, BT_FLOAT128, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT32X_CONST_STRING, BT_FLOAT32X, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT64X_CONST_STRING, BT_FLOAT64X, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT128X_CONST_STRING, BT_FLOAT128X, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_CONST_STRING, BT_DFLOAT32, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_CONST_STRING, BT_DFLOAT64, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING,
+ BT_DFLOAT128, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_STRING_CONST_STRING, BT_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_UNWINDWORD_PTR, BT_UNWINDWORD, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_INT, BT_WINT)
+DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT_WINT, BT_WINT)
+DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLOAT32, BT_DFLOAT32, BT_DFLOAT32)
+DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64)
+DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_VOID_CONST_PTR, BT_VOID, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_INT, BT_UINT, BT_INT)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_ULONG, BT_UINT, BT_ULONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_LONG, BT_UINT, BT_LONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_PTR, BT_UINT, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT_CONST_PTR, BT_UINT, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_PTR, BT_ULONG, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_CONST_PTR, BT_ULONG, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT8_FLOAT, BT_INT8, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT16_FLOAT, BT_INT16, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_FLOAT, BT_UINT32, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_FLOAT, BT_UINT16, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT8_FLOAT, BT_UINT8, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT128_UINT128, BT_UINT128, BT_UINT128)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_FLOAT, BT_UINT64, BT_FLOAT)
+DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT)
+DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_PTR, BT_BOOL, BT_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT32, BT_UINT16, BT_UINT32)
+DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT16, BT_UINT32, BT_UINT16)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_FENV_T_PTR, BT_INT, BT_FENV_T_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_INT_CONST_FENV_T_PTR, BT_INT, BT_CONST_FENV_T_PTR)
+
+DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
+
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_INT, BT_VOID, BT_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_STRING_STRING_CONST_STRING,
+ BT_STRING, BT_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_CONST_STRING,
+ BT_INT, BT_CONST_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_2 (BT_FN_STRING_CONST_STRING_CONST_STRING,
+ BT_STRING, BT_CONST_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_2 (BT_FN_SIZE_CONST_STRING_CONST_STRING,
+ BT_SIZE, BT_CONST_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_2 (BT_FN_STRING_CONST_STRING_INT,
+ BT_STRING, BT_CONST_STRING, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_STRING_CONST_STRING_SIZE,
+ BT_STRING, BT_CONST_STRING, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_SIZE_CONST_STRING_SIZE,
+ BT_SIZE, BT_CONST_STRING, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_FILEPTR,
+ BT_INT, BT_CONST_STRING, BT_FILEPTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_FILEPTR,
+ BT_INT, BT_INT, BT_FILEPTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT16_UINT16_UINT16,
+ BT_UINT16, BT_UINT16, BT_UINT16)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_PTR_INT,
+ BT_INT, BT_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT_PTR_UINT,
+ BT_UINT, BT_PTR, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONG_PTR_LONG,
+ BT_LONG, BT_PTR, BT_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_PTR_ULONG,
+ BT_ULONG, BT_PTR, BT_ULONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRMODE_PTR,
+ BT_VOID, BT_PTRMODE, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTRMODE,
+ BT_VOID, BT_PTR, BT_PTRMODE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT8_UINT8,
+ BT_VOID, BT_UINT8, BT_UINT8)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT16_UINT16,
+ BT_VOID, BT_UINT16, BT_UINT16)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT32_UINT32,
+ BT_VOID, BT_UINT32, BT_UINT32)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT64_UINT64,
+ BT_VOID, BT_UINT64, BT_UINT64)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_FLOAT_FLOAT,
+ BT_VOID, BT_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_DOUBLE_DOUBLE,
+ BT_VOID, BT_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT64_PTR,
+ BT_VOID, BT_UINT64, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VALIST_REF_VALIST_ARG,
+ BT_VOID, BT_VALIST_REF, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONG_LONG_LONG,
+ BT_LONG, BT_LONG, BT_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT8_UINT8_UINT8,
+ BT_UINT8, BT_UINT8, BT_UINT8)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT8_INT8_INT8,
+ BT_INT8, BT_INT8, BT_INT8)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT16_INT16_INT16,
+ BT_INT16, BT_INT16, BT_INT16)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_INT,
+ BT_INT, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT_FLOAT_UINT,
+ BT_UINT, BT_FLOAT, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT_DOUBLE_UINT,
+ BT_UINT, BT_DOUBLE, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_UINT_UINT,
+ BT_FLOAT, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_UINT_UINT,
+ BT_ULONG, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_UINT_PTR,
+ BT_ULONG, BT_UINT, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_ULONG_ULONG_ULONG,
+ BT_ULONG, BT_ULONG, BT_ULONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT_UINT_UINT,
+ BT_UINT, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_PTR_CONST_STRING,
+ BT_INT, BT_PTR, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_SIZE,
+ BT_VOID, BT_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_PTR,
+ BT_VOID, BT_UINT, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_FLOAT,
+ BT_FLOAT, BT_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLE,
+ BT_DOUBLE, BT_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT16_FLOAT16_FLOAT16,
+ BT_FLOAT16, BT_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32_FLOAT32_FLOAT32,
+ BT_FLOAT32, BT_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64_FLOAT64_FLOAT64,
+ BT_FLOAT64, BT_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128_FLOAT128_FLOAT128,
+ BT_FLOAT128, BT_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT32X_FLOAT32X_FLOAT32X,
+ BT_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT64X_FLOAT64X_FLOAT64X,
+ BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT128X_FLOAT128X_FLOAT128X,
+ BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_FLOATPTR,
+ BT_FLOAT, BT_FLOAT, BT_FLOAT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_DOUBLEPTR,
+ BT_DOUBLE, BT_DOUBLE, BT_DOUBLE_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLEPTR,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_LONGDOUBLE,
+ BT_FLOAT, BT_FLOAT, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_LONGDOUBLE,
+ BT_DOUBLE, BT_DOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_INT,
+ BT_FLOAT, BT_FLOAT, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_INT,
+ BT_DOUBLE, BT_DOUBLE, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_INT,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_INTPTR,
+ BT_FLOAT, BT_FLOAT, BT_INT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_INTPTR,
+ BT_DOUBLE, BT_DOUBLE, BT_INT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_INT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_INT_FLOAT,
+ BT_FLOAT, BT_INT, BT_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_INT_DOUBLE,
+ BT_DOUBLE, BT_INT, BT_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_INT_LONGDOUBLE,
+ BT_LONGDOUBLE, BT_INT, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_FLOAT_FLOAT_LONG,
+ BT_FLOAT, BT_FLOAT, BT_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_DOUBLE_DOUBLE_LONG,
+ BT_DOUBLE, BT_DOUBLE, BT_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONG,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_2 (BT_FN_PTR_SIZE_SIZE,
+ BT_PTR, BT_SIZE, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_PTR_PTR_SIZE,
+ BT_PTR, BT_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT_COMPLEX_FLOAT,
+ BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
+ BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE,
+ BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTR, BT_VOID, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING,
+ BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING)
+DEF_FUNCTION_TYPE_2 (BT_FN_SIZE_CONST_PTR_INT, BT_SIZE, BT_CONST_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_I1, BT_I1, BT_VOLATILE_PTR, BT_I1)
+DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_I2, BT_I2, BT_VOLATILE_PTR, BT_I2)
+DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, BT_I4, BT_VOLATILE_PTR, BT_I4)
+DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
+DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_I16, BT_I16, BT_VOLATILE_PTR, BT_I16)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_LONGPTR,
+ BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR,
+ BT_BOOL, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+DEF_FUNCTION_TYPE_2 (BT_FN_I1_CONST_VPTR_INT, BT_I1, BT_CONST_VOLATILE_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_I2_CONST_VPTR_INT, BT_I2, BT_CONST_VOLATILE_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_I4_CONST_VPTR_INT, BT_I4, BT_CONST_VOLATILE_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_I8_CONST_VPTR_INT, BT_I8, BT_CONST_VOLATILE_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_I16_CONST_VPTR_INT, BT_I16, BT_CONST_VOLATILE_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_INT, BT_VOID, BT_VOLATILE_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_VPTR_INT, BT_BOOL, BT_VOLATILE_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE,
+ BT_CONST_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT_UINT_PTR, BT_UINT, BT_UINT, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT_UINT_CONST_PTR, BT_UINT, BT_UINT, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRPTR_CONST_PTR, BT_VOID, BT_PTR_PTR, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_CONST_PTR_SIZE, BT_VOID, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_2 (BT_FN_CONST_PTR_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_UINT32_UINT64_PTR,
+ BT_UINT32, BT_UINT64, BT_PTR)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_FEXCEPT_T_PTR_INT, BT_INT, BT_FEXCEPT_T_PTR,
+ BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_FEXCEPT_T_PTR_INT, BT_INT,
+ BT_CONST_FEXCEPT_T_PTR, BT_INT)
+DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_UINT8, BT_PTR, BT_CONST_PTR, BT_UINT8)
+
+DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR)
+
+DEF_FUNCTION_TYPE_3 (BT_FN_STRING_STRING_CONST_STRING_SIZE,
+ BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_SIZE,
+ BT_INT, BT_CONST_STRING, BT_CONST_STRING, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_CONST_PTR_SIZE,
+ BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_CONST_PTR_SIZE,
+ BT_VOID, BT_PTR, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_PTR_CONST_PTR_SIZE,
+ BT_INT, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_INT_SIZE,
+ BT_PTR, BT_PTR, BT_INT, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_SIZE,
+ BT_VOID, BT_PTR, BT_INT, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT,
+ BT_VOID, BT_PTR, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_CONST_PTR_PTR_SIZE,
+ BT_VOID, BT_CONST_PTR, BT_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_CONST_STRING, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_FILEPTR, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_INT_UINT_UINT,
+ BT_INT, BT_INT, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_UINT_UINT,
+ BT_UINT, BT_UINT, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_UINT_PTR,
+ BT_UINT, BT_UINT, BT_UINT, BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_UINT_ULONG_ULONG_UINT,
+ BT_UINT, BT_ULONG, BT_ULONG, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_ULONG_ULONG_ULONG_ULONG,
+ BT_ULONG, BT_ULONG, BT_ULONG, BT_ULONG)
+DEF_FUNCTION_TYPE_3 (BT_FN_LONG_LONG_UINT_UINT,
+ BT_LONG, BT_LONG, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_LONG_LONG_LONG_DOUBLE,
+ BT_LONG, BT_LONG, BT_LONG, BT_DOUBLE)
+DEF_FUNCTION_TYPE_3 (BT_FN_ULONG_ULONG_UINT_UINT,
+ BT_ULONG, BT_ULONG, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_STRING_CONST_STRING_CONST_STRING_INT,
+ BT_STRING, BT_CONST_STRING, BT_CONST_STRING, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT_FLOAT_FLOAT_FLOAT,
+ BT_FLOAT, BT_FLOAT, BT_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_3 (BT_FN_DOUBLE_DOUBLE_DOUBLE_DOUBLE,
+ BT_DOUBLE, BT_DOUBLE, BT_DOUBLE, BT_DOUBLE)
+DEF_FUNCTION_TYPE_3 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT16_FLOAT16_FLOAT16_FLOAT16,
+ BT_FLOAT16, BT_FLOAT16, BT_FLOAT16, BT_FLOAT16)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT32_FLOAT32_FLOAT32_FLOAT32,
+ BT_FLOAT32, BT_FLOAT32, BT_FLOAT32, BT_FLOAT32)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT64_FLOAT64_FLOAT64_FLOAT64,
+ BT_FLOAT64, BT_FLOAT64, BT_FLOAT64, BT_FLOAT64)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT128_FLOAT128_FLOAT128_FLOAT128,
+ BT_FLOAT128, BT_FLOAT128, BT_FLOAT128, BT_FLOAT128)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT32X_FLOAT32X_FLOAT32X_FLOAT32X,
+ BT_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X, BT_FLOAT32X)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT64X_FLOAT64X_FLOAT64X_FLOAT64X,
+ BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X, BT_FLOAT64X)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT128X_FLOAT128X_FLOAT128X_FLOAT128X,
+ BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X, BT_FLOAT128X)
+DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT_FLOAT_FLOAT_INTPTR,
+ BT_FLOAT, BT_FLOAT, BT_FLOAT, BT_INT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_DOUBLE_DOUBLE_DOUBLE_INTPTR,
+ BT_DOUBLE, BT_DOUBLE, BT_DOUBLE, BT_INT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_INTPTR,
+ BT_LONGDOUBLE, BT_LONGDOUBLE, BT_LONGDOUBLE, BT_INT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_FLOAT_FLOATPTR_FLOATPTR,
+ BT_VOID, BT_FLOAT, BT_FLOAT_PTR, BT_FLOAT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_DOUBLE_DOUBLEPTR_DOUBLEPTR,
+ BT_VOID, BT_DOUBLE, BT_DOUBLE_PTR, BT_DOUBLE_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_LONGDOUBLE_LONGDOUBLEPTR_LONGDOUBLEPTR,
+ BT_VOID, BT_LONGDOUBLE, BT_LONGDOUBLE_PTR, BT_LONGDOUBLE_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_PTR_PTR, BT_VOID, BT_PTR, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_PTR_UINT32, BT_VOID, BT_PTR, BT_PTR, BT_UINT32)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING,
+ BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING, BT_PTR_CONST_STRING)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_INT_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I1_I1, BT_BOOL, BT_VOLATILE_PTR,
+ BT_I1, BT_I1)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I2_I2, BT_BOOL, BT_VOLATILE_PTR,
+ BT_I2, BT_I2)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I4_I4, BT_BOOL, BT_VOLATILE_PTR,
+ BT_I4, BT_I4)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I8_I8, BT_BOOL, BT_VOLATILE_PTR,
+ BT_I8, BT_I8)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I16_I16, BT_BOOL, BT_VOLATILE_PTR,
+ BT_I16, BT_I16)
+DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_I1, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_I1)
+DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_I2, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_I2)
+DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_I4, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_I4)
+DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_I8, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_I8)
+DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_I16, BT_I16, BT_VOLATILE_PTR,
+ BT_I16, BT_I16)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_INT_SIZE, BT_PTR,
+ BT_CONST_PTR, BT_INT, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_INT, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_INT, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_INT, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_INT, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_INT, BT_I16, BT_VOLATILE_PTR, BT_I16, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I1_INT, BT_VOID, BT_VOLATILE_PTR, BT_I1, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_PTRPTR_SIZE_SIZE, BT_INT, BT_PTR_PTR, BT_SIZE, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_INT_INT_INTPTR, BT_BOOL, BT_INT, BT_INT,
+ BT_INT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_LONG_LONG_LONGPTR, BT_BOOL, BT_LONG, BT_LONG,
+ BT_PTR_LONG)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, BT_BOOL,
+ BT_LONGLONG, BT_LONGLONG, BT_PTR_LONGLONG)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_UINT_UINT_UINTPTR, BT_BOOL, BT_UINT, BT_UINT,
+ BT_PTR_UINT)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_ULONG_ULONG_ULONGPTR, BT_BOOL, BT_ULONG,
+ BT_ULONG, BT_PTR_ULONG)
+DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, BT_BOOL,
+ BT_ULONGLONG, BT_ULONGLONG, BT_PTR_ULONGLONG)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_UINT32_UINT64_PTR,
+ BT_VOID, BT_UINT32, BT_UINT64, BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_UINT32_UINT32_PTR,
+ BT_VOID, BT_UINT32, BT_UINT32, BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_SIZE_SIZE_PTR, BT_VOID, BT_SIZE, BT_SIZE,
+ BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_UINT_UINT_PTR_PTR, BT_UINT, BT_UINT, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_CONST_SIZE_BOOL,
+ BT_PTR, BT_PTR, BT_CONST_SIZE, BT_BOOL)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_SIZE_SIZE_PTRMODE,
+ BT_PTR, BT_SIZE, BT_SIZE, BT_PTRMODE)
+DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_UINT8_PTRMODE, BT_VOID, BT_PTR, BT_UINT8,
+ BT_PTRMODE)
+
+DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
+ BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR,
+ BT_SIZE, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_CONST_TM_PTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE,
+ BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE, BT_SIZE)
+DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_INT_SIZE_SIZE,
+ BT_PTR, BT_PTR, BT_INT, BT_SIZE, BT_SIZE)
+DEF_FUNCTION_TYPE_4 (BT_FN_UINT_UINT_UINT_UINT_UINT,
+ BT_UINT, BT_UINT, BT_UINT, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_4 (BT_FN_UINT_FLOAT_FLOAT_FLOAT_FLOAT,
+ BT_UINT, BT_FLOAT, BT_FLOAT, BT_FLOAT, BT_FLOAT)
+DEF_FUNCTION_TYPE_4 (BT_FN_ULONG_ULONG_ULONG_UINT_UINT,
+ BT_ULONG, BT_ULONG, BT_ULONG, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_4 (BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE,
+ BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE, BT_SIZE)
+DEF_FUNCTION_TYPE_4 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_FILEPTR, BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_4 (BT_FN_UINT_OMPFN_PTR_UINT_UINT,
+ BT_UINT, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_PTR_WORD_WORD_PTR,
+ BT_VOID, BT_PTR, BT_WORD, BT_WORD, BT_PTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_VPTR_PTR_INT, BT_VOID, BT_SIZE,
+ BT_VOLATILE_PTR, BT_PTR, BT_INT)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT, BT_VOID, BT_SIZE,
+ BT_CONST_VOLATILE_PTR, BT_PTR, BT_INT)
+DEF_FUNCTION_TYPE_4 (BT_FN_BOOL_UINT_LONGPTR_LONGPTR_LONGPTR,
+ BT_BOOL, BT_UINT, BT_PTR_LONG, BT_PTR_LONG, BT_PTR_LONG)
+DEF_FUNCTION_TYPE_4 (BT_FN_BOOL_UINT_ULLPTR_ULLPTR_ULLPTR,
+ BT_BOOL, BT_UINT, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG,
+ BT_PTR_ULONGLONG)
+DEF_FUNCTION_TYPE_4 (BT_FN_VOID_UINT_PTR_INT_PTR, BT_VOID, BT_INT, BT_PTR,
+ BT_INT, BT_PTR)
+DEF_FUNCTION_TYPE_4 (BT_FN_BOOL_UINT_UINT_UINT_BOOL,
+ BT_BOOL, BT_UINT, BT_UINT, BT_UINT, BT_BOOL)
+
+DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
+ BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
+ BT_PTR_LONG, BT_PTR_LONG)
+DEF_FUNCTION_TYPE_5 (BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, BT_VOID, BT_SIZE,
+ BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I1_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I2_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I4_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I8_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_VPTR_PTR_I16_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_INT, BT_INT)
+DEF_FUNCTION_TYPE_5 (BT_FN_VOID_INT_SIZE_PTR_PTR_PTR,
+ BT_VOID, BT_INT, BT_SIZE, BT_PTR, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_5 (BT_FN_VOID_OMPFN_PTR_UINT_UINT_UINT,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT,
+ BT_UINT)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_UINT_LONGPTR_LONG_LONGPTR_LONGPTR,
+ BT_BOOL, BT_UINT, BT_PTR_LONG, BT_LONG, BT_PTR_LONG,
+ BT_PTR_LONG)
+DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_UINT_ULLPTR_ULL_ULLPTR_ULLPTR,
+ BT_BOOL, BT_UINT, BT_PTR_ULONGLONG, BT_ULONGLONG,
+ BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+
+DEF_FUNCTION_TYPE_6 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG,
+ BT_INT, BT_STRING, BT_SIZE, BT_INT, BT_SIZE,
+ BT_CONST_STRING, BT_VALIST_ARG)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ BT_BOOL, BT_LONG, BT_LONG, BT_LONG, BT_LONG,
+ BT_PTR_LONG, BT_PTR_LONG)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
+ BT_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I1, BT_BOOL, BT_INT,
+ BT_INT)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I2, BT_BOOL, BT_INT,
+ BT_INT)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I4, BT_BOOL, BT_INT,
+ BT_INT)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I8, BT_BOOL, BT_INT,
+ BT_INT)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT,
+ BT_BOOL, BT_VOLATILE_PTR, BT_PTR, BT_I16, BT_BOOL, BT_INT,
+ BT_INT)
+DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT, BT_BOOL, BT_SIZE,
+ BT_VOLATILE_PTR, BT_PTR, BT_PTR, BT_INT, BT_INT)
+
+DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
+ BT_LONG, BT_LONG, BT_LONG, BT_UINT)
+DEF_FUNCTION_TYPE_7 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
+ BT_ULONGLONG, BT_ULONGLONG,
+ BT_PTR_ULONGLONG, BT_PTR_ULONGLONG)
+DEF_FUNCTION_TYPE_7 (BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_UINT_PTR,
+ BT_VOID, BT_INT, BT_SIZE, BT_PTR, BT_PTR, BT_PTR, BT_UINT,
+ BT_PTR)
+
+DEF_FUNCTION_TYPE_8 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
+ BT_LONG, BT_LONG, BT_LONG, BT_LONG, BT_UINT)
+DEF_FUNCTION_TYPE_8 (BT_FN_BOOL_UINT_LONGPTR_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR,
+ BT_BOOL, BT_UINT, BT_PTR_LONG, BT_LONG, BT_LONG,
+ BT_PTR_LONG, BT_PTR_LONG, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_8 (BT_FN_BOOL_UINT_ULLPTR_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR,
+ BT_BOOL, BT_UINT, BT_PTR_ULONGLONG, BT_LONG, BT_ULONGLONG,
+ BT_PTR_ULONGLONG, BT_PTR_ULONGLONG, BT_PTR, BT_PTR)
+
+DEF_FUNCTION_TYPE_9 (BT_FN_VOID_INT_OMPFN_SIZE_PTR_PTR_PTR_UINT_PTR_PTR,
+ BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_SIZE, BT_PTR,
+ BT_PTR, BT_PTR, BT_UINT, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_9 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR,
+ BT_BOOL, BT_LONG, BT_LONG, BT_LONG, BT_LONG, BT_LONG,
+ BT_PTR_LONG, BT_PTR_LONG, BT_PTR, BT_PTR)
+
+DEF_FUNCTION_TYPE_10 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
+ BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
+ BT_BOOL, BT_UINT, BT_PTR, BT_INT, BT_PTR)
+DEF_FUNCTION_TYPE_10 (BT_FN_BOOL_BOOL_ULL_ULL_ULL_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR,
+ BT_BOOL, BT_BOOL, BT_ULONGLONG, BT_ULONGLONG,
+ BT_ULONGLONG, BT_LONG, BT_ULONGLONG, BT_PTR_ULONGLONG,
+ BT_PTR_ULONGLONG, BT_PTR, BT_PTR)
+
+DEF_FUNCTION_TYPE_11 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_LONG_LONG_LONG,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
+ BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
+ BT_UINT, BT_LONG, BT_INT, BT_LONG, BT_LONG, BT_LONG)
+DEF_FUNCTION_TYPE_11 (BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_ULL_ULL_ULL,
+ BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR,
+ BT_PTR_FN_VOID_PTR_PTR, BT_LONG, BT_LONG,
+ BT_UINT, BT_LONG, BT_INT,
+ BT_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG)
+
+DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
+DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)
+DEF_FUNCTION_TYPE_VAR_0 (BT_FN_PTR_VAR, BT_PTR)
+DEF_FUNCTION_TYPE_VAR_0 (BT_FN_BOOL_VAR, BT_BOOL)
+
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_VALIST_REF_VAR,
+ BT_VOID, BT_VALIST_REF)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_CONST_PTR_VAR,
+ BT_VOID, BT_CONST_PTR)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_INT_CONST_STRING_VAR,
+ BT_INT, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_UINT32_UINT32_VAR,
+ BT_UINT32, BT_UINT32)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_LONG_VAR,
+ BT_VOID, BT_LONG)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_ULL_VAR,
+ BT_VOID, BT_ULONGLONG)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_PTR_PTR_VAR, BT_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I1_I1_VAR, BT_I1, BT_I1)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I2_I2_VAR, BT_I2, BT_I2)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I4_I4_VAR, BT_I4, BT_I4)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I8_I8_VAR, BT_I8, BT_I8)
+DEF_FUNCTION_TYPE_VAR_1 (BT_FN_I16_I16_VAR, BT_I16, BT_I16)
+
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_FILEPTR_CONST_STRING_VAR,
+ BT_INT, BT_FILEPTR, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_STRING_CONST_STRING_VAR,
+ BT_INT, BT_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_CONST_STRING_CONST_STRING_VAR,
+ BT_INT, BT_CONST_STRING, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_INT_CONST_STRING_VAR,
+ BT_INT, BT_INT, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_PTR_CONST_PTR_SIZE_VAR, BT_PTR,
+ BT_CONST_PTR, BT_SIZE)
+DEF_FUNCTION_TYPE_VAR_2 (BT_FN_VOID_INT_INT_VAR, BT_VOID,
+ BT_INT, BT_INT)
+
+DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_STRING_SIZE_CONST_STRING_VAR,
+ BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_3 (BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR,
+ BT_SSIZE, BT_STRING, BT_SIZE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VAR,
+ BT_INT, BT_FILEPTR, BT_INT, BT_CONST_STRING)
+
+DEF_FUNCTION_TYPE_VAR_4 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR,
+ BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING)
+
+DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR,
+ BT_INT, BT_STRING, BT_SIZE, BT_INT, BT_SIZE,
+ BT_CONST_STRING)
+
+DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_INT_INT_INT_INT_INT_VAR,
+ BT_INT, BT_INT, BT_INT, BT_INT, BT_INT, BT_INT)
+
+DEF_FUNCTION_TYPE_VAR_6 (BT_FN_VOID_INT_OMPFN_SIZE_PTR_PTR_PTR_VAR,
+ BT_VOID, BT_INT, BT_PTR_FN_VOID_PTR, BT_SIZE,
+ BT_PTR, BT_PTR, BT_PTR)
+
+DEF_FUNCTION_TYPE_VAR_7 (BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_INT_INT_VAR,
+ BT_VOID, BT_INT, BT_SIZE, BT_PTR, BT_PTR,
+ BT_PTR, BT_INT, BT_INT)
+
+DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
+DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
+ BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
+
+
+DEF_FUNCTION_TYPE_1 (BT_FN_I1_VPTR, BT_I1, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I2_VPTR, BT_I2, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I4_VPTR, BT_I4, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I8_VPTR, BT_I8, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_VPTR, BT_FLOAT, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_DOUBLE_PTR, BT_DOUBLE, BT_DOUBLE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_LDOUBLE_VPTR, BT_LONGDOUBLE, BT_VOLATILE_PTR)
+
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I1, BT_VOID, BT_VOLATILE_PTR, BT_I1)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I2, BT_VOID, BT_VOLATILE_PTR, BT_I2)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I4, BT_VOID, BT_VOLATILE_PTR, BT_I4)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I8, BT_VOID, BT_VOLATILE_PTR, BT_I8)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_FLOAT, BT_VOID, BT_VOLATILE_PTR, BT_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_DOUBLE, BT_VOID,
+ BT_VOLATILE_PTR, BT_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_LDOUBLE, BT_VOID,
+ BT_VOLATILE_PTR, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_SIZE, BT_VOID,
+ BT_VOLATILE_PTR, BT_SIZE)
diff --git a/support/cpp/gcc/builtins.def b/support/cpp/gcc/builtins.def
new file mode 100644
index 000000000..005976f34
--- /dev/null
+++ b/support/cpp/gcc/builtins.def
@@ -0,0 +1,1073 @@
+/* This file contains the definitions and documentation for the
+ builtins used in the GNU compiler.
+ Copyright (C) 2000-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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_BUILTIN (ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P,
+ FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT, COND)
+
+ This macro will be called once for each builtin function. The
+ ENUM will be of type `enum built_in_function', and will indicate
+ which builtin function is being processed. The NAME of the builtin
+ function (which will always start with `__builtin_') is a string
+ literal. The CLASS is of type `enum built_in_class' and indicates
+ what kind of builtin is being processed.
+
+ Some builtins are actually two separate functions. For example,
+ for `strcmp' there are two builtin functions; `__builtin_strcmp'
+ and `strcmp' itself. Both behave identically. Other builtins
+ define only the `__builtin' variant. If BOTH_P is TRUE, then this
+ builtin has both variants; otherwise, it is has only the first
+ variant.
+
+ TYPE indicates the type of the function. The symbols correspond to
+ enumerals from builtin-types.def. If BOTH_P is true, then LIBTYPE
+ is the type of the non-`__builtin_' variant. Otherwise, LIBTYPE
+ should be ignored.
+
+ If FALLBACK_P is true then, if for some reason, the compiler cannot
+ expand the builtin function directly, it will call the
+ corresponding library function (which does not have the
+ `__builtin_' prefix.
+
+ If NONANSI_P is true, then the non-`__builtin_' variant is not an
+ ANSI/ISO library function, and so we should pretend it does not
+ exist when compiling in ANSI conformant mode.
+
+ ATTRs is an attribute list as defined in builtin-attrs.def that
+ describes the attributes of this builtin function.
+
+ IMPLICIT specifies condition when the builtin can be produced by
+ compiler. For instance C90 reserves floorf function, but does not
+ define it's meaning. When user uses floorf we may assume that the
+ floorf has the meaning we expect, but we can't produce floorf by
+ simplifying floor((double)float) since the runtime need not implement
+ it.
+
+ The builtins is registered only if COND is true. */
+
+/* A GCC builtin (like __builtin_saveregs) is provided by the
+ compiler, but does not correspond to a function in the standard
+ library. */
+#undef DEF_GCC_BUILTIN
+#define DEF_GCC_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
+ false, false, false, ATTRS, true, true)
+
+/* Like DEF_GCC_BUILTIN, except we don't prepend "__builtin_". */
+#undef DEF_SYNC_BUILTIN
+#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
+ false, false, false, ATTRS, true, true)
+
+/* A set of GCC builtins for _FloatN and _FloatNx types. TYPE_MACRO
+ is called with an argument such as FLOAT32 to produce the enum
+ value for the type. */
+#undef DEF_GCC_FLOATN_NX_BUILTINS
+#define DEF_GCC_FLOATN_NX_BUILTINS(ENUM, NAME, TYPE_MACRO, ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F16, NAME "f16", TYPE_MACRO (FLOAT16), ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F32, NAME "f32", TYPE_MACRO (FLOAT32), ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F64, NAME "f64", TYPE_MACRO (FLOAT64), ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F128, NAME "f128", TYPE_MACRO (FLOAT128), ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F32X, NAME "f32x", TYPE_MACRO (FLOAT32X), ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F64X, NAME "f64x", TYPE_MACRO (FLOAT64X), ATTRS) \
+ DEF_GCC_BUILTIN (ENUM ## F128X, NAME "f128x", TYPE_MACRO (FLOAT128X), ATTRS)
+
+/* A library builtin (like __builtin_strchr) is a builtin equivalent
+ of an ANSI/ISO standard library function. In addition to the
+ `__builtin' version, we will create an ordinary version (e.g,
+ `strchr') as well. If we cannot compute the answer using the
+ builtin function, we will fall back to the standard library
+ version. */
+#undef DEF_LIB_BUILTIN
+#define DEF_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, false, ATTRS, true, true)
+
+/* Like DEF_LIB_BUILTIN, except that the function is not one that is
+ specified by ANSI/ISO C. So, when we're being fully conformant we
+ ignore the version of these builtins that does not begin with
+ __builtin. */
+#undef DEF_EXT_LIB_BUILTIN
+#define DEF_EXT_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, true, ATTRS, false, true)
+
+/* A set of GCC builtins for _FloatN and _FloatNx types. TYPE_MACRO is called
+ with an argument such as FLOAT32 to produce the enum value for the type. If
+ we are compiling for the C language with GNU extensions, we enable the name
+ without the __builtin_ prefix as well as the name with the __builtin_
+ prefix. C++ does not enable these names by default because they don't have
+ the _Float<N> and _Float<N>X keywords, and a class based library should use
+ the __builtin_ names. */
+#undef DEF_FLOATN_BUILTIN
+#define DEF_FLOATN_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ targetm.floatn_builtin_p ((int) ENUM), true, true, ATTRS, \
+ false, true)
+#undef DEF_EXT_LIB_FLOATN_NX_BUILTINS
+#define DEF_EXT_LIB_FLOATN_NX_BUILTINS(ENUM, NAME, TYPE_MACRO, ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F16, NAME "f16", TYPE_MACRO (FLOAT16), ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F32, NAME "f32", TYPE_MACRO (FLOAT32), ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F64, NAME "f64", TYPE_MACRO (FLOAT64), ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F128, NAME "f128", TYPE_MACRO (FLOAT128), ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F32X, NAME "f32x", TYPE_MACRO (FLOAT32X), ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F64X, NAME "f64x", TYPE_MACRO (FLOAT64X), ATTRS) \
+ DEF_FLOATN_BUILTIN (ENUM ## F128X, NAME "f128x", TYPE_MACRO (FLOAT128X), \
+ ATTRS)
+
+/* Like DEF_LIB_BUILTIN, except that the function is only a part of
+ the standard in C94 or above. */
+#undef DEF_C94_BUILTIN
+#define DEF_C94_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc94, ATTRS, \
+ targetm.libc_has_function (function_c94, NULL_TREE), true)
+
+/* Like DEF_LIB_BUILTIN, except that the function is only a part of
+ the standard in C99 or above. */
+#undef DEF_C99_BUILTIN
+#define DEF_C99_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc99, ATTRS, \
+ targetm.libc_has_function (function_c99_misc, NULL_TREE), true)
+
+/* Like DEF_LIB_BUILTIN, except that the function is only a part of
+ the standard in C11 or above. */
+#undef DEF_C11_BUILTIN
+#define DEF_C11_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc11, ATTRS, \
+ targetm.libc_has_function (function_c11_misc, NULL_TREE), true)
+
+/* Like DEF_LIB_BUILTIN, except that the function is only a part of
+ the standard in C2x or above. */
+#undef DEF_C2X_BUILTIN
+#define DEF_C2X_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc2x, ATTRS, \
+ targetm.libc_has_function (function_c2x_misc, NULL_TREE), true)
+
+/* Like DEF_C99_BUILTIN, but for complex math functions. */
+#undef DEF_C99_COMPL_BUILTIN
+#define DEF_C99_COMPL_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc99, ATTRS, \
+ targetm.libc_has_function (function_c99_math_complex, \
+ NULL_TREE), \
+ true)
+
+/* Builtin that is specified by C99 and C90 reserve the name for future use.
+ We can still recognize the builtin in C90 mode but we can't produce it
+ implicitly. */
+#undef DEF_C99_C90RES_BUILTIN
+#define DEF_C99_C90RES_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, !flag_isoc99, ATTRS, \
+ targetm.libc_has_function (function_c99_misc, NULL_TREE), true)
+
+/* Builtin that C99 reserve the name for future use. We can still recognize
+ the builtin in C99 mode but we can't produce it implicitly. */
+#undef DEF_EXT_C99RES_BUILTIN
+#define DEF_EXT_C99RES_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, true, ATTRS, false, true)
+
+/* Allocate the enum and the name for a builtin, but do not actually
+ define it here at all. */
+#undef DEF_BUILTIN_STUB
+#define DEF_BUILTIN_STUB(ENUM, NAME) \
+ DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_LAST, BT_LAST, false, false, \
+ false, ATTR_LAST, false, false)
+
+/* Builtins used in implementing coroutine support. */
+#undef DEF_COROUTINE_BUILTIN
+#define DEF_COROUTINE_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_coro_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, true, ATTRS, true, flag_coroutines)
+
+/* Builtin used by the implementation of OpenACC and OpenMP. Few of these are
+ actually implemented in the compiler; most are in libgomp. */
+#undef DEF_GOACC_BUILTIN
+#define DEF_GOACC_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ false, true, true, ATTRS, false, \
+ flag_openacc)
+#undef DEF_GOACC_BUILTIN_COMPILER
+#define DEF_GOACC_BUILTIN_COMPILER(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ flag_openacc, true, true, ATTRS, false, true)
+#undef DEF_GOACC_BUILTIN_ONLY
+#define DEF_GOACC_BUILTIN_ONLY(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
+ false, false, true, ATTRS, false, flag_openacc)
+#undef DEF_GOMP_BUILTIN
+#define DEF_GOMP_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ false, true, true, ATTRS, false, \
+ (flag_openacc \
+ || flag_openmp \
+ || flag_tree_parallelize_loops > 1))
+
+/* Builtin used by the implementation of GNU TM. These
+ functions are mapped to the actual implementation of the STM library. */
+#undef DEF_TM_BUILTIN
+#define DEF_TM_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
+ false, true, true, ATTRS, false, flag_tm)
+
+/* Builtin used by the implementation of libsanitizer. These
+ functions are mapped to the actual implementation of the
+ libtsan library. */
+#undef DEF_SANITIZER_BUILTIN
+#define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ true, true, true, ATTRS, true, \
+ (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
+ | SANITIZE_HWADDRESS \
+ | SANITIZE_UNDEFINED \
+ | SANITIZE_UNDEFINED_NONDEFAULT) \
+ || flag_sanitize_coverage))
+
+/* Define an attribute list for math functions that are normally
+ "impure" because some of them may write into global memory for
+ `errno'. If !flag_errno_math they are instead "const". */
+#undef ATTR_MATHFN_ERRNO
+#define ATTR_MATHFN_ERRNO (flag_errno_math ? \
+ ATTR_ERRNOCONST_NOTHROW_LEAF_LIST : ATTR_CONST_NOTHROW_LEAF_LIST)
+
+/* Define an attribute list for math functions that are normally
+ "const" but if flag_rounding_math is set they are instead "pure".
+ This distinction accounts for the fact that some math functions
+ check the rounding mode which is akin to examining global
+ memory. */
+#undef ATTR_MATHFN_FPROUNDING
+#define ATTR_MATHFN_FPROUNDING (flag_rounding_math ? \
+ ATTR_PURE_NOTHROW_LEAF_LIST : ATTR_CONST_NOTHROW_LEAF_LIST)
+
+/* Define an attribute list for math functions that are normally
+ "impure" because some of them may write into global memory for
+ `errno'. If !flag_errno_math, we can possibly use "pure" or
+ "const" depending on whether we care about FP rounding. */
+#undef ATTR_MATHFN_FPROUNDING_ERRNO
+#define ATTR_MATHFN_FPROUNDING_ERRNO (flag_errno_math ? \
+ (flag_rounding_math ? ATTR_ERRNOPURE_NOTHROW_LEAF_LIST \
+ : ATTR_ERRNOCONST_NOTHROW_LEAF_LIST) : ATTR_MATHFN_FPROUNDING)
+
+/* Define an attribute list for math functions that need to mind FP
+ rounding, but because they store into memory they are never "const"
+ or "pure". Use of this macro is mainly for documentation and
+ maintenance purposes. */
+#undef ATTR_MATHFN_FPROUNDING_STORE
+#define ATTR_MATHFN_FPROUNDING_STORE ATTR_NOTHROW_LEAF_LIST
+
+/* Define an attribute list for leaf functions that do not throw
+ exceptions normally, but may throw exceptions when using
+ -fnon-call-exceptions. */
+#define ATTR_NOTHROWCALL_LEAF_LIST (flag_non_call_exceptions ? \
+ ATTR_LEAF_LIST : ATTR_NOTHROW_LEAF_LIST)
+
+/* Make sure 0 is not a legitimate builtin. */
+DEF_BUILTIN_STUB(BUILT_IN_NONE, (const char *)0)
+
+/* Category: math builtins. */
+DEF_LIB_BUILTIN (BUILT_IN_ACOS, "acos", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSF, "acosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ACOSH, "acosh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ACOSHF, "acoshf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ACOSHL, "acoshl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ACOSL, "acosl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C11_BUILTIN (BUILT_IN_ALIGNED_ALLOC, "aligned_alloc", BT_FN_PTR_SIZE_SIZE, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ASIN, "asin", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ASINF, "asinf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ASINH, "asinh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_ASINHF, "asinhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_ASINHL, "asinhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ASINL, "asinl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_ATAN, "atan", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_ATAN2, "atan2", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ATAN2F, "atan2f", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ATAN2L, "atan2l", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ATANF, "atanf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_ATANH, "atanh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ATANHF, "atanhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ATANHL, "atanhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ATANL, "atanl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_CBRT, "cbrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_CBRTF, "cbrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_CBRTL, "cbrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_CEIL, "ceil", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILF, "ceilf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_CEILL, "ceill", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define CEIL_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_CEIL, "ceil", CEIL_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef CEIL_TYPE
+DEF_C99_BUILTIN (BUILT_IN_COPYSIGN, "copysign", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_COPYSIGNF, "copysignf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_COPYSIGNL, "copysignl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define COPYSIGN_TYPE(F) BT_FN_##F##_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_COPYSIGN, "copysign", COPYSIGN_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef COPYSIGN_TYPE
+DEF_LIB_BUILTIN (BUILT_IN_COS, "cos", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_COSF, "cosf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_COSH, "cosh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_COSHF, "coshf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_COSHL, "coshl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_COSL, "cosl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_DREM, "drem", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_DREMF, "dremf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_DREML, "dreml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ERF, "erf", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_ERFC, "erfc", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ERFCF, "erfcf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ERFCL, "erfcl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ERFF, "erff", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_ERFL, "erfl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_EXP, "exp", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C2X_BUILTIN (BUILT_IN_EXP10, "exp10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C2X_BUILTIN (BUILT_IN_EXP10F, "exp10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C2X_BUILTIN (BUILT_IN_EXP10L, "exp10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_EXP2, "exp2", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_EXP2F, "exp2f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_EXP2L, "exp2l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_EXPF, "expf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_EXPL, "expl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_EXPM1, "expm1", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_EXPM1F, "expm1f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_EXPM1L, "expm1l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_FABS, "fabs", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSF, "fabsf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FABSL, "fabsl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define FABS_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FABS, "fabs", FABS_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef FABS_TYPE
+DEF_C2X_BUILTIN (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_FECLEAREXCEPT, "feclearexcept", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEGETENV, "fegetenv", BT_FN_INT_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEGETEXCEPTFLAG, "fegetexceptflag", BT_FN_INT_FEXCEPT_T_PTR_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEGETROUND, "fegetround", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEHOLDEXCEPT, "feholdexcept", BT_FN_INT_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FERAISEEXCEPT, "feraiseexcept", BT_FN_INT_INT, ATTR_NULL)
+DEF_C99_BUILTIN (BUILT_IN_FESETENV, "fesetenv", BT_FN_INT_CONST_FENV_T_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FESETEXCEPTFLAG, "fesetexceptflag", BT_FN_INT_CONST_FEXCEPT_T_PTR_INT, ATTR_NULL)
+DEF_C99_BUILTIN (BUILT_IN_FESETROUND, "fesetround", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FETESTEXCEPT, "fetestexcept", BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FEUPDATEENV, "feupdateenv", BT_FN_INT_CONST_FENV_T_PTR, ATTR_NULL)
+DEF_LIB_BUILTIN (BUILT_IN_FLOOR, "floor", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FLOORF, "floorf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FLOORL, "floorl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define FLOOR_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FLOOR, "floor", FLOOR_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef FLOOR_TYPE
+DEF_C99_BUILTIN (BUILT_IN_FMA, "fma", BT_FN_DOUBLE_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_FMAF, "fmaf", BT_FN_FLOAT_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_FMAL, "fmal", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+#define FMA_TYPE(F) BT_FN_##F##_##F##_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FMA, "fma", FMA_TYPE, ATTR_MATHFN_FPROUNDING)
+#undef FMA_TYPE
+DEF_C99_BUILTIN (BUILT_IN_FMAX, "fmax", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FMAXF, "fmaxf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FMAXL, "fmaxl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define FMAX_TYPE(F) BT_FN_##F##_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FMAX, "fmax", FMAX_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef FMAX_TYPE
+DEF_C99_BUILTIN (BUILT_IN_FMIN, "fmin", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FMINF, "fminf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_FMINL, "fminl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define FMIN_TYPE(F) BT_FN_##F##_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_FMIN, "fmin", FMIN_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef FMIN_TYPE
+DEF_LIB_BUILTIN (BUILT_IN_FMOD, "fmod", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FMODF, "fmodf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FMODL, "fmodl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_FREXP, "frexp", BT_FN_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FREXPF, "frexpf", BT_FN_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_FREXPL, "frexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMA, "gamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAF, "gammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAL, "gammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMA_R, "gamma_r", BT_FN_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAF_R, "gammaf_r", BT_FN_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAL_R, "gammal_r", BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_GCC_BUILTIN (BUILT_IN_HUGE_VAL, "huge_val", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_HUGE_VALF, "huge_valf", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_HUGE_VALL, "huge_vall", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define INF_TYPE(F) BT_FN_##F
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_HUGE_VAL, "huge_val", INF_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_HYPOT, "hypot", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_HYPOTF, "hypotf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_HYPOTL, "hypotl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_ICEIL, "iceil", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_ICEILF, "iceilf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_ICEILL, "iceill", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_IFLOOR, "ifloor", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_IFLOORF, "ifloorf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_IFLOORL, "ifloorl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_ILOGB, "ilogb", BT_FN_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ILOGBF, "ilogbf", BT_FN_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_ILOGBL, "ilogbl", BT_FN_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_INF, "inf", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_INFF, "inff", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_INFL, "infl", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_INF, "inf", INF_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef INF_TYPE
+DEF_GCC_BUILTIN (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_INFD64, "infd64", BT_FN_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_INFD128, "infd128", BT_FN_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_IRINT, "irint", BT_FN_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_IRINTF, "irintf", BT_FN_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_IRINTL, "irintl", BT_FN_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_IROUND, "iround", BT_FN_INT_DOUBLE, ATTR_MATHFN_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_IROUNDF, "iroundf", BT_FN_INT_FLOAT, ATTR_MATHFN_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_IROUNDL, "iroundl", BT_FN_INT_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_J0, "j0", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_J0F, "j0f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_J0L, "j0l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_J1, "j1", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_J1F, "j1f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_J1L, "j1l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_JN, "jn", BT_FN_DOUBLE_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_JNF, "jnf", BT_FN_FLOAT_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_JNL, "jnl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_LCEIL, "lceil", BT_FN_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LCEILF, "lceilf", BT_FN_LONG_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LCEILL, "lceill", BT_FN_LONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_LDEXP, "ldexp", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPF, "ldexpf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPL, "ldexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_LFLOOR, "lfloor", BT_FN_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LFLOORF, "lfloorf", BT_FN_LONG_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LFLOORL, "lfloorl", BT_FN_LONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_LGAMMA, "lgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_BUILTIN (BUILT_IN_LGAMMAF, "lgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_BUILTIN (BUILT_IN_LGAMMAL, "lgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_LGAMMA_R, "lgamma_r", BT_FN_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_LGAMMAF_R, "lgammaf_r", BT_FN_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_LGAMMAL_R, "lgammal_r", BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_GCC_BUILTIN (BUILT_IN_LLCEIL, "llceil", BT_FN_LONGLONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LLCEILF, "llceilf", BT_FN_LONGLONG_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LLCEILL, "llceill", BT_FN_LONGLONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LLFLOOR, "llfloor", BT_FN_LONGLONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LLFLOORF, "llfloorf", BT_FN_LONGLONG_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LLFLOORL, "llfloorl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_LLRINT, "llrint", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LLRINTF, "llrintf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LLRINTL, "llrintl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LLROUND, "llround", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LLROUNDF, "llroundf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LLROUNDL, "llroundl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_LOG, "log", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_LOG10, "log10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_LOG10F, "log10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_LOG10L, "log10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOG1P, "log1p", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOG1PF, "log1pf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOG1PL, "log1pl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOG2, "log2", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOG2F, "log2f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOG2L, "log2l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOGB, "logb", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOGBF, "logbf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LOGBL, "logbl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_LOGF, "logf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_LOGL, "logl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LRINT, "lrint", BT_FN_LONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LRINTF, "lrintf", BT_FN_LONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LRINTL, "lrintl", BT_FN_LONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LROUND, "lround", BT_FN_LONG_DOUBLE, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LROUNDF, "lroundf", BT_FN_LONG_FLOAT, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_LROUNDL, "lroundl", BT_FN_LONG_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_MODF, "modf", BT_FN_DOUBLE_DOUBLE_DOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFF, "modff", BT_FN_FLOAT_FLOAT_FLOATPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFL, "modfl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_BUILTIN (BUILT_IN_NAN, "nan", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C99_BUILTIN (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C99_BUILTIN (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+#define NAN_TYPE(F) BT_FN_##F##_CONST_STRING
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_NAN, "nan", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C2X_BUILTIN (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C2X_BUILTIN (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C2X_BUILTIN (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_NANS, "nans", NAN_TYPE, ATTR_CONST_NOTHROW_NONNULL)
+#undef NAN_TYPE
+DEF_GCC_BUILTIN (BUILT_IN_NANSD32, "nansd32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANSD64, "nansd64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_GCC_BUILTIN (BUILT_IN_NANSD128, "nansd128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
+DEF_C99_BUILTIN (BUILT_IN_NEARBYINT, "nearbyint", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_NEARBYINTF, "nearbyintf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_NEARBYINTL, "nearbyintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define NEARBYINT_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_NEARBYINT, "nearbyint", NEARBYINT_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef NEARBYINT_TYPE
+DEF_C99_BUILTIN (BUILT_IN_NEXTAFTER, "nextafter", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_NEXTAFTERF, "nextafterf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_NEXTAFTERL, "nextafterl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARD, "nexttoward", BT_FN_DOUBLE_DOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARDF, "nexttowardf", BT_FN_FLOAT_FLOAT_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_NEXTTOWARDL, "nexttowardl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_POW, "pow", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10, "pow10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10F, "pow10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10L, "pow10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_POWF, "powf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN (BUILT_IN_POWI, "powi", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN (BUILT_IN_POWIF, "powif", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN (BUILT_IN_POWIL, "powil", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_POWL, "powl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_REMAINDER, "remainder", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_REMAINDERF, "remainderf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_REMAINDERL, "remainderl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_REMQUO, "remquo", BT_FN_DOUBLE_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_BUILTIN (BUILT_IN_REMQUOF, "remquof", BT_FN_FLOAT_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_BUILTIN (BUILT_IN_REMQUOL, "remquol", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_BUILTIN (BUILT_IN_RINT, "rint", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_RINTF, "rintf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_RINTL, "rintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+#define RINT_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_RINT, "rint", RINT_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef RINT_TYPE
+DEF_C2X_BUILTIN (BUILT_IN_ROUNDEVEN, "roundeven", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_ROUNDEVENF, "roundevenf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C2X_BUILTIN (BUILT_IN_ROUNDEVENL, "roundevenl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_ROUND, "round", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_ROUNDF, "roundf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_ROUNDL, "roundl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define ROUND_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ROUND, "round", ROUND_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef ROUND_TYPE
+#define ROUNDEVEN_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_ROUNDEVEN, "roundeven", ROUNDEVEN_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef ROUNDEVEN_TYPE
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SCALB, "scalb", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SCALBF, "scalbf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SCALBL, "scalbl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_SCALBLN, "scalbln", BT_FN_DOUBLE_DOUBLE_LONG, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_SCALBLNF, "scalblnf", BT_FN_FLOAT_FLOAT_LONG, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_SCALBLNL, "scalblnl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONG, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_SCALBN, "scalbn", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_SCALBNF, "scalbnf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_SCALBNL, "scalbnl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBIT, "signbit", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITF, "signbitf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITL, "signbitl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITD32, "signbitd32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITD64, "signbitd64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITD128, "signbitd128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICAND, "significand", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDF, "significandf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDL, "significandl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_LIB_BUILTIN (BUILT_IN_SIN, "sin", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SINCOS, "sincos", BT_FN_VOID_DOUBLE_DOUBLEPTR_DOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SINCOSF, "sincosf", BT_FN_VOID_FLOAT_FLOATPTR_FLOATPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SINCOSL, "sincosl", BT_FN_VOID_LONGDOUBLE_LONGDOUBLEPTR_LONGDOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_SINF, "sinf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_SINH, "sinh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_SINHF, "sinhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_SINHL, "sinhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_SINL, "sinl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_SQRT, "sqrt", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_SQRTF, "sqrtf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_SQRTL, "sqrtl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+#define SQRT_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_SQRT, "sqrt", SQRT_TYPE, ATTR_MATHFN_FPROUNDING_ERRNO)
+#undef SQRT_TYPE
+DEF_LIB_BUILTIN (BUILT_IN_TAN, "tan", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_TANF, "tanf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_LIB_BUILTIN (BUILT_IN_TANH, "tanh", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_TANHF, "tanhf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_TANHL, "tanhl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_TANL, "tanl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_BUILTIN (BUILT_IN_TGAMMA, "tgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_TGAMMAF, "tgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_TGAMMAL, "tgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_C99_BUILTIN (BUILT_IN_TRUNC, "trunc", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_TRUNCF, "truncf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_TRUNCL, "truncl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#define TRUNC_TYPE(F) BT_FN_##F##_##F
+DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN_TRUNC, "trunc", TRUNC_TYPE, ATTR_CONST_NOTHROW_LEAF_LIST)
+#undef TRUNC_TYPE
+DEF_EXT_LIB_BUILTIN (BUILT_IN_Y0, "y0", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_Y0F, "y0f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_Y0L, "y0l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_Y1, "y1", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_Y1F, "y1f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_Y1L, "y1l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_YN, "yn", BT_FN_DOUBLE_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_YNF, "ynf", BT_FN_FLOAT_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_YNL, "ynl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+
+/* Category: _Complex math builtins. */
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CABS, "cabs", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CABSF, "cabsf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CABSL, "cabsl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOS, "cacos", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSF, "cacosf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSH, "cacosh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSHF, "cacoshf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSHL, "cacoshl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CACOSL, "cacosl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CARG, "carg", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CARGF, "cargf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CARGL, "cargl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CASIN, "casin", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINF, "casinf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINH, "casinh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINHF, "casinhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINHL, "casinhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CASINL, "casinl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CATAN, "catan", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANF, "catanf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANH, "catanh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANHF, "catanhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANHL, "catanhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CATANL, "catanl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOS, "ccos", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSF, "ccosf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSH, "ccosh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSHF, "ccoshf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSHL, "ccoshl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CCOSL, "ccosl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CEXP, "cexp", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CEXPF, "cexpf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CEXPL, "cexpl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN (BUILT_IN_CEXPI, "cexpi", BT_FN_COMPLEX_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN (BUILT_IN_CEXPIF, "cexpif", BT_FN_COMPLEX_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_GCC_BUILTIN (BUILT_IN_CEXPIL, "cexpil", BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CIMAG, "cimag", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CIMAGF, "cimagf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CIMAGL, "cimagl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CLOG, "clog", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CLOGF, "clogf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CLOGL, "clogl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10, "clog10", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10F, "clog10f", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10L, "clog10l", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CONJ, "conj", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CONJF, "conjf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CONJL, "conjl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CPOW, "cpow", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CPOWF, "cpowf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CPOWL, "cpowl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CPROJ, "cproj", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CPROJF, "cprojf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CPROJL, "cprojl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CREAL, "creal", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CREALF, "crealf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CREALL, "creall", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSIN, "csin", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINF, "csinf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINH, "csinh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINHF, "csinhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINHL, "csinhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSINL, "csinl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSQRT, "csqrt", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSQRTF, "csqrtf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CSQRTL, "csqrtl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CTAN, "ctan", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANF, "ctanf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANH, "ctanh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANHF, "ctanhf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANHL, "ctanhl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+DEF_C99_COMPL_BUILTIN (BUILT_IN_CTANL, "ctanl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
+
+/* Category: string/memory builtins. */
+DEF_EXT_LIB_BUILTIN (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMCHR, "memchr", BT_FN_PTR_CONST_PTR_INT_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY, "mempcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_RINDEX, "rindex", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY, "stpcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STPNCPY, "stpncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCASECMP, "strcasecmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCAT, "strcat", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_C2X_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+DEF_C2X_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRNCMP, "strncmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNLEN, "strnlen", BT_FN_SIZE_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRPBRK, "strpbrk", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRRCHR, "strrchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRSPN, "strspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+DEF_LIB_BUILTIN (BUILT_IN_STRSTR, "strstr", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_LEAF)
+
+/* Category: stdio builtins. */
+DEF_LIB_BUILTIN (BUILT_IN_FPRINTF, "fprintf", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_NONNULL_1_FORMAT_PRINTF_2_3)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_UNLOCKED, "fprintf_unlocked", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_NONNULL_1_FORMAT_PRINTF_2_3)
+DEF_LIB_BUILTIN (BUILT_IN_PUTC, "putc", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTC_UNLOCKED, "putc_unlocked", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_FPUTC, "fputc", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FPUTC_UNLOCKED, "fputc_unlocked", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_FPUTS, "fputs", BT_FN_INT_CONST_STRING_FILEPTR, ATTR_NONNULL_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FPUTS_UNLOCKED, "fputs_unlocked", BT_FN_INT_CONST_STRING_FILEPTR, ATTR_NONNULL_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_FSCANF, "fscanf", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3)
+DEF_LIB_BUILTIN (BUILT_IN_FWRITE, "fwrite", BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, ATTR_NONNULL_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FWRITE_UNLOCKED, "fwrite_unlocked", BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, ATTR_NONNULL_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_PRINTF, "printf", BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_1_2)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_PRINTF_UNLOCKED, "printf_unlocked", BT_FN_INT_CONST_STRING_VAR, ATTR_NONNULL_1_FORMAT_PRINTF_1_2)
+DEF_LIB_BUILTIN (BUILT_IN_PUTCHAR, "putchar", BT_FN_INT_INT, ATTR_NULL)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTCHAR_UNLOCKED, "putchar_unlocked", BT_FN_INT_INT, ATTR_NULL)
+DEF_LIB_BUILTIN (BUILT_IN_PUTS, "puts", BT_FN_INT_CONST_STRING, ATTR_NONNULL_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTS_UNLOCKED, "puts_unlocked", BT_FN_INT_CONST_STRING, ATTR_NONNULL_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_SCANF, "scanf", BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_SCANF_1_2)
+DEF_C99_BUILTIN (BUILT_IN_SNPRINTF, "snprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_3_4)
+
+DEF_LIB_BUILTIN (BUILT_IN_SPRINTF, "sprintf", BT_FN_INT_STRING_CONST_STRING_VAR, ATTR_NOTHROW_NONNULL_1_FORMAT_PRINTF_2_3)
+DEF_LIB_BUILTIN (BUILT_IN_SSCANF, "sscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_FORMAT_SCANF_NOTHROW_2_3)
+DEF_LIB_BUILTIN (BUILT_IN_VFPRINTF, "vfprintf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_NONNULL_1_FORMAT_PRINTF_2_0)
+DEF_C99_BUILTIN (BUILT_IN_VFSCANF, "vfscanf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
+DEF_LIB_BUILTIN (BUILT_IN_VPRINTF, "vprintf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_1_0)
+DEF_C99_BUILTIN (BUILT_IN_VSCANF, "vscanf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_1_0)
+DEF_C99_BUILTIN (BUILT_IN_VSNPRINTF, "vsnprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_3_0)
+DEF_LIB_BUILTIN (BUILT_IN_VSPRINTF, "vsprintf", BT_FN_INT_STRING_CONST_STRING_VALIST_ARG, ATTR_NOTHROW_NONNULL_1_FORMAT_PRINTF_2_0)
+DEF_C99_BUILTIN (BUILT_IN_VSSCANF, "vsscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_NOTHROW_2_0)
+
+/* Category: ctype builtins. */
+DEF_LIB_BUILTIN (BUILT_IN_ISALNUM, "isalnum", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISALPHA, "isalpha", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISASCII, "isascii", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_ISBLANK, "isblank", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISCNTRL, "iscntrl", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISDIGIT, "isdigit", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISGRAPH, "isgraph", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISLOWER, "islower", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISPRINT, "isprint", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISPUNCT, "ispunct", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISSPACE, "isspace", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISUPPER, "isupper", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ISXDIGIT, "isxdigit", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_TOASCII, "toascii", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_TOLOWER, "tolower", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_TOUPPER, "toupper", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+
+/* Category: wctype builtins. */
+DEF_C94_BUILTIN (BUILT_IN_ISWALNUM, "iswalnum", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWALPHA, "iswalpha", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN_ISWBLANK, "iswblank", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWCNTRL, "iswcntrl", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWDIGIT, "iswdigit", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWGRAPH, "iswgraph", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWLOWER, "iswlower", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWPRINT, "iswprint", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWPUNCT, "iswpunct", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWSPACE, "iswspace", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWUPPER, "iswupper", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_ISWXDIGIT, "iswxdigit", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_TOWLOWER, "towlower", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_C94_BUILTIN (BUILT_IN_TOWUPPER, "towupper", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LEAF_LIST)
+
+/* Category: integer overflow checking builtins. */
+DEF_GCC_BUILTIN (BUILT_IN_ADD_OVERFLOW, "add_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_SUB_OVERFLOW, "sub_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_MUL_OVERFLOW, "mul_overflow", BT_FN_BOOL_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ADD_OVERFLOW_P, "add_overflow_p", BT_FN_BOOL_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_SUB_OVERFLOW_P, "sub_overflow_p", BT_FN_BOOL_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_MUL_OVERFLOW_P, "mul_overflow_p", BT_FN_BOOL_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+/* Clang compatibility. */
+DEF_GCC_BUILTIN (BUILT_IN_SADD_OVERFLOW, "sadd_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SADDL_OVERFLOW, "saddl_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SADDLL_OVERFLOW, "saddll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SSUB_OVERFLOW, "ssub_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SSUBL_OVERFLOW, "ssubl_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SSUBLL_OVERFLOW, "ssubll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SMUL_OVERFLOW, "smul_overflow", BT_FN_BOOL_INT_INT_INTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SMULL_OVERFLOW, "smull_overflow", BT_FN_BOOL_LONG_LONG_LONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SMULLL_OVERFLOW, "smulll_overflow", BT_FN_BOOL_LONGLONG_LONGLONG_LONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UADD_OVERFLOW, "uadd_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UADDL_OVERFLOW, "uaddl_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UADDLL_OVERFLOW, "uaddll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_USUB_OVERFLOW, "usub_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_USUBL_OVERFLOW, "usubl_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_USUBLL_OVERFLOW, "usubll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UMUL_OVERFLOW, "umul_overflow", BT_FN_BOOL_UINT_UINT_UINTPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UMULL_OVERFLOW, "umull_overflow", BT_FN_BOOL_ULONG_ULONG_ULONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UMULLL_OVERFLOW, "umulll_overflow", BT_FN_BOOL_ULONGLONG_ULONGLONG_ULONGLONGPTR, ATTR_NOTHROW_NONNULL_LEAF_LIST)
+
+/* Category: miscellaneous builtins. */
+DEF_LIB_BUILTIN (BUILT_IN_ABORT, "abort", BT_FN_VOID, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_COLD_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_ABS, "abs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_AGGREGATE_INCOMING_ADDRESS, "aggregate_incoming_address", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ALLOCA, "alloca", BT_FN_PTR_SIZE, ATTR_ALLOCA_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_APPLY, "apply", BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, ATTR_NULL)
+DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_BSWAP16, "bswap16", BT_FN_UINT16_UINT16, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_BSWAP128, "bswap128", BT_FN_UINT128_UINT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+
+DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
+/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */
+DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_2_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLEAR_PADDING, "clear_padding", BT_FN_VOID_VAR, ATTR_NOTHROW_NONNULL_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLZIMAX, "clzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLZL, "clzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLZLL, "clzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CONSTANT_P, "constant_p", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CTZ, "ctz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CTZIMAX, "ctzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CTZL, "ctzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CTZLL, "ctzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLRSB, "clrsb", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLRSBIMAX, "clrsbimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLRSBL, "clrsbl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_CLRSBLL, "clrsbll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_DCGETTEXT, "dcgettext", BT_FN_STRING_CONST_STRING_CONST_STRING_INT, ATTR_FORMAT_ARG_2)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_DGETTEXT, "dgettext", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_FORMAT_ARG_2)
+DEF_GCC_BUILTIN (BUILT_IN_DWARF_CFA, "dwarf_cfa", BT_FN_PTR, ATTR_NULL)
+DEF_GCC_BUILTIN (BUILT_IN_DWARF_SP_COLUMN, "dwarf_sp_column", BT_FN_UINT, ATTR_NULL)
+DEF_GCC_BUILTIN (BUILT_IN_EH_RETURN, "eh_return", BT_FN_VOID_PTRMODE_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_EH_RETURN_DATA_REGNO, "eh_return_data_regno", BT_FN_INT_INT, ATTR_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECL, "execl", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECLP, "execlp", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECLE, "execle", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_NOTHROW_SENTINEL_1)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECV, "execv", BT_FN_INT_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVP, "execvp", BT_FN_INT_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_EXPECT_WITH_PROBABILITY, "expect_with_probability", BT_FN_LONG_LONG_LONG_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_ASSUME_ALIGNED, "assume_aligned", BT_FN_PTR_CONST_PTR_SIZE_VAR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_UNWINDWORD_PTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_EXTRACT_RETURN_ADDR, "extract_return_addr", BT_FN_PTR_PTR, ATTR_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FFS, "ffs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSIMAX, "ffsimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL)
+/* [trans-mem]: Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed. */
+DEF_LIB_BUILTIN (BUILT_IN_FREE, "free", BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
+DEF_C99_BUILTIN (BUILT_IN_IMAXABS, "imaxabs", BT_FN_INTMAX_INTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_INIT_DWARF_REG_SIZES, "init_dwarf_reg_size_table", BT_FN_VOID_PTR, ATTR_NULL)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITE, "finite", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEF, "finitef", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED64, "finited64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED128, "finited128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FPCLASSIFY, "fpclassify", BT_FN_INT_INT_INT_INT_INT_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ISFINITE, "isfinite", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ISINF_SIGN, "isinf_sign", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFF, "isinff", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD32, "isinfd32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD64, "isinfd64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD128, "isinfd128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_ISNORMAL, "isnormal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
+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_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)
+/* [trans-mem]: Adjust BUILT_IN_TM_MALLOC if BUILT_IN_MALLOC is changed. */
+DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_WARN_UNUSED_RESULT_SIZE_1_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_PARITYIMAX, "parityimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_PARITYL, "parityl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_PARITYLL, "parityll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_POPCOUNT, "popcount", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTIMAX, "popcountimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_POSIX_MEMALIGN, "posix_memalign", BT_FN_INT_PTRPTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LEAF_LIST)
+DEF_LIB_BUILTIN (BUILT_IN_REALLOC, "realloc", BT_FN_PTR_PTR_SIZE, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
+DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_RT_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4)
+DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0)
+DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LEAF_COLD_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_COLD_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL)
+DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR, ATTR_NULL)
+DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_VA_END, "va_end", BT_FN_VOID_VALIST_REF, ATTR_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_VA_START, "va_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK, "va_arg_pack", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_VA_ARG_PACK_LEN, "va_arg_pack_len", BT_FN_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_C99_BUILTIN (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+
+/* Implementing nested functions. */
+DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline")
+DEF_BUILTIN_STUB (BUILT_IN_INIT_HEAP_TRAMPOLINE, "__builtin_init_heap_trampoline")
+DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline")
+DEF_BUILTIN_STUB (BUILT_IN_INIT_DESCRIPTOR, "__builtin_init_descriptor")
+DEF_BUILTIN_STUB (BUILT_IN_ADJUST_DESCRIPTOR, "__builtin_adjust_descriptor")
+DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto")
+
+/* Implementing __builtin_setjmp. */
+DEF_BUILTIN_STUB (BUILT_IN_SETJMP_SETUP, "__builtin_setjmp_setup")
+DEF_BUILTIN_STUB (BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver")
+
+/* Implementing variable sized local variables. */
+DEF_BUILTIN_STUB (BUILT_IN_STACK_SAVE, "__builtin_stack_save")
+DEF_BUILTIN_STUB (BUILT_IN_STACK_RESTORE, "__builtin_stack_restore")
+DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN, "__builtin_alloca_with_align")
+DEF_BUILTIN_STUB (BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX, "__builtin_alloca_with_align_and_max")
+
+/* An internal version of memcmp, used when the result is only tested for
+ equality with zero. */
+DEF_BUILTIN_STUB (BUILT_IN_MEMCMP_EQ, "__builtin_memcmp_eq")
+
+/* An internal version of strcmp/strncmp, used when the result is only
+ tested for equality with zero. */
+DEF_BUILTIN_STUB (BUILT_IN_STRCMP_EQ, "__builtin_strcmp_eq")
+DEF_BUILTIN_STUB (BUILT_IN_STRNCMP_EQ, "__builtin_strncmp_eq")
+
+/* Object size checking builtins. */
+DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_DYNAMIC_OBJECT_SIZE, "dynamic_object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LEAF_LIST)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY_CHK, "__stpcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STPNCPY_CHK, "__stpncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_RETNONNULL_NOTHROW_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_NOTHROW_5_6)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_SPRINTF_CHK, "__sprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR, ATTR_NOTHROW_NONNULL_1_FORMAT_PRINTF_4_5)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_NOTHROW_5_0)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VSPRINTF_CHK, "__vsprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_NOTHROW_NONNULL_1_FORMAT_PRINTF_4_0)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_CHK, "__fprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VAR, ATTR_NONNULL_1_FORMAT_PRINTF_3_4)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_PRINTF_CHK, "__printf_chk", BT_FN_INT_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VFPRINTF_CHK, "__vfprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG, ATTR_NONNULL_1_FORMAT_PRINTF_3_0)
+DEF_EXT_LIB_BUILTIN (BUILT_IN_VPRINTF_CHK, "__vprintf_chk", BT_FN_INT_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
+
+/* Profiling hooks. */
+DEF_BUILTIN (BUILT_IN_PROFILE_FUNC_ENTER, "__cyg_profile_func_enter", BUILT_IN_NORMAL, BT_FN_VOID_PTR_PTR, BT_LAST,
+ false, false, false, ATTR_NULL, true, true)
+DEF_BUILTIN (BUILT_IN_PROFILE_FUNC_EXIT, "__cyg_profile_func_exit", BUILT_IN_NORMAL, BT_FN_VOID_PTR_PTR, BT_LAST,
+ false, false, false, ATTR_NULL, true, true)
+
+/* TLS thread pointer related builtins. */
+DEF_BUILTIN (BUILT_IN_THREAD_POINTER, "__builtin_thread_pointer",
+ BUILT_IN_NORMAL, BT_FN_PTR, BT_LAST,
+ false, false, true, ATTR_CONST_NOTHROW_LIST, true,
+ targetm.have_tls)
+
+DEF_BUILTIN (BUILT_IN_SET_THREAD_POINTER, "__builtin_set_thread_pointer",
+ BUILT_IN_NORMAL, BT_FN_VOID_PTR, BT_LAST,
+ false, false, true, ATTR_NOTHROW_LIST, true,
+ targetm.have_tls)
+
+/* TLS emulation. */
+DEF_BUILTIN (BUILT_IN_EMUTLS_GET_ADDRESS, targetm.emutls.get_address,
+ BUILT_IN_NORMAL,
+ BT_FN_PTR_PTR, BT_FN_PTR_PTR,
+ true, true, true, ATTR_CONST_NOTHROW_NONNULL_LEAF, false,
+ !targetm.have_tls)
+DEF_BUILTIN (BUILT_IN_EMUTLS_REGISTER_COMMON,
+ targetm.emutls.register_common, BUILT_IN_NORMAL,
+ BT_FN_VOID_PTR_WORD_WORD_PTR, BT_FN_VOID_PTR_WORD_WORD_PTR,
+ true, true, true, ATTR_NOTHROW_LEAF_LIST, false,
+ !targetm.have_tls)
+
+/* Suppressing speculation. Users are expected to use the first (N)
+ variant, which will be translated internally into one of the other
+ types. */
+
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_N, "speculation_safe_value",
+ BT_FN_VOID_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_PTR,
+ "speculation_safe_value_ptr", BT_FN_PTR_PTR_VAR,
+ ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_1, "speculation_safe_value_1",
+ BT_FN_I1_I1_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_2, "speculation_safe_value_2",
+ BT_FN_I2_I2_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_4, "speculation_safe_value_4",
+ BT_FN_I4_I4_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_8, "speculation_safe_value_8",
+ BT_FN_I8_I8_VAR, ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_VALUE_16,
+ "speculation_safe_value_16", BT_FN_I16_I16_VAR,
+ ATTR_NOVOPS_NOTHROW_LEAF_LIST)
+
+/* Exception support. */
+DEF_BUILTIN_STUB (BUILT_IN_UNWIND_RESUME, "__builtin_unwind_resume")
+DEF_BUILTIN_STUB (BUILT_IN_CXA_END_CLEANUP, "__builtin_cxa_end_cleanup")
+DEF_BUILTIN_STUB (BUILT_IN_EH_POINTER, "__builtin_eh_pointer")
+DEF_BUILTIN_STUB (BUILT_IN_EH_FILTER, "__builtin_eh_filter")
+DEF_BUILTIN_STUB (BUILT_IN_EH_COPY_VALUES, "__builtin_eh_copy_values")
+
+/* __FILE__, __LINE__, __FUNCTION__ as builtins. */
+DEF_GCC_BUILTIN (BUILT_IN_FILE, "FILE", BT_FN_CONST_STRING, ATTR_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_FUNCTION, "FUNCTION", BT_FN_CONST_STRING, ATTR_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST)
+
+/* Synchronization Primitives. */
+#include "sync-builtins.def"
+
+/* Offloading and Multi Processing builtins. */
+#include "omp-builtins.def"
+
+/* GTM builtins. */
+#include "gtm-builtins.def"
+
+/* Sanitizer builtins. */
+#include "sanitizer.def"
+
+/* Coroutine builtins. */
+#include "coroutine-builtins.def"
+
+#undef DEF_BUILTIN
diff --git a/support/cpp/gcc/c-family/c-ada-spec.h b/support/cpp/gcc/c-family/c-ada-spec.h
new file mode 100644
index 000000000..d3ba0f4a1
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-ada-spec.h
@@ -0,0 +1,44 @@
+/* Interface for -fdump-ada-spec capability.
+ Copyright (C) 2010-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 C_ADA_SPEC_H
+#define C_ADA_SPEC_H
+
+#include "pretty-print.h"
+
+/* In c-ada-spec.cc */
+
+enum cpp_operation {
+ HAS_DEPENDENT_TEMPLATE_ARGS,
+ IS_ABSTRACT,
+ IS_ASSIGNMENT_OPERATOR,
+ IS_CONSTRUCTOR,
+ IS_DESTRUCTOR,
+ IS_COPY_CONSTRUCTOR,
+ IS_MOVE_CONSTRUCTOR,
+ IS_TEMPLATE,
+ IS_TRIVIAL
+};
+
+extern void collect_ada_nodes (tree, const char *);
+extern void collect_source_ref (const char *);
+extern void dump_ada_specs (void (*)(const char *),
+ int (*)(tree, cpp_operation));
+
+#endif /* ! C_ADA_SPEC_H */
diff --git a/support/cpp/gcc/c-family/c-common.cc b/support/cpp/gcc/c-family/c-common.cc
new file mode 100644
index 000000000..c9ea671ea
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-common.cc
@@ -0,0 +1,9583 @@
+/* Subroutines shared by all languages that are variants of C.
+ 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/>. */
+
+#define GCC_C_COMMON_C
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "mem-stats-traits.h" // sdcpp
+#include "c-common.h"
+// sdcpp #include "gimple-expr.h"
+#include "tm_p.h"
+#include "stringpool.h"
+#include "diagnostic.h"
+#include "attribs.h"
+#include "varasm.h"
+#include "c-objc.h"
+#include "common/common-target.h"
+#include "langhooks.h"
+#include "toplev.h"
+#include "tree-iterator.h"
+#include "opts.h"
+#include "gimplify.h"
+#include "substring-locations.h"
+#include "spellcheck.h"
+#include "c-spellcheck.h"
+// sdcpp #include "selftest.h"
+#include "debug.h"
+
+// #include "defaults.h" // sdcpp
+
+cpp_reader *parse_in; /* Declared in c-pragma.h. */
+
+
+/* Mode used to build pointers (VOIDmode means ptr_mode). */
+
+machine_mode c_default_pointer_mode = VOIDmode;
+
+/* The following symbols are subsumed in the c_global_trees array, and
+ listed here individually for documentation purposes.
+
+ INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
+
+ tree short_integer_type_node;
+ tree long_integer_type_node;
+ tree long_long_integer_type_node;
+
+ tree short_unsigned_type_node;
+ tree long_unsigned_type_node;
+ tree long_long_unsigned_type_node;
+
+ tree truthvalue_type_node;
+ tree truthvalue_false_node;
+ tree truthvalue_true_node;
+
+ tree ptrdiff_type_node;
+
+ tree unsigned_char_type_node;
+ tree signed_char_type_node;
+ tree wchar_type_node;
+
+ tree char8_type_node;
+ tree char16_type_node;
+ tree char32_type_node;
+
+ tree float_type_node;
+ tree double_type_node;
+ tree long_double_type_node;
+
+ tree complex_integer_type_node;
+ tree complex_float_type_node;
+ tree complex_double_type_node;
+ tree complex_long_double_type_node;
+
+ tree dfloat32_type_node;
+ tree dfloat64_type_node;
+ tree_dfloat128_type_node;
+
+ tree intQI_type_node;
+ tree intHI_type_node;
+ tree intSI_type_node;
+ tree intDI_type_node;
+ tree intTI_type_node;
+
+ tree unsigned_intQI_type_node;
+ tree unsigned_intHI_type_node;
+ tree unsigned_intSI_type_node;
+ tree unsigned_intDI_type_node;
+ tree unsigned_intTI_type_node;
+
+ tree widest_integer_literal_type_node;
+ tree widest_unsigned_literal_type_node;
+
+ Nodes for types `void *' and `const void *'.
+
+ tree ptr_type_node, const_ptr_type_node;
+
+ Nodes for types `char *' and `const char *'.
+
+ tree string_type_node, const_string_type_node;
+
+ Type `char[SOMENUMBER]'.
+ Used when an array of char is needed and the size is irrelevant.
+
+ tree char_array_type_node;
+
+ Type `wchar_t[SOMENUMBER]' or something like it.
+ Used when a wide string literal is created.
+
+ tree wchar_array_type_node;
+
+ Type `char8_t[SOMENUMBER]' or something like it.
+ Used when a UTF-8 string literal is created.
+
+ tree char8_array_type_node;
+
+ Type `char16_t[SOMENUMBER]' or something like it.
+ Used when a UTF-16 string literal is created.
+
+ tree char16_array_type_node;
+
+ Type `char32_t[SOMENUMBER]' or something like it.
+ Used when a UTF-32 string literal is created.
+
+ tree char32_array_type_node;
+
+ Type `int ()' -- used for implicit declaration of functions.
+
+ tree default_function_type;
+
+ A VOID_TYPE node, packaged in a TREE_LIST.
+
+ tree void_list_node;
+
+ The lazily created VAR_DECLs for __FUNCTION__, __PRETTY_FUNCTION__,
+ and __func__. (C doesn't generate __FUNCTION__ and__PRETTY_FUNCTION__
+ VAR_DECLS, but C++ does.)
+
+ tree function_name_decl_node;
+ tree pretty_function_name_decl_node;
+ tree c99_function_name_decl_node;
+
+ Stack of nested function name VAR_DECLs.
+
+ tree saved_function_name_decls;
+
+*/
+
+tree c_global_trees[CTI_MAX];
+
+/* Switches common to the C front ends. */
+
+/* Nonzero means don't output line number information. */
+
+char flag_no_line_commands;
+
+/* Nonzero causes -E output not to be done, but directives such as
+ #define that have side effects are still obeyed. */
+
+char flag_no_output;
+
+/* Nonzero means dump macros in some fashion. */
+
+char flag_dump_macros;
+
+/* Nonzero means pass #include lines through to the output. */
+
+char flag_dump_includes;
+
+/* Nonzero means process PCH files while preprocessing. */
+
+bool flag_pch_preprocess;
+
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+const char *pch_file;
+
+/* Nonzero if an ISO standard was selected. It rejects macros in the
+ user's namespace. */
+int flag_iso;
+
+/* C/ObjC language option variables. */
+
+
+/* Nonzero means allow type mismatches in conditional expressions;
+ just make their values `void'. */
+
+int flag_cond_mismatch;
+
+/* Nonzero means enable C89 Amendment 1 features. */
+
+int flag_isoc94;
+
+/* Nonzero means use the ISO C99 (or C11) dialect of C. */
+
+int flag_isoc99;
+
+/* Nonzero means use the ISO C11 dialect of C. */
+
+int flag_isoc11;
+
+/* Nonzero means use the ISO C2X dialect of C. */
+
+int flag_isoc2x;
+
+
+/* Nonzero means that we have builtin functions, and main is an int. */
+
+int flag_hosted = 1;
+
+
+/* ObjC language option variables. */
+
+
+/* Tells the compiler that this is a special run. Do not perform any
+ compiling, instead we are to test some platform dependent features
+ and output a C header file with appropriate definitions. */
+
+int print_struct_values;
+
+/* Tells the compiler what is the constant string class for ObjC. */
+
+const char *constant_string_class_name;
+
+
+/* C++ language option variables. */
+
+/* The reference version of the ABI for -Wabi. */
+
+int warn_abi_version = -1;
+
+/* The C++ dialect being used. Default set in c_common_post_options. */
+
+enum cxx_dialect cxx_dialect = cxx_unset;
+
+/* Maximum template instantiation depth. This limit exists to limit the
+ time it takes to notice excessively recursive template instantiations.
+
+ The default is lower than the 1024 recommended by the C++0x standard
+ because G++ runs out of stack before 1024 with highly recursive template
+ argument deduction substitution (g++.dg/cpp0x/enum11.C). */
+
+int max_tinst_depth = 900;
+#if 0 // sdcpp
+
+/* The elements of `ridpointers' are identifier nodes for the reserved
+ type names and storage classes. It is indexed by a RID_... value. */
+tree *ridpointers;
+
+tree (*make_fname_decl) (location_t, tree, int);
+#endif // sdcpp
+
+/* Nonzero means don't warn about problems that occur when the code is
+ executed. */
+int c_inhibit_evaluation_warnings;
+
+/* Whether we are building a boolean conversion inside
+ convert_for_assignment, or some other late binary operation. If
+ build_binary_op is called for C (from code shared by C and C++) in
+ this case, then the operands have already been folded and the
+ result will not be folded again, so C_MAYBE_CONST_EXPR should not
+ be generated. */
+bool in_late_binary_op;
+
+/* Whether lexing has been completed, so subsequent preprocessor
+ errors should use the compiler's input_location. */
+bool done_lexing = false;
+#if 0 // sdcpp
+
+/* Information about how a function name is generated. */
+struct fname_var_t
+{
+ tree *const decl; /* pointer to the VAR_DECL. */
+ const unsigned rid; /* RID number for the identifier. */
+ const int pretty; /* How pretty is it? */
+};
+
+/* The three ways of getting then name of the current function. */
+
+const struct fname_var_t fname_vars[] =
+{
+ /* C99 compliant __func__, must be first. */
+ {&c99_function_name_decl_node, RID_C99_FUNCTION_NAME, 0},
+ /* GCC __FUNCTION__ compliant. */
+ {&function_name_decl_node, RID_FUNCTION_NAME, 0},
+ /* GCC __PRETTY_FUNCTION__ compliant. */
+ {&pretty_function_name_decl_node, RID_PRETTY_FUNCTION_NAME, 1},
+ {NULL, 0, 0},
+};
+
+#endif // sdcpp
+/* Global visibility options. */
+struct visibility_flags visibility_options;
+#if 0 // sdcpp
+
+static tree check_case_value (location_t, tree);
+
+
+static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
+static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
+
+/* Reserved words. The third field is a mask: keywords are disabled
+ 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
+ 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
+ C++ --std=c++20: D_CONLY | D_OBJC
+ ObjC++ is like C++ except that D_OBJC is not set
+
+ If -fno-asm is used, D_ASM is added to the mask. If
+ -fno-gnu-keywords is used, D_EXT is added. If -fno-asm and C in
+ C89 mode, D_EXT89 is added for both -fno-asm and -fno-gnu-keywords.
+ In C with -Wc++-compat, we warn if D_CXXWARN is set.
+
+ Note the complication of the D_CXX_OBJC keywords. These are
+ reserved words such as 'class'. In C++, 'class' is a reserved
+ word. In Objective-C++ it is too. In Objective-C, it is a
+ reserved word too, but only if it follows an '@' sign.
+*/
+const struct c_common_resword c_common_reswords[] =
+{
+ { "_Alignas", RID_ALIGNAS, D_CONLY },
+ { "_Alignof", RID_ALIGNOF, D_CONLY },
+ { "_Atomic", RID_ATOMIC, D_CONLY },
+ { "_Bool", RID_BOOL, D_CONLY },
+ { "_Complex", RID_COMPLEX, 0 },
+ { "_Imaginary", RID_IMAGINARY, D_CONLY },
+ { "_Float16", RID_FLOAT16, D_CONLY },
+ { "_Float32", RID_FLOAT32, D_CONLY },
+ { "_Float64", RID_FLOAT64, D_CONLY },
+ { "_Float128", RID_FLOAT128, D_CONLY },
+ { "_Float32x", RID_FLOAT32X, D_CONLY },
+ { "_Float64x", RID_FLOAT64X, D_CONLY },
+ { "_Float128x", RID_FLOAT128X, D_CONLY },
+ { "_Decimal32", RID_DFLOAT32, D_CONLY },
+ { "_Decimal64", RID_DFLOAT64, D_CONLY },
+ { "_Decimal128", RID_DFLOAT128, D_CONLY },
+ { "_Fract", RID_FRACT, D_CONLY | D_EXT },
+ { "_Accum", RID_ACCUM, D_CONLY | D_EXT },
+ { "_Sat", RID_SAT, D_CONLY | D_EXT },
+ { "_Static_assert", RID_STATIC_ASSERT, D_CONLY },
+ { "_Noreturn", RID_NORETURN, D_CONLY },
+ { "_Generic", RID_GENERIC, D_CONLY },
+ { "_Thread_local", RID_THREAD, D_CONLY },
+ { "__FUNCTION__", RID_FUNCTION_NAME, 0 },
+ { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
+ { "__alignof", RID_ALIGNOF, 0 },
+ { "__alignof__", RID_ALIGNOF, 0 },
+ { "__asm", RID_ASM, 0 },
+ { "__asm__", RID_ASM, 0 },
+ { "__attribute", RID_ATTRIBUTE, 0 },
+ { "__attribute__", RID_ATTRIBUTE, 0 },
+ { "__auto_type", RID_AUTO_TYPE, D_CONLY },
+ { "__bases", RID_BASES, D_CXXONLY },
+ { "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY },
+ { "__builtin_bit_cast", RID_BUILTIN_BIT_CAST, D_CXXONLY },
+ { "__builtin_call_with_static_chain",
+ RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
+ { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
+ { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
+ { "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 },
+ { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 },
+ { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY },
+ { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 },
+ { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 },
+ { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 },
+ { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY },
+ { "__builtin_offsetof", RID_OFFSETOF, 0 },
+ { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
+ { "__builtin_va_arg", RID_VA_ARG, 0 },
+ { "__complex", RID_COMPLEX, 0 },
+ { "__complex__", RID_COMPLEX, 0 },
+ { "__const", RID_CONST, 0 },
+ { "__const__", RID_CONST, 0 },
+ { "__constinit", RID_CONSTINIT, D_CXXONLY },
+ { "__decltype", RID_DECLTYPE, D_CXXONLY },
+ { "__direct_bases", RID_DIRECT_BASES, D_CXXONLY },
+ { "__extension__", RID_EXTENSION, 0 },
+ { "__func__", RID_C99_FUNCTION_NAME, 0 },
+ { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
+ { "__has_nothrow_constructor", RID_HAS_NOTHROW_CONSTRUCTOR, D_CXXONLY },
+ { "__has_nothrow_copy", RID_HAS_NOTHROW_COPY, D_CXXONLY },
+ { "__has_trivial_assign", RID_HAS_TRIVIAL_ASSIGN, D_CXXONLY },
+ { "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, D_CXXONLY },
+ { "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, D_CXXONLY },
+ { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
+ { "__has_unique_object_representations", RID_HAS_UNIQUE_OBJ_REPRESENTATIONS,
+ D_CXXONLY },
+ { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
+ { "__imag", RID_IMAGPART, 0 },
+ { "__imag__", RID_IMAGPART, 0 },
+ { "__inline", RID_INLINE, 0 },
+ { "__inline__", RID_INLINE, 0 },
+ { "__is_abstract", RID_IS_ABSTRACT, D_CXXONLY },
+ { "__is_aggregate", RID_IS_AGGREGATE, D_CXXONLY },
+ { "__is_base_of", RID_IS_BASE_OF, D_CXXONLY },
+ { "__is_class", RID_IS_CLASS, D_CXXONLY },
+ { "__is_empty", RID_IS_EMPTY, D_CXXONLY },
+ { "__is_enum", RID_IS_ENUM, D_CXXONLY },
+ { "__is_final", RID_IS_FINAL, D_CXXONLY },
+ { "__is_layout_compatible", RID_IS_LAYOUT_COMPATIBLE, D_CXXONLY },
+ { "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY },
+ { "__is_pointer_interconvertible_base_of",
+ RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF, D_CXXONLY },
+ { "__is_pod", RID_IS_POD, D_CXXONLY },
+ { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
+ { "__is_same", RID_IS_SAME_AS, D_CXXONLY },
+ { "__is_same_as", RID_IS_SAME_AS, D_CXXONLY },
+ { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
+ { "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY },
+ { "__is_trivially_assignable", RID_IS_TRIVIALLY_ASSIGNABLE, D_CXXONLY },
+ { "__is_trivially_constructible", RID_IS_TRIVIALLY_CONSTRUCTIBLE, D_CXXONLY },
+ { "__is_trivially_copyable", RID_IS_TRIVIALLY_COPYABLE, D_CXXONLY },
+ { "__is_union", RID_IS_UNION, D_CXXONLY },
+ { "__label__", RID_LABEL, 0 },
+ { "__null", RID_NULL, 0 },
+ { "__real", RID_REALPART, 0 },
+ { "__real__", RID_REALPART, 0 },
+ { "__restrict", RID_RESTRICT, 0 },
+ { "__restrict__", RID_RESTRICT, 0 },
+ { "__signed", RID_SIGNED, 0 },
+ { "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
+ { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 },
+ { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 },
+ { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 },
+ { "__typeof", RID_TYPEOF, 0 },
+ { "__typeof__", RID_TYPEOF, 0 },
+ { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
+ { "__volatile", RID_VOLATILE, 0 },
+ { "__volatile__", RID_VOLATILE, 0 },
+ { "__GIMPLE", RID_GIMPLE, D_CONLY },
+ { "__PHI", RID_PHI, D_CONLY },
+ { "__RTL", RID_RTL, D_CONLY },
+ { "alignas", RID_ALIGNAS, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "asm", RID_ASM, D_ASM },
+ { "auto", RID_AUTO, 0 },
+ { "bool", RID_BOOL, D_CXXONLY | D_CXXWARN },
+ { "break", RID_BREAK, 0 },
+ { "case", RID_CASE, 0 },
+ { "catch", RID_CATCH, D_CXX_OBJC | D_CXXWARN },
+ { "char", RID_CHAR, 0 },
+ { "char8_t", RID_CHAR8, D_CXX_CHAR8_T_FLAGS | D_CXXWARN },
+ { "char16_t", RID_CHAR16, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "char32_t", RID_CHAR32, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
+ { "const", RID_CONST, 0 },
+ { "consteval", RID_CONSTEVAL, D_CXXONLY | D_CXX20 | D_CXXWARN },
+ { "constexpr", RID_CONSTEXPR, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "constinit", RID_CONSTINIT, D_CXXONLY | D_CXX20 | D_CXXWARN },
+ { "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN },
+ { "continue", RID_CONTINUE, 0 },
+ { "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "default", RID_DEFAULT, 0 },
+ { "delete", RID_DELETE, D_CXXONLY | D_CXXWARN },
+ { "do", RID_DO, 0 },
+ { "double", RID_DOUBLE, 0 },
+ { "dynamic_cast", RID_DYNCAST, D_CXXONLY | D_CXXWARN },
+ { "else", RID_ELSE, 0 },
+ { "enum", RID_ENUM, 0 },
+ { "explicit", RID_EXPLICIT, D_CXXONLY | D_CXXWARN },
+ { "export", RID_EXPORT, D_CXXONLY | D_CXXWARN },
+ { "extern", RID_EXTERN, 0 },
+ { "false", RID_FALSE, D_CXXONLY | D_CXXWARN },
+ { "float", RID_FLOAT, 0 },
+ { "for", RID_FOR, 0 },
+ { "friend", RID_FRIEND, D_CXXONLY | D_CXXWARN },
+ { "goto", RID_GOTO, 0 },
+ { "if", RID_IF, 0 },
+ { "inline", RID_INLINE, D_EXT89 },
+ { "int", RID_INT, 0 },
+ { "long", RID_LONG, 0 },
+ { "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN },
+ { "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 },
+ { "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN },
+ { "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN },
+ { "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN },
+ { "public", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN },
+ { "register", RID_REGISTER, 0 },
+ { "reinterpret_cast", RID_REINTCAST, D_CXXONLY | D_CXXWARN },
+ { "restrict", RID_RESTRICT, D_CONLY | D_C99 },
+ { "return", RID_RETURN, 0 },
+ { "short", RID_SHORT, 0 },
+ { "signed", RID_SIGNED, 0 },
+ { "sizeof", RID_SIZEOF, 0 },
+ { "static", RID_STATIC, 0 },
+ { "static_assert", RID_STATIC_ASSERT, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "static_cast", RID_STATCAST, D_CXXONLY | D_CXXWARN },
+ { "struct", RID_STRUCT, 0 },
+ { "switch", RID_SWITCH, 0 },
+ { "template", RID_TEMPLATE, D_CXXONLY | D_CXXWARN },
+ { "this", RID_THIS, D_CXXONLY | D_CXXWARN },
+ { "thread_local", RID_THREAD, D_CXXONLY | D_CXX11 | D_CXXWARN },
+ { "throw", RID_THROW, D_CXX_OBJC | D_CXXWARN },
+ { "true", RID_TRUE, D_CXXONLY | D_CXXWARN },
+ { "try", RID_TRY, D_CXX_OBJC | D_CXXWARN },
+ { "typedef", RID_TYPEDEF, 0 },
+ { "typename", RID_TYPENAME, D_CXXONLY | D_CXXWARN },
+ { "typeid", RID_TYPEID, D_CXXONLY | D_CXXWARN },
+ { "typeof", RID_TYPEOF, D_ASM | D_EXT },
+ { "union", RID_UNION, 0 },
+ { "unsigned", RID_UNSIGNED, 0 },
+ { "using", RID_USING, D_CXXONLY | D_CXXWARN },
+ { "virtual", RID_VIRTUAL, D_CXXONLY | D_CXXWARN },
+ { "void", RID_VOID, 0 },
+ { "volatile", RID_VOLATILE, 0 },
+ { "wchar_t", RID_WCHAR, D_CXXONLY },
+ { "while", RID_WHILE, 0 },
+ { "__is_assignable", RID_IS_ASSIGNABLE, D_CXXONLY },
+ { "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY },
+ { "__is_nothrow_assignable", RID_IS_NOTHROW_ASSIGNABLE, D_CXXONLY },
+ { "__is_nothrow_constructible", RID_IS_NOTHROW_CONSTRUCTIBLE, D_CXXONLY },
+
+ /* C++ transactional memory. */
+ { "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM },
+ { "atomic_noexcept", RID_ATOMIC_NOEXCEPT, D_CXXONLY | D_TRANSMEM },
+ { "atomic_cancel", RID_ATOMIC_CANCEL, D_CXXONLY | D_TRANSMEM },
+ { "atomic_commit", RID_TRANSACTION_ATOMIC, D_CXXONLY | D_TRANSMEM },
+
+ /* Concepts-related keywords */
+ { "concept", RID_CONCEPT, D_CXX_CONCEPTS_FLAGS | D_CXXWARN },
+ { "requires", RID_REQUIRES, D_CXX_CONCEPTS_FLAGS | D_CXXWARN },
+
+ /* Modules-related keywords, these are internal unspellable tokens,
+ created by the preprocessor. */
+ { "module ", RID__MODULE, D_CXX_MODULES_FLAGS | D_CXXWARN },
+ { "import ", RID__IMPORT, D_CXX_MODULES_FLAGS | D_CXXWARN },
+ { "export ", RID__EXPORT, D_CXX_MODULES_FLAGS | D_CXXWARN },
+
+ /* Coroutines-related keywords */
+ { "co_await", RID_CO_AWAIT, D_CXX_COROUTINES_FLAGS | D_CXXWARN },
+ { "co_yield", RID_CO_YIELD, D_CXX_COROUTINES_FLAGS | D_CXXWARN },
+ { "co_return", RID_CO_RETURN, D_CXX_COROUTINES_FLAGS | D_CXXWARN },
+
+ /* These Objective-C keywords are recognized only immediately after
+ an '@'. */
+ { "compatibility_alias", RID_AT_ALIAS, D_OBJC },
+ { "defs", RID_AT_DEFS, D_OBJC },
+ { "encode", RID_AT_ENCODE, D_OBJC },
+ { "end", RID_AT_END, D_OBJC },
+ { "implementation", RID_AT_IMPLEMENTATION, D_OBJC },
+ { "interface", RID_AT_INTERFACE, D_OBJC },
+ { "protocol", RID_AT_PROTOCOL, D_OBJC },
+ { "selector", RID_AT_SELECTOR, D_OBJC },
+ { "finally", RID_AT_FINALLY, D_OBJC },
+ { "optional", RID_AT_OPTIONAL, D_OBJC },
+ { "required", RID_AT_REQUIRED, D_OBJC },
+ { "property", RID_AT_PROPERTY, D_OBJC },
+ { "package", RID_AT_PACKAGE, D_OBJC },
+ { "synthesize", RID_AT_SYNTHESIZE, D_OBJC },
+ { "dynamic", RID_AT_DYNAMIC, D_OBJC },
+ /* These are recognized only in protocol-qualifier context
+ (see above) */
+ { "bycopy", RID_BYCOPY, D_OBJC },
+ { "byref", RID_BYREF, D_OBJC },
+ { "in", RID_IN, D_OBJC },
+ { "inout", RID_INOUT, D_OBJC },
+ { "oneway", RID_ONEWAY, D_OBJC },
+ { "out", RID_OUT, D_OBJC },
+ /* These are recognized inside a property attribute list */
+ { "assign", RID_ASSIGN, D_OBJC },
+ { "atomic", RID_PROPATOMIC, D_OBJC },
+ { "copy", RID_COPY, D_OBJC },
+ { "getter", RID_GETTER, D_OBJC },
+ { "nonatomic", RID_NONATOMIC, D_OBJC },
+ { "readonly", RID_READONLY, D_OBJC },
+ { "readwrite", RID_READWRITE, D_OBJC },
+ { "retain", RID_RETAIN, D_OBJC },
+ { "setter", RID_SETTER, D_OBJC },
+ /* These are Objective C implementation of nullability, accepted only in
+ specific contexts. */
+ { "null_unspecified", RID_NULL_UNSPECIFIED, D_OBJC },
+ { "nullable", RID_NULLABLE, D_OBJC },
+ { "nonnull", RID_NONNULL, D_OBJC },
+ { "null_resettable", RID_NULL_RESETTABLE, D_OBJC },
+};
+
+const unsigned int num_c_common_reswords =
+ sizeof c_common_reswords / sizeof (struct c_common_resword);
+
+/* Return identifier for address space AS. */
+
+const char *
+c_addr_space_name (addr_space_t as)
+{
+ int rid = RID_FIRST_ADDR_SPACE + as;
+ gcc_assert (ridpointers [rid]);
+ return IDENTIFIER_POINTER (ridpointers [rid]);
+}
+
+/* Push current bindings for the function name VAR_DECLS. */
+
+void
+start_fname_decls (void)
+{
+ unsigned ix;
+ tree saved = NULL_TREE;
+
+ for (ix = 0; fname_vars[ix].decl; ix++)
+ {
+ tree decl = *fname_vars[ix].decl;
+
+ if (decl)
+ {
+ saved = tree_cons (decl, build_int_cst (integer_type_node, ix),
+ saved);
+ *fname_vars[ix].decl = NULL_TREE;
+ }
+ }
+ if (saved || saved_function_name_decls)
+ /* Normally they'll have been NULL, so only push if we've got a
+ stack, or they are non-NULL. */
+ saved_function_name_decls = tree_cons (saved, NULL_TREE,
+ saved_function_name_decls);
+}
+
+/* Finish up the current bindings, adding them into the current function's
+ statement tree. This must be done _before_ finish_stmt_tree is called.
+ If there is no current function, we must be at file scope and no statements
+ are involved. Pop the previous bindings. */
+
+void
+finish_fname_decls (void)
+{
+ gcc_assert(0);
+#if 0 // sdcpp
+ unsigned ix;
+ tree stmts = NULL_TREE;
+ tree stack = saved_function_name_decls;
+
+ for (; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))
+ append_to_statement_list (TREE_VALUE (stack), &stmts);
+
+ if (stmts)
+ {
+ tree *bodyp = &DECL_SAVED_TREE (current_function_decl);
+
+ if (TREE_CODE (*bodyp) == BIND_EXPR)
+ bodyp = &BIND_EXPR_BODY (*bodyp);
+
+ append_to_statement_list_force (*bodyp, &stmts);
+ *bodyp = stmts;
+ }
+
+ for (ix = 0; fname_vars[ix].decl; ix++)
+ *fname_vars[ix].decl = NULL_TREE;
+
+ if (stack)
+ {
+ /* We had saved values, restore them. */
+ tree saved;
+
+ for (saved = TREE_PURPOSE (stack); saved; saved = TREE_CHAIN (saved))
+ {
+ tree decl = TREE_PURPOSE (saved);
+ unsigned ix = TREE_INT_CST_LOW (TREE_VALUE (saved));
+
+ *fname_vars[ix].decl = decl;
+ }
+ stack = TREE_CHAIN (stack);
+ }
+ saved_function_name_decls = stack;
+#endif
+}
+
+/* Return the text name of the current function, suitably prettified
+ by PRETTY_P. Return string must be freed by caller. */
+
+const char *
+fname_as_string (int pretty_p)
+{
+ const char *name = "top level";
+ char *namep;
+ int vrb = 2, len;
+ cpp_string cstr = { 0, 0 }, strname;
+
+ if (!pretty_p)
+ {
+ name = "";
+ vrb = 0;
+ }
+
+ if (current_function_decl)
+ name = lang_hooks.decl_printable_name (current_function_decl, vrb);
+
+ len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
+
+ namep = XNEWVEC (char, len);
+ snprintf (namep, len, "\"%s\"", name);
+ strname.text = (unsigned char *) namep;
+ strname.len = len - 1;
+
+ if (cpp_interpret_string (parse_in, &strname, 1, &cstr, CPP_STRING))
+ {
+ XDELETEVEC (namep);
+ return (const char *) cstr.text;
+ }
+
+ return namep;
+}
+
+/* Return the VAR_DECL for a const char array naming the current
+ function. If the VAR_DECL has not yet been created, create it
+ now. RID indicates how it should be formatted and IDENTIFIER_NODE
+ ID is its name (unfortunately C and C++ hold the RID values of
+ keywords in different places, so we can't derive RID from ID in
+ this language independent code. LOC is the location of the
+ function. */
+
+tree
+fname_decl (location_t loc, unsigned int rid, tree id)
+{
+ unsigned ix;
+ tree decl = NULL_TREE;
+
+ for (ix = 0; fname_vars[ix].decl; ix++)
+ if (fname_vars[ix].rid == rid)
+ break;
+
+ decl = *fname_vars[ix].decl;
+ if (!decl)
+ {
+ /* If a tree is built here, it would normally have the lineno of
+ the current statement. Later this tree will be moved to the
+ beginning of the function and this line number will be wrong.
+ To avoid this problem set the lineno to 0 here; that prevents
+ it from appearing in the RTL. */
+ tree stmts;
+ location_t saved_location = input_location;
+ input_location = UNKNOWN_LOCATION;
+
+ stmts = push_stmt_list ();
+ decl = (*make_fname_decl) (loc, id, fname_vars[ix].pretty);
+ stmts = pop_stmt_list (stmts);
+ if (!IS_EMPTY_STMT (stmts))
+ saved_function_name_decls
+ = tree_cons (decl, stmts, saved_function_name_decls);
+ *fname_vars[ix].decl = decl;
+ input_location = saved_location;
+ }
+ if (!ix && !current_function_decl)
+ pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
+
+ return decl;
+}
+
+/* Given a STRING_CST, give it a suitable array-of-chars data type. */
+
+#if 0 // sdcpp
+tree
+fix_string_type (tree value)
+{
+ int length = TREE_STRING_LENGTH (value);
+ int nchars, charsz;
+ tree e_type, i_type, a_type;
+
+ /* Compute the number of elements, for the array type. */
+ if (TREE_TYPE (value) == char_array_type_node || !TREE_TYPE (value))
+ {
+ charsz = 1;
+ e_type = char_type_node;
+ }
+ else if (flag_char8_t && TREE_TYPE (value) == char8_array_type_node)
+ {
+ charsz = TYPE_PRECISION (char8_type_node) / BITS_PER_UNIT;
+ e_type = char8_type_node;
+ }
+ else if (TREE_TYPE (value) == char16_array_type_node)
+ {
+ charsz = TYPE_PRECISION (char16_type_node) / BITS_PER_UNIT;
+ e_type = char16_type_node;
+ }
+ else if (TREE_TYPE (value) == char32_array_type_node)
+ {
+ charsz = TYPE_PRECISION (char32_type_node) / BITS_PER_UNIT;
+ e_type = char32_type_node;
+ }
+ else
+ {
+ charsz = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+ e_type = wchar_type_node;
+ }
+
+ /* This matters only for targets where ssizetype has smaller precision
+ than 32 bits. */
+ if (wi::lts_p (wi::to_wide (TYPE_MAX_VALUE (ssizetype)), length))
+ {
+ error ("size of string literal is too large");
+ length = tree_to_shwi (TYPE_MAX_VALUE (ssizetype)) / charsz * charsz;
+ char *str = CONST_CAST (char *, TREE_STRING_POINTER (value));
+ memset (str + length, '\0',
+ MIN (TREE_STRING_LENGTH (value) - length, charsz));
+ TREE_STRING_LENGTH (value) = length;
+ }
+ nchars = length / charsz;
+
+ /* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous
+ limit in C++98 Annex B is very large (65536) and is not normative,
+ so we do not diagnose it (warn_overlength_strings is forced off
+ in c_common_post_options). */
+ if (warn_overlength_strings)
+ {
+ const int nchars_max = flag_isoc99 ? 4095 : 509;
+ const int relevant_std = flag_isoc99 ? 99 : 90;
+ if (nchars - 1 > nchars_max)
+ /* Translators: The %d after 'ISO C' will be 90 or 99. Do not
+ separate the %d from the 'C'. 'ISO' should not be
+ translated, but it may be moved after 'C%d' in languages
+ where modifiers follow nouns. */
+ pedwarn (input_location, OPT_Woverlength_strings,
+ "string length %qd is greater than the length %qd "
+ "ISO C%d compilers are required to support",
+ nchars - 1, nchars_max, relevant_std);
+ }
+
+ /* Create the array type for the string constant. The ISO C++
+ standard says that a string literal has type `const char[N]' or
+ `const wchar_t[N]'. We use the same logic when invoked as a C
+ front-end with -Wwrite-strings.
+ ??? We should change the type of an expression depending on the
+ state of a warning flag. We should just be warning -- see how
+ this is handled in the C++ front-end for the deprecated implicit
+ conversion from string literals to `char*' or `wchar_t*'.
+
+ The C++ front end relies on TYPE_MAIN_VARIANT of a cv-qualified
+ array type being the unqualified version of that type.
+ Therefore, if we are constructing an array of const char, we must
+ construct the matching unqualified array type first. The C front
+ end does not require this, but it does no harm, so we do it
+ unconditionally. */
+ i_type = build_index_type (size_int (nchars - 1));
+ a_type = build_array_type (e_type, i_type);
+ if (c_dialect_cxx() || warn_write_strings)
+ a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
+
+ TREE_TYPE (value) = a_type;
+ TREE_CONSTANT (value) = 1;
+ TREE_READONLY (value) = 1;
+ TREE_STATIC (value) = 1;
+ return value;
+}
+#endif
+
+/* Given a string of type STRING_TYPE, determine what kind of string
+ token would give an equivalent execution encoding: CPP_STRING,
+ CPP_STRING16, or CPP_STRING32. Return CPP_OTHER in case of error.
+ This may not be exactly the string token type that initially created
+ the string, since CPP_WSTRING is indistinguishable from the 16/32 bit
+ string type, and CPP_UTF8STRING is indistinguishable from CPP_STRING
+ at this point.
+
+ This effectively reverses part of the logic in lex_string and
+ fix_string_type. */
+
+static enum cpp_ttype
+get_cpp_ttype_from_string_type (tree string_type)
+{
+ gcc_assert (string_type);
+ if (TREE_CODE (string_type) == POINTER_TYPE)
+ string_type = TREE_TYPE (string_type);
+
+ if (TREE_CODE (string_type) != ARRAY_TYPE)
+ return CPP_OTHER;
+
+ tree element_type = TREE_TYPE (string_type);
+ if (TREE_CODE (element_type) != INTEGER_TYPE)
+ return CPP_OTHER;
+
+ int bits_per_character = TYPE_PRECISION (element_type);
+ switch (bits_per_character)
+ {
+ case 8:
+ return CPP_STRING; /* It could have also been CPP_UTF8STRING. */
+ case 16:
+ return CPP_STRING16;
+ case 32:
+ return CPP_STRING32;
+ }
+
+ return CPP_OTHER;
+}
+
+/* The global record of string concatentations, for use in
+ extracting locations within string literals. */
+#endif // sdcpp
+
+GTY(()) string_concat_db *g_string_concat_db;
+#if 0 // sdcpp
+
+/* Implementation of LANG_HOOKS_GET_SUBSTRING_LOCATION. */
+
+const char *
+c_get_substring_location (const substring_loc &substr_loc,
+ location_t *out_loc)
+{
+ enum cpp_ttype tok_type
+ = get_cpp_ttype_from_string_type (substr_loc.get_string_type ());
+ if (tok_type == CPP_OTHER)
+ return "unrecognized string type";
+
+ return get_location_within_string (parse_in, g_string_concat_db,
+ substr_loc.get_fmt_string_loc (),
+ tok_type,
+ substr_loc.get_caret_idx (),
+ substr_loc.get_start_idx (),
+ substr_loc.get_end_idx (),
+ out_loc);
+}
+
+
+/* Return true iff T is a boolean promoted to int. */
+
+bool
+bool_promoted_to_int_p (tree t)
+{
+ return (CONVERT_EXPR_P (t)
+ && TREE_TYPE (t) == integer_type_node
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == BOOLEAN_TYPE);
+}
+
+/* vector_targets_convertible_p is used for vector pointer types. The
+ callers perform various checks that the qualifiers are satisfactory,
+ while OTOH vector_targets_convertible_p ignores the number of elements
+ in the vectors. That's fine with vector pointers as we can consider,
+ say, a vector of 8 elements as two consecutive vectors of 4 elements,
+ and that does not require and conversion of the pointer values.
+ In contrast, vector_types_convertible_p and
+ vector_types_compatible_elements_p are used for vector value types. */
+/* True if pointers to distinct types T1 and T2 can be converted to
+ each other without an explicit cast. Only returns true for opaque
+ vector types. */
+bool
+vector_targets_convertible_p (const_tree t1, const_tree t2)
+{
+ if (VECTOR_TYPE_P (t1) && VECTOR_TYPE_P (t2)
+ && (TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
+ && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
+ return true;
+
+ return false;
+}
+
+/* vector_types_convertible_p is used for vector value types.
+ It could in principle call vector_targets_convertible_p as a subroutine,
+ but then the check for vector type would be duplicated with its callers,
+ and also the purpose of vector_targets_convertible_p would become
+ muddled.
+ Where vector_types_convertible_p returns true, a conversion might still be
+ needed to make the types match.
+ In contrast, vector_targets_convertible_p is used for vector pointer
+ values, and vector_types_compatible_elements_p is used specifically
+ in the context for binary operators, as a check if use is possible without
+ conversion. */
+/* True if vector types T1 and T2 can be converted to each other
+ without an explicit cast. If EMIT_LAX_NOTE is true, and T1 and T2
+ can only be converted with -flax-vector-conversions yet that is not
+ in effect, emit a note telling the user about that option if such
+ a note has not previously been emitted. */
+bool
+vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
+{
+ static bool emitted_lax_note = false;
+ bool convertible_lax;
+
+ if ((TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
+ && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
+ return true;
+
+ convertible_lax =
+ (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+ && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE
+ || known_eq (TYPE_VECTOR_SUBPARTS (t1),
+ TYPE_VECTOR_SUBPARTS (t2)))
+ && (INTEGRAL_TYPE_P (TREE_TYPE (t1))
+ == INTEGRAL_TYPE_P (TREE_TYPE (t2))));
+
+ if (!convertible_lax || flag_lax_vector_conversions)
+ return convertible_lax;
+
+ if (known_eq (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2))
+ && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ return true;
+
+ if (emit_lax_note && !emitted_lax_note)
+ {
+ emitted_lax_note = true;
+ inform (input_location, "use %<-flax-vector-conversions%> to permit "
+ "conversions between vectors with differing "
+ "element types or numbers of subparts");
+ }
+
+ return false;
+}
+
+/* Build a VEC_PERM_EXPR if V0, V1 and MASK are not error_mark_nodes
+ and have vector types, V0 has the same type as V1, and the number of
+ elements of V0, V1, MASK is the same.
+
+ In case V1 is a NULL_TREE it is assumed that __builtin_shuffle was
+ called with two arguments. In this case implementation passes the
+ first argument twice in order to share the same tree code. This fact
+ could enable the mask-values being twice the vector length. This is
+ an implementation accident and this semantics is not guaranteed to
+ the user. */
+#if 0 // sdcpp
+tree
+c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask,
+ bool complain)
+{
+ tree ret;
+ bool wrap = true;
+ bool maybe_const = false;
+ bool two_arguments = false;
+
+ if (v1 == NULL_TREE)
+ {
+ two_arguments = true;
+ v1 = v0;
+ }
+
+ if (v0 == error_mark_node || v1 == error_mark_node
+ || mask == error_mark_node)
+ return error_mark_node;
+
+ if (!gnu_vector_type_p (TREE_TYPE (mask))
+ || !VECTOR_INTEGER_TYPE_P (TREE_TYPE (mask)))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shuffle%> last argument must "
+ "be an integer vector");
+ return error_mark_node;
+ }
+
+ if (!gnu_vector_type_p (TREE_TYPE (v0))
+ || !gnu_vector_type_p (TREE_TYPE (v1)))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shuffle%> arguments must be vectors");
+ return error_mark_node;
+ }
+
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1)))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shuffle%> argument vectors must be of "
+ "the same type");
+ return error_mark_node;
+ }
+
+ if (maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0)),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
+ && maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shuffle%> number of elements of the "
+ "argument vector(s) and the mask vector should "
+ "be the same");
+ return error_mark_node;
+ }
+
+ if (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
+ != GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shuffle%> argument vector(s) inner type "
+ "must have the same size as inner type of the mask");
+ return error_mark_node;
+ }
+
+ if (!c_dialect_cxx ())
+ {
+ /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR. */
+ v0 = c_fully_fold (v0, false, &maybe_const);
+ wrap &= maybe_const;
+
+ if (two_arguments)
+ v1 = v0 = save_expr (v0);
+ else
+ {
+ v1 = c_fully_fold (v1, false, &maybe_const);
+ wrap &= maybe_const;
+ }
+
+ mask = c_fully_fold (mask, false, &maybe_const);
+ wrap &= maybe_const;
+ }
+ else if (two_arguments)
+ v1 = v0 = save_expr (v0);
+
+ ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask);
+
+ if (!c_dialect_cxx () && !wrap)
+ ret = c_wrap_maybe_const (ret, true);
+
+ return ret;
+}
+#endif
+
+/* Build a VEC_PERM_EXPR if V0, V1 are not error_mark_nodes
+ and have vector types, V0 has the same element type as V1, and the
+ number of elements the result is that of MASK. */
+#if 0 // sdcpp
+tree
+c_build_shufflevector (location_t loc, tree v0, tree v1,
+ const vec<tree> &mask, bool complain)
+{
+ tree ret;
+ bool wrap = true;
+ bool maybe_const = false;
+
+ if (v0 == error_mark_node || v1 == error_mark_node)
+ return error_mark_node;
+
+ if (!gnu_vector_type_p (TREE_TYPE (v0))
+ || !gnu_vector_type_p (TREE_TYPE (v1)))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shufflevector%> arguments must be vectors");
+ return error_mark_node;
+ }
+
+ /* ??? In principle one could select a constant part of a variable size
+ vector but things get a bit awkward with trying to support this here. */
+ unsigned HOST_WIDE_INT v0n, v1n;
+ if (!TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0)).is_constant (&v0n)
+ || !TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)).is_constant (&v1n))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shufflevector%> arguments must be constant"
+ " size vectors");
+ return error_mark_node;
+ }
+
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (v0)))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (v1))))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shufflevector%> argument vectors must "
+ "have the same element type");
+ return error_mark_node;
+ }
+
+ if (!pow2p_hwi (mask.length ()))
+ {
+ if (complain)
+ error_at (loc, "%<__builtin_shufflevector%> must specify a result "
+ "with a power of two number of elements");
+ return error_mark_node;
+ }
+
+ if (!c_dialect_cxx ())
+ {
+ /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR. */
+ v0 = c_fully_fold (v0, false, &maybe_const);
+ wrap &= maybe_const;
+
+ v1 = c_fully_fold (v1, false, &maybe_const);
+ wrap &= maybe_const;
+ }
+
+ unsigned HOST_WIDE_INT maskl = MAX (mask.length (), MAX (v0n, v1n));
+ unsigned HOST_WIDE_INT pad = (v0n < maskl ? maskl - v0n : 0);
+ vec_perm_builder sel (maskl, maskl, 1);
+ unsigned i;
+ for (i = 0; i < mask.length (); ++i)
+ {
+ tree idx = mask[i];
+ if (!tree_fits_shwi_p (idx))
+ {
+ if (complain)
+ error_at (loc, "invalid element index %qE to "
+ "%<__builtin_shufflevector%>", idx);
+ return error_mark_node;
+ }
+ HOST_WIDE_INT iidx = tree_to_shwi (idx);
+ if (iidx < -1
+ || (iidx != -1
+ && (unsigned HOST_WIDE_INT) iidx >= v0n + v1n))
+ {
+ if (complain)
+ error_at (loc, "invalid element index %qE to "
+ "%<__builtin_shufflevector%>", idx);
+ return error_mark_node;
+ }
+ /* ??? Our VEC_PERM_EXPR does not allow for -1 yet. */
+ if (iidx == -1)
+ iidx = i;
+ /* ??? Our VEC_PERM_EXPR does not allow different sized inputs,
+ so pad out a smaller v0. */
+ else if ((unsigned HOST_WIDE_INT) iidx >= v0n)
+ iidx += pad;
+ sel.quick_push (iidx);
+ }
+ /* ??? VEC_PERM_EXPR does not support a result that is smaller than
+ the inputs, so we have to pad id out. */
+ for (; i < maskl; ++i)
+ sel.quick_push (i);
+
+ vec_perm_indices indices (sel, 2, maskl);
+
+ tree ret_type = build_vector_type (TREE_TYPE (TREE_TYPE (v0)), maskl);
+ tree mask_type = build_vector_type (build_nonstandard_integer_type
+ (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (ret_type))), 1),
+ maskl);
+ /* Pad out arguments to the common vector size. */
+ if (v0n < maskl)
+ {
+ constructor_elt elt = { NULL_TREE, build_zero_cst (TREE_TYPE (v0)) };
+ v0 = build_constructor_single (ret_type, NULL_TREE, v0);
+ for (i = 1; i < maskl / v0n; ++i)
+ vec_safe_push (CONSTRUCTOR_ELTS (v0), elt);
+ }
+ if (v1n < maskl)
+ {
+ constructor_elt elt = { NULL_TREE, build_zero_cst (TREE_TYPE (v1)) };
+ v1 = build_constructor_single (ret_type, NULL_TREE, v1);
+ for (i = 1; i < maskl / v1n; ++i)
+ vec_safe_push (CONSTRUCTOR_ELTS (v1), elt);
+ }
+ ret = build3_loc (loc, VEC_PERM_EXPR, ret_type, v0, v1,
+ vec_perm_indices_to_tree (mask_type, indices));
+ /* Get the lowpart we are interested in. */
+ if (mask.length () < maskl)
+ {
+ tree lpartt = build_vector_type (TREE_TYPE (ret_type), mask.length ());
+ ret = build3_loc (loc, BIT_FIELD_REF,
+ lpartt, ret, TYPE_SIZE (lpartt), bitsize_zero_node);
+ /* Wrap the lowpart operation in a TARGET_EXPR so it gets a separate
+ temporary during gimplification. See PR101530 for cases where
+ we'd otherwise end up with non-toplevel BIT_FIELD_REFs. */
+ tree tem = create_tmp_var_raw (lpartt);
+ DECL_CONTEXT (tem) = current_function_decl;
+ ret = build4 (TARGET_EXPR, lpartt, tem, ret, NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (ret) = 1;
+ }
+
+ if (!c_dialect_cxx () && !wrap)
+ ret = c_wrap_maybe_const (ret, true);
+
+ return ret;
+}
+#endif
+
+/* Build a VEC_CONVERT ifn for __builtin_convertvector builtin. */
+
+tree
+c_build_vec_convert (location_t loc1, tree expr, location_t loc2, tree type,
+ bool complain)
+{
+ if (error_operand_p (type))
+ return error_mark_node;
+ if (error_operand_p (expr))
+ return error_mark_node;
+
+ if (!gnu_vector_type_p (TREE_TYPE (expr))
+ || (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (expr))
+ && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (expr))))
+ {
+ if (complain)
+ error_at (loc1, "%<__builtin_convertvector%> first argument must "
+ "be an integer or floating vector");
+ return error_mark_node;
+ }
+
+ if (!gnu_vector_type_p (type)
+ || (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type)))
+ {
+ if (complain)
+ error_at (loc2, "%<__builtin_convertvector%> second argument must "
+ "be an integer or floating vector type");
+ return error_mark_node;
+ }
+
+ if (maybe_ne (TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr)),
+ TYPE_VECTOR_SUBPARTS (type)))
+ {
+ if (complain)
+ error_at (loc1, "%<__builtin_convertvector%> number of elements "
+ "of the first argument vector and the second argument "
+ "vector type should be the same");
+ return error_mark_node;
+ }
+
+ if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr)))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (type)))
+ || (VECTOR_INTEGER_TYPE_P (TREE_TYPE (expr))
+ && VECTOR_INTEGER_TYPE_P (type)
+ && (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (expr)))
+ == TYPE_PRECISION (TREE_TYPE (type)))))
+ return build1_loc (loc1, VIEW_CONVERT_EXPR, type, expr);
+
+ bool wrap = true;
+ bool maybe_const = false;
+ tree ret;
+ if (!c_dialect_cxx ())
+ {
+ /* Avoid C_MAYBE_CONST_EXPRs inside of VEC_CONVERT argument. */
+ expr = c_fully_fold (expr, false, &maybe_const);
+ wrap &= maybe_const;
+ }
+
+ ret = build_call_expr_internal_loc (loc1, IFN_VEC_CONVERT, type, 1, expr);
+
+ if (!wrap)
+ ret = c_wrap_maybe_const (ret, true);
+
+ return ret;
+}
+
+/* Like tree.cc:get_narrower, but retain conversion from C++0x scoped enum
+ to integral type. */
+
+tree
+c_common_get_narrower (tree op, int *unsignedp_ptr)
+{
+ op = get_narrower (op, unsignedp_ptr);
+
+ if (TREE_CODE (TREE_TYPE (op)) == ENUMERAL_TYPE
+ && ENUM_IS_SCOPED (TREE_TYPE (op)))
+ {
+ /* C++0x scoped enumerations don't implicitly convert to integral
+ type; if we stripped an explicit conversion to a larger type we
+ need to replace it so common_type will still work. */
+ tree type = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (op)),
+ TYPE_UNSIGNED (TREE_TYPE (op)));
+ op = fold_convert (type, op);
+ }
+ return op;
+}
+
+/* This is a helper function of build_binary_op.
+
+ For certain operations if both args were extended from the same
+ smaller type, do the arithmetic in that type and then extend.
+
+ BITWISE indicates a bitwise operation.
+ For them, this optimization is safe only if
+ both args are zero-extended or both are sign-extended.
+ Otherwise, we might change the result.
+ Eg, (short)-1 | (unsigned short)-1 is (int)-1
+ but calculated in (unsigned short) it would be (unsigned short)-1.
+*/
+tree
+shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
+{
+ int unsigned0, unsigned1;
+ tree arg0, arg1;
+ int uns;
+ tree type;
+
+ /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents
+ excessive narrowing when we call get_narrower below. For
+ example, suppose that OP0 is of unsigned int extended
+ from signed char and that RESULT_TYPE is long long int.
+ If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
+ like
+
+ (long long int) (unsigned int) signed_char
+
+ which get_narrower would narrow down to
+
+ (unsigned int) signed char
+
+ If we do not cast OP0 first, get_narrower would return
+ signed_char, which is inconsistent with the case of the
+ explicit cast. */
+ op0 = convert (result_type, op0);
+ op1 = convert (result_type, op1);
+
+ arg0 = c_common_get_narrower (op0, &unsigned0);
+ arg1 = c_common_get_narrower (op1, &unsigned1);
+
+ /* UNS is 1 if the operation to be done is an unsigned one. */
+ uns = TYPE_UNSIGNED (result_type);
+
+ /* Handle the case that OP0 (or OP1) does not *contain* a conversion
+ but it *requires* conversion to FINAL_TYPE. */
+
+ if ((TYPE_PRECISION (TREE_TYPE (op0))
+ == TYPE_PRECISION (TREE_TYPE (arg0)))
+ && TREE_TYPE (op0) != result_type)
+ unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+ if ((TYPE_PRECISION (TREE_TYPE (op1))
+ == TYPE_PRECISION (TREE_TYPE (arg1)))
+ && TREE_TYPE (op1) != result_type)
+ unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+
+ /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
+
+ /* For bitwise operations, signedness of nominal type
+ does not matter. Consider only how operands were extended. */
+ if (bitwise)
+ uns = unsigned0;
+
+ /* Note that in all three cases below we refrain from optimizing
+ an unsigned operation on sign-extended args.
+ That would not be valid. */
+
+ /* Both args variable: if both extended in same way
+ from same width, do it in that width.
+ Do it unsigned if args were zero-extended. */
+ if ((TYPE_PRECISION (TREE_TYPE (arg0))
+ < TYPE_PRECISION (result_type))
+ && (TYPE_PRECISION (TREE_TYPE (arg1))
+ == TYPE_PRECISION (TREE_TYPE (arg0)))
+ && unsigned0 == unsigned1
+ && (unsigned0 || !uns))
+ return c_common_signed_or_unsigned_type
+ (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+
+ else if (TREE_CODE (arg0) == INTEGER_CST
+ && (unsigned1 || !uns)
+ && (TYPE_PRECISION (TREE_TYPE (arg1))
+ < TYPE_PRECISION (result_type))
+ && (type
+ = c_common_signed_or_unsigned_type (unsigned1,
+ TREE_TYPE (arg1)))
+ && !POINTER_TYPE_P (type)
+ && int_fits_type_p (arg0, type))
+ return type;
+
+ else if (TREE_CODE (arg1) == INTEGER_CST
+ && (unsigned0 || !uns)
+ && (TYPE_PRECISION (TREE_TYPE (arg0))
+ < TYPE_PRECISION (result_type))
+ && (type
+ = c_common_signed_or_unsigned_type (unsigned0,
+ TREE_TYPE (arg0)))
+ && !POINTER_TYPE_P (type)
+ && int_fits_type_p (arg1, type))
+ return type;
+
+ return result_type;
+}
+
+/* Returns true iff any integer value of type FROM_TYPE can be represented as
+ real of type TO_TYPE. This is a helper function for unsafe_conversion_p. */
+
+static bool
+int_safely_convertible_to_real_p (const_tree from_type, const_tree to_type)
+{
+ tree type_low_bound = TYPE_MIN_VALUE (from_type);
+ tree type_high_bound = TYPE_MAX_VALUE (from_type);
+ REAL_VALUE_TYPE real_low_bound =
+ real_value_from_int_cst (0, type_low_bound);
+ REAL_VALUE_TYPE real_high_bound =
+ real_value_from_int_cst (0, type_high_bound);
+
+ return exact_real_truncate (TYPE_MODE (to_type), &real_low_bound)
+ && exact_real_truncate (TYPE_MODE (to_type), &real_high_bound);
+}
+
+/* Checks if expression EXPR of complex/real/integer type cannot be converted
+ to the complex/real/integer type TYPE. Function returns non-zero when:
+ * EXPR is a constant which cannot be exactly converted to TYPE.
+ * EXPR is not a constant and size of EXPR's type > than size of TYPE,
+ for EXPR type and TYPE being both integers or both real, or both
+ complex.
+ * EXPR is not a constant of complex type and TYPE is a real or
+ an integer.
+ * EXPR is not a constant of real type and TYPE is an integer.
+ * EXPR is not a constant of integer type which cannot be
+ exactly converted to real type.
+
+ Function allows conversions between types of different signedness if
+ CHECK_SIGN is false and can return SAFE_CONVERSION (zero) in that
+ case. Function can return UNSAFE_SIGN if CHECK_SIGN is true.
+
+ RESULT, when non-null is the result of the conversion. When constant
+ it is included in the text of diagnostics.
+
+ Function allows conversions from complex constants to non-complex types,
+ provided that imaginary part is zero and real part can be safely converted
+ to TYPE. */
+
+enum conversion_safety
+unsafe_conversion_p (tree type, tree expr, tree result, bool check_sign)
+{
+ enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
+ tree expr_type = TREE_TYPE (expr);
+
+ expr = fold_for_warn (expr);
+
+ if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+ {
+ /* If type is complex, we are interested in compatibility with
+ underlying type. */
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ type = TREE_TYPE (type);
+
+ /* Warn for real constant that is not an exact integer converted
+ to integer type. */
+ if (TREE_CODE (expr_type) == REAL_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ {
+ if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
+ give_warning = UNSAFE_REAL;
+ }
+ /* Warn for an integer constant that does not fit into integer type. */
+ else if (TREE_CODE (expr_type) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE
+ && !int_fits_type_p (expr, type))
+ {
+ if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
+ && tree_int_cst_sgn (expr) < 0)
+ {
+ if (check_sign)
+ give_warning = UNSAFE_SIGN;
+ }
+ else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
+ {
+ if (check_sign)
+ give_warning = UNSAFE_SIGN;
+ }
+ else
+ give_warning = UNSAFE_OTHER;
+ }
+ else if (TREE_CODE (type) == REAL_TYPE)
+ {
+ /* Warn for an integer constant that does not fit into real type. */
+ if (TREE_CODE (expr_type) == INTEGER_TYPE)
+ {
+ REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
+ if (!exact_real_truncate (TYPE_MODE (type), &a))
+ give_warning = UNSAFE_REAL;
+ }
+ /* Warn for a real constant that does not fit into a smaller
+ real type. */
+ else if (TREE_CODE (expr_type) == REAL_TYPE
+ && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
+ {
+ REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
+ if (!exact_real_truncate (TYPE_MODE (type), &a))
+ give_warning = UNSAFE_REAL;
+ }
+ }
+ }
+
+ else if (TREE_CODE (expr) == COMPLEX_CST)
+ {
+ tree imag_part = TREE_IMAGPART (expr);
+ /* Conversion from complex constant with zero imaginary part,
+ perform check for conversion of real part. */
+ if ((TREE_CODE (imag_part) == REAL_CST
+ && real_zerop (imag_part))
+ || (TREE_CODE (imag_part) == INTEGER_CST
+ && integer_zerop (imag_part)))
+ /* Note: in this branch we use recursive call to unsafe_conversion_p
+ with different type of EXPR, but it is still safe, because when EXPR
+ is a constant, it's type is not used in text of generated warnings
+ (otherwise they could sound misleading). */
+ return unsafe_conversion_p (type, TREE_REALPART (expr), result,
+ check_sign);
+ /* Conversion from complex constant with non-zero imaginary part. */
+ else
+ {
+ /* Conversion to complex type.
+ Perform checks for both real and imaginary parts. */
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ enum conversion_safety re_safety =
+ unsafe_conversion_p (type, TREE_REALPART (expr),
+ result, check_sign);
+ enum conversion_safety im_safety =
+ unsafe_conversion_p (type, imag_part, result, check_sign);
+
+ /* Merge the results into appropriate single warning. */
+
+ /* Note: this case includes SAFE_CONVERSION, i.e. success. */
+ if (re_safety == im_safety)
+ give_warning = re_safety;
+ else if (!re_safety && im_safety)
+ give_warning = im_safety;
+ else if (re_safety && !im_safety)
+ give_warning = re_safety;
+ else
+ give_warning = UNSAFE_OTHER;
+ }
+ /* Warn about conversion from complex to real or integer type. */
+ else
+ give_warning = UNSAFE_IMAGINARY;
+ }
+ }
+
+ /* Checks for remaining case: EXPR is not constant. */
+ else
+ {
+ /* Warn for real types converted to integer types. */
+ if (TREE_CODE (expr_type) == REAL_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ give_warning = UNSAFE_REAL;
+
+ else if (TREE_CODE (expr_type) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ {
+ /* Don't warn about unsigned char y = 0xff, x = (int) y; */
+ expr = get_unwidened (expr, 0);
+ expr_type = TREE_TYPE (expr);
+
+ /* Don't warn for short y; short x = ((int)y & 0xff); */
+ if (TREE_CODE (expr) == BIT_AND_EXPR
+ || TREE_CODE (expr) == BIT_IOR_EXPR
+ || TREE_CODE (expr) == BIT_XOR_EXPR)
+ {
+ /* If both args were extended from a shortest type,
+ use that type if that is safe. */
+ expr_type = shorten_binary_op (expr_type,
+ TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1),
+ /* bitwise */1);
+
+ if (TREE_CODE (expr) == BIT_AND_EXPR)
+ {
+ tree op0 = TREE_OPERAND (expr, 0);
+ tree op1 = TREE_OPERAND (expr, 1);
+ bool unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+ bool unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+
+ /* If one of the operands is a non-negative constant
+ that fits in the target type, then the type of the
+ other operand does not matter. */
+ if ((TREE_CODE (op0) == INTEGER_CST
+ && int_fits_type_p (op0, c_common_signed_type (type))
+ && int_fits_type_p (op0, c_common_unsigned_type (type)))
+ || (TREE_CODE (op1) == INTEGER_CST
+ && int_fits_type_p (op1, c_common_signed_type (type))
+ && int_fits_type_p (op1,
+ c_common_unsigned_type (type))))
+ return SAFE_CONVERSION;
+ /* If constant is unsigned and fits in the target
+ type, then the result will also fit. */
+ else if ((TREE_CODE (op0) == INTEGER_CST
+ && unsigned0
+ && int_fits_type_p (op0, type))
+ || (TREE_CODE (op1) == INTEGER_CST
+ && unsigned1
+ && int_fits_type_p (op1, type)))
+ return SAFE_CONVERSION;
+ }
+ }
+ /* Warn for integer types converted to smaller integer types. */
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
+ give_warning = UNSAFE_OTHER;
+
+ /* When they are the same width but different signedness,
+ then the value may change. */
+ else if (((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type)
+ && TYPE_UNSIGNED (expr_type) != TYPE_UNSIGNED (type))
+ /* Even when converted to a bigger type, if the type is
+ unsigned but expr is signed, then negative values
+ will be changed. */
+ || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)))
+ && check_sign)
+ give_warning = UNSAFE_SIGN;
+ }
+
+ /* Warn for integer types converted to real types if and only if
+ all the range of values of the integer type cannot be
+ represented by the real type. */
+ else if (TREE_CODE (expr_type) == INTEGER_TYPE
+ && TREE_CODE (type) == REAL_TYPE)
+ {
+ /* Don't warn about char y = 0xff; float x = (int) y; */
+ expr = get_unwidened (expr, 0);
+ expr_type = TREE_TYPE (expr);
+
+ if (!int_safely_convertible_to_real_p (expr_type, type))
+ give_warning = UNSAFE_OTHER;
+ }
+
+ /* Warn for real types converted to smaller real types. */
+ else if (TREE_CODE (expr_type) == REAL_TYPE
+ && TREE_CODE (type) == REAL_TYPE
+ && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
+ give_warning = UNSAFE_REAL;
+
+ /* Check conversion between two complex types. */
+ else if (TREE_CODE (expr_type) == COMPLEX_TYPE
+ && TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ /* Extract underlying types (i.e., type of real and imaginary
+ parts) of expr_type and type. */
+ tree from_type = TREE_TYPE (expr_type);
+ tree to_type = TREE_TYPE (type);
+
+ /* Warn for real types converted to integer types. */
+ if (TREE_CODE (from_type) == REAL_TYPE
+ && TREE_CODE (to_type) == INTEGER_TYPE)
+ give_warning = UNSAFE_REAL;
+
+ /* Warn for real types converted to smaller real types. */
+ else if (TREE_CODE (from_type) == REAL_TYPE
+ && TREE_CODE (to_type) == REAL_TYPE
+ && TYPE_PRECISION (to_type) < TYPE_PRECISION (from_type))
+ give_warning = UNSAFE_REAL;
+
+ /* Check conversion for complex integer types. Here implementation
+ is simpler than for real-domain integers because it does not
+ involve sophisticated cases, such as bitmasks, casts, etc. */
+ else if (TREE_CODE (from_type) == INTEGER_TYPE
+ && TREE_CODE (to_type) == INTEGER_TYPE)
+ {
+ /* Warn for integer types converted to smaller integer types. */
+ if (TYPE_PRECISION (to_type) < TYPE_PRECISION (from_type))
+ give_warning = UNSAFE_OTHER;
+
+ /* Check for different signedness, see case for real-domain
+ integers (above) for a more detailed comment. */
+ else if (((TYPE_PRECISION (to_type) == TYPE_PRECISION (from_type)
+ && TYPE_UNSIGNED (to_type) != TYPE_UNSIGNED (from_type))
+ || (TYPE_UNSIGNED (to_type) && !TYPE_UNSIGNED (from_type)))
+ && check_sign)
+ give_warning = UNSAFE_SIGN;
+ }
+ else if (TREE_CODE (from_type) == INTEGER_TYPE
+ && TREE_CODE (to_type) == REAL_TYPE
+ && !int_safely_convertible_to_real_p (from_type, to_type))
+ give_warning = UNSAFE_OTHER;
+ }
+
+ /* Warn for complex types converted to real or integer types. */
+ else if (TREE_CODE (expr_type) == COMPLEX_TYPE
+ && TREE_CODE (type) != COMPLEX_TYPE)
+ give_warning = UNSAFE_IMAGINARY;
+ }
+
+ return give_warning;
+}
+
+
+/* Convert EXPR to TYPE, warning about conversion problems with constants.
+ Invoke this function on every expression that is converted implicitly,
+ i.e. because of language rules and not because of an explicit cast.
+ INIT_CONST is true if the conversion is for arithmetic types for a static
+ initializer and folding must apply accordingly (discarding floating-point
+ exceptions and assuming the default rounding mode is in effect). */
+
+tree
+convert_and_check (location_t loc, tree type, tree expr, bool init_const)
+{
+ tree result;
+ tree expr_for_warning;
+
+ /* Convert from a value with possible excess precision rather than
+ via the semantic type, but do not warn about values not fitting
+ exactly in the semantic type. */
+ if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
+ {
+ tree orig_type = TREE_TYPE (expr);
+ expr = TREE_OPERAND (expr, 0);
+ expr_for_warning = (init_const
+ ? convert_init (orig_type, expr)
+ : convert (orig_type, expr));
+ if (orig_type == type)
+ return expr_for_warning;
+ }
+ else
+ expr_for_warning = expr;
+
+ if (TREE_TYPE (expr) == type)
+ return expr;
+
+ result = init_const ? convert_init (type, expr) : convert (type, expr);
+
+ if (c_inhibit_evaluation_warnings == 0
+ && !TREE_OVERFLOW_P (expr)
+ && result != error_mark_node)
+ warnings_for_convert_and_check (loc, type, expr_for_warning, result);
+
+ return result;
+}
+
+/* A node in a list that describes references to variables (EXPR), which are
+ either read accesses if WRITER is zero, or write accesses, in which case
+ WRITER is the parent of EXPR. */
+struct tlist
+{
+ struct tlist *next;
+ tree expr, writer;
+};
+
+/* Used to implement a cache the results of a call to verify_tree. We only
+ use this for SAVE_EXPRs. */
+struct tlist_cache
+{
+ struct tlist_cache *next;
+ struct tlist *cache_before_sp;
+ struct tlist *cache_after_sp;
+ tree expr;
+};
+
+/* Obstack to use when allocating tlist structures, and corresponding
+ firstobj. */
+static struct obstack tlist_obstack;
+static char *tlist_firstobj = 0;
+
+/* Keep track of the identifiers we've warned about, so we can avoid duplicate
+ warnings. */
+static struct tlist *warned_ids;
+/* SAVE_EXPRs need special treatment. We process them only once and then
+ cache the results. */
+static struct tlist_cache *save_expr_cache;
+
+static void add_tlist (struct tlist **, struct tlist *, tree, int);
+static void merge_tlist (struct tlist **, struct tlist *, int);
+static void verify_tree (tree, struct tlist **, struct tlist **, tree);
+static bool warning_candidate_p (tree);
+static bool candidate_equal_p (const_tree, const_tree);
+static void warn_for_collisions (struct tlist *);
+static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
+static struct tlist *new_tlist (struct tlist *, tree, tree);
+
+/* Create a new struct tlist and fill in its fields. */
+static struct tlist *
+new_tlist (struct tlist *next, tree t, tree writer)
+{
+ struct tlist *l;
+ l = XOBNEW (&tlist_obstack, struct tlist);
+ l->next = next;
+ l->expr = t;
+ l->writer = writer;
+ return l;
+}
+
+/* Add duplicates of the nodes found in ADD to the list *TO. If EXCLUDE_WRITER
+ is nonnull, we ignore any node we find which has a writer equal to it. */
+
+static void
+add_tlist (struct tlist **to, struct tlist *add, tree exclude_writer, int copy)
+{
+ while (add)
+ {
+ struct tlist *next = add->next;
+ if (!copy)
+ add->next = *to;
+ if (!exclude_writer || !candidate_equal_p (add->writer, exclude_writer))
+ *to = copy ? new_tlist (*to, add->expr, add->writer) : add;
+ add = next;
+ }
+}
+
+/* Merge the nodes of ADD into TO. This merging process is done so that for
+ each variable that already exists in TO, no new node is added; however if
+ there is a write access recorded in ADD, and an occurrence on TO is only
+ a read access, then the occurrence in TO will be modified to record the
+ write. */
+
+static void
+merge_tlist (struct tlist **to, struct tlist *add, int copy)
+{
+ struct tlist **end = to;
+
+ while (*end)
+ end = &(*end)->next;
+
+ while (add)
+ {
+ int found = 0;
+ struct tlist *tmp2;
+ struct tlist *next = add->next;
+
+ for (tmp2 = *to; tmp2; tmp2 = tmp2->next)
+ if (candidate_equal_p (tmp2->expr, add->expr))
+ {
+ found = 1;
+ if (!tmp2->writer)
+ tmp2->writer = add->writer;
+ }
+ if (!found)
+ {
+ *end = copy ? new_tlist (NULL, add->expr, add->writer) : add;
+ end = &(*end)->next;
+ *end = 0;
+ }
+ add = next;
+ }
+}
+
+/* WRITTEN is a variable, WRITER is its parent. Warn if any of the variable
+ references in list LIST conflict with it, excluding reads if ONLY writers
+ is nonzero. */
+
+static void
+warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
+ int only_writes)
+{
+ struct tlist *tmp;
+
+ /* Avoid duplicate warnings. */
+ for (tmp = warned_ids; tmp; tmp = tmp->next)
+ if (candidate_equal_p (tmp->expr, written))
+ return;
+
+ while (list)
+ {
+ if (candidate_equal_p (list->expr, written)
+ && !candidate_equal_p (list->writer, writer)
+ && (!only_writes || list->writer))
+ {
+ warned_ids = new_tlist (warned_ids, written, NULL_TREE);
+ warning_at (EXPR_LOC_OR_LOC (writer, input_location),
+ OPT_Wsequence_point, "operation on %qE may be undefined",
+ list->expr);
+ }
+ list = list->next;
+ }
+}
+
+/* Given a list LIST of references to variables, find whether any of these
+ can cause conflicts due to missing sequence points. */
+
+static void
+warn_for_collisions (struct tlist *list)
+{
+ struct tlist *tmp;
+
+ for (tmp = list; tmp; tmp = tmp->next)
+ {
+ if (tmp->writer)
+ warn_for_collisions_1 (tmp->expr, tmp->writer, list, 0);
+ }
+}
+
+/* Return nonzero if X is a tree that can be verified by the sequence point
+ warnings. */
+
+static bool
+warning_candidate_p (tree x)
+{
+ if (DECL_P (x) && DECL_ARTIFICIAL (x))
+ return false;
+
+ if (TREE_CODE (x) == BLOCK)
+ return false;
+
+ /* VOID_TYPE_P (TREE_TYPE (x)) is workaround for cp/tree.cc
+ (lvalue_p) crash on TRY/CATCH. */
+ if (TREE_TYPE (x) == NULL_TREE || VOID_TYPE_P (TREE_TYPE (x)))
+ return false;
+
+ if (!lvalue_p (x))
+ return false;
+
+ /* No point to track non-const calls, they will never satisfy
+ operand_equal_p. */
+ if (TREE_CODE (x) == CALL_EXPR && (call_expr_flags (x) & ECF_CONST) == 0)
+ return false;
+
+ if (TREE_CODE (x) == STRING_CST)
+ return false;
+
+ return true;
+}
+
+/* Return nonzero if X and Y appear to be the same candidate (or NULL) */
+static bool
+candidate_equal_p (const_tree x, const_tree y)
+{
+ return (x == y) || (x && y && operand_equal_p (x, y, 0));
+}
+
+/* Walk the tree X, and record accesses to variables. If X is written by the
+ parent tree, WRITER is the parent.
+ We store accesses in one of the two lists: PBEFORE_SP, and PNO_SP. If this
+ expression or its only operand forces a sequence point, then everything up
+ to the sequence point is stored in PBEFORE_SP. Everything else gets stored
+ in PNO_SP.
+ Once we return, we will have emitted warnings if any subexpression before
+ such a sequence point could be undefined. On a higher level, however, the
+ sequence point may not be relevant, and we'll merge the two lists.
+
+ Example: (b++, a) + b;
+ The call that processes the COMPOUND_EXPR will store the increment of B
+ in PBEFORE_SP, and the use of A in PNO_SP. The higher-level call that
+ processes the PLUS_EXPR will need to merge the two lists so that
+ eventually, all accesses end up on the same list (and we'll warn about the
+ unordered subexpressions b++ and b.
+
+ A note on merging. If we modify the former example so that our expression
+ becomes
+ (b++, b) + a
+ care must be taken not simply to add all three expressions into the final
+ PNO_SP list. The function merge_tlist takes care of that by merging the
+ before-SP list of the COMPOUND_EXPR into its after-SP list in a special
+ way, so that no more than one access to B is recorded. */
+
+static void
+verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
+ tree writer)
+{
+ struct tlist *tmp_before, *tmp_nosp, *tmp_list2, *tmp_list3;
+ enum tree_code code;
+ enum tree_code_class cl;
+
+ restart:
+ /* X may be NULL if it is the operand of an empty statement expression
+ ({ }). */
+ if (x == NULL)
+ return;
+
+ code = TREE_CODE (x);
+ cl = TREE_CODE_CLASS (code);
+
+ if (warning_candidate_p (x))
+ *pno_sp = new_tlist (*pno_sp, x, writer);
+
+ switch (code)
+ {
+ case CONSTRUCTOR:
+ case SIZEOF_EXPR:
+ case PAREN_SIZEOF_EXPR:
+ return;
+
+ case COMPOUND_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ sequenced_binary:
+ tmp_before = tmp_nosp = tmp_list2 = tmp_list3 = 0;
+ verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_nosp, NULL_TREE);
+ warn_for_collisions (tmp_nosp);
+ merge_tlist (pbefore_sp, tmp_before, 0);
+ merge_tlist (pbefore_sp, tmp_nosp, 0);
+ verify_tree (TREE_OPERAND (x, 1), &tmp_list3, &tmp_list2, NULL_TREE);
+ warn_for_collisions (tmp_list2);
+ merge_tlist (pbefore_sp, tmp_list3, 0);
+ merge_tlist (pno_sp, tmp_list2, 0);
+ return;
+
+ case COND_EXPR:
+ tmp_before = tmp_list2 = 0;
+ verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_list2, NULL_TREE);
+ warn_for_collisions (tmp_list2);
+ merge_tlist (pbefore_sp, tmp_before, 0);
+ merge_tlist (pbefore_sp, tmp_list2, 0);
+
+ tmp_list3 = tmp_nosp = 0;
+ verify_tree (TREE_OPERAND (x, 1), &tmp_list3, &tmp_nosp, NULL_TREE);
+ warn_for_collisions (tmp_nosp);
+ merge_tlist (pbefore_sp, tmp_list3, 0);
+
+ tmp_list3 = tmp_list2 = 0;
+ verify_tree (TREE_OPERAND (x, 2), &tmp_list3, &tmp_list2, NULL_TREE);
+ warn_for_collisions (tmp_list2);
+ merge_tlist (pbefore_sp, tmp_list3, 0);
+ /* Rather than add both tmp_nosp and tmp_list2, we have to merge the
+ two first, to avoid warning for (a ? b++ : b++). */
+ merge_tlist (&tmp_nosp, tmp_list2, 0);
+ add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
+ return;
+
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ verify_tree (TREE_OPERAND (x, 0), pno_sp, pno_sp, x);
+ return;
+
+ case MODIFY_EXPR:
+ tmp_before = tmp_nosp = tmp_list3 = 0;
+ verify_tree (TREE_OPERAND (x, 1), &tmp_before, &tmp_nosp, NULL_TREE);
+ verify_tree (TREE_OPERAND (x, 0), &tmp_list3, &tmp_list3, x);
+ /* Expressions inside the LHS are not ordered wrt. the sequence points
+ in the RHS. Example:
+ *a = (a++, 2)
+ Despite the fact that the modification of "a" is in the before_sp
+ list (tmp_before), it conflicts with the use of "a" in the LHS.
+ We can handle this by adding the contents of tmp_list3
+ to those of tmp_before, and redoing the collision warnings for that
+ list. */
+ add_tlist (&tmp_before, tmp_list3, x, 1);
+ warn_for_collisions (tmp_before);
+ /* Exclude the LHS itself here; we first have to merge it into the
+ tmp_nosp list. This is done to avoid warning for "a = a"; if we
+ didn't exclude the LHS, we'd get it twice, once as a read and once
+ as a write. */
+ add_tlist (pno_sp, tmp_list3, x, 0);
+ warn_for_collisions_1 (TREE_OPERAND (x, 0), x, tmp_nosp, 1);
+
+ merge_tlist (pbefore_sp, tmp_before, 0);
+ if (warning_candidate_p (TREE_OPERAND (x, 0)))
+ merge_tlist (&tmp_nosp, new_tlist (NULL, TREE_OPERAND (x, 0), x), 0);
+ add_tlist (pno_sp, tmp_nosp, NULL_TREE, 1);
+ return;
+
+ case CALL_EXPR:
+ /* We need to warn about conflicts among arguments and conflicts between
+ args and the function address. Side effects of the function address,
+ however, are not ordered by the sequence point of the call. */
+ {
+ call_expr_arg_iterator iter;
+ tree arg;
+ tmp_before = tmp_nosp = 0;
+ verify_tree (CALL_EXPR_FN (x), &tmp_before, &tmp_nosp, NULL_TREE);
+ FOR_EACH_CALL_EXPR_ARG (arg, iter, x)
+ {
+ tmp_list2 = tmp_list3 = 0;
+ verify_tree (arg, &tmp_list2, &tmp_list3, NULL_TREE);
+ merge_tlist (&tmp_list3, tmp_list2, 0);
+ add_tlist (&tmp_before, tmp_list3, NULL_TREE, 0);
+ }
+ add_tlist (&tmp_before, tmp_nosp, NULL_TREE, 0);
+ warn_for_collisions (tmp_before);
+ add_tlist (pbefore_sp, tmp_before, NULL_TREE, 0);
+ return;
+ }
+
+ case TREE_LIST:
+ /* Scan all the list, e.g. indices of multi dimensional array. */
+ while (x)
+ {
+ tmp_before = tmp_nosp = 0;
+ verify_tree (TREE_VALUE (x), &tmp_before, &tmp_nosp, NULL_TREE);
+ merge_tlist (&tmp_nosp, tmp_before, 0);
+ add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
+ x = TREE_CHAIN (x);
+ }
+ return;
+
+ case SAVE_EXPR:
+ {
+ struct tlist_cache *t;
+ for (t = save_expr_cache; t; t = t->next)
+ if (candidate_equal_p (t->expr, x))
+ break;
+
+ if (!t)
+ {
+ t = XOBNEW (&tlist_obstack, struct tlist_cache);
+ t->next = save_expr_cache;
+ t->expr = x;
+ save_expr_cache = t;
+
+ tmp_before = tmp_nosp = 0;
+ verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_nosp, NULL_TREE);
+ warn_for_collisions (tmp_nosp);
+
+ tmp_list3 = 0;
+ merge_tlist (&tmp_list3, tmp_nosp, 0);
+ t->cache_before_sp = tmp_before;
+ t->cache_after_sp = tmp_list3;
+ }
+ merge_tlist (pbefore_sp, t->cache_before_sp, 1);
+ add_tlist (pno_sp, t->cache_after_sp, NULL_TREE, 1);
+ return;
+ }
+
+ case ADDR_EXPR:
+ x = TREE_OPERAND (x, 0);
+ if (DECL_P (x))
+ return;
+ writer = 0;
+ goto restart;
+
+ case VIEW_CONVERT_EXPR:
+ if (location_wrapper_p (x))
+ {
+ x = TREE_OPERAND (x, 0);
+ goto restart;
+ }
+ goto do_default;
+
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ if (cxx_dialect >= cxx17)
+ goto sequenced_binary;
+ goto do_default;
+
+ default:
+ do_default:
+ /* For other expressions, simply recurse on their operands.
+ Manual tail recursion for unary expressions.
+ Other non-expressions need not be processed. */
+ if (cl == tcc_unary)
+ {
+ x = TREE_OPERAND (x, 0);
+ writer = 0;
+ goto restart;
+ }
+ else if (IS_EXPR_CODE_CLASS (cl))
+ {
+ int lp;
+ int max = TREE_OPERAND_LENGTH (x);
+ for (lp = 0; lp < max; lp++)
+ {
+ tmp_before = tmp_nosp = 0;
+ verify_tree (TREE_OPERAND (x, lp), &tmp_before, &tmp_nosp, 0);
+ merge_tlist (&tmp_nosp, tmp_before, 0);
+ add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
+ }
+ }
+ return;
+ }
+}
+
+static constexpr size_t verify_sequence_points_limit = 1024;
+
+/* Called from verify_sequence_points via walk_tree. */
+
+static tree
+verify_tree_lim_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (++*((size_t *) data) > verify_sequence_points_limit)
+ return integer_zero_node;
+
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+
+ return NULL_TREE;
+}
+
+/* Try to warn for undefined behavior in EXPR due to missing sequence
+ points. */
+
+void
+verify_sequence_points (tree expr)
+{
+ tlist *before_sp = nullptr, *after_sp = nullptr;
+
+ /* verify_tree is highly recursive, and merge_tlist is O(n^2),
+ so we return early if the expression is too big. */
+ size_t n = 0;
+ if (walk_tree (&expr, verify_tree_lim_r, &n, nullptr))
+ return;
+
+ warned_ids = nullptr;
+ save_expr_cache = nullptr;
+ if (!tlist_firstobj)
+ {
+ gcc_obstack_init (&tlist_obstack);
+ tlist_firstobj = (char *) obstack_alloc (&tlist_obstack, 0);
+ }
+
+ verify_tree (expr, &before_sp, &after_sp, NULL_TREE);
+ warn_for_collisions (after_sp);
+ obstack_free (&tlist_obstack, tlist_firstobj);
+}
+
+/* Validate the expression after `case' and apply default promotions. */
+
+static tree
+check_case_value (location_t loc, tree value)
+{
+ if (value == NULL_TREE)
+ return value;
+
+ if (TREE_CODE (value) == INTEGER_CST)
+ /* Promote char or short to int. */
+ value = perform_integral_promotions (value);
+ else if (value != error_mark_node)
+ {
+ error_at (loc, "case label does not reduce to an integer constant");
+ value = error_mark_node;
+ }
+
+ constant_expression_warning (value);
+
+ return value;
+}
+
+/* Return an integer type with BITS bits of precision,
+ that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
+#endif // sdcpp
+
+tree
+c_common_type_for_size (unsigned int bits, int unsignedp)
+{
+ (void) bits;
+ (void) unsignedp;
+ gcc_assert(0 && "c_common");
+ return tree();
+#if 0 // sdcpp
+ int i;
+
+ if (bits == TYPE_PRECISION (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+
+ if (bits == TYPE_PRECISION (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+
+ if (bits == TYPE_PRECISION (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+
+ if (bits == TYPE_PRECISION (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+
+ if (bits == TYPE_PRECISION (long_long_integer_type_node))
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && bits == int_n_data[i].bitsize)
+ return (unsignedp ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type);
+
+ if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
+ return (unsignedp ? widest_unsigned_literal_type_node
+ : widest_integer_literal_type_node);
+
+ if (bits <= TYPE_PRECISION (intQI_type_node))
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+ if (bits <= TYPE_PRECISION (intHI_type_node))
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+
+ if (bits <= TYPE_PRECISION (intSI_type_node))
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+
+ if (bits <= TYPE_PRECISION (intDI_type_node))
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+
+ return NULL_TREE;
+#endif // sdcpp
+}
+#if 0 // sdcpp
+
+/* Return a fixed-point type that has at least IBIT ibits and FBIT fbits
+ that is unsigned if UNSIGNEDP is nonzero, otherwise signed;
+ and saturating if SATP is nonzero, otherwise not saturating. */
+
+#if 0 // sdcpp
+tree
+c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
+ int unsignedp, int satp)
+{
+ enum mode_class mclass;
+ if (ibit == 0)
+ mclass = unsignedp ? MODE_UFRACT : MODE_FRACT;
+ else
+ mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
+
+ opt_scalar_mode opt_mode;
+ scalar_mode mode;
+ FOR_EACH_MODE_IN_CLASS (opt_mode, mclass)
+ {
+ mode = opt_mode.require ();
+ if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
+ break;
+ }
+
+ if (!opt_mode.exists (&mode) || !targetm.scalar_mode_supported_p (mode))
+ {
+ sorry ("GCC cannot support operators with integer types and "
+ "fixed-point types that have too many integral and "
+ "fractional bits together");
+ return NULL_TREE;
+ }
+
+ return c_common_type_for_mode (mode, satp);
+}
+#endif // sdcpp
+#endif // sdcpp
+
+/* Used for communication between c_common_type_for_mode and
+ c_register_builtin_type. */
+tree registered_builtin_types;
+
+/* Return a data type that has machine mode MODE.
+ If the mode is an integer,
+ then UNSIGNEDP selects between signed and unsigned types.
+ If the mode is a fixed-point mode,
+ then UNSIGNEDP selects between saturating and nonsaturating types. */
+
+
+tree
+c_common_type_for_mode (machine_mode mode, int unsignedp)
+{
+ (void) mode;
+ (void) unsignedp;
+ gcc_assert(0 && "c_common_type_for_mode");
+ return tree();
+#if 0 // sdcpp
+ tree t;
+ int i;
+
+ if (mode == TYPE_MODE (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+
+ if (mode == TYPE_MODE (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+
+ if (mode == TYPE_MODE (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+
+ if (mode == TYPE_MODE (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+
+ if (mode == TYPE_MODE (long_long_integer_type_node))
+ return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && mode == int_n_data[i].m)
+ return (unsignedp ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type);
+
+ if (mode == QImode)
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+ if (mode == HImode)
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+
+ if (mode == SImode)
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+
+ if (mode == DImode)
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (mode == TYPE_MODE (intTI_type_node))
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+
+ if (mode == TYPE_MODE (float_type_node))
+ return float_type_node;
+
+ if (mode == TYPE_MODE (double_type_node))
+ return double_type_node;
+
+ if (mode == TYPE_MODE (long_double_type_node))
+ return long_double_type_node;
+
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE
+ && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i)))
+ return FLOATN_NX_TYPE_NODE (i);
+
+ if (mode == TYPE_MODE (void_type_node))
+ return void_type_node;
+
+ if (mode == TYPE_MODE (build_pointer_type (char_type_node))
+ || mode == TYPE_MODE (build_pointer_type (integer_type_node)))
+ {
+ unsigned int precision
+ = GET_MODE_PRECISION (as_a <scalar_int_mode> (mode));
+ return (unsignedp
+ ? make_unsigned_type (precision)
+ : make_signed_type (precision));
+ }
+
+ if (COMPLEX_MODE_P (mode))
+ {
+ machine_mode inner_mode;
+ tree inner_type;
+
+ if (mode == TYPE_MODE (complex_float_type_node))
+ return complex_float_type_node;
+ if (mode == TYPE_MODE (complex_double_type_node))
+ return complex_double_type_node;
+ if (mode == TYPE_MODE (complex_long_double_type_node))
+ return complex_long_double_type_node;
+
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE
+ && mode == TYPE_MODE (COMPLEX_FLOATN_NX_TYPE_NODE (i)))
+ return COMPLEX_FLOATN_NX_TYPE_NODE (i);
+
+ if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
+ return complex_integer_type_node;
+
+ inner_mode = GET_MODE_INNER (mode);
+ inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+ if (inner_type != NULL_TREE)
+ return build_complex_type (inner_type);
+ }
+ else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
+ && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+ {
+ unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
+ GET_MODE_NUNITS (mode));
+ tree bool_type = build_nonstandard_boolean_type (elem_bits);
+ return build_vector_type_for_mode (bool_type, mode);
+ }
+ else if (VECTOR_MODE_P (mode)
+ && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+ {
+ machine_mode inner_mode = GET_MODE_INNER (mode);
+ tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+ if (inner_type != NULL_TREE)
+ return build_vector_type_for_mode (inner_type, mode);
+ }
+
+ if (dfloat32_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat32_type_node))
+ return dfloat32_type_node;
+ if (dfloat64_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat64_type_node))
+ return dfloat64_type_node;
+ if (dfloat128_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat128_type_node))
+ return dfloat128_type_node;
+
+ if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
+ {
+ if (mode == TYPE_MODE (short_fract_type_node))
+ return unsignedp ? sat_short_fract_type_node : short_fract_type_node;
+ if (mode == TYPE_MODE (fract_type_node))
+ return unsignedp ? sat_fract_type_node : fract_type_node;
+ if (mode == TYPE_MODE (long_fract_type_node))
+ return unsignedp ? sat_long_fract_type_node : long_fract_type_node;
+ if (mode == TYPE_MODE (long_long_fract_type_node))
+ return unsignedp ? sat_long_long_fract_type_node
+ : long_long_fract_type_node;
+
+ if (mode == TYPE_MODE (unsigned_short_fract_type_node))
+ return unsignedp ? sat_unsigned_short_fract_type_node
+ : unsigned_short_fract_type_node;
+ if (mode == TYPE_MODE (unsigned_fract_type_node))
+ return unsignedp ? sat_unsigned_fract_type_node
+ : unsigned_fract_type_node;
+ if (mode == TYPE_MODE (unsigned_long_fract_type_node))
+ return unsignedp ? sat_unsigned_long_fract_type_node
+ : unsigned_long_fract_type_node;
+ if (mode == TYPE_MODE (unsigned_long_long_fract_type_node))
+ return unsignedp ? sat_unsigned_long_long_fract_type_node
+ : unsigned_long_long_fract_type_node;
+
+ if (mode == TYPE_MODE (short_accum_type_node))
+ return unsignedp ? sat_short_accum_type_node : short_accum_type_node;
+ if (mode == TYPE_MODE (accum_type_node))
+ return unsignedp ? sat_accum_type_node : accum_type_node;
+ if (mode == TYPE_MODE (long_accum_type_node))
+ return unsignedp ? sat_long_accum_type_node : long_accum_type_node;
+ if (mode == TYPE_MODE (long_long_accum_type_node))
+ return unsignedp ? sat_long_long_accum_type_node
+ : long_long_accum_type_node;
+
+ if (mode == TYPE_MODE (unsigned_short_accum_type_node))
+ return unsignedp ? sat_unsigned_short_accum_type_node
+ : unsigned_short_accum_type_node;
+ if (mode == TYPE_MODE (unsigned_accum_type_node))
+ return unsignedp ? sat_unsigned_accum_type_node
+ : unsigned_accum_type_node;
+ if (mode == TYPE_MODE (unsigned_long_accum_type_node))
+ return unsignedp ? sat_unsigned_long_accum_type_node
+ : unsigned_long_accum_type_node;
+ if (mode == TYPE_MODE (unsigned_long_long_accum_type_node))
+ return unsignedp ? sat_unsigned_long_long_accum_type_node
+ : unsigned_long_long_accum_type_node;
+
+ if (mode == QQmode)
+ return unsignedp ? sat_qq_type_node : qq_type_node;
+ if (mode == HQmode)
+ return unsignedp ? sat_hq_type_node : hq_type_node;
+ if (mode == SQmode)
+ return unsignedp ? sat_sq_type_node : sq_type_node;
+ if (mode == DQmode)
+ return unsignedp ? sat_dq_type_node : dq_type_node;
+ if (mode == TQmode)
+ return unsignedp ? sat_tq_type_node : tq_type_node;
+
+ if (mode == UQQmode)
+ return unsignedp ? sat_uqq_type_node : uqq_type_node;
+ if (mode == UHQmode)
+ return unsignedp ? sat_uhq_type_node : uhq_type_node;
+ if (mode == USQmode)
+ return unsignedp ? sat_usq_type_node : usq_type_node;
+ if (mode == UDQmode)
+ return unsignedp ? sat_udq_type_node : udq_type_node;
+ if (mode == UTQmode)
+ return unsignedp ? sat_utq_type_node : utq_type_node;
+
+ if (mode == HAmode)
+ return unsignedp ? sat_ha_type_node : ha_type_node;
+ if (mode == SAmode)
+ return unsignedp ? sat_sa_type_node : sa_type_node;
+ if (mode == DAmode)
+ return unsignedp ? sat_da_type_node : da_type_node;
+ if (mode == TAmode)
+ return unsignedp ? sat_ta_type_node : ta_type_node;
+
+ if (mode == UHAmode)
+ return unsignedp ? sat_uha_type_node : uha_type_node;
+ if (mode == USAmode)
+ return unsignedp ? sat_usa_type_node : usa_type_node;
+ if (mode == UDAmode)
+ return unsignedp ? sat_uda_type_node : uda_type_node;
+ if (mode == UTAmode)
+ return unsignedp ? sat_uta_type_node : uta_type_node;
+ }
+
+ for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
+ {
+ tree type = TREE_VALUE (t);
+ if (TYPE_MODE (type) == mode
+ && VECTOR_TYPE_P (type) == VECTOR_MODE_P (mode)
+ && !!unsignedp == !!TYPE_UNSIGNED (type))
+ return type;
+ }
+ return NULL_TREE;
+#endif
+}
+
+#if 0 // sdcpp
+tree
+c_common_unsigned_type (tree type)
+{
+ return c_common_signed_or_unsigned_type (1, type);
+}
+
+/* Return a signed type the same as TYPE in other respects. */
+
+tree
+c_common_signed_type (tree type)
+{
+ return c_common_signed_or_unsigned_type (0, type);
+}
+
+/* Return a type the same as TYPE except unsigned or
+ signed according to UNSIGNEDP. */
+
+tree
+c_common_signed_or_unsigned_type (int unsignedp, tree type)
+{
+ (void) unsignedp;
+ (void) type;
+ gcc_assert(0 && "c_common_signed_or_unsigned_type");
+ return tree();
+#if 0
+ tree type1;
+ int i;
+
+ /* This block of code emulates the behavior of the old
+ c_common_unsigned_type. In particular, it returns
+ long_unsigned_type_node if passed a long, even when a int would
+ have the same size. This is necessary for warnings to work
+ correctly in archs where sizeof(int) == sizeof(long) */
+
+ type1 = TYPE_MAIN_VARIANT (type);
+ if (type1 == signed_char_type_node || type1 == char_type_node || type1 == unsigned_char_type_node)
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (type1 == integer_type_node || type1 == unsigned_type_node)
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
+ return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && (type1 == int_n_trees[i].unsigned_type
+ || type1 == int_n_trees[i].signed_type))
+ return (unsignedp ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type);
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+ if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+ if (type1 == intSI_type_node || type1 == unsigned_intSI_type_node)
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+ if (type1 == intHI_type_node || type1 == unsigned_intHI_type_node)
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+ if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node)
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+#define C_COMMON_FIXED_TYPES(NAME) \
+ if (type1 == short_ ## NAME ## _type_node \
+ || type1 == unsigned_short_ ## NAME ## _type_node) \
+ return unsignedp ? unsigned_short_ ## NAME ## _type_node \
+ : short_ ## NAME ## _type_node; \
+ if (type1 == NAME ## _type_node \
+ || type1 == unsigned_ ## NAME ## _type_node) \
+ return unsignedp ? unsigned_ ## NAME ## _type_node \
+ : NAME ## _type_node; \
+ if (type1 == long_ ## NAME ## _type_node \
+ || type1 == unsigned_long_ ## NAME ## _type_node) \
+ return unsignedp ? unsigned_long_ ## NAME ## _type_node \
+ : long_ ## NAME ## _type_node; \
+ if (type1 == long_long_ ## NAME ## _type_node \
+ || type1 == unsigned_long_long_ ## NAME ## _type_node) \
+ return unsignedp ? unsigned_long_long_ ## NAME ## _type_node \
+ : long_long_ ## NAME ## _type_node;
+
+#define C_COMMON_FIXED_MODE_TYPES(NAME) \
+ if (type1 == NAME ## _type_node \
+ || type1 == u ## NAME ## _type_node) \
+ return unsignedp ? u ## NAME ## _type_node \
+ : NAME ## _type_node;
+
+#define C_COMMON_FIXED_TYPES_SAT(NAME) \
+ if (type1 == sat_ ## short_ ## NAME ## _type_node \
+ || type1 == sat_ ## unsigned_short_ ## NAME ## _type_node) \
+ return unsignedp ? sat_ ## unsigned_short_ ## NAME ## _type_node \
+ : sat_ ## short_ ## NAME ## _type_node; \
+ if (type1 == sat_ ## NAME ## _type_node \
+ || type1 == sat_ ## unsigned_ ## NAME ## _type_node) \
+ return unsignedp ? sat_ ## unsigned_ ## NAME ## _type_node \
+ : sat_ ## NAME ## _type_node; \
+ if (type1 == sat_ ## long_ ## NAME ## _type_node \
+ || type1 == sat_ ## unsigned_long_ ## NAME ## _type_node) \
+ return unsignedp ? sat_ ## unsigned_long_ ## NAME ## _type_node \
+ : sat_ ## long_ ## NAME ## _type_node; \
+ if (type1 == sat_ ## long_long_ ## NAME ## _type_node \
+ || type1 == sat_ ## unsigned_long_long_ ## NAME ## _type_node) \
+ return unsignedp ? sat_ ## unsigned_long_long_ ## NAME ## _type_node \
+ : sat_ ## long_long_ ## NAME ## _type_node;
+
+#define C_COMMON_FIXED_MODE_TYPES_SAT(NAME) \
+ if (type1 == sat_ ## NAME ## _type_node \
+ || type1 == sat_ ## u ## NAME ## _type_node) \
+ return unsignedp ? sat_ ## u ## NAME ## _type_node \
+ : sat_ ## NAME ## _type_node;
+
+ C_COMMON_FIXED_TYPES (fract);
+ C_COMMON_FIXED_TYPES_SAT (fract);
+ C_COMMON_FIXED_TYPES (accum);
+ C_COMMON_FIXED_TYPES_SAT (accum);
+
+ C_COMMON_FIXED_MODE_TYPES (qq);
+ C_COMMON_FIXED_MODE_TYPES (hq);
+ C_COMMON_FIXED_MODE_TYPES (sq);
+ C_COMMON_FIXED_MODE_TYPES (dq);
+ C_COMMON_FIXED_MODE_TYPES (tq);
+ C_COMMON_FIXED_MODE_TYPES_SAT (qq);
+ C_COMMON_FIXED_MODE_TYPES_SAT (hq);
+ C_COMMON_FIXED_MODE_TYPES_SAT (sq);
+ C_COMMON_FIXED_MODE_TYPES_SAT (dq);
+ C_COMMON_FIXED_MODE_TYPES_SAT (tq);
+ C_COMMON_FIXED_MODE_TYPES (ha);
+ C_COMMON_FIXED_MODE_TYPES (sa);
+ C_COMMON_FIXED_MODE_TYPES (da);
+ C_COMMON_FIXED_MODE_TYPES (ta);
+ C_COMMON_FIXED_MODE_TYPES_SAT (ha);
+ C_COMMON_FIXED_MODE_TYPES_SAT (sa);
+ C_COMMON_FIXED_MODE_TYPES_SAT (da);
+ C_COMMON_FIXED_MODE_TYPES_SAT (ta);
+
+ /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
+ the precision; they have precision set to match their range, but
+ may use a wider mode to match an ABI. If we change modes, we may
+ wind up with bad conversions. For INTEGER_TYPEs in C, must check
+ the precision as well, so as to yield correct results for
+ bit-field types. C++ does not have these separate bit-field
+ types, and producing a signed or unsigned variant of an
+ ENUMERAL_TYPE may cause other problems as well. */
+
+ if (!INTEGRAL_TYPE_P (type)
+ || TYPE_UNSIGNED (type) == unsignedp)
+ return type;
+
+#define TYPE_OK(node) \
+ (TYPE_MODE (type) == TYPE_MODE (node) \
+ && TYPE_PRECISION (type) == TYPE_PRECISION (node))
+ if (TYPE_OK (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (TYPE_OK (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (TYPE_OK (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (TYPE_OK (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (TYPE_OK (long_long_integer_type_node))
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && TYPE_MODE (type) == int_n_data[i].m
+ && TYPE_PRECISION (type) == int_n_data[i].bitsize)
+ return (unsignedp ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type);
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (TYPE_OK (intTI_type_node))
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+ if (TYPE_OK (intDI_type_node))
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+ if (TYPE_OK (intSI_type_node))
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+ if (TYPE_OK (intHI_type_node))
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+ if (TYPE_OK (intQI_type_node))
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+#undef TYPE_OK
+
+ return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
+#endif
+}
+
+/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
+
+#if 0 // sdcpp
+tree
+c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
+{
+ int i;
+
+ /* Extended integer types of the same width as a standard type have
+ lesser rank, so those of the same width as int promote to int or
+ unsigned int and are valid for printf formats expecting int or
+ unsigned int. To avoid such special cases, avoid creating
+ extended integer types for bit-fields if a standard integer type
+ is available. */
+ if (width == TYPE_PRECISION (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (width == TYPE_PRECISION (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (width == TYPE_PRECISION (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (width == TYPE_PRECISION (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (width == TYPE_PRECISION (long_long_integer_type_node))
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i]
+ && width == int_n_data[i].bitsize)
+ return (unsignedp ? int_n_trees[i].unsigned_type
+ : int_n_trees[i].signed_type);
+ return build_nonstandard_integer_type (width, unsignedp);
+}
+#endif // sdcpp
+
+/* The C version of the register_builtin_type langhook. */
+
+#endif // sdcpp
+void
+c_register_builtin_type (tree type, const char* name)
+{
+ (void) type;
+ (void) name;
+ fprintf(stderr, "incomplete %s %d\n", __func__, __LINE__);
+#if 0 // sdcpp
+ tree decl;
+
+ decl = build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier (name), type);
+ DECL_ARTIFICIAL (decl) = 1;
+ if (!TYPE_NAME (type))
+ TYPE_NAME (type) = decl;
+ lang_hooks.decls.pushdecl (decl);
+
+ registered_builtin_types = tree_cons (0, type, registered_builtin_types);
+#endif // sdcpp
+}
+#if 0 // sdcpp
+
+/* Print an error message for invalid operands to arith operation
+ CODE with TYPE0 for operand 0, and TYPE1 for operand 1.
+ RICHLOC is a rich location for the message, containing either
+ three separate locations for each of the operator and operands
+
+ lhs op rhs
+ ~~~ ^~ ~~~
+
+ (C FE), or one location ranging over all over them
+
+ lhs op rhs
+ ~~~~^~~~~~
+
+ (C++ FE). */
+
+void
+binary_op_error (rich_location *richloc, enum tree_code code,
+ tree type0, tree type1)
+{
+ const char *opname;
+
+ switch (code)
+ {
+ case PLUS_EXPR:
+ opname = "+"; break;
+ case MINUS_EXPR:
+ opname = "-"; break;
+ case MULT_EXPR:
+ opname = "*"; break;
+ case MAX_EXPR:
+ opname = "max"; break;
+ case MIN_EXPR:
+ opname = "min"; break;
+ case EQ_EXPR:
+ opname = "=="; break;
+ case NE_EXPR:
+ opname = "!="; break;
+ case LE_EXPR:
+ opname = "<="; break;
+ case GE_EXPR:
+ opname = ">="; break;
+ case LT_EXPR:
+ opname = "<"; break;
+ case GT_EXPR:
+ opname = ">"; break;
+ case LSHIFT_EXPR:
+ opname = "<<"; break;
+ case RSHIFT_EXPR:
+ opname = ">>"; break;
+ case TRUNC_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ opname = "%"; break;
+ case TRUNC_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ opname = "/"; break;
+ case BIT_AND_EXPR:
+ opname = "&"; break;
+ case BIT_IOR_EXPR:
+ opname = "|"; break;
+ case TRUTH_ANDIF_EXPR:
+ opname = "&&"; break;
+ case TRUTH_ORIF_EXPR:
+ opname = "||"; break;
+ case BIT_XOR_EXPR:
+ opname = "^"; break;
+ default:
+ gcc_unreachable ();
+ }
+ error_at (richloc,
+ "invalid operands to binary %s (have %qT and %qT)",
+ opname, type0, type1);
+}
+
+/* Given an expression as a tree, return its original type. Do this
+ by stripping any conversion that preserves the sign and precision. */
+static tree
+expr_original_type (tree expr)
+{
+ STRIP_SIGN_NOPS (expr);
+ return TREE_TYPE (expr);
+}
+
+/* Subroutine of build_binary_op, used for comparison operations.
+ See if the operands have both been converted from subword integer types
+ and, if so, perhaps change them both back to their original type.
+ This function is also responsible for converting the two operands
+ to the proper common type for comparison.
+
+ The arguments of this function are all pointers to local variables
+ of build_binary_op: OP0_PTR is &OP0, OP1_PTR is &OP1,
+ RESTYPE_PTR is &RESULT_TYPE and RESCODE_PTR is &RESULTCODE.
+
+ LOC is the location of the comparison.
+
+ If this function returns non-NULL_TREE, it means that the comparison has
+ a constant value. What this function returns is an expression for
+ that value. */
+
+#if 0 // sdcpp
+tree
+shorten_compare (location_t loc, tree *op0_ptr, tree *op1_ptr,
+ tree *restype_ptr, enum tree_code *rescode_ptr)
+{
+ tree type;
+ tree op0 = *op0_ptr;
+ tree op1 = *op1_ptr;
+ int unsignedp0, unsignedp1;
+ int real1, real2;
+ tree primop0, primop1;
+ enum tree_code code = *rescode_ptr;
+
+ /* Throw away any conversions to wider types
+ already present in the operands. */
+
+ primop0 = c_common_get_narrower (op0, &unsignedp0);
+ primop1 = c_common_get_narrower (op1, &unsignedp1);
+
+ /* If primopN is first sign-extended from primopN's precision to opN's
+ precision, then zero-extended from opN's precision to
+ *restype_ptr precision, shortenings might be invalid. */
+ if (TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (TREE_TYPE (op0))
+ && TYPE_PRECISION (TREE_TYPE (op0)) < TYPE_PRECISION (*restype_ptr)
+ && !unsignedp0
+ && TYPE_UNSIGNED (TREE_TYPE (op0)))
+ primop0 = op0;
+ if (TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (TREE_TYPE (op1))
+ && TYPE_PRECISION (TREE_TYPE (op1)) < TYPE_PRECISION (*restype_ptr)
+ && !unsignedp1
+ && TYPE_UNSIGNED (TREE_TYPE (op1)))
+ primop1 = op1;
+
+ /* Handle the case that OP0 does not *contain* a conversion
+ but it *requires* conversion to FINAL_TYPE. */
+
+ if (op0 == primop0 && TREE_TYPE (op0) != *restype_ptr)
+ unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+ if (op1 == primop1 && TREE_TYPE (op1) != *restype_ptr)
+ unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+
+ /* If one of the operands must be floated, we cannot optimize. */
+ real1 = TREE_CODE (TREE_TYPE (primop0)) == REAL_TYPE;
+ real2 = TREE_CODE (TREE_TYPE (primop1)) == REAL_TYPE;
+
+ /* If first arg is constant, swap the args (changing operation
+ so value is preserved), for canonicalization. Don't do this if
+ the second arg is 0. */
+
+ if (TREE_CONSTANT (primop0)
+ && !integer_zerop (primop1) && !real_zerop (primop1)
+ && !fixed_zerop (primop1))
+ {
+ std::swap (primop0, primop1);
+ std::swap (op0, op1);
+ *op0_ptr = op0;
+ *op1_ptr = op1;
+ std::swap (unsignedp0, unsignedp1);
+ std::swap (real1, real2);
+
+ switch (code)
+ {
+ case LT_EXPR:
+ code = GT_EXPR;
+ break;
+ case GT_EXPR:
+ code = LT_EXPR;
+ break;
+ case LE_EXPR:
+ code = GE_EXPR;
+ break;
+ case GE_EXPR:
+ code = LE_EXPR;
+ break;
+ default:
+ break;
+ }
+ *rescode_ptr = code;
+ }
+
+ /* If comparing an integer against a constant more bits wide,
+ maybe we can deduce a value of 1 or 0 independent of the data.
+ Or else truncate the constant now
+ rather than extend the variable at run time.
+
+ This is only interesting if the constant is the wider arg.
+ Also, it is not safe if the constant is unsigned and the
+ variable arg is signed, since in this case the variable
+ would be sign-extended and then regarded as unsigned.
+ Our technique fails in this case because the lowest/highest
+ possible unsigned results don't follow naturally from the
+ lowest/highest possible values of the variable operand.
+ For just EQ_EXPR and NE_EXPR there is another technique that
+ could be used: see if the constant can be faithfully represented
+ in the other operand's type, by truncating it and reextending it
+ and see if that preserves the constant's value. */
+
+ if (!real1 && !real2
+ && TREE_CODE (TREE_TYPE (primop0)) != FIXED_POINT_TYPE
+ && TREE_CODE (primop1) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr))
+ {
+ int min_gt, max_gt, min_lt, max_lt;
+ tree maxval, minval;
+ /* 1 if comparison is nominally unsigned. */
+ int unsignedp = TYPE_UNSIGNED (*restype_ptr);
+ tree val;
+
+ type = c_common_signed_or_unsigned_type (unsignedp0,
+ TREE_TYPE (primop0));
+
+ maxval = TYPE_MAX_VALUE (type);
+ minval = TYPE_MIN_VALUE (type);
+
+ if (unsignedp && !unsignedp0)
+ *restype_ptr = c_common_signed_type (*restype_ptr);
+
+ if (TREE_TYPE (primop1) != *restype_ptr)
+ {
+ /* Convert primop1 to target type, but do not introduce
+ additional overflow. We know primop1 is an int_cst. */
+ primop1 = force_fit_type (*restype_ptr,
+ wi::to_wide
+ (primop1,
+ TYPE_PRECISION (*restype_ptr)),
+ 0, TREE_OVERFLOW (primop1));
+ }
+ if (type != *restype_ptr)
+ {
+ minval = convert (*restype_ptr, minval);
+ maxval = convert (*restype_ptr, maxval);
+ }
+
+ min_gt = tree_int_cst_lt (primop1, minval);
+ max_gt = tree_int_cst_lt (primop1, maxval);
+ min_lt = tree_int_cst_lt (minval, primop1);
+ max_lt = tree_int_cst_lt (maxval, primop1);
+
+ val = 0;
+ /* This used to be a switch, but Genix compiler can't handle that. */
+ if (code == NE_EXPR)
+ {
+ if (max_lt || min_gt)
+ val = truthvalue_true_node;
+ }
+ else if (code == EQ_EXPR)
+ {
+ if (max_lt || min_gt)
+ val = truthvalue_false_node;
+ }
+ else if (code == LT_EXPR)
+ {
+ if (max_lt)
+ val = truthvalue_true_node;
+ if (!min_lt)
+ val = truthvalue_false_node;
+ }
+ else if (code == GT_EXPR)
+ {
+ if (min_gt)
+ val = truthvalue_true_node;
+ if (!max_gt)
+ val = truthvalue_false_node;
+ }
+ else if (code == LE_EXPR)
+ {
+ if (!max_gt)
+ val = truthvalue_true_node;
+ if (min_gt)
+ val = truthvalue_false_node;
+ }
+ else if (code == GE_EXPR)
+ {
+ if (!min_lt)
+ val = truthvalue_true_node;
+ if (max_lt)
+ val = truthvalue_false_node;
+ }
+
+ /* If primop0 was sign-extended and unsigned comparison specd,
+ we did a signed comparison above using the signed type bounds.
+ But the comparison we output must be unsigned.
+
+ Also, for inequalities, VAL is no good; but if the signed
+ comparison had *any* fixed result, it follows that the
+ unsigned comparison just tests the sign in reverse
+ (positive values are LE, negative ones GE).
+ So we can generate an unsigned comparison
+ against an extreme value of the signed type. */
+
+ if (unsignedp && !unsignedp0)
+ {
+ if (val != 0)
+ switch (code)
+ {
+ case LT_EXPR:
+ case GE_EXPR:
+ primop1 = TYPE_MIN_VALUE (type);
+ val = 0;
+ break;
+
+ case LE_EXPR:
+ case GT_EXPR:
+ primop1 = TYPE_MAX_VALUE (type);
+ val = 0;
+ break;
+
+ default:
+ break;
+ }
+ type = c_common_unsigned_type (type);
+ }
+
+ if (TREE_CODE (primop0) != INTEGER_CST
+ /* Don't warn if it's from a (non-system) macro. */
+ && !(from_macro_expansion_at
+ (expansion_point_location_if_in_system_header
+ (EXPR_LOCATION (primop0)))))
+ {
+ if (val == truthvalue_false_node)
+ warning_at (loc, OPT_Wtype_limits,
+ "comparison is always false due to limited range of data type");
+ if (val == truthvalue_true_node)
+ warning_at (loc, OPT_Wtype_limits,
+ "comparison is always true due to limited range of data type");
+ }
+
+ if (val != 0)
+ {
+ /* Don't forget to evaluate PRIMOP0 if it has side effects. */
+ if (TREE_SIDE_EFFECTS (primop0))
+ return build2 (COMPOUND_EXPR, TREE_TYPE (val), primop0, val);
+ return val;
+ }
+
+ /* Value is not predetermined, but do the comparison
+ in the type of the operand that is not constant.
+ TYPE is already properly set. */
+ }
+
+ /* If either arg is decimal float and the other is float, find the
+ proper common type to use for comparison. */
+ else if (real1 && real2
+ && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
+ && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1))))
+ type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
+
+ /* If either arg is decimal float and the other is float, fail. */
+ else if (real1 && real2
+ && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
+ || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1)))))
+ {
+ type = *restype_ptr;
+ primop0 = op0;
+ primop1 = op1;
+ }
+
+ else if (real1 && real2
+ && (TYPE_PRECISION (TREE_TYPE (primop0))
+ == TYPE_PRECISION (TREE_TYPE (primop1))))
+ type = TREE_TYPE (primop0);
+
+ /* If args' natural types are both narrower than nominal type
+ and both extend in the same manner, compare them
+ in the type of the wider arg.
+ Otherwise must actually extend both to the nominal
+ common type lest different ways of extending
+ alter the result.
+ (eg, (short)-1 == (unsigned short)-1 should be 0.) */
+
+ else if (unsignedp0 == unsignedp1 && real1 == real2
+ && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)
+ && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr))
+ {
+ type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
+ type = c_common_signed_or_unsigned_type (unsignedp0
+ || TYPE_UNSIGNED (*restype_ptr),
+ type);
+ /* Make sure shorter operand is extended the right way
+ to match the longer operand. */
+ primop0
+ = convert (c_common_signed_or_unsigned_type (unsignedp0,
+ TREE_TYPE (primop0)),
+ primop0);
+ primop1
+ = convert (c_common_signed_or_unsigned_type (unsignedp1,
+ TREE_TYPE (primop1)),
+ primop1);
+ }
+ else
+ {
+ /* Here we must do the comparison on the nominal type
+ using the args exactly as we received them. */
+ type = *restype_ptr;
+ primop0 = op0;
+ primop1 = op1;
+
+ /* We want to fold unsigned comparisons of >= and < against zero.
+ For these, we may also issue a warning if we have a non-constant
+ compared against zero, where the zero was spelled as "0" (rather
+ than merely folding to it).
+ If we have at least one constant, then op1 is constant
+ and we may have a non-constant expression as op0. */
+ if (!real1 && !real2 && integer_zerop (primop1)
+ && TYPE_UNSIGNED (*restype_ptr))
+ {
+ tree value = NULL_TREE;
+ /* All unsigned values are >= 0, so we warn. However,
+ if OP0 is a constant that is >= 0, the signedness of
+ the comparison isn't an issue, so suppress the
+ warning. */
+ tree folded_op0 = fold_for_warn (op0);
+ bool warn =
+ warn_type_limits && !in_system_header_at (loc)
+ && !(TREE_CODE (folded_op0) == INTEGER_CST
+ && !TREE_OVERFLOW (convert (c_common_signed_type (type),
+ folded_op0)))
+ /* Do not warn for enumeration types. */
+ && (TREE_CODE (expr_original_type (folded_op0)) != ENUMERAL_TYPE);
+
+ switch (code)
+ {
+ case GE_EXPR:
+ if (warn)
+ warning_at (loc, OPT_Wtype_limits,
+ "comparison of unsigned expression in %<>= 0%> "
+ "is always true");
+ value = truthvalue_true_node;
+ break;
+
+ case LT_EXPR:
+ if (warn)
+ warning_at (loc, OPT_Wtype_limits,
+ "comparison of unsigned expression in %<< 0%> "
+ "is always false");
+ value = truthvalue_false_node;
+ break;
+
+ default:
+ break;
+ }
+
+ if (value != NULL_TREE)
+ {
+ /* Don't forget to evaluate PRIMOP0 if it has side effects. */
+ if (TREE_SIDE_EFFECTS (primop0))
+ return build2 (COMPOUND_EXPR, TREE_TYPE (value),
+ primop0, value);
+ return value;
+ }
+ }
+ }
+
+ *op0_ptr = convert (type, primop0);
+ *op1_ptr = convert (type, primop1);
+
+ *restype_ptr = truthvalue_type_node;
+
+ return NULL_TREE;
+}
+
+/* Return a tree for the sum or difference (RESULTCODE says which)
+ of pointer PTROP and integer INTOP. */
+
+tree
+pointer_int_sum (location_t loc, enum tree_code resultcode,
+ tree ptrop, tree intop, bool complain)
+{
+ tree size_exp, ret;
+
+ /* The result is a pointer of the same type that is being added. */
+ tree result_type = TREE_TYPE (ptrop);
+
+ if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
+ {
+ if (complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
+ "pointer of type %<void *%> used in arithmetic");
+ else if (!complain)
+ return error_mark_node;
+ size_exp = integer_one_node;
+ }
+ else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
+ {
+ if (complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
+ "pointer to a function used in arithmetic");
+ else if (!complain)
+ return error_mark_node;
+ size_exp = integer_one_node;
+ }
+ else if (!verify_type_context (loc, TCTX_POINTER_ARITH,
+ TREE_TYPE (result_type)))
+ size_exp = integer_one_node;
+ else
+ {
+ if (!complain && !COMPLETE_TYPE_P (TREE_TYPE (result_type)))
+ return error_mark_node;
+ size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
+ /* Wrap the pointer expression in a SAVE_EXPR to make sure it
+ is evaluated first when the size expression may depend
+ on it for VM types. */
+ if (TREE_SIDE_EFFECTS (size_exp)
+ && TREE_SIDE_EFFECTS (ptrop)
+ && variably_modified_type_p (TREE_TYPE (ptrop), NULL))
+ {
+ ptrop = save_expr (ptrop);
+ size_exp = build2 (COMPOUND_EXPR, TREE_TYPE (intop), ptrop, size_exp);
+ }
+ }
+
+ /* We are manipulating pointer values, so we don't need to warn
+ about relying on undefined signed overflow. We disable the
+ warning here because we use integer types so fold won't know that
+ they are really pointers. */
+ fold_defer_overflow_warnings ();
+
+ /* If what we are about to multiply by the size of the elements
+ contains a constant term, apply distributive law
+ and multiply that constant term separately.
+ This helps produce common subexpressions. */
+ if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
+ && !TREE_CONSTANT (intop)
+ && TREE_CONSTANT (TREE_OPERAND (intop, 1))
+ && TREE_CONSTANT (size_exp)
+ /* If the constant comes from pointer subtraction,
+ skip this optimization--it would cause an error. */
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
+ /* If the constant is unsigned, and smaller than the pointer size,
+ then we must skip this optimization. This is because it could cause
+ an overflow error if the constant is negative but INTOP is not. */
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop))
+ || (TYPE_PRECISION (TREE_TYPE (intop))
+ == TYPE_PRECISION (TREE_TYPE (ptrop)))))
+ {
+ enum tree_code subcode = resultcode;
+ tree int_type = TREE_TYPE (intop);
+ if (TREE_CODE (intop) == MINUS_EXPR)
+ subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
+ /* Convert both subexpression types to the type of intop,
+ because weird cases involving pointer arithmetic
+ can result in a sum or difference with different type args. */
+ ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
+ subcode, ptrop,
+ convert (int_type, TREE_OPERAND (intop, 1)),
+ true);
+ intop = convert (int_type, TREE_OPERAND (intop, 0));
+ }
+
+ /* Convert the integer argument to a type the same size as sizetype
+ so the multiply won't overflow spuriously. */
+ if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
+ || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
+ intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
+ TYPE_UNSIGNED (sizetype)), intop);
+
+ /* Replace the integer argument with a suitable product by the object size.
+ Do this multiplication as signed, then convert to the appropriate type
+ for the pointer operation and disregard an overflow that occurred only
+ because of the sign-extension change in the latter conversion. */
+ {
+ tree t = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (intop), intop,
+ convert (TREE_TYPE (intop), size_exp));
+ intop = convert (sizetype, t);
+ if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
+ intop = wide_int_to_tree (TREE_TYPE (intop), wi::to_wide (intop));
+ }
+
+ /* Create the sum or difference. */
+ if (resultcode == MINUS_EXPR)
+ intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop);
+
+ ret = fold_build_pointer_plus_loc (loc, ptrop, intop);
+
+ fold_undefer_and_ignore_overflow_warnings ();
+
+ return ret;
+}
+#endif
+
+/* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
+ and if NON_CONST is known not to be permitted in an evaluated part
+ of a constant expression. */
+
+tree
+c_wrap_maybe_const (tree expr, bool non_const)
+{
+ location_t loc = EXPR_LOCATION (expr);
+
+ /* This should never be called for C++. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING. */
+ STRIP_TYPE_NOPS (expr);
+ expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+ C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
+ protected_set_expr_location (expr, loc);
+
+ return expr;
+}
+
+/* Return whether EXPR is a declaration whose address can never be NULL.
+ The address of the first struct member could be NULL only if it were
+ accessed through a NULL pointer, and such an access would be invalid.
+ The address of a weak symbol may be null unless it has a definition. */
+
+bool
+decl_with_nonnull_addr_p (const_tree expr)
+{
+ if (!DECL_P (expr))
+ return false;
+
+ if (TREE_CODE (expr) == FIELD_DECL
+ || TREE_CODE (expr) == PARM_DECL
+ || TREE_CODE (expr) == LABEL_DECL)
+ return true;
+
+ if (!VAR_OR_FUNCTION_DECL_P (expr))
+ return false;
+
+ if (!DECL_WEAK (expr))
+ /* Ordinary (non-weak) symbols have nonnull addresses. */
+ return true;
+
+ if (DECL_INITIAL (expr) && DECL_INITIAL (expr) != error_mark_node)
+ /* Initialized weak symbols have nonnull addresses. */
+ return true;
+
+ if (DECL_EXTERNAL (expr) || !TREE_STATIC (expr))
+ /* Uninitialized extern weak symbols and weak symbols with no
+ allocated storage might have a null address. */
+ return false;
+
+ tree attribs = DECL_ATTRIBUTES (expr);
+ if (lookup_attribute ("weakref", attribs))
+ /* Weakref symbols might have a null address unless their referent
+ is known not to. Don't bother following weakref targets here. */
+ return false;
+
+ return true;
+}
+
+/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
+ or for an `if' or `while' statement or ?..: exp. It should already
+ have been validated to be of suitable type; otherwise, a bad
+ diagnostic may result.
+
+ The EXPR is located at LOCATION.
+
+ This preparation consists of taking the ordinary
+ representation of an expression expr and producing a valid tree
+ boolean expression describing whether expr is nonzero. We could
+ simply always do build_binary_op (NE_EXPR, expr, truthvalue_false_node, 1),
+ but we optimize comparisons, &&, ||, and !.
+
+ The resulting type should always be `truthvalue_type_node'. */
+
+#if 0 // sdcpp
+tree
+c_common_truthvalue_conversion (location_t location, tree expr)
+{
+ STRIP_ANY_LOCATION_WRAPPER (expr);
+ switch (TREE_CODE (expr))
+ {
+ case EQ_EXPR: case NE_EXPR: case UNEQ_EXPR: case LTGT_EXPR:
+ case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
+ case UNLE_EXPR: case UNGE_EXPR: case UNLT_EXPR: case UNGT_EXPR:
+ case ORDERED_EXPR: case UNORDERED_EXPR:
+ if (TREE_TYPE (expr) == truthvalue_type_node)
+ return expr;
+ expr = build2 (TREE_CODE (expr), truthvalue_type_node,
+ TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+ goto ret;
+
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ if (TREE_TYPE (expr) == truthvalue_type_node)
+ return expr;
+ expr = build2 (TREE_CODE (expr), truthvalue_type_node,
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)));
+ goto ret;
+
+ case TRUTH_NOT_EXPR:
+ if (TREE_TYPE (expr) == truthvalue_type_node)
+ return expr;
+ expr = build1 (TREE_CODE (expr), truthvalue_type_node,
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)));
+ goto ret;
+
+ case ERROR_MARK:
+ return expr;
+
+ case INTEGER_CST:
+ if (TREE_CODE (TREE_TYPE (expr)) == ENUMERAL_TYPE
+ && !integer_zerop (expr)
+ && !integer_onep (expr))
+ warning_at (location, OPT_Wint_in_bool_context,
+ "enum constant in boolean context");
+ return integer_zerop (expr) ? truthvalue_false_node
+ : truthvalue_true_node;
+
+ case REAL_CST:
+ return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
+ ? truthvalue_true_node
+ : truthvalue_false_node;
+
+ case FIXED_CST:
+ return fixed_compare (NE_EXPR, &TREE_FIXED_CST (expr),
+ &FCONST0 (TYPE_MODE (TREE_TYPE (expr))))
+ ? truthvalue_true_node
+ : truthvalue_false_node;
+
+ case FUNCTION_DECL:
+ expr = build_unary_op (location, ADDR_EXPR, expr, false);
+ /* Fall through. */
+
+ case ADDR_EXPR:
+ {
+ tree inner = TREE_OPERAND (expr, 0);
+ if (decl_with_nonnull_addr_p (inner)
+ /* Check both EXPR and INNER for suppression. */
+ && !warning_suppressed_p (expr, OPT_Waddress)
+ && !warning_suppressed_p (inner, OPT_Waddress))
+ {
+ /* Common Ada programmer's mistake. */
+ warning_at (location,
+ OPT_Waddress,
+ "the address of %qD will always evaluate as %<true%>",
+ inner);
+ suppress_warning (inner, OPT_Waddress);
+ return truthvalue_true_node;
+ }
+ break;
+ }
+
+ case COMPLEX_EXPR:
+ expr = build_binary_op (EXPR_LOCATION (expr),
+ (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+ ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)),
+ false);
+ goto ret;
+
+ case NEGATE_EXPR:
+ case ABS_EXPR:
+ case ABSU_EXPR:
+ case FLOAT_EXPR:
+ case EXCESS_PRECISION_EXPR:
+ /* These don't change whether an object is nonzero or zero. */
+ return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0));
+
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ /* These don't change whether an object is zero or nonzero, but
+ we can't ignore them if their second arg has side-effects. */
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
+ {
+ expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 1),
+ c_common_truthvalue_conversion
+ (location, TREE_OPERAND (expr, 0)));
+ goto ret;
+ }
+ else
+ return c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 0));
+
+ case MULT_EXPR:
+ warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
+ "%<*%> in boolean context, suggest %<&&%> instead");
+ break;
+
+ case LSHIFT_EXPR:
+ /* We will only warn on signed shifts here, because the majority of
+ false positive warnings happen in code where unsigned arithmetic
+ was used in anticipation of a possible overflow.
+ Furthermore, if we see an unsigned type here we know that the
+ result of the shift is not subject to integer promotion rules. */
+ if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+ warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
+ "%<<<%> in boolean context, did you mean %<<%>?");
+ break;
+
+ case COND_EXPR:
+ if (warn_int_in_bool_context
+ && !from_macro_definition_at (EXPR_LOCATION (expr)))
+ {
+ tree val1 = fold_for_warn (TREE_OPERAND (expr, 1));
+ tree val2 = fold_for_warn (TREE_OPERAND (expr, 2));
+ if (TREE_CODE (val1) == INTEGER_CST
+ && TREE_CODE (val2) == INTEGER_CST
+ && !integer_zerop (val1)
+ && !integer_zerop (val2)
+ && (!integer_onep (val1)
+ || !integer_onep (val2)))
+ warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
+ "%<?:%> using integer constants in boolean context, "
+ "the expression will always evaluate to %<true%>");
+ else if ((TREE_CODE (val1) == INTEGER_CST
+ && !integer_zerop (val1)
+ && !integer_onep (val1))
+ || (TREE_CODE (val2) == INTEGER_CST
+ && !integer_zerop (val2)
+ && !integer_onep (val2)))
+ warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context,
+ "%<?:%> using integer constants in boolean context");
+ }
+ /* Distribute the conversion into the arms of a COND_EXPR. */
+ if (c_dialect_cxx ())
+ /* Avoid premature folding. */
+ break;
+ else
+ {
+ int w = warn_int_in_bool_context;
+ warn_int_in_bool_context = 0;
+ /* Folding will happen later for C. */
+ expr = build3 (COND_EXPR, truthvalue_type_node,
+ TREE_OPERAND (expr, 0),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 1)),
+ c_common_truthvalue_conversion (location,
+ TREE_OPERAND (expr, 2)));
+ warn_int_in_bool_context = w;
+ goto ret;
+ }
+
+ CASE_CONVERT:
+ {
+ tree totype = TREE_TYPE (expr);
+ tree fromtype = TREE_TYPE (TREE_OPERAND (expr, 0));
+
+ if (POINTER_TYPE_P (totype)
+ && !c_inhibit_evaluation_warnings
+ && TREE_CODE (fromtype) == REFERENCE_TYPE)
+ {
+ tree inner = expr;
+ STRIP_NOPS (inner);
+
+ if (DECL_P (inner))
+ warning_at (location,
+ OPT_Waddress,
+ "the compiler can assume that the address of "
+ "%qD will always evaluate to %<true%>",
+ inner);
+ }
+
+ /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
+ since that affects how `default_conversion' will behave. */
+ if (TREE_CODE (totype) == REFERENCE_TYPE
+ || TREE_CODE (fromtype) == REFERENCE_TYPE)
+ break;
+ /* Don't strip a conversion from C++0x scoped enum, since they
+ don't implicitly convert to other types. */
+ if (TREE_CODE (fromtype) == ENUMERAL_TYPE
+ && ENUM_IS_SCOPED (fromtype))
+ break;
+ /* If this isn't narrowing the argument, we can ignore it. */
+ if (TYPE_PRECISION (totype) >= TYPE_PRECISION (fromtype))
+ {
+ tree op0 = TREE_OPERAND (expr, 0);
+ if ((TREE_CODE (fromtype) == POINTER_TYPE
+ && TREE_CODE (totype) == INTEGER_TYPE)
+ || warning_suppressed_p (expr, OPT_Waddress))
+ /* Suppress -Waddress for casts to intptr_t, propagating
+ any suppression from the enclosing expression to its
+ operand. */
+ suppress_warning (op0, OPT_Waddress);
+ return c_common_truthvalue_conversion (location, op0);
+ }
+ }
+ break;
+
+ case MODIFY_EXPR:
+ if (!warning_suppressed_p (expr, OPT_Wparentheses)
+ && warn_parentheses
+ && warning_at (location, OPT_Wparentheses,
+ "suggest parentheses around assignment used as "
+ "truth value"))
+ suppress_warning (expr, OPT_Wparentheses);
+ break;
+
+ case CONST_DECL:
+ {
+ tree folded_expr = fold_for_warn (expr);
+ if (folded_expr != expr)
+ return c_common_truthvalue_conversion (location, folded_expr);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
+ {
+ tree t = save_expr (expr);
+ expr = (build_binary_op
+ (EXPR_LOCATION (expr),
+ (TREE_SIDE_EFFECTS (expr)
+ ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
+ c_common_truthvalue_conversion
+ (location,
+ build_unary_op (location, REALPART_EXPR, t, false)),
+ c_common_truthvalue_conversion
+ (location,
+ build_unary_op (location, IMAGPART_EXPR, t, false)),
+ false));
+ goto ret;
+ }
+
+ if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
+ {
+ tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
+ FCONST0 (TYPE_MODE
+ (TREE_TYPE (expr))));
+ return build_binary_op (location, NE_EXPR, expr, fixed_zero_node, true);
+ }
+ else
+ return build_binary_op (location, NE_EXPR, expr, integer_zero_node, true);
+
+ ret:
+ protected_set_expr_location (expr, location);
+ return expr;
+}
+
+#endif // sdcpp
+static void def_builtin_1 (enum built_in_function fncode,
+ const char *name,
+ enum built_in_class fnclass,
+ tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p);
+
+
+/* Apply the TYPE_QUALS to the new DECL. */
+
+void
+c_apply_type_quals_to_decl (int type_quals, tree decl)
+{
+ tree type = TREE_TYPE (decl);
+
+ if (type == error_mark_node)
+ return;
+
+ if ((type_quals & TYPE_QUAL_CONST)
+ || (type && TREE_CODE (type) == REFERENCE_TYPE))
+ /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr
+ constructor can produce constant init, so rely on cp_finish_decl to
+ clear TREE_READONLY if the variable has non-constant init. */
+ TREE_READONLY (decl) = 1;
+ if (type_quals & TYPE_QUAL_VOLATILE)
+ {
+ TREE_SIDE_EFFECTS (decl) = 1;
+ TREE_THIS_VOLATILE (decl) = 1;
+ }
+ if (type_quals & TYPE_QUAL_RESTRICT)
+ {
+ while (type && TREE_CODE (type) == ARRAY_TYPE)
+ /* Allow 'restrict' on arrays of pointers.
+ FIXME currently we just ignore it. */
+ type = TREE_TYPE (type);
+ if (!type
+ || !POINTER_TYPE_P (type)
+ || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
+ error ("invalid use of %<restrict%>");
+ }
+}
+
+/* Return the typed-based alias set for T, which may be an expression
+ or a type. Return -1 if we don't do anything special. */
+
+alias_set_type
+c_common_get_alias_set (tree t)
+{
+ /* For VLAs, use the alias set of the element type rather than the
+ default of alias set 0 for types compared structurally. */
+ if (TYPE_P (t) && TYPE_STRUCTURAL_EQUALITY_P (t))
+ {
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ return get_alias_set (TREE_TYPE (t));
+ return -1;
+ }
+
+ /* That's all the expressions we handle specially. */
+ if (!TYPE_P (t))
+ return -1;
+
+ /* Unlike char, char8_t doesn't alias. */
+ if (flag_char8_t && t == char8_type_node)
+ return -1;
+
+ /* The C standard guarantees that any object may be accessed via an
+ lvalue that has narrow character type (except char8_t). */
+ if (t == char_type_node
+ || t == signed_char_type_node
+ || t == unsigned_char_type_node)
+ return 0;
+
+ /* The C standard specifically allows aliasing between signed and
+ unsigned variants of the same type. We treat the signed
+ variant as canonical. */
+ if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
+ {
+ tree t1 = c_common_signed_type (t);
+
+ /* t1 == t can happen for boolean nodes which are always unsigned. */
+ if (t1 != t)
+ return get_alias_set (t1);
+ }
+
+ return -1;
+}
+
+/* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where
+ the IS_SIZEOF parameter indicates which operator is being applied.
+ The COMPLAIN flag controls whether we should diagnose possibly
+ ill-formed constructs or not. LOC is the location of the SIZEOF or
+ TYPEOF operator. If MIN_ALIGNOF, the least alignment required for
+ a type in any context should be returned, rather than the normal
+ alignment for that type. */
+
+#if 0 // sdcpp
+tree
+c_sizeof_or_alignof_type (location_t loc,
+ tree type, bool is_sizeof, bool min_alignof,
+ int complain)
+{
+ const char *op_name;
+ tree value = NULL;
+ enum tree_code type_code = TREE_CODE (type);
+
+ op_name = is_sizeof ? "sizeof" : "__alignof__";
+
+ if (type_code == FUNCTION_TYPE)
+ {
+ if (is_sizeof)
+ {
+ if (complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
+ "invalid application of %<sizeof%> to a function type");
+ else if (!complain)
+ return error_mark_node;
+ value = size_one_node;
+ }
+ else
+ {
+ if (complain)
+ {
+ if (c_dialect_cxx ())
+ pedwarn (loc, OPT_Wpedantic, "ISO C++ does not permit "
+ "%<alignof%> applied to a function type");
+ else
+ pedwarn (loc, OPT_Wpedantic, "ISO C does not permit "
+ "%<_Alignof%> applied to a function type");
+ }
+ value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ }
+ }
+ else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
+ {
+ if (type_code == VOID_TYPE
+ && complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
+ "invalid application of %qs to a void type", op_name);
+ else if (!complain)
+ return error_mark_node;
+ value = size_one_node;
+ }
+ else if (!COMPLETE_TYPE_P (type)
+ && (!c_dialect_cxx () || is_sizeof || type_code != ARRAY_TYPE))
+ {
+ if (complain)
+ error_at (loc, "invalid application of %qs to incomplete type %qT",
+ op_name, type);
+ return error_mark_node;
+ }
+ else if (c_dialect_cxx () && type_code == ARRAY_TYPE
+ && !COMPLETE_TYPE_P (TREE_TYPE (type)))
+ {
+ if (complain)
+ error_at (loc, "invalid application of %qs to array type %qT of "
+ "incomplete element type", op_name, type);
+ return error_mark_node;
+ }
+ else if (!verify_type_context (loc, is_sizeof ? TCTX_SIZEOF : TCTX_ALIGNOF,
+ type, !complain))
+ {
+ if (!complain)
+ return error_mark_node;
+ value = size_one_node;
+ }
+ else
+ {
+ if (is_sizeof)
+ /* Convert in case a char is more than one unit. */
+ value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
+ size_int (TYPE_PRECISION (char_type_node)
+ / BITS_PER_UNIT));
+ else if (min_alignof)
+ value = size_int (min_align_of_type (type));
+ else
+ value = size_int (TYPE_ALIGN_UNIT (type));
+ }
+
+ /* VALUE will have the middle-end integer type sizetype.
+ However, we should really return a value of type `size_t',
+ which is just a typedef for an ordinary integer type. */
+ value = fold_convert_loc (loc, size_type_node, value);
+
+ return value;
+}
+#endif // sdcpp
+
+/* Implement the __alignof keyword: Return the minimum required
+ alignment of EXPR, measured in bytes. For VAR_DECLs,
+ FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set
+ from an "aligned" __attribute__ specification). LOC is the
+ location of the ALIGNOF operator. */
+
+tree
+c_alignof_expr (location_t loc, tree expr)
+{
+ tree t;
+
+ if (!verify_type_context (loc, TCTX_ALIGNOF, TREE_TYPE (expr)))
+ t = size_one_node;
+
+ else if (VAR_OR_FUNCTION_DECL_P (expr))
+ t = size_int (DECL_ALIGN_UNIT (expr));
+
+ else if (TREE_CODE (expr) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
+ {
+ error_at (loc, "%<__alignof%> applied to a bit-field");
+ t = size_one_node;
+ }
+ else if (TREE_CODE (expr) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
+ t = size_int (DECL_ALIGN_UNIT (TREE_OPERAND (expr, 1)));
+
+ else if (INDIRECT_REF_P (expr))
+ {
+ tree t = TREE_OPERAND (expr, 0);
+ tree best = t;
+ int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
+
+ while (CONVERT_EXPR_P (t)
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
+ {
+ int thisalign;
+
+ t = TREE_OPERAND (t, 0);
+ thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
+ if (thisalign > bestalign)
+ best = t, bestalign = thisalign;
+ }
+ return c_alignof (loc, TREE_TYPE (TREE_TYPE (best)));
+ }
+ else
+ return c_alignof (loc, TREE_TYPE (expr));
+
+ return fold_convert_loc (loc, size_type_node, t);
+}
+
+/* Handle C and C++ default attributes. */
+
+enum built_in_attribute
+{
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_STRING(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_STRING
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+ ATTR_LAST
+};
+
+static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
+
+static void c_init_attributes (void);
+
+enum c_builtin_type
+{
+#define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
+#define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
+#define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
+#define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) NAME,
+#define DEF_FUNCTION_TYPE_9(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8, ARG9) NAME,
+#define DEF_FUNCTION_TYPE_10(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8, ARG9, ARG10) NAME,
+#define DEF_FUNCTION_TYPE_11(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) NAME,
+#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
+#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
+#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
+#define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ NAME,
+#define DEF_FUNCTION_TYPE_VAR_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) NAME,
+#define DEF_FUNCTION_TYPE_VAR_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) NAME,
+#define DEF_POINTER_TYPE(NAME, TYPE) NAME,
+#include "builtin-types.def"
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
+#undef DEF_FUNCTION_TYPE_9
+#undef DEF_FUNCTION_TYPE_10
+#undef DEF_FUNCTION_TYPE_11
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_FUNCTION_TYPE_VAR_6
+#undef DEF_FUNCTION_TYPE_VAR_7
+#undef DEF_POINTER_TYPE
+ BT_LAST
+};
+
+typedef enum c_builtin_type builtin_type;
+
+/* A temporary array for c_common_nodes_and_builtins. Used in
+ communication with def_fn_type. */
+static tree builtin_types[(int) BT_LAST + 1];
+
+/* A helper function for c_common_nodes_and_builtins. Build function type
+ for DEF with return type RET and N arguments. If VAR is true, then the
+ function should be variadic after those N arguments.
+
+ Takes special care not to ICE if any of the types involved are
+ error_mark_node, which indicates that said type is not in fact available
+ (see builtin_type_for_size). In which case the function type as a whole
+ should be error_mark_node. */
+
+static void
+def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
+{
+ tree t;
+ tree *args = XALLOCAVEC (tree, n);
+ va_list list;
+ int i;
+
+ va_start (list, n);
+ for (i = 0; i < n; ++i)
+ {
+ builtin_type a = (builtin_type) va_arg (list, int);
+ t = builtin_types[a];
+ if (t == error_mark_node)
+ goto egress;
+ args[i] = t;
+ }
+
+ t = builtin_types[ret];
+ if (t == error_mark_node)
+ goto egress;
+ if (var)
+ t = build_varargs_function_type_array (t, n, args);
+ else
+ t = build_function_type_array (t, n, args);
+
+ egress:
+ builtin_types[def] = t;
+ va_end (list);
+}
+
+/* Build builtin functions common to both C and C++ language
+ frontends. */
+
+static void
+c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
+{
+#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
+ builtin_types[ENUM] = VALUE;
+#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
+ def_fn_type (ENUM, RETURN, 0, 0);
+#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
+ def_fn_type (ENUM, RETURN, 0, 1, ARG1);
+#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
+ def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) \
+ def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) \
+ def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) \
+ def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
+ ARG7, ARG8);
+#define DEF_FUNCTION_TYPE_9(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8, ARG9) \
+ def_fn_type (ENUM, RETURN, 0, 9, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
+ ARG7, ARG8, ARG9);
+#define DEF_FUNCTION_TYPE_10(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8, ARG9, ARG10) \
+ def_fn_type (ENUM, RETURN, 0, 10, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
+ ARG7, ARG8, ARG9, ARG10);
+#define DEF_FUNCTION_TYPE_11(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8, ARG9, ARG10, ARG11) \
+ def_fn_type (ENUM, RETURN, 0, 11, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
+ ARG7, ARG8, ARG9, ARG10, ARG11);
+#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
+ def_fn_type (ENUM, RETURN, 1, 0);
+#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
+ def_fn_type (ENUM, RETURN, 1, 1, ARG1);
+#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
+ def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+ def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+ def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+ def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_FUNCTION_TYPE_VAR_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6) \
+ def_fn_type (ENUM, RETURN, 1, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+#define DEF_FUNCTION_TYPE_VAR_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7) \
+ def_fn_type (ENUM, RETURN, 1, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_POINTER_TYPE(ENUM, TYPE) \
+ builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_0
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
+#undef DEF_FUNCTION_TYPE_9
+#undef DEF_FUNCTION_TYPE_10
+#undef DEF_FUNCTION_TYPE_11
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_FUNCTION_TYPE_VAR_6
+#undef DEF_FUNCTION_TYPE_VAR_7
+#undef DEF_POINTER_TYPE
+ builtin_types[(int) BT_LAST] = NULL_TREE;
+
+ c_init_attributes ();
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
+ NONANSI_P, ATTRS, IMPLICIT, COND) \
+ if (NAME && COND) \
+ def_builtin_1 (ENUM, NAME, CLASS, \
+ builtin_types[(int) TYPE], \
+ builtin_types[(int) LIBTYPE], \
+ BOTH_P, FALLBACK_P, NONANSI_P, \
+ built_in_attributes[(int) ATTRS], IMPLICIT);
+#include "builtins.def"
+
+ targetm.init_builtins ();
+
+ build_common_builtin_nodes ();
+}
+
+/* Like get_identifier, but avoid warnings about null arguments when
+ the argument may be NULL for targets where GCC lacks stdint.h type
+ information. */
+
+static inline tree
+c_get_ident (const char *id)
+{
+ return get_identifier (id);
+}
+
+/* Build tree nodes and builtin functions common to both C and C++ language
+ frontends. */
+
+#if 1 // sdcpp
+void
+c_common_nodes_and_builtins (void)
+{
+ int char8_type_size;
+ int char16_type_size;
+ int char32_type_size;
+ int wchar_type_size;
+ tree array_domain_type;
+ tree va_list_ref_type_node;
+ tree va_list_arg_type_node;
+ int i;
+
+ fprintf(stderr, "build_common_builtin_nodes\n");
+ build_common_tree_nodes (flag_signed_char);
+
+ /* Define `int' and `char' first so that dbx will output them first. */
+ record_builtin_type (RID_INT, NULL, integer_type_node);
+ record_builtin_type (RID_CHAR, "char", char_type_node);
+
+ /* `signed' is the same as `int'. FIXME: the declarations of "signed",
+ "unsigned long", "long long unsigned" and "unsigned short" were in C++
+ but not C. Are the conditionals here needed? */
+ if (c_dialect_cxx ())
+ record_builtin_type (RID_SIGNED, NULL, integer_type_node);
+ record_builtin_type (RID_LONG, "long int", long_integer_type_node);
+ record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
+ record_builtin_type (RID_MAX, "long unsigned int",
+ long_unsigned_type_node);
+
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ {
+ char name[25];
+
+ sprintf (name, "__int%d", int_n_data[i].bitsize);
+ record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
+ int_n_trees[i].signed_type);
+ sprintf (name, "__int%d__", int_n_data[i].bitsize);
+ record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name,
+ int_n_trees[i].signed_type);
+ ridpointers[RID_FIRST_INT_N + i]
+ = DECL_NAME (TYPE_NAME (int_n_trees[i].signed_type));
+
+ sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
+ record_builtin_type (RID_MAX, name, int_n_trees[i].unsigned_type);
+ sprintf (name, "__int%d__ unsigned", int_n_data[i].bitsize);
+ record_builtin_type (RID_MAX, name, int_n_trees[i].unsigned_type);
+ }
+
+ if (c_dialect_cxx ())
+ record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
+ record_builtin_type (RID_MAX, "long long int",
+ long_long_integer_type_node);
+ record_builtin_type (RID_MAX, "long long unsigned int",
+ long_long_unsigned_type_node);
+ if (c_dialect_cxx ())
+ record_builtin_type (RID_MAX, "long long unsigned",
+ long_long_unsigned_type_node);
+ record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
+ record_builtin_type (RID_MAX, "short unsigned int",
+ short_unsigned_type_node);
+ if (c_dialect_cxx ())
+ record_builtin_type (RID_MAX, "unsigned short",
+ short_unsigned_type_node);
+
+ /* Define both `signed char' and `unsigned char'. */
+ record_builtin_type (RID_MAX, "signed char", signed_char_type_node);
+ record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
+
+ /* These are types that c_common_type_for_size and
+ c_common_type_for_mode use. */
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ intQI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ intHI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ intSI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
+ /* Note that this is different than the __int128 type that's part of
+ the generic __intN support. */
+ if (targetm.scalar_mode_supported_p (TImode))
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier ("__int128_t"),
+ intTI_type_node));
+#endif
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ unsigned_intQI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ unsigned_intHI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ unsigned_intSI_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, NULL_TREE,
+ unsigned_intDI_type_node));
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (targetm.scalar_mode_supported_p (TImode))
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier ("__uint128_t"),
+ unsigned_intTI_type_node));
+#endif
+
+ /* Create the widest literal types. */
+ if (targetm.scalar_mode_supported_p (TImode))
+ {
+ widest_integer_literal_type_node = intTI_type_node;
+ widest_unsigned_literal_type_node = unsigned_intTI_type_node;
+ }
+ else
+ {
+ widest_integer_literal_type_node = intDI_type_node;
+ widest_unsigned_literal_type_node = unsigned_intDI_type_node;
+ }
+
+ signed_size_type_node = c_common_signed_type (size_type_node);
+
+ pid_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (PID_TYPE)));
+
+ record_builtin_type (RID_FLOAT, NULL, float_type_node);
+ record_builtin_type (RID_DOUBLE, NULL, double_type_node);
+ record_builtin_type (RID_MAX, "long double", long_double_type_node);
+
+ if (!c_dialect_cxx ())
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
+ record_builtin_type ((enum rid) (RID_FLOATN_NX_FIRST + i), NULL,
+ FLOATN_NX_TYPE_NODE (i));
+
+ /* Only supported decimal floating point extension if the target
+ actually supports underlying modes. */
+ if (targetm.scalar_mode_supported_p (SDmode)
+ && targetm.scalar_mode_supported_p (DDmode)
+ && targetm.scalar_mode_supported_p (TDmode))
+ {
+ record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node);
+ record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node);
+ record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node);
+ }
+
+ if (targetm.fixed_point_supported_p ())
+ {
+ record_builtin_type (RID_MAX, "short _Fract", short_fract_type_node);
+ record_builtin_type (RID_FRACT, NULL, fract_type_node);
+ record_builtin_type (RID_MAX, "long _Fract", long_fract_type_node);
+ record_builtin_type (RID_MAX, "long long _Fract",
+ long_long_fract_type_node);
+ record_builtin_type (RID_MAX, "unsigned short _Fract",
+ unsigned_short_fract_type_node);
+ record_builtin_type (RID_MAX, "unsigned _Fract",
+ unsigned_fract_type_node);
+ record_builtin_type (RID_MAX, "unsigned long _Fract",
+ unsigned_long_fract_type_node);
+ record_builtin_type (RID_MAX, "unsigned long long _Fract",
+ unsigned_long_long_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat short _Fract",
+ sat_short_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat _Fract", sat_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat long _Fract",
+ sat_long_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat long long _Fract",
+ sat_long_long_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned short _Fract",
+ sat_unsigned_short_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned _Fract",
+ sat_unsigned_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned long _Fract",
+ sat_unsigned_long_fract_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned long long _Fract",
+ sat_unsigned_long_long_fract_type_node);
+ record_builtin_type (RID_MAX, "short _Accum", short_accum_type_node);
+ record_builtin_type (RID_ACCUM, NULL, accum_type_node);
+ record_builtin_type (RID_MAX, "long _Accum", long_accum_type_node);
+ record_builtin_type (RID_MAX, "long long _Accum",
+ long_long_accum_type_node);
+ record_builtin_type (RID_MAX, "unsigned short _Accum",
+ unsigned_short_accum_type_node);
+ record_builtin_type (RID_MAX, "unsigned _Accum",
+ unsigned_accum_type_node);
+ record_builtin_type (RID_MAX, "unsigned long _Accum",
+ unsigned_long_accum_type_node);
+ record_builtin_type (RID_MAX, "unsigned long long _Accum",
+ unsigned_long_long_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat short _Accum",
+ sat_short_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat _Accum", sat_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat long _Accum",
+ sat_long_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat long long _Accum",
+ sat_long_long_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned short _Accum",
+ sat_unsigned_short_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned _Accum",
+ sat_unsigned_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned long _Accum",
+ sat_unsigned_long_accum_type_node);
+ record_builtin_type (RID_MAX, "_Sat unsigned long long _Accum",
+ sat_unsigned_long_long_accum_type_node);
+
+ }
+
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier ("complex int"),
+ complex_integer_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier ("complex float"),
+ complex_float_type_node));
+ lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier ("complex double"),
+ complex_double_type_node));
+ lang_hooks.decls.pushdecl
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier ("complex long double"),
+ complex_long_double_type_node));
+
+ if (!c_dialect_cxx ())
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
+ {
+ char buf[30];
+ sprintf (buf, "complex _Float%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "x" : "");
+ lang_hooks.decls.pushdecl
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier (buf),
+ COMPLEX_FLOATN_NX_TYPE_NODE (i)));
+ }
+
+ /* Make fileptr_type_node a distinct void * type until
+ FILE type is defined. Likewise for const struct tm*. */
+ for (unsigned i = 0;
+ i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
+ ++i)
+ builtin_structptr_types[i].node
+ = build_variant_type_copy (builtin_structptr_types[i].base);
+
+ record_builtin_type (RID_VOID, NULL, void_type_node);
+
+ /* Set the TYPE_NAME for any variants that were built before
+ record_builtin_type gave names to the built-in types. */
+ {
+ tree void_name = TYPE_NAME (void_type_node);
+ TYPE_NAME (void_type_node) = NULL_TREE;
+ TYPE_NAME (build_qualified_type (void_type_node, TYPE_QUAL_CONST))
+ = void_name;
+ TYPE_NAME (void_type_node) = void_name;
+ }
+
+ void_list_node = build_void_list_node ();
+
+ /* Make a type to be the domain of a few array types
+ whose domains don't really matter.
+ 200 is small enough that it always fits in size_t
+ and large enough that it can hold most function names for the
+ initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
+ array_domain_type = build_index_type (size_int (200));
+
+ /* Make a type for arrays of characters.
+ With luck nothing will ever really depend on the length of this
+ array type. */
+ char_array_type_node
+ = build_array_type (char_type_node, array_domain_type);
+
+ string_type_node = build_pointer_type (char_type_node);
+ const_string_type_node
+ = build_pointer_type (build_qualified_type
+ (char_type_node, TYPE_QUAL_CONST));
+
+ /* This is special for C++ so functions can be overloaded. */
+ wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
+ wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
+ wchar_type_size = TYPE_PRECISION (wchar_type_node);
+ underlying_wchar_type_node = wchar_type_node;
+ if (c_dialect_cxx ())
+ {
+ if (TYPE_UNSIGNED (wchar_type_node))
+ wchar_type_node = make_unsigned_type (wchar_type_size);
+ else
+ wchar_type_node = make_signed_type (wchar_type_size);
+ record_builtin_type (RID_WCHAR, "wchar_t", wchar_type_node);
+ }
+
+ /* This is for wide string constants. */
+ wchar_array_type_node
+ = build_array_type (wchar_type_node, array_domain_type);
+
+ /* Define 'char8_t'. */
+ char8_type_node = get_identifier (CHAR8_TYPE);
+ char8_type_node = TREE_TYPE (identifier_global_value (char8_type_node));
+ char8_type_size = TYPE_PRECISION (char8_type_node);
+ if (c_dialect_cxx ())
+ {
+ char8_type_node = make_unsigned_type (char8_type_size);
+
+ if (flag_char8_t)
+ record_builtin_type (RID_CHAR8, "char8_t", char8_type_node);
+ }
+
+ /* This is for UTF-8 string constants. */
+ char8_array_type_node
+ = build_array_type (char8_type_node, array_domain_type);
+
+ /* Define 'char16_t'. */
+ char16_type_node = get_identifier (CHAR16_TYPE);
+ char16_type_node = TREE_TYPE (identifier_global_value (char16_type_node));
+ char16_type_size = TYPE_PRECISION (char16_type_node);
+ if (c_dialect_cxx ())
+ {
+ char16_type_node = make_unsigned_type (char16_type_size);
+
+ if (cxx_dialect >= cxx11)
+ record_builtin_type (RID_CHAR16, "char16_t", char16_type_node);
+ }
+
+ /* This is for UTF-16 string constants. */
+ char16_array_type_node
+ = build_array_type (char16_type_node, array_domain_type);
+
+ /* Define 'char32_t'. */
+ char32_type_node = get_identifier (CHAR32_TYPE);
+ char32_type_node = TREE_TYPE (identifier_global_value (char32_type_node));
+ char32_type_size = TYPE_PRECISION (char32_type_node);
+ if (c_dialect_cxx ())
+ {
+ char32_type_node = make_unsigned_type (char32_type_size);
+
+ if (cxx_dialect >= cxx11)
+ record_builtin_type (RID_CHAR32, "char32_t", char32_type_node);
+ }
+
+ /* This is for UTF-32 string constants. */
+ char32_array_type_node
+ = build_array_type (char32_type_node, array_domain_type);
+
+ wint_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
+
+ intmax_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (INTMAX_TYPE)));
+ uintmax_type_node =
+ TREE_TYPE (identifier_global_value (get_identifier (UINTMAX_TYPE)));
+
+ if (SIG_ATOMIC_TYPE)
+ sig_atomic_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (SIG_ATOMIC_TYPE)));
+ if (INT8_TYPE)
+ int8_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT8_TYPE)));
+ if (INT16_TYPE)
+ int16_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT16_TYPE)));
+ if (INT32_TYPE)
+ int32_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT32_TYPE)));
+ if (INT64_TYPE)
+ int64_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT64_TYPE)));
+ if (UINT8_TYPE)
+ uint8_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT8_TYPE)));
+ if (UINT16_TYPE)
+ c_uint16_type_node = uint16_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT16_TYPE)));
+ if (UINT32_TYPE)
+ c_uint32_type_node = uint32_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT32_TYPE)));
+ if (UINT64_TYPE)
+ c_uint64_type_node = uint64_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT64_TYPE)));
+ if (INT_LEAST8_TYPE)
+ int_least8_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST8_TYPE)));
+ if (INT_LEAST16_TYPE)
+ int_least16_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST16_TYPE)));
+ if (INT_LEAST32_TYPE)
+ int_least32_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST32_TYPE)));
+ if (INT_LEAST64_TYPE)
+ int_least64_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST64_TYPE)));
+ if (UINT_LEAST8_TYPE)
+ uint_least8_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST8_TYPE)));
+ if (UINT_LEAST16_TYPE)
+ uint_least16_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST16_TYPE)));
+ if (UINT_LEAST32_TYPE)
+ uint_least32_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST32_TYPE)));
+ if (UINT_LEAST64_TYPE)
+ uint_least64_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST64_TYPE)));
+ if (INT_FAST8_TYPE)
+ int_fast8_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST8_TYPE)));
+ if (INT_FAST16_TYPE)
+ int_fast16_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST16_TYPE)));
+ if (INT_FAST32_TYPE)
+ int_fast32_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST32_TYPE)));
+ if (INT_FAST64_TYPE)
+ int_fast64_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST64_TYPE)));
+ if (UINT_FAST8_TYPE)
+ uint_fast8_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST8_TYPE)));
+ if (UINT_FAST16_TYPE)
+ uint_fast16_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST16_TYPE)));
+ if (UINT_FAST32_TYPE)
+ uint_fast32_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST32_TYPE)));
+ if (UINT_FAST64_TYPE)
+ uint_fast64_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST64_TYPE)));
+ if (INTPTR_TYPE)
+ intptr_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (INTPTR_TYPE)));
+ if (UINTPTR_TYPE)
+ uintptr_type_node =
+ TREE_TYPE (identifier_global_value (c_get_ident (UINTPTR_TYPE)));
+
+ default_function_type
+ = build_varargs_function_type_list (integer_type_node, NULL_TREE);
+ unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
+
+ lang_hooks.decls.pushdecl
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier ("__builtin_va_list"),
+ va_list_type_node));
+ if (targetm.enum_va_list_p)
+ {
+ int l;
+ const char *pname;
+ tree ptype;
+
+ for (l = 0; targetm.enum_va_list_p (l, &pname, &ptype); ++l)
+ {
+ lang_hooks.decls.pushdecl
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL, get_identifier (pname),
+ ptype));
+
+ }
+ }
+
+ if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
+ {
+ va_list_arg_type_node = va_list_ref_type_node =
+ build_pointer_type (TREE_TYPE (va_list_type_node));
+ }
+ else
+ {
+ va_list_arg_type_node = va_list_type_node;
+ va_list_ref_type_node = build_reference_type (va_list_type_node);
+ }
+
+ c_define_builtins (va_list_ref_type_node, va_list_arg_type_node);
+
+ main_identifier_node = get_identifier ("main");
+
+ /* Create the built-in __null node. It is important that this is
+ not shared. */
+ null_node = make_int_cst (1, 1);
+ TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
+
+ /* Since builtin_types isn't gc'ed, don't export these nodes. */
+ memset (builtin_types, 0, sizeof (builtin_types));
+}
+#endif
+
+/* The number of named compound-literals generated thus far. */
+static GTY(()) int compound_literal_number;
+
+/* Set DECL_NAME for DECL, a VAR_DECL for a compound-literal. */
+
+void
+set_compound_literal_name (tree decl)
+{
+ char *name;
+ ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+ compound_literal_number);
+ compound_literal_number++;
+ DECL_NAME (decl) = get_identifier (name);
+}
+
+/* build_va_arg helper function. Return a VA_ARG_EXPR with location LOC, type
+ TYPE and operand OP. */
+
+static tree
+build_va_arg_1 (location_t loc, tree type, tree op)
+{
+ tree expr = build1 (VA_ARG_EXPR, type, op);
+ SET_EXPR_LOCATION (expr, loc);
+ return expr;
+}
+
+/* Return a VA_ARG_EXPR corresponding to a source-level expression
+ va_arg (EXPR, TYPE) at source location LOC. */
+
+tree
+build_va_arg (location_t loc, tree expr, tree type)
+{
+ tree va_type = TREE_TYPE (expr);
+ tree canon_va_type = (va_type == error_mark_node
+ ? error_mark_node
+ : targetm.canonical_va_list_type (va_type));
+
+ if (va_type == error_mark_node
+ || canon_va_type == NULL_TREE)
+ {
+ if (canon_va_type == NULL_TREE)
+ error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>");
+
+ /* Let's handle things neutrally, if expr:
+ - has undeclared type, or
+ - is not an va_list type. */
+ return build_va_arg_1 (loc, type, error_mark_node);
+ }
+
+ if (TREE_CODE (canon_va_type) != ARRAY_TYPE)
+ {
+ /* Case 1: Not an array type. */
+
+ /* Take the address, to get '&ap'. Note that &ap is not a va_list
+ type. */
+ c_common_mark_addressable_vec (expr);
+ expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (expr)), expr);
+
+ return build_va_arg_1 (loc, type, expr);
+ }
+
+ /* Case 2: Array type.
+
+ Background:
+
+ For contrast, let's start with the simple case (case 1). If
+ canon_va_type is not an array type, but say a char *, then when
+ passing-by-value a va_list, the type of the va_list param decl is
+ the same as for another va_list decl (all ap's are char *):
+
+ f2_1 (char * ap)
+ D.1815 = VA_ARG (&ap, 0B, 1);
+ return D.1815;
+
+ f2 (int i)
+ char * ap.0;
+ char * ap;
+ __builtin_va_start (&ap, 0);
+ ap.0 = ap;
+ res = f2_1 (ap.0);
+ __builtin_va_end (&ap);
+ D.1812 = res;
+ return D.1812;
+
+ However, if canon_va_type is ARRAY_TYPE, then when passing-by-value a
+ va_list the type of the va_list param decl (case 2b, struct * ap) is not
+ the same as for another va_list decl (case 2a, struct ap[1]).
+
+ f2_1 (struct * ap)
+ D.1844 = VA_ARG (ap, 0B, 0);
+ return D.1844;
+
+ f2 (int i)
+ struct ap[1];
+ __builtin_va_start (&ap, 0);
+ res = f2_1 (&ap);
+ __builtin_va_end (&ap);
+ D.1841 = res;
+ return D.1841;
+
+ Case 2b is different because:
+ - on the callee side, the parm decl has declared type va_list, but
+ grokdeclarator changes the type of the parm decl to a pointer to the
+ array elem type.
+ - on the caller side, the pass-by-value uses &ap.
+
+ We unify these two cases (case 2a: va_list is array type,
+ case 2b: va_list is pointer to array elem type), by adding '&' for the
+ array type case, such that we have a pointer to array elem in both
+ cases. */
+
+ if (TREE_CODE (va_type) == ARRAY_TYPE)
+ {
+ /* Case 2a: va_list is array type. */
+
+ /* Take the address, to get '&ap'. Make sure it's a pointer to array
+ elem type. */
+ c_common_mark_addressable_vec (expr);
+ expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (canon_va_type)),
+ expr);
+
+ /* Verify that &ap is still recognized as having va_list type. */
+ tree canon_expr_type
+ = targetm.canonical_va_list_type (TREE_TYPE (expr));
+ gcc_assert (canon_expr_type != NULL_TREE);
+ }
+ else
+ {
+ /* Case 2b: va_list is pointer to array elem type. */
+ gcc_assert (POINTER_TYPE_P (va_type));
+
+ /* Comparison as in std_canonical_va_list_type. */
+ gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (va_type))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (canon_va_type)));
+
+ /* Don't take the address. We've already got '&ap'. */
+ ;
+ }
+
+ return build_va_arg_1 (loc, type, expr);
+}
+
+
+/* Linked list of disabled built-in functions. */
+
+#endif // sdcpp
+struct disabled_builtin
+{
+ const char *name;
+ struct disabled_builtin *next;
+};
+static disabled_builtin *disabled_builtins = NULL;
+
+#if 0 // sdcpp
+static bool builtin_function_disabled_p (const char *);
+#endif // sdcpp
+
+/* Disable a built-in function specified by -fno-builtin-NAME. If NAME
+ begins with "__builtin_", give an error. */
+
+void
+disable_builtin_function (const char *name)
+{
+ if (startswith (name, "__builtin_"))
+ error ("cannot disable built-in function %qs", name);
+ else
+ {
+ disabled_builtin *new_disabled_builtin = XNEW (disabled_builtin);
+ new_disabled_builtin->name = name;
+ new_disabled_builtin->next = disabled_builtins;
+ disabled_builtins = new_disabled_builtin;
+ }
+}
+
+#if 0 // sdcpp
+/* Return true if the built-in function NAME has been disabled, false
+ otherwise. */
+
+static bool
+builtin_function_disabled_p (const char *name)
+{
+ disabled_builtin *p;
+ for (p = disabled_builtins; p != NULL; p = p->next)
+ {
+ if (strcmp (name, p->name) == 0)
+ return true;
+ }
+ return false;
+}
+
+
+/* Worker for DEF_BUILTIN.
+ Possibly define a builtin function with one or two names.
+ Does not declare a non-__builtin_ function if flag_no_builtin, or if
+ nonansi_p and flag_no_nonansi_builtin. */
+
+static void
+def_builtin_1 (enum built_in_function fncode,
+ const char *name,
+ enum built_in_class fnclass,
+ tree fntype, tree libtype,
+ bool both_p, bool fallback_p, bool nonansi_p,
+ tree fnattrs, bool implicit_p)
+{
+ tree decl;
+ const char *libname;
+
+ if (fntype == error_mark_node)
+ return;
+
+ gcc_assert ((!both_p && !fallback_p)
+ || startswith (name, "__builtin_"));
+
+ libname = name + strlen ("__builtin_");
+ decl = add_builtin_function (name, fntype, fncode, fnclass,
+ (fallback_p ? libname : NULL),
+ fnattrs);
+
+ set_builtin_decl (fncode, decl, implicit_p);
+
+ if (both_p
+ && !flag_no_builtin && !builtin_function_disabled_p (libname)
+ && !(nonansi_p && flag_no_nonansi_builtin))
+ add_builtin_function (libname, libtype, fncode, fnclass,
+ NULL, fnattrs);
+}
+
+/* Nonzero if the type T promotes to int. This is (nearly) the
+ integral promotions defined in ISO C99 6.3.1.1/2. */
+
+bool
+c_promoting_integer_type_p (const_tree t)
+{
+ switch (TREE_CODE (t))
+ {
+ case INTEGER_TYPE:
+ return (TYPE_MAIN_VARIANT (t) == char_type_node
+ || TYPE_MAIN_VARIANT (t) == signed_char_type_node
+ || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node
+ || TYPE_MAIN_VARIANT (t) == short_integer_type_node
+ || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node
+ || TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node));
+
+ case ENUMERAL_TYPE:
+ /* ??? Technically all enumerations not larger than an int
+ promote to an int. But this is used along code paths
+ that only want to notice a size change. */
+ return TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node);
+
+ case BOOLEAN_TYPE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Return 1 if PARMS specifies a fixed number of parameters
+ and none of their types is affected by default promotions. */
+
+bool
+self_promoting_args_p (const_tree parms)
+{
+ const_tree t;
+ for (t = parms; t; t = TREE_CHAIN (t))
+ {
+ tree type = TREE_VALUE (t);
+
+ if (type == error_mark_node)
+ continue;
+
+ if (TREE_CHAIN (t) == NULL_TREE && type != void_type_node)
+ return false;
+
+ if (type == NULL_TREE)
+ return false;
+
+ if (TYPE_MAIN_VARIANT (type) == float_type_node)
+ return false;
+
+ if (c_promoting_integer_type_p (type))
+ return false;
+ }
+ return true;
+}
+
+/* Recursively remove any '*' or '&' operator from TYPE. */
+tree
+strip_pointer_operator (tree t)
+{
+ while (POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+ return t;
+}
+
+/* Recursively remove pointer or array type from TYPE. */
+tree
+strip_pointer_or_array_types (tree t)
+{
+ while (TREE_CODE (t) == ARRAY_TYPE || POINTER_TYPE_P (t))
+ t = TREE_TYPE (t);
+ return t;
+}
+
+/* Used to compare case labels. K1 and K2 are actually tree nodes
+ representing case labels, or NULL_TREE for a `default' label.
+ Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
+ K2, and 0 if K1 and K2 are equal. */
+
+int
+case_compare (splay_tree_key k1, splay_tree_key k2)
+{
+ /* Consider a NULL key (such as arises with a `default' label) to be
+ smaller than anything else. */
+ if (!k1)
+ return k2 ? -1 : 0;
+ else if (!k2)
+ return k1 ? 1 : 0;
+
+ return tree_int_cst_compare ((tree) k1, (tree) k2);
+}
+
+/* Process a case label, located at LOC, for the range LOW_VALUE
+ ... HIGH_VALUE. If LOW_VALUE and HIGH_VALUE are both NULL_TREE
+ then this case label is actually a `default' label. If only
+ HIGH_VALUE is NULL_TREE, then case label was declared using the
+ usual C/C++ syntax, rather than the GNU case range extension.
+ 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. */
+
+tree
+c_add_case_label (location_t loc, splay_tree cases, tree cond,
+ tree low_value, tree high_value)
+{
+ tree type;
+ tree label;
+ tree case_label;
+ splay_tree_node node;
+
+ /* Create the LABEL_DECL itself. */
+ label = create_artificial_label (loc);
+
+ /* If there was an error processing the switch condition, bail now
+ before we get more confused. */
+ if (!cond || cond == error_mark_node)
+ goto error_out;
+
+ if ((low_value && TREE_TYPE (low_value)
+ && POINTER_TYPE_P (TREE_TYPE (low_value)))
+ || (high_value && TREE_TYPE (high_value)
+ && POINTER_TYPE_P (TREE_TYPE (high_value))))
+ {
+ error_at (loc, "pointers are not permitted as case values");
+ goto error_out;
+ }
+
+ /* Case ranges are a GNU extension. */
+ if (high_value)
+ pedwarn (loc, OPT_Wpedantic,
+ "range expressions in switch statements are non-standard");
+
+ type = TREE_TYPE (cond);
+ if (low_value)
+ {
+ low_value = check_case_value (loc, low_value);
+ low_value = convert_and_check (loc, type, low_value);
+ low_value = fold (low_value);
+ if (low_value == error_mark_node)
+ goto error_out;
+ }
+ if (high_value)
+ {
+ high_value = check_case_value (loc, high_value);
+ high_value = convert_and_check (loc, type, high_value);
+ high_value = fold (high_value);
+ if (high_value == error_mark_node)
+ goto error_out;
+ }
+
+ if (low_value && high_value)
+ {
+ /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
+ really a case range, even though it was written that way.
+ Remove the HIGH_VALUE to simplify later processing. */
+ if (tree_int_cst_equal (low_value, high_value))
+ high_value = NULL_TREE;
+ else if (!tree_int_cst_lt (low_value, high_value))
+ warning_at (loc, 0, "empty range specified");
+ }
+
+ /* Look up the LOW_VALUE in the table of case labels we already
+ have. */
+ node = splay_tree_lookup (cases, (splay_tree_key) low_value);
+ /* If there was not an exact match, check for overlapping ranges.
+ There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
+ that's a `default' label and the only overlap is an exact match. */
+ if (!node && (low_value || high_value))
+ {
+ splay_tree_node low_bound;
+ splay_tree_node high_bound;
+
+ /* Even though there wasn't an exact match, there might be an
+ overlap between this case range and another case range.
+ Since we've (inductively) not allowed any overlapping case
+ ranges, we simply need to find the greatest low case label
+ that is smaller that LOW_VALUE, and the smallest low case
+ label that is greater than LOW_VALUE. If there is an overlap
+ it will occur in one of these two ranges. */
+ low_bound = splay_tree_predecessor (cases,
+ (splay_tree_key) low_value);
+ high_bound = splay_tree_successor (cases,
+ (splay_tree_key) low_value);
+
+ /* Check to see if the LOW_BOUND overlaps. It is smaller than
+ the LOW_VALUE, so there is no need to check unless the
+ LOW_BOUND is in fact itself a case range. */
+ if (low_bound
+ && CASE_HIGH ((tree) low_bound->value)
+ && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
+ low_value) >= 0)
+ node = low_bound;
+ /* Check to see if the HIGH_BOUND overlaps. The low end of that
+ range is bigger than the low end of the current range, so we
+ are only interested if the current range is a real range, and
+ not an ordinary case label. */
+ else if (high_bound
+ && high_value
+ && (tree_int_cst_compare ((tree) high_bound->key,
+ high_value)
+ <= 0))
+ node = high_bound;
+ }
+ /* If there was an overlap, issue an error. */
+ if (node)
+ {
+ tree duplicate = CASE_LABEL ((tree) node->value);
+
+ if (high_value)
+ {
+ error_at (loc, "duplicate (or overlapping) case value");
+ inform (DECL_SOURCE_LOCATION (duplicate),
+ "this is the first entry overlapping that value");
+ }
+ else if (low_value)
+ {
+ error_at (loc, "duplicate case value") ;
+ inform (DECL_SOURCE_LOCATION (duplicate), "previously used here");
+ }
+ else
+ {
+ error_at (loc, "multiple default labels in one switch");
+ inform (DECL_SOURCE_LOCATION (duplicate),
+ "this is the first default label");
+ }
+ goto error_out;
+ }
+
+ /* Add a CASE_LABEL to the statement-tree. */
+ case_label = add_stmt (build_case_label (low_value, high_value, label));
+ /* Register this case label in the splay tree. */
+ splay_tree_insert (cases,
+ (splay_tree_key) low_value,
+ (splay_tree_value) case_label);
+
+ return case_label;
+
+ error_out:
+ /* Add a label so that the back-end doesn't think that the beginning of
+ the switch is unreachable. Note that we do not add a case label, as
+ that just leads to duplicates and thence to failure later on. */
+ if (!cases->root)
+ {
+ tree t = create_artificial_label (loc);
+ add_stmt (build_stmt (loc, LABEL_EXPR, t));
+ }
+ return error_mark_node;
+}
+
+/* Subroutine of c_switch_covers_all_cases_p, called via
+ splay_tree_foreach. Return 1 if it doesn't cover all the cases.
+ ARGS[0] is initially NULL and after the first iteration is the
+ so far highest case label. ARGS[1] is the minimum of SWITCH_COND's
+ type. */
+
+#if 0 // sdcpp
+static int
+c_switch_covers_all_cases_p_1 (splay_tree_node node, void *data)
+{
+ tree label = (tree) node->value;
+ tree *args = (tree *) data;
+
+ /* If there is a default case, we shouldn't have called this. */
+ gcc_assert (CASE_LOW (label));
+
+ if (args[0] == NULL_TREE)
+ {
+ if (wi::to_widest (args[1]) < wi::to_widest (CASE_LOW (label)))
+ return 1;
+ }
+ else if (wi::add (wi::to_widest (args[0]), 1)
+ != wi::to_widest (CASE_LOW (label)))
+ return 1;
+ if (CASE_HIGH (label))
+ args[0] = CASE_HIGH (label);
+ else
+ args[0] = CASE_LOW (label);
+ return 0;
+}
+
+/* Return true if switch with CASES and switch condition with type
+ covers all possible values in the case labels. */
+
+bool
+c_switch_covers_all_cases_p (splay_tree cases, tree type)
+{
+ /* If there is default:, this is always the case. */
+ splay_tree_node default_node
+ = splay_tree_lookup (cases, (splay_tree_key) NULL);
+ if (default_node)
+ return true;
+
+ if (!INTEGRAL_TYPE_P (type))
+ return false;
+
+ tree args[2] = { NULL_TREE, TYPE_MIN_VALUE (type) };
+ if (splay_tree_foreach (cases, c_switch_covers_all_cases_p_1, args))
+ return false;
+
+ /* If there are no cases at all, or if the highest case label
+ is smaller than TYPE_MAX_VALUE, return false. */
+ if (args[0] == NULL_TREE
+ || wi::to_widest (args[0]) < wi::to_widest (TYPE_MAX_VALUE (type)))
+ return false;
+
+ return true;
+}
+#endif // sdcpp
+#endif // sdcpp
+
+/* Return true if stmt can fall through. Used by block_may_fallthru
+ default case. */
+
+#if 0 // sdcpp
+bool
+c_block_may_fallthru (const_tree stmt)
+{
+ switch (TREE_CODE (stmt))
+ {
+ case SWITCH_STMT:
+ return (!SWITCH_STMT_ALL_CASES_P (stmt)
+ || !SWITCH_STMT_NO_BREAK_P (stmt)
+ || block_may_fallthru (SWITCH_STMT_BODY (stmt)));
+
+ default:
+ return true;
+ }
+}
+
+/* Finish an expression taking the address of LABEL (an
+ IDENTIFIER_NODE). Returns an expression for the address.
+
+ LOC is the location for the expression returned. */
+
+tree
+finish_label_address_expr (tree label, location_t loc)
+{
+ tree result;
+
+ pedwarn (input_location, OPT_Wpedantic, "taking the address of a label is non-standard");
+
+ if (label == error_mark_node)
+ return error_mark_node;
+
+ label = lookup_label (label);
+ if (label == NULL_TREE)
+ result = null_pointer_node;
+ else
+ {
+ TREE_USED (label) = 1;
+ result = build1 (ADDR_EXPR, ptr_type_node, label);
+ /* The current function is not necessarily uninlinable.
+ Computed gotos are incompatible with inlining, but the value
+ here could be used only in a diagnostic, for example. */
+ protected_set_expr_location (result, loc);
+ }
+
+ return result;
+}
+
+
+/* Given a boolean expression ARG, return a tree representing an increment
+ or decrement (as indicated by CODE) of ARG. The front end must check for
+ invalid cases (e.g., decrement in C++). */
+tree
+boolean_increment (enum tree_code code, tree arg)
+{
+ tree val;
+ tree true_res = build_int_cst (TREE_TYPE (arg), 1);
+
+ arg = stabilize_reference (arg);
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
+ break;
+ case POSTINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
+ arg = save_expr (arg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+ break;
+ case PREDECREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
+ invert_truthvalue_loc (input_location, arg));
+ break;
+ case POSTDECREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
+ invert_truthvalue_loc (input_location, arg));
+ arg = save_expr (arg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ TREE_SIDE_EFFECTS (val) = 1;
+ return val;
+}
+
+/* Built-in macros for stddef.h and stdint.h, that require macros
+ defined in this file. */
+void
+c_stddef_cpp_builtins(void)
+{
+ builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0);
+ builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
+ builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
+ builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
+ builtin_define_with_value ("__INTMAX_TYPE__", INTMAX_TYPE, 0);
+ builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
+ if (flag_char8_t)
+ builtin_define_with_value ("__CHAR8_TYPE__", CHAR8_TYPE, 0);
+ builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
+ builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
+ if (SIG_ATOMIC_TYPE)
+ builtin_define_with_value ("__SIG_ATOMIC_TYPE__", SIG_ATOMIC_TYPE, 0);
+ if (INT8_TYPE)
+ builtin_define_with_value ("__INT8_TYPE__", INT8_TYPE, 0);
+ if (INT16_TYPE)
+ builtin_define_with_value ("__INT16_TYPE__", INT16_TYPE, 0);
+ if (INT32_TYPE)
+ builtin_define_with_value ("__INT32_TYPE__", INT32_TYPE, 0);
+ if (INT64_TYPE)
+ builtin_define_with_value ("__INT64_TYPE__", INT64_TYPE, 0);
+ if (UINT8_TYPE)
+ builtin_define_with_value ("__UINT8_TYPE__", UINT8_TYPE, 0);
+ if (UINT16_TYPE)
+ builtin_define_with_value ("__UINT16_TYPE__", UINT16_TYPE, 0);
+ if (UINT32_TYPE)
+ builtin_define_with_value ("__UINT32_TYPE__", UINT32_TYPE, 0);
+ if (UINT64_TYPE)
+ builtin_define_with_value ("__UINT64_TYPE__", UINT64_TYPE, 0);
+ if (INT_LEAST8_TYPE)
+ builtin_define_with_value ("__INT_LEAST8_TYPE__", INT_LEAST8_TYPE, 0);
+ if (INT_LEAST16_TYPE)
+ builtin_define_with_value ("__INT_LEAST16_TYPE__", INT_LEAST16_TYPE, 0);
+ if (INT_LEAST32_TYPE)
+ builtin_define_with_value ("__INT_LEAST32_TYPE__", INT_LEAST32_TYPE, 0);
+ if (INT_LEAST64_TYPE)
+ builtin_define_with_value ("__INT_LEAST64_TYPE__", INT_LEAST64_TYPE, 0);
+ if (UINT_LEAST8_TYPE)
+ builtin_define_with_value ("__UINT_LEAST8_TYPE__", UINT_LEAST8_TYPE, 0);
+ if (UINT_LEAST16_TYPE)
+ builtin_define_with_value ("__UINT_LEAST16_TYPE__", UINT_LEAST16_TYPE, 0);
+ if (UINT_LEAST32_TYPE)
+ builtin_define_with_value ("__UINT_LEAST32_TYPE__", UINT_LEAST32_TYPE, 0);
+ if (UINT_LEAST64_TYPE)
+ builtin_define_with_value ("__UINT_LEAST64_TYPE__", UINT_LEAST64_TYPE, 0);
+ if (INT_FAST8_TYPE)
+ builtin_define_with_value ("__INT_FAST8_TYPE__", INT_FAST8_TYPE, 0);
+ if (INT_FAST16_TYPE)
+ builtin_define_with_value ("__INT_FAST16_TYPE__", INT_FAST16_TYPE, 0);
+ if (INT_FAST32_TYPE)
+ builtin_define_with_value ("__INT_FAST32_TYPE__", INT_FAST32_TYPE, 0);
+ if (INT_FAST64_TYPE)
+ builtin_define_with_value ("__INT_FAST64_TYPE__", INT_FAST64_TYPE, 0);
+ if (UINT_FAST8_TYPE)
+ builtin_define_with_value ("__UINT_FAST8_TYPE__", UINT_FAST8_TYPE, 0);
+ if (UINT_FAST16_TYPE)
+ builtin_define_with_value ("__UINT_FAST16_TYPE__", UINT_FAST16_TYPE, 0);
+ if (UINT_FAST32_TYPE)
+ builtin_define_with_value ("__UINT_FAST32_TYPE__", UINT_FAST32_TYPE, 0);
+ if (UINT_FAST64_TYPE)
+ builtin_define_with_value ("__UINT_FAST64_TYPE__", UINT_FAST64_TYPE, 0);
+ if (INTPTR_TYPE)
+ builtin_define_with_value ("__INTPTR_TYPE__", INTPTR_TYPE, 0);
+ if (UINTPTR_TYPE)
+ builtin_define_with_value ("__UINTPTR_TYPE__", UINTPTR_TYPE, 0);
+ /* GIMPLE FE testcases need access to the GCC internal 'sizetype'.
+ Expose it as __SIZETYPE__. */
+ if (flag_gimple)
+ builtin_define_with_value ("__SIZETYPE__", SIZETYPE, 0);
+}
+
+#if 0 // sdcpp
+static void
+c_init_attributes (void)
+{
+ /* Fill in the built_in_attributes array. */
+#define DEF_ATTR_NULL_TREE(ENUM) \
+ built_in_attributes[(int) ENUM] = NULL_TREE;
+#define DEF_ATTR_INT(ENUM, VALUE) \
+ built_in_attributes[(int) ENUM] = build_int_cst (integer_type_node, VALUE);
+#define DEF_ATTR_STRING(ENUM, VALUE) \
+ built_in_attributes[(int) ENUM] = build_string (strlen (VALUE), VALUE);
+#define DEF_ATTR_IDENT(ENUM, STRING) \
+ built_in_attributes[(int) ENUM] = get_identifier (STRING);
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
+ built_in_attributes[(int) ENUM] \
+ = tree_cons (built_in_attributes[(int) PURPOSE], \
+ built_in_attributes[(int) VALUE], \
+ built_in_attributes[(int) CHAIN]);
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+}
+#endif // sdcpp
+
+/* Check whether the byte alignment ALIGN is a valid user-specified
+ alignment less than the supported maximum. If so, return ALIGN's
+ base-2 log; if not, output an error and return -1. If OBJFILE
+ then reject alignments greater than MAX_OFILE_ALIGNMENT when
+ converted to bits. Otherwise, consider valid only alignments
+ that are less than HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT.
+ Zero is not considered a valid argument (and results in -1 on
+ return) but it only triggers a warning when WARN_ZERO is set. */
+
+int
+check_user_alignment (const_tree align, bool objfile, bool warn_zero)
+{
+ if (error_operand_p (align))
+ return -1;
+
+ if (TREE_CODE (align) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
+ {
+ error ("requested alignment is not an integer constant");
+ return -1;
+ }
+
+ if (integer_zerop (align))
+ {
+ if (warn_zero)
+ warning (OPT_Wattributes,
+ "requested alignment %qE is not a positive power of 2",
+ align);
+ return -1;
+ }
+
+ /* Log2 of the byte alignment ALIGN. */
+ int log2align;
+ if (tree_int_cst_sgn (align) == -1
+ || (log2align = tree_log2 (align)) == -1)
+ {
+ error ("requested alignment %qE is not a positive power of 2",
+ align);
+ return -1;
+ }
+
+ if (objfile)
+ {
+ unsigned maxalign = MAX_OFILE_ALIGNMENT / BITS_PER_UNIT;
+ if (!tree_fits_uhwi_p (align) || tree_to_uhwi (align) > maxalign)
+ {
+ error ("requested alignment %qE exceeds object file maximum %u",
+ align, maxalign);
+ return -1;
+ }
+ }
+
+ if (log2align >= HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT)
+ {
+ error ("requested alignment %qE exceeds maximum %u",
+ align, 1U << (HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT - 1));
+ return -1;
+ }
+
+ return log2align;
+}
+
+/* Determine the ELF symbol visibility for DECL, which is either a
+ variable or a function. It is an error to use this function if a
+ definition of DECL is not available in this translation unit.
+ Returns true if the final visibility has been determined by this
+ function; false if the caller is free to make additional
+ modifications. */
+
+bool
+c_determine_visibility (tree decl)
+{
+ gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
+
+ /* If the user explicitly specified the visibility with an
+ attribute, honor that. DECL_VISIBILITY will have been set during
+ the processing of the attribute. We check for an explicit
+ attribute, rather than just checking DECL_VISIBILITY_SPECIFIED,
+ to distinguish the use of an attribute from the use of a "#pragma
+ GCC visibility push(...)"; in the latter case we still want other
+ considerations to be able to overrule the #pragma. */
+ if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))
+ || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ && (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
+ || lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))))
+ return true;
+
+ /* Set default visibility to whatever the user supplied with
+ visibility_specified depending on #pragma GCC visibility. */
+ if (!DECL_VISIBILITY_SPECIFIED (decl))
+ {
+ if (visibility_options.inpragma
+ || DECL_VISIBILITY (decl) != default_visibility)
+ {
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ /* If visibility changed and DECL already has DECL_RTL, ensure
+ symbol flags are updated. */
+ if (((VAR_P (decl) && TREE_STATIC (decl))
+ || TREE_CODE (decl) == FUNCTION_DECL)
+ && DECL_RTL_SET_P (decl))
+ make_decl_rtl (decl);
+ }
+ }
+ return false;
+}
+
+/* Data to communicate through check_function_arguments_recurse between
+ check_function_nonnull and check_nonnull_arg. */
+
+struct nonnull_arg_ctx
+{
+ /* Location of the call. */
+ location_t loc;
+ /* The function whose arguments are being checked and its type (used
+ for calls through function pointers). */
+ const_tree fndecl, fntype;
+ /* True if a warning has been issued. */
+ bool warned_p;
+};
+
+/* Check the argument list of a function call to CTX.FNDECL of CTX.FNTYPE
+ for null in argument slots that are marked as requiring a non-null
+ pointer argument. The NARGS arguments are passed in the array ARGARRAY.
+ Return true if we have warned. */
+
+static bool
+check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray)
+{
+ int firstarg = 0;
+ if (TREE_CODE (ctx.fntype) == METHOD_TYPE)
+ {
+ bool closure = false;
+ if (ctx.fndecl)
+ {
+ /* For certain lambda expressions the C++ front end emits calls
+ that pass a null this pointer as an argument named __closure
+ to the member operator() of empty function. Detect those
+ and avoid checking them, but proceed to check the remaining
+ arguments. */
+ tree arg0 = DECL_ARGUMENTS (ctx.fndecl);
+ if (tree arg0name = DECL_NAME (arg0))
+ closure = id_equal (arg0name, "__closure");
+ }
+
+ /* In calls to C++ non-static member functions check the this
+ pointer regardless of whether the function is declared with
+ attribute nonnull. */
+ firstarg = 1;
+ if (!closure)
+ check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[0],
+ firstarg, OPT_Wnonnull);
+ }
+
+ tree attrs = lookup_attribute ("nonnull", TYPE_ATTRIBUTES (ctx.fntype));
+ if (attrs == NULL_TREE)
+ return ctx.warned_p;
+
+ tree a = attrs;
+ /* See if any of the nonnull attributes has no arguments. If so,
+ then every pointer argument is checked (in which case the check
+ for pointer type is done in check_nonnull_arg). */
+ if (TREE_VALUE (a) != NULL_TREE)
+ do
+ a = lookup_attribute ("nonnull", TREE_CHAIN (a));
+ while (a != NULL_TREE && TREE_VALUE (a) != NULL_TREE);
+
+ if (a != NULL_TREE)
+ for (int i = firstarg; i < nargs; i++)
+ check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i],
+ i + 1, OPT_Wnonnull);
+ else
+ {
+ /* Walk the argument list. If we encounter an argument number we
+ should check for non-null, do it. */
+ for (int i = firstarg; i < nargs; i++)
+ {
+ for (a = attrs; ; a = TREE_CHAIN (a))
+ {
+ a = lookup_attribute ("nonnull", a);
+ if (a == NULL_TREE || nonnull_check_p (TREE_VALUE (a), i + 1))
+ break;
+ }
+
+ if (a != NULL_TREE)
+ check_function_arguments_recurse (check_nonnull_arg, &ctx,
+ argarray[i], i + 1,
+ OPT_Wnonnull);
+ }
+ }
+ return ctx.warned_p;
+}
+
+/* Check that the Nth argument of a function call (counting backwards
+ from the end) is a (pointer)0. The NARGS arguments are passed in the
+ array ARGARRAY. */
+
+static void
+check_function_sentinel (const_tree fntype, int nargs, tree *argarray)
+{
+ tree attr = lookup_attribute ("sentinel", TYPE_ATTRIBUTES (fntype));
+
+ if (attr)
+ {
+ int len = 0;
+ int pos = 0;
+ tree sentinel;
+ function_args_iterator iter;
+ tree t;
+
+ /* Skip over the named arguments. */
+ FOREACH_FUNCTION_ARGS (fntype, t, iter)
+ {
+ if (len == nargs)
+ break;
+ len++;
+ }
+
+ if (TREE_VALUE (attr))
+ {
+ tree p = TREE_VALUE (TREE_VALUE (attr));
+ pos = TREE_INT_CST_LOW (p);
+ }
+
+ /* The sentinel must be one of the varargs, i.e.
+ in position >= the number of fixed arguments. */
+ if ((nargs - 1 - pos) < len)
+ {
+ warning (OPT_Wformat_,
+ "not enough variable arguments to fit a sentinel");
+ return;
+ }
+
+ /* Validate the sentinel. */
+ sentinel = fold_for_warn (argarray[nargs - 1 - pos]);
+ if ((!POINTER_TYPE_P (TREE_TYPE (sentinel))
+ || !integer_zerop (sentinel))
+ /* Although __null (in C++) is only an integer we allow it
+ nevertheless, as we are guaranteed that it's exactly
+ as wide as a pointer, and we don't want to force
+ users to cast the NULL they have written there.
+ We warn with -Wstrict-null-sentinel, though. */
+ && (warn_strict_null_sentinel || null_node != sentinel))
+ warning (OPT_Wformat_, "missing sentinel in function call");
+ }
+}
+
+/* Check that the same argument isn't passed to two or more
+ restrict-qualified formal and issue a -Wrestrict warning
+ if it is. Return true if a warning has been issued. */
+
+static bool
+check_function_restrict (const_tree fndecl, const_tree fntype,
+ int nargs, tree *unfolded_argarray)
+{
+ int i;
+ tree parms = TYPE_ARG_TYPES (fntype);
+
+ /* Call fold_for_warn on all of the arguments. */
+ auto_vec<tree> argarray (nargs);
+ for (i = 0; i < nargs; i++)
+ argarray.quick_push (fold_for_warn (unfolded_argarray[i]));
+
+ if (fndecl
+ && TREE_CODE (fndecl) == FUNCTION_DECL)
+ {
+ /* Avoid diagnosing calls built-ins with a zero size/bound
+ here. They are checked in more detail elsewhere. */
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
+ && nargs == 3
+ && TREE_CODE (argarray[2]) == INTEGER_CST
+ && integer_zerop (argarray[2]))
+ return false;
+
+ if (DECL_ARGUMENTS (fndecl))
+ parms = DECL_ARGUMENTS (fndecl);
+ }
+
+ for (i = 0; i < nargs; i++)
+ TREE_VISITED (argarray[i]) = 0;
+
+ bool warned = false;
+
+ for (i = 0; i < nargs && parms && parms != void_list_node; i++)
+ {
+ tree type;
+ if (TREE_CODE (parms) == PARM_DECL)
+ {
+ type = TREE_TYPE (parms);
+ parms = DECL_CHAIN (parms);
+ }
+ else
+ {
+ type = TREE_VALUE (parms);
+ parms = TREE_CHAIN (parms);
+ }
+ if (POINTER_TYPE_P (type)
+ && TYPE_RESTRICT (type)
+ && !TYPE_READONLY (TREE_TYPE (type)))
+ warned |= warn_for_restrict (i, argarray.address (), nargs);
+ }
+
+ for (i = 0; i < nargs; i++)
+ TREE_VISITED (argarray[i]) = 0;
+
+ return warned;
+}
+
+/* Helper for check_function_nonnull; given a list of operands which
+ must be non-null in ARGS, determine if operand PARAM_NUM should be
+ checked. */
+
+static bool
+nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
+{
+ unsigned HOST_WIDE_INT arg_num = 0;
+
+ for (; args; args = TREE_CHAIN (args))
+ {
+ bool found = get_attribute_operand (TREE_VALUE (args), &arg_num);
+
+ gcc_assert (found);
+
+ if (arg_num == param_num)
+ return true;
+ }
+ return false;
+}
+
+/* Check that the function argument PARAM (which is operand number
+ PARAM_NUM) is non-null. This is called by check_function_nonnull
+ via check_function_arguments_recurse. */
+
+static void
+check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num)
+{
+ struct nonnull_arg_ctx *pctx = (struct nonnull_arg_ctx *) ctx;
+
+ /* Just skip checking the argument if it's not a pointer. This can
+ happen if the "nonnull" attribute was given without an operand
+ list (which means to check every pointer argument). */
+
+ tree paramtype = TREE_TYPE (param);
+ if (TREE_CODE (paramtype) != POINTER_TYPE
+ && TREE_CODE (paramtype) != NULLPTR_TYPE)
+ return;
+
+ /* Diagnose the simple cases of null arguments. */
+ if (!integer_zerop (fold_for_warn (param)))
+ return;
+
+ auto_diagnostic_group adg;
+
+ const location_t loc = EXPR_LOC_OR_LOC (param, pctx->loc);
+
+ if (TREE_CODE (pctx->fntype) == METHOD_TYPE)
+ --param_num;
+
+ bool warned;
+ if (param_num == 0)
+ {
+ warned = warning_at (loc, OPT_Wnonnull,
+ "%qs pointer is null", "this");
+ if (warned && pctx->fndecl)
+ inform (DECL_SOURCE_LOCATION (pctx->fndecl),
+ "in a call to non-static member function %qD",
+ pctx->fndecl);
+ }
+ else
+ {
+ warned = warning_at (loc, OPT_Wnonnull,
+ "argument %u null where non-null expected",
+ (unsigned) param_num);
+ if (warned && pctx->fndecl)
+ inform (DECL_SOURCE_LOCATION (pctx->fndecl),
+ "in a call to function %qD declared %qs",
+ pctx->fndecl, "nonnull");
+ }
+
+ if (warned)
+ pctx->warned_p = true;
+}
+
+/* Helper for attribute handling; fetch the operand number from
+ the attribute argument list. */
+
+bool
+get_attribute_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
+{
+ /* Verify the arg number is a small constant. */
+ if (tree_fits_uhwi_p (arg_num_expr))
+ {
+ *valp = tree_to_uhwi (arg_num_expr);
+ return true;
+ }
+ else
+ return false;
+}
+
+/* Arguments being collected for optimization. */
+typedef const char *const_char_p; /* For DEF_VEC_P. */
+static GTY(()) vec<const_char_p, va_gc> *optimize_args;
+
+
+/* Inner function to convert a TREE_LIST to argv string to parse the optimize
+ options in ARGS. ATTR_P is true if this is for attribute(optimize), and
+ false for #pragma GCC optimize. */
+
+bool
+parse_optimize_options (tree args, bool attr_p)
+{
+ (void) args;
+ (void) attr_p;
+ (void) optimize_args;
+ gcc_assert(0 && "opt");
+ return false;
+#if 0
+ bool ret = true;
+ unsigned opt_argc;
+ unsigned i;
+ const char **opt_argv;
+ struct cl_decoded_option *decoded_options;
+ unsigned int decoded_options_count;
+ tree ap;
+
+ /* Build up argv vector. Just in case the string is stored away, use garbage
+ collected strings. */
+ vec_safe_truncate (optimize_args, 0);
+ vec_safe_push (optimize_args, (const char *) NULL);
+
+ for (ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
+ {
+ tree value = TREE_VALUE (ap);
+
+ if (TREE_CODE (value) == INTEGER_CST)
+ {
+ char buffer[HOST_BITS_PER_LONG / 3 + 4];
+ sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
+ vec_safe_push (optimize_args, ggc_strdup (buffer));
+ }
+
+ else if (TREE_CODE (value) == STRING_CST)
+ {
+ /* Split string into multiple substrings. */
+ size_t len = TREE_STRING_LENGTH (value);
+ char *p = ASTRDUP (TREE_STRING_POINTER (value));
+ char *end = p + len;
+ char *comma;
+ char *next_p = p;
+
+ while (next_p != NULL)
+ {
+ size_t len2;
+ char *q, *r;
+
+ p = next_p;
+ comma = strchr (p, ',');
+ if (comma)
+ {
+ len2 = comma - p;
+ *comma = '\0';
+ next_p = comma+1;
+ }
+ else
+ {
+ len2 = end - p;
+ next_p = NULL;
+ }
+
+ /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
+ options. */
+ if (*p == '-' && p[1] != 'O' && p[1] != 'f')
+ {
+ ret = false;
+ if (attr_p)
+ warning (OPT_Wattributes,
+ "bad option %qs to attribute %<optimize%>", p);
+ else
+ warning (OPT_Wpragmas,
+ "bad option %qs to pragma %<optimize%>", p);
+ continue;
+ }
+
+ /* Can't use GC memory here, see PR88007. */
+ r = q = XOBNEWVEC (&opts_obstack, char, len2 + 3);
+
+ if (*p != '-')
+ {
+ *r++ = '-';
+
+ /* Assume that Ox is -Ox, a numeric value is -Ox, a s by
+ itself is -Os, and any other switch begins with a -f. */
+ if ((*p >= '0' && *p <= '9')
+ || (p[0] == 's' && p[1] == '\0'))
+ *r++ = 'O';
+ else if (*p != 'O')
+ *r++ = 'f';
+ }
+
+ memcpy (r, p, len2);
+ r[len2] = '\0';
+ vec_safe_push (optimize_args, (const char *) q);
+ }
+
+ }
+ }
+
+ opt_argc = optimize_args->length ();
+ opt_argv = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
+
+ for (i = 1; i < opt_argc; i++)
+ opt_argv[i] = (*optimize_args)[i];
+
+ /* Now parse the options. */
+ decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
+ &decoded_options,
+ &decoded_options_count);
+ /* Drop non-Optimization options. */
+ unsigned j = 1;
+ for (i = 1; i < decoded_options_count; ++i)
+ {
+ if (! (cl_options[decoded_options[i].opt_index].flags & CL_OPTIMIZATION))
+ {
+ ret = false;
+ if (attr_p)
+ warning (OPT_Wattributes,
+ "bad option %qs to attribute %<optimize%>",
+ decoded_options[i].orig_option_with_args_text);
+ else
+ warning (OPT_Wpragmas,
+ "bad option %qs to pragma %<optimize%>",
+ decoded_options[i].orig_option_with_args_text);
+ continue;
+ }
+ if (i != j)
+ decoded_options[j] = decoded_options[i];
+ j++;
+ }
+ decoded_options_count = j;
+
+ /* Merge the decoded options with save_decoded_options. */
+ unsigned save_opt_count = save_opt_decoded_options->length ();
+ unsigned merged_decoded_options_count
+ = save_opt_count + decoded_options_count;
+ cl_decoded_option *merged_decoded_options
+ = XNEWVEC (cl_decoded_option, merged_decoded_options_count);
+
+ /* Note the first decoded_options is used for the program name. */
+ for (unsigned i = 0; i < save_opt_count; ++i)
+ merged_decoded_options[i + 1] = (*save_opt_decoded_options)[i];
+ for (unsigned i = 1; i < decoded_options_count; ++i)
+ merged_decoded_options[save_opt_count + i] = decoded_options[i];
+
+ /* And apply them. */
+ decode_options (&global_options, &global_options_set,
+ merged_decoded_options, merged_decoded_options_count,
+ input_location, global_dc, NULL);
+ free (decoded_options);
+
+ targetm.override_options_after_change();
+
+ optimize_args->truncate (0);
+ return ret;
+#endif
+}
+
+/* Check whether ATTR is a valid attribute fallthrough. */
+
+bool
+attribute_fallthrough_p (tree attr)
+{
+ if (attr == error_mark_node)
+ return false;
+ tree t = lookup_attribute ("fallthrough", attr);
+ if (t == NULL_TREE)
+ return false;
+ /* It is no longer true that "this attribute shall appear at most once in
+ each attribute-list", but we still give a warning. */
+ if (lookup_attribute ("fallthrough", TREE_CHAIN (t)))
+ warning (OPT_Wattributes, "attribute %<fallthrough%> specified multiple "
+ "times");
+ /* No attribute-argument-clause shall be present. */
+ else if (TREE_VALUE (t) != NULL_TREE)
+ warning (OPT_Wattributes, "%<fallthrough%> attribute specified with "
+ "a parameter");
+ /* Warn if other attributes are found. */
+ for (t = attr; t != NULL_TREE; t = TREE_CHAIN (t))
+ {
+ tree name = get_attribute_name (t);
+ if (!is_attribute_p ("fallthrough", name))
+ {
+ if (!c_dialect_cxx () && get_attribute_namespace (t) == NULL_TREE)
+ /* The specifications of standard attributes in C mean
+ this is a constraint violation. */
+ pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
+ get_attribute_name (t));
+ else
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ }
+ }
+ return true;
+}
+
+
+/* Check for valid arguments being passed to a function with FNTYPE.
+ There are NARGS arguments in the array ARGARRAY. LOC should be used
+ for diagnostics. Return true if either -Wnonnull or -Wrestrict has
+ been issued.
+
+ The arguments in ARGARRAY may not have been folded yet (e.g. for C++,
+ to preserve location wrappers); checks that require folded arguments
+ should call fold_for_warn on them. */
+
+bool
+check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
+ int nargs, tree *argarray, vec<location_t> *arglocs)
+{
+ bool warned_p = false;
+
+ /* Check for null being passed in a pointer argument that must be
+ non-null. In C++, this includes the this pointer. We also need
+ to do this if format checking is enabled. */
+ if (warn_nonnull)
+ {
+ nonnull_arg_ctx ctx = { loc, fndecl, fntype, false };
+ warned_p = check_function_nonnull (ctx, nargs, argarray);
+ }
+
+ /* Check for errors in format strings. */
+
+ if (warn_format || warn_suggest_attribute_format)
+ check_function_format (fntype, TYPE_ATTRIBUTES (fntype), nargs, argarray,
+ arglocs);
+
+ if (warn_format)
+ check_function_sentinel (fntype, nargs, argarray);
+
+ if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_SPRINTF:
+ case BUILT_IN_SPRINTF_CHK:
+ case BUILT_IN_SNPRINTF:
+ case BUILT_IN_SNPRINTF_CHK:
+ /* Let the sprintf pass handle these. */
+ return warned_p;
+
+ default:
+ break;
+ }
+ }
+
+ /* check_function_restrict sets the DECL_READ_P for arguments
+ so it must be called unconditionally. */
+ warned_p |= check_function_restrict (fndecl, fntype, nargs, argarray);
+
+ return warned_p;
+}
+
+/* Generic argument checking recursion routine. PARAM is the argument to
+ be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked
+ once the argument is resolved. CTX is context for the callback.
+ OPT is the warning for which this is done. */
+void
+check_function_arguments_recurse (void (*callback)
+ (void *, tree, unsigned HOST_WIDE_INT),
+ void *ctx, tree param,
+ unsigned HOST_WIDE_INT param_num,
+ opt_code opt)
+{
+ if (opt != OPT_Wformat_ && warning_suppressed_p (param))
+ return;
+
+ if (CONVERT_EXPR_P (param)
+ && (TYPE_PRECISION (TREE_TYPE (param))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0)))))
+ {
+ /* Strip coercion. */
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 0), param_num,
+ opt);
+ return;
+ }
+
+ if (TREE_CODE (param) == CALL_EXPR && CALL_EXPR_FN (param))
+ {
+ tree type = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (param)));
+ tree attrs;
+ bool found_format_arg = false;
+
+ /* See if this is a call to a known internationalization function
+ that modifies a format arg. Such a function may have multiple
+ format_arg attributes (for example, ngettext). */
+
+ for (attrs = TYPE_ATTRIBUTES (type);
+ attrs;
+ attrs = TREE_CHAIN (attrs))
+ if (is_attribute_p ("format_arg", get_attribute_name (attrs)))
+ {
+ tree inner_arg;
+ tree format_num_expr;
+ int format_num;
+ int i;
+ call_expr_arg_iterator iter;
+
+ /* Extract the argument number, which was previously checked
+ to be valid. */
+ format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
+
+ format_num = tree_to_uhwi (format_num_expr);
+
+ for (inner_arg = first_call_expr_arg (param, &iter), i = 1;
+ inner_arg != NULL_TREE;
+ inner_arg = next_call_expr_arg (&iter), i++)
+ if (i == format_num)
+ {
+ check_function_arguments_recurse (callback, ctx,
+ inner_arg, param_num,
+ opt);
+ found_format_arg = true;
+ break;
+ }
+ }
+
+ /* If we found a format_arg attribute and did a recursive check,
+ we are done with checking this argument. Otherwise, we continue
+ and this will be considered a non-literal. */
+ if (found_format_arg)
+ return;
+ }
+
+ if (TREE_CODE (param) == COND_EXPR)
+ {
+ /* Simplify to avoid warning for an impossible case. */
+ param = fold_for_warn (param);
+ if (TREE_CODE (param) == COND_EXPR)
+ {
+ /* Check both halves of the conditional expression. */
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 1),
+ param_num, opt);
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 2),
+ param_num, opt);
+ return;
+ }
+ }
+
+ (*callback) (ctx, param, param_num);
+}
+
+/* Checks for a builtin function FNDECL that the number of arguments
+ NARGS against the required number REQUIRED and issues an error if
+ there is a mismatch. Returns true if the number of arguments is
+ correct, otherwise false. LOC is the location of FNDECL. */
+
+static bool
+builtin_function_validate_nargs (location_t loc, tree fndecl, int nargs,
+ int required)
+{
+ if (nargs < required)
+ {
+ error_at (loc, "too few arguments to function %qE", fndecl);
+ return false;
+ }
+ else if (nargs > required)
+ {
+ error_at (loc, "too many arguments to function %qE", fndecl);
+ return false;
+ }
+ return true;
+}
+
+/* Helper macro for check_builtin_function_arguments. */
+#define ARG_LOCATION(N) \
+ (arg_loc.is_empty () \
+ ? EXPR_LOC_OR_LOC (args[(N)], input_location) \
+ : expansion_point_location (arg_loc[(N)]))
+
+/* Verifies the NARGS arguments ARGS to the builtin function FNDECL.
+ Returns false if there was an error, otherwise true. LOC is the
+ location of the function; ARG_LOC is a vector of locations of the
+ arguments. If FNDECL is the result of resolving an overloaded
+ target built-in, ORIG_FNDECL is the original function decl,
+ otherwise it is null. */
+
+bool
+check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
+ tree fndecl, tree orig_fndecl,
+ int nargs, tree *args)
+{
+ if (!fndecl_built_in_p (fndecl))
+ return true;
+
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+ return (!targetm.check_builtin_call
+ || targetm.check_builtin_call (loc, arg_loc, fndecl,
+ orig_fndecl, nargs, args));
+
+ if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND)
+ return true;
+
+ gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL);
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
+ if (!tree_fits_uhwi_p (args[2]))
+ {
+ error_at (ARG_LOCATION (2),
+ "third argument to function %qE must be a constant integer",
+ fndecl);
+ return false;
+ }
+ /* fall through */
+
+ case BUILT_IN_ALLOCA_WITH_ALIGN:
+ {
+ /* Get the requested alignment (in bits) if it's a constant
+ integer expression. */
+ unsigned HOST_WIDE_INT align
+ = tree_fits_uhwi_p (args[1]) ? tree_to_uhwi (args[1]) : 0;
+
+ /* Determine if the requested alignment is a power of 2. */
+ if ((align & (align - 1)))
+ align = 0;
+
+ /* The maximum alignment in bits corresponding to the same
+ maximum in bytes enforced in check_user_alignment(). */
+ unsigned maxalign = (UINT_MAX >> 1) + 1;
+
+ /* Reject invalid alignments. */
+ if (align < BITS_PER_UNIT || maxalign < align)
+ {
+ error_at (ARG_LOCATION (1),
+ "second argument to function %qE must be a constant "
+ "integer power of 2 between %qi and %qu bits",
+ fndecl, BITS_PER_UNIT, maxalign);
+ return false;
+ }
+ return true;
+ }
+
+ case BUILT_IN_CONSTANT_P:
+ return builtin_function_validate_nargs (loc, fndecl, nargs, 1);
+
+ case BUILT_IN_ISFINITE:
+ case BUILT_IN_ISINF:
+ case BUILT_IN_ISINF_SIGN:
+ case BUILT_IN_ISNAN:
+ case BUILT_IN_ISNORMAL:
+ case BUILT_IN_SIGNBIT:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 1))
+ {
+ if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE)
+ {
+ error_at (ARG_LOCATION (0), "non-floating-point argument in "
+ "call to function %qE", fndecl);
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ case BUILT_IN_ISGREATER:
+ case BUILT_IN_ISGREATEREQUAL:
+ case BUILT_IN_ISLESS:
+ case BUILT_IN_ISLESSEQUAL:
+ case BUILT_IN_ISLESSGREATER:
+ case BUILT_IN_ISUNORDERED:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 2))
+ {
+ enum tree_code code0, code1;
+ code0 = TREE_CODE (TREE_TYPE (args[0]));
+ code1 = TREE_CODE (TREE_TYPE (args[1]));
+ if (!((code0 == REAL_TYPE && code1 == REAL_TYPE)
+ || (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
+ || (code0 == INTEGER_TYPE && code1 == REAL_TYPE)))
+ {
+ error_at (loc, "non-floating-point arguments in call to "
+ "function %qE", fndecl);
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ case BUILT_IN_FPCLASSIFY:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 6))
+ {
+ for (unsigned int i = 0; i < 5; i++)
+ if (TREE_CODE (args[i]) != INTEGER_CST)
+ {
+ error_at (ARG_LOCATION (i), "non-const integer argument %u in "
+ "call to function %qE", i + 1, fndecl);
+ return false;
+ }
+
+ if (TREE_CODE (TREE_TYPE (args[5])) != REAL_TYPE)
+ {
+ error_at (ARG_LOCATION (5), "non-floating-point argument in "
+ "call to function %qE", fndecl);
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ case BUILT_IN_ASSUME_ALIGNED:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 2 + (nargs > 2)))
+ {
+ if (nargs >= 3 && TREE_CODE (TREE_TYPE (args[2])) != INTEGER_TYPE)
+ {
+ error_at (ARG_LOCATION (2), "non-integer argument 3 in call to "
+ "function %qE", fndecl);
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ case BUILT_IN_ADD_OVERFLOW:
+ case BUILT_IN_SUB_OVERFLOW:
+ case BUILT_IN_MUL_OVERFLOW:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 3))
+ {
+ unsigned i;
+ for (i = 0; i < 2; i++)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (args[i])))
+ {
+ error_at (ARG_LOCATION (i), "argument %u in call to function "
+ "%qE does not have integral type", i + 1, fndecl);
+ return false;
+ }
+ if (TREE_CODE (TREE_TYPE (args[2])) != POINTER_TYPE
+ || !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (args[2]))))
+ {
+ error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
+ "does not have pointer to integral type", fndecl);
+ return false;
+ }
+ else if (TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) == ENUMERAL_TYPE)
+ {
+ error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
+ "has pointer to enumerated type", fndecl);
+ return false;
+ }
+ else if (TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) == BOOLEAN_TYPE)
+ {
+ error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
+ "has pointer to boolean type", fndecl);
+ return false;
+ }
+ else if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (args[2]))))
+ {
+ error_at (ARG_LOCATION (2), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 3, fndecl, "const",
+ TREE_TYPE (args[2]));
+ return false;
+ }
+ else if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (args[2]))))
+ {
+ error_at (ARG_LOCATION (2), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 3, fndecl,
+ "_Atomic", TREE_TYPE (args[2]));
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ case BUILT_IN_ADD_OVERFLOW_P:
+ case BUILT_IN_SUB_OVERFLOW_P:
+ case BUILT_IN_MUL_OVERFLOW_P:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 3))
+ {
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (args[i])))
+ {
+ error_at (ARG_LOCATION (i), "argument %u in call to function "
+ "%qE does not have integral type", i + 1, fndecl);
+ return false;
+ }
+ if (TREE_CODE (TREE_TYPE (args[2])) == ENUMERAL_TYPE)
+ {
+ error_at (ARG_LOCATION (2), "argument 3 in call to function "
+ "%qE has enumerated type", fndecl);
+ return false;
+ }
+ else if (TREE_CODE (TREE_TYPE (args[2])) == BOOLEAN_TYPE)
+ {
+ error_at (ARG_LOCATION (2), "argument 3 in call to function "
+ "%qE has boolean type", fndecl);
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ case BUILT_IN_CLEAR_PADDING:
+ if (builtin_function_validate_nargs (loc, fndecl, nargs, 1))
+ {
+ if (!POINTER_TYPE_P (TREE_TYPE (args[0])))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function "
+ "%qE does not have pointer type", 1, fndecl);
+ return false;
+ }
+ else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (args[0]))))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function "
+ "%qE points to incomplete type", 1, fndecl);
+ return false;
+ }
+ else if (TYPE_READONLY (TREE_TYPE (TREE_TYPE (args[0]))))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 1, fndecl, "const",
+ TREE_TYPE (args[0]));
+ return false;
+ }
+ else if (TYPE_ATOMIC (TREE_TYPE (TREE_TYPE (args[0]))))
+ {
+ error_at (ARG_LOCATION (0), "argument %u in call to function %qE "
+ "has pointer to %qs type (%qT)", 1, fndecl,
+ "_Atomic", TREE_TYPE (args[0]));
+ return false;
+ }
+ return true;
+ }
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+/* Subroutine of c_parse_error.
+ Return the result of concatenating LHS and RHS. RHS is really
+ a string literal, its first character is indicated by RHS_START and
+ RHS_SIZE is its length (including the terminating NUL character).
+
+ The caller is responsible for deleting the returned pointer. */
+
+static char *
+catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
+{
+ const size_t lhs_size = strlen (lhs);
+ char *result = XNEWVEC (char, lhs_size + rhs_size);
+ memcpy (result, lhs, lhs_size);
+ memcpy (result + lhs_size, rhs_start, rhs_size);
+ return result;
+}
+
+/* Issue the error given by GMSGID at RICHLOC, indicating that it occurred
+ before TOKEN, which had the associated VALUE. */
+
+void
+c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
+ tree value, unsigned char token_flags,
+ rich_location *richloc)
+{
+#define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
+
+ char *message = NULL;
+
+ if (token_type == CPP_EOF)
+ message = catenate_messages (gmsgid, " at end of input");
+ else if (token_type == CPP_CHAR
+ || token_type == CPP_WCHAR
+ || token_type == CPP_CHAR16
+ || token_type == CPP_CHAR32
+ || token_type == CPP_UTF8CHAR)
+ {
+ unsigned int val = TREE_INT_CST_LOW (value);
+ const char *prefix;
+
+ switch (token_type)
+ {
+ default:
+ prefix = "";
+ break;
+ case CPP_WCHAR:
+ prefix = "L";
+ break;
+ case CPP_CHAR16:
+ prefix = "u";
+ break;
+ case CPP_CHAR32:
+ prefix = "U";
+ break;
+ case CPP_UTF8CHAR:
+ prefix = "u8";
+ break;
+ }
+
+ if (val <= UCHAR_MAX && ISGRAPH (val))
+ message = catenate_messages (gmsgid, " before %s'%c'");
+ else
+ message = catenate_messages (gmsgid, " before %s'\\x%x'");
+
+ error_at (richloc, message, prefix, val);
+ free (message);
+ message = NULL;
+ }
+ else if (token_type == CPP_CHAR_USERDEF
+ || token_type == CPP_WCHAR_USERDEF
+ || token_type == CPP_CHAR16_USERDEF
+ || token_type == CPP_CHAR32_USERDEF
+ || token_type == CPP_UTF8CHAR_USERDEF)
+ message = catenate_messages (gmsgid,
+ " before user-defined character literal");
+ else if (token_type == CPP_STRING_USERDEF
+ || token_type == CPP_WSTRING_USERDEF
+ || token_type == CPP_STRING16_USERDEF
+ || token_type == CPP_STRING32_USERDEF
+ || token_type == CPP_UTF8STRING_USERDEF)
+ message = catenate_messages (gmsgid, " before user-defined string literal");
+ else if (token_type == CPP_STRING
+ || token_type == CPP_WSTRING
+ || token_type == CPP_STRING16
+ || token_type == CPP_STRING32
+ || token_type == CPP_UTF8STRING)
+ message = catenate_messages (gmsgid, " before string constant");
+ else if (token_type == CPP_NUMBER)
+ message = catenate_messages (gmsgid, " before numeric constant");
+ else if (token_type == CPP_NAME)
+ {
+ message = catenate_messages (gmsgid, " before %qE");
+ error_at (richloc, message, value);
+ free (message);
+ message = NULL;
+ }
+ else if (token_type == CPP_PRAGMA)
+ message = catenate_messages (gmsgid, " before %<#pragma%>");
+ else if (token_type == CPP_PRAGMA_EOL)
+ message = catenate_messages (gmsgid, " before end of line");
+ else if (token_type == CPP_DECLTYPE)
+ message = catenate_messages (gmsgid, " before %<decltype%>");
+ else if (token_type < N_TTYPES)
+ {
+ message = catenate_messages (gmsgid, " before %qs token");
+ error_at (richloc, message, cpp_type2name (token_type, token_flags));
+ free (message);
+ message = NULL;
+ }
+ else
+ error_at (richloc, gmsgid);
+
+ if (message)
+ {
+ error_at (richloc, message);
+ free (message);
+ }
+#undef catenate_messages
+}
+
+/* Return the gcc option code associated with the reason for a cpp
+ message, or 0 if none. */
+
+#endif // sdcpp
+static int
+c_option_controlling_cpp_diagnostic (enum cpp_warning_reason reason)
+{
+#if 1 // sdcpp
+ (void) reason;
+#else
+ const struct cpp_reason_option_codes_t *entry;
+
+ for (entry = cpp_reason_option_codes; entry->reason != CPP_W_NONE; entry++)
+ {
+ if (entry->reason == reason)
+ return entry->option_code;
+ }
+#endif // sdcpp
+ return 0;
+}
+#if 0 // sdcpp
+
+/* Callback from cpp_diagnostic for PFILE to print diagnostics from the
+ preprocessor. The diagnostic is of type LEVEL, with REASON set
+ to the reason code if LEVEL is represents a warning, at location
+ RICHLOC unless this is after lexing and the compiler's location
+ should be used instead; MSG is the translated message and AP
+ the arguments. Returns true if a diagnostic was emitted, false
+ otherwise. */
+
+#endif // sdcpp
+bool
+c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
+ enum cpp_diagnostic_level level,
+ enum cpp_warning_reason reason,
+ rich_location *richloc,
+ const char *msg, va_list *ap)
+{
+ diagnostic_info diagnostic;
+ diagnostic_t dlevel;
+ bool save_warn_system_headers = global_dc->dc_warn_system_headers;
+ bool ret;
+
+ switch (level)
+ {
+ case CPP_DL_WARNING_SYSHDR:
+ if (flag_no_output)
+ return false;
+ global_dc->dc_warn_system_headers = 1;
+ /* Fall through. */
+ case CPP_DL_WARNING:
+ if (flag_no_output)
+ return false;
+ dlevel = DK_WARNING;
+ break;
+ case CPP_DL_PEDWARN:
+ if (flag_no_output && !flag_pedantic_errors)
+ return false;
+ dlevel = DK_PEDWARN;
+ break;
+ case CPP_DL_ERROR:
+ dlevel = DK_ERROR;
+ break;
+ case CPP_DL_ICE:
+ dlevel = DK_ICE;
+ break;
+ case CPP_DL_NOTE:
+ dlevel = DK_NOTE;
+ break;
+ case CPP_DL_FATAL:
+ dlevel = DK_FATAL;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (done_lexing)
+ richloc->set_range (0, input_location, SHOW_RANGE_WITH_CARET);
+ diagnostic_set_info_translated (&diagnostic, msg, ap,
+ richloc, dlevel);
+ diagnostic_override_option_index
+ (&diagnostic,
+ c_option_controlling_cpp_diagnostic (reason));
+ ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
+ if (level == CPP_DL_WARNING_SYSHDR)
+ global_dc->dc_warn_system_headers = save_warn_system_headers;
+ return ret;
+}
+
+/* Convert a character from the host to the target execution character
+ set. cpplib handles this, mostly. */
+
+HOST_WIDE_INT
+c_common_to_target_charset (HOST_WIDE_INT c)
+{
+ /* Character constants in GCC proper are sign-extended under -fsigned-char,
+ zero-extended under -fno-signed-char. cpplib insists that characters
+ and character constants are always unsigned. Hence we must convert
+ back and forth. */
+ cppchar_t uc = ((cppchar_t)c) & ((((cppchar_t)1) << CHAR_BIT)-1);
+
+ uc = cpp_host_to_exec_charset (parse_in, uc);
+
+ if (flag_signed_char)
+ return ((HOST_WIDE_INT)uc) << (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE)
+ >> (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE);
+ else
+ return uc;
+}
+
+#if 0 // sdcpp
+/* Fold an offsetof-like expression. EXPR is a nested sequence of component
+ references with an INDIRECT_REF of a constant at the bottom; much like the
+ traditional rendering of offsetof as a macro. TYPE is the desired type of
+ the whole expression. Return the folded result. */
+
+tree
+fold_offsetof (tree expr, tree type, enum tree_code ctx)
+{
+ tree base, off, t;
+ tree_code code = TREE_CODE (expr);
+ switch (code)
+ {
+ case ERROR_MARK:
+ return expr;
+
+ case VAR_DECL:
+ error ("cannot apply %<offsetof%> to static data member %qD", expr);
+ return error_mark_node;
+
+ case CALL_EXPR:
+ case TARGET_EXPR:
+ error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+ return error_mark_node;
+
+ case NOP_EXPR:
+ case INDIRECT_REF:
+ if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
+ {
+ error ("cannot apply %<offsetof%> to a non constant address");
+ return error_mark_node;
+ }
+ return convert (type, TREE_OPERAND (expr, 0));
+
+ case COMPONENT_REF:
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ if (DECL_C_BIT_FIELD (t))
+ {
+ error ("attempt to take address of bit-field structure "
+ "member %qD", t);
+ return error_mark_node;
+ }
+ off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
+ size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
+ / BITS_PER_UNIT));
+ break;
+
+ case ARRAY_REF:
+ base = fold_offsetof (TREE_OPERAND (expr, 0), type, code);
+ if (base == error_mark_node)
+ return base;
+
+ t = TREE_OPERAND (expr, 1);
+ STRIP_ANY_LOCATION_WRAPPER (t);
+
+ /* Check if the offset goes beyond the upper bound of the array. */
+ if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
+ {
+ tree upbound = array_ref_up_bound (expr);
+ if (upbound != NULL_TREE
+ && TREE_CODE (upbound) == INTEGER_CST
+ && !tree_int_cst_equal (upbound,
+ TYPE_MAX_VALUE (TREE_TYPE (upbound))))
+ {
+ if (ctx != ARRAY_REF && ctx != COMPONENT_REF)
+ upbound = size_binop (PLUS_EXPR, upbound,
+ build_int_cst (TREE_TYPE (upbound), 1));
+ if (tree_int_cst_lt (upbound, t))
+ {
+ tree v;
+
+ for (v = TREE_OPERAND (expr, 0);
+ TREE_CODE (v) == COMPONENT_REF;
+ v = TREE_OPERAND (v, 0))
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+ {
+ tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
+ for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
+ if (TREE_CODE (fld_chain) == FIELD_DECL)
+ break;
+
+ if (fld_chain)
+ break;
+ }
+ /* Don't warn if the array might be considered a poor
+ man's flexible array member with a very permissive
+ definition thereof. */
+ if (TREE_CODE (v) == ARRAY_REF
+ || TREE_CODE (v) == COMPONENT_REF)
+ warning (OPT_Warray_bounds,
+ "index %E denotes an offset "
+ "greater than size of %qT",
+ t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ }
+ }
+
+ t = convert (sizetype, t);
+ off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+ break;
+
+ case COMPOUND_EXPR:
+ /* Handle static members of volatile structs. */
+ t = TREE_OPERAND (expr, 1);
+ gcc_checking_assert (VAR_P (get_base_address (t)));
+ return fold_offsetof (t, type);
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!POINTER_TYPE_P (type))
+ return size_binop (PLUS_EXPR, base, convert (type, off));
+ return fold_build_pointer_plus (base, off);
+}
+
+/* *PTYPE is an incomplete array. Complete it with a domain based on
+ INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
+ is true. Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
+ 2 if INITIAL_VALUE was NULL, and 3 if INITIAL_VALUE was empty. */
+
+int
+complete_array_type (tree *ptype, tree initial_value, bool do_default)
+{
+ tree maxindex, type, main_type, elt, unqual_elt;
+ int failure = 0, quals;
+ bool overflow_p = false;
+
+ maxindex = size_zero_node;
+ if (initial_value)
+ {
+ STRIP_ANY_LOCATION_WRAPPER (initial_value);
+
+ if (TREE_CODE (initial_value) == STRING_CST)
+ {
+ int eltsize
+ = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
+ maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1);
+ }
+ else if (TREE_CODE (initial_value) == CONSTRUCTOR)
+ {
+ vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value);
+
+ if (vec_safe_is_empty (v))
+ {
+ if (pedantic)
+ failure = 3;
+ maxindex = ssize_int (-1);
+ }
+ else
+ {
+ tree curindex;
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
+ bool fold_p = false;
+
+ if ((*v)[0].index)
+ maxindex = (*v)[0].index, fold_p = true;
+
+ curindex = maxindex;
+
+ for (cnt = 1; vec_safe_iterate (v, cnt, &ce); cnt++)
+ {
+ bool curfold_p = false;
+ if (ce->index)
+ curindex = ce->index, curfold_p = true;
+ else
+ {
+ if (fold_p)
+ {
+ /* Since we treat size types now as ordinary
+ unsigned types, we need an explicit overflow
+ check. */
+ tree orig = curindex;
+ curindex = fold_convert (sizetype, curindex);
+ overflow_p |= tree_int_cst_lt (curindex, orig);
+ }
+ curindex = size_binop (PLUS_EXPR, curindex,
+ size_one_node);
+ }
+ if (tree_int_cst_lt (maxindex, curindex))
+ maxindex = curindex, fold_p = curfold_p;
+ }
+ if (fold_p)
+ {
+ tree orig = maxindex;
+ maxindex = fold_convert (sizetype, maxindex);
+ overflow_p |= tree_int_cst_lt (maxindex, orig);
+ }
+ }
+ }
+ else
+ {
+ /* Make an error message unless that happened already. */
+ if (initial_value != error_mark_node)
+ failure = 1;
+ }
+ }
+ else
+ {
+ failure = 2;
+ if (!do_default)
+ return failure;
+ }
+
+ type = *ptype;
+ elt = TREE_TYPE (type);
+ quals = TYPE_QUALS (strip_array_types (elt));
+ if (quals == 0)
+ unqual_elt = elt;
+ else
+ unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
+
+ /* Using build_distinct_type_copy and modifying things afterward instead
+ of using build_array_type to create a new type preserves all of the
+ TYPE_LANG_FLAG_? bits that the front end may have set. */
+ main_type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ TREE_TYPE (main_type) = unqual_elt;
+ TYPE_DOMAIN (main_type)
+ = build_range_type (TREE_TYPE (maxindex),
+ build_int_cst (TREE_TYPE (maxindex), 0), maxindex);
+ TYPE_TYPELESS_STORAGE (main_type) = TYPE_TYPELESS_STORAGE (type);
+ layout_type (main_type);
+
+ /* Make sure we have the canonical MAIN_TYPE. */
+ hashval_t hashcode = type_hash_canon_hash (main_type);
+ main_type = type_hash_canon (hashcode, main_type);
+
+ /* Fix the canonical type. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
+ || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
+ SET_TYPE_STRUCTURAL_EQUALITY (main_type);
+ else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
+ || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
+ != TYPE_DOMAIN (main_type)))
+ TYPE_CANONICAL (main_type)
+ = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
+ TYPE_CANONICAL (TYPE_DOMAIN (main_type)),
+ TYPE_TYPELESS_STORAGE (main_type));
+ else
+ TYPE_CANONICAL (main_type) = main_type;
+
+ if (quals == 0)
+ type = main_type;
+ else
+ type = c_build_qualified_type (main_type, quals);
+
+ if (COMPLETE_TYPE_P (type)
+ && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
+ && (overflow_p || TREE_OVERFLOW (TYPE_SIZE_UNIT (type))))
+ {
+ error ("size of array is too large");
+ /* If we proceed with the array type as it is, we'll eventually
+ crash in tree_to_[su]hwi(). */
+ type = error_mark_node;
+ }
+
+ *ptype = type;
+ return failure;
+}
+
+/* INIT is an constructor of a structure with a flexible array member.
+ Complete the flexible array member with a domain based on it's value. */
+void
+complete_flexible_array_elts (tree init)
+{
+ tree elt, type;
+
+ if (init == NULL_TREE || TREE_CODE (init) != CONSTRUCTOR)
+ return;
+
+ if (vec_safe_is_empty (CONSTRUCTOR_ELTS (init)))
+ return;
+
+ elt = CONSTRUCTOR_ELTS (init)->last ().value;
+ type = TREE_TYPE (elt);
+ if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_SIZE (type) == NULL_TREE)
+ complete_array_type (&TREE_TYPE (elt), elt, false);
+ else
+ complete_flexible_array_elts (elt);
+}
+
+/* Like c_mark_addressable but don't check register qualifier. */
+void
+c_common_mark_addressable_vec (tree t)
+{
+ while (handled_component_p (t) || TREE_CODE (t) == C_MAYBE_CONST_EXPR)
+ {
+ if (TREE_CODE (t) == C_MAYBE_CONST_EXPR)
+ t = C_MAYBE_CONST_EXPR_EXPR (t);
+ else
+ t = TREE_OPERAND (t, 0);
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != COMPOUND_LITERAL_EXPR
+ && TREE_CODE (t) != TARGET_EXPR)
+ return;
+ if (!VAR_P (t) || !DECL_HARD_REGISTER (t))
+ TREE_ADDRESSABLE (t) = 1;
+ if (TREE_CODE (t) == COMPOUND_LITERAL_EXPR)
+ TREE_ADDRESSABLE (COMPOUND_LITERAL_EXPR_DECL (t)) = 1;
+ else if (TREE_CODE (t) == TARGET_EXPR)
+ TREE_ADDRESSABLE (TARGET_EXPR_SLOT (t)) = 1;
+}
+
+
+
+/* Used to help initialize the builtin-types.def table. When a type of
+ the correct size doesn't exist, use error_mark_node instead of NULL.
+ The later results in segfaults even when a decl using the type doesn't
+ get invoked. */
+
+#if 0 // sdcpp
+tree
+builtin_type_for_size (int size, bool unsignedp)
+{
+ tree type = c_common_type_for_size (size, unsignedp);
+ return type ? type : error_mark_node;
+}
+
+/* Work out the size of the first argument of a call to
+ __builtin_speculation_safe_value. Only pointers and integral types
+ are permitted. Return -1 if the argument type is not supported or
+ the size is too large; 0 if the argument type is a pointer or the
+ size if it is integral. */
+static enum built_in_function
+speculation_safe_value_resolve_call (tree function, vec<tree, va_gc> *params)
+{
+ /* Type of the argument. */
+ tree type;
+ int size;
+
+ if (vec_safe_is_empty (params))
+ {
+ error ("too few arguments to function %qE", function);
+ return BUILT_IN_NONE;
+ }
+
+ type = TREE_TYPE ((*params)[0]);
+ if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ())
+ {
+ /* Force array-to-pointer decay for C++. */
+ (*params)[0] = default_conversion ((*params)[0]);
+ type = TREE_TYPE ((*params)[0]);
+ }
+
+ if (POINTER_TYPE_P (type))
+ return BUILT_IN_SPECULATION_SAFE_VALUE_PTR;
+
+ if (!INTEGRAL_TYPE_P (type))
+ goto incompatible;
+
+ if (!COMPLETE_TYPE_P (type))
+ goto incompatible;
+
+ size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
+ return ((enum built_in_function)
+ ((int) BUILT_IN_SPECULATION_SAFE_VALUE_1 + exact_log2 (size)));
+
+ incompatible:
+ /* Issue the diagnostic only if the argument is valid, otherwise
+ it would be redundant at best and could be misleading. */
+ if (type != error_mark_node)
+ error ("operand type %qT is incompatible with argument %d of %qE",
+ type, 1, function);
+
+ return BUILT_IN_NONE;
+}
+
+/* Validate and coerce PARAMS, the arguments to ORIG_FUNCTION to fit
+ the prototype for FUNCTION. The first argument is mandatory, a second
+ argument, if present, must be type compatible with the first. */
+static bool
+speculation_safe_value_resolve_params (location_t loc, tree orig_function,
+ vec<tree, va_gc> *params)
+{
+ tree val;
+
+ if (params->length () == 0)
+ {
+ error_at (loc, "too few arguments to function %qE", orig_function);
+ return false;
+ }
+
+ else if (params->length () > 2)
+ {
+ error_at (loc, "too many arguments to function %qE", orig_function);
+ return false;
+ }
+
+ val = (*params)[0];
+ if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE)
+ val = default_conversion (val);
+ if (!(TREE_CODE (TREE_TYPE (val)) == POINTER_TYPE
+ || TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE))
+ {
+ error_at (loc,
+ "expecting argument of type pointer or of type integer "
+ "for argument 1");
+ return false;
+ }
+ (*params)[0] = val;
+
+ if (params->length () == 2)
+ {
+ tree val2 = (*params)[1];
+ if (TREE_CODE (TREE_TYPE (val2)) == ARRAY_TYPE)
+ val2 = default_conversion (val2);
+ if (error_operand_p (val2))
+ return false;
+ if (!(TREE_TYPE (val) == TREE_TYPE (val2)
+ || useless_type_conversion_p (TREE_TYPE (val), TREE_TYPE (val2))))
+ {
+ error_at (loc, "both arguments must be compatible");
+ return false;
+ }
+ (*params)[1] = val2;
+ }
+
+ return true;
+}
+
+/* Cast the result of the builtin back to the type of the first argument,
+ preserving any qualifiers that it might have. */
+static tree
+speculation_safe_value_resolve_return (tree first_param, tree result)
+{
+ tree ptype = TREE_TYPE (first_param);
+ tree rtype = TREE_TYPE (result);
+ ptype = TYPE_MAIN_VARIANT (ptype);
+
+ if (tree_int_cst_equal (TYPE_SIZE (ptype), TYPE_SIZE (rtype)))
+ return convert (ptype, result);
+
+ return result;
+}
+
+/* A helper function for resolve_overloaded_builtin in resolving the
+ overloaded __sync_ builtins. Returns a positive power of 2 if the
+ first operand of PARAMS is a pointer to a supported data type.
+ Returns 0 if an error is encountered.
+ FETCH is true when FUNCTION is one of the _FETCH_OP_ or _OP_FETCH_
+ built-ins. */
+
+static int
+sync_resolve_size (tree function, vec<tree, va_gc> *params, bool fetch)
+{
+ /* Type of the argument. */
+ tree argtype;
+ /* Type the argument points to. */
+ tree type;
+ int size;
+
+ if (vec_safe_is_empty (params))
+ {
+ error ("too few arguments to function %qE", function);
+ return 0;
+ }
+
+ argtype = type = TREE_TYPE ((*params)[0]);
+ if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ())
+ {
+ /* Force array-to-pointer decay for C++. */
+ (*params)[0] = default_conversion ((*params)[0]);
+ type = TREE_TYPE ((*params)[0]);
+ }
+ if (TREE_CODE (type) != POINTER_TYPE)
+ goto incompatible;
+
+ type = TREE_TYPE (type);
+ if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+ goto incompatible;
+
+ if (!COMPLETE_TYPE_P (type))
+ goto incompatible;
+
+ if (fetch && TREE_CODE (type) == BOOLEAN_TYPE)
+ goto incompatible;
+
+ size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
+ return size;
+
+ incompatible:
+ /* Issue the diagnostic only if the argument is valid, otherwise
+ it would be redundant at best and could be misleading. */
+ if (argtype != error_mark_node)
+ error ("operand type %qT is incompatible with argument %d of %qE",
+ argtype, 1, function);
+ return 0;
+}
+
+/* A helper function for resolve_overloaded_builtin. Adds casts to
+ PARAMS to make arguments match up with those of FUNCTION. Drops
+ the variadic arguments at the end. Returns false if some error
+ was encountered; true on success. */
+
+static bool
+sync_resolve_params (location_t loc, tree orig_function, tree function,
+ vec<tree, va_gc> *params, bool orig_format)
+{
+ function_args_iterator iter;
+ tree ptype;
+ unsigned int parmnum;
+
+ function_args_iter_init (&iter, TREE_TYPE (function));
+ /* We've declared the implementation functions to use "volatile void *"
+ as the pointer parameter, so we shouldn't get any complaints from the
+ call to check_function_arguments what ever type the user used. */
+ function_args_iter_next (&iter);
+ ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
+ ptype = TYPE_MAIN_VARIANT (ptype);
+
+ /* For the rest of the values, we need to cast these to FTYPE, so that we
+ don't get warnings for passing pointer types, etc. */
+ parmnum = 0;
+ while (1)
+ {
+ tree val, arg_type;
+
+ arg_type = function_args_iter_cond (&iter);
+ /* XXX void_type_node belies the abstraction. */
+ if (arg_type == void_type_node)
+ break;
+
+ ++parmnum;
+ if (params->length () <= parmnum)
+ {
+ error_at (loc, "too few arguments to function %qE", orig_function);
+ return false;
+ }
+
+ /* Only convert parameters if arg_type is unsigned integer type with
+ new format sync routines, i.e. don't attempt to convert pointer
+ arguments (e.g. EXPECTED argument of __atomic_compare_exchange_n),
+ bool arguments (e.g. WEAK argument) or signed int arguments (memmodel
+ kinds). */
+ if (TREE_CODE (arg_type) == INTEGER_TYPE && TYPE_UNSIGNED (arg_type))
+ {
+ /* Ideally for the first conversion we'd use convert_for_assignment
+ so that we get warnings for anything that doesn't match the pointer
+ type. This isn't portable across the C and C++ front ends atm. */
+ val = (*params)[parmnum];
+ val = convert (ptype, val);
+ val = convert (arg_type, val);
+ (*params)[parmnum] = val;
+ }
+
+ function_args_iter_next (&iter);
+ }
+
+ /* __atomic routines are not variadic. */
+ if (!orig_format && params->length () != parmnum + 1)
+ {
+ error_at (loc, "too many arguments to function %qE", orig_function);
+ return false;
+ }
+
+ /* The definition of these primitives is variadic, with the remaining
+ being "an optional list of variables protected by the memory barrier".
+ No clue what that's supposed to mean, precisely, but we consider all
+ call-clobbered variables to be protected so we're safe. */
+ params->truncate (parmnum + 1);
+
+ return true;
+}
+
+/* A helper function for resolve_overloaded_builtin. Adds a cast to
+ RESULT to make it match the type of the first pointer argument in
+ PARAMS. */
+
+static tree
+sync_resolve_return (tree first_param, tree result, bool orig_format)
+{
+ tree ptype = TREE_TYPE (TREE_TYPE (first_param));
+ tree rtype = TREE_TYPE (result);
+ ptype = TYPE_MAIN_VARIANT (ptype);
+
+ /* New format doesn't require casting unless the types are the same size. */
+ if (orig_format || tree_int_cst_equal (TYPE_SIZE (ptype), TYPE_SIZE (rtype)))
+ return convert (ptype, result);
+ else
+ return result;
+}
+#endif
+
+/* This function verifies the PARAMS to generic atomic FUNCTION.
+ It returns the size if all the parameters are the same size, otherwise
+ 0 is returned if the parameters are invalid. */
+
+#if 0 // sdcpp
+static int
+get_atomic_generic_size (location_t loc, tree function,
+ vec<tree, va_gc> *params)
+{
+ unsigned int n_param;
+ unsigned int n_model;
+ unsigned int outputs = 0; // bitset of output parameters
+ unsigned int x;
+ int size_0;
+ tree type_0;
+
+ /* Determine the parameter makeup. */
+ switch (DECL_FUNCTION_CODE (function))
+ {
+ case BUILT_IN_ATOMIC_EXCHANGE:
+ n_param = 4;
+ n_model = 1;
+ outputs = 5;
+ break;
+ case BUILT_IN_ATOMIC_LOAD:
+ n_param = 3;
+ n_model = 1;
+ outputs = 2;
+ break;
+ case BUILT_IN_ATOMIC_STORE:
+ n_param = 3;
+ n_model = 1;
+ outputs = 1;
+ break;
+ case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
+ n_param = 6;
+ n_model = 2;
+ outputs = 3;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (vec_safe_length (params) != n_param)
+ {
+ error_at (loc, "incorrect number of arguments to function %qE", function);
+ return 0;
+ }
+
+ /* Get type of first parameter, and determine its size. */
+ type_0 = TREE_TYPE ((*params)[0]);
+ if (TREE_CODE (type_0) == ARRAY_TYPE && c_dialect_cxx ())
+ {
+ /* Force array-to-pointer decay for C++. */
+ (*params)[0] = default_conversion ((*params)[0]);
+ type_0 = TREE_TYPE ((*params)[0]);
+ }
+ if (TREE_CODE (type_0) != POINTER_TYPE || VOID_TYPE_P (TREE_TYPE (type_0)))
+ {
+ error_at (loc, "argument 1 of %qE must be a non-void pointer type",
+ function);
+ return 0;
+ }
+
+ if (!COMPLETE_TYPE_P (TREE_TYPE (type_0)))
+ {
+ error_at (loc, "argument 1 of %qE must be a pointer to a complete type",
+ function);
+ return 0;
+ }
+
+ /* Types must be compile time constant sizes. */
+ if (!tree_fits_uhwi_p ((TYPE_SIZE_UNIT (TREE_TYPE (type_0)))))
+ {
+ error_at (loc,
+ "argument 1 of %qE must be a pointer to a constant size type",
+ function);
+ return 0;
+ }
+
+ size_0 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type_0)));
+
+ /* Zero size objects are not allowed. */
+ if (size_0 == 0)
+ {
+ error_at (loc,
+ "argument 1 of %qE must be a pointer to a nonzero size object",
+ function);
+ return 0;
+ }
+
+ /* Check each other parameter is a pointer and the same size. */
+ for (x = 0; x < n_param - n_model; x++)
+ {
+ int size;
+ tree type = TREE_TYPE ((*params)[x]);
+ /* __atomic_compare_exchange has a bool in the 4th position, skip it. */
+ if (n_param == 6 && x == 3)
+ continue;
+ if (TREE_CODE (type) == ARRAY_TYPE && c_dialect_cxx ())
+ {
+ /* Force array-to-pointer decay for C++. */
+ (*params)[x] = default_conversion ((*params)[x]);
+ type = TREE_TYPE ((*params)[x]);
+ }
+ if (!POINTER_TYPE_P (type))
+ {
+ error_at (loc, "argument %d of %qE must be a pointer type", x + 1,
+ function);
+ return 0;
+ }
+ else if (TYPE_SIZE_UNIT (TREE_TYPE (type))
+ && TREE_CODE ((TYPE_SIZE_UNIT (TREE_TYPE (type))))
+ != INTEGER_CST)
+ {
+ error_at (loc, "argument %d of %qE must be a pointer to a constant "
+ "size type", x + 1, function);
+ return 0;
+ }
+ else if (FUNCTION_POINTER_TYPE_P (type))
+ {
+ error_at (loc, "argument %d of %qE must not be a pointer to a "
+ "function", x + 1, function);
+ return 0;
+ }
+ tree type_size = TYPE_SIZE_UNIT (TREE_TYPE (type));
+ size = type_size ? tree_to_uhwi (type_size) : 0;
+ if (size != size_0)
+ {
+ error_at (loc, "size mismatch in argument %d of %qE", x + 1,
+ function);
+ return 0;
+ }
+
+ {
+ auto_diagnostic_group d;
+ int quals = TYPE_QUALS (TREE_TYPE (type));
+ /* Must not write to an argument of a const-qualified type. */
+ if (outputs & (1 << x) && quals & TYPE_QUAL_CONST)
+ {
+ if (c_dialect_cxx ())
+ {
+ error_at (loc, "argument %d of %qE must not be a pointer to "
+ "a %<const%> type", x + 1, function);
+ return 0;
+ }
+ else
+ pedwarn (loc, OPT_Wincompatible_pointer_types, "argument %d "
+ "of %qE discards %<const%> qualifier", x + 1,
+ function);
+ }
+ /* Only the first argument is allowed to be volatile. */
+ if (x > 0 && quals & TYPE_QUAL_VOLATILE)
+ {
+ if (c_dialect_cxx ())
+ {
+ error_at (loc, "argument %d of %qE must not be a pointer to "
+ "a %<volatile%> type", x + 1, function);
+ return 0;
+ }
+ else
+ pedwarn (loc, OPT_Wincompatible_pointer_types, "argument %d "
+ "of %qE discards %<volatile%> qualifier", x + 1,
+ function);
+ }
+ }
+ }
+
+ /* Check memory model parameters for validity. */
+ for (x = n_param - n_model ; x < n_param; x++)
+ {
+ tree p = (*params)[x];
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
+ {
+ error_at (loc, "non-integer memory model argument %d of %qE", x + 1,
+ function);
+ return 0;
+ }
+ p = fold_for_warn (p);
+ if (TREE_CODE (p) == INTEGER_CST)
+ {
+ /* memmodel_base masks the low 16 bits, thus ignore any bits above
+ it by using TREE_INT_CST_LOW instead of tree_to_*hwi. Those high
+ bits will be checked later during expansion in target specific
+ way. */
+ if (memmodel_base (TREE_INT_CST_LOW (p)) >= MEMMODEL_LAST)
+ warning_at (loc, OPT_Winvalid_memory_model,
+ "invalid memory model argument %d of %qE", x + 1,
+ function);
+ }
+ }
+
+ return size_0;
+}
+
+
+/* This will take an __atomic_ generic FUNCTION call, and add a size parameter N
+ at the beginning of the parameter list PARAMS representing the size of the
+ objects. This is to match the library ABI requirement. LOC is the location
+ of the function call.
+ The new function is returned if it needed rebuilding, otherwise NULL_TREE is
+ returned to allow the external call to be constructed. */
+
+static tree
+add_atomic_size_parameter (unsigned n, location_t loc, tree function,
+ vec<tree, va_gc> *params)
+{
+ tree size_node;
+
+ /* Insert a SIZE_T parameter as the first param. If there isn't
+ enough space, allocate a new vector and recursively re-build with that. */
+ if (!params->space (1))
+ {
+ unsigned int z, len;
+ vec<tree, va_gc> *v;
+ tree f;
+
+ len = params->length ();
+ vec_alloc (v, len + 1);
+ v->quick_push (build_int_cst (size_type_node, n));
+ for (z = 0; z < len; z++)
+ v->quick_push ((*params)[z]);
+ f = build_function_call_vec (loc, vNULL, function, v, NULL);
+ vec_free (v);
+ return f;
+ }
+
+ /* Add the size parameter and leave as a function call for processing. */
+ size_node = build_int_cst (size_type_node, n);
+ params->quick_insert (0, size_node);
+ return NULL_TREE;
+}
+#endif
+
+#if 0 // sdcpp
+/* Return whether atomic operations for naturally aligned N-byte
+ arguments are supported, whether inline or through libatomic. */
+static bool
+atomic_size_supported_p (int n)
+{
+ switch (n)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ return true;
+
+ case 16:
+ return targetm.scalar_mode_supported_p (TImode);
+
+ default:
+ return false;
+ }
+}
+
+/* This will process an __atomic_exchange function call, determine whether it
+ needs to be mapped to the _N variation, or turned into a library call.
+ LOC is the location of the builtin call.
+ FUNCTION is the DECL that has been invoked;
+ PARAMS is the argument list for the call. The return value is non-null
+ TRUE is returned if it is translated into the proper format for a call to the
+ external library, and NEW_RETURN is set the tree for that function.
+ FALSE is returned if processing for the _N variation is required, and
+ NEW_RETURN is set to the return value the result is copied into. */
+static bool
+resolve_overloaded_atomic_exchange (location_t loc, tree function,
+ vec<tree, va_gc> *params, tree *new_return)
+{
+ tree p0, p1, p2, p3;
+ tree I_type, I_type_ptr;
+ int n = get_atomic_generic_size (loc, function, params);
+
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
+ /* If not a lock-free size, change to the library generic format. */
+ if (!atomic_size_supported_p (n))
+ {
+ *new_return = add_atomic_size_parameter (n, loc, function, params);
+ return true;
+ }
+
+ /* Otherwise there is a lockfree match, transform the call from:
+ void fn(T* mem, T* desired, T* return, model)
+ into
+ *return = (T) (fn (In* mem, (In) *desired, model)) */
+
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+ p2 = (*params)[2];
+ p3 = (*params)[3];
+
+ /* Create pointer to appropriate size. */
+ I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
+ I_type_ptr = build_pointer_type (I_type);
+
+ /* Convert object pointer to required type. */
+ p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+ (*params)[0] = p0;
+ /* Convert new value to required type, and dereference it. */
+ p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+ p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
+ (*params)[1] = p1;
+
+ /* Move memory model to the 3rd position, and end param list. */
+ (*params)[2] = p3;
+ params->truncate (3);
+
+ /* Convert return pointer and dereference it for later assignment. */
+ *new_return = build_indirect_ref (loc, p2, RO_UNARY_STAR);
+
+ return false;
+}
+
+
+/* This will process an __atomic_compare_exchange function call, determine
+ whether it needs to be mapped to the _N variation, or turned into a lib call.
+ LOC is the location of the builtin call.
+ FUNCTION is the DECL that has been invoked;
+ PARAMS is the argument list for the call. The return value is non-null
+ TRUE is returned if it is translated into the proper format for a call to the
+ external library, and NEW_RETURN is set the tree for that function.
+ FALSE is returned if processing for the _N variation is required. */
+
+static bool
+resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
+ vec<tree, va_gc> *params,
+ tree *new_return)
+{
+ tree p0, p1, p2;
+ tree I_type, I_type_ptr;
+ int n = get_atomic_generic_size (loc, function, params);
+
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
+ /* If not a lock-free size, change to the library generic format. */
+ if (!atomic_size_supported_p (n))
+ {
+ /* The library generic format does not have the weak parameter, so
+ remove it from the param list. Since a parameter has been removed,
+ we can be sure that there is room for the SIZE_T parameter, meaning
+ there will not be a recursive rebuilding of the parameter list, so
+ there is no danger this will be done twice. */
+ if (n > 0)
+ {
+ (*params)[3] = (*params)[4];
+ (*params)[4] = (*params)[5];
+ params->truncate (5);
+ }
+ *new_return = add_atomic_size_parameter (n, loc, function, params);
+ return true;
+ }
+
+ /* Otherwise, there is a match, so the call needs to be transformed from:
+ bool fn(T* mem, T* desired, T* return, weak, success, failure)
+ into
+ bool fn ((In *)mem, (In *)expected, (In) *desired, weak, succ, fail) */
+
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+ p2 = (*params)[2];
+
+ /* Create pointer to appropriate size. */
+ I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
+ I_type_ptr = build_pointer_type (I_type);
+
+ /* Convert object pointer to required type. */
+ p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+ (*params)[0] = p0;
+
+ /* Convert expected pointer to required type. */
+ p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
+ (*params)[1] = p1;
+
+ /* Convert desired value to required type, and dereference it. */
+ p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
+ p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
+ (*params)[2] = p2;
+
+ /* The rest of the parameters are fine. NULL means no special return value
+ processing.*/
+ *new_return = NULL;
+ return false;
+}
+#endif
+
+
+/* This will process an __atomic_load function call, determine whether it
+ needs to be mapped to the _N variation, or turned into a library call.
+ LOC is the location of the builtin call.
+ FUNCTION is the DECL that has been invoked;
+ PARAMS is the argument list for the call. The return value is non-null
+ TRUE is returned if it is translated into the proper format for a call to the
+ external library, and NEW_RETURN is set the tree for that function.
+ FALSE is returned if processing for the _N variation is required, and
+ NEW_RETURN is set to the return value the result is copied into. */
+
+#if 0 //sdcpp
+static bool
+resolve_overloaded_atomic_load (location_t loc, tree function,
+ vec<tree, va_gc> *params, tree *new_return)
+{
+ tree p0, p1, p2;
+ tree I_type, I_type_ptr;
+ int n = get_atomic_generic_size (loc, function, params);
+
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
+ /* If not a lock-free size, change to the library generic format. */
+ if (!atomic_size_supported_p (n))
+ {
+ *new_return = add_atomic_size_parameter (n, loc, function, params);
+ return true;
+ }
+
+ /* Otherwise, there is a match, so the call needs to be transformed from:
+ void fn(T* mem, T* return, model)
+ into
+ *return = (T) (fn ((In *) mem, model)) */
+
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+ p2 = (*params)[2];
+
+ /* Create pointer to appropriate size. */
+ I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
+ I_type_ptr = build_pointer_type (I_type);
+
+ /* Convert object pointer to required type. */
+ p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+ (*params)[0] = p0;
+
+ /* Move memory model to the 2nd position, and end param list. */
+ (*params)[1] = p2;
+ params->truncate (2);
+
+ /* Convert return pointer and dereference it for later assignment. */
+ *new_return = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+
+ return false;
+}
+
+
+/* This will process an __atomic_store function call, determine whether it
+ needs to be mapped to the _N variation, or turned into a library call.
+ LOC is the location of the builtin call.
+ FUNCTION is the DECL that has been invoked;
+ PARAMS is the argument list for the call. The return value is non-null
+ TRUE is returned if it is translated into the proper format for a call to the
+ external library, and NEW_RETURN is set the tree for that function.
+ FALSE is returned if processing for the _N variation is required, and
+ NEW_RETURN is set to the return value the result is copied into. */
+
+static bool
+resolve_overloaded_atomic_store (location_t loc, tree function,
+ vec<tree, va_gc> *params, tree *new_return)
+{
+ tree p0, p1;
+ tree I_type, I_type_ptr;
+ int n = get_atomic_generic_size (loc, function, params);
+
+ /* Size of 0 is an error condition. */
+ if (n == 0)
+ {
+ *new_return = error_mark_node;
+ return true;
+ }
+
+ /* If not a lock-free size, change to the library generic format. */
+ if (!atomic_size_supported_p (n))
+ {
+ *new_return = add_atomic_size_parameter (n, loc, function, params);
+ return true;
+ }
+
+ /* Otherwise, there is a match, so the call needs to be transformed from:
+ void fn(T* mem, T* value, model)
+ into
+ fn ((In *) mem, (In) *value, model) */
+
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+
+ /* Create pointer to appropriate size. */
+ I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
+ I_type_ptr = build_pointer_type (I_type);
+
+ /* Convert object pointer to required type. */
+ p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
+ (*params)[0] = p0;
+
+ /* Convert new value to required type, and dereference it. */
+ p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
+ p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
+ (*params)[1] = p1;
+
+ /* The memory model is in the right spot already. Return is void. */
+ *new_return = NULL_TREE;
+
+ return false;
+}
+
+
+/* Some builtin functions are placeholders for other expressions. This
+ function should be called immediately after parsing the call expression
+ before surrounding code has committed to the type of the expression.
+
+ LOC is the location of the builtin call.
+
+ FUNCTION is the DECL that has been invoked; it is known to be a builtin.
+ PARAMS is the argument list for the call. The return value is non-null
+ when expansion is complete, and null if normal processing should
+ continue. */
+
+tree
+resolve_overloaded_builtin (location_t loc, tree function,
+ vec<tree, va_gc> *params)
+{
+ /* Is function one of the _FETCH_OP_ or _OP_FETCH_ built-ins?
+ Those are not valid to call with a pointer to _Bool (or C++ bool)
+ and so must be rejected. */
+ bool fetch_op = true;
+ bool orig_format = true;
+ tree new_return = NULL_TREE;
+
+ switch (DECL_BUILT_IN_CLASS (function))
+ {
+ case BUILT_IN_NORMAL:
+ break;
+ case BUILT_IN_MD:
+ if (targetm.resolve_overloaded_builtin)
+ return targetm.resolve_overloaded_builtin (loc, function, params);
+ else
+ return NULL_TREE;
+ default:
+ return NULL_TREE;
+ }
+
+ /* Handle BUILT_IN_NORMAL here. */
+ enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
+ switch (orig_code)
+ {
+ case BUILT_IN_SPECULATION_SAFE_VALUE_N:
+ {
+ tree new_function, first_param, result;
+ enum built_in_function fncode
+ = speculation_safe_value_resolve_call (function, params);
+
+ if (fncode == BUILT_IN_NONE)
+ return error_mark_node;
+
+ first_param = (*params)[0];
+ if (!speculation_safe_value_resolve_params (loc, function, params))
+ return error_mark_node;
+
+ if (targetm.have_speculation_safe_value (true))
+ {
+ new_function = builtin_decl_explicit (fncode);
+ result = build_function_call_vec (loc, vNULL, new_function, params,
+ NULL);
+
+ if (result == error_mark_node)
+ return result;
+
+ return speculation_safe_value_resolve_return (first_param, result);
+ }
+ else
+ {
+ /* This target doesn't have, or doesn't need, active mitigation
+ against incorrect speculative execution. Simply return the
+ first parameter to the builtin. */
+ if (!targetm.have_speculation_safe_value (false))
+ /* The user has invoked __builtin_speculation_safe_value
+ even though __HAVE_SPECULATION_SAFE_VALUE is not
+ defined: emit a warning. */
+ warning_at (input_location, 0,
+ "this target does not define a speculation barrier; "
+ "your program will still execute correctly, "
+ "but incorrect speculation may not be "
+ "restricted");
+
+ /* If the optional second argument is present, handle any side
+ effects now. */
+ if (params->length () == 2
+ && TREE_SIDE_EFFECTS ((*params)[1]))
+ return build2 (COMPOUND_EXPR, TREE_TYPE (first_param),
+ (*params)[1], first_param);
+
+ return first_param;
+ }
+ }
+
+ case BUILT_IN_ATOMIC_EXCHANGE:
+ case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
+ case BUILT_IN_ATOMIC_LOAD:
+ case BUILT_IN_ATOMIC_STORE:
+ {
+ /* Handle these 4 together so that they can fall through to the next
+ case if the call is transformed to an _N variant. */
+ switch (orig_code)
+ {
+ case BUILT_IN_ATOMIC_EXCHANGE:
+ {
+ if (resolve_overloaded_atomic_exchange (loc, function, params,
+ &new_return))
+ return new_return;
+ /* Change to the _N variant. */
+ orig_code = BUILT_IN_ATOMIC_EXCHANGE_N;
+ break;
+ }
+
+ case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
+ {
+ if (resolve_overloaded_atomic_compare_exchange (loc, function,
+ params,
+ &new_return))
+ return new_return;
+ /* Change to the _N variant. */
+ orig_code = BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N;
+ break;
+ }
+ case BUILT_IN_ATOMIC_LOAD:
+ {
+ if (resolve_overloaded_atomic_load (loc, function, params,
+ &new_return))
+ return new_return;
+ /* Change to the _N variant. */
+ orig_code = BUILT_IN_ATOMIC_LOAD_N;
+ break;
+ }
+ case BUILT_IN_ATOMIC_STORE:
+ {
+ if (resolve_overloaded_atomic_store (loc, function, params,
+ &new_return))
+ return new_return;
+ /* Change to the _N variant. */
+ orig_code = BUILT_IN_ATOMIC_STORE_N;
+ break;
+ }
+ default:
+ gcc_unreachable ();
+ }
+ }
+ /* FALLTHRU */
+ case BUILT_IN_ATOMIC_EXCHANGE_N:
+ case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N:
+ case BUILT_IN_ATOMIC_LOAD_N:
+ case BUILT_IN_ATOMIC_STORE_N:
+ fetch_op = false;
+ /* FALLTHRU */
+ case BUILT_IN_ATOMIC_ADD_FETCH_N:
+ case BUILT_IN_ATOMIC_SUB_FETCH_N:
+ case BUILT_IN_ATOMIC_AND_FETCH_N:
+ case BUILT_IN_ATOMIC_NAND_FETCH_N:
+ case BUILT_IN_ATOMIC_XOR_FETCH_N:
+ case BUILT_IN_ATOMIC_OR_FETCH_N:
+ case BUILT_IN_ATOMIC_FETCH_ADD_N:
+ case BUILT_IN_ATOMIC_FETCH_SUB_N:
+ case BUILT_IN_ATOMIC_FETCH_AND_N:
+ case BUILT_IN_ATOMIC_FETCH_NAND_N:
+ case BUILT_IN_ATOMIC_FETCH_XOR_N:
+ case BUILT_IN_ATOMIC_FETCH_OR_N:
+ orig_format = false;
+ /* FALLTHRU */
+ case BUILT_IN_SYNC_FETCH_AND_ADD_N:
+ case BUILT_IN_SYNC_FETCH_AND_SUB_N:
+ case BUILT_IN_SYNC_FETCH_AND_OR_N:
+ case BUILT_IN_SYNC_FETCH_AND_AND_N:
+ case BUILT_IN_SYNC_FETCH_AND_XOR_N:
+ case BUILT_IN_SYNC_FETCH_AND_NAND_N:
+ case BUILT_IN_SYNC_ADD_AND_FETCH_N:
+ case BUILT_IN_SYNC_SUB_AND_FETCH_N:
+ case BUILT_IN_SYNC_OR_AND_FETCH_N:
+ case BUILT_IN_SYNC_AND_AND_FETCH_N:
+ case BUILT_IN_SYNC_XOR_AND_FETCH_N:
+ case BUILT_IN_SYNC_NAND_AND_FETCH_N:
+ case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N:
+ case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N:
+ case BUILT_IN_SYNC_LOCK_TEST_AND_SET_N:
+ case BUILT_IN_SYNC_LOCK_RELEASE_N:
+ {
+ /* The following are not _FETCH_OPs and must be accepted with
+ pointers to _Bool (or C++ bool). */
+ if (fetch_op)
+ fetch_op =
+ (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
+ && orig_code != BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+ && orig_code != BUILT_IN_SYNC_LOCK_TEST_AND_SET_N
+ && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N);
+
+ int n = sync_resolve_size (function, params, fetch_op);
+ tree new_function, first_param, result;
+ enum built_in_function fncode;
+
+ if (n == 0)
+ return error_mark_node;
+
+ fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
+ new_function = builtin_decl_explicit (fncode);
+ if (!sync_resolve_params (loc, function, new_function, params,
+ orig_format))
+ return error_mark_node;
+
+ first_param = (*params)[0];
+ result = build_function_call_vec (loc, vNULL, new_function, params,
+ NULL);
+ if (result == error_mark_node)
+ return result;
+ if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
+ && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N
+ && orig_code != BUILT_IN_ATOMIC_STORE_N
+ && orig_code != BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N)
+ result = sync_resolve_return (first_param, result, orig_format);
+
+ if (fetch_op)
+ /* Prevent -Wunused-value warning. */
+ TREE_USED (result) = true;
+
+ /* If new_return is set, assign function to that expr and cast the
+ result to void since the generic interface returned void. */
+ if (new_return)
+ {
+ /* Cast function result from I{1,2,4,8,16} to the required type. */
+ result = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (new_return), result);
+ result = build2 (MODIFY_EXPR, TREE_TYPE (new_return), new_return,
+ result);
+ TREE_SIDE_EFFECTS (result) = 1;
+ protected_set_expr_location (result, loc);
+ result = convert (void_type_node, result);
+ }
+ return result;
+ }
+
+ default:
+ return NULL_TREE;
+ }
+}
+#endif
+
+/* vector_types_compatible_elements_p is used in type checks of vectors
+ values used as operands of binary operators. Where it returns true, and
+ the other checks of the caller succeed (being vector types in he first
+ place, and matching number of elements), we can just treat the types
+ as essentially the same.
+ Contrast with vector_targets_convertible_p, which is used for vector
+ pointer types, and vector_types_convertible_p, which will allow
+ language-specific matches under the control of flag_lax_vector_conversions,
+ and might still require a conversion. */
+/* True if vector types T1 and T2 can be inputs to the same binary
+ operator without conversion.
+ We don't check the overall vector size here because some of our callers
+ want to give different error messages when the vectors are compatible
+ except for the element count. */
+
+bool
+vector_types_compatible_elements_p (tree t1, tree t2)
+{
+ bool opaque = TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2);
+ t1 = TREE_TYPE (t1);
+ t2 = TREE_TYPE (t2);
+
+ enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
+
+ gcc_assert ((INTEGRAL_TYPE_P (t1)
+ || c1 == REAL_TYPE
+ || c1 == FIXED_POINT_TYPE)
+ && (INTEGRAL_TYPE_P (t2)
+ || c2 == REAL_TYPE
+ || c2 == FIXED_POINT_TYPE));
+
+ t1 = c_common_signed_type (t1);
+ t2 = c_common_signed_type (t2);
+ /* Equality works here because c_common_signed_type uses
+ TYPE_MAIN_VARIANT. */
+ if (t1 == t2)
+ return true;
+ if (opaque && c1 == c2
+ && (INTEGRAL_TYPE_P (t1) || c1 == REAL_TYPE)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+ return true;
+ return false;
+}
+
+/* Check for missing format attributes on function pointers. LTYPE is
+ the new type or left-hand side type. RTYPE is the old type or
+ right-hand side type. Returns TRUE if LTYPE is missing the desired
+ attribute. */
+
+bool
+check_missing_format_attribute (tree ltype, tree rtype)
+{
+ tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
+ tree ra;
+
+ for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
+ if (is_attribute_p ("format", get_attribute_name (ra)))
+ break;
+ if (ra)
+ {
+ tree la;
+ for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
+ if (is_attribute_p ("format", get_attribute_name (la)))
+ break;
+ return !la;
+ }
+ else
+ return false;
+}
+
+/* Setup a TYPE_DECL node as a typedef representation.
+
+ X is a TYPE_DECL for a typedef statement. Create a brand new
+ ..._TYPE node (which will be just a variant of the existing
+ ..._TYPE node with identical properties) and then install X
+ as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
+
+ The whole point here is to end up with a situation where each
+ and every ..._TYPE node the compiler creates will be uniquely
+ associated with AT MOST one node representing a typedef name.
+ This way, even though the compiler substitutes corresponding
+ ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
+ early on, later parts of the compiler can always do the reverse
+ translation and get back the corresponding typedef name. For
+ example, given:
+
+ typedef struct S MY_TYPE;
+ MY_TYPE object;
+
+ Later parts of the compiler might only know that `object' was of
+ type `struct S' if it were not for code just below. With this
+ code however, later parts of the compiler see something like:
+
+ struct S' == struct S
+ typedef struct S' MY_TYPE;
+ struct S' object;
+
+ And they can then deduce (from the node for type struct S') that
+ the original object declaration was:
+
+ MY_TYPE object;
+
+ Being able to do this is important for proper support of protoize,
+ and also for generating precise symbolic debugging information
+ which takes full account of the programmer's (typedef) vocabulary.
+
+ Obviously, we don't want to generate a duplicate ..._TYPE node if
+ the TYPE_DECL node that we are now processing really represents a
+ standard built-in type. */
+
+void
+set_underlying_type (tree x)
+{
+ if (x == error_mark_node)
+ return;
+ if (DECL_IS_UNDECLARED_BUILTIN (x) && TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE)
+ {
+ if (TYPE_NAME (TREE_TYPE (x)) == 0)
+ TYPE_NAME (TREE_TYPE (x)) = x;
+ }
+ else if (TREE_TYPE (x) != error_mark_node
+ && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
+ {
+ tree tt = TREE_TYPE (x);
+ DECL_ORIGINAL_TYPE (x) = tt;
+ tt = build_variant_type_copy (tt);
+ TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
+ TYPE_NAME (tt) = x;
+
+ /* Mark the type as used only when its type decl is decorated
+ with attribute unused. */
+ if (lookup_attribute ("unused", DECL_ATTRIBUTES (x)))
+ TREE_USED (tt) = 1;
+
+ TREE_TYPE (x) = tt;
+ }
+}
+
+/* Return true if it is worth exposing the DECL_ORIGINAL_TYPE of TYPE to
+ the user in diagnostics, false if it would be better to use TYPE itself.
+ TYPE is known to satisfy typedef_variant_p. */
+
+bool
+user_facing_original_type_p (const_tree type)
+{
+ gcc_assert (typedef_variant_p (type));
+ tree decl = TYPE_NAME (type);
+
+ /* Look through any typedef in "user" code. */
+ if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_UNDECLARED_BUILTIN (decl))
+ return true;
+
+ /* If the original type is also named and is in the user namespace,
+ assume it too is a user-facing type. */
+ tree orig_type = DECL_ORIGINAL_TYPE (decl);
+ if (tree orig_id = TYPE_IDENTIFIER (orig_type))
+ if (!name_reserved_for_implementation_p (IDENTIFIER_POINTER (orig_id)))
+ return true;
+
+ switch (TREE_CODE (orig_type))
+ {
+ /* Don't look through to an anonymous vector type, since the syntax
+ we use for them in diagnostics isn't real C or C++ syntax.
+ And if ORIG_TYPE is named but in the implementation namespace,
+ TYPE is likely to be more meaningful to the user. */
+ case VECTOR_TYPE:
+ return false;
+
+ /* Don't expose anonymous tag types that are presumably meant to be
+ known by their typedef name. Also don't expose tags that are in
+ the implementation namespace, such as:
+
+ typedef struct __foo foo; */
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ return false;
+
+ /* Look through to anything else. */
+ default:
+ return true;
+ }
+}
+
+/* Record the types used by the current global variable declaration
+ being parsed, so that we can decide later to emit their debug info.
+ Those types are in types_used_by_cur_var_decl, and we are going to
+ store them in the types_used_by_vars_hash hash table.
+ DECL is the declaration of the global variable that has been parsed. */
+
+#if 0 // sdcpp
+void
+record_types_used_by_current_var_decl (tree decl)
+{
+ gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
+
+ while (types_used_by_cur_var_decl && !types_used_by_cur_var_decl->is_empty ())
+ {
+ tree type = types_used_by_cur_var_decl->pop ();
+ types_used_by_var_decl_insert (type, decl);
+ }
+}
+#endif
+
+/* The C and C++ parsers both use vectors to hold function arguments.
+ For efficiency, we keep a cache of unused vectors. This is the
+ cache. */
+
+typedef vec<tree, va_gc> *tree_gc_vec;
+static GTY((deletable)) vec<tree_gc_vec, va_gc> *tree_vector_cache;
+
+/* Return a new vector from the cache. If the cache is empty,
+ allocate a new vector. These vectors are GC'ed, so it is OK if the
+ pointer is not released.. */
+
+vec<tree, va_gc> *
+make_tree_vector (void)
+{
+ if (tree_vector_cache && !tree_vector_cache->is_empty ())
+ return tree_vector_cache->pop ();
+ else
+ {
+ /* Passing 0 to vec::alloc returns NULL, and our callers require
+ that we always return a non-NULL value. The vector code uses
+ 4 when growing a NULL vector, so we do too. */
+ vec<tree, va_gc> *v;
+ vec_alloc (v, 4);
+ return v;
+ }
+}
+
+/* Release a vector of trees back to the cache. */
+
+void
+release_tree_vector (vec<tree, va_gc> *vec)
+{
+ if (vec != NULL)
+ {
+ if (vec->allocated () >= 16)
+ /* Don't cache vecs that have expanded more than once. On a p64
+ target, vecs double in alloc size with each power of 2 elements, e.g
+ at 16 elements the alloc increases from 128 to 256 bytes. */
+ vec_free (vec);
+ else
+ {
+ vec->truncate (0);
+ vec_safe_push (tree_vector_cache, vec);
+ }
+ }
+}
+
+/* Get a new tree vector holding a single tree. */
+
+vec<tree, va_gc> *
+make_tree_vector_single (tree t)
+{
+ vec<tree, va_gc> *ret = make_tree_vector ();
+ ret->quick_push (t);
+ return ret;
+}
+
+/* Get a new tree vector of the TREE_VALUEs of a TREE_LIST chain. */
+
+vec<tree, va_gc> *
+make_tree_vector_from_list (tree list)
+{
+ vec<tree, va_gc> *ret = make_tree_vector ();
+ for (; list; list = TREE_CHAIN (list))
+ vec_safe_push (ret, TREE_VALUE (list));
+ return ret;
+}
+
+/* Get a new tree vector of the values of a CONSTRUCTOR. */
+
+vec<tree, va_gc> *
+make_tree_vector_from_ctor (tree ctor)
+{
+ vec<tree,va_gc> *ret = make_tree_vector ();
+ vec_safe_reserve (ret, CONSTRUCTOR_NELTS (ctor));
+ for (unsigned i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
+ ret->quick_push (CONSTRUCTOR_ELT (ctor, i)->value);
+ return ret;
+}
+
+/* Get a new tree vector which is a copy of an existing one. */
+
+vec<tree, va_gc> *
+make_tree_vector_copy (const vec<tree, va_gc> *orig)
+{
+ vec<tree, va_gc> *ret;
+ unsigned int ix;
+ tree t;
+
+ ret = make_tree_vector ();
+ vec_safe_reserve (ret, vec_safe_length (orig));
+ FOR_EACH_VEC_SAFE_ELT (orig, ix, t)
+ ret->quick_push (t);
+ return ret;
+}
+
+/* Return true if KEYWORD starts a type specifier. */
+
+bool
+keyword_begins_type_specifier (enum rid keyword)
+{
+ (void) keyword;
+ gcc_assert(0 && "keyword");
+ return false;
+#if 0 // sdcpp
+ switch (keyword)
+ {
+ case RID_AUTO_TYPE:
+ case RID_INT:
+ case RID_CHAR:
+ case RID_FLOAT:
+ case RID_DOUBLE:
+ case RID_VOID:
+ case RID_UNSIGNED:
+ case RID_LONG:
+ case RID_SHORT:
+ case RID_SIGNED:
+ CASE_RID_FLOATN_NX:
+ case RID_DFLOAT32:
+ case RID_DFLOAT64:
+ case RID_DFLOAT128:
+ case RID_FRACT:
+ case RID_ACCUM:
+ case RID_BOOL:
+ case RID_WCHAR:
+ case RID_CHAR8:
+ case RID_CHAR16:
+ case RID_CHAR32:
+ case RID_SAT:
+ case RID_COMPLEX:
+ case RID_TYPEOF:
+ case RID_STRUCT:
+ case RID_CLASS:
+ case RID_UNION:
+ case RID_ENUM:
+ return true;
+ default:
+ if (keyword >= RID_FIRST_INT_N
+ && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
+ && int_n_enabled_p[keyword-RID_FIRST_INT_N])
+ return true;
+ return false;
+ }
+#endif
+}
+
+/* Return true if KEYWORD names a type qualifier. */
+
+bool
+keyword_is_type_qualifier (enum rid keyword)
+{
+ switch (keyword)
+ {
+ case RID_CONST:
+ case RID_VOLATILE:
+ case RID_RESTRICT:
+ case RID_ATOMIC:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Return true if KEYWORD names a storage class specifier.
+
+ RID_TYPEDEF is not included in this list despite `typedef' being
+ listed in C99 6.7.1.1. 6.7.1.3 indicates that `typedef' is listed as
+ such for syntactic convenience only. */
+
+bool
+keyword_is_storage_class_specifier (enum rid keyword)
+{
+ switch (keyword)
+ {
+ case RID_STATIC:
+ case RID_EXTERN:
+ case RID_REGISTER:
+ case RID_AUTO:
+ case RID_MUTABLE:
+ case RID_THREAD:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Return true if KEYWORD names a function-specifier [dcl.fct.spec]. */
+
+static bool
+keyword_is_function_specifier (enum rid keyword)
+{
+ switch (keyword)
+ {
+ case RID_INLINE:
+ case RID_NORETURN:
+ case RID_VIRTUAL:
+ case RID_EXPLICIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Return true if KEYWORD names a decl-specifier [dcl.spec] or a
+ declaration-specifier (C99 6.7). */
+
+bool
+keyword_is_decl_specifier (enum rid keyword)
+{
+ if (keyword_is_storage_class_specifier (keyword)
+ || keyword_is_type_qualifier (keyword)
+ || keyword_is_function_specifier (keyword))
+ return true;
+
+ switch (keyword)
+ {
+ case RID_TYPEDEF:
+ case RID_FRIEND:
+ case RID_CONSTEXPR:
+ case RID_CONSTINIT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Initialize language-specific-bits of tree_contains_struct. */
+
+void
+c_common_init_ts (void)
+{
+ gcc_assert(0 && "c_common_init_ts");
+ MARK_TS_EXP (SIZEOF_EXPR);
+ MARK_TS_EXP (PAREN_SIZEOF_EXPR);
+ MARK_TS_EXP (C_MAYBE_CONST_EXPR);
+ MARK_TS_EXP (EXCESS_PRECISION_EXPR);
+ MARK_TS_EXP (BREAK_STMT);
+ MARK_TS_EXP (CONTINUE_STMT);
+ MARK_TS_EXP (DO_STMT);
+ MARK_TS_EXP (FOR_STMT);
+ MARK_TS_EXP (SWITCH_STMT);
+ MARK_TS_EXP (WHILE_STMT);
+}
+
+/* Build a user-defined numeric literal out of an integer constant type VALUE
+ with identifier SUFFIX. */
+
+tree
+build_userdef_literal (tree suffix_id, tree value,
+ enum overflow_type overflow, tree num_string)
+{
+ tree literal = make_node (USERDEF_LITERAL);
+ USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
+ USERDEF_LITERAL_VALUE (literal) = value;
+ USERDEF_LITERAL_OVERFLOW (literal) = overflow;
+ USERDEF_LITERAL_NUM_STRING (literal) = num_string;
+ return literal;
+}
+
+/* For vector[index], convert the vector to an array of the underlying type.
+ Return true if the resulting ARRAY_REF should not be an lvalue. */
+
+bool
+convert_vector_to_array_for_subscript (location_t loc,
+ tree *vecp, tree index)
+{
+ bool ret = false;
+ if (gnu_vector_type_p (TREE_TYPE (*vecp)))
+ {
+ tree type = TREE_TYPE (*vecp);
+
+ ret = !lvalue_p (*vecp);
+
+ index = fold_for_warn (index);
+ if (TREE_CODE (index) == INTEGER_CST)
+ if (!tree_fits_uhwi_p (index)
+ || maybe_ge (tree_to_uhwi (index), TYPE_VECTOR_SUBPARTS (type)))
+ warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
+
+ /* We are building an ARRAY_REF so mark the vector as addressable
+ to not run into the gimplifiers premature setting of DECL_GIMPLE_REG_P
+ for function parameters. */
+ c_common_mark_addressable_vec (*vecp);
+
+ *vecp = build1 (VIEW_CONVERT_EXPR,
+ build_array_type_nelts (TREE_TYPE (type),
+ TYPE_VECTOR_SUBPARTS (type)),
+ *vecp);
+ }
+ return ret;
+}
+
+/* Determine which of the operands, if any, is a scalar that needs to be
+ converted to a vector, for the range of operations. */
+enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
+ bool complain)
+{
+ tree type0 = TREE_TYPE (op0);
+ tree type1 = TREE_TYPE (op1);
+ bool integer_only_op = false;
+ enum stv_conv ret = stv_firstarg;
+
+ gcc_assert (gnu_vector_type_p (type0) || gnu_vector_type_p (type1));
+ switch (code)
+ {
+ /* Most GENERIC binary expressions require homogeneous arguments.
+ LSHIFT_EXPR and RSHIFT_EXPR are exceptions and accept a first
+ argument that is a vector and a second one that is a scalar, so
+ we never return stv_secondarg for them. */
+ case RSHIFT_EXPR:
+ case LSHIFT_EXPR:
+ if (TREE_CODE (type0) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+ {
+ if (unsafe_conversion_p (TREE_TYPE (type1), op0,
+ NULL_TREE, false))
+ {
+ if (complain)
+ error_at (loc, "conversion of scalar %qT to vector %qT "
+ "involves truncation", type0, type1);
+ return stv_error;
+ }
+ else
+ return stv_firstarg;
+ }
+ break;
+
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ integer_only_op = true;
+ /* fall through */
+
+ case VEC_COND_EXPR:
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case RDIV_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case LE_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case GT_EXPR:
+ /* What about UNLT_EXPR? */
+ if (gnu_vector_type_p (type0))
+ {
+ ret = stv_secondarg;
+ std::swap (type0, type1);
+ std::swap (op0, op1);
+ }
+
+ if (TREE_CODE (type0) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+ {
+ if (unsafe_conversion_p (TREE_TYPE (type1), op0,
+ NULL_TREE, false))
+ {
+ if (complain)
+ error_at (loc, "conversion of scalar %qT to vector %qT "
+ "involves truncation", type0, type1);
+ return stv_error;
+ }
+ return ret;
+ }
+ else if (!integer_only_op
+ /* Allow integer --> real conversion if safe. */
+ && (TREE_CODE (type0) == REAL_TYPE
+ || TREE_CODE (type0) == INTEGER_TYPE)
+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+ {
+ if (unsafe_conversion_p (TREE_TYPE (type1), op0,
+ NULL_TREE, false))
+ {
+ if (complain)
+ error_at (loc, "conversion of scalar %qT to vector %qT "
+ "involves truncation", type0, type1);
+ return stv_error;
+ }
+ return ret;
+ }
+ default:
+ break;
+ }
+
+ return stv_nothing;
+}
+
+/* Return the alignment of std::max_align_t.
+
+ [support.types.layout] The type max_align_t is a POD type whose alignment
+ requirement is at least as great as that of every scalar type, and whose
+ alignment requirement is supported in every context. */
+
+unsigned
+max_align_t_align ()
+{
+ unsigned int max_align = MAX (TYPE_ALIGN (long_long_integer_type_node),
+ TYPE_ALIGN (long_double_type_node));
+ if (float128_type_node != NULL_TREE)
+ max_align = MAX (max_align, TYPE_ALIGN (float128_type_node));
+ return max_align;
+}
+
+/* Return true iff ALIGN is an integral constant that is a fundamental
+ alignment, as defined by [basic.align] in the c++-11
+ specifications.
+
+ That is:
+
+ [A fundamental alignment is represented by an alignment less than or
+ equal to the greatest alignment supported by the implementation
+ in all contexts, which is equal to alignof(max_align_t)]. */
+
+bool
+cxx_fundamental_alignment_p (unsigned align)
+{
+ return (align <= max_align_t_align ());
+}
+
+/* Return true if T is a pointer to a zero-sized aggregate. */
+
+bool
+pointer_to_zero_sized_aggr_p (tree t)
+{
+ if (!POINTER_TYPE_P (t))
+ return false;
+ t = TREE_TYPE (t);
+ return (TYPE_SIZE (t) && integer_zerop (TYPE_SIZE (t)));
+}
+
+/* For an EXPR of a FUNCTION_TYPE that references a GCC built-in function
+ with no library fallback or for an ADDR_EXPR whose operand is such type
+ issues an error pointing to the location LOC.
+ Returns true when the expression has been diagnosed and false
+ otherwise. */
+
+bool
+reject_gcc_builtin (const_tree expr, location_t loc /* = UNKNOWN_LOCATION */)
+{
+ if (TREE_CODE (expr) == ADDR_EXPR)
+ expr = TREE_OPERAND (expr, 0);
+
+ STRIP_ANY_LOCATION_WRAPPER (expr);
+
+ if (TREE_TYPE (expr)
+ && TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
+ && TREE_CODE (expr) == FUNCTION_DECL
+ /* The intersection of DECL_BUILT_IN and DECL_IS_UNDECLARED_BUILTIN avoids
+ false positives for user-declared built-ins such as abs or
+ strlen, and for C++ operators new and delete.
+ The c_decl_implicit() test avoids false positives for implicitly
+ declared built-ins with library fallbacks (such as abs). */
+ && fndecl_built_in_p (expr)
+ && DECL_IS_UNDECLARED_BUILTIN (expr)
+ && !c_decl_implicit (expr)
+ && !DECL_ASSEMBLER_NAME_SET_P (expr))
+ {
+ if (loc == UNKNOWN_LOCATION)
+ loc = EXPR_LOC_OR_LOC (expr, input_location);
+
+ /* Reject arguments that are built-in functions with
+ no library fallback. */
+ error_at (loc, "built-in function %qE must be directly called", expr);
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Issue an ERROR for an invalid SIZE of array NAME which is null
+ for unnamed arrays. */
+
+void
+invalid_array_size_error (location_t loc, cst_size_error error,
+ const_tree size, const_tree name)
+{
+ tree maxsize = max_object_size ();
+ switch (error)
+ {
+ case cst_size_not_constant:
+ if (name)
+ error_at (loc, "size of array %qE is not a constant expression",
+ name);
+ else
+ error_at (loc, "size of array is not a constant expression");
+ break;
+ case cst_size_negative:
+ if (name)
+ error_at (loc, "size %qE of array %qE is negative",
+ size, name);
+ else
+ error_at (loc, "size %qE of array is negative",
+ size);
+ break;
+ case cst_size_too_big:
+ if (name)
+ error_at (loc, "size %qE of array %qE exceeds maximum "
+ "object size %qE", size, name, maxsize);
+ else
+ error_at (loc, "size %qE of array exceeds maximum "
+ "object size %qE", size, maxsize);
+ break;
+ case cst_size_overflow:
+ if (name)
+ error_at (loc, "size of array %qE exceeds maximum "
+ "object size %qE", name, maxsize);
+ else
+ error_at (loc, "size of array exceeds maximum "
+ "object size %qE", maxsize);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Check if array size calculations overflow or if the array covers more
+ than half of the address space. Return true if the size of the array
+ is valid, false otherwise. T is either the type of the array or its
+ size, and NAME is the name of the array, or null for unnamed arrays. */
+
+#if 0 // sdcpp
+bool
+valid_array_size_p (location_t loc, const_tree t, tree name, bool complain)
+{
+ if (t == error_mark_node)
+ return true;
+
+ const_tree size;
+ if (TYPE_P (t))
+ {
+ if (!COMPLETE_TYPE_P (t))
+ return true;
+ size = TYPE_SIZE_UNIT (t);
+ }
+ else
+ size = t;
+
+ if (TREE_CODE (size) != INTEGER_CST)
+ return true;
+
+ cst_size_error error;
+ if (valid_constant_size_p (size, &error))
+ return true;
+
+ if (!complain)
+ return false;
+
+ if (TREE_CODE (TREE_TYPE (size)) == ENUMERAL_TYPE)
+ /* Show the value of the enumerator rather than its name. */
+ size = convert (ssizetype, const_cast<tree> (size));
+
+ invalid_array_size_error (loc, error, size, name);
+ return false;
+}
+#endif // sdcpp
+
+/* Read SOURCE_DATE_EPOCH from environment to have a deterministic
+ timestamp to replace embedded current dates to get reproducible
+ results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */
+
+#endif // sdcpp
+
+time_t
+cb_get_source_date_epoch (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ char *source_date_epoch;
+ int64_t epoch;
+ char *endptr;
+
+ source_date_epoch = getenv ("SOURCE_DATE_EPOCH");
+ if (!source_date_epoch)
+ return (time_t) -1;
+
+ errno = 0;
+#if defined(INT64_T_IS_LONG)
+ epoch = strtol (source_date_epoch, &endptr, 10);
+#else
+ epoch = strtoll (source_date_epoch, &endptr, 10);
+#endif
+ if (errno != 0 || endptr == source_date_epoch || *endptr != '\0'
+ || epoch < 0 || epoch > MAX_SOURCE_DATE_EPOCH)
+ {
+ error_at (input_location, "environment variable %qs must "
+ "expand to a non-negative integer less than or equal to %wd",
+ "SOURCE_DATE_EPOCH", MAX_SOURCE_DATE_EPOCH);
+ return (time_t) -1;
+ }
+
+ return (time_t) epoch;
+}
+
+#if 0 // sdcpp
+
+/* Callback for libcpp for offering spelling suggestions for misspelled
+ directives. GOAL is an unrecognized string; CANDIDATES is a
+ NULL-terminated array of candidate strings. Return the closest
+ match to GOAL within CANDIDATES, or NULL if none are good
+ suggestions. */
+
+const char *
+cb_get_suggestion (cpp_reader *, const char *goal,
+ const char *const *candidates)
+{
+ best_match<const char *, const char *> bm (goal);
+ while (*candidates)
+ bm.consider (*candidates++);
+ return bm.get_best_meaningful_candidate ();
+}
+
+/* Return the latice point which is the wider of the two FLT_EVAL_METHOD
+ modes X, Y. This isn't just >, as the FLT_EVAL_METHOD values added
+ by C TS 18661-3 for interchange types that are computed in their
+ native precision are larger than the C11 values for evaluating in the
+ precision of float/double/long double. If either mode is
+ FLT_EVAL_METHOD_UNPREDICTABLE, return that. */
+
+enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method x,
+ enum flt_eval_method y)
+{
+ if (x == FLT_EVAL_METHOD_UNPREDICTABLE
+ || y == FLT_EVAL_METHOD_UNPREDICTABLE)
+ return FLT_EVAL_METHOD_UNPREDICTABLE;
+
+ /* GCC only supports one interchange type right now, _Float16. If
+ we're evaluating _Float16 in 16-bit precision, then flt_eval_method
+ will be FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16. */
+ if (x == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+ return y;
+ if (y == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+ return x;
+
+ /* Other values for flt_eval_method are directly comparable, and we want
+ the maximum. */
+ return MAX (x, y);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD in the
+ context of ISO/IEC TS 18861-3.
+
+ This relates to the effective excess precision seen by the user,
+ which is the join point of the precision the target requests for
+ -fexcess-precision={standard,fast,16} and the implicit excess precision
+ the target uses. */
+
+static enum flt_eval_method
+c_ts18661_flt_eval_method (void)
+{
+ enum flt_eval_method implicit
+ = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+ enum excess_precision_type flag_type
+ = (flag_excess_precision == EXCESS_PRECISION_STANDARD
+ ? EXCESS_PRECISION_TYPE_STANDARD
+ : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+ ? EXCESS_PRECISION_TYPE_FLOAT16
+ : EXCESS_PRECISION_TYPE_FAST));
+
+ enum flt_eval_method requested
+ = targetm.c.excess_precision (flag_type);
+
+ return excess_precision_mode_join (implicit, requested);
+}
+
+/* As c_cpp_ts18661_flt_eval_method, but clamps the expected values to
+ those that were permitted by C11. That is to say, eliminates
+ FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16. */
+
+static enum flt_eval_method
+c_c11_flt_eval_method (void)
+{
+ return excess_precision_mode_join (c_ts18661_flt_eval_method (),
+ FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD.
+ MAYBE_C11_ONLY_P is TRUE if we should check
+ FLAG_PERMITTED_EVAL_METHODS as to whether we should limit the possible
+ values we can return to those from C99/C11, and FALSE otherwise.
+ See the comments on c_ts18661_flt_eval_method for what value we choose
+ to set here. */
+
+int
+c_flt_eval_method (bool maybe_c11_only_p)
+{
+ if (maybe_c11_only_p
+ && flag_permitted_flt_eval_methods
+ == PERMITTED_FLT_EVAL_METHODS_C11)
+ return c_c11_flt_eval_method ();
+ else
+ return c_ts18661_flt_eval_method ();
+}
+
+/* An enum for get_missing_token_insertion_kind for describing the best
+ place to insert a missing token, if there is one. */
+
+enum missing_token_insertion_kind
+{
+ MTIK_IMPOSSIBLE,
+ MTIK_INSERT_BEFORE_NEXT,
+ MTIK_INSERT_AFTER_PREV
+};
+
+/* Given a missing token of TYPE, determine if it is reasonable to
+ emit a fix-it hint suggesting the insertion of the token, and,
+ if so, where the token should be inserted relative to other tokens.
+
+ It only makes sense to do this for values of TYPE that are symbols.
+
+ Some symbols should go before the next token, e.g. in:
+ if flag)
+ we want to insert the missing '(' immediately before "flag",
+ giving:
+ if (flag)
+ rather than:
+ if( flag)
+ These use MTIK_INSERT_BEFORE_NEXT.
+
+ Other symbols should go after the previous token, e.g. in:
+ if (flag
+ do_something ();
+ we want to insert the missing ')' immediately after the "flag",
+ giving:
+ if (flag)
+ do_something ();
+ rather than:
+ if (flag
+ )do_something ();
+ These use MTIK_INSERT_AFTER_PREV. */
+
+static enum missing_token_insertion_kind
+get_missing_token_insertion_kind (enum cpp_ttype type)
+{
+ switch (type)
+ {
+ /* Insert missing "opening" brackets immediately
+ before the next token. */
+ case CPP_OPEN_SQUARE:
+ case CPP_OPEN_PAREN:
+ return MTIK_INSERT_BEFORE_NEXT;
+
+ /* Insert other missing symbols immediately after
+ the previous token. */
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_SQUARE:
+ case CPP_SEMICOLON:
+ case CPP_COMMA:
+ case CPP_COLON:
+ return MTIK_INSERT_AFTER_PREV;
+
+ /* Other kinds of token don't get fix-it hints. */
+ default:
+ return MTIK_IMPOSSIBLE;
+ }
+}
+
+/* Given RICHLOC, a location for a diagnostic describing a missing token
+ of kind TOKEN_TYPE, potentially add a fix-it hint suggesting the
+ insertion of the token.
+
+ The location of the attempted fix-it hint depends on TOKEN_TYPE:
+ it will either be:
+ (a) immediately after PREV_TOKEN_LOC, or
+
+ (b) immediately before the primary location within RICHLOC (taken to
+ be that of the token following where the token was expected).
+
+ If we manage to add a fix-it hint, then the location of the
+ fix-it hint is likely to be more useful as the primary location
+ of the diagnostic than that of the following token, so we swap
+ these locations.
+
+ For example, given this bogus code:
+ 123456789012345678901234567890
+ 1 | int missing_semicolon (void)
+ 2 | {
+ 3 | return 42
+ 4 | }
+
+ we will emit:
+
+ "expected ';' before '}'"
+
+ RICHLOC's primary location is at the closing brace, so before "swapping"
+ we would emit the error at line 4 column 1:
+
+ 123456789012345678901234567890
+ 3 | return 42 |< fix-it hint emitted for this line
+ | ; |
+ 4 | } |< "expected ';' before '}'" emitted at this line
+ | ^ |
+
+ It's more useful for the location of the diagnostic to be at the
+ fix-it hint, so we swap the locations, so the primary location
+ is at the fix-it hint, with the old primary location inserted
+ as a secondary location, giving this, with the error at line 3
+ column 12:
+
+ 123456789012345678901234567890
+ 3 | return 42 |< "expected ';' before '}'" emitted at this line,
+ | ^ | with fix-it hint
+ 4 | ; |
+ | } |< secondary range emitted here
+ | ~ |. */
+
+void
+maybe_suggest_missing_token_insertion (rich_location *richloc,
+ enum cpp_ttype token_type,
+ location_t prev_token_loc)
+{
+ gcc_assert (richloc);
+
+ enum missing_token_insertion_kind mtik
+ = get_missing_token_insertion_kind (token_type);
+
+ switch (mtik)
+ {
+ default:
+ gcc_unreachable ();
+ break;
+
+ case MTIK_IMPOSSIBLE:
+ return;
+
+ case MTIK_INSERT_BEFORE_NEXT:
+ /* Attempt to add the fix-it hint before the primary location
+ of RICHLOC. */
+ richloc->add_fixit_insert_before (cpp_type2name (token_type, 0));
+ break;
+
+ case MTIK_INSERT_AFTER_PREV:
+ /* Attempt to add the fix-it hint after PREV_TOKEN_LOC. */
+ richloc->add_fixit_insert_after (prev_token_loc,
+ cpp_type2name (token_type, 0));
+ break;
+ }
+
+ /* If we were successful, use the fix-it hint's location as the
+ primary location within RICHLOC, adding the old primary location
+ back as a secondary location. */
+ if (!richloc->seen_impossible_fixit_p ())
+ {
+ fixit_hint *hint = richloc->get_last_fixit_hint ();
+ location_t hint_loc = hint->get_start_loc ();
+ location_t old_loc = richloc->get_loc ();
+
+ richloc->set_range (0, hint_loc, SHOW_RANGE_WITH_CARET);
+ richloc->add_range (old_loc);
+ }
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that fold_for_warn on error_mark_node is safe. */
+
+static void
+test_fold_for_warn ()
+{
+ ASSERT_EQ (error_mark_node, fold_for_warn (error_mark_node));
+}
+
+/* Run all of the selftests within this file. */
+
+static void
+c_common_cc_tests ()
+{
+ test_fold_for_warn ();
+}
+
+/* Run all of the tests within c-family. */
+
+void
+c_family_tests (void)
+{
+ c_common_cc_tests ();
+ c_format_cc_tests ();
+ c_indentation_cc_tests ();
+ c_pretty_print_cc_tests ();
+ c_spellcheck_cc_tests ();
+ c_diagnostic_cc_tests ();
+ c_opt_problem_cc_tests ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+/* Attempt to locate a suitable location within FILE for a
+ #include directive to be inserted before.
+ LOC is the location of the relevant diagnostic.
+
+ Attempt to return the location within FILE immediately
+ after the last #include within that file, or the start of
+ that file if it has no #include directives.
+
+ Return UNKNOWN_LOCATION if no suitable location is found,
+ or if an error occurs. */
+
+static location_t
+try_to_locate_new_include_insertion_point (const char *file, location_t loc)
+{
+ /* Locate the last ordinary map within FILE that ended with a #include. */
+ const line_map_ordinary *last_include_ord_map = NULL;
+
+ /* ...and the next ordinary map within FILE after that one. */
+ const line_map_ordinary *last_ord_map_after_include = NULL;
+
+ /* ...and the first ordinary map within FILE. */
+ const line_map_ordinary *first_ord_map_in_file = NULL;
+
+ /* Get ordinary map containing LOC (or its expansion). */
+ const line_map_ordinary *ord_map_for_loc = NULL;
+ linemap_resolve_location (line_table, loc, LRK_MACRO_EXPANSION_POINT,
+ &ord_map_for_loc);
+ gcc_assert (ord_map_for_loc);
+
+ for (unsigned int i = 0; i < LINEMAPS_ORDINARY_USED (line_table); i++)
+ {
+ const line_map_ordinary *ord_map
+ = LINEMAPS_ORDINARY_MAP_AT (line_table, i);
+
+ if (const line_map_ordinary *from
+ = linemap_included_from_linemap (line_table, ord_map))
+ /* We cannot use pointer equality, because with preprocessed
+ input all filename strings are unique. */
+ if (0 == strcmp (from->to_file, file))
+ {
+ last_include_ord_map = from;
+ last_ord_map_after_include = NULL;
+ }
+
+ /* Likewise, use strcmp, and reject any line-zero introductory
+ map. */
+ if (ord_map->to_line && 0 == strcmp (ord_map->to_file, file))
+ {
+ if (!first_ord_map_in_file)
+ first_ord_map_in_file = ord_map;
+ if (last_include_ord_map && !last_ord_map_after_include)
+ last_ord_map_after_include = ord_map;
+ }
+
+ /* Stop searching when reaching the ord_map containing LOC,
+ as it makes no sense to provide fix-it hints that appear
+ after the diagnostic in question. */
+ if (ord_map == ord_map_for_loc)
+ break;
+ }
+
+ /* Determine where to insert the #include. */
+ const line_map_ordinary *ord_map_for_insertion;
+
+ /* We want the next ordmap in the file after the last one that's a
+ #include, but failing that, the start of the file. */
+ if (last_ord_map_after_include)
+ ord_map_for_insertion = last_ord_map_after_include;
+ else
+ ord_map_for_insertion = first_ord_map_in_file;
+
+ if (!ord_map_for_insertion)
+ return UNKNOWN_LOCATION;
+
+ /* The "start_location" is column 0, meaning "the whole line".
+ rich_location and edit_context can't cope with this, so use
+ column 1 instead. */
+ location_t col_0 = ord_map_for_insertion->start_location;
+ return linemap_position_for_loc_and_offset (line_table, col_0, 1);
+}
+
+/* A map from filenames to sets of headers added to them, for
+ ensuring idempotency within maybe_add_include_fixit. */
+
+/* The values within the map. We need string comparison as there's
+ no guarantee that two different diagnostics that are recommending
+ adding e.g. "<stdio.h>" are using the same buffer. */
+
+typedef hash_set <const char *, false, nofree_string_hash> per_file_includes_t;
+
+/* The map itself. We don't need string comparison for the filename keys,
+ as they come from libcpp. */
+
+typedef hash_map <const char *, per_file_includes_t *> added_includes_t;
+static added_includes_t *added_includes;
+
+/* Attempt to add a fix-it hint to RICHLOC, adding "#include HEADER\n"
+ in a suitable location within the file of RICHLOC's primary
+ location.
+
+ This function is idempotent: a header will be added at most once to
+ any given file.
+
+ If OVERRIDE_LOCATION is true, then if a fix-it is added and will be
+ printed, then RICHLOC's primary location will be replaced by that of
+ the fix-it hint (for use by "inform" notes where the location of the
+ issue has already been reported). */
+
+void
+maybe_add_include_fixit (rich_location *richloc, const char *header,
+ bool override_location)
+{
+ location_t loc = richloc->get_loc ();
+ const char *file = LOCATION_FILE (loc);
+ if (!file)
+ return;
+
+ /* Idempotency: don't add the same header more than once to a given file. */
+ if (!added_includes)
+ added_includes = new added_includes_t ();
+ per_file_includes_t *&set = added_includes->get_or_insert (file);
+ if (set)
+ if (set->contains (header))
+ /* ...then we've already added HEADER to that file. */
+ return;
+ if (!set)
+ set = new per_file_includes_t ();
+ set->add (header);
+
+ /* Attempt to locate a suitable place for the new directive. */
+ location_t include_insert_loc
+ = try_to_locate_new_include_insertion_point (file, loc);
+ if (include_insert_loc == UNKNOWN_LOCATION)
+ return;
+
+ char *text = xasprintf ("#include %s\n", header);
+ richloc->add_fixit_insert_before (include_insert_loc, text);
+ free (text);
+
+ if (override_location && global_dc->show_caret)
+ {
+ /* Replace the primary location with that of the insertion point for the
+ fix-it hint.
+
+ We use SHOW_LINES_WITHOUT_RANGE so that we don't meaningless print a
+ caret for the insertion point (or colorize it).
+
+ Hence we print e.g.:
+
+ ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2
+ 73 | # include <debug/vector>
+ +++ |+#include <vector>
+ 74 | #endif
+
+ rather than:
+
+ ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:74:1: note: msg 2
+ 73 | # include <debug/vector>
+ +++ |+#include <vector>
+ 74 | #endif
+ | ^
+
+ avoiding the caret on the first column of line 74. */
+ richloc->set_range (0, include_insert_loc, SHOW_LINES_WITHOUT_RANGE);
+ }
+}
+
+/* Attempt to convert a braced array initializer list CTOR for array
+ TYPE into a STRING_CST for convenience and efficiency. Return
+ the converted string on success or the original ctor on failure. */
+
+static tree
+braced_list_to_string (tree type, tree ctor, bool member)
+{
+ /* Ignore non-members with unknown size like arrays with unspecified
+ bound. */
+ tree typesize = TYPE_SIZE_UNIT (type);
+ if (!member && !tree_fits_uhwi_p (typesize))
+ return ctor;
+
+ /* If the target char size differes 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;
+
+ /* 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
+ a designator, as in:
+ const char a[] = { [7] = 0 }; */
+ unsigned HOST_WIDE_INT maxelts;
+ if (typesize)
+ {
+ maxelts = tree_to_uhwi (typesize);
+ maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ }
+ else
+ maxelts = HOST_WIDE_INT_M1U;
+
+ /* Avoid converting initializers for zero-length arrays (but do
+ create them for flexible array members). */
+ if (!maxelts)
+ return ctor;
+
+ unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+ auto_vec<char> str;
+ str.reserve (nelts + 1);
+
+ unsigned HOST_WIDE_INT i;
+ tree index, value;
+
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+ {
+ unsigned HOST_WIDE_INT idx = i;
+ if (index)
+ {
+ if (!tree_fits_uhwi_p (index))
+ return ctor;
+ idx = tree_to_uhwi (index);
+ }
+
+ /* auto_vec is limited to UINT_MAX elements. */
+ if (idx > UINT_MAX)
+ return ctor;
+
+ /* Avoid non-constant initializers. */
+ if (!tree_fits_shwi_p (value))
+ return ctor;
+
+ /* Skip over embedded nuls except the last one (initializer
+ elements are in ascending order of indices). */
+ HOST_WIDE_INT val = tree_to_shwi (value);
+ if (!val && i + 1 < nelts)
+ continue;
+
+ if (idx < str.length())
+ return ctor;
+
+ /* Bail if the CTOR has a block of more than 256 embedded nuls
+ due to implicitly initialized elements. */
+ unsigned nchars = (idx - str.length ()) + 1;
+ if (nchars > 256)
+ return ctor;
+
+ if (nchars > 1)
+ {
+ str.reserve (idx);
+ str.quick_grow_cleared (idx);
+ }
+
+ if (idx >= maxelts)
+ return ctor;
+
+ str.safe_insert (idx, val);
+ }
+
+ /* Append a nul string termination. */
+ if (maxelts != HOST_WIDE_INT_M1U && str.length () < maxelts)
+ str.safe_push (0);
+
+ /* Build a STRING_CST with the same type as the array. */
+ tree res = build_string (str.length (), str.begin ());
+ TREE_TYPE (res) = type;
+ return res;
+}
+
+/* Implementation of the two-argument braced_lists_to_string withe
+ the same arguments plus MEMBER which is set for struct members
+ to allow initializers for flexible member arrays. */
+
+static tree
+braced_lists_to_strings (tree type, tree ctor, bool member)
+{
+ if (TREE_CODE (ctor) != CONSTRUCTOR)
+ return ctor;
+
+ tree_code code = TREE_CODE (type);
+
+ tree ttp;
+ if (code == ARRAY_TYPE)
+ ttp = TREE_TYPE (type);
+ else if (code == RECORD_TYPE)
+ {
+ ttp = TREE_TYPE (ctor);
+ if (TREE_CODE (ttp) == ARRAY_TYPE)
+ {
+ type = ttp;
+ ttp = TREE_TYPE (ttp);
+ }
+ }
+ else
+ return ctor;
+
+ if ((TREE_CODE (ttp) == ARRAY_TYPE || TREE_CODE (ttp) == INTEGER_TYPE)
+ && TYPE_STRING_FLAG (ttp))
+ return braced_list_to_string (type, ctor, member);
+
+ code = TREE_CODE (ttp);
+ if (code == ARRAY_TYPE || RECORD_OR_UNION_TYPE_P (ttp))
+ {
+ bool rec = RECORD_OR_UNION_TYPE_P (ttp);
+
+ /* Handle array of arrays or struct member initializers. */
+ tree val;
+ unsigned HOST_WIDE_INT idx;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), idx, val)
+ {
+ val = braced_lists_to_strings (ttp, val, rec);
+ CONSTRUCTOR_ELT (ctor, idx)->value = val;
+ }
+ }
+
+ return ctor;
+}
+
+/* Attempt to convert a CTOR containing braced array initializer lists
+ for array TYPE into one containing STRING_CSTs, for convenience and
+ efficiency. Recurse for arrays of arrays and member initializers.
+ Return the converted CTOR or STRING_CST on success or the original
+ CTOR otherwise. */
+
+tree
+braced_lists_to_strings (tree type, tree ctor)
+{
+ return braced_lists_to_strings (type, ctor, false);
+}
+
+
+/* Emit debug for functions before finalizing early debug. */
+#endif // sdcpp
+
+void
+c_common_finalize_early_debug (void)
+{
+ gcc_assert(0 && "common dbg");
+#if 0 // sdcpp
+ /* Emit early debug for reachable functions, and by consequence,
+ locally scoped symbols. Also emit debug for extern declared
+ functions that are still reachable at this point. */
+ struct cgraph_node *cnode;
+ FOR_EACH_FUNCTION (cnode)
+ if (!cnode->alias && !cnode->thunk
+ && (cnode->has_gimple_body_p ()
+ || !DECL_IS_UNDECLARED_BUILTIN (cnode->decl)))
+ (*debug_hooks->early_global_decl) (cnode->decl);
+#endif
+}
+
+// #include "gt-c-family-c-common.h"
diff --git a/support/cpp/gcc/c-family/c-common.def b/support/cpp/gcc/c-family/c-common.def
new file mode 100644
index 000000000..0759ace5f
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-common.def
@@ -0,0 +1,89 @@
+/* This file contains the definitions and documentation for the
+ additional tree codes used in the GNU C compiler (see tree.def
+ for the standard codes).
+ Copyright (C) 1987-2022 Free Software Foundation, Inc.
+ Written by Benjamin Chelf <chelf@codesourcery.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.
+
+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/>. */
+
+/* Tree nodes used in the C frontend. These are also shared with the
+ C++ and Objective C frontends. */
+
+/* A C_MAYBE_CONST_EXPR, currently only used for C and Objective C,
+ tracks information about constancy of an expression and VLA type
+ sizes or VM expressions from typeof that need to be evaluated
+ before the main expression. It is used during parsing and removed
+ in c_fully_fold. C_MAYBE_CONST_EXPR_PRE is the expression to
+ evaluate first, if not NULL; C_MAYBE_CONST_EXPR_EXPR is the main
+ expression. If C_MAYBE_CONST_EXPR_INT_OPERANDS is set then the
+ expression may be used in an unevaluated part of an integer
+ constant expression, but not in an evaluated part. If
+ C_MAYBE_CONST_EXPR_NON_CONST is set then the expression contains
+ something that cannot occur in an evaluated part of a constant
+ expression (or outside of sizeof in C90 mode); otherwise it does
+ not. */
+DEFTREECODE (C_MAYBE_CONST_EXPR, "c_maybe_const_expr", tcc_expression, 2)
+
+/* An EXCESS_PRECISION_EXPR, currently only used for C and Objective
+ C, represents an expression evaluated in greater range or precision
+ than its type. The type of the EXCESS_PRECISION_EXPR is the
+ semantic type while the operand represents what is actually being
+ evaluated. */
+DEFTREECODE (EXCESS_PRECISION_EXPR, "excess_precision_expr", tcc_expression, 1)
+
+/* Used to represent a user-defined literal.
+ The operands are an IDENTIFIER for the suffix, the VALUE of the literal,
+ and for numeric literals the original string representation of the
+ number. */
+DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3)
+
+/* Represents a 'sizeof' expression during C++ template expansion,
+ or for the purpose of -Wsizeof-pointer-memaccess warning. */
+DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1)
+
+/* Like above, but enclosed in parentheses. Used to suppress warnings. */
+DEFTREECODE (PAREN_SIZEOF_EXPR, "paren_sizeof_expr", tcc_expression, 1)
+
+/* Used to represent a `for' statement. The operands are
+ FOR_INIT_STMT, FOR_COND, FOR_EXPR, FOR_BODY, and FOR_SCOPE,
+ respectively. */
+DEFTREECODE (FOR_STMT, "for_stmt", tcc_statement, 5)
+
+/* Used to represent a 'while' statement. The operands are WHILE_COND
+ and WHILE_BODY, respectively. */
+DEFTREECODE (WHILE_STMT, "while_stmt", tcc_statement, 2)
+
+/* Used to represent a 'do' statement. The operands are DO_COND and
+ DO_BODY, respectively. */
+DEFTREECODE (DO_STMT, "do_stmt", tcc_statement, 2)
+
+/* Used to represent a 'break' statement. */
+DEFTREECODE (BREAK_STMT, "break_stmt", tcc_statement, 0)
+
+/* Used to represent a 'continue' statement. */
+DEFTREECODE (CONTINUE_STMT, "continue_stmt", tcc_statement, 0)
+
+/* Used to represent a 'switch' statement. The operands are
+ SWITCH_STMT_COND, SWITCH_STMT_BODY, SWITCH_STMT_TYPE, and
+ SWITCH_STMT_SCOPE, respectively. */
+DEFTREECODE (SWITCH_STMT, "switch_stmt", tcc_statement, 4)
+
+/*
+Local variables:
+mode:c
+End:
+*/
diff --git a/support/cpp/gcc/c-family/c-common.h b/support/cpp/gcc/c-family/c-common.h
new file mode 100644
index 000000000..35fa56cc1
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-common.h
@@ -0,0 +1,1541 @@
+/* Definitions for c-common.cc.
+ 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/>. */
+
+#ifndef GCC_C_COMMON_H
+#define GCC_C_COMMON_H
+
+#include "splay-tree.h"
+#include "cpplib.h"
+#include "alias.h"
+#include "tree.h"
+#include "fold-const.h"
+// sdcpp #include "wide-int-bitmask.h"
+
+/* In order for the format checking to accept the C frontend
+ diagnostic framework extensions, you must include this file before
+ diagnostic-core.h, not after. The C front end formats are a subset of those
+ for C++, so they are the appropriate set to use in common code;
+ cp-tree.h overrides this for C++. */
+#if defined(GCC_DIAGNOSTIC_CORE_H)
+#error \
+In order for the format checking to accept the C front end diagnostic \
+framework extensions, you must include this file before diagnostic-core.h \
+never after.
+#endif
+#ifndef GCC_DIAG_STYLE
+#define GCC_DIAG_STYLE __gcc_cdiag__
+#endif
+#include "diagnostic-core.h"
+
+/* Usage of TREE_LANG_FLAG_?:
+ 0: IDENTIFIER_MARKED (used by search routines).
+ C_MAYBE_CONST_EXPR_INT_OPERANDS (in C_MAYBE_CONST_EXPR, for C)
+ 1: C_DECLARED_LABEL_FLAG (in LABEL_DECL)
+ STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST)
+ C_MAYBE_CONST_EXPR_NON_CONST (in C_MAYBE_CONST_EXPR, for C)
+ 2: unused
+ 3: STATEMENT_LIST_HAS_LABEL (in STATEMENT_LIST)
+ 4: unused
+*/
+
+/* Reserved identifiers. This is the union of all the keywords for C,
+ C++, and Objective-C. All the type modifiers have to be in one
+ block at the beginning, because they are used as mask bits. There
+ are 28 type modifiers; if we add many more we will have to redesign
+ the mask mechanism. */
+
+enum rid
+{
+ /* Modifiers: */
+ /* C, in empirical order of frequency. */
+ RID_STATIC = 0,
+ RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN,
+ RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
+ RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
+ RID_NORETURN, RID_ATOMIC,
+
+ /* C extensions */
+ RID_COMPLEX, RID_THREAD, RID_SAT,
+
+ /* C++ */
+ RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE,
+
+ /* ObjC ("PQ" reserved words - they do not appear after a '@' and
+ are keywords only in specific contexts) */
+ RID_IN, RID_OUT, RID_INOUT, RID_BYCOPY, RID_BYREF, RID_ONEWAY,
+
+ /* ObjC ("PATTR" reserved words - they do not appear after a '@'
+ and are keywords only as property attributes) */
+ RID_GETTER, RID_SETTER,
+ RID_READONLY, RID_READWRITE,
+ RID_ASSIGN, RID_RETAIN, RID_COPY,
+ RID_PROPATOMIC, RID_NONATOMIC,
+
+ /* ObjC nullability support keywords that also can appear in the
+ property attribute context. These values should remain contiguous
+ with the other property attributes. */
+ RID_NULL_UNSPECIFIED, RID_NULLABLE, RID_NONNULL, RID_NULL_RESETTABLE,
+
+ /* C (reserved and imaginary types not implemented, so any use is a
+ syntax error) */
+ RID_IMAGINARY,
+
+ /* C */
+ RID_INT, RID_CHAR, RID_FLOAT, RID_DOUBLE, RID_VOID,
+ RID_ENUM, RID_STRUCT, RID_UNION, RID_IF, RID_ELSE,
+ RID_WHILE, RID_DO, RID_FOR, RID_SWITCH, RID_CASE,
+ RID_DEFAULT, RID_BREAK, RID_CONTINUE, RID_RETURN, RID_GOTO,
+ RID_SIZEOF,
+
+ /* C extensions */
+ RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG,
+ RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
+ RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE,
+ RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH,
+ RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER,
+ RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
+
+ /* TS 18661-3 keywords, in the same sequence as the TI_* values. */
+ RID_FLOAT16,
+ RID_FLOATN_NX_FIRST = RID_FLOAT16,
+ RID_FLOAT32,
+ RID_FLOAT64,
+ RID_FLOAT128,
+ RID_FLOAT32X,
+ RID_FLOAT64X,
+ RID_FLOAT128X,
+#define CASE_RID_FLOATN_NX \
+ case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128: \
+ case RID_FLOAT32X: case RID_FLOAT64X: case RID_FLOAT128X
+
+ RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
+
+ /* "__GIMPLE", for the GIMPLE-parsing extension to the C frontend. */
+ RID_GIMPLE,
+
+ /* "__PHI", for parsing PHI function in GIMPLE FE. */
+ RID_PHI,
+
+ /* "__RTL", for the RTL-parsing extension to the C frontend. */
+ RID_RTL,
+
+ /* C11 */
+ RID_ALIGNAS, RID_GENERIC,
+
+ /* This means to warn that this is a C++ keyword, and then treat it
+ as a normal identifier. */
+ RID_CXX_COMPAT_WARN,
+
+ /* GNU transactional memory extension */
+ RID_TRANSACTION_ATOMIC, RID_TRANSACTION_RELAXED, RID_TRANSACTION_CANCEL,
+
+ /* Too many ways of getting the name of a function as a string */
+ RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,
+
+ /* C++ (some of these are keywords in Objective-C as well, but only
+ if they appear after a '@') */
+ RID_BOOL, RID_WCHAR, RID_CLASS,
+ RID_PUBLIC, RID_PRIVATE, RID_PROTECTED,
+ RID_TEMPLATE, RID_NULL, RID_CATCH,
+ RID_DELETE, RID_FALSE, RID_NAMESPACE,
+ RID_NEW, RID_OFFSETOF, RID_OPERATOR,
+ RID_THIS, RID_THROW, RID_TRUE,
+ RID_TRY, RID_TYPENAME, RID_TYPEID,
+ RID_USING, RID_CHAR16, RID_CHAR32,
+
+ /* casts */
+ RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
+
+ /* C++ extensions */
+ RID_ADDRESSOF, RID_BASES,
+ RID_BUILTIN_LAUNDER, RID_DIRECT_BASES,
+ RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
+ RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
+ RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
+ RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_UNIQUE_OBJ_REPRESENTATIONS,
+ RID_HAS_VIRTUAL_DESTRUCTOR, RID_BUILTIN_BIT_CAST,
+ RID_IS_ABSTRACT, RID_IS_AGGREGATE,
+ RID_IS_BASE_OF, RID_IS_CLASS,
+ RID_IS_EMPTY, RID_IS_ENUM,
+ RID_IS_FINAL, RID_IS_LAYOUT_COMPATIBLE,
+ RID_IS_LITERAL_TYPE,
+ RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF,
+ RID_IS_POD, RID_IS_POLYMORPHIC,
+ RID_IS_SAME_AS,
+ RID_IS_STD_LAYOUT, RID_IS_TRIVIAL,
+ RID_IS_TRIVIALLY_ASSIGNABLE, RID_IS_TRIVIALLY_CONSTRUCTIBLE,
+ RID_IS_TRIVIALLY_COPYABLE,
+ RID_IS_UNION, RID_UNDERLYING_TYPE,
+ RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE,
+ RID_IS_NOTHROW_ASSIGNABLE, RID_IS_NOTHROW_CONSTRUCTIBLE,
+
+ /* C++11 */
+ RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
+
+ /* C++20 */
+ RID_CONSTINIT, RID_CONSTEVAL,
+
+ /* char8_t */
+ RID_CHAR8,
+
+ /* C++ concepts */
+ RID_CONCEPT, RID_REQUIRES,
+
+ /* C++ modules. */
+ RID__MODULE, RID__IMPORT, RID__EXPORT, /* Internal tokens. */
+
+ /* C++ coroutines */
+ RID_CO_AWAIT, RID_CO_YIELD, RID_CO_RETURN,
+
+ /* C++ transactional memory. */
+ RID_ATOMIC_NOEXCEPT, RID_ATOMIC_CANCEL, RID_SYNCHRONIZED,
+
+ /* Objective-C ("AT" reserved words - they are only keywords when
+ they follow '@') */
+ RID_AT_ENCODE, RID_AT_END,
+ RID_AT_CLASS, RID_AT_ALIAS, RID_AT_DEFS,
+ RID_AT_PRIVATE, RID_AT_PROTECTED, RID_AT_PUBLIC, RID_AT_PACKAGE,
+ RID_AT_PROTOCOL, RID_AT_SELECTOR,
+ RID_AT_THROW, RID_AT_TRY, RID_AT_CATCH,
+ RID_AT_FINALLY, RID_AT_SYNCHRONIZED,
+ RID_AT_OPTIONAL, RID_AT_REQUIRED, RID_AT_PROPERTY,
+ RID_AT_SYNTHESIZE, RID_AT_DYNAMIC,
+ RID_AT_INTERFACE,
+ RID_AT_IMPLEMENTATION,
+
+ /* Named address support, mapping the keyword to a particular named address
+ number. Named address space 0 is reserved for the generic address. If
+ there are more than 254 named addresses, the addr_space_t type will need
+ to be grown from an unsigned char to unsigned short. */
+ RID_ADDR_SPACE_0, /* generic address */
+ RID_ADDR_SPACE_1,
+ RID_ADDR_SPACE_2,
+ RID_ADDR_SPACE_3,
+ RID_ADDR_SPACE_4,
+ RID_ADDR_SPACE_5,
+ RID_ADDR_SPACE_6,
+ RID_ADDR_SPACE_7,
+ RID_ADDR_SPACE_8,
+ RID_ADDR_SPACE_9,
+ RID_ADDR_SPACE_10,
+ RID_ADDR_SPACE_11,
+ RID_ADDR_SPACE_12,
+ RID_ADDR_SPACE_13,
+ RID_ADDR_SPACE_14,
+ RID_ADDR_SPACE_15,
+
+ RID_FIRST_ADDR_SPACE = RID_ADDR_SPACE_0,
+ RID_LAST_ADDR_SPACE = RID_ADDR_SPACE_15,
+
+ /* __intN keywords. The _N_M here doesn't correspond to the intN
+ in the keyword; use the bitsize in int_n_t_data_t[M] for that.
+ For example, if int_n_t_data_t[0].bitsize is 13, then RID_INT_N_0
+ is for __int13. */
+
+ /* Note that the range to use is RID_FIRST_INT_N through
+ RID_FIRST_INT_N + NUM_INT_N_ENTS - 1 and c-parser.cc has a list of
+ all RID_INT_N_* in a case statement. */
+
+ RID_INT_N_0,
+ RID_INT_N_1,
+ RID_INT_N_2,
+ RID_INT_N_3,
+
+ RID_FIRST_INT_N = RID_INT_N_0,
+ RID_LAST_INT_N = RID_INT_N_3,
+
+ RID_MAX,
+
+ RID_FIRST_MODIFIER = RID_STATIC,
+ RID_LAST_MODIFIER = RID_ONEWAY,
+
+ RID_FIRST_CXX11 = RID_CONSTEXPR,
+ RID_LAST_CXX11 = RID_STATIC_ASSERT,
+ RID_FIRST_CXX20 = RID_CONSTINIT,
+ RID_LAST_CXX20 = RID_CONSTINIT,
+ RID_FIRST_AT = RID_AT_ENCODE,
+ RID_LAST_AT = RID_AT_IMPLEMENTATION,
+ RID_FIRST_PQ = RID_IN,
+ RID_LAST_PQ = RID_ONEWAY,
+ RID_FIRST_PATTR = RID_GETTER,
+ RID_LAST_PATTR = RID_NULL_RESETTABLE
+};
+
+#define OBJC_IS_AT_KEYWORD(rid) \
+ ((unsigned int) (rid) >= (unsigned int) RID_FIRST_AT && \
+ (unsigned int) (rid) <= (unsigned int) RID_LAST_AT)
+
+#define OBJC_IS_PQ_KEYWORD(rid) \
+ ((unsigned int) (rid) >= (unsigned int) RID_FIRST_PQ && \
+ (unsigned int) (rid) <= (unsigned int) RID_LAST_PQ)
+
+/* Keywords permitted in an @property attribute context. */
+#define OBJC_IS_PATTR_KEYWORD(rid) \
+ ((((unsigned int) (rid) >= (unsigned int) RID_FIRST_PATTR && \
+ (unsigned int) (rid) <= (unsigned int) RID_LAST_PATTR)) \
+ || rid == RID_CLASS)
+
+/* OBJC_IS_CXX_KEYWORD recognizes the 'CXX_OBJC' keywords (such as
+ 'class') which are shared in a subtle way between Objective-C and
+ C++. When the lexer is lexing in Objective-C/Objective-C++, if it
+ finds '@' followed by one of these identifiers (eg, '@class'), it
+ recognizes the whole as an Objective-C keyword. If the identifier
+ is found elsewhere, it follows the rules of the C/C++ language.
+ */
+#define OBJC_IS_CXX_KEYWORD(rid) \
+ (rid == RID_CLASS || rid == RID_SYNCHRONIZED \
+ || rid == RID_PUBLIC || rid == RID_PROTECTED || rid == RID_PRIVATE \
+ || rid == RID_TRY || rid == RID_THROW || rid == RID_CATCH)
+
+/* The elements of `ridpointers' are identifier nodes for the reserved
+ type names and storage classes. It is indexed by a RID_... value. */
+extern GTY ((length ("(int) RID_MAX"))) tree *ridpointers;
+
+/* Standard named or nameless data types of the C compiler. */
+
+enum c_tree_index
+{
+ CTI_CHAR8_TYPE,
+ CTI_CHAR16_TYPE,
+ CTI_CHAR32_TYPE,
+ CTI_WCHAR_TYPE,
+ CTI_UNDERLYING_WCHAR_TYPE,
+ CTI_WINT_TYPE,
+ CTI_SIGNED_SIZE_TYPE, /* For format checking only. */
+ CTI_UNSIGNED_PTRDIFF_TYPE, /* For format checking only. */
+ CTI_INTMAX_TYPE,
+ CTI_UINTMAX_TYPE,
+ CTI_WIDEST_INT_LIT_TYPE,
+ CTI_WIDEST_UINT_LIT_TYPE,
+
+ /* Types for <stdint.h>, that may not be defined on all
+ targets. */
+ CTI_SIG_ATOMIC_TYPE,
+ CTI_INT8_TYPE,
+ CTI_INT16_TYPE,
+ CTI_INT32_TYPE,
+ CTI_INT64_TYPE,
+ CTI_UINT8_TYPE,
+ CTI_UINT16_TYPE,
+ CTI_UINT32_TYPE,
+ CTI_UINT64_TYPE,
+ CTI_INT_LEAST8_TYPE,
+ CTI_INT_LEAST16_TYPE,
+ CTI_INT_LEAST32_TYPE,
+ CTI_INT_LEAST64_TYPE,
+ CTI_UINT_LEAST8_TYPE,
+ CTI_UINT_LEAST16_TYPE,
+ CTI_UINT_LEAST32_TYPE,
+ CTI_UINT_LEAST64_TYPE,
+ CTI_INT_FAST8_TYPE,
+ CTI_INT_FAST16_TYPE,
+ CTI_INT_FAST32_TYPE,
+ CTI_INT_FAST64_TYPE,
+ CTI_UINT_FAST8_TYPE,
+ CTI_UINT_FAST16_TYPE,
+ CTI_UINT_FAST32_TYPE,
+ CTI_UINT_FAST64_TYPE,
+ CTI_INTPTR_TYPE,
+ CTI_UINTPTR_TYPE,
+
+ CTI_CHAR_ARRAY_TYPE,
+ CTI_CHAR8_ARRAY_TYPE,
+ CTI_CHAR16_ARRAY_TYPE,
+ CTI_CHAR32_ARRAY_TYPE,
+ CTI_WCHAR_ARRAY_TYPE,
+ CTI_STRING_TYPE,
+ CTI_CONST_STRING_TYPE,
+
+ /* Type for boolean expressions (bool in C++, int in C). */
+ CTI_TRUTHVALUE_TYPE,
+ CTI_TRUTHVALUE_TRUE,
+ CTI_TRUTHVALUE_FALSE,
+
+ CTI_DEFAULT_FUNCTION_TYPE,
+
+ CTI_NULL,
+
+ /* These are not types, but we have to look them up all the time. */
+ CTI_FUNCTION_NAME_DECL,
+ CTI_PRETTY_FUNCTION_NAME_DECL,
+ CTI_C99_FUNCTION_NAME_DECL,
+
+ CTI_MODULE_HWM,
+ /* Below here entities change during compilation. */
+
+ CTI_SAVED_FUNCTION_NAME_DECLS,
+
+ CTI_MAX
+};
+
+#if 0 // sdcpp
+#define C_CPP_HASHNODE(id) \
+ (&(((struct c_common_identifier *) (id))->node))
+#define C_RID_CODE(id) \
+ ((enum rid) (((struct c_common_identifier *) (id))->node.rid_code))
+#define C_SET_RID_CODE(id, code) \
+ (((struct c_common_identifier *) (id))->node.rid_code = (unsigned char) code)
+
+/* Identifier part common to the C front ends. Inherits from
+ tree_identifier, despite appearances. */
+#endif // sdcpp
+struct GTY(()) c_common_identifier {
+ struct tree_common common;
+ struct cpp_hashnode node;
+};
+
+/* An entry in the reserved keyword table. */
+
+struct c_common_resword
+{
+ const char *const word;
+ ENUM_BITFIELD(rid) const rid : 16;
+ const unsigned int disable : 16;
+};
+
+/* Mode used to build pointers (VOIDmode means ptr_mode). */
+
+extern machine_mode c_default_pointer_mode;
+
+/* Extra cpp_ttype values for C++. */
+
+/* A token type for template-ids. If a template-id is processed while
+ parsing tentatively, it is replaced with a CPP_TEMPLATE_ID token;
+ the value of the CPP_TEMPLATE_ID is whatever was returned by
+ cp_parser_template_id. */
+#define CPP_TEMPLATE_ID ((enum cpp_ttype) (CPP_KEYWORD + 1))
+
+/* A token type for nested-name-specifiers. If a
+ nested-name-specifier is processed while parsing tentatively, it is
+ replaced with a CPP_NESTED_NAME_SPECIFIER token; the value of the
+ CPP_NESTED_NAME_SPECIFIER is whatever was returned by
+ cp_parser_nested_name_specifier_opt. */
+#define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1))
+
+/* A token type for pre-parsed C++0x decltype. */
+#define CPP_DECLTYPE ((enum cpp_ttype) (CPP_NESTED_NAME_SPECIFIER + 1))
+
+/* A token type for pre-parsed primary-expression (lambda- or statement-). */
+#define CPP_PREPARSED_EXPR ((enum cpp_ttype) (CPP_DECLTYPE + 1))
+
+/* The number of token types, including C++-specific ones. */
+#define N_CP_TTYPES ((int) (CPP_PREPARSED_EXPR + 1))
+
+/* Disable mask. Keywords are disabled if (reswords[i].disable &
+ mask) is _true_. Thus for keywords which are present in all
+ languages the disable field is zero. */
+
+#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_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS
+#define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T
+#define D_CXX_MODULES_FLAGS (D_CXXONLY | D_CXX_MODULES)
+#define D_CXX_COROUTINES_FLAGS (D_CXXONLY | D_CXX_COROUTINES)
+
+/* The reserved keyword table. */
+extern const struct c_common_resword c_common_reswords[];
+
+/* The number of items in the reserved keyword table. */
+extern const unsigned int num_c_common_reswords;
+
+#define char8_type_node c_global_trees[CTI_CHAR8_TYPE]
+#define char16_type_node c_global_trees[CTI_CHAR16_TYPE]
+#define char32_type_node c_global_trees[CTI_CHAR32_TYPE]
+#define wchar_type_node c_global_trees[CTI_WCHAR_TYPE]
+#define underlying_wchar_type_node c_global_trees[CTI_UNDERLYING_WCHAR_TYPE]
+#define wint_type_node c_global_trees[CTI_WINT_TYPE]
+#define signed_size_type_node c_global_trees[CTI_SIGNED_SIZE_TYPE]
+#define unsigned_ptrdiff_type_node c_global_trees[CTI_UNSIGNED_PTRDIFF_TYPE]
+#define intmax_type_node c_global_trees[CTI_INTMAX_TYPE]
+#define uintmax_type_node c_global_trees[CTI_UINTMAX_TYPE]
+#define widest_integer_literal_type_node c_global_trees[CTI_WIDEST_INT_LIT_TYPE]
+#define widest_unsigned_literal_type_node c_global_trees[CTI_WIDEST_UINT_LIT_TYPE]
+
+#define sig_atomic_type_node c_global_trees[CTI_SIG_ATOMIC_TYPE]
+#define int8_type_node c_global_trees[CTI_INT8_TYPE]
+#define int16_type_node c_global_trees[CTI_INT16_TYPE]
+#define int32_type_node c_global_trees[CTI_INT32_TYPE]
+#define int64_type_node c_global_trees[CTI_INT64_TYPE]
+#define uint8_type_node c_global_trees[CTI_UINT8_TYPE]
+#define c_uint16_type_node c_global_trees[CTI_UINT16_TYPE]
+#define c_uint32_type_node c_global_trees[CTI_UINT32_TYPE]
+#define c_uint64_type_node c_global_trees[CTI_UINT64_TYPE]
+#define int_least8_type_node c_global_trees[CTI_INT_LEAST8_TYPE]
+#define int_least16_type_node c_global_trees[CTI_INT_LEAST16_TYPE]
+#define int_least32_type_node c_global_trees[CTI_INT_LEAST32_TYPE]
+#define int_least64_type_node c_global_trees[CTI_INT_LEAST64_TYPE]
+#define uint_least8_type_node c_global_trees[CTI_UINT_LEAST8_TYPE]
+#define uint_least16_type_node c_global_trees[CTI_UINT_LEAST16_TYPE]
+#define uint_least32_type_node c_global_trees[CTI_UINT_LEAST32_TYPE]
+#define uint_least64_type_node c_global_trees[CTI_UINT_LEAST64_TYPE]
+#define int_fast8_type_node c_global_trees[CTI_INT_FAST8_TYPE]
+#define int_fast16_type_node c_global_trees[CTI_INT_FAST16_TYPE]
+#define int_fast32_type_node c_global_trees[CTI_INT_FAST32_TYPE]
+#define int_fast64_type_node c_global_trees[CTI_INT_FAST64_TYPE]
+#define uint_fast8_type_node c_global_trees[CTI_UINT_FAST8_TYPE]
+#define uint_fast16_type_node c_global_trees[CTI_UINT_FAST16_TYPE]
+#define uint_fast32_type_node c_global_trees[CTI_UINT_FAST32_TYPE]
+#define uint_fast64_type_node c_global_trees[CTI_UINT_FAST64_TYPE]
+#define intptr_type_node c_global_trees[CTI_INTPTR_TYPE]
+#define uintptr_type_node c_global_trees[CTI_UINTPTR_TYPE]
+
+#define truthvalue_type_node c_global_trees[CTI_TRUTHVALUE_TYPE]
+#define truthvalue_true_node c_global_trees[CTI_TRUTHVALUE_TRUE]
+#define truthvalue_false_node c_global_trees[CTI_TRUTHVALUE_FALSE]
+
+#define char_array_type_node c_global_trees[CTI_CHAR_ARRAY_TYPE]
+#define char8_array_type_node c_global_trees[CTI_CHAR8_ARRAY_TYPE]
+#define char16_array_type_node c_global_trees[CTI_CHAR16_ARRAY_TYPE]
+#define char32_array_type_node c_global_trees[CTI_CHAR32_ARRAY_TYPE]
+#define wchar_array_type_node c_global_trees[CTI_WCHAR_ARRAY_TYPE]
+#define string_type_node c_global_trees[CTI_STRING_TYPE]
+#define const_string_type_node c_global_trees[CTI_CONST_STRING_TYPE]
+
+#define default_function_type c_global_trees[CTI_DEFAULT_FUNCTION_TYPE]
+
+#define function_name_decl_node c_global_trees[CTI_FUNCTION_NAME_DECL]
+#define pretty_function_name_decl_node c_global_trees[CTI_PRETTY_FUNCTION_NAME_DECL]
+#define c99_function_name_decl_node c_global_trees[CTI_C99_FUNCTION_NAME_DECL]
+#define saved_function_name_decls c_global_trees[CTI_SAVED_FUNCTION_NAME_DECLS]
+
+/* The node for C++ `__null'. */
+#define null_node c_global_trees[CTI_NULL]
+
+extern GTY(()) tree c_global_trees[CTI_MAX];
+
+/* Mark which labels are explicitly declared.
+ These may be shadowed, and may be referenced from nested functions. */
+#define C_DECLARED_LABEL_FLAG(label) TREE_LANG_FLAG_1 (label)
+
+enum c_language_kind
+{
+ clk_c = 0, /* C90, C94, C99, C11 or C2X */
+ clk_objc = 1, /* clk_c with ObjC features. */
+ clk_cxx = 2, /* ANSI/ISO C++ */
+ clk_objcxx = 3 /* clk_cxx with ObjC features. */
+};
+
+/* To test for a specific language use c_language, defined by each
+ front end. For "ObjC features" or "not C++" use the macros. */
+extern c_language_kind c_language;
+
+#define c_dialect_cxx() ((c_language & clk_cxx) != 0)
+#define c_dialect_objc() ((c_language & clk_objc) != 0)
+
+/* The various name of operator that appears in error messages. */
+enum ref_operator {
+ /* NULL */
+ RO_NULL,
+ /* array indexing */
+ RO_ARRAY_INDEXING,
+ /* unary * */
+ RO_UNARY_STAR,
+ /* -> */
+ RO_ARROW,
+ /* implicit conversion */
+ RO_IMPLICIT_CONVERSION,
+ /* ->* */
+ RO_ARROW_STAR
+};
+
+/* Information about a statement tree. */
+
+struct GTY(()) stmt_tree_s {
+ /* A stack of statement lists being collected. */
+ vec<tree, va_gc> *x_cur_stmt_list;
+
+ /* In C++, Nonzero if we should treat statements as full
+ expressions. In particular, this variable is non-zero if at the
+ end of a statement we should destroy any temporaries created
+ during that statement. Similarly, if, at the end of a block, we
+ should destroy any local variables in this block. Normally, this
+ variable is nonzero, since those are the normal semantics of
+ C++.
+
+ This flag has no effect in C. */
+ int stmts_are_full_exprs_p;
+};
+
+typedef struct stmt_tree_s *stmt_tree;
+
+/* Global state pertinent to the current function. Some C dialects
+ extend this structure with additional fields. */
+
+struct GTY(()) c_language_function {
+ /* While we are parsing the function, this contains information
+ about the statement-tree that we are building. */
+ struct stmt_tree_s x_stmt_tree;
+
+ /* Vector of locally defined typedefs, for
+ -Wunused-local-typedefs. */
+ vec<tree, va_gc> *local_typedefs;
+};
+
+#define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
+
+/* When building a statement-tree, this is the current statement list
+ being collected. */
+#define cur_stmt_list (stmt_list_stack->last ())
+
+#define building_stmt_list_p() (stmt_list_stack && !stmt_list_stack->is_empty())
+
+/* Language-specific hooks. */
+
+/* If non-NULL, this function is called after a precompile header file
+ is loaded. */
+extern void (*lang_post_pch_load) (void);
+
+extern void push_file_scope (void);
+extern void pop_file_scope (void);
+extern stmt_tree current_stmt_tree (void);
+extern tree push_stmt_list (void);
+extern tree pop_stmt_list (tree);
+extern tree add_stmt (tree);
+extern void push_cleanup (tree, tree, bool);
+
+// sdcpp extern tree build_modify_expr (location_t, tree, tree, enum tree_code,
+// sdcpp location_t, tree, tree);
+extern tree build_indirect_ref (location_t, tree, ref_operator);
+
+extern bool has_c_linkage (const_tree decl);
+extern bool c_decl_implicit (const_tree);
+
+/* Switches common to the C front ends. */
+
+/* Nonzero means don't output line number information. */
+
+extern char flag_no_line_commands;
+
+/* Nonzero causes -E output not to be done, but directives such as
+ #define that have side effects are still obeyed. */
+
+extern char flag_no_output;
+
+/* Nonzero means dump macros in some fashion; contains the 'D', 'M',
+ 'N' or 'U' of the command line switch. */
+
+extern char flag_dump_macros;
+
+/* Nonzero means pass #include lines through to the output. */
+
+extern char flag_dump_includes;
+
+/* Nonzero means process PCH files while preprocessing. */
+
+extern bool flag_pch_preprocess;
+
+/* The file name to which we should write a precompiled header, or
+ NULL if no header will be written in this compile. */
+
+extern const char *pch_file;
+
+/* Nonzero if an ISO standard was selected. It rejects macros in the
+ user's namespace. */
+
+extern int flag_iso;
+
+/* C/ObjC language option variables. */
+
+
+/* Nonzero means allow type mismatches in conditional expressions;
+ just make their values `void'. */
+
+extern int flag_cond_mismatch;
+
+/* Nonzero means enable C89 Amendment 1 features. */
+
+extern int flag_isoc94;
+
+/* Nonzero means use the ISO C99 (or later) dialect of C. */
+
+extern int flag_isoc99;
+
+/* Nonzero means use the ISO C11 (or later) dialect of C. */
+
+extern int flag_isoc11;
+
+/* Nonzero means use the ISO C2X dialect of C. */
+
+extern int flag_isoc2x;
+
+/* Nonzero means that we have builtin functions, and main is an int. */
+
+extern int flag_hosted;
+
+/* ObjC language option variables. */
+
+
+/* Tells the compiler that this is a special run. Do not perform any
+ compiling, instead we are to test some platform dependent features
+ and output a C header file with appropriate definitions. */
+
+extern int print_struct_values;
+
+/* Tells the compiler what is the constant string class for ObjC. */
+
+extern const char *constant_string_class_name;
+
+
+/* C++ language option variables. */
+
+/* The reference version of the ABI for -Wabi. */
+
+extern int warn_abi_version;
+
+/* Return TRUE if one of {flag_abi_version,flag_abi_compat_version} is
+ less than N and the other is at least N. */
+#define abi_compat_version_crosses(N) \
+ (abi_version_at_least(N) \
+ != (flag_abi_compat_version == 0 \
+ || flag_abi_compat_version >= (N)))
+
+/* Return TRUE if one of {flag_abi_version,warn_abi_version} is
+ less than N and the other is at least N, for use by -Wabi. */
+#define abi_version_crosses(N) \
+ (abi_version_at_least(N) \
+ != (warn_abi_version == 0 \
+ || warn_abi_version >= (N)))
+
+/* The supported C++ dialects. */
+
+enum cxx_dialect {
+ cxx_unset,
+ /* C++98 with TC1 */
+ cxx98,
+ cxx03 = cxx98,
+ /* C++11 */
+ cxx0x,
+ cxx11 = cxx0x,
+ /* C++14 */
+ cxx14,
+ /* C++17 */
+ cxx17,
+ /* C++20 */
+ cxx20,
+ /* C++23 */
+ cxx23
+};
+
+/* The C++ dialect being used. C++98 is the default. */
+extern enum cxx_dialect cxx_dialect;
+
+/* Maximum template instantiation depth. This limit is rather
+ arbitrary, but it exists to limit the time it takes to notice
+ excessively recursive template instantiations. */
+
+extern int max_tinst_depth;
+
+/* Nonzero means that we should not issue warnings about problems that
+ occur when the code is executed, because the code being processed
+ is not expected to be executed. This is set during parsing. This
+ is used for cases like sizeof() and "0 ? a : b". This is a count,
+ not a bool, because unexecuted expressions can nest. */
+
+extern int c_inhibit_evaluation_warnings;
+
+/* Whether lexing has been completed, so subsequent preprocessor
+ errors should use the compiler's input_location. */
+
+extern bool done_lexing;
+
+/* C types are partitioned into three subsets: object, function, and
+ incomplete types. */
+#define C_TYPE_OBJECT_P(type) \
+ (TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type))
+
+#define C_TYPE_INCOMPLETE_P(type) \
+ (TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type) == 0)
+
+#define C_TYPE_FUNCTION_P(type) \
+ (TREE_CODE (type) == FUNCTION_TYPE)
+
+/* For convenience we define a single macro to identify the class of
+ object or incomplete types. */
+#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
+ (!C_TYPE_FUNCTION_P (type))
+
+/* Return true if TYPE is a vector type that should be subject to the GNU
+ vector extensions (as opposed to a vector type that is used only for
+ the purposes of defining target-specific built-in functions). */
+
+#if 0 // sdcpp
+inline bool
+gnu_vector_type_p (const_tree type)
+{
+ return TREE_CODE (type) == VECTOR_TYPE && !TYPE_INDIVISIBLE_P (type);
+}
+#endif
+
+struct visibility_flags
+{
+ unsigned inpragma : 1; /* True when in #pragma GCC visibility. */
+ unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */
+};
+
+/* These enumerators are possible types of unsafe conversions. */
+enum conversion_safety {
+ /* The conversion is safe. */
+ SAFE_CONVERSION = 0,
+ /* Another type of conversion with problems. */
+ UNSAFE_OTHER,
+ /* Conversion between signed and unsigned integers. */
+ UNSAFE_SIGN,
+ /* Conversions that reduce the precision of reals including conversions
+ from reals to integers. */
+ UNSAFE_REAL,
+ /* Conversions from complex to reals or integers, that discard imaginary
+ component. */
+ UNSAFE_IMAGINARY
+};
+
+/* Global visibility options. */
+extern struct visibility_flags visibility_options;
+
+/* Attribute table common to the C front ends. */
+extern const struct attribute_spec c_common_attribute_table[];
+extern const struct attribute_spec c_common_format_attribute_table[];
+
+/* Pointer to function to lazily generate the VAR_DECL for __FUNCTION__ etc.
+ ID is the identifier to use, NAME is the string.
+ TYPE_DEP indicates whether it depends on type of the function or not
+ (i.e. __PRETTY_FUNCTION__). */
+
+extern tree (*make_fname_decl) (location_t, tree, int);
+
+/* In c-decl.cc and cp/tree.cc. FIXME. */
+extern void c_register_addr_space (const char *str, addr_space_t as);
+
+/* In c-common.cc. */
+extern bool in_late_binary_op;
+extern const char *c_addr_space_name (addr_space_t as);
+extern tree identifier_global_value (tree);
+extern tree identifier_global_tag (tree);
+extern bool names_builtin_p (const char *);
+extern tree c_linkage_bindings (tree);
+extern void record_builtin_type (enum rid, const char *, tree);
+extern tree build_void_list_node (void);
+extern void start_fname_decls (void);
+extern void finish_fname_decls (void);
+extern const char *fname_as_string (int);
+extern tree fname_decl (location_t, unsigned, tree);
+
+extern int check_user_alignment (const_tree, bool, bool);
+extern bool check_function_arguments (location_t loc, const_tree, const_tree,
+ int, tree *, vec<location_t> *);
+// sdcpp extern void check_function_arguments_recurse (void (*)
+// sdcpp (void *, tree,
+// sdcpp unsigned HOST_WIDE_INT),
+// sdcpp void *, tree,
+// sdcpp unsigned HOST_WIDE_INT,
+// sdcpp opt_code);
+extern bool check_builtin_function_arguments (location_t, vec<location_t>,
+ tree, tree, int, tree *);
+extern void check_function_format (const_tree, tree, int, tree *,
+ vec<location_t> *);
+extern bool attribute_fallthrough_p (tree);
+extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
+extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
+extern bool c_common_handle_option (size_t, const char *, HOST_WIDE_INT, int,
+ location_t,
+ const struct cl_option_handlers *);
+extern bool default_handle_c_option (size_t, const char *, int);
+extern tree c_common_type_for_mode (machine_mode, int);
+extern tree c_common_type_for_size (unsigned int, int);
+extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
+ int, int);
+extern tree c_common_unsigned_type (tree);
+extern tree c_common_signed_type (tree);
+extern tree c_common_signed_or_unsigned_type (int, tree);
+extern void c_common_init_ts (void);
+extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
+extern enum conversion_safety unsafe_conversion_p (tree, tree, tree, bool);
+extern bool decl_with_nonnull_addr_p (const_tree);
+extern tree c_fully_fold (tree, bool, bool *, bool = false);
+extern tree c_wrap_maybe_const (tree, bool);
+extern tree c_common_truthvalue_conversion (location_t, tree);
+extern void c_apply_type_quals_to_decl (int, tree);
+extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int);
+extern tree c_alignof_expr (location_t, tree);
+/* Print an error message for invalid operands to arith operation CODE.
+ NOP_EXPR is used as a special case (see truthvalue_conversion). */
+// sdcpp extern void binary_op_error (rich_location *, enum tree_code, tree, tree);
+extern tree fix_string_type (tree);
+extern tree convert_and_check (location_t, tree, tree, bool = false);
+extern bool c_determine_visibility (tree);
+extern bool vector_types_compatible_elements_p (tree, tree);
+extern void mark_valid_location_for_stdc_pragma (bool);
+extern bool valid_location_for_stdc_pragma_p (void);
+extern void set_float_const_decimal64 (void);
+extern void clear_float_const_decimal64 (void);
+extern bool float_const_decimal64_p (void);
+
+extern bool keyword_begins_type_specifier (enum rid);
+extern bool keyword_is_storage_class_specifier (enum rid);
+extern bool keyword_is_type_qualifier (enum rid);
+extern bool keyword_is_decl_specifier (enum rid);
+extern unsigned max_align_t_align (void);
+extern bool cxx_fundamental_alignment_p (unsigned);
+extern bool pointer_to_zero_sized_aggr_p (tree);
+extern bool bool_promoted_to_int_p (tree);
+extern tree fold_for_warn (tree);
+extern tree c_common_get_narrower (tree, int *);
+extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *);
+extern void c_common_finalize_early_debug (void);
+
+/* Used by convert_and_check; in front ends. */
+extern tree convert_init (tree, tree);
+
+#define c_sizeof(LOC, T) c_sizeof_or_alignof_type (LOC, T, true, false, 1)
+#define c_alignof(LOC, T) c_sizeof_or_alignof_type (LOC, T, false, false, 1)
+
+/* Subroutine of build_binary_op, used for certain operations. */
+extern tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise);
+
+/* Subroutine of build_binary_op, used for comparison operations.
+ See if the operands have both been converted from subword integer types
+ and, if so, perhaps change them both back to their original type. */
+// sdcpp extern tree shorten_compare (location_t, tree *, tree *, tree *,
+// sdcpp enum tree_code *);
+
+// sdcpp extern tree pointer_int_sum (location_t, enum tree_code, tree, tree,
+// sdcpp bool = true);
+
+/* Add qualifiers to a type, in the fashion for C. */
+// sdcpp extern tree c_build_qualified_type (tree, int, tree = NULL_TREE, size_t = 0);
+
+/* Build tree nodes and builtin functions common to both C and C++ language
+ frontends. */
+extern void c_common_nodes_and_builtins (void);
+
+extern void disable_builtin_function (const char *);
+
+extern void set_compound_literal_name (tree decl);
+
+extern tree build_va_arg (location_t, tree, tree);
+
+extern const unsigned int c_family_lang_mask;
+extern unsigned int c_common_option_lang_mask (void);
+extern void c_common_diagnostics_set_defaults (diagnostic_context *);
+extern bool c_common_complain_wrong_lang_p (const struct cl_option *);
+extern void c_common_init_options_struct (struct gcc_options *);
+extern void c_common_init_options (unsigned int, struct cl_decoded_option *);
+extern bool c_common_post_options (const char **);
+extern bool c_common_init (void);
+extern void c_common_finish (void);
+extern void c_common_parse_file (void);
+extern FILE *get_dump_info (int, dump_flags_t *);
+extern alias_set_type c_common_get_alias_set (tree);
+extern void c_register_builtin_type (tree, const char*);
+extern bool c_promoting_integer_type_p (const_tree);
+extern bool self_promoting_args_p (const_tree);
+extern tree strip_pointer_operator (tree);
+extern tree strip_pointer_or_array_types (tree);
+extern HOST_WIDE_INT c_common_to_target_charset (HOST_WIDE_INT);
+
+/* This is the basic parsing function. */
+extern void c_parse_file (void);
+
+extern void c_parse_final_cleanups (void);
+
+/* These macros provide convenient access to the various _STMT nodes. */
+
+/* Nonzero if a given STATEMENT_LIST represents the outermost binding
+ if a statement expression. */
+#define STATEMENT_LIST_STMT_EXPR(NODE) \
+ TREE_LANG_FLAG_1 (STATEMENT_LIST_CHECK (NODE))
+
+/* Nonzero if a label has been added to the statement list. */
+#define STATEMENT_LIST_HAS_LABEL(NODE) \
+ TREE_LANG_FLAG_3 (STATEMENT_LIST_CHECK (NODE))
+
+/* C_MAYBE_CONST_EXPR accessors. */
+#define C_MAYBE_CONST_EXPR_PRE(NODE) \
+ TREE_OPERAND (C_MAYBE_CONST_EXPR_CHECK (NODE), 0)
+#define C_MAYBE_CONST_EXPR_EXPR(NODE) \
+ TREE_OPERAND (C_MAYBE_CONST_EXPR_CHECK (NODE), 1)
+#define C_MAYBE_CONST_EXPR_INT_OPERANDS(NODE) \
+ TREE_LANG_FLAG_0 (C_MAYBE_CONST_EXPR_CHECK (NODE))
+#define C_MAYBE_CONST_EXPR_NON_CONST(NODE) \
+ TREE_LANG_FLAG_1 (C_MAYBE_CONST_EXPR_CHECK (NODE))
+#define EXPR_INT_CONST_OPERANDS(EXPR) \
+ (INTEGRAL_TYPE_P (TREE_TYPE (EXPR)) \
+ && (TREE_CODE (EXPR) == INTEGER_CST \
+ || (TREE_CODE (EXPR) == C_MAYBE_CONST_EXPR \
+ && C_MAYBE_CONST_EXPR_INT_OPERANDS (EXPR))))
+
+/* In a FIELD_DECL, nonzero if the decl was originally a bitfield. */
+#define DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) == 1)
+#define SET_DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 1)
+#define CLEAR_DECL_C_BIT_FIELD(NODE) \
+ (DECL_LANG_FLAG_4 (FIELD_DECL_CHECK (NODE)) = 0)
+
+/* True if the decl was an unnamed bitfield. */
+#define DECL_UNNAMED_BIT_FIELD(NODE) \
+ (DECL_C_BIT_FIELD (NODE) && !DECL_NAME (NODE))
+
+extern tree do_case (location_t, tree, tree);
+// extern tree build_stmt (location_t, enum tree_code, ...);
+// extern tree build_real_imag_expr (location_t, enum tree_code, tree);
+
+/* These functions must be defined by each front-end which implements
+ a variant of the C language. They are used in c-common.cc. */
+
+// extern tree build_unary_op (location_t, enum tree_code, tree, bool);
+// extern tree build_binary_op (location_t, enum tree_code, tree, tree, bool);
+extern tree perform_integral_promotions (tree);
+
+/* These functions must be defined by each front-end which implements
+ a variant of the C language. They are used by port files. */
+
+extern tree default_conversion (tree);
+
+/* Given two integer or real types, return the type for their sum.
+ Given two compatible ANSI C types, returns the merged type. */
+
+extern tree common_type (tree, tree);
+
+extern tree decl_constant_value (tree);
+
+/* Handle increment and decrement of boolean types. */
+// sdcpp 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 bool c_switch_covers_all_cases_p (splay_tree, tree);
+extern bool c_block_may_fallthru (const_tree);
+
+extern tree build_function_call (location_t, tree, tree);
+
+// sdcpp extern tree build_function_call_vec (location_t, vec<location_t>, tree,
+// sdcpp vec<tree, va_gc> *, vec<tree, va_gc> *,
+// sdcpp tree = NULL_TREE);
+
+extern tree resolve_overloaded_builtin (location_t, tree, vec<tree, va_gc> *);
+
+extern tree finish_label_address_expr (tree, location_t);
+
+/* Same function prototype, but the C and C++ front ends have
+ different implementations. Used in c-common.cc. */
+extern tree lookup_label (tree);
+extern tree lookup_name (tree);
+extern bool lvalue_p (const_tree);
+
+extern bool vector_targets_convertible_p (const_tree t1, const_tree t2);
+extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note);
+extern tree c_build_vec_perm_expr (location_t, tree, tree, tree, bool = true);
+extern tree c_build_shufflevector (location_t, tree, tree,
+ const vec<tree> &, bool = true);
+extern tree c_build_vec_convert (location_t, tree, location_t, tree, bool = true);
+
+extern void init_c_lex (void);
+
+extern void c_cpp_builtins (cpp_reader *);
+extern void c_cpp_builtins_optimize_pragma (cpp_reader *, tree, tree);
+extern bool c_cpp_diagnostic (cpp_reader *, enum cpp_diagnostic_level,
+ enum cpp_warning_reason, rich_location *,
+ const char *, va_list *)
+ ATTRIBUTE_GCC_DIAG(5,0);
+extern int c_common_has_attribute (cpp_reader *, bool);
+extern int c_common_has_builtin (cpp_reader *);
+
+extern bool parse_optimize_options (tree, bool);
+
+/* Positive if an implicit `extern "C"' scope has just been entered;
+ negative if such a scope has just been exited. */
+extern GTY(()) int pending_lang_change;
+
+/* Information recorded about each file examined during compilation. */
+
+struct c_fileinfo
+{
+ int time; /* Time spent in the file. */
+
+ /* Flags used only by C++.
+ INTERFACE_ONLY nonzero means that we are in an "interface" section
+ of the compiler. INTERFACE_UNKNOWN nonzero means we cannot trust
+ the value of INTERFACE_ONLY. If INTERFACE_UNKNOWN is zero and
+ INTERFACE_ONLY is zero, it means that we are responsible for
+ exporting definitions that others might need. */
+ short interface_only;
+ short interface_unknown;
+};
+
+struct c_fileinfo *get_fileinfo (const char *);
+extern void dump_time_statistics (void);
+
+extern bool c_dump_tree (void *, tree);
+
+extern void verify_sequence_points (tree);
+
+// sdcpp extern tree fold_offsetof (tree, tree = size_type_node,
+// sdcpp tree_code ctx = ERROR_MARK);
+
+extern int complete_array_type (tree *, tree, bool);
+extern void complete_flexible_array_elts (tree);
+
+extern tree builtin_type_for_size (int, bool);
+
+extern void c_common_mark_addressable_vec (tree);
+
+extern void set_underlying_type (tree);
+extern bool user_facing_original_type_p (const_tree);
+extern void record_types_used_by_current_var_decl (tree);
+extern vec<tree, va_gc> *make_tree_vector (void);
+extern void release_tree_vector (vec<tree, va_gc> *);
+extern vec<tree, va_gc> *make_tree_vector_single (tree);
+extern vec<tree, va_gc> *make_tree_vector_from_list (tree);
+extern vec<tree, va_gc> *make_tree_vector_from_ctor (tree);
+extern vec<tree, va_gc> *make_tree_vector_copy (const vec<tree, va_gc> *);
+
+/* Used for communication between c_common_type_for_mode and
+ c_register_builtin_type. */
+extern GTY(()) tree registered_builtin_types;
+
+/* Read SOURCE_DATE_EPOCH from environment to have a deterministic
+ timestamp to replace embedded current dates to get reproducible
+ results. Returns -1 if SOURCE_DATE_EPOCH is not defined. */
+extern time_t cb_get_source_date_epoch (cpp_reader *pfile);
+
+/* The value (as a unix timestamp) corresponds to date
+ "Dec 31 9999 23:59:59 UTC", which is the latest date that __DATE__ and
+ __TIME__ can store. */
+#define MAX_SOURCE_DATE_EPOCH HOST_WIDE_INT_C (253402300799)
+
+/* Callback for libcpp for offering spelling suggestions for misspelled
+ directives. */
+extern const char *cb_get_suggestion (cpp_reader *, const char *,
+ const char *const *);
+
+extern GTY(()) string_concat_db *g_string_concat_db;
+
+class substring_loc;
+extern const char *c_get_substring_location (const substring_loc &substr_loc,
+ location_t *out_loc);
+
+/* In c-gimplify.cc. */
+typedef struct bc_state
+{
+ tree bc_label[2];
+} bc_state_t;
+extern void save_bc_state (bc_state_t *);
+extern void restore_bc_state (bc_state_t *);
+// sdcpp extern tree c_genericize_control_stmt (tree *, int *, void *,
+// sdcpp walk_tree_fn, walk_tree_lh);
+extern void c_genericize (tree);
+extern int c_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+extern tree c_build_bind_expr (location_t, tree, tree);
+
+/* In c-lex.cc. */
+extern enum cpp_ttype
+conflict_marker_get_final_tok_kind (enum cpp_ttype tok1_kind);
+
+/* In c-pch.cc */
+extern void pch_init (void);
+extern void pch_cpp_save_state (void);
+extern int c_common_valid_pch (cpp_reader *pfile, const char *name, int fd);
+extern void c_common_read_pch (cpp_reader *pfile, const char *name, int fd,
+ const char *orig);
+extern void c_common_write_pch (void);
+extern void c_common_no_more_pch (void);
+extern void c_common_pch_pragma (cpp_reader *pfile, const char *);
+
+/* In *-checksum.c */
+extern const unsigned char executable_checksum[16];
+
+/* In c-cppbuiltin.cc */
+extern void builtin_define_std (const char *macro);
+extern void builtin_define_with_value (const char *, const char *, int);
+extern void builtin_define_with_int_value (const char *, HOST_WIDE_INT);
+extern void builtin_define_type_sizeof (const char *, tree);
+extern void c_stddef_cpp_builtins (void);
+#endif // sdcpp
+extern void fe_file_change (const line_map_ordinary *);
+extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char,
+ rich_location *richloc);
+
+/* In c-ppoutput.cc */
+extern void init_pp_output (FILE *);
+extern void preprocess_file (cpp_reader *);
+extern void pp_file_change (const line_map_ordinary *);
+extern void pp_dir_change (cpp_reader *, const char *);
+extern bool check_missing_format_attribute (tree, tree);
+#if 0 // sdcpp
+
+/* In c-omp.cc */
+typedef wide_int_bitmask omp_clause_mask;
+
+#define OMP_CLAUSE_MASK_1 omp_clause_mask (1)
+
+enum c_omp_clause_split
+{
+ C_OMP_CLAUSE_SPLIT_TARGET = 0,
+ C_OMP_CLAUSE_SPLIT_TEAMS,
+ C_OMP_CLAUSE_SPLIT_DISTRIBUTE,
+ C_OMP_CLAUSE_SPLIT_PARALLEL,
+ C_OMP_CLAUSE_SPLIT_FOR,
+ C_OMP_CLAUSE_SPLIT_SIMD,
+ C_OMP_CLAUSE_SPLIT_COUNT,
+ C_OMP_CLAUSE_SPLIT_SECTIONS = C_OMP_CLAUSE_SPLIT_FOR,
+ C_OMP_CLAUSE_SPLIT_TASKLOOP = C_OMP_CLAUSE_SPLIT_FOR,
+ C_OMP_CLAUSE_SPLIT_LOOP = C_OMP_CLAUSE_SPLIT_FOR,
+ C_OMP_CLAUSE_SPLIT_MASKED = C_OMP_CLAUSE_SPLIT_DISTRIBUTE
+};
+
+enum c_omp_region_type
+{
+ C_ORT_OMP = 1 << 0,
+ C_ORT_ACC = 1 << 1,
+ C_ORT_DECLARE_SIMD = 1 << 2,
+ C_ORT_TARGET = 1 << 3,
+ C_ORT_OMP_DECLARE_SIMD = C_ORT_OMP | C_ORT_DECLARE_SIMD,
+ C_ORT_OMP_TARGET = C_ORT_OMP | C_ORT_TARGET
+};
+
+extern tree c_finish_omp_master (location_t, tree);
+extern tree c_finish_omp_masked (location_t, tree, tree);
+extern tree c_finish_omp_taskgroup (location_t, tree, tree);
+extern tree c_finish_omp_critical (location_t, tree, tree, tree);
+extern tree c_finish_omp_ordered (location_t, tree, tree);
+extern void c_finish_omp_barrier (location_t);
+// sdcpp extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code,
+// sdcpp tree, tree, tree, tree, tree, tree, bool,
+// sdcpp enum omp_memory_order, bool, bool = false);
+extern bool c_omp_depend_t_p (tree);
+// sdcpp extern void c_finish_omp_depobj (location_t, tree, enum omp_clause_depend_kind,
+// sdcpp tree);
+extern void c_finish_omp_flush (location_t, int);
+extern void c_finish_omp_taskwait (location_t);
+extern void c_finish_omp_taskyield (location_t);
+// sdcpp extern tree c_finish_omp_for (location_t, enum tree_code, tree, tree, tree,
+// sdcpp tree, tree, tree, tree, bool);
+// sdcpp extern bool c_omp_check_loop_iv (tree, tree, walk_tree_lh);
+// sdcpp extern bool c_omp_check_loop_iv_exprs (location_t, enum tree_code, tree, int,
+// sdcpp tree, tree, tree, walk_tree_lh);
+extern tree c_finish_oacc_wait (location_t, tree, tree);
+extern tree c_oacc_split_loop_clauses (tree, tree *, bool);
+// sdcpp extern void c_omp_split_clauses (location_t, enum tree_code, omp_clause_mask,
+// sdcpp tree, tree *);
+extern tree c_omp_declare_simd_clauses_to_numbers (tree, tree);
+extern void c_omp_declare_simd_clauses_to_decls (tree, tree);
+extern bool c_omp_predefined_variable (tree);
+// sdcpp extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree);
+// sdcpp extern enum omp_clause_defaultmap_kind c_omp_predetermined_mapping (tree);
+extern tree c_omp_check_context_selector (location_t, tree);
+extern void c_omp_mark_declare_variant (location_t, tree, tree);
+extern void c_omp_adjust_map_clauses (tree, bool);
+
+enum c_omp_directive_kind {
+ C_OMP_DIR_STANDALONE,
+ C_OMP_DIR_CONSTRUCT,
+ C_OMP_DIR_DECLARATIVE,
+ C_OMP_DIR_UTILITY,
+ C_OMP_DIR_INFORMATIONAL
+};
+
+struct c_omp_directive {
+ const char *first, *second, *third;
+ unsigned int id;
+ enum c_omp_directive_kind kind;
+ bool simd;
+};
+
+extern const struct c_omp_directive *c_omp_categorize_directive (const char *,
+ const char *,
+ const char *);
+
+/* Return next tree in the chain for chain_next walking of tree nodes. */
+#if 0 // sdcpp
+static inline tree
+c_tree_chain_next (tree t)
+{
+ /* TREE_CHAIN of a type is TYPE_STUB_DECL, which is different
+ kind of object, never a long chain of nodes. Prefer
+ TYPE_NEXT_VARIANT for types. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPE_COMMON))
+ return TYPE_NEXT_VARIANT (t);
+ /* Otherwise, if there is TREE_CHAIN, return it. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
+ return TREE_CHAIN (t);
+ return NULL;
+}
+#endif // sdcpp
+
+/* Mask used by tm_stmt_attr. */
+#define TM_STMT_ATTR_OUTER 2
+#define TM_STMT_ATTR_ATOMIC 4
+#define TM_STMT_ATTR_RELAXED 8
+
+/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these
+ are ordered specifically such that more restrictive attributes are
+ at lower bit positions. This fact is known by the C++ tm attribute
+ inheritance code such that least bit extraction (mask & -mask) results
+ in the most restrictive attribute. */
+#define TM_ATTR_SAFE 1
+#define TM_ATTR_CALLABLE 2
+#define TM_ATTR_PURE 4
+#define TM_ATTR_IRREVOCABLE 8
+#define TM_ATTR_MAY_CANCEL_OUTER 16
+
+/* A suffix-identifier value doublet that represents user-defined literals
+ for C++-0x. */
+enum overflow_type {
+ OT_UNDERFLOW = -1,
+ OT_NONE,
+ OT_OVERFLOW
+};
+
+#if 0 // sdcpp
+struct GTY(()) tree_userdef_literal {
+ struct tree_base base;
+ tree suffix_id;
+ tree value;
+ tree num_string;
+ enum overflow_type overflow;
+};
+
+#define USERDEF_LITERAL_SUFFIX_ID(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id)
+
+#define USERDEF_LITERAL_VALUE(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
+
+#define USERDEF_LITERAL_OVERFLOW(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->overflow)
+
+#define USERDEF_LITERAL_NUM_STRING(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
+
+#define USERDEF_LITERAL_TYPE(NODE) \
+ (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
+
+extern tree build_userdef_literal (tree suffix_id, tree value,
+ enum overflow_type overflow,
+ tree num_string);
+#endif // sdcpp
+
+
+/* WHILE_STMT accessors. These give access to the condition of the
+ while statement and the body of the while statement, respectively. */
+#define WHILE_COND(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 0)
+#define WHILE_BODY(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 1)
+
+/* DO_STMT accessors. These give access to the condition of the do
+ statement and the body of the do statement, respectively. */
+#define DO_COND(NODE) TREE_OPERAND (DO_STMT_CHECK (NODE), 0)
+#define DO_BODY(NODE) TREE_OPERAND (DO_STMT_CHECK (NODE), 1)
+
+/* FOR_STMT accessors. These give access to the init statement,
+ condition, update expression, and body of the for statement,
+ respectively. */
+#define FOR_INIT_STMT(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 0)
+#define FOR_COND(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 1)
+#define FOR_EXPR(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 2)
+#define FOR_BODY(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 3)
+#define FOR_SCOPE(NODE) TREE_OPERAND (FOR_STMT_CHECK (NODE), 4)
+
+#define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
+#define SWITCH_STMT_BODY(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1)
+#define SWITCH_STMT_TYPE(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 2)
+#define SWITCH_STMT_SCOPE(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 3)
+/* True if there are case labels for all possible values of switch cond, either
+ because there is a default: case label or because the case label ranges cover
+ all values. */
+#define SWITCH_STMT_ALL_CASES_P(NODE) \
+ TREE_LANG_FLAG_0 (SWITCH_STMT_CHECK (NODE))
+/* True if the body of a switch stmt contains no BREAK_STMTs. */
+#define SWITCH_STMT_NO_BREAK_P(NODE) \
+ TREE_LANG_FLAG_2 (SWITCH_STMT_CHECK (NODE))
+
+
+/* Nonzero if NODE is the target for genericization of 'break' stmts. */
+#define LABEL_DECL_BREAK(NODE) \
+ DECL_LANG_FLAG_0 (LABEL_DECL_CHECK (NODE))
+
+/* Nonzero if NODE is the target for genericization of 'continue' stmts. */
+#define LABEL_DECL_CONTINUE(NODE) \
+ DECL_LANG_FLAG_1 (LABEL_DECL_CHECK (NODE))
+
+extern bool convert_vector_to_array_for_subscript (location_t, tree *, tree);
+
+/* Possibe cases of scalar_to_vector conversion. */
+enum stv_conv {
+ stv_error, /* Error occurred. */
+ stv_nothing, /* Nothing happened. */
+ stv_firstarg, /* First argument must be expanded. */
+ stv_secondarg /* Second argument must be expanded. */
+};
+
+// sdcpp extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
+// sdcpp tree op0, tree op1, bool);
+
+extern tree find_inv_trees (tree *, int *, void *);
+extern tree replace_inv_trees (tree *, int *, void *);
+
+extern bool reject_gcc_builtin (const_tree, location_t = UNKNOWN_LOCATION);
+extern bool valid_array_size_p (location_t, const_tree, tree, bool = true);
+// sdcpp extern void invalid_array_size_error (location_t, cst_size_error,
+// sdcpp const_tree, const_tree);
+
+/* In c-warn.cc. */
+extern void constant_expression_warning (tree);
+extern void constant_expression_error (tree);
+// sdcpp extern void overflow_warning (location_t, tree, tree = NULL_TREE);
+// sdcpp extern void warn_logical_operator (location_t, enum tree_code, tree,
+// sdcpp enum tree_code, tree, enum tree_code, tree);
+// sdcpp extern void warn_tautological_cmp (const op_location_t &, enum tree_code,
+// sdcpp tree, tree);
+// sdcpp extern void warn_logical_not_parentheses (location_t, enum tree_code, tree,
+// sdcpp tree);
+extern bool warn_if_unused_value (const_tree, location_t, bool = false);
+extern bool strict_aliasing_warning (location_t, tree, tree);
+extern void sizeof_pointer_memaccess_warning (location_t *, tree,
+ vec<tree, va_gc> *, tree *,
+ bool (*) (tree, tree));
+extern void check_main_parameter_types (tree decl);
+extern void warnings_for_convert_and_check (location_t, tree, tree, tree);
+extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool);
+extern void warn_for_omitted_condop (location_t, tree);
+extern bool warn_for_restrict (unsigned, tree *, unsigned);
+extern void warn_for_address_or_pointer_of_packed_member (tree, tree);
+extern void warn_parm_array_mismatch (location_t, tree, tree);
+extern void maybe_warn_sizeof_array_div (location_t, tree, tree, tree, tree);
+// sdcpp extern void do_warn_array_compare (location_t, tree_code, tree, tree);
+
+/* Places where an lvalue, or modifiable lvalue, may be required.
+ Used to select diagnostic messages in lvalue_error and
+ readonly_error. */
+enum lvalue_use {
+ lv_assign,
+ lv_increment,
+ lv_decrement,
+ lv_addressof,
+ lv_asm
+};
+
+#if 0 // sdcpp
+extern void lvalue_error (location_t, enum lvalue_use);
+extern void invalid_indirection_error (location_t, tree, ref_operator);
+extern void readonly_error (location_t, tree, enum lvalue_use);
+extern void warn_array_subscript_with_type_char (location_t, tree);
+extern void warn_about_parentheses (location_t,
+ enum tree_code,
+ enum tree_code, tree,
+ enum tree_code, tree);
+extern void warn_for_unused_label (tree label);
+extern void warn_for_div_by_zero (location_t, tree divisor);
+extern void warn_for_memset (location_t, tree, tree, int);
+extern void warn_for_sign_compare (location_t,
+ tree orig_op0, tree orig_op1,
+ tree op0, tree op1,
+ tree result_type,
+ enum tree_code resultcode);
+extern void do_warn_double_promotion (tree, tree, tree, const char *,
+ location_t);
+extern void do_warn_unused_parameter (tree);
+extern void record_locally_defined_typedef (tree);
+extern void maybe_record_typedef_use (tree);
+extern void maybe_warn_unused_local_typedefs (void);
+extern void maybe_warn_bool_compare (location_t, enum tree_code, tree, tree);
+extern bool maybe_warn_shift_overflow (location_t, tree, tree);
+extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **);
+extern bool diagnose_mismatched_attributes (tree, tree);
+extern tree do_warn_duplicated_branches_r (tree *, int *, void *);
+extern void warn_for_multistatement_macros (location_t, location_t,
+ location_t, enum rid);
+#endif //sdcpp
+
+#if 0 // sdcpp
+/* In c-attribs.cc. */
+extern bool attribute_takes_identifier_p (const_tree);
+extern tree handle_deprecated_attribute (tree *, tree, tree, int, bool *);
+extern tree handle_unused_attribute (tree *, tree, tree, int, bool *);
+extern tree handle_fallthrough_attribute (tree *, tree, tree, int, bool *);
+extern int parse_tm_stmt_attr (tree, int);
+extern int tm_attr_to_mask (tree);
+extern tree tm_mask_to_attr (int);
+extern tree find_tm_attribute (tree);
+extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[];
+extern const struct attribute_spec::exclusions attr_noreturn_exclusions[];
+extern tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
+extern bool has_attribute (location_t, tree, tree, tree (*)(tree));
+extern tree build_attr_access_from_parms (tree, bool);
+#endif // sdcpp
+
+/* In c-format.cc. */
+extern bool valid_format_string_type_p (tree);
+
+/* A bitmap of flags to positional_argument. */
+enum posargflags {
+ /* Consider positional attribute argument value zero valid. */
+ POSARG_ZERO = 1,
+ /* Consider positional attribute argument value valid if it refers
+ to the ellipsis (i.e., beyond the last typed argument). */
+ POSARG_ELLIPSIS = 2
+};
+
+// sdcpp extern tree positional_argument (const_tree, const_tree, tree, tree_code,
+// sdcpp int = 0, int = posargflags ());
+
+extern enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
+
+extern int c_flt_eval_method (bool ts18661_p);
+extern void add_no_sanitize_value (tree node, unsigned int flags);
+
+extern void maybe_add_include_fixit (rich_location *, const char *, bool);
+extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
+ enum cpp_ttype token_type,
+ location_t prev_token_loc);
+extern tree braced_lists_to_strings (tree, tree);
+
+#if CHECKING_P
+namespace selftest {
+ /* Declarations for specific families of tests within c-family,
+ by source file, in alphabetical order. */
+ extern void c_diagnostic_cc_tests (void);
+ extern void c_format_cc_tests (void);
+ extern void c_indentation_cc_tests (void);
+ extern void c_opt_problem_cc_tests (void);
+ extern void c_pretty_print_cc_tests (void);
+ extern void c_spellcheck_cc_tests (void);
+
+ /* The entrypoint for running all of the above tests. */
+ extern void c_family_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
+#endif /* ! GCC_C_COMMON_H */
diff --git a/support/cpp/gcc/c-family/c-cppbuiltin.cc b/support/cpp/gcc/c-family/c-cppbuiltin.cc
new file mode 100644
index 000000000..f12162cff
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-cppbuiltin.cc
@@ -0,0 +1,2053 @@
+/* Define builtin-in macros for the C family front ends.
+ Copyright (C) 2002-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 "target.h"
+#include "c-common.h"
+#include "memmodel.h"
+// sdcpp #include "tm_p.h" /* For TARGET_CPU_CPP_BUILTINS & friends. */
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "flags.h"
+#include "c-pragma.h"
+// sdcpp #include "output.h" /* For user_label_prefix. */
+extern const char *user_label_prefix;
+#include "debug.h" /* For dwarf2out_do_cfi_asm. */
+#include "common/common-target.h"
+#include "cppbuiltin.h"
+#include "configargs.h"
+
+#ifndef TARGET_OS_CPP_BUILTINS
+# define TARGET_OS_CPP_BUILTINS()
+#endif
+
+#ifndef TARGET_OBJFMT_CPP_BUILTINS
+# define TARGET_OBJFMT_CPP_BUILTINS()
+#endif
+
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX ""
+#endif
+
+/* Non-static as some targets don't use it. */
+#if 0 // sdcpp
+static void builtin_define_with_hex_fp_value (const char *, tree,
+ int, const char *,
+ const char *,
+ const char *);
+static void builtin_define_stdint_macros (void);
+static void builtin_define_constants (const char *, tree);
+static void builtin_define_type_max (const char *, tree);
+static void builtin_define_type_minmax (const char *, const char *, tree);
+static void builtin_define_type_width (const char *, tree, tree);
+static void builtin_define_float_constants (const char *,
+ const char *,
+ const char *,
+ const char *,
+ tree);
+
+/* Return true if MODE provides a fast multiply/add (FMA) builtin function.
+ Originally this function used the fma optab, but that doesn't work with
+ -save-temps, so just rely on the HAVE_fma macros for the standard floating
+ point types. */
+
+static bool
+mode_has_fma (machine_mode mode)
+{
+ switch (mode)
+ {
+#ifdef HAVE_fmasf4
+ case E_SFmode:
+ return !!HAVE_fmasf4;
+#endif
+
+#ifdef HAVE_fmadf4
+ case E_DFmode:
+ return !!HAVE_fmadf4;
+#endif
+
+#ifdef HAVE_fmakf4 /* PowerPC if long double != __float128. */
+ case E_KFmode:
+ return !!HAVE_fmakf4;
+#endif
+
+#ifdef HAVE_fmaxf4
+ case E_XFmode:
+ return !!HAVE_fmaxf4;
+#endif
+
+#ifdef HAVE_fmatf4
+ case E_TFmode:
+ return !!HAVE_fmatf4;
+#endif
+
+ default:
+ break;
+ }
+
+ return false;
+}
+#endif // sdcpp
+
+/* Define NAME with value TYPE size_unit. */
+void
+builtin_define_type_sizeof (const char *name, tree type)
+{
+ (void) name;
+ (void) type;
+ fprintf(stderr, "incomplete %s %d\n", __func__, __LINE__);
+// builtin_define_with_int_value (name,
+// tree_to_uhwi (TYPE_SIZE_UNIT (type)));
+}
+
+/* Define the float.h constants for TYPE using NAME_PREFIX, FP_SUFFIX,
+ and FP_CAST. */
+#if 0 // sdcpp
+static void
+builtin_define_float_constants (const char *name_prefix,
+ const char *fp_suffix,
+ const char *fp_cast,
+ const char *fma_suffix,
+ tree type)
+{
+ fprintf(stderr, "incomplete %s %d\n", __func__, __LINE__);
+ (void) name_prefix;
+ (void) fp_suffix;
+ (void) fp_cast;
+ (void) fma_suffix;
+ (void) type;
+ /* Used to convert radix-based values to base 10 values in several cases.
+
+ In the max_exp -> max_10_exp conversion for 128-bit IEEE, we need at
+ least 6 significant digits for correct results. Using the fraction
+ formed by (log(2)*1e6)/(log(10)*1e6) overflows a 32-bit integer as an
+ intermediate; perhaps someone can find a better approximation, in the
+ mean time, I suspect using doubles won't harm the bootstrap here. */
+
+ const double log10_2 = .30102999566398119521;
+ double log10_b;
+ const struct real_format *fmt;
+ const struct real_format *widefmt;
+
+ char name[64], buf[128];
+ int dig, min_10_exp, max_10_exp;
+ int decimal_dig;
+ int type_decimal_dig;
+
+ fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
+ gcc_assert (fmt->b != 10);
+ widefmt = REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node));
+ gcc_assert (widefmt->b != 10);
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ tree wtype = FLOATN_NX_TYPE_NODE (i);
+ if (wtype != NULL_TREE)
+ {
+ const struct real_format *wfmt
+ = REAL_MODE_FORMAT (TYPE_MODE (wtype));
+ gcc_assert (wfmt->b != 10);
+ if (wfmt->p > widefmt->p)
+ widefmt = wfmt;
+ }
+ }
+
+ /* The radix of the exponent representation. */
+ if (type == float_type_node)
+ builtin_define_with_int_value ("__FLT_RADIX__", fmt->b);
+ log10_b = log10_2;
+
+ /* The number of radix digits, p, in the floating-point significand. */
+ sprintf (name, "__%s_MANT_DIG__", name_prefix);
+ builtin_define_with_int_value (name, fmt->p);
+
+ /* The number of decimal digits, q, such that any floating-point number
+ with q decimal digits can be rounded into a floating-point number with
+ p radix b digits and back again without change to the q decimal digits,
+
+ p log10 b if b is a power of 10
+ floor((p - 1) log10 b) otherwise
+ */
+ dig = (fmt->p - 1) * log10_b;
+ sprintf (name, "__%s_DIG__", name_prefix);
+ builtin_define_with_int_value (name, dig);
+
+ /* The minimum negative int x such that b**(x-1) is a normalized float. */
+ sprintf (name, "__%s_MIN_EXP__", name_prefix);
+ sprintf (buf, "(%d)", fmt->emin);
+ builtin_define_with_value (name, buf, 0);
+
+ /* The minimum negative int x such that 10**x is a normalized float,
+
+ ceil (log10 (b ** (emin - 1)))
+ = ceil (log10 (b) * (emin - 1))
+
+ Recall that emin is negative, so the integer truncation calculates
+ the ceiling, not the floor, in this case. */
+ min_10_exp = (fmt->emin - 1) * log10_b;
+ sprintf (name, "__%s_MIN_10_EXP__", name_prefix);
+ sprintf (buf, "(%d)", min_10_exp);
+ builtin_define_with_value (name, buf, 0);
+
+ /* The maximum int x such that b**(x-1) is a representable float. */
+ sprintf (name, "__%s_MAX_EXP__", name_prefix);
+ builtin_define_with_int_value (name, fmt->emax);
+
+ /* The maximum int x such that 10**x is in the range of representable
+ finite floating-point numbers,
+
+ floor (log10((1 - b**-p) * b**emax))
+ = floor (log10(1 - b**-p) + log10(b**emax))
+ = floor (log10(1 - b**-p) + log10(b)*emax)
+
+ The safest thing to do here is to just compute this number. But since
+ we don't link cc1 with libm, we cannot. We could implement log10 here
+ a series expansion, but that seems too much effort because:
+
+ Note that the first term, for all extant p, is a number exceedingly close
+ to zero, but slightly negative. Note that the second term is an integer
+ scaling an irrational number, and that because of the floor we are only
+ interested in its integral portion.
+
+ In order for the first term to have any effect on the integral portion
+ of the second term, the second term has to be exceedingly close to an
+ integer itself (e.g. 123.000000000001 or something). Getting a result
+ that close to an integer requires that the irrational multiplicand have
+ a long series of zeros in its expansion, which doesn't occur in the
+ first 20 digits or so of log10(b).
+
+ Hand-waving aside, crunching all of the sets of constants above by hand
+ does not yield a case for which the first term is significant, which
+ in the end is all that matters. */
+ max_10_exp = fmt->emax * log10_b;
+ sprintf (name, "__%s_MAX_10_EXP__", name_prefix);
+ builtin_define_with_int_value (name, max_10_exp);
+
+ /* The number of decimal digits, n, such that any floating-point number
+ can be rounded to n decimal digits and back again without change to
+ the value.
+
+ p * log10(b) if b is a power of 10
+ ceil(1 + p * log10(b)) otherwise
+
+ The only macro we care about is this number for the widest supported
+ floating type, but we want this value for rendering constants below. */
+ {
+ double d_decimal_dig
+ = 1 + (fmt->p < widefmt->p ? widefmt->p : fmt->p) * log10_b;
+ decimal_dig = d_decimal_dig;
+ if (decimal_dig < d_decimal_dig)
+ decimal_dig++;
+ }
+ /* Similar, for this type rather than long double. */
+ {
+ double type_d_decimal_dig = 1 + fmt->p * log10_b;
+ type_decimal_dig = type_d_decimal_dig;
+ if (type_decimal_dig < type_d_decimal_dig)
+ type_decimal_dig++;
+ }
+ /* Define __DECIMAL_DIG__ to the value for long double to be
+ compatible with C99 and C11; see DR#501 and N2108. */
+ if (type == long_double_type_node)
+ builtin_define_with_int_value ("__DECIMAL_DIG__", type_decimal_dig);
+ sprintf (name, "__%s_DECIMAL_DIG__", name_prefix);
+ builtin_define_with_int_value (name, type_decimal_dig);
+
+ /* Since, for the supported formats, B is always a power of 2, we
+ construct the following numbers directly as a hexadecimal
+ constants. */
+ get_max_float (fmt, buf, sizeof (buf), false);
+
+ sprintf (name, "__%s_MAX__", name_prefix);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
+
+ get_max_float (fmt, buf, sizeof (buf), true);
+
+ sprintf (name, "__%s_NORM_MAX__", name_prefix);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
+
+ /* The minimum normalized positive floating-point number,
+ b**(emin-1). */
+ sprintf (name, "__%s_MIN__", name_prefix);
+ sprintf (buf, "0x1p%d", fmt->emin - 1);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
+
+ /* The difference between 1 and the least value greater than 1 that is
+ representable in the given floating point type, b**(1-p). */
+ sprintf (name, "__%s_EPSILON__", name_prefix);
+ if (fmt->pnan < fmt->p)
+ /* This is an IBM extended double format, so 1.0 + any double is
+ representable precisely. */
+ sprintf (buf, "0x1p%d", fmt->emin - fmt->p);
+ else
+ sprintf (buf, "0x1p%d", 1 - fmt->p);
+ builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
+
+ /* For C++ std::numeric_limits<T>::denorm_min and C11 *_TRUE_MIN.
+ The minimum denormalized positive floating-point number, b**(emin-p).
+ The minimum normalized positive floating-point number for formats
+ that don't support denormals. */
+ sprintf (name, "__%s_DENORM_MIN__", name_prefix);
+ sprintf (buf, "0x1p%d", fmt->emin - (fmt->has_denorm ? fmt->p : 1));
+ builtin_define_with_hex_fp_value (name, type, decimal_dig,
+ buf, fp_suffix, fp_cast);
+
+ sprintf (name, "__%s_HAS_DENORM__", name_prefix);
+ builtin_define_with_value (name, fmt->has_denorm ? "1" : "0", 0);
+
+ /* For C++ std::numeric_limits<T>::has_infinity. */
+ sprintf (name, "__%s_HAS_INFINITY__", name_prefix);
+ builtin_define_with_int_value (name,
+ MODE_HAS_INFINITIES (TYPE_MODE (type)));
+ /* For C++ std::numeric_limits<T>::has_quiet_NaN. We do not have a
+ predicate to distinguish a target that has both quiet and
+ signalling NaNs from a target that has only quiet NaNs or only
+ signalling NaNs, so we assume that a target that has any kind of
+ NaN has quiet NaNs. */
+ sprintf (name, "__%s_HAS_QUIET_NAN__", name_prefix);
+ builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
+
+ /* Note whether we have fast FMA. */
+ if (mode_has_fma (TYPE_MODE (type)) && fma_suffix != NULL)
+ {
+ sprintf (name, "__FP_FAST_FMA%s", fma_suffix);
+ builtin_define_with_int_value (name, 1);
+ }
+
+ /* For C2x *_IS_IEC_60559. 0 means the type does not match an IEC
+ 60559 format, 1 that it matches a format but not operations and 2
+ that it matches a format and operations (but may not conform to
+ Annex F; we take this as meaning exceptions and rounding modes
+ need not be supported). */
+ sprintf (name, "__%s_IS_IEC_60559__", name_prefix);
+ builtin_define_with_int_value (name,
+ (fmt->ieee_bits == 0
+ ? 0 : (fmt->round_towards_zero ? 1 : 2)));
+}
+
+/* Define __DECx__ constants for TYPE using NAME_PREFIX and SUFFIX. */
+static void
+builtin_define_decimal_float_constants (const char *name_prefix,
+ const char *suffix,
+ tree type)
+{
+ const struct real_format *fmt;
+ char name[64], buf[128], *p;
+ int digits;
+
+ fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
+
+ /* The number of radix digits, p, in the significand. */
+ sprintf (name, "__%s_MANT_DIG__", name_prefix);
+ builtin_define_with_int_value (name, fmt->p);
+
+ /* The minimum negative int x such that b**(x-1) is a normalized float. */
+ sprintf (name, "__%s_MIN_EXP__", name_prefix);
+ sprintf (buf, "(%d)", fmt->emin);
+ builtin_define_with_value (name, buf, 0);
+
+ /* The maximum int x such that b**(x-1) is a representable float. */
+ sprintf (name, "__%s_MAX_EXP__", name_prefix);
+ builtin_define_with_int_value (name, fmt->emax);
+
+ /* Compute the minimum representable value. */
+ sprintf (name, "__%s_MIN__", name_prefix);
+ sprintf (buf, "1E%d%s", fmt->emin - 1, suffix);
+ builtin_define_with_value (name, buf, 0);
+
+ /* Compute the maximum representable value. */
+ sprintf (name, "__%s_MAX__", name_prefix);
+ p = buf;
+ for (digits = fmt->p; digits; digits--)
+ {
+ *p++ = '9';
+ if (digits == fmt->p)
+ *p++ = '.';
+ }
+ *p = 0;
+ /* fmt->p plus 1, to account for the decimal point and fmt->emax
+ minus 1 because the digits are nines, not 1.0. */
+ sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax - 1, suffix);
+ builtin_define_with_value (name, buf, 0);
+
+ /* Compute epsilon (the difference between 1 and least value greater
+ than 1 representable). */
+ sprintf (name, "__%s_EPSILON__", name_prefix);
+ sprintf (buf, "1E-%d%s", fmt->p - 1, suffix);
+ builtin_define_with_value (name, buf, 0);
+
+ /* Minimum subnormal positive decimal value. */
+ sprintf (name, "__%s_SUBNORMAL_MIN__", name_prefix);
+ p = buf;
+ for (digits = fmt->p; digits > 1; digits--)
+ {
+ *p++ = '0';
+ if (digits == fmt->p)
+ *p++ = '.';
+ }
+ *p = 0;
+ sprintf (&buf[fmt->p], "1E%d%s", fmt->emin - 1, suffix);
+ builtin_define_with_value (name, buf, 0);
+}
+
+/* Define fixed-point constants for TYPE using NAME_PREFIX and SUFFIX. */
+
+static void
+builtin_define_fixed_point_constants (const char *name_prefix,
+ const char *suffix,
+ tree type)
+{
+ char name[64], buf[256], *new_buf;
+ int i, mod;
+
+ sprintf (name, "__%s_FBIT__", name_prefix);
+ builtin_define_with_int_value (name, TYPE_FBIT (type));
+
+ sprintf (name, "__%s_IBIT__", name_prefix);
+ builtin_define_with_int_value (name, TYPE_IBIT (type));
+
+ /* If there is no suffix, defines are for fixed-point modes.
+ We just return. */
+ if (strcmp (suffix, "") == 0)
+ return;
+
+ if (TYPE_UNSIGNED (type))
+ {
+ sprintf (name, "__%s_MIN__", name_prefix);
+ sprintf (buf, "0.0%s", suffix);
+ builtin_define_with_value (name, buf, 0);
+ }
+ else
+ {
+ sprintf (name, "__%s_MIN__", name_prefix);
+ if (ALL_ACCUM_MODE_P (TYPE_MODE (type)))
+ sprintf (buf, "(-0X1P%d%s-0X1P%d%s)", TYPE_IBIT (type) - 1, suffix,
+ TYPE_IBIT (type) - 1, suffix);
+ else
+ sprintf (buf, "(-0.5%s-0.5%s)", suffix, suffix);
+ builtin_define_with_value (name, buf, 0);
+ }
+
+ sprintf (name, "__%s_MAX__", name_prefix);
+ sprintf (buf, "0X");
+ new_buf = buf + 2;
+ mod = (TYPE_FBIT (type) + TYPE_IBIT (type)) % 4;
+ if (mod)
+ sprintf (new_buf++, "%x", (1 << mod) - 1);
+ for (i = 0; i < (TYPE_FBIT (type) + TYPE_IBIT (type)) / 4; i++)
+ sprintf (new_buf++, "F");
+ sprintf (new_buf, "P-%d%s", TYPE_FBIT (type), suffix);
+ builtin_define_with_value (name, buf, 0);
+
+ sprintf (name, "__%s_EPSILON__", name_prefix);
+ sprintf (buf, "0x1P-%d%s", TYPE_FBIT (type), suffix);
+ builtin_define_with_value (name, buf, 0);
+}
+
+/* Define macros used by <stdint.h>. */
+static void
+builtin_define_stdint_macros (void)
+{
+ builtin_define_type_max ("__INTMAX_MAX__", intmax_type_node);
+ builtin_define_constants ("__INTMAX_C", intmax_type_node);
+ builtin_define_type_max ("__UINTMAX_MAX__", uintmax_type_node);
+ builtin_define_constants ("__UINTMAX_C", uintmax_type_node);
+ builtin_define_type_width ("__INTMAX_WIDTH__", intmax_type_node,
+ uintmax_type_node);
+ if (sig_atomic_type_node)
+ {
+ builtin_define_type_minmax ("__SIG_ATOMIC_MIN__", "__SIG_ATOMIC_MAX__",
+ sig_atomic_type_node);
+ builtin_define_type_width ("__SIG_ATOMIC_WIDTH__", sig_atomic_type_node,
+ NULL_TREE);
+ }
+ if (int8_type_node)
+ builtin_define_type_max ("__INT8_MAX__", int8_type_node);
+ if (int16_type_node)
+ builtin_define_type_max ("__INT16_MAX__", int16_type_node);
+ if (int32_type_node)
+ builtin_define_type_max ("__INT32_MAX__", int32_type_node);
+ if (int64_type_node)
+ builtin_define_type_max ("__INT64_MAX__", int64_type_node);
+ if (uint8_type_node)
+ builtin_define_type_max ("__UINT8_MAX__", uint8_type_node);
+ if (c_uint16_type_node)
+ builtin_define_type_max ("__UINT16_MAX__", c_uint16_type_node);
+ if (c_uint32_type_node)
+ builtin_define_type_max ("__UINT32_MAX__", c_uint32_type_node);
+ if (c_uint64_type_node)
+ builtin_define_type_max ("__UINT64_MAX__", c_uint64_type_node);
+ if (int_least8_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST8_MAX__", int_least8_type_node);
+ builtin_define_constants ("__INT8_C", int_least8_type_node);
+ builtin_define_type_width ("__INT_LEAST8_WIDTH__", int_least8_type_node,
+ uint_least8_type_node);
+ }
+ if (int_least16_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST16_MAX__", int_least16_type_node);
+ builtin_define_constants ("__INT16_C", int_least16_type_node);
+ builtin_define_type_width ("__INT_LEAST16_WIDTH__",
+ int_least16_type_node,
+ uint_least16_type_node);
+ }
+ if (int_least32_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST32_MAX__", int_least32_type_node);
+ builtin_define_constants ("__INT32_C", int_least32_type_node);
+ builtin_define_type_width ("__INT_LEAST32_WIDTH__",
+ int_least32_type_node,
+ uint_least32_type_node);
+ }
+ if (int_least64_type_node)
+ {
+ builtin_define_type_max ("__INT_LEAST64_MAX__", int_least64_type_node);
+ builtin_define_constants ("__INT64_C", int_least64_type_node);
+ builtin_define_type_width ("__INT_LEAST64_WIDTH__",
+ int_least64_type_node,
+ uint_least64_type_node);
+ }
+ if (uint_least8_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST8_MAX__", uint_least8_type_node);
+ builtin_define_constants ("__UINT8_C", uint_least8_type_node);
+ }
+ if (uint_least16_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST16_MAX__", uint_least16_type_node);
+ builtin_define_constants ("__UINT16_C", uint_least16_type_node);
+ }
+ if (uint_least32_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST32_MAX__", uint_least32_type_node);
+ builtin_define_constants ("__UINT32_C", uint_least32_type_node);
+ }
+ if (uint_least64_type_node)
+ {
+ builtin_define_type_max ("__UINT_LEAST64_MAX__", uint_least64_type_node);
+ builtin_define_constants ("__UINT64_C", uint_least64_type_node);
+ }
+ if (int_fast8_type_node)
+ {
+ builtin_define_type_max ("__INT_FAST8_MAX__", int_fast8_type_node);
+ builtin_define_type_width ("__INT_FAST8_WIDTH__", int_fast8_type_node,
+ uint_fast8_type_node);
+ }
+ if (int_fast16_type_node)
+ {
+ builtin_define_type_max ("__INT_FAST16_MAX__", int_fast16_type_node);
+ builtin_define_type_width ("__INT_FAST16_WIDTH__", int_fast16_type_node,
+ uint_fast16_type_node);
+ }
+ if (int_fast32_type_node)
+ {
+ builtin_define_type_max ("__INT_FAST32_MAX__", int_fast32_type_node);
+ builtin_define_type_width ("__INT_FAST32_WIDTH__", int_fast32_type_node,
+ uint_fast32_type_node);
+ }
+ if (int_fast64_type_node)
+ {
+ builtin_define_type_max ("__INT_FAST64_MAX__", int_fast64_type_node);
+ builtin_define_type_width ("__INT_FAST64_WIDTH__", int_fast64_type_node,
+ uint_fast64_type_node);
+ }
+ if (uint_fast8_type_node)
+ builtin_define_type_max ("__UINT_FAST8_MAX__", uint_fast8_type_node);
+ if (uint_fast16_type_node)
+ builtin_define_type_max ("__UINT_FAST16_MAX__", uint_fast16_type_node);
+ if (uint_fast32_type_node)
+ builtin_define_type_max ("__UINT_FAST32_MAX__", uint_fast32_type_node);
+ if (uint_fast64_type_node)
+ builtin_define_type_max ("__UINT_FAST64_MAX__", uint_fast64_type_node);
+ if (intptr_type_node)
+ {
+ builtin_define_type_max ("__INTPTR_MAX__", intptr_type_node);
+ builtin_define_type_width ("__INTPTR_WIDTH__", intptr_type_node,
+ uintptr_type_node);
+ }
+ if (uintptr_type_node)
+ builtin_define_type_max ("__UINTPTR_MAX__", uintptr_type_node);
+}
+#endif // sdcpp
+
+#if 0 // sdcpp
+/* Adjust the optimization macros when a #pragma GCC optimization is done to
+ reflect the current level. */
+void
+c_cpp_builtins_optimize_pragma (cpp_reader *pfile, tree prev_tree,
+ tree cur_tree)
+{
+ struct cl_optimization *prev = TREE_OPTIMIZATION (prev_tree);
+ struct cl_optimization *cur = TREE_OPTIMIZATION (cur_tree);
+ bool prev_fast_math;
+ bool cur_fast_math;
+
+ /* -undef turns off target-specific built-ins. */
+ if (flag_undef)
+ return;
+
+ /* Make sure all of the builtins about to be declared have
+ BUILTINS_LOCATION has their location_t. */
+ cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
+
+ /* Other target-independent built-ins determined by command-line
+ options. */
+ if (!prev->x_optimize_size && cur->x_optimize_size)
+ cpp_define_unused (pfile, "__OPTIMIZE_SIZE__");
+ else if (prev->x_optimize_size && !cur->x_optimize_size)
+ cpp_undef (pfile, "__OPTIMIZE_SIZE__");
+
+ if (!prev->x_optimize && cur->x_optimize)
+ cpp_define_unused (pfile, "__OPTIMIZE__");
+ else if (prev->x_optimize && !cur->x_optimize)
+ cpp_undef (pfile, "__OPTIMIZE__");
+
+ prev_fast_math = fast_math_flags_struct_set_p (prev);
+ cur_fast_math = fast_math_flags_struct_set_p (cur);
+ if (!prev_fast_math && cur_fast_math)
+ cpp_define_unused (pfile, "__FAST_MATH__");
+ else if (prev_fast_math && !cur_fast_math)
+ cpp_undef (pfile, "__FAST_MATH__");
+
+ if (!prev->x_flag_signaling_nans && cur->x_flag_signaling_nans)
+ cpp_define_unused (pfile, "__SUPPORT_SNAN__");
+ else if (prev->x_flag_signaling_nans && !cur->x_flag_signaling_nans)
+ cpp_undef (pfile, "__SUPPORT_SNAN__");
+
+ if (!prev->x_flag_errno_math && cur->x_flag_errno_math)
+ cpp_undef (pfile, "__NO_MATH_ERRNO__");
+ else if (prev->x_flag_errno_math && !cur->x_flag_errno_math)
+ cpp_define_unused (pfile, "__NO_MATH_ERRNO__");
+
+ if (!prev->x_flag_finite_math_only && cur->x_flag_finite_math_only)
+ {
+ cpp_undef (pfile, "__FINITE_MATH_ONLY__");
+ cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=1");
+ }
+ else if (prev->x_flag_finite_math_only && !cur->x_flag_finite_math_only)
+ {
+ cpp_undef (pfile, "__FINITE_MATH_ONLY__");
+ cpp_define_unused (pfile, "__FINITE_MATH_ONLY__=0");
+ }
+
+ if (!prev->x_flag_reciprocal_math && cur->x_flag_reciprocal_math)
+ cpp_define_unused (pfile, "__RECIPROCAL_MATH__");
+ else if (prev->x_flag_reciprocal_math && !cur->x_flag_reciprocal_math)
+ cpp_undef (pfile, "__RECIPROCAL_MATH__");
+
+ if (!prev->x_flag_signed_zeros && cur->x_flag_signed_zeros)
+ cpp_undef (pfile, "__NO_SIGNED_ZEROS__");
+ else if (prev->x_flag_signed_zeros && !cur->x_flag_signed_zeros)
+ cpp_define_unused (pfile, "__NO_SIGNED_ZEROS__");
+
+ if (!prev->x_flag_trapping_math && cur->x_flag_trapping_math)
+ cpp_undef (pfile, "__NO_TRAPPING_MATH__");
+ else if (prev->x_flag_trapping_math && !cur->x_flag_trapping_math)
+ cpp_define_unused (pfile, "__NO_TRAPPING_MATH__");
+
+ if (!prev->x_flag_associative_math && cur->x_flag_associative_math)
+ cpp_define_unused (pfile, "__ASSOCIATIVE_MATH__");
+ else if (prev->x_flag_associative_math && !cur->x_flag_associative_math)
+ cpp_undef (pfile, "__ASSOCIATIVE_MATH__");
+
+ if (!prev->x_flag_rounding_math && cur->x_flag_rounding_math)
+ cpp_define_unused (pfile, "__ROUNDING_MATH__");
+ else if (prev->x_flag_rounding_math && !cur->x_flag_rounding_math)
+ cpp_undef (pfile, "__ROUNDING_MATH__");
+
+ cpp_stop_forcing_token_locations (parse_in);
+}
+#endif // sdcpp
+
+
+/* This function will emit cpp macros to indicate the presence of various lock
+ free atomic operations. */
+
+#if 0 // sdcpp
+static void
+cpp_atomic_builtins (cpp_reader *pfile)
+{
+ /* Set a flag for each size of object that compare and swap exists for up to
+ a 16 byte object. */
+#define SWAP_LIMIT 17
+ bool have_swap[SWAP_LIMIT];
+// sdcpp unsigned int psize;
+
+ /* Clear the map of sizes compare_and swap exists for. */
+ memset (have_swap, 0, sizeof (have_swap));
+
+ /* Tell source code if the compiler makes sync_compare_and_swap
+ builtins available. */
+#ifndef HAVE_sync_compare_and_swapqi
+#define HAVE_sync_compare_and_swapqi 0
+#endif
+#ifndef HAVE_atomic_compare_and_swapqi
+#define HAVE_atomic_compare_and_swapqi 0
+#endif
+
+ if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+ have_swap[1] = true;
+ }
+
+#ifndef HAVE_sync_compare_and_swaphi
+#define HAVE_sync_compare_and_swaphi 0
+#endif
+#ifndef HAVE_atomic_compare_and_swaphi
+#define HAVE_atomic_compare_and_swaphi 0
+#endif
+ if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+ have_swap[2] = true;
+ }
+
+#ifndef HAVE_sync_compare_and_swapsi
+#define HAVE_sync_compare_and_swapsi 0
+#endif
+#ifndef HAVE_atomic_compare_and_swapsi
+#define HAVE_atomic_compare_and_swapsi 0
+#endif
+ if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+ have_swap[4] = true;
+ }
+
+#ifndef HAVE_sync_compare_and_swapdi
+#define HAVE_sync_compare_and_swapdi 0
+#endif
+#ifndef HAVE_atomic_compare_and_swapdi
+#define HAVE_atomic_compare_and_swapdi 0
+#endif
+ if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+ have_swap[8] = true;
+ }
+
+#ifndef HAVE_sync_compare_and_swapti
+#define HAVE_sync_compare_and_swapti 0
+#endif
+#ifndef HAVE_atomic_compare_and_swapti
+#define HAVE_atomic_compare_and_swapti 0
+#endif
+ if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
+ {
+ cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+ have_swap[16] = true;
+ }
+
+ /* Tell the source code about various types. These map to the C++11 and C11
+ macros where 2 indicates lock-free always, and 1 indicates sometimes
+ lock free. */
+#define SIZEOF_NODE(T) (tree_to_uhwi (TYPE_SIZE_UNIT (T)))
+#define SWAP_INDEX(T) ((SIZEOF_NODE (T) < SWAP_LIMIT) ? SIZEOF_NODE (T) : 0)
+ builtin_define_with_int_value ("__GCC_ATOMIC_BOOL_LOCK_FREE",
+ (have_swap[SWAP_INDEX (boolean_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR_LOCK_FREE",
+ (have_swap[SWAP_INDEX (signed_char_type_node)]? 2 : 1));
+ if (flag_char8_t)
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR8_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (char8_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR16_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (char16_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_CHAR32_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (char32_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_WCHAR_T_LOCK_FREE",
+ (have_swap[SWAP_INDEX (wchar_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_SHORT_LOCK_FREE",
+ (have_swap[SWAP_INDEX (short_integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_INT_LOCK_FREE",
+ (have_swap[SWAP_INDEX (integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_LONG_LOCK_FREE",
+ (have_swap[SWAP_INDEX (long_integer_type_node)]? 2 : 1));
+ builtin_define_with_int_value ("__GCC_ATOMIC_LLONG_LOCK_FREE",
+ (have_swap[SWAP_INDEX (long_long_integer_type_node)]? 2 : 1));
+
+ /* If we're dealing with a "set" value that doesn't exactly correspond
+ to a boolean truth value, let the library work around that. */
+// sdcpp builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL",
+// sdcpp targetm.atomic_test_and_set_trueval);
+
+ /* Macros for C++17 hardware interference size constants. Either both or
+ neither should be set. */
+ gcc_assert (!param_destruct_interfere_size
+ == !param_construct_interfere_size);
+ if (param_destruct_interfere_size)
+ {
+ /* FIXME The way of communicating these values to the library should be
+ part of the C++ ABI, whether macro or builtin. */
+ builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE",
+ param_destruct_interfere_size);
+ builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE",
+ param_construct_interfere_size);
+ }
+
+#if 0 // sdcpp
+ /* ptr_type_node can't be used here since ptr_mode is only set when
+ toplev calls backend_init which is not done with -E or pch. */
+ psize = POINTER_SIZE_UNITS;
+ if (psize >= SWAP_LIMIT)
+ psize = 0;
+ builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE",
+ (have_swap[psize]? 2 : 1));
+#endif // sdcpp
+}
+#endif // sdcpp
+
+/* Return TRUE if the implicit excess precision in which the back-end will
+ compute floating-point calculations is not more than the explicit
+ excess precision that the front-end will apply under
+ -fexcess-precision=[standard|fast|16].
+
+ More intuitively, return TRUE if the excess precision proposed by the
+ front-end is the excess precision that will actually be used. */
+
+#if 0 // sdcpp
+static bool
+c_cpp_flt_eval_method_iec_559 (void)
+{
+ enum excess_precision_type front_end_ept
+ = (flag_excess_precision == EXCESS_PRECISION_STANDARD
+ ? EXCESS_PRECISION_TYPE_STANDARD
+ : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+ ? EXCESS_PRECISION_TYPE_FLOAT16
+ : EXCESS_PRECISION_TYPE_FAST));
+
+ enum flt_eval_method back_end
+ = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+ enum flt_eval_method front_end
+ = targetm.c.excess_precision (front_end_ept);
+
+ return excess_precision_mode_join (front_end, back_end) == front_end;
+}
+#endif // sdcpp
+
+#if 0 // sdcpp
+/* Return the value for __GCC_IEC_559. */
+static int
+cpp_iec_559_value (void)
+{
+ /* The default is support for IEEE 754-2008. */
+ int ret = 2;
+
+ /* float and double must be binary32 and binary64. If they are but
+ with reversed NaN convention, at most IEEE 754-1985 is
+ supported. */
+ const struct real_format *ffmt
+ = REAL_MODE_FORMAT (TYPE_MODE (float_type_node));
+ const struct real_format *dfmt
+ = REAL_MODE_FORMAT (TYPE_MODE (double_type_node));
+ if (!ffmt->qnan_msb_set || !dfmt->qnan_msb_set)
+ ret = 1;
+ if (ffmt->b != 2
+ || ffmt->p != 24
+ || ffmt->pnan != 24
+ || ffmt->emin != -125
+ || ffmt->emax != 128
+ || ffmt->signbit_rw != 31
+ || ffmt->round_towards_zero
+ || !ffmt->has_sign_dependent_rounding
+ || !ffmt->has_nans
+ || !ffmt->has_inf
+ || !ffmt->has_denorm
+ || !ffmt->has_signed_zero
+ || dfmt->b != 2
+ || dfmt->p != 53
+ || dfmt->pnan != 53
+ || dfmt->emin != -1021
+ || dfmt->emax != 1024
+ || dfmt->signbit_rw != 63
+ || dfmt->round_towards_zero
+ || !dfmt->has_sign_dependent_rounding
+ || !dfmt->has_nans
+ || !dfmt->has_inf
+ || !dfmt->has_denorm
+ || !dfmt->has_signed_zero)
+ ret = 0;
+
+ /* In strict C standards conformance mode, consider a back-end providing
+ more implicit excess precision than the explicit excess precision
+ the front-end options would require to mean a lack of IEEE 754
+ support. For C++, and outside strict conformance mode, do not consider
+ this to mean a lack of IEEE 754 support. */
+
+ if (flag_iso
+ && !c_dialect_cxx ()
+ && !c_cpp_flt_eval_method_iec_559 ())
+ ret = 0;
+
+ if (flag_iso
+ && !c_dialect_cxx ()
+ && flag_fp_contract_mode == FP_CONTRACT_FAST)
+ ret = 0;
+
+ /* Various options are contrary to IEEE 754 semantics. */
+ if (flag_unsafe_math_optimizations
+ || flag_associative_math
+ || flag_reciprocal_math
+ || flag_finite_math_only
+ || !flag_signed_zeros
+ || flag_single_precision_constant)
+ ret = 0;
+
+ /* If the target does not support IEEE 754 exceptions and rounding
+ modes, consider IEEE 754 support to be absent. */
+ if (!targetm.float_exceptions_rounding_supported_p ())
+ ret = 0;
+
+ return ret;
+}
+
+/* Return the value for __GCC_IEC_559_COMPLEX. */
+static int
+cpp_iec_559_complex_value (void)
+{
+ /* The value is no bigger than that of __GCC_IEC_559. */
+ int ret = cpp_iec_559_value ();
+
+ /* Some options are contrary to the required default state of the
+ CX_LIMITED_RANGE pragma. */
+ if (flag_complex_method != 2)
+ ret = 0;
+
+ return ret;
+}
+#endif // sdcpp
+
+/* Hook that registers front end and target-specific built-ins. */
+void
+c_cpp_builtins (cpp_reader *pfile)
+{
+// sdcpp int i;
+
+ /* -undef turns off target-specific built-ins. */
+ if (flag_undef)
+ return;
+
+ define_language_independent_builtin_macros (pfile);
+
+ /* encoding definitions used by users and libraries */
+ builtin_define_with_value ("__GNUC_EXECUTION_CHARSET_NAME",
+ cpp_get_narrow_charset_name (pfile), 1);
+ builtin_define_with_value ("__GNUC_WIDE_EXECUTION_CHARSET_NAME",
+ cpp_get_wide_charset_name (pfile), 1);
+
+
+ if (c_dialect_cxx ())
+ {
+ int major;
+ parse_basever (&major, NULL, NULL);
+ cpp_define_formatted (pfile, "__GNUG__=%d", major);
+ }
+
+ /* For stddef.h. They require macros defined in c-common.cc. */
+ c_stddef_cpp_builtins ();
+
+#if 0 // sdcpp
+ if (c_dialect_cxx ())
+ {
+ if (flag_weak && SUPPORTS_ONE_ONLY)
+ cpp_define (pfile, "__GXX_WEAK__=1");
+ else
+ cpp_define (pfile, "__GXX_WEAK__=0");
+
+ if (warn_deprecated)
+ cpp_define (pfile, "__DEPRECATED");
+
+ if (flag_rtti)
+ {
+ cpp_define (pfile, "__GXX_RTTI");
+ cpp_define (pfile, "__cpp_rtti=199711L");
+ }
+
+ if (cxx_dialect >= cxx11)
+ cpp_define (pfile, "__GXX_EXPERIMENTAL_CXX0X__");
+
+ /* Binary literals have been allowed in g++ before C++11
+ and were standardized for C++14. */
+ if (!pedantic || cxx_dialect > cxx11)
+ cpp_define (pfile, "__cpp_binary_literals=201304L");
+
+ /* Similarly for hexadecimal floating point literals and C++17. */
+ if (!pedantic || cpp_get_options (parse_in)->extended_numbers)
+ cpp_define (pfile, "__cpp_hex_float=201603L");
+
+ /* Arrays of runtime bound were removed from C++14, but we still
+ support GNU VLAs. Let's define this macro to a low number
+ (corresponding to the initial test release of GNU C++) if we won't
+ complain about use of VLAs. */
+ if (c_dialect_cxx ()
+ && (pedantic ? warn_vla == 0 : warn_vla <= 0))
+ cpp_define (pfile, "__cpp_runtime_arrays=198712L");
+
+ if (cxx_dialect >= cxx11)
+ {
+ /* Set feature test macros for C++11. */
+ if (cxx_dialect <= cxx14)
+ cpp_define (pfile, "__cpp_unicode_characters=200704L");
+ cpp_define (pfile, "__cpp_raw_strings=200710L");
+ cpp_define (pfile, "__cpp_unicode_literals=200710L");
+ cpp_define (pfile, "__cpp_user_defined_literals=200809L");
+ cpp_define (pfile, "__cpp_lambdas=200907L");
+ if (cxx_dialect == cxx11)
+ cpp_define (pfile, "__cpp_constexpr=200704L");
+ if (cxx_dialect <= cxx14)
+ cpp_define (pfile, "__cpp_range_based_for=200907L");
+ if (cxx_dialect <= cxx14)
+ cpp_define (pfile, "__cpp_static_assert=200410L");
+ cpp_define (pfile, "__cpp_decltype=200707L");
+ cpp_define (pfile, "__cpp_attributes=200809L");
+ cpp_define (pfile, "__cpp_rvalue_reference=200610L");
+ cpp_define (pfile, "__cpp_rvalue_references=200610L");
+ cpp_define (pfile, "__cpp_variadic_templates=200704L");
+ cpp_define (pfile, "__cpp_initializer_lists=200806L");
+ cpp_define (pfile, "__cpp_delegating_constructors=200604L");
+ cpp_define (pfile, "__cpp_nsdmi=200809L");
+ if (!flag_new_inheriting_ctors)
+ cpp_define (pfile, "__cpp_inheriting_constructors=200802L");
+ else
+ cpp_define (pfile, "__cpp_inheriting_constructors=201511L");
+ cpp_define (pfile, "__cpp_ref_qualifiers=200710L");
+ cpp_define (pfile, "__cpp_alias_templates=200704L");
+ }
+ if (cxx_dialect > cxx11)
+ {
+ /* Set feature test macros for C++14. */
+ cpp_define (pfile, "__cpp_return_type_deduction=201304L");
+ if (cxx_dialect <= cxx17)
+ {
+ cpp_define (pfile, "__cpp_init_captures=201304L");
+ cpp_define (pfile, "__cpp_generic_lambdas=201304L");
+ }
+ if (cxx_dialect <= cxx14)
+ cpp_define (pfile, "__cpp_constexpr=201304L");
+ cpp_define (pfile, "__cpp_decltype_auto=201304L");
+ cpp_define (pfile, "__cpp_aggregate_nsdmi=201304L");
+ cpp_define (pfile, "__cpp_variable_templates=201304L");
+ cpp_define (pfile, "__cpp_digit_separators=201309L");
+ }
+ if (cxx_dialect > cxx14)
+ {
+ /* Set feature test macros for C++17. */
+ cpp_define (pfile, "__cpp_unicode_characters=201411L");
+ cpp_define (pfile, "__cpp_static_assert=201411L");
+ cpp_define (pfile, "__cpp_namespace_attributes=201411L");
+ cpp_define (pfile, "__cpp_enumerator_attributes=201411L");
+ cpp_define (pfile, "__cpp_nested_namespace_definitions=201411L");
+ cpp_define (pfile, "__cpp_fold_expressions=201603L");
+ if (cxx_dialect <= cxx17)
+ cpp_define (pfile, "__cpp_nontype_template_args=201411L");
+ cpp_define (pfile, "__cpp_range_based_for=201603L");
+ if (cxx_dialect <= cxx17)
+ cpp_define (pfile, "__cpp_constexpr=201603L");
+ cpp_define (pfile, "__cpp_if_constexpr=201606L");
+ cpp_define (pfile, "__cpp_capture_star_this=201603L");
+ cpp_define (pfile, "__cpp_inline_variables=201606L");
+ cpp_define (pfile, "__cpp_aggregate_bases=201603L");
+ if (cxx_dialect <= cxx17)
+ cpp_define (pfile, "__cpp_deduction_guides=201703L");
+ cpp_define (pfile, "__cpp_noexcept_function_type=201510L");
+ /* Old macro, superseded by
+ __cpp_nontype_template_parameter_auto. */
+ cpp_define (pfile, "__cpp_template_auto=201606L");
+ cpp_define (pfile, "__cpp_structured_bindings=201606L");
+ cpp_define (pfile, "__cpp_variadic_using=201611L");
+ cpp_define (pfile, "__cpp_guaranteed_copy_elision=201606L");
+ cpp_define (pfile, "__cpp_nontype_template_parameter_auto=201606L");
+ }
+ if (cxx_dialect > cxx17)
+ {
+ /* Set feature test macros for C++20. */
+ cpp_define (pfile, "__cpp_init_captures=201803L");
+ cpp_define (pfile, "__cpp_generic_lambdas=201707L");
+ cpp_define (pfile, "__cpp_designated_initializers=201707L");
+ if (cxx_dialect <= cxx20)
+ cpp_define (pfile, "__cpp_constexpr=202002L");
+ cpp_define (pfile, "__cpp_constexpr_in_decltype=201711L");
+ cpp_define (pfile, "__cpp_conditional_explicit=201806L");
+ cpp_define (pfile, "__cpp_consteval=201811L");
+ cpp_define (pfile, "__cpp_constinit=201907L");
+ cpp_define (pfile, "__cpp_deduction_guides=201907L");
+ cpp_define (pfile, "__cpp_nontype_template_args=201911L");
+ cpp_define (pfile, "__cpp_nontype_template_parameter_class=201806L");
+ cpp_define (pfile, "__cpp_impl_destroying_delete=201806L");
+ cpp_define (pfile, "__cpp_constexpr_dynamic_alloc=201907L");
+ cpp_define (pfile, "__cpp_impl_three_way_comparison=201907L");
+ cpp_define (pfile, "__cpp_aggregate_paren_init=201902L");
+ cpp_define (pfile, "__cpp_using_enum=201907L");
+ }
+ if (cxx_dialect > cxx20)
+ {
+ /* Set feature test macros for C++23. */
+ cpp_define (pfile, "__cpp_size_t_suffix=202011L");
+ cpp_define (pfile, "__cpp_if_consteval=202106L");
+ cpp_define (pfile, "__cpp_constexpr=202110L");
+ cpp_define (pfile, "__cpp_multidimensional_subscript=202110L");
+ }
+ if (flag_concepts)
+ {
+ if (cxx_dialect >= cxx20)
+ cpp_define (pfile, "__cpp_concepts=202002L");
+ else
+ cpp_define (pfile, "__cpp_concepts=201507L");
+ }
+ if (flag_modules)
+ /* The std-defined value is 201907L, but I don't think we can
+ claim victory yet. 201810 is the p1103 date. */
+ cpp_define (pfile, "__cpp_modules=201810L");
+ if (flag_coroutines)
+ cpp_define (pfile, "__cpp_impl_coroutine=201902L"); /* n4861, DIS */
+ if (flag_tm)
+ /* Use a value smaller than the 201505 specified in
+ the TS, since we don't yet support atomic_cancel. */
+ cpp_define (pfile, "__cpp_transactional_memory=201500L");
+ if (flag_sized_deallocation)
+ cpp_define (pfile, "__cpp_sized_deallocation=201309L");
+ if (aligned_new_threshold)
+ {
+ cpp_define (pfile, "__cpp_aligned_new=201606L");
+ cpp_define_formatted (pfile, "__STDCPP_DEFAULT_NEW_ALIGNMENT__=%d",
+ aligned_new_threshold);
+ }
+ if (flag_new_ttp)
+ cpp_define (pfile, "__cpp_template_template_args=201611L");
+ if (flag_threadsafe_statics)
+ cpp_define (pfile, "__cpp_threadsafe_static_init=200806L");
+ if (flag_char8_t)
+ cpp_define (pfile, "__cpp_char8_t=201811L");
+#ifndef THREAD_MODEL_SPEC
+ /* Targets that define THREAD_MODEL_SPEC need to define
+ __STDCPP_THREADS__ in their config/XXX/XXX-c.c themselves. */
+ if (cxx_dialect >= cxx11 && strcmp (thread_model, "single") != 0)
+ cpp_define (pfile, "__STDCPP_THREADS__=1");
+#endif
+ if (flag_implicit_constexpr)
+ cpp_define (pfile, "__cpp_implicit_constexpr=20211111L");
+ }
+#endif // sdcpp
+#if 0 // sdcpp
+ /* Note that we define this for C as well, so that we know if
+ __attribute__((cleanup)) will interface with EH. */
+ if (flag_exceptions)
+ {
+ cpp_define (pfile, "__EXCEPTIONS");
+ if (c_dialect_cxx ())
+ cpp_define (pfile, "__cpp_exceptions=199711L");
+ }
+
+ /* Represents the C++ ABI version, always defined so it can be used while
+ preprocessing C and assembler. */
+ if (flag_abi_version == 0)
+ /* We should have set this to something real in c_common_post_options. */
+ gcc_unreachable ();
+ else if (flag_abi_version == 1)
+ /* Due to a historical accident, this version had the value
+ "102". */
+ builtin_define_with_int_value ("__GXX_ABI_VERSION", 102);
+ else
+ /* Newer versions have values 1002, 1003, .... */
+ builtin_define_with_int_value ("__GXX_ABI_VERSION",
+ 1000 + flag_abi_version);
+
+ /* libgcc needs to know this. */
+ if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ)
+ cpp_define (pfile, "__USING_SJLJ_EXCEPTIONS__");
+
+ /* limits.h and stdint.h need to know these. */
+ builtin_define_type_max ("__SCHAR_MAX__", signed_char_type_node);
+ builtin_define_type_max ("__SHRT_MAX__", short_integer_type_node);
+ builtin_define_type_max ("__INT_MAX__", integer_type_node);
+ builtin_define_type_max ("__LONG_MAX__", long_integer_type_node);
+ builtin_define_type_max ("__LONG_LONG_MAX__", long_long_integer_type_node);
+ builtin_define_type_minmax ("__WCHAR_MIN__", "__WCHAR_MAX__",
+ underlying_wchar_type_node);
+ builtin_define_type_minmax ("__WINT_MIN__", "__WINT_MAX__", wint_type_node);
+ builtin_define_type_max ("__PTRDIFF_MAX__", ptrdiff_type_node);
+ builtin_define_type_max ("__SIZE_MAX__", size_type_node);
+
+ /* These are needed for TS 18661-1. */
+ builtin_define_type_width ("__SCHAR_WIDTH__", signed_char_type_node,
+ unsigned_char_type_node);
+ builtin_define_type_width ("__SHRT_WIDTH__", short_integer_type_node,
+ short_unsigned_type_node);
+ builtin_define_type_width ("__INT_WIDTH__", integer_type_node,
+ unsigned_type_node);
+ builtin_define_type_width ("__LONG_WIDTH__", long_integer_type_node,
+ long_unsigned_type_node);
+ builtin_define_type_width ("__LONG_LONG_WIDTH__",
+ long_long_integer_type_node,
+ long_long_unsigned_type_node);
+ builtin_define_type_width ("__WCHAR_WIDTH__", underlying_wchar_type_node,
+ NULL_TREE);
+ builtin_define_type_width ("__WINT_WIDTH__", wint_type_node, NULL_TREE);
+ builtin_define_type_width ("__PTRDIFF_WIDTH__", ptrdiff_type_node, NULL_TREE);
+ builtin_define_type_width ("__SIZE_WIDTH__", size_type_node, NULL_TREE);
+#endif // sdcpp
+
+#if 0 // sdcpp
+ if (c_dialect_cxx ())
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i])
+ {
+ char buf[35+20+20];
+
+ /* These are used to configure the C++ library. */
+
+ if (!flag_iso || int_n_data[i].bitsize == POINTER_SIZE)
+ {
+ sprintf (buf, "__GLIBCXX_TYPE_INT_N_%d=__int%d", i, int_n_data[i].bitsize);
+ cpp_define (parse_in, buf);
+
+ sprintf (buf, "__GLIBCXX_BITSIZE_INT_N_%d=%d", i, int_n_data[i].bitsize);
+ cpp_define (parse_in, buf);
+ }
+ }
+
+ /* stdint.h and the testsuite need to know these. */
+ builtin_define_stdint_macros ();
+#endif // sdcpp
+
+ /* Provide information for library headers to determine whether to
+ define macros such as __STDC_IEC_559__ and
+ __STDC_IEC_559_COMPLEX__. */
+// sdcpp builtin_define_with_int_value ("__GCC_IEC_559", cpp_iec_559_value ());
+// sdcpp builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
+// sdcpp cpp_iec_559_complex_value ());
+
+ /* float.h needs these to correctly set FLT_EVAL_METHOD
+
+ We define two values:
+
+ __FLT_EVAL_METHOD__
+ Which, depending on the value given for
+ -fpermitted-flt-eval-methods, may be limited to only those values
+ for FLT_EVAL_METHOD defined in C99/C11.
+
+ __FLT_EVAL_METHOD_TS_18661_3__
+ Which always permits the values for FLT_EVAL_METHOD defined in
+ ISO/IEC TS 18661-3. */
+#if 0 // sdcpp
+ builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
+ c_flt_eval_method (true));
+ builtin_define_with_int_value ("__FLT_EVAL_METHOD_TS_18661_3__",
+ c_flt_eval_method (false));
+
+ /* And decfloat.h needs this. */
+ builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
+ TARGET_DEC_EVAL_METHOD);
+
+ builtin_define_float_constants ("FLT", "F", "%s", "F", float_type_node);
+ /* Cast the double precision constants. This is needed when single
+ precision constants are specified or when pragma FLOAT_CONST_DECIMAL64
+ is used. The correct result is computed by the compiler when using
+ macros that include a cast. We use a different cast for C++ to avoid
+ problems with -Wold-style-cast. */
+ builtin_define_float_constants ("DBL", "L",
+ (c_dialect_cxx ()
+ ? "double(%s)"
+ : "((double)%s)"),
+ "", double_type_node);
+ builtin_define_float_constants ("LDBL", "L", "%s", "L",
+ long_double_type_node);
+
+#endif // sdcpp
+#if 0 // sdcpp
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE)
+ continue;
+ char prefix[20], csuffix[20];
+ sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "X" : "");
+ sprintf (csuffix, "F%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "x" : "");
+ builtin_define_float_constants (prefix, ggc_strdup (csuffix), "%s",
+ csuffix, FLOATN_NX_TYPE_NODE (i));
+ }
+#endif // sdcpp
+
+ /* For float.h. */
+#if 0 // sdcpp
+ if (targetm.decimal_float_supported_p ())
+ {
+ builtin_define_decimal_float_constants ("DEC32", "DF",
+ dfloat32_type_node);
+ builtin_define_decimal_float_constants ("DEC64", "DD",
+ dfloat64_type_node);
+ builtin_define_decimal_float_constants ("DEC128", "DL",
+ dfloat128_type_node);
+ }
+
+ /* For fixed-point fibt, ibit, max, min, and epsilon. */
+ if (targetm.fixed_point_supported_p ())
+ {
+ builtin_define_fixed_point_constants ("SFRACT", "HR",
+ short_fract_type_node);
+ builtin_define_fixed_point_constants ("USFRACT", "UHR",
+ unsigned_short_fract_type_node);
+ builtin_define_fixed_point_constants ("FRACT", "R",
+ fract_type_node);
+ builtin_define_fixed_point_constants ("UFRACT", "UR",
+ unsigned_fract_type_node);
+ builtin_define_fixed_point_constants ("LFRACT", "LR",
+ long_fract_type_node);
+ builtin_define_fixed_point_constants ("ULFRACT", "ULR",
+ unsigned_long_fract_type_node);
+ builtin_define_fixed_point_constants ("LLFRACT", "LLR",
+ long_long_fract_type_node);
+ builtin_define_fixed_point_constants ("ULLFRACT", "ULLR",
+ unsigned_long_long_fract_type_node);
+ builtin_define_fixed_point_constants ("SACCUM", "HK",
+ short_accum_type_node);
+ builtin_define_fixed_point_constants ("USACCUM", "UHK",
+ unsigned_short_accum_type_node);
+ builtin_define_fixed_point_constants ("ACCUM", "K",
+ accum_type_node);
+ builtin_define_fixed_point_constants ("UACCUM", "UK",
+ unsigned_accum_type_node);
+ builtin_define_fixed_point_constants ("LACCUM", "LK",
+ long_accum_type_node);
+ builtin_define_fixed_point_constants ("ULACCUM", "ULK",
+ unsigned_long_accum_type_node);
+ builtin_define_fixed_point_constants ("LLACCUM", "LLK",
+ long_long_accum_type_node);
+ builtin_define_fixed_point_constants ("ULLACCUM", "ULLK",
+ unsigned_long_long_accum_type_node);
+
+ builtin_define_fixed_point_constants ("QQ", "", qq_type_node);
+ builtin_define_fixed_point_constants ("HQ", "", hq_type_node);
+ builtin_define_fixed_point_constants ("SQ", "", sq_type_node);
+ builtin_define_fixed_point_constants ("DQ", "", dq_type_node);
+ builtin_define_fixed_point_constants ("TQ", "", tq_type_node);
+ builtin_define_fixed_point_constants ("UQQ", "", uqq_type_node);
+ builtin_define_fixed_point_constants ("UHQ", "", uhq_type_node);
+ builtin_define_fixed_point_constants ("USQ", "", usq_type_node);
+ builtin_define_fixed_point_constants ("UDQ", "", udq_type_node);
+ builtin_define_fixed_point_constants ("UTQ", "", utq_type_node);
+ builtin_define_fixed_point_constants ("HA", "", ha_type_node);
+ builtin_define_fixed_point_constants ("SA", "", sa_type_node);
+ builtin_define_fixed_point_constants ("DA", "", da_type_node);
+ builtin_define_fixed_point_constants ("TA", "", ta_type_node);
+ builtin_define_fixed_point_constants ("UHA", "", uha_type_node);
+ builtin_define_fixed_point_constants ("USA", "", usa_type_node);
+ builtin_define_fixed_point_constants ("UDA", "", uda_type_node);
+ builtin_define_fixed_point_constants ("UTA", "", uta_type_node);
+ }
+
+ /* For libgcc-internal use only. */
+ if (flag_building_libgcc)
+ {
+ /* Properties of floating-point modes for libgcc2.c. */
+ opt_scalar_float_mode mode_iter;
+ FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_FLOAT)
+ {
+ scalar_float_mode mode = mode_iter.require ();
+ const char *name = GET_MODE_NAME (mode);
+ const size_t name_len = strlen (name);
+ char float_h_prefix[16] = "";
+ char *macro_name
+ = XALLOCAVEC (char, name_len + sizeof ("__LIBGCC__MANT_DIG__"));
+ sprintf (macro_name, "__LIBGCC_%s_MANT_DIG__", name);
+ builtin_define_with_int_value (macro_name,
+ REAL_MODE_FORMAT (mode)->p);
+ if (!targetm.scalar_mode_supported_p (mode)
+ || !targetm.libgcc_floating_mode_supported_p (mode))
+ continue;
+ macro_name = XALLOCAVEC (char, name_len
+ + sizeof ("__LIBGCC_HAS__MODE__"));
+ sprintf (macro_name, "__LIBGCC_HAS_%s_MODE__", name);
+ cpp_define (pfile, macro_name);
+ macro_name = XALLOCAVEC (char, name_len
+ + sizeof ("__LIBGCC__FUNC_EXT__"));
+ sprintf (macro_name, "__LIBGCC_%s_FUNC_EXT__", name);
+ char suffix[20] = "";
+ if (mode == TYPE_MODE (double_type_node))
+ {
+ /* Empty suffix correct. */
+ memcpy (float_h_prefix, "DBL", 4);
+ }
+ else if (mode == TYPE_MODE (float_type_node))
+ {
+ suffix[0] = 'f';
+ memcpy (float_h_prefix, "FLT", 4);
+ }
+ else if (mode == TYPE_MODE (long_double_type_node))
+ {
+ suffix[0] = 'l';
+ memcpy (float_h_prefix, "LDBL", 5);
+ }
+ else
+ {
+ bool found_suffix = false;
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE
+ && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i)))
+ {
+ sprintf (suffix, "f%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "x" : "");
+ found_suffix = true;
+ sprintf (float_h_prefix, "FLT%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "X" : "");
+ break;
+ }
+ gcc_assert (found_suffix);
+ }
+ builtin_define_with_value (macro_name, suffix, 0);
+
+ /* The way __LIBGCC_*_EXCESS_PRECISION__ is used is about
+ eliminating excess precision from results assigned to
+ variables - meaning it should be about the implicit excess
+ precision only. */
+ bool excess_precision = false;
+ machine_mode float16_type_mode = (float16_type_node
+ ? TYPE_MODE (float16_type_node)
+ : VOIDmode);
+ switch (targetm.c.excess_precision
+ (EXCESS_PRECISION_TYPE_IMPLICIT))
+ {
+ case FLT_EVAL_METHOD_UNPREDICTABLE:
+ case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+ excess_precision = (mode == float16_type_mode
+ || mode == TYPE_MODE (float_type_node)
+ || mode == TYPE_MODE (double_type_node));
+ break;
+
+ case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+ excess_precision = (mode == float16_type_mode
+ || mode == TYPE_MODE (float_type_node));
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+ excess_precision = mode == float16_type_mode;
+ break;
+ case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
+ excess_precision = false;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ macro_name = XALLOCAVEC (char, name_len
+ + sizeof ("__LIBGCC__EXCESS_PRECISION__"));
+ sprintf (macro_name, "__LIBGCC_%s_EXCESS_PRECISION__", name);
+ builtin_define_with_int_value (macro_name, excess_precision);
+
+ char val_name[64];
+
+ macro_name = XALLOCAVEC (char, name_len
+ + sizeof ("__LIBGCC__EPSILON__"));
+ sprintf (macro_name, "__LIBGCC_%s_EPSILON__", name);
+ sprintf (val_name, "__%s_EPSILON__", float_h_prefix);
+ builtin_define_with_value (macro_name, val_name, 0);
+
+ macro_name = XALLOCAVEC (char, name_len + sizeof ("__LIBGCC__MAX__"));
+ sprintf (macro_name, "__LIBGCC_%s_MAX__", name);
+ sprintf (val_name, "__%s_MAX__", float_h_prefix);
+ builtin_define_with_value (macro_name, val_name, 0);
+
+ macro_name = XALLOCAVEC (char, name_len + sizeof ("__LIBGCC__MIN__"));
+ sprintf (macro_name, "__LIBGCC_%s_MIN__", name);
+ sprintf (val_name, "__%s_MIN__", float_h_prefix);
+ builtin_define_with_value (macro_name, val_name, 0);
+
+#ifdef HAVE_adddf3
+ builtin_define_with_int_value ("__LIBGCC_HAVE_HWDBL__",
+ HAVE_adddf3);
+#endif
+ }
+
+ /* For libgcc crtstuff.c and libgcc2.c. */
+ builtin_define_with_int_value ("__LIBGCC_EH_TABLES_CAN_BE_READ_ONLY__",
+ EH_TABLES_CAN_BE_READ_ONLY);
+#ifdef EH_FRAME_SECTION_NAME
+ builtin_define_with_value ("__LIBGCC_EH_FRAME_SECTION_NAME__",
+ EH_FRAME_SECTION_NAME, 1);
+#endif
+#ifdef CTORS_SECTION_ASM_OP
+ builtin_define_with_value ("__LIBGCC_CTORS_SECTION_ASM_OP__",
+ CTORS_SECTION_ASM_OP, 1);
+#endif
+#ifdef DTORS_SECTION_ASM_OP
+ builtin_define_with_value ("__LIBGCC_DTORS_SECTION_ASM_OP__",
+ DTORS_SECTION_ASM_OP, 1);
+#endif
+#ifdef TEXT_SECTION_ASM_OP
+ builtin_define_with_value ("__LIBGCC_TEXT_SECTION_ASM_OP__",
+ TEXT_SECTION_ASM_OP, 1);
+#endif
+#ifdef INIT_SECTION_ASM_OP
+ builtin_define_with_value ("__LIBGCC_INIT_SECTION_ASM_OP__",
+ INIT_SECTION_ASM_OP, 1);
+#endif
+#ifdef INIT_ARRAY_SECTION_ASM_OP
+ /* Despite the name of this target macro, the expansion is not
+ actually used, and may be empty rather than a string
+ constant. */
+ cpp_define (pfile, "__LIBGCC_INIT_ARRAY_SECTION_ASM_OP__");
+#endif
+
+ /* For libgcc enable-execute-stack.c. */
+ builtin_define_with_int_value ("__LIBGCC_TRAMPOLINE_SIZE__",
+ TRAMPOLINE_SIZE);
+
+ /* For libgcc generic-morestack.c and unwinder code. */
+ if (STACK_GROWS_DOWNWARD)
+ cpp_define (pfile, "__LIBGCC_STACK_GROWS_DOWNWARD__");
+
+ /* For libgcc unwinder code. */
+#ifdef DONT_USE_BUILTIN_SETJMP
+ cpp_define (pfile, "__LIBGCC_DONT_USE_BUILTIN_SETJMP__");
+#endif
+#ifdef DWARF_ALT_FRAME_RETURN_COLUMN
+ builtin_define_with_int_value ("__LIBGCC_DWARF_ALT_FRAME_RETURN_COLUMN__",
+ DWARF_ALT_FRAME_RETURN_COLUMN);
+#endif
+ builtin_define_with_int_value ("__LIBGCC_DWARF_FRAME_REGISTERS__",
+ DWARF_FRAME_REGISTERS);
+#ifdef EH_RETURN_STACKADJ_RTX
+ cpp_define (pfile, "__LIBGCC_EH_RETURN_STACKADJ_RTX__");
+#endif
+#ifdef JMP_BUF_SIZE
+ builtin_define_with_int_value ("__LIBGCC_JMP_BUF_SIZE__",
+ JMP_BUF_SIZE);
+#endif
+ builtin_define_with_int_value ("__LIBGCC_STACK_POINTER_REGNUM__",
+ STACK_POINTER_REGNUM);
+
+ /* For libgcov. */
+ builtin_define_with_int_value ("__LIBGCC_VTABLE_USES_DESCRIPTORS__",
+ TARGET_VTABLE_USES_DESCRIPTORS);
+ builtin_define_with_int_value ("__LIBGCC_GCOV_TYPE_SIZE",
+ targetm.gcov_type_size());
+ }
+#endif // sdcpp
+
+ /* For use in assembly language. */
+ builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
+ builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
+
+ /* Misc. */
+ if (flag_gnu89_inline)
+ cpp_define (pfile, "__GNUC_GNU_INLINE__");
+ else
+ cpp_define (pfile, "__GNUC_STDC_INLINE__");
+
+ if (flag_no_inline)
+ cpp_define (pfile, "__NO_INLINE__");
+
+ if (flag_iso)
+ cpp_define (pfile, "__STRICT_ANSI__");
+
+ if (!flag_signed_char)
+ cpp_define (pfile, "__CHAR_UNSIGNED__");
+
+#if 0 // sdcpp
+ if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
+ cpp_define (pfile, "__WCHAR_UNSIGNED__");
+
+ cpp_atomic_builtins (pfile);
+
+ /* Show support for __builtin_speculation_safe_value () if the target
+ has been updated to fully support it. */
+ if (targetm.have_speculation_safe_value (false))
+ cpp_define (pfile, "__HAVE_SPECULATION_SAFE_VALUE");
+#endif
+
+#ifdef DWARF2_UNWIND_INFO
+ if (dwarf2out_do_cfi_asm ())
+ cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
+#endif
+
+ /* Make the choice of ObjC runtime visible to source code. */
+ if (c_dialect_objc () && flag_next_runtime)
+ cpp_define (pfile, "__NEXT_RUNTIME__");
+
+ /* Show the availability of some target pragmas. */
+ cpp_define (pfile, "__PRAGMA_REDEFINE_EXTNAME");
+
+ /* Make the choice of the stack protector runtime visible to source code.
+ The macro names and values here were chosen for compatibility with an
+ earlier implementation, i.e. ProPolice. */
+ if (flag_stack_protect == SPCT_FLAG_EXPLICIT)
+ cpp_define (pfile, "__SSP_EXPLICIT__=4");
+ if (flag_stack_protect == SPCT_FLAG_STRONG)
+ cpp_define (pfile, "__SSP_STRONG__=3");
+ if (flag_stack_protect == SPCT_FLAG_ALL)
+ cpp_define (pfile, "__SSP_ALL__=2");
+ else if (flag_stack_protect == SPCT_FLAG_DEFAULT)
+ cpp_define (pfile, "__SSP__=1");
+
+ if (flag_openacc)
+ cpp_define (pfile, "_OPENACC=201711");
+
+ if (flag_openmp)
+ cpp_define (pfile, "_OPENMP=201511");
+
+#if 0 // sdcpp
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (int_n_enabled_p[i])
+ {
+ char buf[15+20];
+ sprintf(buf, "__SIZEOF_INT%d__", int_n_data[i].bitsize);
+ builtin_define_type_sizeof (buf,
+ int_n_trees[i].signed_type);
+ }
+#endif // sdcpp
+ builtin_define_type_sizeof ("__SIZEOF_WCHAR_T__", wchar_type_node);
+ builtin_define_type_sizeof ("__SIZEOF_WINT_T__", wint_type_node);
+ builtin_define_type_sizeof ("__SIZEOF_PTRDIFF_T__",
+ unsigned_ptrdiff_type_node);
+
+ /* A straightforward target hook doesn't work, because of problems
+ linking that hook's body when part of non-C front ends. */
+# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
+# define preprocessing_trad_p() (cpp_get_options (pfile)->traditional)
+# define builtin_define(TXT) cpp_define (pfile, TXT)
+# define builtin_assert(TXT) cpp_assert (pfile, TXT)
+// sdcpp TARGET_CPU_CPP_BUILTINS ();
+// sdcpp TARGET_OS_CPP_BUILTINS ();
+// sdcpp TARGET_OBJFMT_CPP_BUILTINS ();
+
+ /* Support the __declspec keyword by turning them into attributes.
+ Note that the current way we do this may result in a collision
+ with predefined attributes later on. This can be solved by using
+ one attribute, say __declspec__, and passing args to it. The
+ problem with that approach is that args are not accumulated: each
+ new appearance would clobber any existing args. */
+//sdcpp if (TARGET_DECLSPEC)
+//sdcpp builtin_define ("__declspec(x)=__attribute__((x))");
+
+ /* If decimal floating point is supported, tell the user if the
+ alternate format (BID) is used instead of the standard (DPD)
+ format. */
+ if (ENABLE_DECIMAL_FLOAT && ENABLE_DECIMAL_BID_FORMAT)
+ cpp_define (pfile, "__DECIMAL_BID_FORMAT__");
+}
+
+/* Pass an object-like macro. If it doesn't lie in the user's
+ namespace, defines it unconditionally. Otherwise define a version
+ with two leading underscores, and another version with two leading
+ and trailing underscores, and define the original only if an ISO
+ standard was not nominated.
+
+ e.g. passing "unix" defines "__unix", "__unix__" and possibly
+ "unix". Passing "_mips" defines "__mips", "__mips__" and possibly
+ "_mips". */
+void
+builtin_define_std (const char *macro)
+{
+ size_t len = strlen (macro);
+ char *buff = (char *) alloca (len + 5);
+ char *p = buff + 2;
+ char *q = p + len;
+
+ /* prepend __ (or maybe just _) if in user's namespace. */
+ memcpy (p, macro, len + 1);
+ if (!( *p == '_' && (p[1] == '_' || ISUPPER (p[1]))))
+ {
+ if (*p != '_')
+ *--p = '_';
+ if (p[1] != '_')
+ *--p = '_';
+ }
+ cpp_define (parse_in, p);
+
+ /* If it was in user's namespace... */
+ if (p != buff + 2)
+ {
+ /* Define the macro with leading and following __. */
+ if (q[-1] != '_')
+ *q++ = '_';
+ if (q[-2] != '_')
+ *q++ = '_';
+ *q = '\0';
+ cpp_define (parse_in, p);
+
+ /* Finally, define the original macro if permitted. */
+ if (!flag_iso)
+ cpp_define (parse_in, macro);
+ }
+}
+
+/* Pass an object-like macro and a value to define it to. The third
+ parameter says whether or not to turn the value into a string
+ constant. */
+void
+builtin_define_with_value (const char *macro, const char *expansion, int is_str)
+{
+ char *buf;
+ size_t mlen = strlen (macro);
+ size_t elen = strlen (expansion);
+ size_t extra = 2; /* space for an = and a NUL */
+
+ if (is_str)
+ {
+ char *quoted_expansion = (char *) alloca (elen * 4 + 1);
+ const char *p;
+ char *q;
+ extra += 2; /* space for two quote marks */
+ for (p = expansion, q = quoted_expansion; *p; p++)
+ {
+ switch (*p)
+ {
+ case '\n':
+ *q++ = '\\';
+ *q++ = 'n';
+ break;
+
+ case '\t':
+ *q++ = '\\';
+ *q++ = 't';
+ break;
+
+ case '\\':
+ *q++ = '\\';
+ *q++ = '\\';
+ break;
+
+ case '"':
+ *q++ = '\\';
+ *q++ = '"';
+ break;
+
+ default:
+ if (ISPRINT ((unsigned char) *p))
+ *q++ = *p;
+ else
+ {
+ sprintf (q, "\\%03o", (unsigned char) *p);
+ q += 4;
+ }
+ }
+ }
+ *q = '\0';
+ expansion = quoted_expansion;
+ elen = q - expansion;
+ }
+
+ buf = (char *) alloca (mlen + elen + extra);
+ if (is_str)
+ sprintf (buf, "%s=\"%s\"", macro, expansion);
+ else
+ sprintf (buf, "%s=%s", macro, expansion);
+
+ cpp_define (parse_in, buf);
+}
+
+
+/* Pass an object-like macro and an integer value to define it to. */
+void
+builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value)
+{
+ char *buf;
+ size_t mlen = strlen (macro);
+ size_t vlen = 18;
+ size_t extra = 2; /* space for = and NUL. */
+
+ buf = (char *) alloca (mlen + vlen + extra);
+ memcpy (buf, macro, mlen);
+ buf[mlen] = '=';
+ sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
+
+ cpp_define (parse_in, buf);
+}
+
+/* builtin_define_with_hex_fp_value is very expensive, so the following
+ array and function allows it to be done lazily when __DBL_MAX__
+ etc. is first used. */
+
+struct GTY(()) lazy_hex_fp_value_struct
+{
+ const char *hex_str;
+ machine_mode mode;
+ int digits;
+ const char *fp_suffix;
+};
+/* Number of the expensive to compute macros we should evaluate lazily.
+ Each builtin_define_float_constants invocation calls
+ builtin_define_with_hex_fp_value 5 times and builtin_define_float_constants
+ is called for FLT, DBL, LDBL and up to NUM_FLOATN_NX_TYPES times for
+ FLTNN*. */
+#define LAZY_HEX_FP_VALUES_CNT (5 * (3 + NUM_FLOATN_NX_TYPES))
+#if 0 // sdcpp
+static GTY(()) struct lazy_hex_fp_value_struct
+ lazy_hex_fp_values[LAZY_HEX_FP_VALUES_CNT];
+static GTY(()) unsigned lazy_hex_fp_value_count;
+
+static void
+lazy_hex_fp_value (cpp_reader *, cpp_macro *macro, unsigned num)
+{
+ REAL_VALUE_TYPE real;
+ char dec_str[64], buf1[256];
+
+ gcc_checking_assert (num < lazy_hex_fp_value_count);
+
+ real_from_string (&real, lazy_hex_fp_values[num].hex_str);
+ real_to_decimal_for_mode (dec_str, &real, sizeof (dec_str),
+ lazy_hex_fp_values[num].digits, 0,
+ lazy_hex_fp_values[num].mode);
+
+ size_t len
+ = sprintf (buf1, "%s%s", dec_str, lazy_hex_fp_values[num].fp_suffix);
+ gcc_assert (len < sizeof (buf1));
+ for (unsigned idx = 0; idx < macro->count; idx++)
+ if (macro->exp.tokens[idx].type == CPP_NUMBER)
+ {
+ macro->exp.tokens[idx].val.str.len = len;
+ macro->exp.tokens[idx].val.str.text
+ = (const unsigned char *) ggc_strdup (buf1);
+ return;
+ }
+
+ /* We must have replaced a token. */
+ gcc_unreachable ();
+}
+
+/* Pass an object-like macro a hexadecimal floating-point value. */
+static void
+builtin_define_with_hex_fp_value (const char *macro,
+ tree type, int digits,
+ const char *hex_str,
+ const char *fp_suffix,
+ const char *fp_cast)
+{
+ REAL_VALUE_TYPE real;
+ char dec_str[64], buf[256], buf1[128], buf2[64];
+
+ /* This is very expensive, so if possible expand them lazily. */
+ if (lazy_hex_fp_value_count < LAZY_HEX_FP_VALUES_CNT
+ && flag_dump_macros == 0
+ && flag_dump_go_spec == NULL
+ && !cpp_get_options (parse_in)->traditional)
+ {
+ if (lazy_hex_fp_value_count == 0)
+ cpp_get_callbacks (parse_in)->user_lazy_macro = lazy_hex_fp_value;
+ sprintf (buf2, fp_cast, "1.1");
+ sprintf (buf1, "%s=%s", macro, buf2);
+ cpp_define (parse_in, buf1);
+ struct cpp_hashnode *node = C_CPP_HASHNODE (get_identifier (macro));
+ lazy_hex_fp_values[lazy_hex_fp_value_count].hex_str
+ = ggc_strdup (hex_str);
+ lazy_hex_fp_values[lazy_hex_fp_value_count].mode = TYPE_MODE (type);
+ lazy_hex_fp_values[lazy_hex_fp_value_count].digits = digits;
+ lazy_hex_fp_values[lazy_hex_fp_value_count].fp_suffix = fp_suffix;
+ cpp_define_lazily (parse_in, node, lazy_hex_fp_value_count++);
+ return;
+ }
+
+ /* Hex values are really cool and convenient, except that they're
+ not supported in strict ISO C90 mode. First, the "p-" sequence
+ is not valid as part of a preprocessor number. Second, we get a
+ pedwarn from the preprocessor, which has no context, so we can't
+ suppress the warning with __extension__.
+
+ So instead what we do is construct the number in hex (because
+ it's easy to get the exact correct value), parse it as a real,
+ then print it back out as decimal. */
+
+ real_from_string (&real, hex_str);
+ real_to_decimal_for_mode (dec_str, &real, sizeof (dec_str), digits, 0,
+ TYPE_MODE (type));
+
+ /* Assemble the macro in the following fashion
+ macro = fp_cast [dec_str fp_suffix] */
+ sprintf (buf2, "%s%s", dec_str, fp_suffix);
+ sprintf (buf1, fp_cast, buf2);
+ sprintf (buf, "%s=%s", macro, buf1);
+
+ cpp_define (parse_in, buf);
+}
+#endif // sdcpp
+
+/* Return a string constant for the suffix for a value of type TYPE
+ promoted according to the integer promotions. The type must be one
+ of the standard integer type nodes. */
+
+#if 0 // sdcpp
+static const char *
+type_suffix (tree type)
+{
+ static const char *const suffixes[] = { "", "U", "L", "UL", "LL", "ULL" };
+ int unsigned_suffix;
+ int is_long;
+ int tp = TYPE_PRECISION (type);
+
+ if (type == long_long_integer_type_node
+ || type == long_long_unsigned_type_node
+ || tp > TYPE_PRECISION (long_integer_type_node))
+ is_long = 2;
+ else if (type == long_integer_type_node
+ || type == long_unsigned_type_node
+ || tp > TYPE_PRECISION (integer_type_node))
+ is_long = 1;
+ else if (type == integer_type_node
+ || type == unsigned_type_node
+ || type == short_integer_type_node
+ || type == short_unsigned_type_node
+ || type == signed_char_type_node
+ || type == unsigned_char_type_node
+ /* ??? "char" is not a signed or unsigned integer type and
+ so is not permitted for the standard typedefs, but some
+ systems use it anyway. */
+ || type == char_type_node)
+ is_long = 0;
+ else
+ gcc_unreachable ();
+
+ unsigned_suffix = TYPE_UNSIGNED (type);
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ unsigned_suffix = 0;
+ return suffixes[is_long * 2 + unsigned_suffix];
+}
+
+/* Define MACRO as a <stdint.h> constant-suffix macro for TYPE. */
+static void
+builtin_define_constants (const char *macro, tree type)
+{
+ const char *suffix;
+ char *buf;
+
+ suffix = type_suffix (type);
+
+ if (suffix[0] == 0)
+ {
+ buf = (char *) alloca (strlen (macro) + 6);
+ sprintf (buf, "%s(c)=c", macro);
+ }
+ else
+ {
+ buf = (char *) alloca (strlen (macro) + 9 + strlen (suffix) + 1);
+ sprintf (buf, "%s(c)=c ## %s", macro, suffix);
+ }
+
+ cpp_define (parse_in, buf);
+}
+
+/* Define MAX for TYPE based on the precision of the type. */
+
+static void
+builtin_define_type_max (const char *macro, tree type)
+{
+ builtin_define_type_minmax (NULL, macro, type);
+}
+
+/* Given a value with COUNT LSBs set, fill BUF with a hexidecimal
+ representation of that value. For example, a COUNT of 10 would
+ return "0x3ff". */
+
+static void
+print_bits_of_hex (char *buf, int bufsz, int count)
+{
+ gcc_assert (bufsz > 3);
+ *buf++ = '0';
+ *buf++ = 'x';
+ bufsz -= 2;
+
+ gcc_assert (count > 0);
+
+ switch (count % 4) {
+ case 0:
+ break;
+ case 1:
+ *buf++ = '1';
+ bufsz --;
+ count -= 1;
+ break;
+ case 2:
+ *buf++ = '3';
+ bufsz --;
+ count -= 2;
+ break;
+ case 3:
+ *buf++ = '7';
+ bufsz --;
+ count -= 3;
+ break;
+ }
+ while (count >= 4)
+ {
+ gcc_assert (bufsz > 1);
+ *buf++ = 'f';
+ bufsz --;
+ count -= 4;
+ }
+ gcc_assert (bufsz > 0);
+ *buf++ = 0;
+}
+
+/* Define MIN_MACRO (if not NULL) and MAX_MACRO for TYPE based on the
+ precision of the type. */
+
+static void
+builtin_define_type_minmax (const char *min_macro, const char *max_macro,
+ tree type)
+{
+#define PBOH_SZ (MAX_BITSIZE_MODE_ANY_INT/4+4)
+ char value[PBOH_SZ];
+
+ const char *suffix;
+ char *buf;
+ int bits;
+
+ bits = TYPE_PRECISION (type) + (TYPE_UNSIGNED (type) ? 0 : -1);
+
+ print_bits_of_hex (value, PBOH_SZ, bits);
+
+ suffix = type_suffix (type);
+
+ buf = (char *) alloca (strlen (max_macro) + 1 + strlen (value)
+ + strlen (suffix) + 1);
+ sprintf (buf, "%s=%s%s", max_macro, value, suffix);
+
+ cpp_define (parse_in, buf);
+
+ if (min_macro)
+ {
+ if (TYPE_UNSIGNED (type))
+ {
+ buf = (char *) alloca (strlen (min_macro) + 2 + strlen (suffix) + 1);
+ sprintf (buf, "%s=0%s", min_macro, suffix);
+ }
+ else
+ {
+ buf = (char *) alloca (strlen (min_macro) + 3
+ + strlen (max_macro) + 6);
+ sprintf (buf, "%s=(-%s - 1)", min_macro, max_macro);
+ }
+ cpp_define (parse_in, buf);
+ }
+}
+
+/* Define WIDTH_MACRO for the width of TYPE. If TYPE2 is not NULL,
+ both types must have the same width. */
+
+static void
+builtin_define_type_width (const char *width_macro, tree type, tree type2)
+{
+ if (type2 != NULL_TREE)
+ gcc_assert (TYPE_PRECISION (type) == TYPE_PRECISION (type2));
+ builtin_define_with_int_value (width_macro, TYPE_PRECISION (type));
+}
+
+#include "gt-c-family-c-cppbuiltin.h"
+#endif // sdcpp
diff --git a/support/cpp/gcc/c-family/c-dump.cc b/support/cpp/gcc/c-family/c-dump.cc
new file mode 100644
index 000000000..7904daf66
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-dump.cc
@@ -0,0 +1,91 @@
+/* Tree-dumping functionality for C-family languages.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Written by Mark Mitchell <mark@codesourcery.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.
+
+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 "c-common.h"
+
+#if 0 // sdcpp
+#include "tree-dump.h"
+
+/* Dump any C-specific tree codes and attributes of common codes. */
+
+static void
+dump_stmt (dump_info_p di, const_tree t)
+{
+ if (EXPR_HAS_LOCATION (t))
+ dump_int (di, "line", EXPR_LINENO (t));
+}
+
+bool
+c_dump_tree (void *dump_info, tree t)
+{
+ enum tree_code code;
+ dump_info_p di = (dump_info_p) dump_info;
+
+ /* Figure out what kind of node this is. */
+ code = TREE_CODE (t);
+
+ switch (code)
+ {
+ case FIELD_DECL:
+ if (DECL_C_BIT_FIELD (t))
+ dump_string (di, "bitfield");
+ break;
+
+ case BREAK_STMT:
+ case CONTINUE_STMT:
+ dump_stmt (di, t);
+ break;
+
+ case DO_STMT:
+ dump_stmt (di, t);
+ dump_child ("body", DO_BODY (t));
+ dump_child ("cond", DO_COND (t));
+ break;
+
+ case FOR_STMT:
+ dump_stmt (di, t);
+ dump_child ("init", FOR_INIT_STMT (t));
+ dump_child ("cond", FOR_COND (t));
+ dump_child ("expr", FOR_EXPR (t));
+ dump_child ("body", FOR_BODY (t));
+ break;
+
+ case SWITCH_STMT:
+ dump_stmt (di, t);
+ dump_child ("cond", SWITCH_STMT_COND (t));
+ dump_child ("body", SWITCH_STMT_BODY (t));
+ break;
+
+ case WHILE_STMT:
+ dump_stmt (di, t);
+ dump_child ("cond", WHILE_COND (t));
+ dump_child ("body", WHILE_BODY (t));
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+#endif
diff --git a/support/cpp/gcc/c-family/c-format.h b/support/cpp/gcc/c-family/c-format.h
new file mode 100644
index 000000000..7f32f8d64
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-format.h
@@ -0,0 +1,354 @@
+/* Check calls to formatted I/O functions (-Wformat).
+ 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/>. */
+
+#ifndef GCC_C_FORMAT_H
+#define GCC_C_FORMAT_H
+
+/* The meaningfully distinct length modifiers for format checking recognized
+ by GCC. */
+enum format_lengths
+{
+ FMT_LEN_none,
+ FMT_LEN_hh,
+ FMT_LEN_h,
+ FMT_LEN_l,
+ FMT_LEN_ll,
+ FMT_LEN_L,
+ FMT_LEN_z,
+ FMT_LEN_t,
+ FMT_LEN_j,
+ FMT_LEN_H,
+ FMT_LEN_D,
+ FMT_LEN_DD,
+ FMT_LEN_w, /* GCC's HOST_WIDE_INT. */
+ FMT_LEN_MAX
+};
+
+
+/* The standard versions in which various format features appeared. */
+enum format_std_version
+{
+ STD_C89,
+ STD_C94,
+ STD_C9L, /* C99, but treat as C89 if -Wno-long-long. */
+ STD_C99,
+ STD_C2X,
+ STD_EXT
+};
+
+/* Flags that may apply to a particular kind of format checked by GCC. */
+enum
+{
+ /* This format converts arguments of types determined by the
+ format string. */
+ FMT_FLAG_ARG_CONVERT = 1,
+ /* The scanf allocation 'a' kludge applies to this format kind. */
+ FMT_FLAG_SCANF_A_KLUDGE = 2,
+ /* A % during parsing a specifier is allowed to be a modified % rather
+ that indicating the format is broken and we are out-of-sync. */
+ FMT_FLAG_FANCY_PERCENT_OK = 4,
+ /* With $ operand numbers, it is OK to reference the same argument more
+ than once. */
+ FMT_FLAG_DOLLAR_MULTIPLE = 8,
+ /* This format type uses $ operand numbers (strfmon doesn't). */
+ FMT_FLAG_USE_DOLLAR = 16,
+ /* Zero width is bad in this type of format (scanf). */
+ FMT_FLAG_ZERO_WIDTH_BAD = 32,
+ /* Empty precision specification is OK in this type of format (printf). */
+ FMT_FLAG_EMPTY_PREC_OK = 64,
+ /* Gaps are allowed in the arguments with $ operand numbers if all
+ arguments are pointers (scanf). */
+ FMT_FLAG_DOLLAR_GAP_POINTER_OK = 128,
+ /* The format arg is an opaque object that will be parsed by an external
+ facility. */
+ FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL = 256
+ /* Not included here: details of whether width or precision may occur
+ (controlled by width_char and precision_char); details of whether
+ '*' can be used for these (width_type and precision_type); details
+ of whether length modifiers can occur (length_char_specs). */
+};
+
+/* Structure describing a length modifier supported in format checking, and
+ possibly a doubled version such as "hh". */
+struct format_length_info
+{
+ /* Name of the single-character length modifier. If prefixed by
+ a zero character, it describes a multi character length
+ modifier, like I64, I32, etc. */
+ const char *name;
+ /* Index into a format_char_info.types array. */
+ enum format_lengths index;
+ /* Standard version this length appears in. */
+ enum format_std_version std;
+ /* Same, if the modifier can be repeated, or NULL if it can't. */
+ const char *double_name;
+ enum format_lengths double_index;
+ enum format_std_version double_std;
+
+ /* If this flag is set, just scalar width identity is checked, and
+ not the type identity itself. */
+ int scalar_identity_flag;
+};
+
+
+/* Structure describing the combination of a conversion specifier
+ (or a set of specifiers which act identically) and a length modifier. */
+struct format_type_detail
+{
+ /* The standard version this combination of length and type appeared in.
+ This is only relevant if greater than those for length and type
+ individually; otherwise it is ignored. */
+ enum format_std_version std;
+ /* The name to use for the type, if different from that generated internally
+ (e.g., "signed size_t"). */
+ const char *name;
+ /* The type itself. */
+ tree *type;
+};
+
+
+/* Macros to fill out tables of these. */
+#define NOARGUMENTS { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
+#define BADLEN { STD_C89, NULL, NULL }
+#define NOLENGTHS { BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
+
+
+/* Structure describing a format conversion specifier (or a set of specifiers
+ which act identically), and the length modifiers used with it. */
+struct format_char_info
+{
+ const char *format_chars;
+ int pointer_count;
+ enum format_std_version std;
+ /* Types accepted for each length modifier. */
+ format_type_detail types[FMT_LEN_MAX];
+ /* List of other modifier characters allowed with these specifiers.
+ This lists flags, and additionally "w" for width, "p" for precision
+ (right precision, for strfmon), "#" for left precision (strfmon),
+ "a" for scanf "a" allocation extension (not applicable in C99 mode),
+ "*" for scanf suppression, and "E" and "O" for those strftime
+ modifiers. */
+ const char *flag_chars;
+ /* List of additional flags describing these conversion specifiers.
+ "c" for generic character pointers being allowed, "2" for strftime
+ two digit year formats, "3" for strftime formats giving two digit
+ years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
+ "o" if use of strftime "O" is a GNU extension beyond C99,
+ "p" if use of strftime "O" is a C2x feature,
+ "W" if the argument is a pointer which is dereferenced and written into,
+ "R" if the argument is a pointer which is dereferenced and read from,
+ "i" for printf integer formats where the '0' flag is ignored with
+ precision, and "[" for the starting character of a scanf scanset,
+ "<" if the specifier introduces a quoted sequence (such as "%<"),
+ ">" if the specifier terminates a quoted sequence (such as "%>"),
+ "[" if the specifier introduces a color sequence (such as "%r"),
+ "]" if the specifier terminates a color sequence (such as "%R"),
+ "'" (single quote) if the specifier is expected to be quoted when
+ it appears outside a quoted sequence and unquoted otherwise (such
+ as the GCC internal printf format directive "%T"), and
+ "\"" (double quote) if the specifier is not expected to appear in
+ a quoted sequence (such as the GCC internal format directive "%K". */
+ const char *flags2;
+ /* If this format conversion character consumes more than one argument,
+ CHAIN points to information about the next argument. For later
+ arguments, only POINTER_COUNT, TYPES, and the "c", "R", and "W" flags
+ in FLAGS2 are used. */
+ const struct format_char_info *chain;
+};
+
+
+/* Structure describing a flag accepted by some kind of format. */
+struct format_flag_spec
+{
+ /* The flag character in question (0 for end of array). */
+ int flag_char;
+ /* Zero if this entry describes the flag character in general, or a
+ nonzero character that may be found in flags2 if it describes the
+ flag when used with certain formats only. If the latter, only
+ the first such entry found that applies to the current conversion
+ specifier is used; the values of 'name' and 'long_name' it supplies
+ will be used, if non-NULL and the standard version is higher than
+ the unpredicated one, for any pedantic warning. For example, 'o'
+ for strftime formats (meaning 'O' is an extension over C99). */
+ int predicate;
+ /* Nonzero if the next character after this flag in the format should
+ be skipped ('=' in strfmon), zero otherwise. */
+ int skip_next_char;
+ /* True if the flag introduces quoting (as in GCC's %qE). */
+ bool quoting;
+ /* The name to use for this flag in diagnostic messages. For example,
+ N_("'0' flag"), N_("field width"). */
+ const char *name;
+ /* Long name for this flag in diagnostic messages; currently only used for
+ "ISO C does not support ...". For example, N_("the 'I' printf flag"). */
+ const char *long_name;
+ /* The standard version in which it appeared. */
+ enum format_std_version std;
+};
+
+
+/* Structure describing a combination of flags that is bad for some kind
+ of format. */
+struct format_flag_pair
+{
+ /* The first flag character in question (0 for end of array). */
+ int flag_char1;
+ /* The second flag character. */
+ int flag_char2;
+ /* Nonzero if the message should say that the first flag is ignored with
+ the second, zero if the combination should simply be objected to. */
+ int ignored;
+ /* Zero if this entry applies whenever this flag combination occurs,
+ a nonzero character from flags2 if it only applies in some
+ circumstances (e.g. 'i' for printf formats ignoring 0 with precision). */
+ int predicate;
+};
+
+
+/* Structure describing a particular kind of format processed by GCC. */
+struct format_kind_info
+{
+ /* The name of this kind of format, for use in diagnostics. Also
+ the name of the attribute (without preceding and following __). */
+ const char *name;
+ /* Specifications of the length modifiers accepted; possibly NULL. */
+ const format_length_info *length_char_specs;
+ /* Details of the conversion specification characters accepted. */
+ const format_char_info *conversion_specs;
+ /* String listing the flag characters that are accepted. */
+ const char *flag_chars;
+ /* String listing modifier characters (strftime) accepted. May be NULL. */
+ const char *modifier_chars;
+ /* Details of the flag characters, including pseudo-flags. */
+ const format_flag_spec *flag_specs;
+ /* Details of bad combinations of flags. */
+ const format_flag_pair *bad_flag_pairs;
+ /* Flags applicable to this kind of format. */
+ int flags;
+ /* Flag character to treat a width as, or 0 if width not used. */
+ int width_char;
+ /* Flag character to treat a left precision (strfmon) as,
+ or 0 if left precision not used. */
+ int left_precision_char;
+ /* Flag character to treat a precision (for strfmon, right precision) as,
+ or 0 if precision not used. */
+ int precision_char;
+ /* If a flag character has the effect of suppressing the conversion of
+ an argument ('*' in scanf), that flag character, otherwise 0. */
+ int suppression_char;
+ /* Flag character to treat a length modifier as (ignored if length
+ modifiers not used). Need not be placed in flag_chars for conversion
+ specifiers, but is used to check for bad combinations such as length
+ modifier with assignment suppression in scanf. */
+ int length_code_char;
+ /* Assignment-allocation flag character ('m' in scanf), otherwise 0. */
+ int alloc_char;
+ /* Pointer to type of argument expected if '*' is used for a width,
+ or NULL if '*' not used for widths. */
+ tree *width_type;
+ /* Pointer to type of argument expected if '*' is used for a precision,
+ or NULL if '*' not used for precisions. */
+ tree *precision_type;
+};
+
+#define T_I &integer_type_node
+#define T89_I { STD_C89, NULL, T_I }
+#define T_L &long_integer_type_node
+#define T89_L { STD_C89, NULL, T_L }
+#define T_LL &long_long_integer_type_node
+#define T9L_LL { STD_C9L, NULL, T_LL }
+#define TEX_LL { STD_EXT, NULL, T_LL }
+#define T_S &short_integer_type_node
+#define T89_S { STD_C89, NULL, T_S }
+#define T_UI &unsigned_type_node
+#define T89_UI { STD_C89, NULL, T_UI }
+#define T2X_UI { STD_C2X, NULL, T_UI }
+#define T_UL &long_unsigned_type_node
+#define T89_UL { STD_C89, NULL, T_UL }
+#define T2X_UL { STD_C2X, NULL, T_UL }
+#define T_ULL &long_long_unsigned_type_node
+#define T9L_ULL { STD_C9L, NULL, T_ULL }
+#define T2X_ULL { STD_C2X, NULL, T_ULL }
+#define TEX_ULL { STD_EXT, NULL, T_ULL }
+#define T_US &short_unsigned_type_node
+#define T89_US { STD_C89, NULL, T_US }
+#define T2X_US { STD_C2X, NULL, T_US }
+#define T_F &float_type_node
+#define T89_F { STD_C89, NULL, T_F }
+#define T99_F { STD_C99, NULL, T_F }
+#define T_D &double_type_node
+#define T89_D { STD_C89, NULL, T_D }
+#define T99_D { STD_C99, NULL, T_D }
+#define T_LD &long_double_type_node
+#define T89_LD { STD_C89, NULL, T_LD }
+#define T99_LD { STD_C99, NULL, T_LD }
+#define T_C &char_type_node
+#define T89_C { STD_C89, NULL, T_C }
+#define T_SC &signed_char_type_node
+#define T99_SC { STD_C99, NULL, T_SC }
+#define T_UC &unsigned_char_type_node
+#define T99_UC { STD_C99, NULL, T_UC }
+#define T2X_UC { STD_C2X, NULL, T_UC }
+#define T_V &void_type_node
+#define T89_G { STD_C89, NULL, &local_gimple_ptr_node }
+#define T_CGRAPH_NODE { STD_C89, NULL, &local_cgraph_node_ptr_node }
+#define T_EVENT_PTR { STD_C89, NULL, &local_event_ptr_node }
+#define T89_T { STD_C89, NULL, &local_tree_type_node }
+#define T89_V { STD_C89, NULL, T_V }
+#define T_W &wchar_type_node
+#define T94_W { STD_C94, "wchar_t", T_W }
+#define TEX_W { STD_EXT, "wchar_t", T_W }
+#define T_WI &wint_type_node
+#define T94_WI { STD_C94, "wint_t", T_WI }
+#define TEX_WI { STD_EXT, "wint_t", T_WI }
+#define T_ST &size_type_node
+#define T99_ST { STD_C99, "size_t", T_ST }
+#define T2X_ST { STD_C2X, "size_t", T_ST }
+#define T_SST &signed_size_type_node
+#define T99_SST { STD_C99, "signed size_t", T_SST }
+#define T_PD &ptrdiff_type_node
+#define T99_PD { STD_C99, "ptrdiff_t", T_PD }
+#define T_UPD &unsigned_ptrdiff_type_node
+#define T99_UPD { STD_C99, "unsigned ptrdiff_t", T_UPD }
+#define T2X_UPD { STD_C2X, "unsigned ptrdiff_t", T_UPD }
+#define T_IM &intmax_type_node
+#define T99_IM { STD_C99, "intmax_t", T_IM }
+#define T_UIM &uintmax_type_node
+#define T99_UIM { STD_C99, "uintmax_t", T_UIM }
+#define T2X_UIM { STD_C2X, "uintmax_t", T_UIM }
+#define T_D32 &dfloat32_type_node
+#define T2X_D32 { STD_C2X, "_Decimal32", T_D32 }
+#define T_D64 &dfloat64_type_node
+#define T2X_D64 { STD_C2X, "_Decimal64", T_D64 }
+#define T_D128 &dfloat128_type_node
+#define T2X_D128 { STD_C2X, "_Decimal128", T_D128 }
+
+/* Structure describing how format attributes such as "printf" are
+ interpreted as "gnu_printf" or "ms_printf" on a particular system.
+ TARGET_OVERRIDES_FORMAT_ATTRIBUTES is used to specify target-specific
+ defaults. */
+struct target_ovr_attr
+{
+ /* The name of the to be copied format attribute. */
+ const char *named_attr_src;
+ /* The name of the to be overridden format attribute. */
+ const char *named_attr_dst;
+};
+
+#endif /* GCC_C_FORMAT_H */
diff --git a/support/cpp/gcc/c-family/c-indentation.cc b/support/cpp/gcc/c-family/c-indentation.cc
new file mode 100644
index 000000000..22c10681a
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-indentation.cc
@@ -0,0 +1,815 @@
+/* Implementation of -Wmisleading-indentation
+ Copyright (C) 2015-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 "c-common.h"
+#include "c-indentation.h"
+// sdcpp #include "selftest.h"
+#include "diagnostic.h"
+
+/* Round up VIS_COLUMN to nearest tab stop. */
+
+static unsigned int
+next_tab_stop (unsigned int vis_column, unsigned int tab_width)
+{
+ vis_column = ((vis_column + tab_width) / tab_width) * tab_width;
+ return vis_column;
+}
+
+/* Convert libcpp's notion of a column (a 1-based char count) to
+ the "visual column" (0-based column, respecting tabs), by reading the
+ relevant line.
+
+ Returns true if a conversion was possible, writing the result to OUT,
+ otherwise returns false. If FIRST_NWS is not NULL, then write to it
+ the visual column corresponding to the first non-whitespace character
+ on the line (up to or before EXPLOC). */
+
+static bool
+get_visual_column (expanded_location exploc,
+ unsigned int *out,
+ unsigned int *first_nws,
+ unsigned int tab_width)
+{
+ char_span line = location_get_source_line (exploc.file, exploc.line);
+ if (!line)
+ return false;
+ if ((size_t)exploc.column > line.length ())
+ return false;
+ unsigned int vis_column = 0;
+ for (int i = 1; i < exploc.column; i++)
+ {
+ unsigned char ch = line[i - 1];
+
+ if (first_nws != NULL && !ISSPACE (ch))
+ {
+ *first_nws = vis_column;
+ first_nws = NULL;
+ }
+
+ if (ch == '\t')
+ vis_column = next_tab_stop (vis_column, tab_width);
+ else
+ vis_column++;
+ }
+
+ if (first_nws != NULL)
+ *first_nws = vis_column;
+
+ *out = vis_column;
+ return true;
+}
+
+/* Attempt to determine the first non-whitespace character in line LINE_NUM
+ of source line FILE.
+
+ If this is possible, return true and write its "visual column" to
+ *FIRST_NWS.
+ Otherwise, return false, leaving *FIRST_NWS untouched. */
+
+static bool
+get_first_nws_vis_column (const char *file, int line_num,
+ unsigned int *first_nws,
+ unsigned int tab_width)
+{
+ gcc_assert (first_nws);
+
+ char_span line = location_get_source_line (file, line_num);
+ if (!line)
+ return false;
+ unsigned int vis_column = 0;
+ for (size_t i = 1; i < line.length (); i++)
+ {
+ unsigned char ch = line[i - 1];
+
+ if (!ISSPACE (ch))
+ {
+ *first_nws = vis_column;
+ return true;
+ }
+
+ if (ch == '\t')
+ vis_column = next_tab_stop (vis_column, tab_width);
+ else
+ vis_column++;
+ }
+
+ /* No non-whitespace characters found. */
+ return false;
+}
+
+/* Determine if there is an unindent/outdent between
+ BODY_EXPLOC and NEXT_STMT_EXPLOC, to ensure that we don't
+ issue a warning for cases like the following:
+
+ (1) Preprocessor logic
+
+ if (flagA)
+ foo ();
+ ^ BODY_EXPLOC
+ #if SOME_CONDITION_THAT_DOES_NOT_HOLD
+ if (flagB)
+ #endif
+ bar ();
+ ^ NEXT_STMT_EXPLOC
+
+ "bar ();" is visually aligned below "foo ();" and
+ is (as far as the parser sees) the next token, but
+ this isn't misleading to a human reader.
+
+ (2) Empty macro with bad indentation
+
+ In the following, the
+ "if (i > 0)"
+ is poorly indented, and ought to be on the same column as
+ "engine_ref_debug(e, 0, -1)"
+ However, it is not misleadingly indented, due to the presence
+ of that macro.
+
+ #define engine_ref_debug(X, Y, Z)
+
+ if (locked)
+ i = foo (0);
+ else
+ i = foo (1);
+ engine_ref_debug(e, 0, -1)
+ if (i > 0)
+ return 1;
+
+ Return true if such an unindent/outdent is detected. */
+
+static bool
+detect_intervening_unindent (const char *file,
+ int body_line,
+ int next_stmt_line,
+ unsigned int vis_column,
+ unsigned int tab_width)
+{
+ gcc_assert (file);
+ gcc_assert (next_stmt_line > body_line);
+
+ for (int line = body_line + 1; line < next_stmt_line; line++)
+ {
+ unsigned int line_vis_column;
+ if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width))
+ if (line_vis_column < vis_column)
+ return true;
+ }
+
+ /* Not found. */
+ return false;
+}
+
+
+/* Helper function for warn_for_misleading_indentation; see
+ description of that function below. */
+
+static bool
+should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
+ const token_indent_info &body_tinfo,
+ const token_indent_info &next_tinfo)
+{
+ /* Don't attempt to compare indentation if #line or # 44 "file"-style
+ directives are present, suggesting generated code.
+
+ All bets are off if these are present: the file that the #line
+ directive could have an entirely different coding layout to C/C++
+ (e.g. .md files).
+
+ To determine if a #line is present, in theory we could look for a
+ map with reason == LC_RENAME_VERBATIM. However, if there has
+ subsequently been a long line requiring a column number larger than
+ that representable by the original LC_RENAME_VERBATIM map, then
+ we'll have a map with reason LC_RENAME.
+ Rather than attempting to search all of the maps for a
+ LC_RENAME_VERBATIM, instead we have libcpp set a flag whenever one
+ is seen, and we check for the flag here.
+ */
+ if (line_table->seen_line_directive)
+ return false;
+
+ /* We can't usefully warn about do-while and switch statements since the
+ bodies of these statements are always explicitly delimited at both ends,
+ so control flow is quite obvious. */
+ if (guard_tinfo.keyword == RID_DO
+ || guard_tinfo.keyword == RID_SWITCH)
+ return false;
+
+ /* If the token following the body is a close brace or an "else"
+ then while indentation may be sloppy, there is not much ambiguity
+ about control flow, e.g.
+
+ if (foo) <- GUARD
+ bar (); <- BODY
+ else baz (); <- NEXT
+
+ {
+ while (foo) <- GUARD
+ bar (); <- BODY
+ } <- NEXT
+ baz ();
+ */
+ enum cpp_ttype next_tok_type = next_tinfo.type;
+ if (next_tok_type == CPP_CLOSE_BRACE
+ || next_tinfo.keyword == RID_ELSE)
+ return false;
+
+ /* Likewise, if the body of the guard is a compound statement then control
+ flow is quite visually explicit regardless of the code's possibly poor
+ indentation, e.g.
+
+ while (foo) <- GUARD
+ { <- BODY
+ bar ();
+ }
+ baz (); <- NEXT
+
+ Things only get muddy when the body of the guard does not have
+ braces, e.g.
+
+ if (foo) <- GUARD
+ bar (); <- BODY
+ baz (); <- NEXT
+ */
+ enum cpp_ttype body_type = body_tinfo.type;
+ if (body_type == CPP_OPEN_BRACE)
+ return false;
+
+ /* Don't warn here about spurious semicolons. */
+ if (next_tok_type == CPP_SEMICOLON)
+ return false;
+
+ location_t guard_loc = guard_tinfo.location;
+ location_t body_loc = body_tinfo.location;
+ location_t next_stmt_loc = next_tinfo.location;
+
+ /* Resolve each token location to the respective macro expansion
+ point that produced the token. */
+ if (linemap_location_from_macro_expansion_p (line_table, guard_loc))
+ guard_loc = linemap_resolve_location (line_table, guard_loc,
+ LRK_MACRO_EXPANSION_POINT, NULL);
+ if (linemap_location_from_macro_expansion_p (line_table, body_loc))
+ body_loc = linemap_resolve_location (line_table, body_loc,
+ LRK_MACRO_EXPANSION_POINT, NULL);
+ if (linemap_location_from_macro_expansion_p (line_table, next_stmt_loc))
+ next_stmt_loc = linemap_resolve_location (line_table, next_stmt_loc,
+ LRK_MACRO_EXPANSION_POINT, NULL);
+
+ /* When all three tokens are produced from a single macro expansion, we
+ instead consider their loci inside that macro's definition. */
+ if (guard_loc == body_loc && body_loc == next_stmt_loc)
+ {
+ const line_map *guard_body_common_map
+ = first_map_in_common (line_table,
+ guard_tinfo.location, body_tinfo.location,
+ &guard_loc, &body_loc);
+ const line_map *body_next_common_map
+ = first_map_in_common (line_table,
+ body_tinfo.location, next_tinfo.location,
+ &body_loc, &next_stmt_loc);
+
+ /* Punt on complicated nesting of macros. */
+ if (guard_body_common_map != body_next_common_map)
+ return false;
+
+ guard_loc = linemap_resolve_location (line_table, guard_loc,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+ body_loc = linemap_resolve_location (line_table, body_loc,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+ next_stmt_loc = linemap_resolve_location (line_table, next_stmt_loc,
+ LRK_MACRO_DEFINITION_LOCATION,
+ NULL);
+ }
+
+ expanded_location body_exploc = expand_location (body_loc);
+ expanded_location next_stmt_exploc = expand_location (next_stmt_loc);
+ expanded_location guard_exploc = expand_location (guard_loc);
+
+ /* PR c++/68819: if the column number is zero, we presumably
+ had a location_t > LINE_MAP_MAX_LOCATION_WITH_COLS, and so
+ we have no column information. */
+ if (!guard_exploc.column || !body_exploc.column || !next_stmt_exploc.column)
+ {
+ static bool issued_note = false;
+ if (!issued_note)
+ {
+ /* Notify the user the first time this happens. */
+ issued_note = true;
+ inform (guard_loc,
+ "%<-Wmisleading-indentation%> is disabled from this point"
+ " onwards, since column-tracking was disabled due to"
+ " the size of the code/headers");
+ if (!flag_large_source_files)
+ inform (guard_loc,
+ "adding %<-flarge-source-files%> will allow for more"
+ " column-tracking support, at the expense of compilation"
+ " time and memory");
+ }
+ return false;
+ }
+
+ /* Give up if the loci are not all distinct. */
+ if (guard_loc == body_loc || body_loc == next_stmt_loc)
+ return false;
+
+ const unsigned int tab_width = global_dc->tabstop;
+
+ /* They must be in the same file. */
+ if (next_stmt_exploc.file != body_exploc.file)
+ return false;
+
+ /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
+ the location of the guard.
+
+ Cases where we want to issue a warning:
+
+ if (flag)
+ foo (); bar ();
+ ^ WARN HERE
+
+ if (flag) foo (); bar ();
+ ^ WARN HERE
+
+
+ if (flag) ; {
+ ^ WARN HERE
+
+ if (flag)
+ ; {
+ ^ WARN HERE
+
+ Cases where we don't want to issue a warning:
+
+ various_code (); if (flag) foo (); bar (); more_code ();
+ ^ DON'T WARN HERE. */
+ if (next_stmt_exploc.line == body_exploc.line)
+ {
+ if (guard_exploc.file != body_exploc.file)
+ return true;
+ if (guard_exploc.line < body_exploc.line)
+ /* The guard is on a line before a line that contains both
+ the body and the next stmt. */
+ return true;
+ else if (guard_exploc.line == body_exploc.line)
+ {
+ /* They're all on the same line. */
+ gcc_assert (guard_exploc.file == next_stmt_exploc.file);
+ gcc_assert (guard_exploc.line == next_stmt_exploc.line);
+ unsigned int guard_vis_column;
+ unsigned int guard_line_first_nws;
+ if (!get_visual_column (guard_exploc,
+ &guard_vis_column,
+ &guard_line_first_nws, tab_width))
+ return false;
+ /* Heuristic: only warn if the guard is the first thing
+ on its line. */
+ if (guard_vis_column == guard_line_first_nws)
+ return true;
+ }
+ }
+
+ /* If NEXT_STMT_LOC is on a line after BODY_LOC, consider
+ their relative locations, and of the guard.
+
+ Cases where we want to issue a warning:
+ if (flag)
+ foo ();
+ bar ();
+ ^ WARN HERE
+
+ Cases where we don't want to issue a warning:
+ if (flag)
+ foo ();
+ bar ();
+ ^ DON'T WARN HERE (autogenerated code?)
+
+ if (flagA)
+ foo ();
+ #if SOME_CONDITION_THAT_DOES_NOT_HOLD
+ if (flagB)
+ #endif
+ bar ();
+ ^ DON'T WARN HERE
+
+ if (flag)
+ ;
+ foo ();
+ ^ DON'T WARN HERE
+
+ #define emit
+ if (flag)
+ foo ();
+ emit bar ();
+ ^ DON'T WARN HERE
+
+ */
+ if (next_stmt_exploc.line > body_exploc.line)
+ {
+ /* Determine if GUARD_LOC and NEXT_STMT_LOC are aligned on the same
+ "visual column"... */
+ unsigned int next_stmt_vis_column;
+ unsigned int next_stmt_line_first_nws;
+ unsigned int body_vis_column;
+ unsigned int body_line_first_nws;
+ unsigned int guard_vis_column;
+ unsigned int guard_line_first_nws;
+ /* If we can't determine it, don't issue a warning. This is sometimes
+ the case for input files containing #line directives, and these
+ are often for autogenerated sources (e.g. from .md files), where
+ it's not clear that it's meaningful to look at indentation. */
+ if (!get_visual_column (next_stmt_exploc,
+ &next_stmt_vis_column,
+ &next_stmt_line_first_nws, tab_width))
+ return false;
+ if (!get_visual_column (body_exploc,
+ &body_vis_column,
+ &body_line_first_nws, tab_width))
+ return false;
+ if (!get_visual_column (guard_exploc,
+ &guard_vis_column,
+ &guard_line_first_nws, tab_width))
+ return false;
+
+ /* If the line where the next stmt starts has non-whitespace
+ on it before the stmt, then don't warn:
+ #define emit
+ if (flag)
+ foo ();
+ emit bar ();
+ ^ DON'T WARN HERE
+ (PR c/69122). */
+ if (next_stmt_line_first_nws < next_stmt_vis_column)
+ return false;
+
+ if ((body_type != CPP_SEMICOLON
+ && next_stmt_vis_column == body_vis_column)
+ /* As a special case handle the case where the body is a semicolon
+ that may be hidden by a preceding comment, e.g. */
+
+ // if (p)
+ // /* blah */;
+ // foo (1);
+
+ /* by looking instead at the column of the first non-whitespace
+ character on the body line. */
+ || (body_type == CPP_SEMICOLON
+ && body_exploc.line > guard_exploc.line
+ && body_line_first_nws != body_vis_column
+ && next_stmt_vis_column > guard_line_first_nws))
+ {
+ /* Don't warn if they are aligned on the same column
+ as the guard itself (suggesting autogenerated code that doesn't
+ bother indenting at all).
+ For "else" clauses, we consider the column of the first
+ non-whitespace character on the guard line instead of the column
+ of the actual guard token itself because it is more sensible.
+ Consider:
+
+ if (p) {
+ foo (1);
+ } else // GUARD
+ foo (2); // BODY
+ foo (3); // NEXT
+
+ and:
+
+ if (p)
+ foo (1);
+ } else // GUARD
+ foo (2); // BODY
+ foo (3); // NEXT
+
+ If we just used the column of the "else" token, we would warn on
+ the first example and not warn on the second. But we want the
+ exact opposite to happen: to not warn on the first example (which
+ is probably autogenerated) and to warn on the second (whose
+ indentation is misleading). Using the column of the first
+ non-whitespace character on the guard line makes that
+ happen. */
+ unsigned int guard_column = (guard_tinfo.keyword == RID_ELSE
+ ? guard_line_first_nws
+ : guard_vis_column);
+ if (guard_column == body_vis_column)
+ return false;
+
+ /* We may have something like:
+
+ if (p)
+ {
+ foo (1);
+ } else // GUARD
+ foo (2); // BODY
+ foo (3); // NEXT
+
+ in which case the columns are not aligned but the code is not
+ misleadingly indented. If the column of the body isn't indented
+ more than the guard line then don't warn. */
+ if (body_vis_column <= guard_line_first_nws)
+ return false;
+
+ /* Don't warn if there is an unindent between the two statements. */
+ int vis_column = MIN (next_stmt_vis_column, body_vis_column);
+ if (detect_intervening_unindent (body_exploc.file, body_exploc.line,
+ next_stmt_exploc.line,
+ vis_column, tab_width))
+ return false;
+
+ /* Otherwise, they are visually aligned: issue a warning. */
+ return true;
+ }
+
+ /* Also issue a warning for code having the form:
+
+ if (flag);
+ foo ();
+
+ while (flag);
+ {
+ ...
+ }
+
+ for (...);
+ {
+ ...
+ }
+
+ if (flag)
+ ;
+ else if (flag);
+ foo ();
+
+ where the semicolon at the end of each guard is most likely spurious.
+
+ But do not warn on:
+
+ for (..);
+ foo ();
+
+ where the next statement is aligned with the guard.
+ */
+ if (body_type == CPP_SEMICOLON)
+ {
+ if (body_exploc.line == guard_exploc.line)
+ {
+ if (next_stmt_vis_column > guard_line_first_nws
+ || (next_tok_type == CPP_OPEN_BRACE
+ && next_stmt_vis_column == guard_line_first_nws))
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+/* Return the string identifier corresponding to the given guard token. */
+
+const char *
+guard_tinfo_to_string (enum rid keyword)
+{
+ switch (keyword)
+ {
+ case RID_FOR:
+ return "for";
+ case RID_ELSE:
+ return "else";
+ case RID_IF:
+ return "if";
+ case RID_WHILE:
+ return "while";
+ case RID_DO:
+ return "do";
+ case RID_SWITCH:
+ return "switch";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Called by the C/C++ frontends when we have a guarding statement at
+ GUARD_LOC containing a statement at BODY_LOC, where the block wasn't
+ written using braces, like this:
+
+ if (flag)
+ foo ();
+
+ along with the location of the next token, at NEXT_STMT_LOC,
+ so that we can detect followup statements that are within
+ the same "visual block" as the guarded statement, but which
+ aren't logically grouped within the guarding statement, such
+ as:
+
+ GUARD_LOC
+ |
+ V
+ if (flag)
+ foo (); <- BODY_LOC
+ bar (); <- NEXT_STMT_LOC
+
+ In the above, "bar ();" isn't guarded by the "if", but
+ is indented to misleadingly suggest that it is in the same
+ block as "foo ();".
+
+ GUARD_KIND identifies the kind of clause e.g. "if", "else" etc. */
+
+void
+warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
+ const token_indent_info &body_tinfo,
+ const token_indent_info &next_tinfo)
+{
+ /* Early reject for the case where -Wmisleading-indentation is disabled,
+ to avoid doing work only to have the warning suppressed inside the
+ diagnostic machinery. */
+ if (!warn_misleading_indentation)
+ return;
+
+ if (should_warn_for_misleading_indentation (guard_tinfo,
+ body_tinfo,
+ next_tinfo))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (guard_tinfo.location, OPT_Wmisleading_indentation,
+ "this %qs clause does not guard...",
+ guard_tinfo_to_string (guard_tinfo.keyword)))
+ inform (next_tinfo.location,
+ "...this statement, but the latter is misleadingly indented"
+ " as if it were guarded by the %qs",
+ guard_tinfo_to_string (guard_tinfo.keyword));
+ }
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that next_tab_stop works as expected. */
+
+static void
+test_next_tab_stop ()
+{
+ const unsigned int tab_width = 8;
+
+ ASSERT_EQ (next_tab_stop (0, tab_width), 8);
+ ASSERT_EQ (next_tab_stop (1, tab_width), 8);
+ ASSERT_EQ (next_tab_stop (7, tab_width), 8);
+
+ ASSERT_EQ (next_tab_stop (8, tab_width), 16);
+ ASSERT_EQ (next_tab_stop (9, tab_width), 16);
+ ASSERT_EQ (next_tab_stop (15, tab_width), 16);
+
+ ASSERT_EQ (next_tab_stop (16, tab_width), 24);
+ ASSERT_EQ (next_tab_stop (17, tab_width), 24);
+ ASSERT_EQ (next_tab_stop (23, tab_width), 24);
+}
+
+/* Verify that the given call to get_visual_column succeeds, with
+ the given results. */
+
+static void
+assert_get_visual_column_succeeds (const location &loc,
+ const char *file, int line, int column,
+ const unsigned int tab_width,
+ unsigned int expected_visual_column,
+ unsigned int expected_first_nws)
+{
+ expanded_location exploc;
+ exploc.file = file;
+ exploc.line = line;
+ exploc.column = column;
+ exploc.data = NULL;
+ exploc.sysp = false;
+ unsigned int actual_visual_column;
+ unsigned int actual_first_nws;
+ bool result = get_visual_column (exploc,
+ &actual_visual_column,
+ &actual_first_nws, tab_width);
+ ASSERT_TRUE_AT (loc, result);
+ ASSERT_EQ_AT (loc, actual_visual_column, expected_visual_column);
+ ASSERT_EQ_AT (loc, actual_first_nws, expected_first_nws);
+}
+
+/* Verify that the given call to get_visual_column succeeds, with
+ the given results. */
+
+#define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN, \
+ TAB_WIDTH, \
+ EXPECTED_VISUAL_COLUMN, \
+ EXPECTED_FIRST_NWS) \
+ SELFTEST_BEGIN_STMT \
+ assert_get_visual_column_succeeds (SELFTEST_LOCATION, \
+ FILENAME, LINE, COLUMN, \
+ TAB_WIDTH, \
+ EXPECTED_VISUAL_COLUMN, \
+ EXPECTED_FIRST_NWS); \
+ SELFTEST_END_STMT
+
+/* Verify that the given call to get_visual_column fails gracefully. */
+
+static void
+assert_get_visual_column_fails (const location &loc,
+ const char *file, int line, int column,
+ const unsigned int tab_width)
+{
+ expanded_location exploc;
+ exploc.file = file;
+ exploc.line = line;
+ exploc.column = column;
+ exploc.data = NULL;
+ exploc.sysp = false;
+ unsigned int actual_visual_column;
+ unsigned int actual_first_nws;
+ bool result = get_visual_column (exploc,
+ &actual_visual_column,
+ &actual_first_nws, tab_width);
+ ASSERT_FALSE_AT (loc, result);
+}
+
+/* Verify that the given call to get_visual_column fails gracefully. */
+
+#define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN, \
+ TAB_WIDTH) \
+ SELFTEST_BEGIN_STMT \
+ assert_get_visual_column_fails (SELFTEST_LOCATION, \
+ FILENAME, LINE, COLUMN, \
+ TAB_WIDTH); \
+ SELFTEST_END_STMT
+
+/* Verify that get_visual_column works as expected. */
+
+static void
+test_get_visual_column ()
+{
+ /* Create a tempfile with a mixture of tabs and spaces.
+
+ Both lines have either a space or a tab, then " line N",
+ for 8 characters in total.
+
+ 1-based "columns" (w.r.t. to line 1):
+ .....................0000000001111.
+ .....................1234567890123. */
+ const char *content = (" line 1\n"
+ "\t line 2\n");
+ line_table_test ltt;
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
+
+ const unsigned int tab_width = 8;
+ const char *file = tmp.get_filename ();
+
+ /* Line 1 (space-based indentation). */
+ {
+ const int line = 1;
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 1, 1);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 2, 2);
+ /* first_nws should have stopped increasing. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 3, 2);
+ /* Verify the end-of-line boundary. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 7, 2);
+ ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
+ }
+
+ /* Line 2 (tab-based indentation). */
+ {
+ const int line = 2;
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 8, 8);
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 9, 9);
+ /* first_nws should have stopped increasing. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 10, 9);
+ /* Verify the end-of-line boundary. */
+ ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 14, 9);
+ ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
+ }
+}
+
+/* Run all of the selftests within this file. */
+
+void
+c_indentation_cc_tests ()
+{
+ test_next_tab_stop ();
+ test_get_visual_column ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/support/cpp/gcc/c-family/c-indentation.h b/support/cpp/gcc/c-family/c-indentation.h
new file mode 100644
index 000000000..a344e9d70
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-indentation.h
@@ -0,0 +1,54 @@
+/* Definitions for c-indentation.cc.
+ Copyright (C) 2015-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_C_INDENTATION_H
+#define GCC_C_INDENTATION_H
+
+/* Token information used by the -Wmisleading-indentation implementation. */
+
+struct token_indent_info
+{
+ location_t location;
+ ENUM_BITFIELD (cpp_ttype) type : 8;
+ ENUM_BITFIELD (rid) keyword : 8;
+};
+
+/* Extract token information from TOKEN, which ought to either be a
+ cp_token * or a c_token *. */
+
+template <typename T>
+inline token_indent_info
+get_token_indent_info (const T *token)
+{
+ token_indent_info info;
+ info.location = token->location;
+ info.type = token->type;
+ info.keyword = token->keyword;
+
+ return info;
+}
+
+extern void
+warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
+ const token_indent_info &body_tinfo,
+ const token_indent_info &next_tinfo);
+extern const char *
+guard_tinfo_to_string (enum rid keyword);
+
+#endif /* ! GCC_C_INDENTATION_H */
diff --git a/support/cpp/gcc/c-family/c-lex.cc b/support/cpp/gcc/c-family/c-lex.cc
new file mode 100644
index 000000000..076ea1a4d
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-lex.cc
@@ -0,0 +1,1518 @@
+/* Mainly the interface between cpplib and the C front ends.
+ 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "c-common.h"
+#include "timevar.h"
+#include "stringpool.h"
+#include "stor-layout.h"
+#include "c-pragma.h"
+#include "debug.h"
+#include "flags.h"
+#include "file-prefix-map.h" /* remap_macro_filename() */
+#include "langhooks.h"
+#include "attribs.h"
+#include "real.h" // sdcpp
+
+
+/* We may keep statistics about how long which files took to compile. */
+static int header_time, body_time;
+static splay_tree file_info_tree;
+#if 0 // sdcpp
+
+int pending_lang_change; /* If we need to switch languages - C++ only */
+int c_header_level; /* depth in C headers - C++ only */
+
+static tree interpret_integer (const cpp_token *, unsigned int,
+ enum overflow_type *);
+static tree interpret_float (const cpp_token *, unsigned int, const char *,
+ enum overflow_type *);
+static tree interpret_fixed (const cpp_token *, unsigned int);
+static enum integer_type_kind narrowest_unsigned_type
+ (const widest_int &, unsigned int);
+static enum integer_type_kind narrowest_signed_type
+ (const widest_int &, unsigned int);
+static enum cpp_ttype lex_string (const cpp_token *, tree *, bool, bool);
+static tree lex_charconst (const cpp_token *);
+static void update_header_times (const char *);
+static int dump_one_header (splay_tree_node, void *);
+static void cb_line_change (cpp_reader *, const cpp_token *, int);
+static void cb_ident (cpp_reader *, unsigned int, const cpp_string *);
+static void cb_def_pragma (cpp_reader *, unsigned int);
+static void cb_define (cpp_reader *, unsigned int, cpp_hashnode *);
+static void cb_undef (cpp_reader *, unsigned int, cpp_hashnode *);
+
+void
+init_c_lex (void)
+{
+ struct c_fileinfo *toplevel;
+
+ /* The get_fileinfo data structure must be initialized before
+ cpp_read_main_file is called. */
+ toplevel = get_fileinfo ("<top level>");
+ if (flag_detailed_statistics)
+ {
+ header_time = 0;
+ body_time = get_run_time ();
+ toplevel->time = body_time;
+ }
+
+ struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
+
+ cb->line_change = cb_line_change;
+ cb->ident = cb_ident;
+ cb->def_pragma = cb_def_pragma;
+ cb->valid_pch = c_common_valid_pch;
+ cb->read_pch = c_common_read_pch;
+ cb->has_attribute = c_common_has_attribute;
+ cb->has_builtin = c_common_has_builtin;
+ cb->get_source_date_epoch = cb_get_source_date_epoch;
+ cb->get_suggestion = cb_get_suggestion;
+ cb->remap_filename = remap_macro_filename;
+
+ /* Set the debug callbacks if we can use them. */
+ if ((debug_info_level == DINFO_LEVEL_VERBOSE
+ && dwarf_debuginfo_p ())
+ || flag_dump_go_spec != NULL)
+ {
+ cb->define = cb_define;
+ cb->undef = cb_undef;
+ }
+}
+#endif // sdcpp
+
+struct c_fileinfo *
+get_fileinfo (const char *name)
+{
+ splay_tree_node n;
+ struct c_fileinfo *fi;
+
+ if (!file_info_tree)
+ file_info_tree = splay_tree_new (splay_tree_compare_strings,
+ 0,
+ splay_tree_delete_pointers);
+
+ n = splay_tree_lookup (file_info_tree, (splay_tree_key) name);
+ if (n)
+ return (struct c_fileinfo *) n->value;
+
+ fi = XNEW (struct c_fileinfo);
+ fi->time = 0;
+ fi->interface_only = 0;
+ fi->interface_unknown = 1;
+ splay_tree_insert (file_info_tree, (splay_tree_key) name,
+ (splay_tree_value) fi);
+ return fi;
+}
+#if 0 // sdcpp
+
+#endif // sdcpp
+static void
+update_header_times (const char *name)
+{
+ /* Changing files again. This means currently collected time
+ is charged against header time, and body time starts back at 0. */
+ if (flag_detailed_statistics)
+ {
+ int this_time = get_run_time ();
+ struct c_fileinfo *file = get_fileinfo (name);
+ header_time += this_time - body_time;
+ file->time += this_time - body_time;
+ body_time = this_time;
+ }
+}
+#if 0 //sdcpp
+
+static int
+dump_one_header (splay_tree_node n, void * ARG_UNUSED (dummy))
+{
+ print_time ((const char *) n->key,
+ ((struct c_fileinfo *) n->value)->time);
+ return 0;
+}
+
+void
+dump_time_statistics (void)
+{
+ struct c_fileinfo *file = get_fileinfo (LOCATION_FILE (input_location));
+ int this_time = get_run_time ();
+ file->time += this_time - body_time;
+
+ fprintf (stderr, "\n******\n");
+ print_time ("header files (total)", header_time);
+ print_time ("main file (total)", this_time - body_time);
+ fprintf (stderr, "ratio = %g : 1\n",
+ (double) header_time / (double) (this_time - body_time));
+ fprintf (stderr, "\n******\n");
+
+ splay_tree_foreach (file_info_tree, dump_one_header, 0);
+}
+
+static void
+cb_ident (cpp_reader * ARG_UNUSED (pfile),
+ unsigned int ARG_UNUSED (line),
+ const cpp_string * ARG_UNUSED (str))
+{
+ fprintf(stderr, "c_indent, incomplete\n");
+#if 0 // sdcpp
+ if (!flag_no_ident)
+ {
+ /* Convert escapes in the string. */
+ cpp_string cstr = { 0, 0 };
+ if (cpp_interpret_string (pfile, str, 1, &cstr, CPP_STRING))
+ {
+ targetm.asm_out.output_ident ((const char *) cstr.text);
+ free (CONST_CAST (unsigned char *, cstr.text));
+ }
+ }
+#endif // sdcpp
+}
+
+/* Called at the start of every non-empty line. TOKEN is the first
+ lexed token on the line. Used for diagnostic line numbers. */
+static void
+cb_line_change (cpp_reader * ARG_UNUSED (pfile), const cpp_token *token,
+ int parsing_args)
+{
+ if (token->type != CPP_EOF && !parsing_args)
+ input_location = token->src_loc;
+}
+#endif // sdcpp
+
+void
+fe_file_change (const line_map_ordinary *new_map)
+{
+ if (new_map == NULL)
+ return;
+
+ if (new_map->reason == LC_ENTER)
+ {
+ /* Don't stack the main buffer on the input stack;
+ we already did in compile_file. */
+ if (!MAIN_FILE_P (new_map))
+ {
+ location_t included_at = linemap_included_from (new_map);
+ int line = 0;
+ if (included_at > BUILTINS_LOCATION)
+ line = SOURCE_LINE (new_map - 1, included_at);
+
+ input_location = new_map->start_location;
+ (*debug_hooks->start_source_file) (line, LINEMAP_FILE (new_map));
+#ifdef SYSTEM_IMPLICIT_EXTERN_C
+ if (c_header_level)
+ ++c_header_level;
+ else if (LINEMAP_SYSP (new_map) == 2)
+ {
+ c_header_level = 1;
+ ++pending_lang_change;
+ }
+#endif
+ }
+ }
+ else if (new_map->reason == LC_LEAVE)
+ {
+#ifdef SYSTEM_IMPLICIT_EXTERN_C
+ if (c_header_level && --c_header_level == 0)
+ {
+ if (LINEMAP_SYSP (new_map) == 2)
+ warning (0, "badly nested C headers from preprocessor");
+ --pending_lang_change;
+ }
+#endif
+ input_location = new_map->start_location;
+
+ (*debug_hooks->end_source_file) (LINEMAP_LINE (new_map));
+ }
+
+ update_header_times (LINEMAP_FILE (new_map));
+ input_location = new_map->start_location;
+}
+
+#if 0 // sdcpp
+static void
+cb_def_pragma (cpp_reader *pfile, location_t loc)
+{
+ /* Issue a warning message if we have been asked to do so. Ignore
+ unknown pragmas in system headers unless an explicit
+ -Wunknown-pragmas has been given. */
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
+ {
+ const unsigned char *space, *name;
+ const cpp_token *s;
+ location_t fe_loc = loc;
+
+ space = name = (const unsigned char *) "";
+ s = cpp_get_token (pfile);
+ if (s->type != CPP_EOF)
+ {
+ space = cpp_token_as_text (pfile, s);
+ s = cpp_get_token (pfile);
+ if (s->type == CPP_NAME)
+ name = cpp_token_as_text (pfile, s);
+ }
+
+ warning_at (fe_loc, OPT_Wunknown_pragmas, "ignoring %<#pragma %s %s%>",
+ space, name);
+ }
+}
+#endif // sdcpp
+
+/* #define callback for DWARF and DWARF2 debug info. */
+#if 0 // sdcpp
+static void
+cb_define (cpp_reader *pfile, location_t loc, cpp_hashnode *node)
+{
+ const struct line_map *map = linemap_lookup (line_table, loc);
+ (*debug_hooks->define) (SOURCE_LINE (linemap_check_ordinary (map), loc),
+ (const char *) cpp_macro_definition (pfile, node));
+}
+
+/* #undef callback for DWARF and DWARF2 debug info. */
+static void
+cb_undef (cpp_reader *pfile, location_t loc, cpp_hashnode *node)
+{
+ if (lang_hooks.preprocess_undef)
+ lang_hooks.preprocess_undef (pfile, loc, node);
+
+ const struct line_map *map = linemap_lookup (line_table, loc);
+ (*debug_hooks->undef) (SOURCE_LINE (linemap_check_ordinary (map), loc),
+ (const char *) NODE_NAME (node));
+}
+#endif // sdcpp
+
+/* Wrapper around cpp_get_token to skip CPP_PADDING tokens
+ and not consume CPP_EOF. */
+static const cpp_token *
+get_token_no_padding (cpp_reader *pfile)
+{
+ for (;;)
+ {
+ const cpp_token *ret = cpp_peek_token (pfile, 0);
+ if (ret->type == CPP_EOF)
+ return ret;
+ ret = cpp_get_token (pfile);
+ if (ret->type != CPP_PADDING)
+ return ret;
+ }
+}
+
+/* Callback for has_attribute. */
+int
+c_common_has_attribute (cpp_reader *pfile, bool std_syntax)
+{
+ int result = 0;
+ tree attr_name = NULL_TREE;
+ const cpp_token *token;
+
+ token = get_token_no_padding (pfile);
+ if (token->type != CPP_OPEN_PAREN)
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "missing '(' after \"__has_attribute\"");
+ return 0;
+ }
+ token = get_token_no_padding (pfile);
+ if (token->type == CPP_NAME)
+ {
+ attr_name = get_identifier ((const char *)
+ cpp_token_as_text (pfile, token));
+// sdcpp attr_name = canonicalize_attr_name (attr_name);
+ bool have_scope = false;
+ int idx = 0;
+ const cpp_token *nxt_token;
+ do
+ nxt_token = cpp_peek_token (pfile, idx++);
+ while (nxt_token->type == CPP_PADDING);
+ if (nxt_token->type == CPP_SCOPE)
+ {
+ have_scope = true;
+ get_token_no_padding (pfile); // Eat scope.
+ nxt_token = get_token_no_padding (pfile);
+ if (nxt_token->type == CPP_NAME)
+ {
+ tree attr_ns = attr_name;
+ tree attr_id
+ = get_identifier ((const char *)
+ cpp_token_as_text (pfile, nxt_token));
+// sdcpp attr_id = canonicalize_attr_name (attr_id);
+#if 0 // sdcpp
+ if (c_dialect_cxx ())
+ {
+ /* OpenMP attributes need special handling. */
+ if ((flag_openmp || flag_openmp_simd)
+ && is_attribute_p ("omp", attr_ns)
+ && (is_attribute_p ("directive", attr_id)
+ || is_attribute_p ("sequence", attr_id)))
+ result = 1;
+ }
+#endif // sdcpp
+ if (result)
+ attr_name = NULL_TREE;
+ else
+ attr_name = build_tree_list (attr_ns, attr_id);
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "attribute identifier required after scope");
+ attr_name = NULL_TREE;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "incomplete, something with attributes\n");
+#if 0 // sdcpp
+ /* Some standard attributes need special handling. */
+ if (c_dialect_cxx ())
+ {
+ if (is_attribute_p ("noreturn", attr_name))
+ result = 200809;
+ else if (is_attribute_p ("deprecated", attr_name))
+ result = 201309;
+ else if (is_attribute_p ("maybe_unused", attr_name)
+ || is_attribute_p ("fallthrough", attr_name))
+ result = 201603;
+ else if (is_attribute_p ("no_unique_address", attr_name)
+ || is_attribute_p ("likely", attr_name)
+ || is_attribute_p ("unlikely", attr_name))
+ result = 201803;
+ else if (is_attribute_p ("nodiscard", attr_name))
+ result = 201907;
+ }
+ else
+ {
+ if (is_attribute_p ("deprecated", attr_name)
+ || is_attribute_p ("maybe_unused", attr_name)
+ || is_attribute_p ("fallthrough", attr_name))
+ result = 201904;
+ else if (is_attribute_p ("nodiscard", attr_name))
+ result = 202003;
+ }
+#endif // sdcpp
+ if (result)
+ attr_name = NULL_TREE;
+ }
+ if (attr_name && (have_scope || !std_syntax))
+ {
+ fprintf(stderr, "incomplete, something with attrib\n");
+#if 0 // sdcpp
+ init_attributes ();
+ const struct attribute_spec *attr = lookup_attribute_spec (attr_name);
+ if (attr)
+ result = 1;
+#endif
+ }
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "macro \"__has_attribute\" requires an identifier");
+ return 0;
+ }
+
+ if (get_token_no_padding (pfile)->type != CPP_CLOSE_PAREN)
+ cpp_error (pfile, CPP_DL_ERROR,
+ "missing ')' after \"__has_attribute\"");
+
+ return result;
+}
+
+/* Callback for has_builtin. */
+
+int
+c_common_has_builtin (cpp_reader *pfile)
+{
+ const cpp_token *token = get_token_no_padding (pfile);
+ if (token->type != CPP_OPEN_PAREN)
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "missing '(' after \"__has_builtin\"");
+ return 0;
+ }
+
+ const char *name = "";
+ token = get_token_no_padding (pfile);
+ if (token->type == CPP_NAME)
+ {
+ name = (const char *) cpp_token_as_text (pfile, token);
+ token = get_token_no_padding (pfile);
+ if (token->type != CPP_CLOSE_PAREN)
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "expected ')' after \"%s\"", name);
+ name = "";
+ }
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "macro \"__has_builtin\" requires an identifier");
+ if (token->type == CPP_CLOSE_PAREN)
+ return 0;
+ }
+
+ /* Consume tokens up to the closing parenthesis, including any nested
+ pairs of parentheses, to avoid confusing redundant errors. */
+ for (unsigned nparen = 1; ; token = get_token_no_padding (pfile))
+ {
+ if (token->type == CPP_OPEN_PAREN)
+ ++nparen;
+ else if (token->type == CPP_CLOSE_PAREN)
+ --nparen;
+ else if (token->type == CPP_EOF)
+ break;
+ if (!nparen)
+ break;
+ }
+
+ return names_builtin_p (name);
+}
+
+
+/* Read a token and return its type. Fill *VALUE with its value, if
+ applicable. Fill *CPP_FLAGS with the token's flags, if it is
+ non-NULL. */
+
+#if 0 // sdcpp
+enum cpp_ttype
+c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
+ int lex_flags)
+{
+ const cpp_token *tok;
+ enum cpp_ttype type;
+ unsigned char add_flags = 0;
+ enum overflow_type overflow = OT_NONE;
+
+ timevar_push (TV_CPP);
+ retry:
+ tok = cpp_get_token_with_location (parse_in, loc);
+ type = tok->type;
+
+ retry_after_at:
+ switch (type)
+ {
+ case CPP_PADDING:
+ goto retry;
+
+ case CPP_NAME:
+ *value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node.node));
+ break;
+
+ case CPP_NUMBER:
+ {
+ const char *suffix = NULL;
+ unsigned int flags = cpp_classify_number (parse_in, tok, &suffix, *loc);
+
+ switch (flags & CPP_N_CATEGORY)
+ {
+ case CPP_N_INVALID:
+ /* cpplib has issued an error. */
+ *value = error_mark_node;
+ break;
+
+ case CPP_N_INTEGER:
+ /* 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;
+ *value = interpret_integer (tok, flags, &overflow);
+ break;
+
+ case CPP_N_FLOATING:
+ *value = interpret_float (tok, flags, suffix, &overflow);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (flags & CPP_N_USERDEF)
+ {
+ char *str;
+ tree literal;
+ tree suffix_id = get_identifier (suffix);
+ int len = tok->val.str.len - strlen (suffix);
+ /* If this is going to be used as a C string to pass to a
+ raw literal operator, we need to add a trailing NUL. */
+ tree num_string = build_string (len + 1,
+ (const char *) tok->val.str.text);
+ TREE_TYPE (num_string) = char_array_type_node;
+ num_string = fix_string_type (num_string);
+ str = CONST_CAST (char *, TREE_STRING_POINTER (num_string));
+ str[len] = '\0';
+ literal = build_userdef_literal (suffix_id, *value, overflow,
+ num_string);
+ *value = literal;
+ }
+ }
+ break;
+
+ case CPP_ATSIGN:
+ /* An @ may give the next token special significance in Objective-C. */
+ if (c_dialect_objc ())
+ {
+ location_t atloc = *loc;
+ location_t newloc;
+
+ retry_at:
+ tok = cpp_get_token_with_location (parse_in, &newloc);
+ type = tok->type;
+ switch (type)
+ {
+ case CPP_PADDING:
+ goto retry_at;
+
+ case CPP_STRING:
+ case CPP_WSTRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
+ case CPP_UTF8STRING:
+ type = lex_string (tok, value, true, true);
+ break;
+
+ case CPP_NAME:
+ *value = HT_IDENT_TO_GCC_IDENT (HT_NODE (tok->val.node.node));
+ if (OBJC_IS_AT_KEYWORD (C_RID_CODE (*value))
+ || OBJC_IS_CXX_KEYWORD (C_RID_CODE (*value)))
+ {
+ type = CPP_AT_NAME;
+ /* Note the complication: if we found an OBJC_CXX
+ keyword, for example, 'class', we will be
+ returning a token of type CPP_AT_NAME and rid
+ code RID_CLASS (not RID_AT_CLASS). The language
+ parser needs to convert that to RID_AT_CLASS.
+ However, we've now spliced the '@' together with the
+ keyword that follows; Adjust the location so that we
+ get a source range covering the composite.
+ */
+ *loc = make_location (atloc, atloc, newloc);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ /* ... or not. */
+ error_at (atloc, "stray %<@%> in program");
+ *loc = newloc;
+ goto retry_after_at;
+ }
+ break;
+ }
+
+ /* FALLTHROUGH */
+ case CPP_HASH:
+ case CPP_PASTE:
+ {
+ unsigned char name[8];
+
+ *cpp_spell_token (parse_in, tok, name, true) = 0;
+
+ error_at (*loc, "stray %qs in program", name);
+ }
+
+ goto retry;
+
+ case CPP_OTHER:
+ {
+ cppchar_t c = tok->val.str.text[0];
+
+ if (c == '"' || c == '\'')
+ error_at (*loc, "missing terminating %c character", (int) c);
+ else if (ISGRAPH (c))
+ error_at (*loc, "stray %qc in program", (int) c);
+ else
+ {
+ rich_location rich_loc (line_table, *loc);
+ rich_loc.set_escape_on_output (true);
+ error_at (&rich_loc, "stray %<\\%o%> in program", (int) c);
+ }
+ }
+ goto retry;
+
+ case CPP_CHAR_USERDEF:
+ case CPP_WCHAR_USERDEF:
+ case CPP_CHAR16_USERDEF:
+ case CPP_CHAR32_USERDEF:
+ case CPP_UTF8CHAR_USERDEF:
+ {
+ tree literal;
+ cpp_token temp_tok = *tok;
+ const char *suffix = cpp_get_userdef_suffix (tok);
+ temp_tok.val.str.len -= strlen (suffix);
+ temp_tok.type = cpp_userdef_char_remove_type (type);
+ literal = build_userdef_literal (get_identifier (suffix),
+ lex_charconst (&temp_tok),
+ OT_NONE, NULL_TREE);
+ *value = literal;
+ }
+ break;
+
+ case CPP_CHAR:
+ case CPP_WCHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
+ case CPP_UTF8CHAR:
+ *value = lex_charconst (tok);
+ break;
+
+ case CPP_STRING_USERDEF:
+ case CPP_WSTRING_USERDEF:
+ case CPP_STRING16_USERDEF:
+ case CPP_STRING32_USERDEF:
+ case CPP_UTF8STRING_USERDEF:
+ {
+ tree literal, string;
+ const char *suffix = cpp_get_userdef_suffix (tok);
+ string = build_string (tok->val.str.len - strlen (suffix),
+ (const char *) tok->val.str.text);
+ literal = build_userdef_literal (get_identifier (suffix),
+ string, OT_NONE, NULL_TREE);
+ *value = literal;
+ }
+ break;
+
+ case CPP_STRING:
+ case CPP_WSTRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
+ case CPP_UTF8STRING:
+ if ((lex_flags & C_LEX_STRING_NO_JOIN) == 0)
+ {
+ type = lex_string (tok, value, false,
+ (lex_flags & C_LEX_STRING_NO_TRANSLATE) == 0);
+ break;
+ }
+ *value = build_string (tok->val.str.len, (const char *) tok->val.str.text);
+ break;
+
+ case CPP_PRAGMA:
+ fprintf(stderr, "incomplete, CPP_PRAGMA\n");
+ // sdcpp *value = build_int_cst (integer_type_node, tok->val.pragma);
+ break;
+
+ case CPP_HEADER_NAME:
+ *value = build_string (tok->val.str.len, (const char *)tok->val.str.text);
+ break;
+
+ /* This token should not be visible outside cpplib. */
+ case CPP_MACRO_ARG:
+ gcc_unreachable ();
+
+ /* CPP_COMMENT will appear when compiling with -C. Ignore, except
+ when it is a FALLTHROUGH comment, in that case set
+ PREV_FALLTHROUGH flag on the next non-comment token. */
+ case CPP_COMMENT:
+ if (tok->flags & PREV_FALLTHROUGH)
+ {
+ do
+ {
+ tok = cpp_get_token_with_location (parse_in, loc);
+ type = tok->type;
+ }
+ while (type == CPP_PADDING || type == CPP_COMMENT);
+ add_flags |= PREV_FALLTHROUGH;
+ goto retry_after_at;
+ }
+ goto retry;
+
+ default:
+ *value = NULL_TREE;
+ break;
+ }
+
+ if (cpp_flags)
+ *cpp_flags = tok->flags | add_flags;
+
+ timevar_pop (TV_CPP);
+
+ return type;
+}
+
+/* Returns the narrowest C-visible unsigned type, starting with the
+ minimum specified by FLAGS, that can fit HIGH:LOW, or itk_none if
+ there isn't one. */
+
+static enum integer_type_kind
+narrowest_unsigned_type (const widest_int &val, unsigned int flags)
+{
+ int itk;
+
+ if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ itk = itk_unsigned_int;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ itk = itk_unsigned_long;
+ else
+ itk = itk_unsigned_long_long;
+
+ for (; itk < itk_none; itk += 2 /* skip unsigned types */)
+ {
+ tree upper;
+
+ if (integer_types[itk] == NULL_TREE)
+ continue;
+ upper = TYPE_MAX_VALUE (integer_types[itk]);
+
+ if (wi::geu_p (wi::to_widest (upper), val))
+ return (enum integer_type_kind) itk;
+ }
+
+ return itk_none;
+}
+
+/* Ditto, but narrowest signed type. */
+static enum integer_type_kind
+narrowest_signed_type (const widest_int &val, unsigned int flags)
+{
+ int itk;
+
+ if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ itk = itk_int;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ itk = itk_long;
+ else
+ itk = itk_long_long;
+
+ for (; itk < itk_none; itk += 2 /* skip signed types */)
+ {
+ tree upper;
+
+ if (integer_types[itk] == NULL_TREE)
+ continue;
+ upper = TYPE_MAX_VALUE (integer_types[itk]);
+
+ if (wi::geu_p (wi::to_widest (upper), val))
+ return (enum integer_type_kind) itk;
+ }
+
+ return itk_none;
+}
+
+/* Interpret TOKEN, an integer with FLAGS as classified by cpplib. */
+static tree
+interpret_integer (const cpp_token *token, unsigned int flags,
+ enum overflow_type *overflow)
+{
+ tree value, type;
+ enum integer_type_kind itk;
+ cpp_num integer;
+ HOST_WIDE_INT ival[3];
+
+ *overflow = OT_NONE;
+
+ integer = cpp_interpret_integer (parse_in, token, flags);
+ if (integer.overflow)
+ *overflow = OT_OVERFLOW;
+
+ ival[0] = integer.low;
+ ival[1] = integer.high;
+ ival[2] = 0;
+ widest_int wval = widest_int::from_array (ival, 3);
+
+ /* The type of a constant with a U suffix is straightforward. */
+ if (flags & CPP_N_UNSIGNED)
+ itk = narrowest_unsigned_type (wval, flags);
+ else
+ {
+ /* The type of a potentially-signed integer constant varies
+ depending on the base it's in, the standard in use, and the
+ length suffixes. */
+ enum integer_type_kind itk_u
+ = narrowest_unsigned_type (wval, flags);
+ enum integer_type_kind itk_s
+ = narrowest_signed_type (wval, flags);
+
+ /* In both C89 and C99, octal and hex constants may be signed or
+ unsigned, whichever fits tighter. We do not warn about this
+ choice differing from the traditional choice, as the constant
+ is probably a bit pattern and either way will work. */
+ if ((flags & CPP_N_RADIX) != CPP_N_DECIMAL)
+ itk = MIN (itk_u, itk_s);
+ else
+ {
+ /* In C99, decimal constants are always signed.
+ In C89, decimal constants that don't fit in long have
+ undefined behavior; we try to make them unsigned long.
+ In GCC's extended C89, that last is true of decimal
+ constants that don't fit in long long, too. */
+
+ itk = itk_s;
+ if (itk_s > itk_u && itk_s > itk_long)
+ {
+ if (!flag_isoc99)
+ {
+ if (itk_u < itk_unsigned_long)
+ itk_u = itk_unsigned_long;
+ itk = itk_u;
+ warning (0, "this decimal constant is unsigned only in ISO C90");
+ }
+ else
+ warning (OPT_Wtraditional,
+ "this decimal constant would be unsigned in ISO C90");
+ }
+ }
+ }
+
+ if (itk == itk_none)
+ /* cpplib has already issued a warning for overflow. */
+ type = ((flags & CPP_N_UNSIGNED)
+ ? widest_unsigned_literal_type_node
+ : widest_integer_literal_type_node);
+ else if (flags & CPP_N_SIZE_T)
+ {
+ /* itk refers to fundamental types not aliased size types. */
+ if (flags & CPP_N_UNSIGNED)
+ type = size_type_node;
+ else
+ type = signed_size_type_node;
+ }
+ else
+ {
+ type = integer_types[itk];
+ if (itk > itk_unsigned_long
+ && (flags & CPP_N_WIDTH) != CPP_N_LARGE)
+ emit_diagnostic
+ ((c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99)
+ ? DK_PEDWARN : DK_WARNING,
+ input_location, OPT_Wlong_long,
+ (flags & CPP_N_UNSIGNED)
+ ? "integer constant is too large for %<unsigned long%> type"
+ : "integer constant is too large for %<long%> type");
+ }
+
+ fprintf(stderr, "wide_int, incomplete\n");
+ (void) type;
+#if 0 // sdcpp
+ value = wide_int_to_tree (type, wval);
+
+ /* Convert imaginary to a complex type. */
+ if (flags & CPP_N_IMAGINARY)
+ value = build_complex (NULL_TREE, build_int_cst (type, 0), value);
+#endif // sdcpp
+
+ return value;
+}
+
+/* Interpret TOKEN, a floating point number with FLAGS as classified
+ by cpplib. For C++11 SUFFIX may contain a user-defined literal suffix. */
+static tree
+interpret_float (const cpp_token *token, unsigned int flags,
+ const char *suffix, enum overflow_type *overflow)
+{
+ tree type;
+ tree const_type;
+ tree value;
+ REAL_VALUE_TYPE real;
+ REAL_VALUE_TYPE real_trunc;
+ char *copy;
+ size_t copylen;
+
+ *overflow = OT_NONE;
+
+ /* Default (no suffix) depends on whether the FLOAT_CONST_DECIMAL64
+ pragma has been used and is either double or _Decimal64. Types
+ that are not allowed with decimal float default to double. */
+ if (flags & CPP_N_DEFAULT)
+ {
+ flags ^= CPP_N_DEFAULT;
+ flags |= CPP_N_MEDIUM;
+
+ if (((flags & CPP_N_HEX) == 0) && ((flags & CPP_N_IMAGINARY) == 0))
+ {
+ warning (OPT_Wunsuffixed_float_constants,
+ "unsuffixed floating constant");
+ if (float_const_decimal64_p ())
+ flags |= CPP_N_DFLOAT;
+ }
+ }
+
+ /* Decode _Fract and _Accum. */
+ if (flags & CPP_N_FRACT || flags & CPP_N_ACCUM)
+ return interpret_fixed (token, flags);
+
+ /* Decode type based on width and properties. */
+ if (flags & CPP_N_DFLOAT)
+ fprintf(stderr, "CPP_N_DFLOAT, incomplete\n");
+#if 0 // sdcpp
+ if (!targetm.decimal_float_supported_p ())
+ {
+ error ("decimal floating-point not supported for this target");
+ return error_mark_node;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ type = dfloat128_type_node;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ type = dfloat32_type_node;
+ else
+ type = dfloat64_type_node;
+#endif // sdcpp
+ else
+ if (flags & CPP_N_WIDTH_MD)
+ {
+ fprintf(stderr, "CPP_N_WIDTH, incomplete\n");
+#if 0 // sdcpp
+ char suffix;
+ machine_mode mode;
+
+ if ((flags & CPP_N_WIDTH_MD) == CPP_N_MD_W)
+ suffix = 'w';
+ else
+ suffix = 'q';
+
+ mode = targetm.c.mode_for_suffix (suffix);
+ if (mode == VOIDmode)
+ {
+ error ("unsupported non-standard suffix on floating constant");
+
+ return error_mark_node;
+ }
+ else
+ pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
+
+ type = c_common_type_for_mode (mode, 0);
+ gcc_assert (type);
+#endif // sdcpp
+ }
+ else if ((flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) != 0)
+ {
+ fprintf(stderr, "CPP_N_FLOAT|NX, incomplete\n");
+#if 0 // sdcpp
+ unsigned int n = (flags & CPP_N_WIDTH_FLOATN_NX) >> CPP_FLOATN_SHIFT;
+ bool extended = (flags & CPP_N_FLOATNX) != 0;
+ type = NULL_TREE;
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (floatn_nx_types[i].n == (int) n
+ && floatn_nx_types[i].extended == extended)
+ {
+ type = FLOATN_NX_TYPE_NODE (i);
+ break;
+ }
+ if (type == NULL_TREE)
+ {
+ error ("unsupported non-standard suffix on floating constant");
+ return error_mark_node;
+ }
+ else
+ pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
+#endif
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ type = long_double_type_node;
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
+ || flag_single_precision_constant)
+ type = float_type_node;
+ else
+ type = double_type_node;
+
+ const_type = excess_precision_type (type);
+ if (!const_type)
+ const_type = type;
+
+ /* Copy the constant to a nul-terminated buffer. If the constant
+ has any suffixes, cut them off; REAL_VALUE_ATOF/ REAL_VALUE_HTOF
+ can't handle them. */
+ copylen = token->val.str.len;
+ if (flags & CPP_N_USERDEF)
+ copylen -= strlen (suffix);
+ else if (flags & CPP_N_DFLOAT)
+ copylen -= 2;
+ else
+ {
+ if ((flags & CPP_N_WIDTH) != CPP_N_MEDIUM)
+ /* Must be an F or L or machine defined suffix. */
+ copylen--;
+ if (flags & CPP_N_IMAGINARY)
+ /* I or J suffix. */
+ copylen--;
+ if (flags & CPP_N_FLOATNX)
+ copylen--;
+ if (flags & (CPP_N_FLOATN | CPP_N_FLOATNX))
+ {
+ unsigned int n = (flags & CPP_N_WIDTH_FLOATN_NX) >> CPP_FLOATN_SHIFT;
+ while (n > 0)
+ {
+ copylen--;
+ n /= 10;
+ }
+ }
+ }
+
+ copy = (char *) alloca (copylen + 1);
+ if (c_dialect_cxx () ? cxx_dialect > cxx11 : flag_isoc2x)
+ {
+ size_t maxlen = 0;
+ for (size_t i = 0; i < copylen; ++i)
+ if (token->val.str.text[i] != '\'')
+ copy[maxlen++] = token->val.str.text[i];
+ copy[maxlen] = '\0';
+ }
+ else
+ {
+ memcpy (copy, token->val.str.text, copylen);
+ copy[copylen] = '\0';
+ }
+
+ real_from_string3 (&real, copy, TYPE_MODE (const_type));
+ if (const_type != type)
+ /* Diagnosing if the result of converting the value with excess
+ precision to the semantic type would overflow (with associated
+ double rounding) is more appropriate than diagnosing if the
+ result of converting the string directly to the semantic type
+ would overflow. */
+ real_convert (&real_trunc, TYPE_MODE (type), &real);
+
+ /* Both C and C++ require a diagnostic for a floating constant
+ outside the range of representable values of its type. Since we
+ have __builtin_inf* to produce an infinity, this is now a
+ mandatory pedwarn if the target does not support infinities. */
+ if (REAL_VALUE_ISINF (real)
+ || (const_type != type && REAL_VALUE_ISINF (real_trunc)))
+ {
+ *overflow = OT_OVERFLOW;
+ if (!(flags & CPP_N_USERDEF))
+ {
+ if (!MODE_HAS_INFINITIES (TYPE_MODE (type)))
+ pedwarn (input_location, 0,
+ "floating constant exceeds range of %qT", type);
+ else
+ warning (OPT_Woverflow,
+ "floating constant exceeds range of %qT", type);
+ }
+ }
+ /* We also give a warning if the value underflows. */
+ else if (real_equal (&real, &dconst0)
+ || (const_type != type
+ && real_equal (&real_trunc, &dconst0)))
+ {
+ REAL_VALUE_TYPE realvoidmode;
+ int oflow = real_from_string (&realvoidmode, copy);
+ *overflow = (oflow == 0 ? OT_NONE
+ : (oflow < 0 ? OT_UNDERFLOW : OT_OVERFLOW));
+ if (!(flags & CPP_N_USERDEF))
+ {
+ if (oflow < 0 || !real_equal (&realvoidmode, &dconst0))
+ warning (OPT_Woverflow, "floating constant truncated to zero");
+ }
+ }
+
+ /* Create a node with determined type and value. */
+ value = build_real (const_type, real);
+ if (flags & CPP_N_IMAGINARY)
+ {
+ value = build_complex (NULL_TREE,
+ fold_convert (const_type,
+ integer_zero_node), value);
+ if (type != const_type)
+ {
+ const_type = TREE_TYPE (value);
+ type = build_complex_type (type);
+ }
+ }
+
+ if (type != const_type)
+ value = build1_loc (token->src_loc, EXCESS_PRECISION_EXPR, type, value);
+
+ return value;
+}
+
+/* Interpret TOKEN, a fixed-point number with FLAGS as classified
+ by cpplib. */
+
+static tree
+interpret_fixed (const cpp_token *token, unsigned int flags)
+{
+ tree type;
+ tree value;
+ FIXED_VALUE_TYPE fixed;
+ char *copy;
+ size_t copylen;
+
+ copylen = token->val.str.len;
+
+ if (flags & CPP_N_FRACT) /* _Fract. */
+ {
+ if (flags & CPP_N_UNSIGNED) /* Unsigned _Fract. */
+ {
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ {
+ type = unsigned_long_long_fract_type_node;
+ copylen -= 4;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ {
+ type = unsigned_long_fract_type_node;
+ copylen -= 3;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ {
+ type = unsigned_short_fract_type_node;
+ copylen -= 3;
+ }
+ else
+ {
+ type = unsigned_fract_type_node;
+ copylen -= 2;
+ }
+ }
+ else /* Signed _Fract. */
+ {
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ {
+ type = long_long_fract_type_node;
+ copylen -= 3;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ {
+ type = long_fract_type_node;
+ copylen -= 2;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ {
+ type = short_fract_type_node;
+ copylen -= 2;
+ }
+ else
+ {
+ type = fract_type_node;
+ copylen --;
+ }
+ }
+ }
+ else /* _Accum. */
+ {
+ if (flags & CPP_N_UNSIGNED) /* Unsigned _Accum. */
+ {
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ {
+ type = unsigned_long_long_accum_type_node;
+ copylen -= 4;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ {
+ type = unsigned_long_accum_type_node;
+ copylen -= 3;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ {
+ type = unsigned_short_accum_type_node;
+ copylen -= 3;
+ }
+ else
+ {
+ type = unsigned_accum_type_node;
+ copylen -= 2;
+ }
+ }
+ else /* Signed _Accum. */
+ {
+ if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ {
+ type = long_long_accum_type_node;
+ copylen -= 3;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+ {
+ type = long_accum_type_node;
+ copylen -= 2;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+ {
+ type = short_accum_type_node;
+ copylen -= 2;
+ }
+ else
+ {
+ type = accum_type_node;
+ copylen --;
+ }
+ }
+ }
+
+ copy = (char *) alloca (copylen + 1);
+ memcpy (copy, token->val.str.text, copylen);
+ copy[copylen] = '\0';
+
+ fixed_from_string (&fixed, copy, SCALAR_TYPE_MODE (type));
+
+ /* Create a node with determined type and value. */
+ value = build_fixed (type, fixed);
+
+ return value;
+}
+
+/* Convert a series of STRING, WSTRING, STRING16, STRING32 and/or
+ UTF8STRING tokens into a tree, performing string constant
+ concatenation. TOK is the first of these. VALP is the location to
+ write the string into. OBJC_STRING indicates whether an '@' token
+ preceded the incoming token (in that case, the strings can either
+ be ObjC strings, preceded by a single '@', or normal strings, not
+ preceded by '@'. The result will be a CPP_OBJC_STRING). Returns
+ the CPP token type of the result (CPP_STRING, CPP_WSTRING,
+ CPP_STRING32, CPP_STRING16, CPP_UTF8STRING, or CPP_OBJC_STRING).
+
+ This is unfortunately more work than it should be. If any of the
+ strings in the series has an L prefix, the result is a wide string
+ (6.4.5p4). Whether or not the result is a wide string affects the
+ meaning of octal and hexadecimal escapes (6.4.4.4p6,9). But escape
+ sequences do not continue across the boundary between two strings in
+ a series (6.4.5p7), so we must not lose the boundaries. Therefore
+ cpp_interpret_string takes a vector of cpp_string structures, which
+ we must arrange to provide. */
+
+static enum cpp_ttype
+lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate)
+{
+ tree value;
+ size_t concats = 0;
+ struct obstack str_ob;
+ struct obstack loc_ob;
+ cpp_string istr;
+ enum cpp_ttype type = tok->type;
+
+ /* Try to avoid the overhead of creating and destroying an obstack
+ for the common case of just one string. */
+ cpp_string str = tok->val.str;
+ location_t init_loc = tok->src_loc;
+ cpp_string *strs = &str;
+ location_t *locs = NULL;
+
+ /* objc_at_sign_was_seen is only used when doing Objective-C string
+ concatenation. It is 'true' if we have seen an '@' before the
+ current string, and 'false' if not. We must see exactly one or
+ zero '@' before each string. */
+ bool objc_at_sign_was_seen = false;
+
+ retry:
+ tok = cpp_get_token (parse_in);
+ switch (tok->type)
+ {
+ case CPP_PADDING:
+ goto retry;
+ case CPP_ATSIGN:
+ if (objc_string)
+ {
+ if (objc_at_sign_was_seen)
+ error ("repeated %<@%> before Objective-C string");
+
+ objc_at_sign_was_seen = true;
+ goto retry;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ break;
+
+ case CPP_WSTRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
+ case CPP_UTF8STRING:
+ if (type != tok->type)
+ {
+ if (type == CPP_STRING)
+ type = tok->type;
+ else
+ error ("unsupported non-standard concatenation of string literals");
+ }
+ /* FALLTHROUGH */
+
+ case CPP_STRING:
+ if (!concats)
+ {
+ gcc_obstack_init (&str_ob);
+ gcc_obstack_init (&loc_ob);
+ obstack_grow (&str_ob, &str, sizeof (cpp_string));
+ obstack_grow (&loc_ob, &init_loc, sizeof (location_t));
+ }
+
+ concats++;
+ obstack_grow (&str_ob, &tok->val.str, sizeof (cpp_string));
+ obstack_grow (&loc_ob, &tok->src_loc, sizeof (location_t));
+
+ if (objc_string)
+ objc_at_sign_was_seen = false;
+ goto retry;
+ }
+
+ /* It is an error if we saw a '@' with no following string. */
+ if (objc_at_sign_was_seen)
+ error ("stray %<@%> in program");
+
+ /* We have read one more token than we want. */
+ _cpp_backup_tokens (parse_in, 1);
+ if (concats)
+ {
+ strs = XOBFINISH (&str_ob, cpp_string *);
+ locs = XOBFINISH (&loc_ob, location_t *);
+ }
+
+ if (concats && !objc_string && !in_system_header_at (input_location))
+ warning (OPT_Wtraditional,
+ "traditional C rejects string constant concatenation");
+
+ if ((translate
+ ? cpp_interpret_string : cpp_interpret_string_notranslate)
+ (parse_in, strs, concats + 1, &istr, type))
+ {
+ value = build_string (istr.len, (const char *) istr.text);
+ free (CONST_CAST (unsigned char *, istr.text));
+ if (concats)
+ {
+ gcc_assert (locs);
+ gcc_assert (g_string_concat_db);
+ g_string_concat_db->record_string_concatenation (concats + 1, locs);
+ }
+ }
+ else
+ {
+ /* Callers cannot generally handle error_mark_node in this context,
+ so return the empty string instead. cpp_interpret_string has
+ issued an error. */
+ switch (type)
+ {
+ default:
+ case CPP_STRING:
+ case CPP_UTF8STRING:
+ value = build_string (1, "");
+ break;
+ case CPP_STRING16:
+ value = build_string (TYPE_PRECISION (char16_type_node)
+ / TYPE_PRECISION (char_type_node),
+ "\0"); /* char16_t is 16 bits */
+ break;
+ case CPP_STRING32:
+ value = build_string (TYPE_PRECISION (char32_type_node)
+ / TYPE_PRECISION (char_type_node),
+ "\0\0\0"); /* char32_t is 32 bits */
+ break;
+ case CPP_WSTRING:
+ value = build_string (TYPE_PRECISION (wchar_type_node)
+ / TYPE_PRECISION (char_type_node),
+ "\0\0\0"); /* widest supported wchar_t
+ is 32 bits */
+ break;
+ }
+ }
+
+ switch (type)
+ {
+ default:
+ case CPP_STRING:
+ TREE_TYPE (value) = char_array_type_node;
+ break;
+ case CPP_UTF8STRING:
+ if (flag_char8_t)
+ TREE_TYPE (value) = char8_array_type_node;
+ else
+ TREE_TYPE (value) = char_array_type_node;
+ break;
+ case CPP_STRING16:
+ TREE_TYPE (value) = char16_array_type_node;
+ break;
+ case CPP_STRING32:
+ TREE_TYPE (value) = char32_array_type_node;
+ break;
+ case CPP_WSTRING:
+ TREE_TYPE (value) = wchar_array_type_node;
+ }
+ *valp = fix_string_type (value);
+
+ if (concats)
+ {
+ obstack_free (&str_ob, 0);
+ obstack_free (&loc_ob, 0);
+ }
+
+ return objc_string ? CPP_OBJC_STRING : type;
+}
+
+/* Converts a (possibly wide) character constant token into a tree. */
+static tree
+lex_charconst (const cpp_token *token)
+{
+ cppchar_t result;
+ tree type, value;
+ unsigned int chars_seen;
+ int unsignedp = 0;
+
+ result = cpp_interpret_charconst (parse_in, token,
+ &chars_seen, &unsignedp);
+
+ if (token->type == CPP_WCHAR)
+ type = wchar_type_node;
+ else if (token->type == CPP_CHAR32)
+ type = char32_type_node;
+ else if (token->type == CPP_CHAR16)
+ type = char16_type_node;
+ else if (token->type == CPP_UTF8CHAR)
+ {
+ if (!c_dialect_cxx ())
+ type = unsigned_char_type_node;
+ else if (flag_char8_t)
+ type = char8_type_node;
+ else
+ type = char_type_node;
+ }
+ /* In C, a character constant has type 'int'.
+ In C++ 'char', but multi-char charconsts have type 'int'. */
+ else if (!c_dialect_cxx () || chars_seen > 1)
+ type = integer_type_node;
+ else
+ type = char_type_node;
+
+ /* Cast to cppchar_signed_t to get correct sign-extension of RESULT
+ before possibly widening to HOST_WIDE_INT for build_int_cst. */
+ fprintf(stderr, "charconst, incomplete\n");
+#if 0 // sdcpp
+ if (unsignedp || (cppchar_signed_t) result >= 0)
+ value = build_int_cst (type, result);
+ else
+ value = build_int_cst (type, (cppchar_signed_t) result);
+#endif // sdcpp
+
+ return value;
+}
+
+/* Helper function for c_parser_peek_conflict_marker
+ and cp_lexer_peek_conflict_marker.
+ Given a possible conflict marker token of kind TOK1_KIND
+ consisting of a pair of characters, get the token kind for the
+ standalone final character. */
+
+enum cpp_ttype
+conflict_marker_get_final_tok_kind (enum cpp_ttype tok1_kind)
+{
+ switch (tok1_kind)
+ {
+ default: gcc_unreachable ();
+ case CPP_LSHIFT:
+ /* "<<" and '<' */
+ return CPP_LESS;
+
+ case CPP_EQ_EQ:
+ /* "==" and '=' */
+ return CPP_EQ;
+
+ case CPP_RSHIFT:
+ /* ">>" and '>' */
+ return CPP_GREATER;
+ }
+}
+#endif // sdcpp
diff --git a/support/cpp/gcc/c-family/c-objc.h b/support/cpp/gcc/c-family/c-objc.h
new file mode 100644
index 000000000..567b383af
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-objc.h
@@ -0,0 +1,183 @@
+/* Definitions of Objective-C front-end entry points used for C and C++.
+ 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/>. */
+
+#if 0 // sdcpp ndef GCC_C_COMMON_OBJC_H
+#define GCC_C_COMMON_OBJC_H
+
+/* ObjC ivar visibility types. */
+enum GTY(()) objc_ivar_visibility_kind {
+ OBJC_IVAR_VIS_PROTECTED = 0,
+ OBJC_IVAR_VIS_PUBLIC = 1,
+ OBJC_IVAR_VIS_PRIVATE = 2,
+ OBJC_IVAR_VIS_PACKAGE = 3
+};
+
+/* ObjC property attribute kinds.
+ These have two fields; a unique value (that identifies which attribute)
+ and a group key that indicates membership of an exclusion group.
+ Only one member may be present from an exclusion group in a given attribute
+ list.
+ getters and setters have additional rules, since they are excluded from
+ non-overlapping group sets. */
+
+enum objc_property_attribute_group
+{
+ OBJC_PROPATTR_GROUP_UNKNOWN = 0,
+ OBJC_PROPATTR_GROUP_GETTER,
+ OBJC_PROPATTR_GROUP_SETTER,
+ OBJC_PROPATTR_GROUP_READWRITE,
+ OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPATTR_GROUP_ATOMIC,
+ OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPATTR_GROUP_CLASS,
+ OBJC_PROPATTR_GROUP_MAX
+};
+
+enum objc_property_attribute_kind
+{
+ OBJC_PROPERTY_ATTR_UNKNOWN = 0|OBJC_PROPATTR_GROUP_UNKNOWN,
+ OBJC_PROPERTY_ATTR_GETTER = ( 1 << 8)|OBJC_PROPATTR_GROUP_GETTER,
+ OBJC_PROPERTY_ATTR_SETTER = ( 2 << 8)|OBJC_PROPATTR_GROUP_SETTER,
+ OBJC_PROPERTY_ATTR_READONLY = ( 3 << 8)|OBJC_PROPATTR_GROUP_READWRITE,
+ OBJC_PROPERTY_ATTR_READWRITE = ( 4 << 8)|OBJC_PROPATTR_GROUP_READWRITE,
+ OBJC_PROPERTY_ATTR_ASSIGN = ( 5 << 8)|OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPERTY_ATTR_RETAIN = ( 6 << 8)|OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPERTY_ATTR_COPY = ( 7 << 8)|OBJC_PROPATTR_GROUP_ASSIGN,
+ OBJC_PROPERTY_ATTR_ATOMIC = ( 8 << 8)|OBJC_PROPATTR_GROUP_ATOMIC,
+ OBJC_PROPERTY_ATTR_NONATOMIC = ( 9 << 8)|OBJC_PROPATTR_GROUP_ATOMIC,
+ OBJC_PROPERTY_ATTR_NULL_UNSPECIFIED = (12 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_NULLABLE = (13 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_NONNULL = (14 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_NULL_RESETTABLE = (15 << 8)|OBJC_PROPATTR_GROUP_NULLABLE,
+ OBJC_PROPERTY_ATTR_CLASS = (16 << 8)|OBJC_PROPATTR_GROUP_CLASS,
+ OBJC_PROPERTY_ATTR_MAX = (255 << 8|OBJC_PROPATTR_GROUP_MAX)
+};
+
+#define OBJC_PROPATTR_GROUP_MASK 0x0f
+
+/* To contain parsed, but unverified, information about a single property
+ attribute. */
+struct property_attribute_info
+{
+ property_attribute_info () = default;
+ property_attribute_info (tree name, location_t loc,
+ enum objc_property_attribute_kind k)
+ : name (name), ident (NULL_TREE), prop_loc (loc), prop_kind (k),
+ parse_error (false) {}
+
+ enum objc_property_attribute_group group ()
+ {
+ return (enum objc_property_attribute_group)
+ ((unsigned)prop_kind & OBJC_PROPATTR_GROUP_MASK);
+ }
+
+ tree name; /* Name of the attribute. */
+ tree ident; /* For getter/setter cases, the method/selector name. */
+ location_t prop_loc; /* Extended location covering the parsed attr. */
+ enum objc_property_attribute_kind prop_kind : 16;
+ unsigned parse_error : 1; /* The C/C++ parser saw an error in this attr. */
+};
+
+extern enum objc_property_attribute_kind objc_prop_attr_kind_for_rid (enum rid);
+
+/* Objective-C / Objective-C++ entry points. */
+
+/* The following ObjC/ObjC++ functions are called by the C and/or C++
+ front-ends; they all must have corresponding stubs in stub-objc.cc. */
+extern void objc_write_global_declarations (void);
+extern tree objc_is_class_name (tree);
+extern tree objc_is_object_ptr (tree);
+extern void objc_check_decl (tree);
+extern void objc_check_global_decl (tree);
+extern tree objc_common_type (tree, tree);
+extern bool objc_compare_types (tree, tree, int, tree);
+extern bool objc_have_common_type (tree, tree, int, tree);
+extern bool objc_diagnose_private_ivar (tree);
+extern void objc_volatilize_decl (tree);
+extern tree objc_rewrite_function_call (tree, tree);
+extern tree objc_message_selector (void);
+extern tree objc_lookup_ivar (tree, tree);
+extern void objc_clear_super_receiver (void);
+extern int objc_is_public (tree, tree);
+extern tree objc_is_id (tree);
+extern void objc_declare_alias (tree, tree);
+extern void objc_declare_class (tree);
+extern void objc_declare_protocol (tree, tree);
+extern tree objc_build_message_expr (tree, tree);
+extern tree objc_finish_message_expr (tree, tree, tree, tree*);
+extern tree objc_build_selector_expr (location_t, tree);
+extern tree objc_build_protocol_expr (tree);
+extern tree objc_build_encode_expr (tree);
+extern tree objc_build_string_object (tree);
+extern tree objc_get_protocol_qualified_type (tree, tree);
+extern tree objc_get_class_reference (tree);
+extern tree objc_get_class_ivars (tree);
+extern bool objc_detect_field_duplicates (bool);
+extern void objc_start_class_interface (tree, location_t, tree, tree, tree);
+extern void objc_start_category_interface (tree, tree, tree, tree);
+extern void objc_start_protocol (tree, tree, tree);
+extern void objc_continue_interface (void);
+extern void objc_finish_interface (void);
+extern void objc_start_class_implementation (tree, tree);
+extern void objc_start_category_implementation (tree, tree);
+extern void objc_continue_implementation (void);
+extern void objc_finish_implementation (void);
+extern void objc_set_visibility (objc_ivar_visibility_kind);
+extern tree objc_build_method_signature (bool, tree, tree, tree, bool);
+extern void objc_add_method_declaration (bool, tree, tree);
+extern bool objc_start_method_definition (bool, tree, tree, tree);
+extern void objc_finish_method_definition (tree);
+extern void objc_add_instance_variable (tree);
+extern tree objc_build_keyword_decl (tree, tree, tree, tree);
+extern tree objc_build_throw_stmt (location_t, tree);
+extern void objc_begin_try_stmt (location_t, tree);
+extern tree objc_finish_try_stmt (void);
+extern void objc_begin_catch_clause (tree);
+extern void objc_finish_catch_clause (void);
+extern void objc_build_finally_clause (location_t, tree);
+extern tree objc_build_synchronized (location_t, tree, tree);
+extern int objc_static_init_needed_p (void);
+extern tree objc_generate_static_init_call (tree);
+extern tree objc_generate_write_barrier (tree, enum tree_code, tree);
+extern void objc_set_method_opt (bool);
+extern void objc_finish_foreach_loop (location_t, tree, tree, tree, tree, tree);
+extern bool objc_method_decl (enum tree_code);
+extern void objc_add_property_declaration (location_t, tree,
+ vec<property_attribute_info *>&);
+extern tree objc_maybe_build_component_ref (tree, tree);
+extern tree objc_build_class_component_ref (tree, tree);
+extern tree objc_maybe_build_modify_expr (tree, tree);
+extern tree objc_build_incr_expr_for_property_ref (location_t, enum tree_code,
+ tree, tree);
+extern void objc_add_synthesize_declaration (location_t, tree);
+extern void objc_add_dynamic_declaration (location_t, tree);
+extern const char * objc_maybe_printable_name (tree, int);
+extern bool objc_is_property_ref (tree);
+extern bool objc_non_constant_expr_p (tree);
+extern bool objc_string_ref_type_p (tree);
+extern void objc_check_format_arg (tree, tree);
+extern void objc_finish_function (void);
+extern void objc_maybe_warn_exceptions (location_t);
+
+/* The following are provided by the C and C++ front-ends, and called by
+ ObjC/ObjC++. */
+extern void *objc_get_current_scope (void);
+extern void objc_mark_locals_volatile (void *);
+
+#endif /* ! GCC_C_COMMON_OBJC_H */
diff --git a/support/cpp/gcc/c-family/c-opts.cc b/support/cpp/gcc/c-family/c-opts.cc
new file mode 100644
index 000000000..ca7ce55d8
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-opts.cc
@@ -0,0 +1,1902 @@
+/* C/ObjC/C++ command line option handling.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Contributed by Neil Booth.
+
+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 <map> // BUG?
+#include <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ \
+ <<":" << __func__ << "\n" )
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "c-target.h"
+#include "c-common.h"
+#include "memmodel.h"
+// sdcpp #include "tm_p.h" /* For C_COMMON_OVERRIDE_OPTIONS. */
+#include "diagnostic.h"
+#include "c-pragma.h"
+#include "flags.h"
+#include "toplev.h"
+#include "langhooks.h"
+#include "tree-diagnostic.h" /* for virt_loc_aware_diagnostic_finalizer */
+#include "intl.h"
+#include "cppdefault.h"
+#include "incpath.h"
+#include "debug.h" /* For debug_hooks. */
+#include "opts.h"
+#include "plugin.h" /* For PLUGIN_INCLUDE_FILE event. */
+#include "mkdeps.h"
+#include "dumpfile.h"
+#include "file-prefix-map.h" /* add_*_prefix_map() */
+
+// #include "../libcpp/internal.h" // BUG
+
+#ifndef DOLLARS_IN_IDENTIFIERS
+# define DOLLARS_IN_IDENTIFIERS true
+#endif
+
+#ifndef TARGET_SYSTEM_ROOT
+# define TARGET_SYSTEM_ROOT NULL
+#endif
+
+#ifndef TARGET_OPTF
+#define TARGET_OPTF(ARG)
+#endif
+
+/* CPP's options. */
+cpp_options *cpp_opts = nullptr;
+
+/* Input filename. */
+static const char *this_input_filename;
+
+/* Filename and stream for preprocessed output. */
+static const char *out_fname;
+static FILE *out_stream;
+
+/* Append dependencies to deps_file. */
+static bool deps_append;
+
+/* If dependency switches (-MF etc.) have been given. */
+static bool deps_seen;
+
+/* If -v seen. */
+static bool verbose;
+
+/* Dependency output file. */
+static const char *deps_file;
+
+/* The prefix given by -iprefix, if any. */
+static const char *iprefix;
+
+/* The multilib directory given by -imultilib, if any. */
+static const char *imultilib;
+
+/* The system root, if any. Overridden by -isysroot. */
+static const char *sysroot = TARGET_SYSTEM_ROOT;
+
+/* Zero disables all standard directories for headers. */
+static bool std_inc = true;
+
+/* Zero disables the C++-specific standard directories for headers. */
+static bool std_cxx_inc = true;
+
+/* If the quote chain has been split by -I-. */
+static bool quote_chain_split;
+
+/* Number of deferred options. */
+static size_t deferred_count;
+
+/* Number of deferred options scanned for -include. */
+static size_t include_cursor;
+
+/* Dump files/flags to use during parsing. */
+static FILE *original_dump_file = NULL;
+static dump_flags_t original_dump_flags;
+
+/* Whether any standard preincluded header has been preincluded. */
+static bool done_preinclude;
+
+static void handle_OPT_d (const char *);
+static void set_std_cxx98 (int);
+static void set_std_cxx11 (int);
+static void set_std_cxx14 (int);
+static void set_std_cxx17 (int);
+static void set_std_cxx20 (int);
+static void set_std_cxx23 (int);
+static void set_std_c89 (int, int);
+static void set_std_c99 (int);
+static void set_std_c11 (int);
+static void set_std_c17 (int);
+static void set_std_c2x (int);
+static void check_deps_environment_vars (void);
+static void handle_deferred_opts (void);
+static void sanitize_cpp_opts (void);
+static void add_prefixed_path (const char *, incpath_kind);
+static void push_command_line_include (void);
+static void cb_file_change (cpp_reader *, const line_map_ordinary *);
+static void cb_dir_change (cpp_reader *, const char *);
+static void c_finish_options (void);
+
+#ifndef STDC_0_IN_SYSTEM_HEADERS
+#define STDC_0_IN_SYSTEM_HEADERS 0
+#endif
+
+/* Holds switches parsed by c_common_handle_option (), but whose
+ handling is deferred to c_common_post_options (). */
+static void defer_opt (enum opt_code, const char *);
+static struct deferred_opt
+{
+ enum opt_code code;
+ const char *arg;
+} *deferred_opts;
+
+
+extern const unsigned int
+c_family_lang_mask = (CL_C | CL_CXX | CL_ObjC | CL_ObjCXX);
+
+/* Defer option CODE with argument ARG. */
+static void
+defer_opt (enum opt_code code, const char *arg)
+{
+ deferred_opts[deferred_count].code = code;
+ deferred_opts[deferred_count].arg = arg;
+ deferred_count++;
+}
+
+/* Return language mask for option parsing. */
+unsigned int
+c_common_option_lang_mask (void)
+{
+ static const unsigned int lang_flags[] = {CL_C, CL_ObjC, CL_CXX, CL_ObjCXX};
+
+ return lang_flags[c_language];
+}
+
+/* Diagnostic finalizer for C/C++/Objective-C/Objective-C++. */
+static void
+c_diagnostic_finalizer (diagnostic_context *context,
+ diagnostic_info *diagnostic,
+ diagnostic_t)
+{
+ char *saved_prefix = pp_take_prefix (context->printer);
+ pp_set_prefix (context->printer, NULL);
+ pp_newline (context->printer);
+ diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
+ /* By default print macro expansion contexts in the diagnostic
+ finalizer -- for tokens resulting from macro expansion. */
+ virt_loc_aware_diagnostic_finalizer (context, diagnostic);
+ pp_set_prefix (context->printer, saved_prefix);
+ pp_flush (context->printer);
+}
+
+/* Common default settings for diagnostics. */
+void
+c_common_diagnostics_set_defaults (diagnostic_context *context)
+{
+ diagnostic_finalizer (context) = c_diagnostic_finalizer;
+ context->opt_permissive = OPT_fpermissive;
+}
+
+/* Input charset configuration for diagnostics. */
+static const char *
+c_common_input_charset_cb (const char * /*filename*/)
+{
+ const char *cs = cpp_opts->input_charset;
+ return cpp_input_conversion_is_trivial (cs) ? nullptr : cs;
+}
+
+/* Whether options from all C-family languages should be accepted
+ quietly. */
+static bool accept_all_c_family_options = false;
+
+/* Return whether to complain about a wrong-language option. */
+bool
+c_common_complain_wrong_lang_p (const struct cl_option *option)
+{
+ if (accept_all_c_family_options
+ && (option->flags & c_family_lang_mask))
+ return false;
+
+ return true;
+}
+
+/* Initialize options structure OPTS. */
+void
+c_common_init_options_struct (struct gcc_options *opts)
+{
+ opts->x_flag_exceptions = c_dialect_cxx ();
+ opts->x_warn_pointer_arith = c_dialect_cxx ();
+ opts->x_warn_write_strings = c_dialect_cxx ();
+ opts->x_flag_warn_unused_result = true;
+
+ /* By default, C99-like requirements for complex multiply and divide. */
+ opts->x_flag_complex_method = 2;
+ opts->x_flag_default_complex_method = opts->x_flag_complex_method;
+}
+
+/* Common initialization before calling option handlers. */
+void
+c_common_init_options (unsigned int decoded_options_count,
+ struct cl_decoded_option *decoded_options)
+{
+ unsigned int i;
+ struct cpp_callbacks *cb;
+
+ g_string_concat_db
+ = new (ggc_alloc <string_concat_db> ()) string_concat_db ();
+
+ parse_in = cpp_create_reader (c_dialect_cxx () ? CLK_GNUCXX: CLK_GNUC89,
+ ident_hash, line_table);
+ cb = cpp_get_callbacks (parse_in);
+ cb->diagnostic = c_cpp_diagnostic;
+
+ cpp_opts = cpp_get_options (parse_in);
+ cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
+ cpp_opts->objc = c_dialect_objc ();
+ cpp_opts->deps.modules = true;
+
+ /* Reset to avoid warnings on internal definitions. We set it just
+ before passing on command-line options to cpplib. */
+ cpp_opts->warn_dollars = 0;
+
+ deferred_opts = XNEWVEC (struct deferred_opt, decoded_options_count);
+
+ if (c_language == clk_c)
+ {
+ /* The default for C is gnu17. */
+ set_std_c17 (false /* ISO */);
+
+ /* If preprocessing assembly language, accept any of the C-family
+ front end options since the driver may pass them through. */
+ for (i = 1; i < decoded_options_count; i++)
+ if (decoded_options[i].opt_index == OPT_lang_asm)
+ {
+ accept_all_c_family_options = true;
+ break;
+ }
+ }
+
+ /* Set C++ standard to C++17 if not specified on the command line. */
+ if (c_dialect_cxx ())
+ set_std_cxx17 (/*ISO*/false);
+
+ global_dc->colorize_source_p = true;
+
+ cpp_opts->allow_naked_hash = 0;
+ cpp_opts->preproc_asm = 1;
+ cpp_opts->pedantic_parse_number = 0;
+ cpp_opts->obj_ext = NULL;
+
+
+#if 0 // from sdcpp.c
+
+ /* Kevin abuse for SDCC. */
+ cpp_register_pragma(parse_in, 0, "sdcc_hash", do_pragma_sdcc_hash, false);
+ /* SDCC _asm specific */
+ cpp_register_pragma(parse_in, 0, "preproc_asm", do_pragma_preproc_asm, false);
+ /* SDCC specific */
+ cpp_register_pragma(parse_in, 0, "pedantic_parse_number", do_pragma_pedantic_parse_number, false);
+
+#endif
+}
+
+# if 0 // sdcpp init option, from sdcpp-opts.c
+ struct cpp_callbacks *cb;
+
+ parse_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
+ cb = cpp_get_callbacks (parse_in);
+ cb->error = c_cpp_error;
+
+ cpp_opts = cpp_get_options (parse_in);
+ cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
+ cpp_opts->objc = 0;
+
+ /* Reset to avoid warnings on internal definitions. We set it just
+ before passing on command-line options to cpplib. */
+ cpp_opts->warn_dollars = 0;
+
+ deferred_opts = XNEWVEC (struct deferred_opt, argc);
+
+ return CL_SDCPP;
+#endif
+
+/* Handle switch SCODE with argument ARG. VALUE is true, unless no-
+ form of an -f or -W option was given. Returns false if the switch was
+ invalid, true if valid. Use HANDLERS in recursive handle_option calls. */
+bool
+c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
+ int kind, location_t loc,
+ const struct cl_option_handlers *handlers)
+{
+ const struct cl_option *option = &cl_options[scode];
+ enum opt_code code = (enum opt_code) scode;
+ bool result = true;
+
+ /* Prevent resetting the language standard to a C dialect when the driver
+ has already determined that we're looking at assembler input. */
+ bool preprocessing_asm_p = (cpp_get_options (parse_in)->lang == CLK_ASM);
+
+ switch (code)
+ {
+ default:
+ if (cl_options[code].flags & c_family_lang_mask)
+ {
+ if ((option->flags & CL_TARGET)
+ // sdcpp && ! targetcm.handle_c_option (scode, arg, value)
+ )
+ result = false;
+ break;
+ }
+ result = false;
+ break;
+
+ case OPT__output_pch_:
+ pch_file = arg;
+ break;
+
+ case OPT_A:
+ defer_opt (code, arg);
+ break;
+
+ case OPT_C:
+ cpp_opts->discard_comments = 0;
+ break;
+
+ case OPT_CC:
+ cpp_opts->discard_comments = 0;
+ cpp_opts->discard_comments_in_macro_exp = 0;
+ break;
+
+ case OPT_D:
+ defer_opt (code, arg);
+ break;
+
+ case OPT_H:
+ cpp_opts->print_include_names = 1;
+ break;
+
+ case OPT_F:
+ TARGET_OPTF (xstrdup (arg));
+ break;
+
+ case OPT_I:
+ if (strcmp (arg, "-"))
+ add_path (xstrdup (arg), INC_BRACKET, 0, true);
+ else
+ {
+ if (quote_chain_split)
+ error ("%<-I-%> specified twice");
+ quote_chain_split = true;
+ split_quote_chain ();
+ inform (input_location, "obsolete option %<-I-%> used, "
+ "please use %<-iquote%> instead");
+ }
+ break;
+
+ case OPT_M:
+ case OPT_MM:
+ /* When doing dependencies with -M or -MM, suppress normal
+ preprocessed output, but still do -dM etc. as software
+ depends on this. Preprocessed output does occur if -MD, -MMD
+ or environment var dependency generation is used. */
+ cpp_opts->deps.style = (code == OPT_M ? DEPS_SYSTEM: DEPS_USER);
+ flag_no_output = 1;
+ break;
+
+ case OPT_MD:
+ case OPT_MMD:
+ cpp_opts->deps.style = (code == OPT_MD ? DEPS_SYSTEM: DEPS_USER);
+ cpp_opts->deps.need_preprocessor_output = true;
+ deps_file = arg;
+ break;
+
+ case OPT_MF:
+ deps_seen = true;
+ deps_file = arg;
+ break;
+
+ case OPT_MG:
+ deps_seen = true;
+ cpp_opts->deps.missing_files = true;
+ break;
+
+ case OPT_MP:
+ deps_seen = true;
+ cpp_opts->deps.phony_targets = true;
+ break;
+
+ case OPT_Mmodules:
+ /* Do not set deps_seen, so the user can unconditionally turn
+ this on or off. */
+ cpp_opts->deps.modules = true;
+ break;
+
+ case OPT_Mno_modules:
+ /* Do not set deps_seen, so the user can unconditionally turn
+ this on or off. */
+ cpp_opts->deps.modules = false;
+ break;
+
+ case OPT_MQ:
+ case OPT_MT:
+ deps_seen = true;
+ defer_opt (code, arg);
+ break;
+
+ case OPT_P:
+ flag_no_line_commands = 1;
+ break;
+
+ case OPT_U:
+ defer_opt (code, arg);
+ break;
+
+ case OPT_Wall:
+ /* ??? Don't add new options here. Use LangEnabledBy in c.opt. */
+
+ cpp_opts->warn_num_sign_change = value;
+ break;
+
+ case OPT_Wunknown_pragmas:
+ /* Set to greater than 1, so that even unknown pragmas in
+ system headers will be warned about. */
+ /* ??? There is no way to handle this automatically for now. */
+ warn_unknown_pragmas = value * 2;
+ break;
+
+ case OPT_ansi:
+ if (!c_dialect_cxx ())
+ set_std_c89 (false, true);
+ else
+ set_std_cxx98 (true);
+ break;
+
+ case OPT_d:
+ handle_OPT_d (arg);
+ break;
+
+ case OPT_Wabi_:
+ warn_abi = true;
+ if (value == 1)
+ {
+ warning (0, "%<-Wabi=1%> is not supported, using =2");
+ value = 2;
+ }
+ warn_abi_version = value;
+ break;
+
+ case OPT_fcanonical_system_headers:
+ cpp_opts->canonical_system_headers = value;
+ break;
+
+ case OPT_fcond_mismatch:
+ if (!c_dialect_cxx ())
+ {
+ flag_cond_mismatch = value;
+ break;
+ }
+ warning (0, "switch %qs is no longer supported", option->opt_text);
+ break;
+
+ case OPT_fbuiltin_:
+ if (value)
+ result = false;
+ else
+ disable_builtin_function (arg);
+ break;
+
+ case OPT_fdirectives_only:
+ cpp_opts->directives_only = value;
+ break;
+
+ case OPT_fdollars_in_identifiers:
+ cpp_opts->dollars_in_ident = value;
+ break;
+
+ case OPT_fmacro_prefix_map_:
+ add_macro_prefix_map (arg);
+ break;
+
+ case OPT_ffreestanding:
+ value = !value;
+ /* Fall through. */
+ case OPT_fhosted:
+ flag_hosted = value;
+ flag_no_builtin = !value;
+ break;
+
+ case OPT_fconstant_string_class_:
+ constant_string_class_name = arg;
+ break;
+
+ case OPT_fextended_identifiers:
+ cpp_opts->extended_identifiers = value;
+ break;
+
+ case OPT_fmax_include_depth_:
+ cpp_opts->max_include_depth = value;
+ break;
+
+ case OPT_foperator_names:
+ cpp_opts->operator_names = value;
+ break;
+
+ case OPT_fpch_deps:
+ cpp_opts->restore_pch_deps = value;
+ break;
+
+ case OPT_fpch_preprocess:
+ flag_pch_preprocess = value;
+ break;
+
+ case OPT_fpermissive:
+ flag_permissive = value;
+ global_dc->permissive = value;
+ break;
+
+ case OPT_fpreprocessed:
+ cpp_opts->preprocessed = value;
+ break;
+
+ case OPT_fdebug_cpp:
+ cpp_opts->debug = 1;
+ break;
+
+ case OPT_ftrack_macro_expansion:
+ if (value)
+ value = 2;
+ /* Fall Through. */
+
+ case OPT_ftrack_macro_expansion_:
+ if (arg && *arg != '\0')
+ cpp_opts->track_macro_expansion = value;
+ else
+ cpp_opts->track_macro_expansion = 2;
+ break;
+
+ case OPT_fexec_charset_:
+ cpp_opts->narrow_charset = arg;
+ break;
+
+ case OPT_fwide_exec_charset_:
+ cpp_opts->wide_charset = arg;
+ break;
+
+ case OPT_finput_charset_:
+ cpp_opts->input_charset = arg;
+ break;
+
+ case OPT_ftemplate_depth_:
+ max_tinst_depth = value;
+ break;
+
+ case OPT_fvisibility_inlines_hidden:
+ visibility_options.inlines_hidden = value;
+ break;
+
+ case OPT_femit_struct_debug_baseonly:
+ set_struct_debug_option (&global_options, loc, "base");
+ break;
+
+ case OPT_femit_struct_debug_reduced:
+ set_struct_debug_option (&global_options, loc,
+ "dir:ord:sys,dir:gen:any,ind:base");
+ break;
+
+ case OPT_femit_struct_debug_detailed_:
+ set_struct_debug_option (&global_options, loc, arg);
+ break;
+
+ case OPT_fext_numeric_literals:
+ cpp_opts->ext_numeric_literals = value;
+ break;
+
+ case OPT_idirafter:
+ add_path (xstrdup (arg), INC_AFTER, 0, true);
+ break;
+
+ case OPT_imacros:
+ case OPT_include:
+ defer_opt (code, arg);
+ break;
+
+ case OPT_imultilib:
+ imultilib = arg;
+ break;
+
+ case OPT_iprefix:
+ iprefix = arg;
+ break;
+
+ case OPT_iquote:
+ add_path (xstrdup (arg), INC_QUOTE, 0, true);
+ break;
+
+ case OPT_isysroot:
+ sysroot = arg;
+ break;
+
+ case OPT_isystem:
+ add_path (xstrdup (arg), INC_SYSTEM, 0, true);
+ break;
+
+ case OPT_iwithprefix:
+ add_prefixed_path (arg, INC_SYSTEM);
+ break;
+
+ case OPT_iwithprefixbefore:
+ add_prefixed_path (arg, INC_BRACKET);
+ break;
+
+ case OPT_lang_asm:
+ cpp_set_lang (parse_in, CLK_ASM);
+ cpp_opts->dollars_in_ident = false;
+ break;
+
+ case OPT_nostdinc:
+ std_inc = false;
+ break;
+
+ case OPT_nostdinc__:
+ std_cxx_inc = false;
+ break;
+
+ case OPT_o:
+ if (!out_fname)
+ out_fname = arg;
+ else
+ error ("output filename specified twice");
+ break;
+
+ case OPT_print_objc_runtime_info:
+ print_struct_values = 1;
+ break;
+
+ case OPT_remap:
+ cpp_opts->remap = 1;
+ break;
+
+ case OPT_std_c__98:
+ case OPT_std_gnu__98:
+ if (!preprocessing_asm_p)
+ set_std_cxx98 (code == OPT_std_c__98 /* ISO */);
+ break;
+
+ case OPT_std_c__11:
+ case OPT_std_gnu__11:
+ if (!preprocessing_asm_p)
+ set_std_cxx11 (code == OPT_std_c__11 /* ISO */);
+ break;
+
+ case OPT_std_c__14:
+ case OPT_std_gnu__14:
+ if (!preprocessing_asm_p)
+ set_std_cxx14 (code == OPT_std_c__14 /* ISO */);
+ break;
+
+ case OPT_std_c__17:
+ case OPT_std_gnu__17:
+ if (!preprocessing_asm_p)
+ set_std_cxx17 (code == OPT_std_c__17 /* ISO */);
+ break;
+
+ case OPT_std_c__20:
+ case OPT_std_gnu__20:
+ if (!preprocessing_asm_p)
+ set_std_cxx20 (code == OPT_std_c__20 /* ISO */);
+ break;
+
+ case OPT_std_c__23:
+ case OPT_std_gnu__23:
+ if (!preprocessing_asm_p)
+ set_std_cxx23 (code == OPT_std_c__23 /* ISO */);
+ break;
+
+ case OPT_std_c90:
+ case OPT_std_iso9899_199409:
+ if (!preprocessing_asm_p)
+ set_std_c89 (code == OPT_std_iso9899_199409 /* c94 */, true /* ISO */);
+ break;
+
+ case OPT_std_gnu90:
+ if (!preprocessing_asm_p)
+ set_std_c89 (false /* c94 */, false /* ISO */);
+ break;
+
+ case OPT_std_c99:
+ if (!preprocessing_asm_p)
+ set_std_c99 (true /* ISO */);
+ break;
+
+ case OPT_std_gnu99:
+ if (!preprocessing_asm_p)
+ set_std_c99 (false /* ISO */);
+ break;
+
+ case OPT_std_c11:
+ if (!preprocessing_asm_p)
+ set_std_c11 (true /* ISO */);
+ break;
+
+ case OPT_std_gnu11:
+ if (!preprocessing_asm_p)
+ set_std_c11 (false /* ISO */);
+ break;
+
+ case OPT_std_c17:
+ if (!preprocessing_asm_p)
+ set_std_c17 (true /* ISO */);
+ break;
+
+ case OPT_std_gnu17:
+ if (!preprocessing_asm_p)
+ set_std_c17 (false /* ISO */);
+ break;
+
+ case OPT_std_c2x:
+ if (!preprocessing_asm_p)
+ set_std_c2x (true /* ISO */);
+ break;
+
+ case OPT_std_gnu2x:
+ if (!preprocessing_asm_p)
+ set_std_c2x (false /* ISO */);
+ break;
+
+ case OPT_trigraphs:
+ cpp_opts->trigraphs = 1;
+ break;
+
+ case OPT_traditional_cpp:
+ cpp_opts->traditional = 1;
+ break;
+
+ case OPT_v:
+ verbose = true;
+ break;
+ }
+
+ switch (c_language)
+ {
+ case clk_c:
+ C_handle_option_auto (&global_options, &global_options_set,
+ scode, arg, value,
+ c_family_lang_mask, kind,
+ loc, handlers, global_dc);
+ break;
+
+ case clk_objc:
+ ObjC_handle_option_auto (&global_options, &global_options_set,
+ scode, arg, value,
+ c_family_lang_mask, kind,
+ loc, handlers, global_dc);
+ break;
+
+ case clk_cxx:
+ CXX_handle_option_auto (&global_options, &global_options_set,
+ scode, arg, value,
+ c_family_lang_mask, kind,
+ loc, handlers, global_dc);
+ break;
+
+ case clk_objcxx:
+ ObjCXX_handle_option_auto (&global_options, &global_options_set,
+ scode, arg, value,
+ c_family_lang_mask, kind,
+ loc, handlers, global_dc);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ cpp_handle_option_auto (&global_options, scode, cpp_opts);
+ return result;
+}
+
+/* Default implementation of TARGET_HANDLE_C_OPTION. */
+
+bool
+default_handle_c_option (size_t code ATTRIBUTE_UNUSED,
+ const char *arg ATTRIBUTE_UNUSED,
+ int value ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+/* Post-switch processing. */
+bool
+c_common_post_options (const char **pfilename)
+{
+ /* Canonicalize the input and output filenames. */
+ if (in_fnames == NULL)
+ {
+ in_fnames = XNEWVEC (const char *, 1);
+ in_fnames[0] = "";
+ }
+ else if (strcmp (in_fnames[0], "-") == 0)
+ {
+ if (pch_file)
+ error ("cannot use %<-%> as input filename for a precompiled header");
+
+ in_fnames[0] = "";
+ }
+
+ if (out_fname == NULL || !strcmp (out_fname, "-"))
+ out_fname = "";
+
+ if (cpp_opts->deps.style == DEPS_NONE)
+ check_deps_environment_vars ();
+
+ handle_deferred_opts ();
+
+ sanitize_cpp_opts ();
+
+ register_include_chains (parse_in, sysroot, iprefix, imultilib,
+ std_inc, std_cxx_inc && c_dialect_cxx (), verbose);
+
+#ifdef C_COMMON_OVERRIDE_OPTIONS
+ /* Some machines may reject certain combinations of C
+ language-specific options. */
+ C_COMMON_OVERRIDE_OPTIONS;
+#endif
+
+ /* Excess precision other than "fast" requires front-end
+ support. */
+ if (c_dialect_cxx ())
+ { untested();
+ if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
+ sorry ("%<-fexcess-precision=standard%> for C++");
+ flag_excess_precision = EXCESS_PRECISION_FAST;
+ }
+ else if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
+ flag_excess_precision = (flag_iso ? EXCESS_PRECISION_STANDARD
+ : EXCESS_PRECISION_FAST);
+
+ /* ISO C restricts floating-point expression contraction to within
+ source-language expressions (-ffp-contract=on, currently an alias
+ for -ffp-contract=off). */
+ if (flag_iso
+ && !c_dialect_cxx ()
+ && (OPTION_SET_P (flag_fp_contract_mode)
+ == (enum fp_contract_mode) 0)
+ && flag_unsafe_math_optimizations == 0)
+ flag_fp_contract_mode = FP_CONTRACT_OFF;
+
+ /* If we are compiling C, and we are outside of a standards mode,
+ we can permit the new values from ISO/IEC TS 18661-3 for
+ FLT_EVAL_METHOD. Otherwise, we must restrict the possible values to
+ the set specified in ISO C99/C11. */
+ if (!flag_iso
+ && !c_dialect_cxx ()
+ && (OPTION_SET_P (flag_permitted_flt_eval_methods)
+ == PERMITTED_FLT_EVAL_METHODS_DEFAULT))
+ flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_TS_18661;
+ else
+ flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
+
+ /* C2X Annex F does not permit certain built-in functions to raise
+ "inexact". */
+ if (flag_isoc2x)
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ flag_fp_int_builtin_inexact, 0);
+
+ /* By default we use C99 inline semantics in GNU99 or C99 mode. C99
+ inline semantics are not supported in GNU89 or C89 mode. */
+ if (flag_gnu89_inline == -1)
+ flag_gnu89_inline = !flag_isoc99;
+ else if (!flag_gnu89_inline && !flag_isoc99)
+ error ("%<-fno-gnu89-inline%> is only supported in GNU99 or C99 mode");
+
+ /* Default to ObjC sjlj exception handling if NeXT runtime < v2. */
+ if (flag_objc_sjlj_exceptions < 0)
+ flag_objc_sjlj_exceptions = (flag_next_runtime && flag_objc_abi < 2);
+ if (flag_objc_exceptions && !flag_objc_sjlj_exceptions)
+ flag_exceptions = 1;
+
+ /* If -ffreestanding, -fno-hosted or -fno-builtin then disable
+ pattern recognition. */
+ if (flag_no_builtin)
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ flag_tree_loop_distribute_patterns, 0);
+
+ /* -Woverlength-strings is off by default, but is enabled by -Wpedantic.
+ It is never enabled in C++, as the minimum limit is not normative
+ in that standard. */
+ if (c_dialect_cxx ())
+ warn_overlength_strings = 0;
+
+ /* Wmain is enabled by default in C++ but not in C. */
+ /* Wmain is disabled by default for -ffreestanding (!flag_hosted),
+ even if -Wall or -Wpedantic was given (warn_main will be 2 if set
+ by -Wall, 1 if set by -Wmain). */
+ if (warn_main == -1)
+ warn_main = (c_dialect_cxx () && flag_hosted) ? 1 : 0;
+ else if (warn_main == 2)
+ warn_main = flag_hosted ? 1 : 0;
+
+ /* In C, -Wall and -Wc++-compat enable -Wenum-compare; if it has not
+ yet been set, it is disabled by default. In C++, it is enabled
+ by default. */
+ if (warn_enum_compare == -1)
+ warn_enum_compare = c_dialect_cxx () ? 1 : 0;
+
+ /* -Wpacked-bitfield-compat is on by default for the C languages. The
+ warning is issued in stor-layout.cc which is not part of the front-end so
+ we need to selectively turn it on here. */
+ if (warn_packed_bitfield_compat == -1)
+ warn_packed_bitfield_compat = 1;
+
+ /* Special format checking options don't work without -Wformat; warn if
+ they are used. */
+ if (!warn_format)
+ {
+ warning (OPT_Wformat_y2k,
+ "%<-Wformat-y2k%> ignored without %<-Wformat%>");
+ warning (OPT_Wformat_extra_args,
+ "%<-Wformat-extra-args%> ignored without %<-Wformat%>");
+ warning (OPT_Wformat_zero_length,
+ "%<-Wformat-zero-length%> ignored without %<-Wformat%>");
+ warning (OPT_Wformat_nonliteral,
+ "%<-Wformat-nonliteral%> ignored without %<-Wformat%>");
+ warning (OPT_Wformat_contains_nul,
+ "%<-Wformat-contains-nul%> ignored without %<-Wformat%>");
+ warning (OPT_Wformat_security,
+ "%<-Wformat-security%> ignored without %<-Wformat%>");
+ }
+
+ /* -Wimplicit-function-declaration is enabled by default for C99. */
+ if (warn_implicit_function_declaration == -1)
+ warn_implicit_function_declaration = flag_isoc99;
+
+ /* -Wimplicit-int is enabled by default for C99. */
+ if (warn_implicit_int == -1)
+ warn_implicit_int = flag_isoc99;
+
+ /* -Wold-style-definition is enabled by default for C2X. */
+ if (warn_old_style_definition == -1)
+ warn_old_style_definition = flag_isoc2x;
+
+ /* -Wshift-overflow is enabled by default in C99 and C++11 modes. */
+ if (warn_shift_overflow == -1)
+ warn_shift_overflow = cxx_dialect >= cxx11 || flag_isoc99;
+
+ /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 to C++17
+ modes. */
+ if (warn_shift_negative_value == -1)
+ warn_shift_negative_value = (extra_warnings
+ && (cxx_dialect >= cxx11 || flag_isoc99)
+ && cxx_dialect < cxx20);
+
+ /* -Wregister is enabled by default in C++17. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_register,
+ cxx_dialect >= cxx17);
+
+ /* -Wcomma-subscript is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_comma_subscript,
+ cxx_dialect >= cxx23
+ || (cxx_dialect == cxx20 && warn_deprecated));
+
+ /* -Wvolatile is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_volatile,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
+ /* -Wdeprecated-enum-enum-conversion is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_enum_enum_conv,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
+ /* -Wdeprecated-enum-float-conversion is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_enum_float_conv,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
+ /* Declone C++ 'structors if -Os. */
+ if (flag_declone_ctor_dtor == -1)
+ flag_declone_ctor_dtor = optimize_size;
+
+ if (flag_abi_compat_version == 1)
+ {
+ warning (0, "%<-fabi-compat-version=1%> is not supported, using =2");
+ flag_abi_compat_version = 2;
+ }
+
+ /* Change flag_abi_version to be the actual current ABI level, for the
+ benefit of c_cpp_builtins, and to make comparison simpler. */
+ const int latest_abi_version = 17;
+ /* Generate compatibility aliases for ABI v13 (8.2) by default. */
+ const int abi_compat_default = 13;
+
+#define clamp(X) if (X == 0 || X > latest_abi_version) X = latest_abi_version
+ clamp (flag_abi_version);
+ clamp (warn_abi_version);
+ clamp (flag_abi_compat_version);
+#undef clamp
+
+ /* Default -Wabi= or -fabi-compat-version= from each other. */
+ if (warn_abi_version == -1 && flag_abi_compat_version != -1)
+ warn_abi_version = flag_abi_compat_version;
+ else if (flag_abi_compat_version == -1 && warn_abi_version != -1)
+ flag_abi_compat_version = warn_abi_version;
+ else if (warn_abi_version == -1 && flag_abi_compat_version == -1)
+ {
+ warn_abi_version = latest_abi_version;
+ if (flag_abi_version == latest_abi_version)
+ {
+ auto_diagnostic_group d;
+ if (warning (OPT_Wabi, "%<-Wabi%> won%'t warn about anything"))
+ {
+ inform (input_location, "%<-Wabi%> warns about differences "
+ "from the most up-to-date ABI, which is also used "
+ "by default");
+ inform (input_location, "use e.g. %<-Wabi=11%> to warn about "
+ "changes from GCC 7");
+ }
+ flag_abi_compat_version = abi_compat_default;
+ }
+ else
+ flag_abi_compat_version = latest_abi_version;
+ }
+
+ /* By default, enable the new inheriting constructor semantics along with ABI
+ 11. New and old should coexist fine, but it is a change in what
+ artificial symbols are generated. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ flag_new_inheriting_ctors,
+ abi_version_at_least (11));
+
+ /* For GCC 7, only enable DR150 resolution by default if -std=c++17. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_new_ttp,
+ cxx_dialect >= cxx17);
+
+ /* C++11 guarantees forward progress. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_finite_loops,
+ optimize >= 2 && cxx_dialect >= cxx11);
+
+ /* It's OK to discard calls to pure/const functions that might throw. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ flag_delete_dead_exceptions, true);
+
+ if (cxx_dialect >= cxx11)
+ {
+ /* If we're allowing C++0x constructs, don't warn about C++98
+ identifiers which are keywords in C++0x. */
+ warn_cxx11_compat = 0;
+ cpp_opts->cpp_warn_cxx11_compat = 0;
+
+ if (warn_narrowing == -1)
+ warn_narrowing = 1;
+
+ /* Unless -f{,no-}ext-numeric-literals has been used explicitly,
+ for -std=c++{11,14,17,20,23} default to -fno-ext-numeric-literals. */
+ if (flag_iso && !OPTION_SET_P (flag_ext_numeric_literals))
+ cpp_opts->ext_numeric_literals = 0;
+ }
+ else if (warn_narrowing == -1)
+ warn_narrowing = 0;
+
+ /* C++17 has stricter evaluation order requirements; let's use some of them
+ for earlier C++ as well, so chaining works as expected. */
+ if (c_dialect_cxx ()
+ && flag_strong_eval_order == -1)
+ flag_strong_eval_order = (cxx_dialect >= cxx17 ? 2 : 1);
+
+ if (flag_implicit_constexpr && cxx_dialect < cxx14)
+ flag_implicit_constexpr = false;
+
+ /* Global sized deallocation is new in C++14. */
+ if (flag_sized_deallocation == -1)
+ flag_sized_deallocation = (cxx_dialect >= cxx14);
+
+ /* char8_t support is new in C++20. */
+ if (flag_char8_t == -1)
+ flag_char8_t = (cxx_dialect >= cxx20);
+
+ if (flag_extern_tls_init)
+ {
+ if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK)
+ {
+ /* Lazy TLS initialization for a variable in another TU requires
+ alias and weak reference support. */
+ if (flag_extern_tls_init > 0)
+ sorry ("external TLS initialization functions not supported "
+ "on this target");
+
+ flag_extern_tls_init = 0;
+ }
+ else
+ flag_extern_tls_init = 1;
+ }
+
+ /* Enable by default only for C++ and C++ with ObjC extensions. */
+ if (warn_return_type == -1 && c_dialect_cxx ())
+ warn_return_type = 1;
+
+ /* C++20 is the final version of concepts. We still use -fconcepts
+ to know when concepts are enabled. Note that -fconcepts-ts can
+ be used to include additional features, although modified to
+ work with the standard. */
+ if (cxx_dialect >= cxx20 || flag_concepts_ts)
+ flag_concepts = 1;
+ else if (flag_concepts)
+ /* For -std=c++17 -fconcepts, imply -fconcepts-ts. */
+ flag_concepts_ts = 1;
+
+ if (num_in_fnames > 1)
+ error ("too many filenames given; type %<%s %s%> for usage",
+ progname, "--help");
+
+ if (flag_preprocess_only)
+ {
+ /* Open the output now. We must do so even if flag_no_output is
+ on, because there may be other output than from the actual
+ preprocessing (e.g. from -dM). */
+ if (out_fname[0] == '\0')
+ out_stream = stdout;
+ else
+ out_stream = fopen (out_fname, "w");
+
+ if (out_stream == NULL)
+ fatal_error (input_location, "opening output file %s: %m", out_fname);
+
+ init_pp_output (out_stream);
+ }
+ else
+ { untested();
+#if 0 // sdcpp
+ init_c_lex ();
+
+ /* When writing a PCH file, avoid reading some other PCH file,
+ because the default address space slot then can't be used
+ for the output PCH file. */
+ if (pch_file)
+ { untested();
+ c_common_no_more_pch ();
+ /* Only -g0 and -gdwarf* are supported with PCH, for other
+ debug formats we warn here and refuse to load any PCH files. */
+ if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
+ warning (OPT_Wdeprecated,
+ "the %qs debug info cannot be used with "
+ "pre-compiled headers",
+ debug_set_names (write_symbols & ~DWARF2_DEBUG));
+ }
+ else if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
+ c_common_no_more_pch ();
+
+ /* Yuk. WTF is this? I do know ObjC relies on it somewhere. */
+ input_location = UNKNOWN_LOCATION;
+#endif // sdcpp
+ }
+
+ struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
+ cb->file_change = cb_file_change;
+ cb->dir_change = cb_dir_change;
+ if (lang_hooks.preprocess_options)
+ lang_hooks.preprocess_options (parse_in);
+ cpp_post_options (parse_in);
+ init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in));
+
+ /* Let diagnostics infrastructure know how to convert input files the same
+ way libcpp will do it, namely using the configured input charset and
+ skipping a UTF-8 BOM if present. */
+ diagnostic_initialize_input_context (global_dc,
+ c_common_input_charset_cb, true);
+ input_location = UNKNOWN_LOCATION;
+
+ *pfilename = this_input_filename
+ = cpp_read_main_file (parse_in, in_fnames[0],
+ /* We'll inject preamble pieces if this is
+ not preprocessed. */
+ !cpp_opts->preprocessed);
+
+ /* Don't do any compilation or preprocessing if there is no input file. */
+ if (this_input_filename == NULL)
+ { untested();
+ errorcount++;
+ return false;
+ }
+
+ if (flag_working_directory
+ && flag_preprocess_only && !flag_no_line_commands)
+ pp_dir_change (parse_in, get_src_pwd ());
+
+ /* Disable LTO output when outputting a precompiled header. */
+ if (pch_file && flag_lto)
+ { untested();
+ flag_lto = 0;
+ flag_generate_lto = 0;
+ }
+
+ return flag_preprocess_only;
+}
+
+/* Front end initialization common to C, ObjC and C++. */
+// looks like sdcpp_common_init
+bool
+c_common_init (void)
+{
+ /* Set up preprocessor arithmetic. Must be done after call to
+ c_common_nodes_and_builtins for type nodes to be good. */
+
+#if 1 // sdcpp
+ cpp_opts->precision = CHAR_BIT * sizeof (long);
+ cpp_opts->char_precision = CHAR_BIT;
+ cpp_opts->int_precision = CHAR_BIT * sizeof (int);
+ cpp_opts->wchar_precision = CHAR_BIT * sizeof (int);
+ cpp_opts->unsigned_wchar = 1;
+#else // gcc
+ cpp_opts->precision = TYPE_PRECISION (intmax_type_node);
+ cpp_opts->char_precision = TYPE_PRECISION (char_type_node);
+ cpp_opts->int_precision = TYPE_PRECISION (integer_type_node);
+ cpp_opts->wchar_precision = TYPE_PRECISION (wchar_type_node);
+ cpp_opts->unsigned_wchar = TYPE_UNSIGNED (wchar_type_node);
+#endif
+ cpp_opts->bytes_big_endian = BYTES_BIG_ENDIAN;
+
+ /* This can't happen until after wchar_precision and bytes_big_endian
+ are known. */
+ cpp_init_iconv (parse_in);
+
+ if (version_flag)
+ {
+ int i;
+ fputs ("Compiler executable checksum: ", stderr);
+ for (i = 0; i < 16; i++)
+ fprintf (stderr, "%02x", executable_checksum[i]);
+ putc ('\n', stderr);
+ }
+
+ /* Has to wait until now so that cpplib has its hash table. */
+ init_pragma ();
+
+ gcc_assert (flag_preprocess_only);
+ if (flag_preprocess_only)
+ {
+ c_finish_options ();
+ preprocess_file (parse_in);
+ return false;
+ }
+
+ return true;
+}
+
+/* Initialize the integrated preprocessor after debug output has been
+ initialized; loop over each input file. */
+void
+c_common_parse_file (void)
+{
+ unsigned int i;
+
+ i = 0;
+ for (;;)
+ {
+ c_finish_options ();
+ /* Open the dump file to use for the original dump output
+ here, to be used during parsing for the current file. */
+ original_dump_file = dump_begin (TDI_original, &original_dump_flags);
+ pch_init ();
+ push_file_scope ();
+ c_parse_file ();
+ pop_file_scope ();
+ /* And end the main input file, if the debug writer wants it */
+ if (debug_hooks->start_end_main_source_file)
+ (*debug_hooks->end_source_file) (0);
+ if (++i >= num_in_fnames)
+ break;
+ cpp_undef_all (parse_in);
+ cpp_clear_file_cache (parse_in);
+ this_input_filename
+ = cpp_read_main_file (parse_in, in_fnames[i]);
+ if (original_dump_file)
+ {
+ dump_end (TDI_original, original_dump_file);
+ original_dump_file = NULL;
+ }
+ /* If an input file is missing, abandon further compilation.
+ cpplib has issued a diagnostic. */
+ if (!this_input_filename)
+ break;
+ }
+
+ c_parse_final_cleanups ();
+}
+
+/* Returns the appropriate dump file for PHASE to dump with FLAGS. */
+
+FILE *
+get_dump_info (int phase, dump_flags_t *flags)
+{
+ gcc_assert (phase == TDI_original);
+
+ *flags = original_dump_flags;
+ return original_dump_file;
+}
+
+/* Common finish hook for the C, ObjC and C++ front ends. */
+void
+c_common_finish (void)
+{
+ FILE *deps_stream = NULL;
+
+ /* Note that we write the dependencies even if there are errors. This is
+ useful for handling outdated generated headers that now trigger errors
+ (for example, with #error) which would be resolved by re-generating
+ them. In a sense, this complements -MG. */
+ if (cpp_opts->deps.style != DEPS_NONE)
+ {
+ /* If -M or -MM was seen without -MF, default output to the
+ output stream. */
+ if (!deps_file)
+ deps_stream = out_stream;
+ else if (deps_file[0] == '-' && deps_file[1] == '\0')
+ deps_stream = stdout;
+ else
+ {
+ deps_stream = fopen (deps_file, deps_append ? "a": "w");
+ if (!deps_stream)
+ fatal_error (input_location, "opening dependency file %s: %m",
+ deps_file);
+ }
+ }
+
+ /* For performance, avoid tearing down cpplib's internal structures
+ with cpp_destroy (). */
+ cpp_finish (parse_in, deps_stream);
+
+ if (deps_stream && deps_stream != out_stream && deps_stream != stdout
+ && (ferror (deps_stream) || fclose (deps_stream)))
+ fatal_error (input_location, "closing dependency file %s: %m", deps_file);
+
+ if (out_stream && (ferror (out_stream) || fclose (out_stream)))
+ fatal_error (input_location, "when writing output to %s: %m", out_fname);
+}
+
+/* Either of two environment variables can specify output of
+ dependencies. Their value is either "OUTPUT_FILE" or "OUTPUT_FILE
+ DEPS_TARGET", where OUTPUT_FILE is the file to write deps info to
+ and DEPS_TARGET is the target to mention in the deps. They also
+ result in dependency information being appended to the output file
+ rather than overwriting it, and like Sun's compiler
+ SUNPRO_DEPENDENCIES suppresses the dependency on the main file. */
+static void
+check_deps_environment_vars (void)
+{
+ char *spec;
+
+ spec = getenv ("DEPENDENCIES_OUTPUT");
+ if (spec)
+ cpp_opts->deps.style = DEPS_USER;
+ else
+ {
+ spec = getenv ("SUNPRO_DEPENDENCIES");
+ if (spec)
+ {
+ cpp_opts->deps.style = DEPS_SYSTEM;
+ cpp_opts->deps.ignore_main_file = true;
+ }
+ }
+
+ if (spec)
+ {
+ /* Find the space before the DEPS_TARGET, if there is one. */
+ char *s = strchr (spec, ' ');
+ if (s)
+ {
+ /* Let the caller perform MAKE quoting. */
+ defer_opt (OPT_MT, s + 1);
+ *s = '\0';
+ }
+
+ /* Command line -MF overrides environment variables and default. */
+ if (!deps_file)
+ deps_file = spec;
+
+ deps_append = 1;
+ deps_seen = true;
+ }
+}
+
+/* Handle deferred command line switches. */
+static void
+handle_deferred_opts (void)
+{
+ /* Avoid allocating the deps buffer if we don't need it.
+ (This flag may be true without there having been -MT or -MQ
+ options, but we'll still need the deps buffer.) */
+ if (!deps_seen)
+ return;
+
+ if (mkdeps *deps = cpp_get_deps (parse_in))
+ for (unsigned i = 0; i < deferred_count; i++)
+ {
+ struct deferred_opt *opt = &deferred_opts[i];
+
+ if (opt->code == OPT_MT || opt->code == OPT_MQ)
+ deps_add_target (deps, opt->arg, opt->code == OPT_MQ);
+ }
+}
+
+/* These settings are appropriate for GCC, but not necessarily so for
+ cpplib as a library. */
+static void
+sanitize_cpp_opts (void)
+{
+ /* If we don't know what style of dependencies to output, complain
+ if any other dependency switches have been given. */
+ if (deps_seen && cpp_opts->deps.style == DEPS_NONE)
+ error ("to generate dependencies you must specify either %<-M%> "
+ "or %<-MM%>");
+
+ /* -dM and dependencies suppress normal output; do it here so that
+ the last -d[MDN] switch overrides earlier ones. */
+ if (flag_dump_macros == 'M')
+ flag_no_output = 1;
+
+ /* By default, -fdirectives-only implies -dD. This allows subsequent phases
+ to perform proper macro expansion. */
+ if (cpp_opts->directives_only && !cpp_opts->preprocessed && !flag_dump_macros)
+ flag_dump_macros = 'D';
+
+ /* Disable -dD, -dN and -dI if normal output is suppressed. Allow
+ -dM since at least glibc relies on -M -dM to work. */
+ /* Also, flag_no_output implies flag_no_line_commands, always. */
+ if (flag_no_output)
+ {
+ if (flag_dump_macros != 'M')
+ flag_dump_macros = 0;
+ flag_dump_includes = 0;
+ flag_no_line_commands = 1;
+ }
+ else if (cpp_opts->deps.missing_files)
+ error ("%<-MG%> may only be used with %<-M%> or %<-MM%>");
+
+ cpp_opts->unsigned_char = !flag_signed_char;
+ cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
+
+ /* Wlong-long is disabled by default. It is enabled by:
+ [-Wpedantic | -Wtraditional] -std=[gnu|c]++98 ; or
+ [-Wpedantic | -Wtraditional] -std=non-c99
+
+ Either -Wlong-long or -Wno-long-long override any other settings.
+ ??? These conditions should be handled in c.opt. */
+ if (warn_long_long == -1)
+ {
+ warn_long_long = ((pedantic || warn_traditional)
+ && (c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99));
+ cpp_opts->cpp_warn_long_long = warn_long_long;
+ }
+
+ /* If we're generating preprocessor output, emit current directory
+ if explicitly requested or if debugging information is enabled.
+ ??? Maybe we should only do it for debugging formats that
+ actually output the current directory? */
+ if (flag_working_directory == -1)
+ flag_working_directory = (debug_info_level != DINFO_LEVEL_NONE);
+
+ if (warn_implicit_fallthrough < 5)
+ cpp_opts->cpp_warn_implicit_fallthrough = warn_implicit_fallthrough;
+ else
+ cpp_opts->cpp_warn_implicit_fallthrough = 0;
+
+ if (cpp_opts->directives_only)
+ {
+ if (cpp_warn_unused_macros)
+ error ("%<-fdirectives-only%> is incompatible "
+ "with %<-Wunused-macros%>");
+ if (cpp_opts->traditional)
+ error ("%<-fdirectives-only%> is incompatible with %<-traditional%>");
+ }
+}
+
+/* Add include path with a prefix at the front of its name. */
+static void
+add_prefixed_path (const char *suffix, incpath_kind chain)
+{
+ char *path;
+ const char *prefix;
+ size_t prefix_len, suffix_len;
+
+ suffix_len = strlen (suffix);
+ prefix = iprefix ? iprefix : cpp_GCC_INCLUDE_DIR;
+ prefix_len = iprefix ? strlen (iprefix) : cpp_GCC_INCLUDE_DIR_len;
+
+ path = (char *) xmalloc (prefix_len + suffix_len + 1);
+ memcpy (path, prefix, prefix_len);
+ memcpy (path + prefix_len, suffix, suffix_len);
+ path[prefix_len + suffix_len] = '\0';
+
+ add_path (path, chain, 0, false);
+}
+
+/* Handle -D, -U, -A, -imacros, and the first -include. */
+static void
+c_finish_options (void)
+{
+ if (!cpp_opts->preprocessed)
+ {
+ const line_map_ordinary *bltin_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_RENAME, 0,
+ _("<built-in>"), 0));
+ cb_file_change (parse_in, bltin_map);
+ linemap_line_start (line_table, 0, 1);
+
+ /* Make sure all of the builtins about to be declared have
+ BUILTINS_LOCATION has their location_t. */
+ cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
+
+ cpp_init_builtins (parse_in, flag_hosted);
+ // sdcpp c_cpp_builtins (parse_in);
+
+ /* We're about to send user input to cpplib, so make it warn for
+ things that we previously (when we sent it internal definitions)
+ told it to not warn.
+
+ C99 permits implementation-defined characters in identifiers.
+ The documented meaning of -std= is to turn off extensions that
+ conflict with the specified standard, and since a strictly
+ conforming program cannot contain a '$', we do not condition
+ their acceptance on the -std= setting. */
+ cpp_opts->warn_dollars = (cpp_opts->cpp_pedantic && !cpp_opts->c99);
+
+ const line_map_ordinary *cmd_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_RENAME, 0,
+ _("<command-line>"), 0));
+ cb_file_change (parse_in, cmd_map);
+ linemap_line_start (line_table, 0, 1);
+
+ /* All command line defines must have the same location. */
+ cpp_force_token_locations (parse_in, line_table->highest_line);
+ for (size_t i = 0; i < deferred_count; i++)
+ {
+ struct deferred_opt *opt = &deferred_opts[i];
+
+ if (opt->code == OPT_D)
+ cpp_define (parse_in, opt->arg);
+ else if (opt->code == OPT_U)
+ cpp_undef (parse_in, opt->arg);
+ else if (opt->code == OPT_A)
+ {
+ if (opt->arg[0] == '-')
+ cpp_unassert (parse_in, opt->arg + 1);
+ else
+ cpp_assert (parse_in, opt->arg);
+ }
+ }
+
+ cpp_stop_forcing_token_locations (parse_in);
+ }
+ else if (cpp_opts->directives_only)
+ cpp_init_special_builtins (parse_in);
+
+ /* Start the main input file, if the debug writer wants it. */
+ if (debug_hooks->start_end_main_source_file
+ && !flag_preprocess_only)
+ (*debug_hooks->start_source_file) (0, this_input_filename);
+
+ if (!cpp_opts->preprocessed)
+ /* Handle -imacros after -D and -U. */
+ for (size_t i = 0; i < deferred_count; i++)
+ {
+ struct deferred_opt *opt = &deferred_opts[i];
+
+ if (opt->code == OPT_imacros
+ && cpp_push_include (parse_in, opt->arg))
+ {
+ /* Disable push_command_line_include callback for now. */
+ include_cursor = deferred_count + 1;
+ cpp_scan_nooutput (parse_in);
+ }
+ }
+
+ include_cursor = 0;
+ push_command_line_include ();
+}
+
+/* Give CPP the next file given by -include, if any. */
+static void
+push_command_line_include (void)
+{
+ /* This can happen if disabled by -imacros for example.
+ Punt so that we don't set "<command-line>" as the filename for
+ the header. */
+ if (include_cursor > deferred_count)
+ return;
+
+ if (!done_preinclude)
+ {
+ done_preinclude = true;
+ if (flag_hosted && std_inc && !cpp_opts->preprocessed)
+ {
+ const char *preinc = 0; // sdcpp targetcm.c_preinclude ();
+ if (preinc && cpp_push_default_include (parse_in, preinc))
+ return;
+ }
+ }
+
+ pch_cpp_save_state ();
+
+ while (include_cursor < deferred_count)
+ {
+ struct deferred_opt *opt = &deferred_opts[include_cursor++];
+
+ if (!cpp_opts->preprocessed && opt->code == OPT_include
+ && cpp_push_include (parse_in, opt->arg))
+ return;
+ }
+
+ if (include_cursor == deferred_count)
+ {
+ include_cursor++;
+ /* -Wunused-macros should only warn about macros defined hereafter. */
+ cpp_opts->warn_unused_macros = cpp_warn_unused_macros;
+ /* Restore the line map back to the main file. */
+ if (!cpp_opts->preprocessed)
+ {
+ cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+ if (lang_hooks.preprocess_main_file)
+ /* We're starting the main file. Inform the FE of that. */
+ lang_hooks.preprocess_main_file
+ (parse_in, line_table, LINEMAPS_LAST_ORDINARY_MAP (line_table));
+ }
+
+ /* Set this here so the client can change the option if it wishes,
+ and after stacking the main file so we don't trace the main file. */
+ line_table->trace_includes = cpp_opts->print_include_names;
+ }
+}
+
+/* File change callback. Has to handle -include files. */
+static void
+cb_file_change (cpp_reader *reader, const line_map_ordinary *new_map)
+{
+ if (flag_preprocess_only)
+ pp_file_change (new_map);
+ else
+ fe_file_change (new_map);
+
+ if (new_map && cpp_opts->preprocessed
+ && lang_hooks.preprocess_main_file && MAIN_FILE_P (new_map)
+ && ORDINARY_MAP_STARTING_LINE_NUMBER (new_map))
+ /* We're starting the main file. Inform the FE of that. */
+ lang_hooks.preprocess_main_file (reader, line_table, new_map);
+
+ if (new_map
+ && (new_map->reason == LC_ENTER || new_map->reason == LC_RENAME))
+ {
+ /* Signal to plugins that a file is included. This could happen
+ several times with the same file path, e.g. because of
+ several '#include' or '#line' directives... */
+ invoke_plugin_callbacks
+ (PLUGIN_INCLUDE_FILE,
+ const_cast<char*> (ORDINARY_MAP_FILE_NAME (new_map)));
+ }
+
+ if (new_map == 0 || (new_map->reason == LC_LEAVE && MAIN_FILE_P (new_map)))
+ {
+ pch_cpp_save_state ();
+ push_command_line_include ();
+ }
+}
+
+void
+cb_dir_change (cpp_reader * ARG_UNUSED (pfile), const char *dir)
+{
+ if (!set_src_pwd (dir))
+ warning (0, "too late for # directive to set debug directory");
+}
+
+/* Set the C 89 standard (with 1994 amendments if C94, without GNU
+ extensions if ISO). There is no concept of gnu94. */
+static void
+set_std_c89 (int c94, int iso)
+{
+ cpp_set_lang (parse_in, c94 ? CLK_STDC94: iso ? CLK_STDC89: CLK_GNUC89);
+ flag_iso = iso;
+ flag_no_asm = iso;
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_isoc94 = c94;
+ flag_isoc99 = 0;
+ flag_isoc11 = 0;
+ flag_isoc2x = 0;
+ lang_hooks.name = "GNU C89";
+}
+
+/* Set the C 99 standard (without GNU extensions if ISO). */
+static void
+set_std_c99 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_STDC99: CLK_GNUC99);
+ flag_no_asm = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ flag_isoc2x = 0;
+ flag_isoc11 = 0;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
+ lang_hooks.name = "GNU C99";
+}
+
+/* Set the C 11 standard (without GNU extensions if ISO). */
+static void
+set_std_c11 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_STDC11: CLK_GNUC11);
+ flag_no_asm = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ flag_isoc2x = 0;
+ flag_isoc11 = 1;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
+ lang_hooks.name = "GNU C11";
+}
+
+/* Set the C 17 standard (without GNU extensions if ISO). */
+static void
+set_std_c17 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_STDC17: CLK_GNUC17);
+ flag_no_asm = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ flag_isoc2x = 0;
+ flag_isoc11 = 1;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
+ lang_hooks.name = "GNU C17";
+}
+
+/* Set the C 2X standard (without GNU extensions if ISO). */
+static void
+set_std_c2x (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_STDC2X: CLK_GNUC2X);
+ flag_no_asm = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ flag_isoc2x = 1;
+ flag_isoc11 = 1;
+ flag_isoc99 = 1;
+ flag_isoc94 = 1;
+ lang_hooks.name = "GNU C2X";
+}
+
+
+/* Set the C++ 98 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx98 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX98: CLK_GNUCXX);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ flag_isoc94 = 0;
+ flag_isoc99 = 0;
+ cxx_dialect = cxx98;
+ lang_hooks.name = "GNU C++98";
+}
+
+/* Set the C++ 2011 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx11 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX11: CLK_GNUCXX11);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ /* C++11 includes the C99 standard library. */
+ flag_isoc94 = 1;
+ flag_isoc99 = 1;
+ cxx_dialect = cxx11;
+ lang_hooks.name = "GNU C++11";
+}
+
+/* Set the C++ 2014 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx14 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX14: CLK_GNUCXX14);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ /* C++14 includes the C99 standard library. */
+ flag_isoc94 = 1;
+ flag_isoc99 = 1;
+ cxx_dialect = cxx14;
+ lang_hooks.name = "GNU C++14";
+}
+
+/* Set the C++ 2017 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx17 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX17: CLK_GNUCXX17);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ /* C++17 includes the C11 standard library. */
+ flag_isoc94 = 1;
+ flag_isoc99 = 1;
+ flag_isoc11 = 1;
+ cxx_dialect = cxx17;
+ lang_hooks.name = "GNU C++17";
+}
+
+/* Set the C++ 2020 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx20 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX20: CLK_GNUCXX20);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ /* C++20 includes the C11 standard library. */
+ flag_isoc94 = 1;
+ flag_isoc99 = 1;
+ flag_isoc11 = 1;
+ /* C++20 includes coroutines. */
+ flag_coroutines = true;
+ cxx_dialect = cxx20;
+ lang_hooks.name = "GNU C++20";
+}
+
+/* Set the C++ 2023 standard (without GNU extensions if ISO). */
+static void
+set_std_cxx23 (int iso)
+{
+ cpp_set_lang (parse_in, iso ? CLK_CXX23: CLK_GNUCXX23);
+ flag_no_gnu_keywords = iso;
+ flag_no_nonansi_builtin = iso;
+ flag_iso = iso;
+ /* C++23 includes the C11 standard library. */
+ flag_isoc94 = 1;
+ flag_isoc99 = 1;
+ flag_isoc11 = 1;
+ /* C++23 includes coroutines. */
+ flag_coroutines = true;
+ cxx_dialect = cxx23;
+ lang_hooks.name = "GNU C++23";
+}
+
+/* Args to -d specify what to dump. Silently ignore
+ unrecognized options; they may be aimed at toplev.cc. */
+static void
+handle_OPT_d (const char *arg)
+{
+ char c;
+
+ while ((c = *arg++) != '\0')
+ switch (c)
+ {
+ case 'M': /* Dump macros only. */
+ case 'N': /* Dump names. */
+ case 'D': /* Dump definitions. */
+ case 'U': /* Dump used macros. */
+ flag_dump_macros = c;
+ break;
+
+ case 'I':
+ flag_dump_includes = 1;
+ break;
+ }
+}
diff --git a/support/cpp/gcc/c-family/c-ppoutput.cc b/support/cpp/gcc/c-family/c-ppoutput.cc
new file mode 100644
index 000000000..bd1cd555a
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-ppoutput.cc
@@ -0,0 +1,843 @@
+/* Preprocess only, using cpplib.
+ Copyright (C) 1995-2022 Free Software Foundation, Inc.
+ Written by Per Bothner, 1994-95.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ \
+ <<":" << __func__ << "\n" )
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "c-common.h" /* For flags. */
+#include "../libcpp/internal.h"
+#include "langhooks.h"
+#include "c-pragma.h" /* For parse_in. */
+#include "file-prefix-map.h" /* remap_macro_filename() */
+
+/* Encapsulates state used to convert a stream of tokens into a text
+ file. */
+static struct
+{
+ FILE *outf; /* Stream to write to. */
+ const cpp_token *prev; /* Previous token. */
+ const cpp_token *source; /* Source token for spacing. */
+ unsigned src_line; /* Line number currently being written. */
+ bool printed; /* True if something output at line. */
+ bool first_time; /* pp_file_change hasn't been called yet. */
+ bool prev_was_system_token; /* True if the previous token was a
+ system token.*/
+ const char *src_file; /* Current source file. */
+} print;
+
+/* Defined and undefined macros being queued for output with -dU at
+ the next newline. */
+struct macro_queue
+{
+ struct macro_queue *next; /* Next macro in the list. */
+ char *macro; /* The name of the macro if not
+ defined, the full definition if
+ defined. */
+};
+static macro_queue *define_queue, *undef_queue;
+
+/* General output routines. */
+static void scan_translation_unit (cpp_reader *);
+static void scan_translation_unit_directives_only (cpp_reader *);
+static void scan_translation_unit_trad (cpp_reader *);
+static void account_for_newlines (const unsigned char *, size_t);
+static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
+static void dump_queued_macros (cpp_reader *);
+
+static bool print_line_1 (location_t, const char*, FILE *);
+static bool print_line (location_t, const char *);
+static bool maybe_print_line_1 (location_t, FILE *);
+static bool maybe_print_line (location_t);
+static bool do_line_change (cpp_reader *, const cpp_token *,
+ location_t, int);
+
+/* Callback routines for the parser. Most of these are active only
+ in specific modes. */
+static void cb_line_change (cpp_reader *, const cpp_token *, int);
+static void cb_define (cpp_reader *, location_t, cpp_hashnode *);
+static void cb_undef (cpp_reader *, location_t, cpp_hashnode *);
+static void cb_used_define (cpp_reader *, location_t, cpp_hashnode *);
+static void cb_used_undef (cpp_reader *, location_t, cpp_hashnode *);
+static void cb_include (cpp_reader *, location_t, const unsigned char *,
+ const char *, int, const cpp_token **);
+static void cb_ident (cpp_reader *, location_t, const cpp_string *);
+static void cb_def_pragma (cpp_reader *, location_t);
+static void cb_read_pch (cpp_reader *pfile, const char *name,
+ int fd, const char *orig_name);
+
+/* Preprocess and output. */
+void
+preprocess_file (cpp_reader *pfile)
+{
+ /* A successful cpp_read_main_file guarantees that we can call
+ cpp_scan_nooutput or cpp_get_token next. */
+ if (flag_no_output && pfile->buffer)
+ {
+ /* Scan -included buffers, then the main file. */
+ while (pfile->buffer->prev)
+ cpp_scan_nooutput (pfile);
+ cpp_scan_nooutput (pfile);
+ }
+ else if (cpp_get_options (pfile)->traditional)
+ scan_translation_unit_trad (pfile);
+ else if (cpp_get_options (pfile)->directives_only
+ && !cpp_get_options (pfile)->preprocessed)
+ scan_translation_unit_directives_only (pfile);
+ else
+ scan_translation_unit (pfile);
+
+ /* -dM command line option. Should this be elsewhere? */
+ if (flag_dump_macros == 'M')
+ cpp_forall_identifiers (pfile, dump_macro, NULL);
+
+ /* Flush any pending output. */
+ if (print.printed)
+ putc ('\n', print.outf);
+}
+
+/* Set up the callbacks as appropriate. */
+void
+init_pp_output (FILE *out_stream)
+{
+ cpp_callbacks *cb = cpp_get_callbacks (parse_in);
+
+ if (!flag_no_output)
+ {
+ cb->line_change = cb_line_change;
+ /* Don't emit #pragma or #ident directives if we are processing
+ assembly language; the assembler may choke on them. */
+ if (cpp_get_options (parse_in)->lang != CLK_ASM)
+ {
+ cb->ident = cb_ident;
+ cb->def_pragma = cb_def_pragma;
+ }
+ }
+
+ if (flag_dump_includes)
+ cb->include = cb_include;
+
+ if (flag_pch_preprocess)
+ {
+ cb->valid_pch = c_common_valid_pch;
+ cb->read_pch = cb_read_pch;
+ }
+
+ if (flag_dump_macros == 'N' || flag_dump_macros == 'D')
+ {
+ cb->define = cb_define;
+ cb->undef = cb_undef;
+ }
+
+ if (flag_dump_macros == 'U')
+ {
+ cb->before_define = dump_queued_macros;
+ cb->used_define = cb_used_define;
+ cb->used_undef = cb_used_undef;
+ }
+
+ cb->has_attribute = c_common_has_attribute;
+ cb->has_builtin = c_common_has_builtin;
+ cb->get_source_date_epoch = cb_get_source_date_epoch;
+ cb->remap_filename = remap_macro_filename;
+
+ /* Initialize the print structure. */
+ print.src_line = 1;
+ print.printed = false;
+ print.prev = 0;
+ print.outf = out_stream;
+ print.first_time = 1;
+ print.src_file = "";
+ print.prev_was_system_token = false;
+}
+
+// FIXME: Ideally we'd just turn the entirety of the print struct into
+// an encapsulated streamer ...
+
+class token_streamer
+{
+ bool avoid_paste;
+ bool do_line_adjustments;
+ bool in_pragma;
+ bool line_marker_emitted;
+
+ public:
+ token_streamer (cpp_reader *pfile)
+ :avoid_paste (false),
+ do_line_adjustments (cpp_get_options (pfile)->lang != CLK_ASM
+ && !flag_no_line_commands),
+ in_pragma (false),
+ line_marker_emitted (false)
+ {
+ }
+
+ void begin_pragma ()
+ {
+ in_pragma = true;
+ }
+
+ void stream (cpp_reader *pfile, const cpp_token *tok, location_t);
+};
+
+void
+token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
+ location_t loc)
+{
+ if (token->type == CPP_PADDING)
+ {
+ avoid_paste = true;
+ if (print.source == NULL
+ || (!(print.source->flags & PREV_WHITE)
+ && token->val.source == NULL))
+ print.source = token->val.source;
+ return;
+ }
+
+ if (token->type == CPP_EOF)
+ return;
+
+ /* Subtle logic to output a space if and only if necessary. */
+ if (avoid_paste)
+ {
+ unsigned src_line = LOCATION_LINE (loc);
+
+ if (print.source == NULL)
+ print.source = token;
+
+ if (src_line != print.src_line
+ && do_line_adjustments
+ && !in_pragma)
+ {
+ line_marker_emitted = do_line_change (pfile, token, loc, false);
+ putc (' ', print.outf);
+ print.printed = true;
+ }
+ else if (print.source->flags & PREV_WHITE
+ || (print.prev
+ && cpp_avoid_paste (pfile, print.prev, token))
+ || (print.prev == NULL && token->type == CPP_HASH))
+ {
+ putc (' ', print.outf);
+ print.printed = true;
+ }
+ }
+ else if (token->flags & PREV_WHITE)
+ {
+ unsigned src_line = LOCATION_LINE (loc);
+
+ if (src_line != print.src_line
+ && do_line_adjustments
+ && !in_pragma)
+ line_marker_emitted = do_line_change (pfile, token, loc, false);
+ putc (' ', print.outf);
+ print.printed = true;
+ }
+
+ avoid_paste = false;
+ print.source = NULL;
+ print.prev = token;
+ if (token->type == CPP_PRAGMA)
+ {
+ const char *space;
+ const char *name;
+
+ line_marker_emitted = maybe_print_line (token->src_loc);
+ fputs ("#pragma ", print.outf);
+ c_pp_lookup_pragma (token->val.pragma, &space, &name);
+ if (space)
+ fprintf (print.outf, "%s %s", space, name);
+ else
+ fprintf (print.outf, "%s", name);
+ print.printed = true;
+ in_pragma = true;
+ }
+ else if (token->type == CPP_PRAGMA_EOL)
+ {
+ maybe_print_line (UNKNOWN_LOCATION);
+ in_pragma = false;
+ }
+ else
+ {
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, token->src_loc, print.outf);
+
+ if (do_line_adjustments
+ && !in_pragma
+ && !line_marker_emitted
+ && print.prev_was_system_token != !!in_system_header_at (loc)
+ && !is_location_from_builtin_token (loc))
+ /* The system-ness of this token is different from the one of
+ the previous token. Let's emit a line change to mark the
+ new system-ness before we emit the token. */
+ {
+ do_line_change (pfile, token, loc, false);
+ print.prev_was_system_token = !!in_system_header_at (loc);
+ }
+ cpp_output_token (token, print.outf);
+ line_marker_emitted = false;
+ print.printed = true;
+ }
+
+ /* CPP_COMMENT tokens and raw-string literal tokens can have
+ embedded new-line characters. Rather than enumerating all the
+ possible token types just check if token uses val.str union
+ member. */
+ if (cpp_token_val_index (token) == CPP_TOKEN_FLD_STR)
+ account_for_newlines (token->val.str.text, token->val.str.len);
+}
+
+/* Writes out the preprocessed file, handling spacing and paste
+ avoidance issues. */
+
+// sdcpp hacked version
+bool in_asm(); // hacked in libcpp
+static void
+scan_translation_unit (cpp_reader *pfile)
+{
+ bool avoid_paste = false;
+
+ print.source = NULL;
+ for (;;)
+ {
+ const cpp_token *token = cpp_get_token (pfile);
+
+ if (token->type == CPP_PADDING)
+ {
+ avoid_paste = true;
+ if (print.source == NULL
+ || (!(print.source->flags & PREV_WHITE)
+ && token->val.source == NULL))
+ print.source = token->val.source;
+ continue;
+ }
+
+ if (token->type == CPP_EOF)
+ break;
+
+ /* Subtle logic to output a space if and only if necessary. */
+ if (avoid_paste)
+ {
+ if (print.source == NULL)
+ print.source = token;
+ if (print.source->flags & PREV_WHITE
+ || (print.prev
+ && cpp_avoid_paste (pfile, print.prev, token))
+ || (print.prev == NULL && token->type == CPP_HASH))
+ putc (' ', print.outf);
+ if (in_asm() && print.source->flags & PREV_NL)
+ fputs ("\x87 ", print.outf);
+ }
+ else
+ {
+ if (token->flags & PREV_WHITE)
+ putc (' ', print.outf);
+ if (in_asm() && token->flags & PREV_NL)
+ fputs ("\x87 ", print.outf);
+ }
+
+ avoid_paste = false;
+ print.source = NULL;
+ print.prev = token;
+ cpp_output_token (token, print.outf);
+
+ if (token->type == CPP_COMMENT)
+ account_for_newlines (token->val.str.text, token->val.str.len);
+ }
+}
+
+class do_streamer : public token_streamer
+{
+ public:
+ uintptr_t filter;
+
+ do_streamer (cpp_reader *pfile, uintptr_t filter)
+ :token_streamer (pfile), filter (filter)
+ {
+ }
+};
+
+static void
+directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
+{
+ va_list args;
+ va_start (args, data_);
+
+ do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
+ switch (task)
+ {
+ default:
+ gcc_unreachable ();
+
+ case CPP_DO_print:
+ {
+ print.src_line += va_arg (args, unsigned);
+
+ const void *buf = va_arg (args, const void *);
+ size_t size = va_arg (args, size_t);
+ fwrite (buf, 1, size, print.outf);
+ }
+ break;
+
+ case CPP_DO_location:
+ maybe_print_line (va_arg (args, location_t));
+ break;
+
+ case CPP_DO_token:
+ {
+ const cpp_token *token = va_arg (args, const cpp_token *);
+ location_t spelling_loc = va_arg (args, location_t);
+ streamer->stream (pfile, token, spelling_loc);
+ if (streamer->filter)
+ {
+ unsigned flags = lang_hooks.preprocess_token
+ (pfile, token, streamer->filter);
+ if (flags & lang_hooks::PT_begin_pragma)
+ streamer->begin_pragma ();
+ }
+ }
+ break;
+ }
+
+ va_end (args);
+}
+
+/* Writes out the preprocessed file, handling spacing and paste
+ avoidance issues. */
+static void
+scan_translation_unit_directives_only (cpp_reader *pfile)
+{
+ uintptr_t filter = 0;
+ if (lang_hooks.preprocess_token)
+ filter = lang_hooks.preprocess_token (pfile, NULL, filter);
+ do_streamer streamer (pfile, filter);
+ cpp_directive_only_process (pfile, &streamer, directives_only_cb);
+ if (streamer.filter)
+ lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
+}
+
+/* Adjust print.src_line for newlines embedded in output. */
+static void
+account_for_newlines (const unsigned char *str, size_t len)
+{
+ while (len--)
+ if (*str++ == '\n')
+ print.src_line++;
+}
+
+/* Writes out a traditionally preprocessed file. */
+static void
+scan_translation_unit_trad (cpp_reader *pfile)
+{ untested();
+ while (_cpp_read_logical_line_trad (pfile))
+ {
+ size_t len = pfile->out.cur - pfile->out.base;
+ maybe_print_line (pfile->out.first_line);
+ fwrite (pfile->out.base, 1, len, print.outf);
+ print.printed = true;
+ if (!CPP_OPTION (pfile, discard_comments))
+ account_for_newlines (pfile->out.base, len);
+ }
+}
+
+/* If the token read on logical line LINE needs to be output on a
+ different line to the current one, output the required newlines or
+ a line marker. If a line marker was emitted, return TRUE otherwise
+ return FALSE. */
+
+static bool
+maybe_print_line_1 (location_t src_loc, FILE *stream)
+{
+ bool emitted_line_marker = false;
+ unsigned src_line = LOCATION_LINE (src_loc);
+ const char *src_file = LOCATION_FILE (src_loc);
+
+ /* End the previous line of text. */
+ if (print.printed)
+ {
+ putc ('\n', stream);
+ print.src_line++;
+ print.printed = false;
+ }
+
+ if (!flag_no_line_commands
+ && src_line >= print.src_line
+ && src_line < print.src_line + 8
+ && src_loc != UNKNOWN_LOCATION
+ && strcmp (src_file, print.src_file) == 0)
+ {
+ while (src_line > print.src_line)
+ {
+ putc ('\n', stream);
+ print.src_line++;
+ }
+ }
+ else
+ emitted_line_marker = print_line_1 (src_loc, "", stream);
+
+ return emitted_line_marker;
+}
+
+/* If the token read on logical line LINE needs to be output on a
+ different line to the current one, output the required newlines or
+ a line marker. If a line marker was emitted, return TRUE otherwise
+ return FALSE. */
+
+static bool
+maybe_print_line (location_t src_loc)
+{
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, src_loc,
+ print.outf);
+ return maybe_print_line_1 (src_loc, print.outf);
+}
+
+/* Output a line marker for logical line LINE. Special flags are "1"
+ or "2" indicating entering or leaving a file. If the line marker
+ was effectively emitted, return TRUE otherwise return FALSE. */
+
+static bool
+print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
+{
+ bool emitted_line_marker = false;
+
+ /* End any previous line of text. */
+ if (print.printed)
+ putc ('\n', stream);
+ print.printed = false;
+
+ if (src_loc != UNKNOWN_LOCATION && !flag_no_line_commands)
+ {
+ const char *file_path = LOCATION_FILE (src_loc);
+ size_t to_file_len = strlen (file_path);
+ unsigned char *to_file_quoted =
+ (unsigned char *) alloca (to_file_len * 4 + 1);
+
+ /* cpp_quote_string does not nul-terminate, so we have to do it
+ ourselves. */
+ unsigned char *p = cpp_quote_string (to_file_quoted,
+ (const unsigned char *) file_path,
+ to_file_len);
+ *p = '\0';
+
+ print.src_line = LOCATION_LINE (src_loc);
+ print.src_file = file_path;
+
+ fprintf (stream, "#line %u \"%s\"%s",
+ print.src_line, to_file_quoted, special_flags);
+
+ int sysp = in_system_header_at (src_loc);
+ if (sysp == 2)
+ fputs (" 3 4", stream);
+ else if (sysp == 1)
+ fputs (" 3", stream);
+
+ putc ('\n', stream);
+ emitted_line_marker = true;
+ }
+
+ return emitted_line_marker;
+}
+
+/* Output a line marker for logical line LINE. Special flags are "1"
+ or "2" indicating entering or leaving a file. Return TRUE if a
+ line marker was effectively emitted, FALSE otherwise. */
+
+static bool
+print_line (location_t src_loc, const char *special_flags)
+{
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, src_loc,
+ print.outf);
+ return print_line_1 (src_loc, special_flags, print.outf);
+}
+
+/* Helper function for cb_line_change and scan_translation_unit.
+ Return TRUE if a line marker is emitted, FALSE otherwise. */
+static bool
+do_line_change (cpp_reader *pfile, const cpp_token *token,
+ location_t src_loc, int parsing_args)
+{
+ bool emitted_line_marker = false;
+ if (define_queue || undef_queue)
+ dump_queued_macros (pfile);
+
+ if (token->type == CPP_EOF || parsing_args)
+ return false;
+
+ emitted_line_marker = maybe_print_line (src_loc);
+ print.prev = 0;
+ print.source = 0;
+
+ /* Supply enough spaces to put this token in its original column,
+ one space per column greater than 2, since scan_translation_unit
+ will provide a space if PREV_WHITE. Don't bother trying to
+ reconstruct tabs; we can't get it right in general, and nothing
+ ought to care. Some things do care; the fault lies with them. */
+ if (!CPP_OPTION (pfile, traditional))
+ {
+ int spaces = LOCATION_COLUMN (src_loc) - 2;
+ print.printed = true;
+
+ while (-- spaces >= 0)
+ putc (' ', print.outf);
+ }
+
+ return emitted_line_marker;
+}
+
+/* Called when a line of output is started. TOKEN is the first token
+ of the line, and at end of file will be CPP_EOF. */
+static void
+cb_line_change (cpp_reader *pfile, const cpp_token *token,
+ int parsing_args)
+{
+ do_line_change (pfile, token, token->src_loc, parsing_args);
+}
+
+static void
+cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
+ const cpp_string *str)
+{
+ maybe_print_line (line);
+ fprintf (print.outf, "#ident %s\n", str->text);
+ print.src_line++;
+}
+
+static void
+cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
+{
+ const line_map_ordinary *map;
+
+ maybe_print_line (line);
+ fputs ("#define ", print.outf);
+
+ /* 'D' is whole definition; 'N' is name only. */
+ if (flag_dump_macros == 'D')
+ fputs ((const char *) cpp_macro_definition (pfile, node),
+ print.outf);
+ else
+ fputs ((const char *) NODE_NAME (node), print.outf);
+
+ putc ('\n', print.outf);
+ print.printed = false;
+ linemap_resolve_location (line_table, line,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+ print.src_line++;
+}
+
+static void
+cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
+{
+ if (lang_hooks.preprocess_undef)
+ lang_hooks.preprocess_undef (pfile, line, node);
+ maybe_print_line (line);
+ fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
+ print.src_line++;
+}
+
+static void
+cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
+ cpp_hashnode *node)
+{
+ if (cpp_user_macro_p (node))
+ {
+ macro_queue *q;
+ q = XNEW (macro_queue);
+ q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
+ q->next = define_queue;
+ define_queue = q;
+ }
+}
+
+static void
+cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED,
+ location_t line ATTRIBUTE_UNUSED,
+ cpp_hashnode *node)
+{
+ macro_queue *q;
+ q = XNEW (macro_queue);
+ q->macro = xstrdup ((const char *) NODE_NAME (node));
+ q->next = undef_queue;
+ undef_queue = q;
+}
+
+static void
+dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ macro_queue *q;
+
+ /* End the previous line of text. */
+ if (print.printed)
+ {
+ putc ('\n', print.outf);
+ print.src_line++;
+ print.printed = false;
+ }
+
+ for (q = define_queue; q;)
+ {
+ macro_queue *oq;
+ fputs ("#define ", print.outf);
+ fputs (q->macro, print.outf);
+ putc ('\n', print.outf);
+ print.printed = false;
+ print.src_line++;
+ oq = q;
+ q = q->next;
+ free (oq->macro);
+ free (oq);
+ }
+ define_queue = NULL;
+ for (q = undef_queue; q;)
+ {
+ macro_queue *oq;
+ fprintf (print.outf, "#undef %s\n", q->macro);
+ print.src_line++;
+ oq = q;
+ q = q->next;
+ free (oq->macro);
+ free (oq);
+ }
+ undef_queue = NULL;
+}
+
+static void
+cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
+ const unsigned char *dir, const char *header, int angle_brackets,
+ const cpp_token **comments)
+{
+ maybe_print_line (line);
+ if (angle_brackets)
+ fprintf (print.outf, "#%s <%s>", dir, header);
+ else
+ fprintf (print.outf, "#%s \"%s\"", dir, header);
+
+ if (comments != NULL)
+ {
+ while (*comments != NULL)
+ {
+ if ((*comments)->flags & PREV_WHITE)
+ putc (' ', print.outf);
+ cpp_output_token (*comments, print.outf);
+ ++comments;
+ }
+ }
+
+ putc ('\n', print.outf);
+ print.printed = false;
+ print.src_line++;
+}
+
+/* Callback called when -fworking-director and -E to emit working
+ directory in cpp output file. */
+
+void
+pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
+{
+ size_t to_file_len = strlen (dir);
+ unsigned char *to_file_quoted =
+ (unsigned char *) alloca (to_file_len * 4 + 1);
+ unsigned char *p;
+
+ /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
+ p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len);
+ *p = '\0';
+ fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted);
+}
+
+/* The file name, line number or system header flags have changed, as
+ described in MAP. */
+
+void
+pp_file_change (const line_map_ordinary *map)
+{
+ const char *flags = "";
+
+ if (flag_no_line_commands)
+ return;
+
+ if (map != NULL)
+ {
+ input_location = map->start_location;
+ if (print.first_time)
+ {
+ /* Avoid printing foo.i when the main file is foo.c. */
+ if (!cpp_get_options (parse_in)->preprocessed)
+ print_line (map->start_location, flags);
+ print.first_time = 0;
+ }
+ else
+ {
+ /* Bring current file to correct line when entering a new file. */
+ if (map->reason == LC_ENTER)
+ {
+ maybe_print_line (linemap_included_from (map));
+ flags = " 1";
+ }
+ else if (map->reason == LC_LEAVE)
+ flags = " 2";
+ print_line (map->start_location, flags);
+ }
+ }
+}
+
+/* Copy a #pragma directive to the preprocessed output. */
+static void
+cb_def_pragma (cpp_reader *pfile, location_t line)
+{
+ maybe_print_line (line);
+ fputs ("#pragma ", print.outf);
+ cpp_output_line (pfile, print.outf);
+ print.printed = false;
+ print.src_line++;
+}
+
+/* Dump out the hash table. */
+static int
+dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
+{
+ if (cpp_user_macro_p (node))
+ {
+ fputs ("#define ", print.outf);
+ fputs ((const char *) cpp_macro_definition (pfile, node),
+ print.outf);
+ putc ('\n', print.outf);
+ print.printed = false;
+ print.src_line++;
+ }
+
+ return 1;
+}
+
+/* Load in the PCH file NAME, open on FD. It was originally searched for
+ by ORIG_NAME. Also, print out a #include command so that the PCH
+ file can be loaded when the preprocessed output is compiled. */
+
+static void
+cb_read_pch (cpp_reader *pfile, const char *name,
+ int fd, const char *orig_name ATTRIBUTE_UNUSED)
+{
+ c_common_read_pch (pfile, name, fd, orig_name);
+
+ fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name);
+ print.src_line++;
+}
diff --git a/support/cpp/gcc/c-family/c-pragma.cc b/support/cpp/gcc/c-family/c-pragma.cc
new file mode 100644
index 000000000..fc9a91323
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-pragma.cc
@@ -0,0 +1,1701 @@
+/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
+ 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "function.h" /* For cfun. */
+#include "c-common.h"
+#include "memmodel.h"
+// #include "tm_p.h" /* For REGISTER_TARGET_PRAGMAS. */
+#include "stringpool.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "attribs.h"
+#include "varasm.h"
+#include "c-pragma.h"
+#include "opts.h"
+#include "plugin.h"
+#include "opt-suggestions.h"
+
+#define GCC_BAD(gmsgid) \
+ do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
+#define GCC_BAD2(gmsgid, arg) \
+ do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
+#define GCC_BAD_AT(loc, gmsgid) \
+ do { warning_at (loc, OPT_Wpragmas, gmsgid); return; } while (0)
+#define GCC_BAD2_AT(loc, gmsgid, arg) \
+ do { warning_at (loc, OPT_Wpragmas, gmsgid, arg); return; } while (0)
+
+struct GTY(()) align_stack {
+ int alignment;
+ tree id;
+ struct align_stack * prev;
+};
+
+// sdcpp static GTY(()) struct align_stack * alignment_stack;
+
+static void handle_pragma_pack (cpp_reader *);
+
+/* If we have a "global" #pragma pack(<n>) in effect when the first
+ #pragma pack(push,<n>) is encountered, this stores the value of
+ maximum_field_alignment in effect. When the final pop_alignment()
+ happens, we restore the value to this, not to a value of 0 for
+ maximum_field_alignment. Value is in bits. */
+#if 0 // sdcpp
+static int default_alignment;
+#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = *(alignment_stack == NULL \
+ ? &default_alignment \
+ : &alignment_stack->alignment) = (ALIGN))
+
+static void push_alignment (int, tree);
+static void pop_alignment (tree);
+
+/* Push an alignment value onto the stack. */
+static void
+push_alignment (int alignment, tree id)
+{
+ align_stack * entry = ggc_alloc<align_stack> ();
+
+ entry->alignment = alignment;
+ entry->id = id;
+ entry->prev = alignment_stack;
+
+ /* The current value of maximum_field_alignment is not necessarily
+ 0 since there may be a #pragma pack(<n>) in effect; remember it
+ so that we can restore it after the final #pragma pop(). */
+ if (alignment_stack == NULL)
+ default_alignment = maximum_field_alignment;
+
+ alignment_stack = entry;
+
+ maximum_field_alignment = alignment;
+}
+
+/* Undo a push of an alignment onto the stack. */
+static void
+pop_alignment (tree id)
+{
+ align_stack * entry;
+
+ if (alignment_stack == NULL)
+ GCC_BAD ("%<#pragma pack (pop)%> encountered without matching "
+ "%<#pragma pack (push)%>");
+
+ /* If we got an identifier, strip away everything above the target
+ entry so that the next step will restore the state just below it. */
+ if (id)
+ {
+ for (entry = alignment_stack; entry; entry = entry->prev)
+ if (entry->id == id)
+ {
+ alignment_stack = entry;
+ break;
+ }
+ if (entry == NULL)
+ warning (OPT_Wpragmas,
+ "%<#pragma pack(pop, %E)%> encountered without matching "
+ "%<#pragma pack(push, %E)%>"
+ , id, id);
+ }
+
+ entry = alignment_stack->prev;
+
+ maximum_field_alignment = entry ? entry->alignment : default_alignment;
+
+ alignment_stack = entry;
+}
+#endif // sdcpp
+
+/* #pragma pack ()
+ #pragma pack (N)
+
+ #pragma pack (push)
+ #pragma pack (push, N)
+ #pragma pack (push, ID)
+ #pragma pack (push, ID, N)
+ #pragma pack (pop)
+ #pragma pack (pop, ID) */
+static void
+handle_pragma_pack (cpp_reader *)
+{
+#if 0 // sdcpp
+ location_t loc;
+ tree x, id = 0;
+ int align = -1;
+ enum cpp_ttype token;
+ enum { set, push, pop } action;
+
+ if (pragma_lex (&x) != CPP_OPEN_PAREN)
+ GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
+
+ token = pragma_lex (&x, &loc);
+ if (token == CPP_CLOSE_PAREN)
+ {
+ action = set;
+ align = initial_max_fld_align;
+ }
+ else if (token == CPP_NUMBER)
+ {
+ if (TREE_CODE (x) != INTEGER_CST)
+ GCC_BAD_AT (loc, "invalid constant in %<#pragma pack%> - ignored");
+ align = TREE_INT_CST_LOW (x);
+ action = set;
+ if (pragma_lex (&x) != CPP_CLOSE_PAREN)
+ GCC_BAD ("malformed %<#pragma pack%> - ignored");
+ }
+ else if (token == CPP_NAME)
+ {
+#define GCC_BAD_ACTION do { if (action != pop) \
+ GCC_BAD ("malformed %<#pragma pack(push[, id][, <n>])%> - ignored"); \
+ else \
+ GCC_BAD ("malformed %<#pragma pack(pop[, id])%> - ignored"); \
+ } while (0)
+
+ const char *op = IDENTIFIER_POINTER (x);
+ if (!strcmp (op, "push"))
+ action = push;
+ else if (!strcmp (op, "pop"))
+ action = pop;
+ else
+ GCC_BAD2_AT (loc, "unknown action %qE for %<#pragma pack%> - ignored",
+ x);
+
+ while ((token = pragma_lex (&x)) == CPP_COMMA)
+ {
+ token = pragma_lex (&x, &loc);
+ if (token == CPP_NAME && id == 0)
+ {
+ id = x;
+ }
+ else if (token == CPP_NUMBER && action == push && align == -1)
+ {
+ if (TREE_CODE (x) != INTEGER_CST)
+ GCC_BAD_AT (loc,
+ "invalid constant in %<#pragma pack%> - ignored");
+ align = TREE_INT_CST_LOW (x);
+ if (align == -1)
+ action = set;
+ }
+ else
+ GCC_BAD_ACTION;
+ }
+
+ if (token != CPP_CLOSE_PAREN)
+ GCC_BAD_ACTION;
+#undef GCC_BAD_ACTION
+ }
+ else
+ GCC_BAD ("malformed %<#pragma pack%> - ignored");
+
+ if (pragma_lex (&x, &loc) != CPP_EOF)
+ warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma pack%>");
+
+ if (flag_pack_struct)
+ GCC_BAD ("%<#pragma pack%> has no effect with %<-fpack-struct%> - ignored");
+
+ if (action != pop)
+ switch (align)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ align *= BITS_PER_UNIT;
+ break;
+ case -1:
+ if (action == push)
+ {
+ align = maximum_field_alignment;
+ break;
+ }
+ /* FALLTHRU */
+ default:
+ GCC_BAD2 ("alignment must be a small power of two, not %d", align);
+ }
+
+ switch (action)
+ {
+ case set: SET_GLOBAL_ALIGNMENT (align); break;
+ case push: push_alignment (align, id); break;
+ case pop: pop_alignment (id); break;
+ }
+#endif // sdcpp
+}
+
+struct GTY(()) pending_weak
+{
+ tree name;
+ tree value;
+};
+
+
+#if 0 // sdcpp
+static GTY(()) vec<pending_weak, va_gc> *pending_weaks;
+
+static void apply_pragma_weak (tree, tree);
+static void handle_pragma_weak (cpp_reader *);
+
+static void
+apply_pragma_weak (tree decl, tree value)
+{
+ if (value)
+ {
+ value = build_string (IDENTIFIER_LENGTH (value),
+ IDENTIFIER_POINTER (value));
+ fprintf(stderr, "apply_pragma_weak, incomplete\n");
+// sdcpp decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
+// sdcpp build_tree_list (NULL, value)),
+// sdcpp 0);
+ }
+
+ fprintf(stderr, "apply_pragma_weak2, incomplete\n");
+// sdcpp if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
+// sdcpp && !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */
+// sdcpp && DECL_ASSEMBLER_NAME_SET_P (decl)
+// sdcpp && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+// sdcpp warning (OPT_Wpragmas, "applying %<#pragma weak %+D%> after first use "
+// sdcpp "results in unspecified behavior", decl);
+
+ declare_weak (decl);
+}
+#endif // sdcpp
+
+#if 0 // sdcpp
+void
+maybe_apply_pragma_weak (tree decl)
+{
+ tree id;
+ int i;
+ pending_weak *pe;
+
+ /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed. */
+
+ /* No weak symbols pending, take the short-cut. */
+ if (vec_safe_is_empty (pending_weaks))
+ return;
+ /* If it's not visible outside this file, it doesn't matter whether
+ it's weak. */
+ if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
+ return;
+ /* If it's not a function or a variable, it can't be weak.
+ FIXME: what kinds of things are visible outside this file but
+ aren't functions or variables? Should this be an assert instead? */
+ if (!VAR_OR_FUNCTION_DECL_P (decl))
+ return;
+
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ id = DECL_ASSEMBLER_NAME (decl);
+ else
+ {
+ id = DECL_ASSEMBLER_NAME (decl);
+ SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE);
+ }
+
+ FOR_EACH_VEC_ELT (*pending_weaks, i, pe)
+ if (id == pe->name)
+ {
+ apply_pragma_weak (decl, pe->value);
+ pending_weaks->unordered_remove (i);
+ break;
+ }
+}
+
+/* Process all "#pragma weak A = B" directives where we have not seen
+ a decl for A. */
+void
+maybe_apply_pending_pragma_weaks (void)
+{
+ tree alias_id, id, decl;
+ (void) alias_id;
+ (void) decl;
+ int i;
+ pending_weak *pe;
+ symtab_node *target;
+ (void) target;
+
+ if (vec_safe_is_empty (pending_weaks))
+ return;
+
+ FOR_EACH_VEC_ELT (*pending_weaks, i, pe)
+ {
+ alias_id = pe->name;
+ id = pe->value;
+
+ if (id == NULL)
+ continue;
+
+ fprintf(stderr, "%s, incomplete\n", __func__);
+#if 0 // sdcpp
+ target = symtab_node::get_for_asmname (id);
+ decl = build_decl (UNKNOWN_LOCATION,
+ target ? TREE_CODE (target->decl) : FUNCTION_DECL,
+ alias_id, default_function_type);
+
+ DECL_ARTIFICIAL (decl) = 1;
+ TREE_PUBLIC (decl) = 1;
+ DECL_WEAK (decl) = 1;
+ if (VAR_P (decl))
+ TREE_STATIC (decl) = 1;
+ if (!target)
+ {
+ error ("%q+D aliased to undefined symbol %qE",
+ decl, id);
+ continue;
+ }
+
+ assemble_alias (decl, id);
+#endif // sdcpp
+ }
+}
+#endif // sdcpp
+
+/* #pragma weak name [= value] */
+static void
+handle_pragma_weak (cpp_reader *)
+{
+#if 0 // sdcpp
+ tree name, value, x, decl;
+ enum cpp_ttype t;
+
+ value = 0;
+
+ if (pragma_lex (&name) != CPP_NAME)
+ GCC_BAD ("malformed %<#pragma weak%>, ignored");
+ t = pragma_lex (&x);
+ if (t == CPP_EQ)
+ {
+ if (pragma_lex (&value) != CPP_NAME)
+ GCC_BAD ("malformed %<#pragma weak%>, ignored");
+ t = pragma_lex (&x);
+ }
+ if (t != CPP_EOF)
+ warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
+
+ decl = identifier_global_value (name);
+ if (decl && DECL_P (decl))
+ {
+ if (!VAR_OR_FUNCTION_DECL_P (decl))
+ GCC_BAD2 ("%<#pragma weak%> declaration of %q+D not allowed,"
+ " ignored", decl);
+ apply_pragma_weak (decl, value);
+ if (value)
+ {
+ DECL_EXTERNAL (decl) = 0;
+ if (VAR_P (decl))
+ TREE_STATIC (decl) = 1;
+ assemble_alias (decl, value);
+ }
+ }
+ else
+ {
+ pending_weak pe = {name, value};
+ vec_safe_push (pending_weaks, pe);
+ }
+#endif // sdcpp
+}
+
+#if 0 // sdcpp
+static enum scalar_storage_order_kind global_sso;
+
+void
+maybe_apply_pragma_scalar_storage_order (tree type)
+{
+ if (global_sso == SSO_NATIVE)
+ return;
+
+ gcc_assert (RECORD_OR_UNION_TYPE_P (type));
+
+ if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
+ return;
+
+ if (global_sso == SSO_BIG_ENDIAN)
+ TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
+ else if (global_sso == SSO_LITTLE_ENDIAN)
+ TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
+ else
+ gcc_unreachable ();
+}
+
+static void
+handle_pragma_scalar_storage_order (cpp_reader *)
+{
+ const char *kind_string;
+ enum cpp_ttype token;
+ tree x;
+
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ {
+ error ("%<scalar_storage_order%> is not supported because endianness "
+ "is not uniform");
+ return;
+ }
+
+ if (c_dialect_cxx ())
+ {
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
+ warning (OPT_Wunknown_pragmas,
+ "%<#pragma scalar_storage_order%> is not supported for C++");
+ return;
+ }
+
+ token = pragma_lex (&x);
+ if (token != CPP_NAME)
+ GCC_BAD ("missing %<big-endian%>, %<little-endian%>, or %<default%> after "
+ "%<#pragma scalar_storage_order%>");
+ kind_string = IDENTIFIER_POINTER (x);
+ if (strcmp (kind_string, "default") == 0)
+ global_sso = default_sso;
+ else if (strcmp (kind_string, "big") == 0)
+ global_sso = SSO_BIG_ENDIAN;
+ else if (strcmp (kind_string, "little") == 0)
+ global_sso = SSO_LITTLE_ENDIAN;
+ else
+ GCC_BAD ("expected %<big-endian%>, %<little-endian%>, or %<default%> after "
+ "%<#pragma scalar_storage_order%>");
+}
+#endif // sdcpp
+
+/* GCC supports two #pragma directives for renaming the external
+ symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
+ compatibility with the Solaris and VMS system headers. GCC also
+ has its own notation for this, __asm__("name") annotations.
+
+ Corner cases of these features and their interaction:
+
+ 1) Both pragmas silently apply only to declarations with external
+ linkage (that is, TREE_PUBLIC || DECL_EXTERNAL). Asm labels
+ do not have this restriction.
+
+ 2) In C++, both #pragmas silently apply only to extern "C" declarations.
+ Asm labels do not have this restriction.
+
+ 3) If any of the three ways of changing DECL_ASSEMBLER_NAME is
+ applied to a decl whose DECL_ASSEMBLER_NAME is already set, and the
+ new name is different, a warning issues and the name does not change.
+
+ 4) The "source name" for #pragma redefine_extname is the DECL_NAME,
+ *not* the DECL_ASSEMBLER_NAME.
+
+ 5) If #pragma extern_prefix is in effect and a declaration occurs
+ with an __asm__ name, the #pragma extern_prefix is silently
+ ignored for that declaration.
+
+ 6) If #pragma extern_prefix and #pragma redefine_extname apply to
+ the same declaration, whichever triggered first wins, and a warning
+ is issued. (We would like to have #pragma redefine_extname always
+ win, but it can appear either before or after the declaration, and
+ if it appears afterward, we have no way of knowing whether a modified
+ DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.) */
+
+struct GTY(()) pending_redefinition {
+ tree oldname;
+ tree newname;
+};
+
+
+#if 0 // sdcpp
+static GTY(()) vec<pending_redefinition, va_gc> *pending_redefine_extname;
+
+static void handle_pragma_redefine_extname (cpp_reader *);
+
+/* #pragma redefine_extname oldname newname */
+static void
+handle_pragma_redefine_extname (cpp_reader *)
+{
+ tree oldname, newname, decls, x;
+ enum cpp_ttype t;
+ bool found;
+
+ if (pragma_lex (&oldname) != CPP_NAME)
+ GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
+ if (pragma_lex (&newname) != CPP_NAME)
+ GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
+ t = pragma_lex (&x);
+ if (t != CPP_EOF)
+ warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
+
+ found = false;
+ for (decls = c_linkage_bindings (oldname);
+ decls; )
+ {
+ tree decl;
+ if (TREE_CODE (decls) == TREE_LIST)
+ {
+ decl = TREE_VALUE (decls);
+ decls = TREE_CHAIN (decls);
+ }
+ else
+ {
+ decl = decls;
+ decls = NULL_TREE;
+ }
+
+ if ((TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+ && VAR_OR_FUNCTION_DECL_P (decl))
+ {
+ found = true;
+ fprintf(stderr, "%s, incomplete\n", __func__);
+#if 0 // sdcpp
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ {
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = targetm.strip_name_encoding (name);
+
+ if (!id_equal (newname, name))
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> "
+ "ignored due to conflict with previous rename");
+ }
+ else
+ symtab->change_decl_assembler_name (decl, newname);
+#endif
+ }
+ }
+
+ if (!found)
+ /* We have to add this to the rename list even if there's already
+ a global value that doesn't meet the above criteria, because in
+ C++ "struct foo {...};" puts "foo" in the current namespace but
+ does *not* conflict with a subsequent declaration of a function
+ or variable foo. See g++.dg/other/pragma-re-2.C. */
+ add_to_renaming_pragma_list (oldname, newname);
+}
+
+/* This is called from here and from ia64-c.cc. */
+void
+add_to_renaming_pragma_list (tree oldname, tree newname)
+{
+ unsigned ix;
+ pending_redefinition *p;
+
+ FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
+ if (oldname == p->oldname)
+ {
+ if (p->newname != newname)
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored due to "
+ "conflict with previous %<#pragma redefine_extname%>");
+ return;
+ }
+
+ pending_redefinition e = {oldname, newname};
+ vec_safe_push (pending_redefine_extname, e);
+}
+#endif // sdcpp
+
+/* The current prefix set by #pragma extern_prefix. */
+GTY(()) tree pragma_extern_prefix;
+
+/* Hook from the front ends to apply the results of one of the preceding
+ pragmas that rename variables. */
+
+#if 0 // sdcpp
+tree
+maybe_apply_renaming_pragma (tree decl, tree asmname)
+{
+ unsigned ix;
+ pending_redefinition *p;
+
+ /* The renaming pragmas are only applied to declarations with
+ external linkage. */
+ if (!VAR_OR_FUNCTION_DECL_P (decl)
+ || (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
+ || !has_c_linkage (decl))
+ return asmname;
+
+ /* If the DECL_ASSEMBLER_NAME is already set, it does not change,
+ but we may warn about a rename that conflicts. */
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ {
+ const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ oldname = targetm.strip_name_encoding (oldname);
+
+ if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname))
+ warning (OPT_Wpragmas, "%<asm%> declaration ignored due to "
+ "conflict with previous rename");
+
+ /* Take any pending redefine_extname off the list. */
+ FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
+ if (DECL_NAME (decl) == p->oldname)
+ {
+ /* Only warn if there is a conflict. */
+ if (!id_equal (p->newname, oldname))
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored "
+ "due to conflict with previous rename");
+
+ pending_redefine_extname->unordered_remove (ix);
+ break;
+ }
+ return NULL_TREE;
+ }
+
+ /* Find out if we have a pending #pragma redefine_extname. */
+ FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
+ if (DECL_NAME (decl) == p->oldname)
+ {
+ tree newname = p->newname;
+ pending_redefine_extname->unordered_remove (ix);
+
+ /* If we already have an asmname, #pragma redefine_extname is
+ ignored (with a warning if it conflicts). */
+ if (asmname)
+ {
+ if (strcmp (TREE_STRING_POINTER (asmname),
+ IDENTIFIER_POINTER (newname)) != 0)
+ warning (OPT_Wpragmas, "%<#pragma redefine_extname%> ignored "
+ "due to conflict with %<asm%> declaration");
+ return asmname;
+ }
+
+ /* Otherwise we use what we've got; #pragma extern_prefix is
+ silently ignored. */
+ return build_string (IDENTIFIER_LENGTH (newname),
+ IDENTIFIER_POINTER (newname));
+ }
+
+ /* If we've got an asmname, #pragma extern_prefix is silently ignored. */
+ if (asmname)
+ return asmname;
+
+ /* If #pragma extern_prefix is in effect, apply it. */
+ if (pragma_extern_prefix)
+ {
+ const char *prefix = TREE_STRING_POINTER (pragma_extern_prefix);
+ size_t plen = TREE_STRING_LENGTH (pragma_extern_prefix) - 1;
+
+ const char *id = IDENTIFIER_POINTER (DECL_NAME (decl));
+ size_t ilen = IDENTIFIER_LENGTH (DECL_NAME (decl));
+
+ char *newname = (char *) alloca (plen + ilen + 1);
+
+ memcpy (newname, prefix, plen);
+ memcpy (newname + plen, id, ilen + 1);
+
+ return build_string (plen + ilen, newname);
+ }
+
+ /* Nada. */
+ return NULL_TREE;
+}
+#endif
+
+
+static void handle_pragma_visibility (cpp_reader *);
+
+static vec<int> visstack;
+
+/* Push the visibility indicated by STR onto the top of the #pragma
+ visibility stack. KIND is 0 for #pragma GCC visibility, 1 for
+ C++ namespace with visibility attribute and 2 for C++ builtin
+ ABI namespace. push_visibility/pop_visibility calls must have
+ matching KIND, it is not allowed to push visibility using one
+ KIND and pop using a different one. */
+
+void
+push_visibility (const char *str, int kind)
+{
+ visstack.safe_push (((int) default_visibility) | (kind << 8));
+ if (!strcmp (str, "default"))
+ default_visibility = VISIBILITY_DEFAULT;
+ else if (!strcmp (str, "internal"))
+ default_visibility = VISIBILITY_INTERNAL;
+ else if (!strcmp (str, "hidden"))
+ default_visibility = VISIBILITY_HIDDEN;
+ else if (!strcmp (str, "protected"))
+ default_visibility = VISIBILITY_PROTECTED;
+ else
+ GCC_BAD ("%<#pragma GCC visibility push()%> must specify %<default%>, "
+ "%<internal%>, %<hidden%> or %<protected%>");
+ visibility_options.inpragma = 1;
+}
+
+/* Pop a level of the #pragma visibility stack. Return true if
+ successful. */
+
+bool
+pop_visibility (int kind)
+{
+ if (!visstack.length ())
+ return false;
+ if ((visstack.last () >> 8) != kind)
+ return false;
+ default_visibility
+ = (enum symbol_visibility) (visstack.pop () & 0xff);
+ visibility_options.inpragma
+ = visstack.length () != 0;
+ return true;
+}
+
+/* Sets the default visibility for symbols to something other than that
+ specified on the command line. */
+
+static void
+handle_pragma_visibility (cpp_reader *)
+{
+#if 0 // sdcpp
+ /* Form is #pragma GCC visibility push(hidden)|pop */
+ tree x;
+ enum cpp_ttype token;
+ enum { bad, push, pop } action = bad;
+
+ token = pragma_lex (&x);
+ if (token == CPP_NAME)
+ {
+ const char *op = IDENTIFIER_POINTER (x);
+ if (!strcmp (op, "push"))
+ action = push;
+ else if (!strcmp (op, "pop"))
+ action = pop;
+ }
+ if (bad == action)
+ GCC_BAD ("%<#pragma GCC visibility%> must be followed by %<push%> "
+ "or %<pop%>");
+ else
+ {
+ if (pop == action)
+ {
+ if (! pop_visibility (0))
+ GCC_BAD ("no matching push for %<#pragma GCC visibility pop%>");
+ }
+ else
+ {
+ if (pragma_lex (&x) != CPP_OPEN_PAREN)
+ GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
+ token = pragma_lex (&x);
+ if (token != CPP_NAME)
+ GCC_BAD ("malformed %<#pragma GCC visibility push%>");
+ else
+ push_visibility (IDENTIFIER_POINTER (x), 0);
+ if (pragma_lex (&x) != CPP_CLOSE_PAREN)
+ GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
+ }
+ }
+ if (pragma_lex (&x) != CPP_EOF)
+ warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
+#endif // sdcpp
+}
+
+#if 0 // sdcpp
+static void
+handle_pragma_diagnostic(cpp_reader *)
+{
+ tree x;
+ location_t loc;
+ enum cpp_ttype token = pragma_lex (&x, &loc);
+ if (token != CPP_NAME)
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "missing %<error%>, %<warning%>, %<ignored%>, %<push%>, "
+ "%<pop%>, or %<ignored_attributes%> after "
+ "%<#pragma GCC diagnostic%>");
+ return;
+ }
+
+ diagnostic_t kind;
+ const char *kind_string = IDENTIFIER_POINTER (x);
+ if (strcmp (kind_string, "error") == 0)
+ kind = DK_ERROR;
+ else if (strcmp (kind_string, "warning") == 0)
+ kind = DK_WARNING;
+ else if (strcmp (kind_string, "ignored") == 0)
+ kind = DK_IGNORED;
+ else if (strcmp (kind_string, "push") == 0)
+ {
+ diagnostic_push_diagnostics (global_dc, input_location);
+ return;
+ }
+ else if (strcmp (kind_string, "pop") == 0)
+ {
+ diagnostic_pop_diagnostics (global_dc, input_location);
+ return;
+ }
+ else if (strcmp (kind_string, "ignored_attributes") == 0)
+ {
+ token = pragma_lex (&x, &loc);
+ if (token != CPP_STRING)
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "missing attribute name after %<#pragma GCC diagnostic "
+ "ignored_attributes%>");
+ return;
+ }
+ char *args = xstrdup (TREE_STRING_POINTER (x));
+ const size_t l = strlen (args);
+ if (l == 0)
+ {
+ warning_at (loc, OPT_Wpragmas, "missing argument to %<#pragma GCC "
+ "diagnostic ignored_attributes%>");
+ free (args);
+ return;
+ }
+ else if (args[l - 1] == ',')
+ {
+ warning_at (loc, OPT_Wpragmas, "trailing %<,%> in arguments for "
+ "%<#pragma GCC diagnostic ignored_attributes%>");
+ free (args);
+ return;
+ }
+ auto_vec<char *> v;
+ for (char *p = strtok (args, ","); p; p = strtok (NULL, ","))
+ v.safe_push (p);
+ handle_ignored_attributes_option (&v);
+ free (args);
+ return;
+ }
+ else
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "expected %<error%>, %<warning%>, %<ignored%>, %<push%>, "
+ "%<pop%>, %<ignored_attributes%> after "
+ "%<#pragma GCC diagnostic%>");
+ return;
+ }
+
+ token = pragma_lex (&x, &loc);
+ if (token != CPP_STRING)
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "missing option after %<#pragma GCC diagnostic%> kind");
+ return;
+ }
+
+ const char *option_string = TREE_STRING_POINTER (x);
+ unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON;
+ /* option_string + 1 to skip the initial '-' */
+ unsigned int option_index = find_opt (option_string + 1, lang_mask);
+ if (option_index == OPT_SPECIAL_unknown)
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wpragmas,
+ "unknown option after %<#pragma GCC diagnostic%> kind"))
+ {
+ option_proposer op;
+ const char *hint = op.suggest_option (option_string + 1);
+ if (hint)
+ inform (loc, "did you mean %<-%s%>?", hint);
+ }
+ return;
+ }
+ else if (!(cl_options[option_index].flags & CL_WARNING))
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "%qs is not an option that controls warnings", option_string);
+ return;
+ }
+ else if (!(cl_options[option_index].flags & lang_mask))
+ {
+ char *ok_langs = write_langs (cl_options[option_index].flags);
+ char *bad_lang = write_langs (c_common_option_lang_mask ());
+ warning_at (loc, OPT_Wpragmas,
+ "option %qs is valid for %s but not for %s",
+ option_string, ok_langs, bad_lang);
+ free (ok_langs);
+ free (bad_lang);
+ return;
+ }
+
+ struct cl_option_handlers handlers;
+ set_default_handlers (&handlers, NULL);
+ const char *arg = NULL;
+ if (cl_options[option_index].flags & CL_JOINED)
+ arg = option_string + 1 + cl_options[option_index].opt_len;
+ /* FIXME: input_location isn't the best location here, but it is
+ what we used to do here before and changing it breaks e.g.
+ PR69543 and PR69558. */
+ control_warning_option (option_index, (int) kind,
+ arg, kind != DK_IGNORED,
+ input_location, lang_mask, &handlers,
+ &global_options, &global_options_set,
+ global_dc);
+}
+#endif // sdcpp
+
+/* Parse #pragma GCC target (xxx) to set target specific options. */
+#if 0 // sdcpp
+static void
+handle_pragma_target(cpp_reader *)
+{
+ location_t loc;
+ enum cpp_ttype token;
+ tree x;
+ bool close_paren_needed_p = false;
+
+ if (cfun)
+ {
+ error ("%<#pragma GCC option%> is not allowed inside functions");
+ return;
+ }
+
+ token = pragma_lex (&x, &loc);
+ if (token == CPP_OPEN_PAREN)
+ {
+ close_paren_needed_p = true;
+ token = pragma_lex (&x, &loc);
+ }
+
+ if (token != CPP_STRING)
+ GCC_BAD_AT (loc, "%<#pragma GCC option%> is not a string");
+
+ /* Strings are user options. */
+ else
+ {
+ tree args = NULL_TREE;
+
+ do
+ {
+ /* Build up the strings now as a tree linked list. Skip empty
+ strings. */
+ if (TREE_STRING_LENGTH (x) > 0)
+ args = tree_cons (NULL_TREE, x, args);
+
+ token = pragma_lex (&x);
+ while (token == CPP_COMMA)
+ token = pragma_lex (&x);
+ }
+ while (token == CPP_STRING);
+
+ if (close_paren_needed_p)
+ {
+ if (token == CPP_CLOSE_PAREN)
+ token = pragma_lex (&x);
+ else
+ GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
+ "not have a final %<)%>");
+ }
+
+ if (token != CPP_EOF)
+ {
+ error ("%<#pragma GCC target%> string is badly formed");
+ return;
+ }
+
+ /* put arguments in the order the user typed them. */
+ args = nreverse (args);
+
+ fprintf(stderr, "%s, incomplete\n", __func__);
+ // sdcpp if (targetm.target_option.pragma_parse (args, NULL_TREE))
+ // sdcpp current_target_pragma = chainon (current_target_pragma, args);
+
+ /* A target pragma can also influence optimization options. */
+ tree current_optimize
+ = build_optimization_node (&global_options, &global_options_set);
+ if (current_optimize != optimization_current_node)
+ optimization_current_node = current_optimize;
+ }
+}
+
+/* Handle #pragma GCC optimize to set optimization options. */
+static void
+handle_pragma_optimize (cpp_reader *)
+{
+ enum cpp_ttype token;
+ tree x;
+ bool close_paren_needed_p = false;
+ tree optimization_previous_node = optimization_current_node;
+
+ if (cfun)
+ {
+ error ("%<#pragma GCC optimize%> is not allowed inside functions");
+ return;
+ }
+
+ token = pragma_lex (&x);
+ if (token == CPP_OPEN_PAREN)
+ {
+ close_paren_needed_p = true;
+ token = pragma_lex (&x);
+ }
+
+ if (token != CPP_STRING && token != CPP_NUMBER)
+ GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
+
+ /* Strings/numbers are user options. */
+ else
+ {
+ tree args = NULL_TREE;
+
+ do
+ {
+ /* Build up the numbers/strings now as a list. */
+ if (token != CPP_STRING || TREE_STRING_LENGTH (x) > 0)
+ args = tree_cons (NULL_TREE, x, args);
+
+ token = pragma_lex (&x);
+ while (token == CPP_COMMA)
+ token = pragma_lex (&x);
+ }
+ while (token == CPP_STRING || token == CPP_NUMBER);
+
+ if (close_paren_needed_p)
+ {
+ if (token == CPP_CLOSE_PAREN)
+ token = pragma_lex (&x);
+ else
+ GCC_BAD ("%<#pragma GCC optimize (string [,string]...)%> does "
+ "not have a final %<)%>");
+ }
+
+ if (token != CPP_EOF)
+ {
+ error ("%<#pragma GCC optimize%> string is badly formed");
+ return;
+ }
+
+ /* put arguments in the order the user typed them. */
+ args = nreverse (args);
+
+ parse_optimize_options (args, false);
+ current_optimize_pragma = chainon (current_optimize_pragma, args);
+ optimization_current_node
+ = build_optimization_node (&global_options, &global_options_set);
+ c_cpp_builtins_optimize_pragma (parse_in,
+ optimization_previous_node,
+ optimization_current_node);
+ }
+}
+
+/* Stack of the #pragma GCC options created with #pragma GCC push_option. Save
+ both the binary representation of the options and the TREE_LIST of
+ strings that will be added to the function's attribute list. */
+struct GTY(()) opt_stack {
+ struct opt_stack *prev;
+ tree target_binary;
+ tree target_strings;
+ tree optimize_binary;
+ tree optimize_strings;
+ gcc_options * GTY ((skip)) saved_global_options;
+};
+
+static GTY(()) struct opt_stack * options_stack;
+#endif // sdcpp
+
+/* Handle #pragma GCC push_options to save the current target and optimization
+ options. */
+
+#if 0 // sdcpp
+static void
+handle_pragma_push_options (cpp_reader *)
+{
+ enum cpp_ttype token;
+ tree x = 0;
+
+ token = pragma_lex (&x);
+ if (token != CPP_EOF)
+ {
+ warning (OPT_Wpragmas, "junk at end of %<#pragma push_options%>");
+ return;
+ }
+
+ opt_stack *p = ggc_alloc<opt_stack> ();
+ p->prev = options_stack;
+ options_stack = p;
+
+ /* Save optimization and target flags in binary format. */
+ if (flag_checking)
+ {
+ p->saved_global_options = XNEW (gcc_options);
+ *p->saved_global_options = global_options;
+ }
+ p->optimize_binary = build_optimization_node (&global_options,
+ &global_options_set);
+ p->target_binary = build_target_option_node (&global_options,
+ &global_options_set);
+
+ /* Save optimization and target flags in string list format. */
+ p->optimize_strings = copy_list (current_optimize_pragma);
+ p->target_strings = copy_list (current_target_pragma);
+}
+
+/* Handle #pragma GCC pop_options to restore the current target and
+ optimization options from a previous push_options. */
+
+static void
+handle_pragma_pop_options (cpp_reader *)
+{
+ enum cpp_ttype token;
+ tree x = 0;
+ opt_stack *p;
+
+ token = pragma_lex (&x);
+ if (token != CPP_EOF)
+ {
+ warning (OPT_Wpragmas, "junk at end of %<#pragma pop_options%>");
+ return;
+ }
+
+ if (! options_stack)
+ {
+ warning (OPT_Wpragmas,
+ "%<#pragma GCC pop_options%> without a corresponding "
+ "%<#pragma GCC push_options%>");
+ return;
+ }
+
+ p = options_stack;
+ options_stack = p->prev;
+
+ if (p->target_binary != target_option_current_node)
+ {
+ fprintf(stderr, "%s, incomplete\n", __func__);
+ // sdcpp (void) targetm.target_option.pragma_parse (NULL_TREE, p->target_binary);
+ target_option_current_node = p->target_binary;
+ }
+
+ /* Always restore optimization options as optimization_current_node is
+ * overwritten by invoke_set_current_function_hook. */
+ cl_optimization_restore (&global_options, &global_options_set,
+ TREE_OPTIMIZATION (p->optimize_binary));
+ cl_target_option_restore (&global_options, &global_options_set,
+ TREE_TARGET_OPTION (p->target_binary));
+
+ if (p->optimize_binary != optimization_current_node)
+ {
+ c_cpp_builtins_optimize_pragma (parse_in, optimization_current_node,
+ p->optimize_binary);
+ optimization_current_node = p->optimize_binary;
+ }
+ if (flag_checking && !seen_error ())
+ {
+ cl_optimization_compare (p->saved_global_options, &global_options);
+ free (p->saved_global_options);
+ }
+
+ current_target_pragma = p->target_strings;
+ current_optimize_pragma = p->optimize_strings;
+}
+
+/* Handle #pragma GCC reset_options to restore the current target and
+ optimization options to the original options used on the command line. */
+
+static void
+handle_pragma_reset_options (cpp_reader *)
+{
+ enum cpp_ttype token;
+ tree x = 0;
+ tree new_optimize = optimization_default_node;
+ tree new_target = target_option_default_node;
+
+ token = pragma_lex (&x);
+ if (token != CPP_EOF)
+ {
+ warning (OPT_Wpragmas, "junk at end of %<#pragma reset_options%>");
+ return;
+ }
+
+ if (new_target != target_option_current_node)
+ {
+ fprintf(stderr, "%s, incomplete\n", __func__);
+ // sdcpp (void) targetm.target_option.pragma_parse (NULL_TREE, new_target);
+ target_option_current_node = new_target;
+ }
+
+ if (new_optimize != optimization_current_node)
+ {
+ tree old_optimize = optimization_current_node;
+ cl_optimization_restore (&global_options, &global_options_set,
+ TREE_OPTIMIZATION (new_optimize));
+ c_cpp_builtins_optimize_pragma (parse_in, old_optimize, new_optimize);
+ optimization_current_node = new_optimize;
+ }
+
+ current_target_pragma = NULL_TREE;
+ current_optimize_pragma = NULL_TREE;
+}
+
+/* Print a plain user-specified message. */
+
+static void
+handle_pragma_message (cpp_reader *)
+{
+ location_t loc;
+ enum cpp_ttype token;
+ tree x, message = 0;
+
+ token = pragma_lex (&x);
+ if (token == CPP_OPEN_PAREN)
+ {
+ token = pragma_lex (&x);
+ if (token == CPP_STRING)
+ message = x;
+ else
+ GCC_BAD ("expected a string after %<#pragma message%>");
+ if (pragma_lex (&x) != CPP_CLOSE_PAREN)
+ GCC_BAD ("malformed %<#pragma message%>, ignored");
+ }
+ else if (token == CPP_STRING)
+ message = x;
+ else
+ GCC_BAD ("expected a string after %<#pragma message%>");
+
+ gcc_assert (message);
+
+ if (pragma_lex (&x, &loc) != CPP_EOF)
+ warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma message%>");
+
+ if (TREE_STRING_LENGTH (message) > 1)
+ inform (input_location, "%<#pragma message: %s%>",
+ TREE_STRING_POINTER (message));
+}
+
+/* Mark whether the current location is valid for a STDC pragma. */
+
+static bool valid_location_for_stdc_pragma;
+
+void
+mark_valid_location_for_stdc_pragma (bool flag)
+{
+ valid_location_for_stdc_pragma = flag;
+}
+
+/* Return true if the current location is valid for a STDC pragma. */
+
+bool
+valid_location_for_stdc_pragma_p (void)
+{
+ return valid_location_for_stdc_pragma;
+}
+
+enum pragma_switch_t { PRAGMA_ON, PRAGMA_OFF, PRAGMA_DEFAULT, PRAGMA_BAD };
+#endif // sdcpp
+
+/* A STDC pragma must appear outside of external declarations or
+ preceding all explicit declarations and statements inside a compound
+ statement; its behavior is undefined if used in any other context.
+ It takes a switch of ON, OFF, or DEFAULT. */
+
+#if 0 // sdcpp
+static enum pragma_switch_t
+handle_stdc_pragma (const char *pname)
+{
+ const char *arg;
+ tree t;
+ enum pragma_switch_t ret;
+
+ if (!valid_location_for_stdc_pragma_p ())
+ {
+ warning (OPT_Wpragmas, "invalid location for %<pragma %s%>, ignored",
+ pname);
+ return PRAGMA_BAD;
+ }
+
+ if (pragma_lex (&t) != CPP_NAME)
+ {
+ warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
+ return PRAGMA_BAD;
+ }
+
+ arg = IDENTIFIER_POINTER (t);
+
+ if (!strcmp (arg, "ON"))
+ ret = PRAGMA_ON;
+ else if (!strcmp (arg, "OFF"))
+ ret = PRAGMA_OFF;
+ else if (!strcmp (arg, "DEFAULT"))
+ ret = PRAGMA_DEFAULT;
+ else
+ {
+ warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
+ return PRAGMA_BAD;
+ }
+
+ if (pragma_lex (&t) != CPP_EOF)
+ {
+ warning (OPT_Wpragmas, "junk at end of %<#pragma %s%>", pname);
+ return PRAGMA_BAD;
+ }
+
+ return ret;
+}
+#endif // sdcpp
+
+/* #pragma STDC FLOAT_CONST_DECIMAL64 ON
+ #pragma STDC FLOAT_CONST_DECIMAL64 OFF
+ #pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT */
+
+#if 0 //sdcpp
+static void
+handle_pragma_float_const_decimal64 (cpp_reader *)
+{
+ if (c_dialect_cxx ())
+ {
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
+ warning (OPT_Wunknown_pragmas,
+ "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
+ " for C++");
+ return;
+ }
+
+ if (!targetm.decimal_float_supported_p ())
+ {
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
+ warning (OPT_Wunknown_pragmas,
+ "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
+ " on this target");
+ return;
+ }
+
+ pedwarn (input_location, OPT_Wpedantic,
+ "ISO C does not support %<#pragma STDC FLOAT_CONST_DECIMAL64%>");
+
+ switch (handle_stdc_pragma ("STDC FLOAT_CONST_DECIMAL64"))
+ {
+ case PRAGMA_ON:
+ set_float_const_decimal64 ();
+ break;
+ case PRAGMA_OFF:
+ case PRAGMA_DEFAULT:
+ clear_float_const_decimal64 ();
+ break;
+ case PRAGMA_BAD:
+ break;
+ }
+}
+#endif //sdcpp
+
+/* A vector of registered pragma callbacks, which is never freed. */
+
+static vec<internal_pragma_handler> registered_pragmas;
+
+struct pragma_ns_name
+{
+ const char *space;
+ const char *name;
+};
+
+
+static vec<pragma_ns_name> registered_pp_pragmas;
+
+struct omp_pragma_def { const char *name; unsigned int id; };
+static const struct omp_pragma_def oacc_pragmas[] = {
+ { "atomic", PRAGMA_OACC_ATOMIC },
+ { "cache", PRAGMA_OACC_CACHE },
+ { "data", PRAGMA_OACC_DATA },
+ { "declare", PRAGMA_OACC_DECLARE },
+ { "enter", PRAGMA_OACC_ENTER_DATA },
+ { "exit", PRAGMA_OACC_EXIT_DATA },
+ { "host_data", PRAGMA_OACC_HOST_DATA },
+ { "kernels", PRAGMA_OACC_KERNELS },
+ { "loop", PRAGMA_OACC_LOOP },
+ { "parallel", PRAGMA_OACC_PARALLEL },
+ { "routine", PRAGMA_OACC_ROUTINE },
+ { "serial", PRAGMA_OACC_SERIAL },
+ { "update", PRAGMA_OACC_UPDATE },
+ { "wait", PRAGMA_OACC_WAIT }
+};
+static const struct omp_pragma_def omp_pragmas[] = {
+ { "allocate", PRAGMA_OMP_ALLOCATE },
+ { "atomic", PRAGMA_OMP_ATOMIC },
+ { "barrier", PRAGMA_OMP_BARRIER },
+ { "cancel", PRAGMA_OMP_CANCEL },
+ { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
+ { "critical", PRAGMA_OMP_CRITICAL },
+ { "depobj", PRAGMA_OMP_DEPOBJ },
+ { "error", PRAGMA_OMP_ERROR },
+ { "end", PRAGMA_OMP_END_DECLARE_TARGET },
+ { "flush", PRAGMA_OMP_FLUSH },
+ { "nothing", PRAGMA_OMP_NOTHING },
+ { "requires", PRAGMA_OMP_REQUIRES },
+ { "scope", PRAGMA_OMP_SCOPE },
+ { "section", PRAGMA_OMP_SECTION },
+ { "sections", PRAGMA_OMP_SECTIONS },
+ { "single", PRAGMA_OMP_SINGLE },
+ { "task", PRAGMA_OMP_TASK },
+ { "taskgroup", PRAGMA_OMP_TASKGROUP },
+ { "taskwait", PRAGMA_OMP_TASKWAIT },
+ { "taskyield", PRAGMA_OMP_TASKYIELD },
+ { "threadprivate", PRAGMA_OMP_THREADPRIVATE }
+};
+static const struct omp_pragma_def omp_pragmas_simd[] = {
+ { "declare", PRAGMA_OMP_DECLARE },
+ { "distribute", PRAGMA_OMP_DISTRIBUTE },
+ { "for", PRAGMA_OMP_FOR },
+ { "loop", PRAGMA_OMP_LOOP },
+ { "masked", PRAGMA_OMP_MASKED },
+ { "master", PRAGMA_OMP_MASTER },
+ { "ordered", PRAGMA_OMP_ORDERED },
+ { "parallel", PRAGMA_OMP_PARALLEL },
+ { "scan", PRAGMA_OMP_SCAN },
+ { "simd", PRAGMA_OMP_SIMD },
+ { "target", PRAGMA_OMP_TARGET },
+ { "taskloop", PRAGMA_OMP_TASKLOOP },
+ { "teams", PRAGMA_OMP_TEAMS },
+};
+
+void
+c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
+{
+ const int n_oacc_pragmas = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas);
+ const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
+ const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd)
+ / sizeof (*omp_pragmas);
+ int i;
+
+ for (i = 0; i < n_oacc_pragmas; ++i)
+ if (oacc_pragmas[i].id == id)
+ {
+ *space = "acc";
+ *name = oacc_pragmas[i].name;
+ return;
+ }
+
+ for (i = 0; i < n_omp_pragmas; ++i)
+ if (omp_pragmas[i].id == id)
+ {
+ *space = "omp";
+ *name = omp_pragmas[i].name;
+ return;
+ }
+
+ for (i = 0; i < n_omp_pragmas_simd; ++i)
+ if (omp_pragmas_simd[i].id == id)
+ {
+ *space = "omp";
+ *name = omp_pragmas_simd[i].name;
+ return;
+ }
+
+ if (id >= PRAGMA_FIRST_EXTERNAL
+ && (id < PRAGMA_FIRST_EXTERNAL + registered_pp_pragmas.length ()))
+ {
+ *space = registered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL].space;
+ *name = registered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL].name;
+ return;
+ }
+
+ gcc_unreachable ();
+}
+
+/* Front-end wrappers for pragma registration to avoid dragging
+ cpplib.h in almost everywhere. */
+
+static void
+c_register_pragma_1 (const char *space, const char *name,
+ internal_pragma_handler ihandler, bool allow_expansion)
+{
+ unsigned id;
+
+ if (flag_preprocess_only)
+ {
+ pragma_ns_name ns_name;
+
+ if (!allow_expansion)
+ return;
+
+ ns_name.space = space;
+ ns_name.name = name;
+ registered_pp_pragmas.safe_push (ns_name);
+ id = registered_pp_pragmas.length ();
+ id += PRAGMA_FIRST_EXTERNAL - 1;
+ }
+ else
+ {
+ registered_pragmas.safe_push (ihandler);
+ id = registered_pragmas.length ();
+ id += PRAGMA_FIRST_EXTERNAL - 1;
+
+ /* The C front end allocates 8 bits in c_token. The C++ front end
+ keeps the pragma kind in the form of INTEGER_CST, so no small
+ limit applies. At present this is sufficient. */
+ gcc_assert (id < 256);
+ }
+
+ cpp_register_deferred_pragma (parse_in, space, name, id,
+ allow_expansion, false);
+}
+
+/* Register a C pragma handler, using a space and a name. It disallows pragma
+ expansion (if you want it, use c_register_pragma_with_expansion instead). */
+void
+c_register_pragma (const char *space, const char *name,
+ pragma_handler_1arg handler)
+{
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_1arg = handler;
+ ihandler.extra_data = false;
+ ihandler.data = NULL;
+ c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name, it also carries an
+ extra data field which can be used by the handler. It disallows pragma
+ expansion (if you want it, use c_register_pragma_with_expansion_and_data
+ instead). */
+void
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
+{
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_2arg = handler;
+ ihandler.extra_data = true;
+ ihandler.data = data;
+ c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name. It allows pragma
+ expansion as in the following example:
+
+ #define NUMBER 10
+ #pragma count (NUMBER)
+
+ Name expansion is still disallowed. */
+void
+c_register_pragma_with_expansion (const char *space, const char *name,
+ pragma_handler_1arg handler)
+{
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_1arg = handler;
+ ihandler.extra_data = false;
+ ihandler.data = NULL;
+ c_register_pragma_1 (space, name, ihandler, true);
+}
+
+/* Register a C pragma handler, using a space and a name, it also carries an
+ extra data field which can be used by the handler. It allows pragma
+ expansion as in the following example:
+
+ #define NUMBER 10
+ #pragma count (NUMBER)
+
+ Name expansion is still disallowed. */
+void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+ pragma_handler_2arg handler,
+ void *data)
+{
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_2arg = handler;
+ ihandler.extra_data = true;
+ ihandler.data = data;
+ c_register_pragma_1 (space, name, ihandler, true);
+}
+
+void
+c_invoke_pragma_handler (unsigned int id)
+{
+ internal_pragma_handler *ihandler;
+ pragma_handler_1arg handler_1arg;
+ pragma_handler_2arg handler_2arg;
+
+ id -= PRAGMA_FIRST_EXTERNAL;
+ ihandler = &registered_pragmas[id];
+ if (ihandler->extra_data)
+ {
+ handler_2arg = ihandler->handler.handler_2arg;
+ handler_2arg (parse_in, ihandler->data);
+ }
+ else
+ {
+ handler_1arg = ihandler->handler.handler_1arg;
+ handler_1arg (parse_in);
+ }
+}
+
+/* Set up front-end pragmas. */
+void
+init_pragma (void)
+{
+ if (flag_openacc)
+ {
+ const int n_oacc_pragmas
+ = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas);
+ int i;
+
+ for (i = 0; i < n_oacc_pragmas; ++i)
+ cpp_register_deferred_pragma (parse_in, "acc", oacc_pragmas[i].name,
+ oacc_pragmas[i].id, true, true);
+ }
+
+ if (flag_openmp)
+ {
+ const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
+ int i;
+
+ for (i = 0; i < n_omp_pragmas; ++i)
+ cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
+ omp_pragmas[i].id, true, true);
+ }
+ if (flag_openmp || flag_openmp_simd)
+ {
+ const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd)
+ / sizeof (*omp_pragmas);
+ int i;
+
+ for (i = 0; i < n_omp_pragmas_simd; ++i)
+ cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas_simd[i].name,
+ omp_pragmas_simd[i].id, true, true);
+ }
+
+ if (!flag_preprocess_only)
+ cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
+ PRAGMA_GCC_PCH_PREPROCESS, false, false);
+
+ if (!flag_preprocess_only)
+ cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
+ false);
+
+ if (!flag_preprocess_only)
+ cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL,
+ false, false);
+
+#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
+ c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
+#else
+ c_register_pragma (0, "pack", handle_pragma_pack);
+#endif
+ c_register_pragma (0, "weak", handle_pragma_weak);
+
+ c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
+
+#if 0 // sdcpp
+ c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
+ c_register_pragma ("GCC", "target", handle_pragma_target);
+ c_register_pragma ("GCC", "optimize", handle_pragma_optimize);
+ c_register_pragma ("GCC", "push_options", handle_pragma_push_options);
+ c_register_pragma ("GCC", "pop_options", handle_pragma_pop_options);
+ c_register_pragma ("GCC", "reset_options", handle_pragma_reset_options);
+
+ c_register_pragma ("STDC", "FLOAT_CONST_DECIMAL64",
+ handle_pragma_float_const_decimal64);
+
+ c_register_pragma_with_expansion (0, "redefine_extname",
+ handle_pragma_redefine_extname);
+
+ c_register_pragma_with_expansion (0, "message", handle_pragma_message);
+
+#ifdef REGISTER_TARGET_PRAGMAS
+ // fprintf(stderr, "no REGISTER_TARGET_PRAGMAS\n");
+ // REGISTER_TARGET_PRAGMAS ();
+#endif
+
+ global_sso = default_sso;
+ c_register_pragma (0, "scalar_storage_order",
+ handle_pragma_scalar_storage_order);
+
+ /* Allow plugins to register their own pragmas. */
+ invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
+#endif // sdcpp
+}
+
+// sdcpp #include "gt-c-family-c-pragma.h"
diff --git a/support/cpp/gcc/c-family/c-pragma.h b/support/cpp/gcc/c-family/c-pragma.h
new file mode 100644
index 000000000..54864c2ec
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-pragma.h
@@ -0,0 +1,270 @@
+/* Pragma related interfaces.
+ Copyright (C) 1995-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_C_PRAGMA_H
+#define GCC_C_PRAGMA_H
+
+#include "cpplib.h" /* For enum cpp_ttype. */
+
+/* Pragma identifiers built in to the front end parsers. Identifiers
+ for ancillary handlers will follow these. */
+enum pragma_kind {
+ PRAGMA_NONE = 0,
+
+ PRAGMA_OACC_ATOMIC,
+ PRAGMA_OACC_CACHE,
+ PRAGMA_OACC_DATA,
+ PRAGMA_OACC_DECLARE,
+ PRAGMA_OACC_ENTER_DATA,
+ PRAGMA_OACC_EXIT_DATA,
+ PRAGMA_OACC_HOST_DATA,
+ PRAGMA_OACC_KERNELS,
+ PRAGMA_OACC_LOOP,
+ PRAGMA_OACC_PARALLEL,
+ PRAGMA_OACC_ROUTINE,
+ PRAGMA_OACC_SERIAL,
+ PRAGMA_OACC_UPDATE,
+ PRAGMA_OACC_WAIT,
+
+ /* PRAGMA_OMP__START_ should be equal to the first PRAGMA_OMP_* code. */
+ PRAGMA_OMP_ALLOCATE,
+ PRAGMA_OMP__START_ = PRAGMA_OMP_ALLOCATE,
+ PRAGMA_OMP_ATOMIC,
+ PRAGMA_OMP_BARRIER,
+ PRAGMA_OMP_CANCEL,
+ PRAGMA_OMP_CANCELLATION_POINT,
+ PRAGMA_OMP_CRITICAL,
+ PRAGMA_OMP_DECLARE,
+ PRAGMA_OMP_DEPOBJ,
+ PRAGMA_OMP_DISTRIBUTE,
+ PRAGMA_OMP_ERROR,
+ PRAGMA_OMP_END_DECLARE_TARGET,
+ PRAGMA_OMP_FLUSH,
+ PRAGMA_OMP_FOR,
+ PRAGMA_OMP_LOOP,
+ PRAGMA_OMP_NOTHING,
+ PRAGMA_OMP_MASKED,
+ PRAGMA_OMP_MASTER,
+ PRAGMA_OMP_ORDERED,
+ PRAGMA_OMP_PARALLEL,
+ PRAGMA_OMP_REQUIRES,
+ PRAGMA_OMP_SCAN,
+ PRAGMA_OMP_SCOPE,
+ PRAGMA_OMP_SECTION,
+ PRAGMA_OMP_SECTIONS,
+ PRAGMA_OMP_SIMD,
+ PRAGMA_OMP_SINGLE,
+ PRAGMA_OMP_TARGET,
+ PRAGMA_OMP_TASK,
+ PRAGMA_OMP_TASKGROUP,
+ PRAGMA_OMP_TASKLOOP,
+ PRAGMA_OMP_TASKWAIT,
+ PRAGMA_OMP_TASKYIELD,
+ PRAGMA_OMP_THREADPRIVATE,
+ PRAGMA_OMP_TEAMS,
+ /* PRAGMA_OMP__LAST_ should be equal to the last PRAGMA_OMP_* code. */
+ PRAGMA_OMP__LAST_ = PRAGMA_OMP_TEAMS,
+
+ PRAGMA_GCC_PCH_PREPROCESS,
+ PRAGMA_IVDEP,
+ PRAGMA_UNROLL,
+
+ PRAGMA_FIRST_EXTERNAL
+};
+
+
+/* All clauses defined by OpenACC 2.0, and OpenMP 2.5, 3.0, 3.1, 4.0, 4.5, 5.0,
+ and 5.1. Used internally by both C and C++ parsers. */
+enum pragma_omp_clause {
+ PRAGMA_OMP_CLAUSE_NONE = 0,
+
+ PRAGMA_OMP_CLAUSE_AFFINITY,
+ PRAGMA_OMP_CLAUSE_ALIGNED,
+ PRAGMA_OMP_CLAUSE_ALLOCATE,
+ PRAGMA_OMP_CLAUSE_BIND,
+ PRAGMA_OMP_CLAUSE_COLLAPSE,
+ PRAGMA_OMP_CLAUSE_COPYIN,
+ PRAGMA_OMP_CLAUSE_COPYPRIVATE,
+ PRAGMA_OMP_CLAUSE_DEFAULT,
+ PRAGMA_OMP_CLAUSE_DEFAULTMAP,
+ PRAGMA_OMP_CLAUSE_DEPEND,
+ PRAGMA_OMP_CLAUSE_DETACH,
+ PRAGMA_OMP_CLAUSE_DEVICE,
+ PRAGMA_OMP_CLAUSE_DEVICE_TYPE,
+ PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_FILTER,
+ PRAGMA_OMP_CLAUSE_FINAL,
+ PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
+ PRAGMA_OMP_CLAUSE_FOR,
+ PRAGMA_OMP_CLAUSE_FROM,
+ PRAGMA_OMP_CLAUSE_GRAINSIZE,
+ PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR,
+ PRAGMA_OMP_CLAUSE_HINT,
+ PRAGMA_OMP_CLAUSE_IF,
+ PRAGMA_OMP_CLAUSE_IN_REDUCTION,
+ PRAGMA_OMP_CLAUSE_INBRANCH,
+ PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR,
+ PRAGMA_OMP_CLAUSE_LASTPRIVATE,
+ PRAGMA_OMP_CLAUSE_LINEAR,
+ PRAGMA_OMP_CLAUSE_LINK,
+ PRAGMA_OMP_CLAUSE_MAP,
+ PRAGMA_OMP_CLAUSE_MERGEABLE,
+ PRAGMA_OMP_CLAUSE_NOGROUP,
+ PRAGMA_OMP_CLAUSE_NONTEMPORAL,
+ PRAGMA_OMP_CLAUSE_NOTINBRANCH,
+ PRAGMA_OMP_CLAUSE_NOWAIT,
+ PRAGMA_OMP_CLAUSE_NUM_TASKS,
+ PRAGMA_OMP_CLAUSE_NUM_TEAMS,
+ PRAGMA_OMP_CLAUSE_NUM_THREADS,
+ PRAGMA_OMP_CLAUSE_ORDER,
+ PRAGMA_OMP_CLAUSE_ORDERED,
+ PRAGMA_OMP_CLAUSE_PARALLEL,
+ PRAGMA_OMP_CLAUSE_PRIORITY,
+ PRAGMA_OMP_CLAUSE_PRIVATE,
+ PRAGMA_OMP_CLAUSE_PROC_BIND,
+ PRAGMA_OMP_CLAUSE_REDUCTION,
+ PRAGMA_OMP_CLAUSE_SAFELEN,
+ PRAGMA_OMP_CLAUSE_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_SECTIONS,
+ PRAGMA_OMP_CLAUSE_SHARED,
+ PRAGMA_OMP_CLAUSE_SIMD,
+ PRAGMA_OMP_CLAUSE_SIMDLEN,
+ PRAGMA_OMP_CLAUSE_TASK_REDUCTION,
+ PRAGMA_OMP_CLAUSE_TASKGROUP,
+ PRAGMA_OMP_CLAUSE_THREAD_LIMIT,
+ PRAGMA_OMP_CLAUSE_THREADS,
+ PRAGMA_OMP_CLAUSE_TO,
+ PRAGMA_OMP_CLAUSE_UNIFORM,
+ PRAGMA_OMP_CLAUSE_UNTIED,
+ PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR,
+ PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR,
+
+ /* Clauses for OpenACC. */
+ PRAGMA_OACC_CLAUSE_ASYNC,
+ PRAGMA_OACC_CLAUSE_ATTACH,
+ PRAGMA_OACC_CLAUSE_AUTO,
+ PRAGMA_OACC_CLAUSE_COPY,
+ PRAGMA_OACC_CLAUSE_COPYOUT,
+ PRAGMA_OACC_CLAUSE_CREATE,
+ PRAGMA_OACC_CLAUSE_DELETE,
+ PRAGMA_OACC_CLAUSE_DEVICEPTR,
+ PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT,
+ PRAGMA_OACC_CLAUSE_FINALIZE,
+ PRAGMA_OACC_CLAUSE_GANG,
+ PRAGMA_OACC_CLAUSE_HOST,
+ PRAGMA_OACC_CLAUSE_INDEPENDENT,
+ PRAGMA_OACC_CLAUSE_NO_CREATE,
+ PRAGMA_OACC_CLAUSE_NOHOST,
+ PRAGMA_OACC_CLAUSE_NUM_GANGS,
+ PRAGMA_OACC_CLAUSE_NUM_WORKERS,
+ PRAGMA_OACC_CLAUSE_PRESENT,
+ PRAGMA_OACC_CLAUSE_SELF,
+ PRAGMA_OACC_CLAUSE_SEQ,
+ PRAGMA_OACC_CLAUSE_TILE,
+ PRAGMA_OACC_CLAUSE_VECTOR,
+ PRAGMA_OACC_CLAUSE_VECTOR_LENGTH,
+ PRAGMA_OACC_CLAUSE_WAIT,
+ PRAGMA_OACC_CLAUSE_WORKER,
+ PRAGMA_OACC_CLAUSE_IF_PRESENT,
+ PRAGMA_OACC_CLAUSE_COLLAPSE = PRAGMA_OMP_CLAUSE_COLLAPSE,
+ PRAGMA_OACC_CLAUSE_COPYIN = PRAGMA_OMP_CLAUSE_COPYIN,
+ PRAGMA_OACC_CLAUSE_DEVICE = PRAGMA_OMP_CLAUSE_DEVICE,
+ PRAGMA_OACC_CLAUSE_DEFAULT = PRAGMA_OMP_CLAUSE_DEFAULT,
+ PRAGMA_OACC_CLAUSE_DETACH = PRAGMA_OMP_CLAUSE_DETACH,
+ PRAGMA_OACC_CLAUSE_FIRSTPRIVATE = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
+ PRAGMA_OACC_CLAUSE_IF = PRAGMA_OMP_CLAUSE_IF,
+ PRAGMA_OACC_CLAUSE_PRIVATE = PRAGMA_OMP_CLAUSE_PRIVATE,
+ PRAGMA_OACC_CLAUSE_REDUCTION = PRAGMA_OMP_CLAUSE_REDUCTION,
+ PRAGMA_OACC_CLAUSE_LINK = PRAGMA_OMP_CLAUSE_LINK,
+ PRAGMA_OACC_CLAUSE_USE_DEVICE = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR
+};
+
+extern struct cpp_reader* parse_in;
+
+/* It's safe to always leave visibility pragma enabled as if
+ visibility is not supported on the host OS platform the
+ statements are ignored. */
+extern void push_visibility (const char *, int);
+extern bool pop_visibility (int);
+
+extern void init_pragma (void);
+
+/* Front-end wrappers for pragma registration. */
+typedef void (*pragma_handler_1arg)(struct cpp_reader *);
+/* A second pragma handler, which adds a void * argument allowing to pass extra
+ data to the handler. */
+typedef void (*pragma_handler_2arg)(struct cpp_reader *, void *);
+
+/* This union allows to abstract the different handlers. */
+union gen_pragma_handler {
+ pragma_handler_1arg handler_1arg;
+ pragma_handler_2arg handler_2arg;
+};
+/* Internally used to keep the data of the handler. */
+struct internal_pragma_handler {
+ union gen_pragma_handler handler;
+ /* Permits to know if handler is a pragma_handler_1arg (extra_data is false)
+ or a pragma_handler_2arg (extra_data is true). */
+ bool extra_data;
+ /* A data field which can be used when extra_data is true. */
+ void * data;
+};
+
+extern void c_register_pragma (const char *space, const char *name,
+ pragma_handler_1arg handler);
+extern void c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler,
+ void *data);
+
+extern void c_register_pragma_with_expansion (const char *space,
+ const char *name,
+ pragma_handler_1arg handler);
+extern void c_register_pragma_with_expansion_and_data (const char *space,
+ const char *name,
+ pragma_handler_2arg handler,
+ void *data);
+extern void c_invoke_pragma_handler (unsigned int);
+
+extern void maybe_apply_pragma_weak (tree);
+extern void maybe_apply_pending_pragma_weaks (void);
+extern tree maybe_apply_renaming_pragma (tree, tree);
+extern void maybe_apply_pragma_scalar_storage_order (tree);
+extern void add_to_renaming_pragma_list (tree, tree);
+
+extern enum cpp_ttype pragma_lex (tree *, location_t *loc = NULL);
+
+/* Flags for use with c_lex_with_flags. The values here were picked
+ so that 0 means to translate and join strings. */
+#define C_LEX_STRING_NO_TRANSLATE 1 /* Do not lex strings into
+ execution character set. */
+#define C_LEX_STRING_NO_JOIN 2 /* Do not concatenate strings
+ nor translate them into execution
+ character set. */
+
+/* This is not actually available to pragma parsers. It's merely a
+ convenient location to declare this function for c-lex, after
+ having enum cpp_ttype declared. */
+extern enum cpp_ttype c_lex_with_flags (tree *, location_t *, unsigned char *,
+ int);
+
+extern void c_pp_lookup_pragma (unsigned int, const char **, const char **);
+
+extern GTY(()) tree pragma_extern_prefix;
+
+#endif /* GCC_C_PRAGMA_H */
diff --git a/support/cpp/gcc/c-family/c-pretty-print.h b/support/cpp/gcc/c-family/c-pretty-print.h
new file mode 100644
index 000000000..ba7624dab
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-pretty-print.h
@@ -0,0 +1,143 @@
+/* Various declarations for the C and C++ pretty-printers.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+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_C_PRETTY_PRINTER
+#define GCC_C_PRETTY_PRINTER
+
+#include "tree.h"
+#include "c-family/c-common.h"
+#include "pretty-print.h"
+
+
+enum pp_c_pretty_print_flags
+ {
+ pp_c_flag_abstract = 1 << 1,
+ pp_c_flag_gnu_v3 = 1 << 2,
+ pp_c_flag_last_bit = 3
+ };
+
+
+/* The data type used to bundle information necessary for pretty-printing
+ a C or C++ entity. */
+class c_pretty_printer;
+
+/* The type of a C pretty-printer 'member' function. */
+typedef void (*c_pretty_print_fn) (c_pretty_printer *, tree);
+
+/* The datatype that contains information necessary for pretty-printing
+ a tree that represents a C construct. Any pretty-printer for a
+ language using C syntax can derive from this datatype and reuse
+ facilities provided here. A derived pretty-printer can override
+ any function listed in the vtable below. See cp/cxx-pretty-print.h
+ and cp/cxx-pretty-print.cc for an example of derivation. */
+class c_pretty_printer : public pretty_printer
+{
+public:
+ c_pretty_printer ();
+ pretty_printer *clone () const OVERRIDE;
+
+ // Format string, possibly translated.
+ void translate_string (const char *);
+
+ virtual void constant (tree);
+ virtual void id_expression (tree);
+ virtual void primary_expression (tree);
+ virtual void postfix_expression (tree);
+ virtual void unary_expression (tree);
+ virtual void multiplicative_expression (tree);
+ virtual void conditional_expression (tree);
+ virtual void assignment_expression (tree);
+ virtual void expression (tree);
+
+ virtual void type_id (tree);
+ virtual void statement (tree);
+
+ virtual void declaration (tree);
+ virtual void declaration_specifiers (tree);
+ virtual void simple_type_specifier (tree);
+ virtual void function_specifier (tree);
+ virtual void storage_class_specifier (tree);
+ virtual void declarator (tree);
+ virtual void direct_declarator (tree);
+ virtual void abstract_declarator (tree);
+ virtual void direct_abstract_declarator (tree);
+
+ virtual void initializer (tree);
+ /* Points to the first element of an array of offset-list.
+ Not used yet. */
+ int *offset_list;
+
+ pp_flags flags;
+
+ /* These must be overridden by each of the C and C++ front-end to
+ reflect their understanding of syntactic productions when they differ. */
+ c_pretty_print_fn type_specifier_seq;
+ c_pretty_print_fn ptr_operator;
+ c_pretty_print_fn parameter_list;
+};
+
+#define pp_c_tree_identifier(PPI, ID) \
+ pp_c_identifier (PPI, IDENTIFIER_POINTER (ID))
+
+#define pp_type_specifier_seq(PP, D) (PP)->type_specifier_seq (PP, D)
+#define pp_ptr_operator(PP, D) (PP)->ptr_operator (PP, D)
+#define pp_parameter_list(PP, T) (PP)->parameter_list (PP, T)
+
+void pp_c_whitespace (c_pretty_printer *);
+void pp_c_left_paren (c_pretty_printer *);
+void pp_c_right_paren (c_pretty_printer *);
+void pp_c_left_brace (c_pretty_printer *);
+void pp_c_right_brace (c_pretty_printer *);
+void pp_c_left_bracket (c_pretty_printer *);
+void pp_c_right_bracket (c_pretty_printer *);
+void pp_c_dot (c_pretty_printer *);
+void pp_c_ampersand (c_pretty_printer *);
+void pp_c_star (c_pretty_printer *);
+void pp_c_arrow (c_pretty_printer *);
+void pp_c_semicolon (c_pretty_printer *);
+void pp_c_complement (c_pretty_printer *);
+void pp_c_exclamation (c_pretty_printer *);
+void pp_c_space_for_pointer_operator (c_pretty_printer *, tree);
+
+/* Declarations. */
+void pp_c_tree_decl_identifier (c_pretty_printer *, tree);
+void pp_c_function_definition (c_pretty_printer *, tree);
+void pp_c_attributes (c_pretty_printer *, tree);
+void pp_c_attributes_display (c_pretty_printer *, tree);
+void pp_c_cv_qualifiers (c_pretty_printer *pp, int qualifiers, bool func_type);
+void pp_c_type_qualifier_list (c_pretty_printer *, tree);
+void pp_c_parameter_type_list (c_pretty_printer *, tree);
+void pp_c_specifier_qualifier_list (c_pretty_printer *, tree);
+/* Expressions. */
+void pp_c_logical_or_expression (c_pretty_printer *, tree);
+void pp_c_expression_list (c_pretty_printer *, tree);
+void pp_c_constructor_elts (c_pretty_printer *, vec<constructor_elt, va_gc> *);
+void pp_c_call_argument_list (c_pretty_printer *, tree);
+void pp_c_type_cast (c_pretty_printer *, tree);
+void pp_c_cast_expression (c_pretty_printer *, tree);
+void pp_c_init_declarator (c_pretty_printer *, tree);
+void pp_c_ws_string (c_pretty_printer *, const char *);
+void pp_c_identifier (c_pretty_printer *, const char *);
+void pp_c_string_literal (c_pretty_printer *, tree);
+void pp_c_integer_constant (c_pretty_printer *, tree);
+
+void print_c_tree (FILE *file, tree t);
+
+#endif /* GCC_C_PRETTY_PRINTER */
diff --git a/support/cpp/gcc/c-family/c-spellcheck.h b/support/cpp/gcc/c-family/c-spellcheck.h
new file mode 100644
index 000000000..015d37380
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-spellcheck.h
@@ -0,0 +1,53 @@
+/* Find near-matches for macros.
+ Copyright (C) 2016-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 C_SPELLCHECK_H
+#define C_SPELLCHECK_H
+
+#include "spellcheck.h"
+
+extern bool name_reserved_for_implementation_p (const char *str);
+
+/* Specialization of edit_distance_traits for preprocessor macros. */
+
+template <>
+struct edit_distance_traits<cpp_hashnode *>
+{
+ static size_t get_length (cpp_hashnode *hashnode)
+ {
+ return hashnode->ident.len;
+ }
+
+ static const char *get_string (cpp_hashnode *hashnode)
+ {
+ return (const char *)hashnode->ident.str;
+ }
+};
+
+/* Specialization of best_match<> for finding the closest preprocessor
+ macro to a given identifier. */
+
+class best_macro_match : public best_match<tree, cpp_hashnode *>
+{
+ public:
+ best_macro_match (tree goal, edit_distance_t best_distance_so_far,
+ cpp_reader *reader);
+};
+
+#endif /* C_SPELLCHECK_H */
diff --git a/support/cpp/gcc/c-family/c-target-def.h b/support/cpp/gcc/c-family/c-target-def.h
new file mode 100644
index 000000000..ab1e50f78
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-target-def.h
@@ -0,0 +1,21 @@
+/* Default initializers for C-family target hooks.
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "c-family/c-target-hooks-def.h"
+#include "tree.h"
+#include "c-family/c-common.h"
+#include "hooks.h"
diff --git a/support/cpp/gcc/c-family/c-target-hooks-def.h b/support/cpp/gcc/c-family/c-target-hooks-def.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-target-hooks-def.h
diff --git a/support/cpp/gcc/c-family/c-target.def b/support/cpp/gcc/c-family/c-target.def
new file mode 100644
index 000000000..141dcf307
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-target.def
@@ -0,0 +1,116 @@
+/* Target hook definitions for C-family front ends.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* See target-hooks-macros.h for details of macros that should be
+ provided by the including file, and how to use them here. */
+#include "target-hooks-macros.h"
+
+#undef HOOK_TYPE
+#define HOOK_TYPE "C Target Hook"
+
+HOOK_VECTOR (TARGETCM_INITIALIZER, gcc_targetcm)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+/* Handle target switch CODE (an OPT_* value). ARG is the argument
+ passed to the switch; it is NULL if no argument was. VALUE is the
+ value of ARG if CODE specifies a UInteger option, otherwise it is
+ 1 if the positive form of the switch was used and 0 if the negative
+ form was. Return true if the switch was valid. */
+DEFHOOK
+(handle_c_option,
+ "",
+ bool, (size_t code, const char *arg, int value),
+ default_handle_c_option)
+
+/* Targets may provide a string object type that can be used within
+ and between C, C++, and Objective-C dialects. */
+
+DEFHOOK
+(objc_construct_string_object,
+ "Targets may provide a string object type that can be used within\n\
+and between C, C++ and their respective Objective-C dialects.\n\
+A string object might, for example, embed encoding and length information.\n\
+These objects are considered opaque to the compiler and handled as references.\n\
+An ideal implementation makes the composition of the string object\n\
+match that of the Objective-C @code{NSString} (@code{NXString} for GNUStep),\n\
+allowing efficient interworking between C-only and Objective-C code.\n\
+If a target implements string objects then this hook should return a\n\
+reference to such an object constructed from the normal `C' string\n\
+representation provided in @var{string}.\n\
+At present, the hook is used by Objective-C only, to obtain a\n\
+ common-format string object when the target provides one.",
+ tree, (tree string),
+ NULL)
+
+DEFHOOK
+(objc_declare_unresolved_class_reference,
+ "Declare that Objective C class @var{classname} is referenced\n\
+by the current TU.",
+ void, (const char *classname),
+ NULL)
+
+DEFHOOK
+(objc_declare_class_definition,
+ "Declare that Objective C class @var{classname} is defined\n\
+by the current TU.",
+ void, (const char *classname),
+ NULL)
+
+DEFHOOK
+(string_object_ref_type_p,
+ "If a target implements string objects then this hook should return\n\
+@code{true} if @var{stringref} is a valid reference to such an object.",
+ bool, (const_tree stringref),
+ hook_bool_const_tree_false)
+
+DEFHOOK
+(check_string_object_format_arg,
+ "If a target implements string objects then this hook should\n\
+provide a facility to check the function arguments in @var{args_list}\n\
+against the format specifiers in @var{format_arg} where the type of\n\
+@var{format_arg} is one recognized as a valid string reference type.",
+ void, (tree format_arg, tree args_list),
+ NULL)
+
+DEFHOOK
+(c_preinclude,
+ "Define this hook to return the name of a header file to be included at\n\
+the start of all compilations, as if it had been included with\n\
+@code{#include <@var{file}>}. If this hook returns @code{NULL}, or is\n\
+not defined, or the header is not found, or if the user specifies\n\
+@option{-ffreestanding} or @option{-nostdinc}, no header is included.\n\
+\n\
+This hook can be used together with a header provided by the system C\n\
+library to implement ISO C requirements for certain macros to be\n\
+predefined that describe properties of the whole implementation rather\n\
+than just the compiler.",
+ const char *, (void),
+ hook_constcharptr_void_null)
+
+DEFHOOK
+(cxx_implicit_extern_c,
+ "Define this hook to add target-specific C++ implicit extern C functions.\n\
+If this function returns true for the name of a file-scope function, that\n\
+function implicitly gets extern \"C\" linkage rather than whatever language\n\
+linkage the declaration would normally have. An example of such function\n\
+is WinMain on Win32 targets.",
+ bool, (const char*),
+ NULL)
+
+HOOK_VECTOR_END (C90_EMPTY_HACK)
diff --git a/support/cpp/gcc/c-family/c-target.h b/support/cpp/gcc/c-family/c-target.h
new file mode 100644
index 000000000..ee2a0fec2
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-target.h
@@ -0,0 +1,35 @@
+/* Data structure definitions for target-specific C-family behavior.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+#ifndef GCC_C_TARGET_H
+#define GCC_C_TARGET_H
+
+#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
+#define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS;
+#define DEFHOOK_UNDOC DEFHOOK
+#define HOOKSTRUCT(FRAGMENT) FRAGMENT
+
+#include "c-target.def"
+
+/* Each target can provide their own. */
+extern struct gcc_targetcm targetcm;
+
+#endif /* GCC_C_TARGET_H */
diff --git a/support/cpp/gcc/c-family/c-ubsan.h b/support/cpp/gcc/c-family/c-ubsan.h
new file mode 100644
index 000000000..2f31ba36d
--- /dev/null
+++ b/support/cpp/gcc/c-family/c-ubsan.h
@@ -0,0 +1,34 @@
+/* UndefinedBehaviorSanitizer, undefined behavior detector.
+ Copyright (C) 2013-2022 Free Software Foundation, Inc.
+ Contributed by Marek Polacek <polacek@redhat.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.
+
+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_C_UBSAN_H
+#define GCC_C_UBSAN_H
+
+extern tree ubsan_instrument_division (location_t, tree, tree);
+extern tree ubsan_instrument_shift (location_t, enum tree_code, tree, tree);
+extern tree ubsan_instrument_vla (location_t, tree);
+extern tree ubsan_instrument_return (location_t);
+extern tree ubsan_instrument_bounds (location_t, tree, tree *, bool);
+extern bool ubsan_array_ref_instrumented_p (const_tree);
+extern void ubsan_maybe_instrument_array_ref (tree *, bool);
+extern void ubsan_maybe_instrument_reference (tree *);
+extern void ubsan_maybe_instrument_member_call (tree, bool);
+
+#endif /* GCC_C_UBSAN_H */
diff --git a/support/cpp/gcc/c-family/c.opt b/support/cpp/gcc/c-family/c.opt
new file mode 100644
index 000000000..b32941157
--- /dev/null
+++ b/support/cpp/gcc/c-family/c.opt
@@ -0,0 +1,2503 @@
+; Options for the C, ObjC, C++ and ObjC++ front ends.
+; Copyright (C) 2003-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/>.
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+Language
+C
+
+Language
+ObjC
+
+Language
+C++
+
+Language
+ObjC++
+
+-all-warnings
+C ObjC C++ ObjC++ Warning Alias(Wall)
+
+-ansi
+C ObjC C++ ObjC++ Alias(ansi)
+
+-assert
+C ObjC C++ ObjC++ Separate Alias(A) MissingArgError(assertion missing after %qs)
+
+-assert=
+C ObjC C++ ObjC++ Joined Alias(A) MissingArgError(assertion missing after %qs)
+
+-comments
+C ObjC C++ ObjC++ Alias(C)
+
+-comments-in-macros
+C ObjC C++ ObjC++ Alias(CC)
+
+-define-macro
+C ObjC C++ ObjC++ Separate Alias(D) MissingArgError(macro name missing after %qs)
+
+-define-macro=
+C ObjC C++ ObjC++ Joined Alias(D) MissingArgError(macro name missing after %qs)
+
+-dependencies
+C ObjC C++ ObjC++ Alias(M)
+
+-dump
+C ObjC C++ ObjC++ Separate Alias(d)
+
+-dump=
+C ObjC C++ ObjC++ Joined Alias(d)
+
+-imacros
+C ObjC C++ ObjC++ Separate Alias(imacros) MissingArgError(missing filename after %qs)
+
+-imacros=
+C ObjC C++ ObjC++ Joined Alias(imacros) MissingArgError(missing filename after %qs)
+
+-include
+C ObjC C++ ObjC++ Separate Alias(include) MissingArgError(missing filename after %qs)
+
+-include=
+C ObjC C++ ObjC++ Joined Alias(include) MissingArgError(missing filename after %qs)
+
+-include-barrier
+C ObjC C++ ObjC++ Alias(I, -)
+
+-include-directory
+C ObjC C++ ObjC++ Separate Alias(I) MissingArgError(missing path after %qs)
+
+-include-directory=
+C ObjC C++ ObjC++ Joined Alias(I) MissingArgError(missing path after %qs)
+
+-include-directory-after
+C ObjC C++ ObjC++ Separate Alias(idirafter) MissingArgError(missing path after %qs)
+
+-include-directory-after=
+C ObjC C++ ObjC++ Joined Alias(idirafter) MissingArgError(missing path after %qs)
+
+-include-prefix
+C ObjC C++ ObjC++ Separate Alias(iprefix)
+
+-include-prefix=
+C ObjC C++ ObjC++ JoinedOrMissing Alias(iprefix)
+
+-include-with-prefix
+C ObjC C++ ObjC++ Separate Alias(iwithprefix)
+
+-include-with-prefix=
+C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix)
+
+-include-with-prefix-after
+C ObjC C++ ObjC++ Separate Alias(iwithprefix)
+
+-include-with-prefix-after=
+C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefix)
+
+-include-with-prefix-before
+C ObjC C++ ObjC++ Separate Alias(iwithprefixbefore)
+
+-include-with-prefix-before=
+C ObjC C++ ObjC++ JoinedOrMissing Alias(iwithprefixbefore)
+
+-no-integrated-cpp
+Driver Alias(no-integrated-cpp)
+
+-no-line-commands
+C ObjC C++ ObjC++ Alias(P)
+
+-no-standard-includes
+C ObjC C++ ObjC++ Alias(nostdinc)
+
+-no-warnings
+C ObjC C++ ObjC++ Alias(w)
+
+-output
+C ObjC C++ ObjC++ Separate Alias(o)
+
+-output=
+C ObjC C++ ObjC++ Joined Alias(o)
+
+-output-pch=
+C ObjC C++ ObjC++ Joined Separate
+
+-pedantic
+C ObjC C++ ObjC++ Alias(pedantic)
+
+-preprocess
+C ObjC C++ ObjC++ Undocumented Alias(E)
+
+-print-missing-file-dependencies
+C ObjC C++ ObjC++ Alias(MG)
+
+-trace-includes
+C ObjC C++ ObjC++ Alias(H)
+
+-traditional
+Driver Alias(traditional)
+
+-traditional-cpp
+C ObjC C++ ObjC++ Alias(traditional-cpp)
+
+-trigraphs
+C ObjC C++ ObjC++ Alias(trigraphs)
+
+-undefine-macro
+C ObjC C++ ObjC++ Separate Alias(U) MissingArgError(macro name missing after %qs)
+
+-undefine-macro=
+C ObjC C++ ObjC++ Joined Alias(U) MissingArgError(macro name missing after %qs)
+
+-user-dependencies
+C ObjC C++ ObjC++ Alias(MM)
+
+-verbose
+Common C ObjC C++ ObjC++ Alias(v)
+
+-write-dependencies
+C ObjC C++ ObjC++ NoDriverArg Separate Alias(MD) MissingArgError(missing filename after %qs)
+
+-write-user-dependencies
+C ObjC C++ ObjC++ NoDriverArg Separate Alias(MMD) MissingArgError(missing filename after %qs)
+
+A
+C ObjC C++ ObjC++ Joined Separate MissingArgError(assertion missing after %qs)
+-A<question>=<answer> Assert the <answer> to <question>. Putting '-' before <question> disables the <answer> to <question>.
+
+C
+C ObjC C++ ObjC++
+Do not discard comments.
+
+CC
+C ObjC C++ ObjC++
+Do not discard comments in macro expansions.
+
+D
+C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
+-D<macro>[=<val>] Define a <macro> with <val> as its value. If just <macro> is given, <val> is taken to be 1.
+
+E
+C ObjC C++ ObjC++ Undocumented Var(flag_preprocess_only)
+
+F
+Driver C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+-F <dir> Add <dir> to the end of the main framework include path.
+
+fgimple
+C Var(flag_gimple) Init(0)
+Enable parsing GIMPLE.
+
+H
+C ObjC C++ ObjC++
+Print the name of header files as they are used.
+
+I
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+-I <dir> Add <dir> to the end of the main include path.
+
+M
+C ObjC C++ ObjC++
+Generate make dependencies.
+
+MD
+C ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
+Generate make dependencies and compile.
+
+MF
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
+-MF <file> Write dependency output to the given file.
+
+MG
+C ObjC C++ ObjC++
+Treat missing header files as generated files.
+
+MM
+C ObjC C++ ObjC++
+Like -M but ignore system header files.
+
+MMD
+C ObjC C++ ObjC++ NoDriverArg Separate MissingArgError(missing filename after %qs)
+Like -MD but ignore system header files.
+
+Mmodules
+C++
+Generate C++ Module dependency information.
+
+Mno-modules
+C++
+; undocumented
+
+MP
+C ObjC C++ ObjC++
+Generate phony targets for all headers.
+
+MQ
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
+-MQ <target> Add a target that may require quoting.
+
+MT
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after %qs)
+-MT <target> Add a target that does not require quoting.
+
+P
+C ObjC C++ ObjC++
+Do not generate #line directives.
+
+U
+C ObjC C++ ObjC++ Joined Separate MissingArgError(macro name missing after %qs)
+-U<macro> Undefine <macro>.
+
+WNSObject-attribute
+C ObjC C++ ObjC++ LTO Var(warn_nsobject_attribute) Warning Init(1)
+Warn if the NSObject attribute is applied to a non-typedef.
+
+Wabi
+C ObjC C++ ObjC++ LTO Var(warn_abi) Warning
+Warn about things that will change when compiling with an ABI-compliant compiler.
+
+Wabi=
+C ObjC C++ ObjC++ LTO Joined RejectNegative UInteger Warning
+Warn about things that change between the current -fabi-version and the specified version.
+
+Wabi-tag
+C++ ObjC++ Var(warn_abi_tag) Warning
+Warn if a subobject has an abi_tag attribute that the complete object type does not have.
+
+Wpsabi
+C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Warning Undocumented LangEnabledBy(C ObjC C++ ObjC++,Wabi)
+
+Wabsolute-value
+C ObjC Var(warn_absolute_value) Warning EnabledBy(Wextra)
+Warn on suspicious calls of standard functions computing absolute values.
+
+Waddress
+C ObjC C++ ObjC++ Var(warn_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious uses of memory addresses.
+
+Enum
+Name(warn_aligned_new_level) Type(int) UnknownError(argument %qs to %<-Waligned-new%> not recognized)
+
+EnumValue
+Enum(warn_aligned_new_level) String(none) Value(0)
+
+EnumValue
+Enum(warn_aligned_new_level) String(global) Value(1)
+
+EnumValue
+Enum(warn_aligned_new_level) String(all) Value(2)
+
+Waligned-new
+C++ ObjC++ Alias(Waligned-new=,global,none)
+Warn about 'new' of type with extended alignment without -faligned-new.
+
+Waligned-new=
+C++ ObjC++ Var(warn_aligned_new) Enum(warn_aligned_new_level) Joined RejectNegative Warning LangEnabledBy(C++ ObjC++,Wall,1,0)
+-Waligned-new=[none|global|all] Warn even if 'new' uses a class member allocation function.
+
+Wall
+C ObjC C++ ObjC++ Warning
+Enable most warning messages.
+
+Walloca
+C ObjC C++ ObjC++ Var(warn_alloca) Warning
+Warn on any use of alloca.
+
+Walloc-size-larger-than=
+C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Joined Host_Wide_Int ByteSize Warning Init(HOST_WIDE_INT_MAX)
+-Walloc-size-larger-than=<bytes> Warn for calls to allocation functions that
+attempt to allocate objects larger than the specified number of bytes.
+
+Wno-alloc-size-larger-than
+C ObjC C++ LTO ObjC++ Alias(Walloc-size-larger-than=,18446744073709551615EiB,none) Warning
+Disable Walloc-size-larger-than= warning. Equivalent to Walloc-size-larger-than=<SIZE_MAX> or larger.
+
+Walloc-zero
+C ObjC C++ ObjC++ Var(warn_alloc_zero) Warning
+Warn for calls to allocation functions that specify zero bytes.
+
+Walloca-larger-than=
+C ObjC C++ LTO ObjC++ Var(warn_alloca_limit) Warning Joined Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX)
+-Walloca-larger-than=<number> Warn on unbounded uses of
+alloca, and on bounded uses of alloca whose bound can be larger than
+<number> bytes.
+
+Wno-alloca-larger-than
+C ObjC C++ LTO ObjC++ Alias(Walloca-larger-than=,18446744073709551615EiB,none) Warning
+Disable Walloca-larger-than= warning. Equivalent to Walloca-larger-than=<SIZE_MAX> or larger.
+
+Warray-bounds=
+LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0)
+; in common.opt
+
+Warray-compare
+C ObjC C++ ObjC++ Var(warn_array_compare) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall)
+Warn about comparisons between two operands of array type.
+
+Warray-parameter
+C ObjC C++ ObjC++ Warning Alias(Warray-parameter=, 2, 0)
+Warn about mismatched declarations of array parameters and unsafe accesses to them.
+
+Warray-parameter=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_array_parameter) IntegerRange(0, 2) LangEnabledBy(C ObjC C++ ObjC++,Wall, 2, 0) Warning
+Warn about mismatched declarations of array parameters and unsafe accesses to them.
+
+Wzero-length-bounds
+C ObjC C++ ObjC++ Var(warn_zero_length_bounds) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about accesses to interior zero-length array members.
+
+Wassign-intercept
+ObjC ObjC++ Var(warn_assign_intercept) Warning
+Warn whenever an Objective-C assignment is being intercepted by the garbage collector.
+
+Wbad-function-cast
+C ObjC Var(warn_bad_function_cast) Warning
+Warn about casting functions to incompatible types.
+
+Wbidi-chars
+C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none)
+;
+
+Wbidi-chars=
+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level) EnumSet
+-Wbidi-chars=[none|unpaired|any|ucn] Warn about UTF-8 bidirectional control characters.
+
+; Required for these enum values.
+SourceInclude
+cpplib.h
+
+Enum
+Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none) Set(1)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired) Set(1)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any) Set(1)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(ucn) Value(bidirectional_ucn) Set(2)
+
+Wbool-compare
+C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about boolean expression compared with an integer value different from true/false.
+
+Wbool-operation
+C ObjC C++ ObjC++ Var(warn_bool_op) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about certain operations on boolean expressions.
+
+Wframe-address
+C ObjC C++ ObjC++ Var(warn_frame_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn when __builtin_frame_address or __builtin_return_address is used unsafely.
+
+Wbuiltin-declaration-mismatch
+C ObjC C++ ObjC++ Var(warn_builtin_declaration_mismatch) Init(1) Warning
+Warn when a built-in function is declared with the wrong signature.
+
+Wbuiltin-macro-redefined
+C ObjC C++ ObjC++ CPP(warn_builtin_macro_redefined) CppReason(CPP_W_BUILTIN_MACRO_REDEFINED) Var(cpp_warn_builtin_macro_redefined) Init(1) Warning
+Warn when a built-in preprocessor macro is undefined or redefined.
+
+Wc11-c2x-compat
+C ObjC CPP(cpp_warn_c11_c2x_compat) CppReason(CPP_W_C11_C2X_COMPAT) Var(warn_c11_c2x_compat) Init(-1) Warning
+Warn about features not present in ISO C11, but present in ISO C2X.
+
+Wc90-c99-compat
+C ObjC CPP(cpp_warn_c90_c99_compat) CppReason(CPP_W_C90_C99_COMPAT) Var(warn_c90_c99_compat) Init(-1) Warning
+Warn about features not present in ISO C90, but present in ISO C99.
+
+Wc99-c11-compat
+C ObjC Var(warn_c99_c11_compat) Init(-1) Warning
+Warn about features not present in ISO C99, but present in ISO C11.
+
+Wc++-compat
+C ObjC Var(warn_cxx_compat) CPP(warn_cxx_operator_names) CppReason(CPP_W_CXX_OPERATOR_NAMES) Init(0) Warning
+Warn about C constructs that are not in the common subset of C and C++.
+
+Wc++0x-compat
+C++ ObjC++ Warning Alias(Wc++11-compat) Undocumented
+
+Wc++11-compat
+C++ ObjC++ Var(warn_cxx11_compat) Warning LangEnabledBy(C++ ObjC++,Wall) Init(0) CPP(cpp_warn_cxx11_compat) CppReason(CPP_W_CXX11_COMPAT)
+Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 2011.
+
+Wc++14-compat
+C++ ObjC++ Var(warn_cxx14_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn about C++ constructs whose meaning differs between ISO C++ 2011 and ISO C++ 2014.
+
+Wc++1z-compat
+C++ ObjC++ Warning Alias(Wc++17-compat) Undocumented
+
+Wc++17-compat
+C++ ObjC++ Var(warn_cxx17_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn about C++ constructs whose meaning differs between ISO C++ 2014 and ISO C++ 2017.
+
+Wc++2a-compat
+C++ ObjC++ Warning Alias(Wc++20-compat) Undocumented
+
+Wc++20-compat
+C++ ObjC++ Var(warn_cxx20_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn about C++ constructs whose meaning differs between ISO C++ 2017 and ISO C++ 2020.
+
+Wc++11-extensions
+C++ ObjC++ Var(warn_cxx11_extensions) Warning Init(1)
+Warn about C++11 constructs in code compiled with an older standard.
+
+Wc++14-extensions
+C++ ObjC++ Var(warn_cxx14_extensions) Warning Init(1)
+Warn about C++14 constructs in code compiled with an older standard.
+
+Wc++17-extensions
+C++ ObjC++ Var(warn_cxx17_extensions) Warning Init(1)
+Warn about C++17 constructs in code compiled with an older standard.
+
+Wc++20-extensions
+C++ ObjC++ Var(warn_cxx20_extensions) Warning Init(1)
+Warn about C++20 constructs in code compiled with an older standard.
+
+Wc++23-extensions
+C++ ObjC++ Var(warn_cxx23_extensions) Warning Init(1)
+Warn about C++23 constructs in code compiled with an older standard.
+
+Wcast-function-type
+C ObjC C++ ObjC++ Var(warn_cast_function_type) Warning EnabledBy(Wextra)
+Warn about casts between incompatible function types.
+
+Wcast-qual
+C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
+Warn about casts which discard qualifiers.
+
+Wcatch-value
+C++ ObjC++ Warning Alias(Wcatch-value=, 1, 0)
+Warn about catch handlers of non-reference type.
+
+Wcatch-value=
+C++ ObjC++ Var(warn_catch_value) Warning Joined RejectNegative UInteger LangEnabledBy(C++ ObjC++,Wall, 1, 0) IntegerRange(0, 3)
+Warn about catch handlers of non-reference type.
+
+Wchar-subscripts
+C ObjC C++ ObjC++ Var(warn_char_subscripts) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about subscripts whose type is \"char\".
+
+Wchkp
+C ObjC C++ ObjC++ Warning WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+Wclobbered
+C ObjC C++ ObjC++ Var(warn_clobbered) Warning EnabledBy(Wextra)
+Warn about variables that might be changed by \"longjmp\" or \"vfork\".
+
+Wcomma-subscript
+C++ ObjC++ Var(warn_comma_subscript) Warning
+Warn about uses of a comma operator within a subscripting expression.
+
+Wcomment
+C ObjC C++ ObjC++ CPP(warn_comments) CppReason(CPP_W_COMMENTS) Var(cpp_warn_comment) Init(0) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about possibly nested block comments, and C++ comments spanning more than one physical line.
+
+Wcomments
+C ObjC C++ ObjC++ Warning Alias(Wcomment)
+Synonym for -Wcomment.
+
+Wconditionally-supported
+C++ ObjC++ Var(warn_conditionally_supported) Warning
+Warn for conditionally-supported constructs.
+
+Wconversion
+C ObjC C++ ObjC++ Var(warn_conversion) Warning
+Warn for implicit type conversions that may change a value.
+
+Wconversion-null
+C++ ObjC++ Var(warn_conversion_null) Init(1) Warning
+Warn for converting NULL from/to a non-pointer type.
+
+Wcpp
+C ObjC C++ ObjC++ CppReason(CPP_W_WARNING_DIRECTIVE)
+; Documented in common.opt
+
+Wctad-maybe-unsupported
+C++ ObjC++ Var(warn_ctad_maybe_unsupported) Warning
+Warn when performing class template argument deduction on a type with no
+deduction guides.
+
+Wctor-dtor-privacy
+C++ ObjC++ Var(warn_ctor_dtor_privacy) Warning
+Warn when all constructors and destructors are private.
+
+Wdangling-else
+C ObjC C++ ObjC++ Var(warn_dangling_else) Warning LangEnabledBy(C ObjC C++ ObjC++,Wparentheses)
+Warn about dangling else.
+
+Wdangling-pointer
+C ObjC C++ LTO ObjC++ Alias(Wdangling-pointer=, 2, 0) Warning
+Warn for uses of pointers to auto variables whose lifetime has ended.
+
+Wdangling-pointer=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_dangling_pointer) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 2, 0) IntegerRange(0, 2)
+Warn for uses of pointers to auto variables whose lifetime has ended.
+
+Wdate-time
+C ObjC C++ ObjC++ CPP(warn_date_time) CppReason(CPP_W_DATE_TIME) Var(cpp_warn_date_time) Init(0) Warning
+Warn about __TIME__, __DATE__ and __TIMESTAMP__ usage.
+
+Wdeclaration-after-statement
+C ObjC Var(warn_declaration_after_statement) Init(-1) Warning
+Warn when a declaration is found after a statement.
+
+Wdelete-incomplete
+C++ ObjC++ Var(warn_delete_incomplete) Init(1) Warning
+Warn when deleting a pointer to incomplete type.
+
+Wdelete-non-virtual-dtor
+C++ ObjC++ Var(warn_delnonvdtor) Warning LangEnabledBy(C++ ObjC++,Wall || Weffc++)
+Warn about deleting polymorphic objects with non-virtual destructors.
+
+Wdeprecated
+C C++ ObjC ObjC++ CPP(cpp_warn_deprecated) CppReason(CPP_W_DEPRECATED)
+; Documented in common.opt
+
+Wdeprecated-copy
+C++ ObjC++ Var(warn_deprecated_copy) Warning LangEnabledBy(C++ ObjC++, Wextra)
+Mark implicitly-declared copy operations as deprecated if the class has a
+user-provided copy operation.
+
+Wdeprecated-copy-dtor
+C++ ObjC++ Var(warn_deprecated_copy, 2) Warning
+Mark implicitly-declared copy operations as deprecated if the class has a
+user-provided copy operation or destructor.
+
+Wdeprecated-enum-enum-conversion
+C++ ObjC++ Var(warn_deprecated_enum_enum_conv) Warning
+Warn about deprecated arithmetic conversions on operands of enumeration types.
+
+Wdeprecated-enum-float-conversion
+C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning
+Warn about deprecated arithmetic conversions on operands where one is of enumeration
+type and the other is of a floating-point type.
+
+Wdesignated-init
+C ObjC Var(warn_designated_init) Init(1) Warning
+Warn about positional initialization of structs requiring designated initializers.
+
+Wdiscarded-array-qualifiers
+C ObjC Var(warn_discarded_array_qualifiers) Init(1) Warning
+Warn if qualifiers on arrays which are pointer targets are discarded.
+
+Wdiscarded-qualifiers
+C ObjC Var(warn_discarded_qualifiers) Init(1) Warning
+Warn if type qualifiers on pointers are discarded.
+
+Wdiv-by-zero
+C ObjC C++ ObjC++ Var(warn_div_by_zero) Init(1) Warning
+Warn about compile-time integer division by zero.
+
+Wduplicated-branches
+C ObjC C++ ObjC++ Var(warn_duplicated_branches) Init(0) Warning
+Warn about duplicated branches in if-else statements.
+
+Wduplicated-cond
+C ObjC C++ ObjC++ Var(warn_duplicated_cond) Init(0) Warning
+Warn about duplicated conditions in an if-else-if chain.
+
+Weffc++
+C++ ObjC++ Var(warn_ecpp) Warning
+Warn about violations of Effective C++ style rules.
+
+Wempty-body
+C ObjC C++ ObjC++ Var(warn_empty_body) Warning EnabledBy(Wextra)
+Warn about an empty body in an if or else statement.
+
+Wendif-labels
+C ObjC C++ ObjC++ CPP(warn_endif_labels) CppReason(CPP_W_ENDIF_LABELS) Var(cpp_warn_endif_labels) Init(1) Warning LangEnabledBy(C ObjC C++ ObjC++,Wpedantic)
+Warn about stray tokens after #else and #endif.
+
+Wenum-compare
+C ObjC C++ ObjC++ Var(warn_enum_compare) Init(-1) Warning LangEnabledBy(C ObjC,Wall || Wc++-compat)
+Warn about comparison of different enum types.
+
+Wenum-conversion
+C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra)
+Warn about implicit conversion of enum types.
+
+Werror
+C ObjC C++ ObjC++
+; Documented in common.opt
+
+Werror-implicit-function-declaration
+C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration)
+This switch is deprecated; use -Werror=implicit-function-declaration instead.
+
+Wexceptions
+C++ ObjC++ Var(warn_exceptions) Init(1) Warning
+Warn when an exception handler is shadowed by another handler.
+
+Wextra
+C ObjC C++ ObjC++ Warning
+; in common.opt
+
+Wextra-semi
+C++ ObjC++ Var(warn_extra_semi) Warning
+Warn about semicolon after in-class function definition.
+
+Wfloat-conversion
+C ObjC C++ ObjC++ Var(warn_float_conversion) Warning LangEnabledBy(C ObjC C++ ObjC++,Wconversion)
+Warn for implicit type conversions that cause loss of floating point precision.
+
+Wfloat-equal
+C ObjC C++ ObjC++ Var(warn_float_equal) Warning
+Warn if testing floating point numbers for equality.
+
+Wformat
+C ObjC C++ ObjC++ Warning Alias(Wformat=, 1, 0)
+Warn about printf/scanf/strftime/strfmon format string anomalies.
+
+Wformat-contains-nul
+C ObjC C++ ObjC++ Var(warn_format_contains_nul) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
+Warn about format strings that contain NUL bytes.
+
+Wformat-diag
+C ObjC C++ ObjC++ Var(warn_format_diag) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
+Warn about GCC format strings with strings unsuitable for diagnostics.
+
+Wformat-extra-args
+C ObjC C++ ObjC++ Var(warn_format_extra_args) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 1, 0)
+Warn if passing too many arguments to a function for its format string.
+
+Wformat-nonliteral
+C ObjC C++ ObjC++ Var(warn_format_nonliteral) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0)
+Warn about format strings that are not literals.
+
+Wformat-overflow
+C ObjC C++ LTO ObjC++ Warning Alias(Wformat-overflow=, 1, 0) IntegerRange(0, 2)
+Warn about function calls with format strings that write past the end
+of the destination region. Same as -Wformat-overflow=1.
+
+Wformat-security
+C ObjC C++ ObjC++ Var(warn_format_security) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=, warn_format >= 2, 0)
+Warn about possible security problems with format functions.
+
+Wformat-signedness
+C ObjC C++ ObjC++ Var(warn_format_signedness) Warning
+Warn about sign differences with format functions.
+
+Wformat-truncation
+C ObjC C++ LTO ObjC++ Warning Alias(Wformat-truncation=, 1, 0)
+Warn about calls to snprintf and similar functions that truncate output.
+Same as -Wformat-truncation=1.
+
+Wformat-y2k
+C ObjC C++ ObjC++ Var(warn_format_y2k) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 2, 0)
+Warn about strftime formats yielding 2-digit years.
+
+Wformat-zero-length
+C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning LangEnabledBy(C ObjC C++ ObjC++,Wformat=,warn_format >= 1, 0)
+Warn about zero-length formats.
+
+Wformat=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_format) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) IntegerRange(0, 2)
+Warn about printf/scanf/strftime/strfmon format string anomalies.
+
+Wformat-overflow=
+C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_overflow) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2)
+Warn about function calls with format strings that write past the end
+of the destination region.
+
+Wformat-truncation=
+C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2)
+Warn about calls to snprintf and similar functions that truncate output.
+
+Wif-not-aligned
+C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning
+Warn when the field in a struct is not aligned.
+
+Wignored-qualifiers
+C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra)
+Warn whenever type qualifiers are ignored.
+
+Wignored-attributes
+C C++ Var(warn_ignored_attributes) Init(1) Warning
+Warn whenever attributes are ignored.
+
+Winaccessible-base
+C++ ObjC++ Var(warn_inaccessible_base) Init(1) Warning
+Warn when a base is inaccessible in derived due to ambiguity.
+
+Wincompatible-pointer-types
+C ObjC Var(warn_incompatible_pointer_types) Init(1) Warning
+Warn when there is a conversion between pointers that have incompatible types.
+
+Winfinite-recursion
+C ObjC C++ LTO ObjC++ Var(warn_infinite_recursion) Warning LangEnabledBy(C ObjC C++ LTO ObjC++, Wall)
+Warn for infinitely recursive calls.
+
+Waddress-of-packed-member
+C ObjC C++ ObjC++ Var(warn_address_of_packed_member) Init(1) Warning
+Warn when the address of packed member of struct or union is taken.
+
+Winit-self
+C ObjC C++ ObjC++ Var(warn_init_self) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn about variables which are initialized to themselves.
+
+Winit-list-lifetime
+C++ ObjC++ Var(warn_init_list) Warning Init(1)
+Warn about uses of std::initializer_list that can result in dangling pointers.
+
+Winterference-size
+C++ ObjC++ Var(warn_interference_size) Warning Init(1)
+Warn about nonsensical values of --param destructive-interference-size or
+constructive-interference-size.
+
+Wimplicit
+C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall)
+Warn about implicit declarations.
+
+Wimplicit-fallthrough=
+LangEnabledBy(C ObjC C++ ObjC++,Wextra,3,0)
+; in common.opt
+
+Wdouble-promotion
+C ObjC C++ ObjC++ Var(warn_double_promotion) Warning
+Warn about implicit conversions from \"float\" to \"double\".
+
+Wexpansion-to-defined
+C ObjC C++ ObjC++ CPP(warn_expansion_to_defined) CppReason(CPP_W_EXPANSION_TO_DEFINED) Var(cpp_warn_expansion_to_defined) Init(0) Warning EnabledBy(Wextra || Wpedantic)
+Warn if \"defined\" is used outside #if.
+
+Wimplicit-function-declaration
+C ObjC Var(warn_implicit_function_declaration) Init(-1) Warning LangEnabledBy(C ObjC,Wimplicit)
+Warn about implicit function declarations.
+
+Wimplicit-int
+C ObjC Var(warn_implicit_int) Init(-1) Warning LangEnabledBy(C ObjC,Wimplicit)
+Warn when a declaration does not specify a type.
+
+Wimport
+C ObjC C++ ObjC++ Undocumented Ignore
+
+Winherited-variadic-ctor
+C++ ObjC++ Var(warn_inh_var_ctor) Init(1) Warning
+Warn about C++11 inheriting constructors when the base has a variadic constructor.
+
+Wint-conversion
+C ObjC Var(warn_int_conversion) Init(1) Warning
+Warn about incompatible integer to pointer and pointer to integer conversions.
+
+Wint-in-bool-context
+C ObjC C++ ObjC++ Var(warn_int_in_bool_context) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for suspicious integer expressions in boolean context.
+
+Wint-to-pointer-cast
+C ObjC C++ ObjC++ Var(warn_int_to_pointer_cast) Init(1) Warning
+Warn when there is a cast to a pointer from an integer of a different size.
+
+Winvalid-offsetof
+C++ ObjC++ Var(warn_invalid_offsetof) Init(1) Warning
+Warn about invalid uses of the \"offsetof\" macro.
+
+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.
+
+Wjump-misses-init
+C ObjC Var(warn_jump_misses_init) Warning LangEnabledby(C ObjC,Wc++-compat)
+Warn when a jump misses a variable initialization.
+
+Wliteral-suffix
+C++ ObjC++ CPP(warn_literal_suffix) CppReason(CPP_W_LITERAL_SUFFIX) Var(cpp_warn_literal_suffix) Init(1) Warning
+Warn when a string or character literal is followed by a ud-suffix which does not begin with an underscore.
+
+Wlogical-op
+C ObjC C++ ObjC++ Var(warn_logical_op) Init(0) Warning
+Warn when a logical operator is suspiciously always evaluating to true or false.
+
+Wlogical-not-parentheses
+C ObjC C++ ObjC++ Var(warn_logical_not_paren) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn when logical not is used on the left hand side operand of a comparison.
+
+Wlong-long
+C ObjC C++ ObjC++ CPP(cpp_warn_long_long) CppReason(CPP_W_LONG_LONG) Var(warn_long_long) Init(-1) Warning LangEnabledBy(C ObjC,Wc90-c99-compat)
+Do not warn about using \"long long\" when -pedantic.
+
+Wmain
+C ObjC C++ ObjC++ Var(warn_main) Init(-1) Warning LangEnabledBy(C ObjC,Wall, 2, 0)
+Warn about suspicious declarations of \"main\".
+
+Wmain
+LangEnabledBy(C ObjC C++ ObjC++,Wpedantic, 2, 0)
+;
+
+Wmemset-transposed-args
+C ObjC C++ ObjC++ Var(warn_memset_transposed_args) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious calls to memset where the third argument is constant literal zero and the second is not.
+
+Wmemset-elt-size
+C ObjC C++ ObjC++ Var(warn_memset_elt_size) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious calls to memset where the third argument contains the number of elements not multiplied by the element size.
+
+Wmisleading-indentation
+C C++ Common Var(warn_misleading_indentation) Warning LangEnabledBy(C C++,Wall)
+Warn when the indentation of the code does not reflect the block structure.
+
+Wmismatched-dealloc
+C ObjC C++ ObjC++ Var(warn_mismatched_alloc) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for deallocation calls with arguments returned from mismatched allocation
+functions.
+
+Wmismatched-new-delete
+C++ ObjC++ Var(warn_mismatched_new_delete) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn for mismatches between calls to operator new or delete and the corresponding
+call to the allocation or deallocation function.
+
+Wmismatched-tags
+C++ ObjC++ Var(warn_mismatched_tags) Warning
+Warn when a class is redeclared or referenced using a mismatched class-key.
+
+Wmissing-braces
+C ObjC C++ ObjC++ Var(warn_missing_braces) Warning LangEnabledBy(C ObjC,Wall)
+Warn about possibly missing braces around initializers.
+
+Wmissing-declarations
+C ObjC C++ ObjC++ Var(warn_missing_declarations) Warning
+Warn about global functions without previous declarations.
+
+Wmissing-field-initializers
+C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra)
+Warn about missing fields in struct initializers.
+
+Wmissing-requires
+C++ ObjC++ Var(warn_missing_requires) Init(1) Warning
+Warn about likely missing requires keyword.
+
+Wmissing-template-keyword
+C++ ObjC++ Var(warn_missing_template_keyword) Init(1) Warning
+Warn when the template keyword is missing after a member access token in a dependent member access expression if that member is a template.
+
+Wmultistatement-macros
+C ObjC C++ ObjC++ Var(warn_multistatement_macros) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about unsafe macros expanding to multiple statements used as a body of a clause such as if, else, while, switch, or for.
+
+Wmultiple-inheritance
+C++ ObjC++ Var(warn_multiple_inheritance) Warning
+Warn on direct multiple inheritance.
+
+Wnamespaces
+C++ ObjC++ Var(warn_namespaces) Warning
+Warn on namespace definition.
+
+Wpacked-not-aligned
+C ObjC C++ ObjC++ Var(warn_packed_not_aligned) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn when fields in a struct with the packed attribute are misaligned.
+
+Wrange-loop-construct
+C++ ObjC++ Var(warn_range_loop_construct) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn when a range-based for-loop is creating unnecessary copies.
+
+Wredundant-tags
+C++ ObjC++ Var(warn_redundant_tags) Warning
+Warn when a class or enumerated type is referenced using a redundant class-key.
+
+Wsized-deallocation
+C++ ObjC++ Var(warn_sized_deallocation) Warning EnabledBy(Wextra)
+Warn about missing sized deallocation functions.
+
+Wsizeof-pointer-div
+C ObjC C++ ObjC++ Var(warn_sizeof_pointer_div) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious divisions of two sizeof expressions that don't work correctly with pointers.
+
+Wsizeof-array-div
+C ObjC C++ ObjC++ Var(warn_sizeof_array_div) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about divisions of two sizeof operators when the first one is applied
+to an array and the divisor does not equal the size of the array element.
+
+Wsizeof-pointer-memaccess
+C ObjC C++ ObjC++ Var(warn_sizeof_pointer_memaccess) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about suspicious length parameters to certain string functions if the argument uses sizeof.
+
+Wsizeof-array-argument
+C ObjC C++ ObjC++ Var(warn_sizeof_array_argument) Warning Init(1)
+Warn when sizeof is applied on a parameter declared as an array.
+
+Wstring-compare
+C ObjC C++ LTO ObjC++ Warning Var(warn_string_compare) Warning LangEnabledBy(C ObjC C++ ObjC++, Wextra)
+Warn about calls to strcmp and strncmp used in equality expressions that
+are necessarily true or false due to the length of one and size of the other
+argument.
+
+Wstringop-overflow
+C ObjC C++ LTO ObjC++ Warning Alias(Wstringop-overflow=, 2, 0)
+Warn about buffer overflow in string manipulation functions like memcpy
+and strcpy.
+
+Wstringop-overflow=
+C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Init(2) Warning LangEnabledBy(C ObjC C++ LTO ObjC++, Wall, 2, 0) IntegerRange(0, 4)
+Under the control of Object Size type, warn about buffer overflow in string
+manipulation functions like memcpy and strcpy.
+
+Wstringop-overread
+C ObjC C++ LTO ObjC++ Var(warn_stringop_overread) Init(1) Warning LangEnabledBy(C ObjC C++ LTO ObjC++, Wall)
+Warn about reading past the end of a source array in string manipulation functions like memchr and memcpy.
+
+Wstringop-truncation
+C ObjC C++ LTO ObjC++ Var(warn_stringop_truncation) Warning Init (1) LangEnabledBy(C ObjC C++ LTO ObjC++, Wall)
+Warn about truncation in string manipulation functions like strncat and strncpy.
+
+Wsuggest-attribute=format
+C ObjC C++ ObjC++ Var(warn_suggest_attribute_format) Warning
+Warn about functions which might be candidates for format attributes.
+
+Wsuggest-override
+C++ ObjC++ Var(warn_override) Warning
+Suggest that the override keyword be used when the declaration of a virtual
+function overrides another.
+
+Wswitch
+C ObjC C++ ObjC++ Var(warn_switch) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about enumerated switches, with no default, missing a case.
+
+Wswitch-default
+C ObjC C++ ObjC++ Var(warn_switch_default) Warning
+Warn about enumerated switches missing a \"default:\" statement.
+
+Wswitch-enum
+C ObjC C++ ObjC++ Var(warn_switch_enum) Warning
+Warn about all enumerated switches missing a specific case.
+
+Wswitch-bool
+C ObjC C++ ObjC++ Var(warn_switch_bool) Warning Init(1)
+Warn about switches with boolean controlling expression.
+
+Wswitch-outside-range
+C ObjC C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1)
+Warn about switch values that are outside of the switch's type range.
+
+Wtemplates
+C++ ObjC++ Var(warn_templates) Warning
+Warn on primary template declaration.
+
+Wmissing-attributes
+C ObjC C++ ObjC++ Var(warn_missing_attributes) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about declarations of entities that may be missing attributes
+that related entities have been declared with.
+
+Wmissing-format-attribute
+C ObjC C++ ObjC++ Warning Alias(Wsuggest-attribute=format)
+;
+
+Wmissing-include-dirs
+C ObjC C++ ObjC++ CPP(warn_missing_include_dirs) CppReason(CPP_W_MISSING_INCLUDE_DIRS) Var(cpp_warn_missing_include_dirs) Init(0) Warning
+Warn about user-specified include directories that do not exist.
+
+Wmissing-parameter-type
+C ObjC Var(warn_missing_parameter_type) Warning EnabledBy(Wextra)
+Warn about function parameters declared without a type specifier in K&R-style functions.
+
+Wmissing-prototypes
+C ObjC Var(warn_missing_prototypes) Warning
+Warn about global functions without prototypes.
+
+Wmudflap
+C ObjC C++ ObjC++ WarnRemoved
+
+Wmultichar
+C ObjC C++ ObjC++ CPP(warn_multichar) CppReason(CPP_W_MULTICHAR) Var(cpp_warn_multichar) Init(0) Warning
+Warn about use of multi-character character constants.
+
+Wnarrowing
+C ObjC C++ ObjC++ Warning Var(warn_narrowing) Init(-1) LangEnabledBy(C++ ObjC++,Wall || Wc++11-compat)
+Warn about narrowing conversions within { } that are ill-formed in C++11.
+
+Wnested-externs
+C ObjC Var(warn_nested_externs) Warning
+Warn about \"extern\" declarations not at file scope.
+
+Wnoexcept
+C++ ObjC++ Var(warn_noexcept) Warning
+Warn when a noexcept expression evaluates to false even though the expression can't actually throw.
+
+Wnoexcept-type
+C++ ObjC++ Warning Var(warn_noexcept_type) LangEnabledBy(C++ ObjC++,Wabi || Wc++17-compat)
+Warn if C++17 noexcept function type will change the mangled name of a symbol.
+
+Wnon-template-friend
+C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning
+Warn when non-templatized friend functions are declared within a template.
+
+Wclass-conversion
+C++ ObjC++ Var(warn_class_conversion) Init(1) Warning
+Warn when a conversion function will never be called due to the type it converts to.
+
+Wclass-memaccess
+C++ ObjC++ Var(warn_class_memaccess) Warning LangEnabledBy(C++ ObjC++, Wall)
+Warn for unsafe raw memory writes to objects of class types.
+
+Wnon-virtual-dtor
+C++ ObjC++ Var(warn_nonvdtor) Warning LangEnabledBy(C++ ObjC++,Weffc++)
+Warn about non-virtual destructors.
+
+Wnonnull
+C ObjC C++ LTO ObjC++ Var(warn_nonnull) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=,warn_format >= 1,0)
+Warn about NULL being passed to argument slots marked as requiring non-NULL.
+
+Wnonnull
+C ObjC C++ LTO ObjC++ LangEnabledBy(C ObjC C++ LTO ObjC++,Wall)
+;
+
+Wnonnull-compare
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall)
+;
+
+Wnormalized
+C ObjC C++ ObjC++ Warning Alias(Wnormalized=,nfc,none)
+;
+
+Wnormalized=
+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(warn_normalize) CppReason(CPP_W_NORMALIZE) Init(normalized_C) Var(cpp_warn_normalize) Enum(cpp_normalize_level)
+-Wnormalized=[none|id|nfc|nfkc] Warn about non-normalized Unicode strings.
+
+; Required for these enum values.
+SourceInclude
+cpplib.h
+
+Enum
+Name(cpp_normalize_level) Type(int) UnknownError(argument %qs to %<-Wnormalized%> not recognized)
+
+EnumValue
+Enum(cpp_normalize_level) String(none) Value(normalized_none)
+
+EnumValue
+Enum(cpp_normalize_level) String(nfkc) Value(normalized_KC)
+
+EnumValue
+Enum(cpp_normalize_level) String(id) Value(normalized_identifier_C)
+
+EnumValue
+Enum(cpp_normalize_level) String(nfc) Value(normalized_C)
+
+Wobjc-root-class
+ObjC ObjC++ Var(warn_objc_root_class) Warning Init(1)
+Warn if a class interface has no superclass. Root classes may use an attribute
+to suppress this warning.
+
+Wold-style-cast
+C++ ObjC++ Var(warn_old_style_cast) Warning
+Warn if a C-style cast is used in a program.
+
+Wold-style-declaration
+C ObjC Var(warn_old_style_declaration) Warning EnabledBy(Wextra)
+Warn for obsolescent usage in a declaration.
+
+Wold-style-definition
+C ObjC Var(warn_old_style_definition) Init(-1) Warning
+Warn if an old-style parameter definition is used.
+
+Wopenacc-parallelism
+C C++ Var(warn_openacc_parallelism) Warning
+Warn about potentially suboptimal choices related to OpenACC parallelism.
+
+Wopenmp-simd
+C C++ Var(warn_openmp_simd) Warning LangEnabledBy(C C++,Wall)
+Warn if a simd directive is overridden by the vectorizer cost model.
+
+Woverlength-strings
+C ObjC C++ ObjC++ Var(warn_overlength_strings) Warning LangEnabledBy(C ObjC C++ ObjC++,Wpedantic)
+Warn if a string is longer than the maximum portable length specified by the standard.
+
+Woverloaded-virtual
+C++ ObjC++ Var(warn_overloaded_virtual) Warning
+Warn about overloaded virtual function names.
+
+Woverride-init
+C ObjC Var(warn_override_init) Warning EnabledBy(Wextra)
+Warn about overriding initializers without side effects.
+
+Woverride-init-side-effects
+C ObjC Var(warn_override_init_side_effects) Init(1) Warning
+Warn about overriding initializers with side effects.
+
+Wpacked-bitfield-compat
+C ObjC C++ ObjC++ Var(warn_packed_bitfield_compat) Init(-1) Warning
+Warn about packed bit-fields whose offset changed in GCC 4.4.
+
+Wparentheses
+C ObjC C++ ObjC++ Var(warn_parentheses) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about possibly missing parentheses.
+
+Wpedantic
+C ObjC C++ ObjC++ CPP(cpp_pedantic) CppReason(CPP_W_PEDANTIC) Warning
+; Documented in common.opt
+
+Wpessimizing-move
+C++ ObjC++ Var(warn_pessimizing_move) Warning LangEnabledBy(C++ ObjC++, Wall)
+Warn about calling std::move on a local object in a return statement preventing copy elision.
+
+Wpmf-conversions
+C++ ObjC++ Var(warn_pmf2ptr) Init(1) Warning
+Warn when converting the type of pointers to member functions.
+
+Wpointer-arith
+C ObjC C++ ObjC++ Var(warn_pointer_arith) Warning LangEnabledBy(C ObjC C++ ObjC++,Wpedantic)
+Warn about function pointer arithmetic.
+
+Wpointer-sign
+C ObjC Var(warn_pointer_sign) Warning LangEnabledBy(C ObjC,Wall || Wpedantic)
+Warn when a pointer differs in signedness in an assignment.
+
+Wpointer-compare
+C ObjC C++ ObjC++ Var(warn_pointer_compare) Init(1) Warning
+Warn when a pointer is compared with a zero character constant.
+
+Wpointer-to-int-cast
+C ObjC Var(warn_pointer_to_int_cast) Init(1) Warning
+Warn when a pointer is cast to an integer of a different size.
+
+Wpragmas
+C ObjC C++ ObjC++ Var(warn_pragmas) Init(1) Warning
+Warn about misuses of pragmas.
+
+Wprio-ctor-dtor
+C ObjC C++ ObjC++ Var(warn_prio_ctor_dtor) Init(1) Warning
+Warn if constructor or destructors with priorities from 0 to 100 are used.
+
+Wproperty-assign-default
+ObjC ObjC++ Var(warn_property_assign_default) Init(1) Warning
+Warn if a property for an Objective-C object has no assign semantics specified.
+
+Wprotocol
+ObjC ObjC++ Var(warn_protocol) Init(1) Warning
+Warn if inherited methods are unimplemented.
+
+Wplacement-new
+C++ Warning Alias(Wplacement-new=, 1, 0)
+Warn for placement new expressions with undefined behavior.
+
+Wplacement-new=
+C++ Joined RejectNegative UInteger Var(warn_placement_new) Init(-1) Warning IntegerRange(0, 2)
+Warn for placement new expressions with undefined behavior.
+
+Wredundant-decls
+C ObjC C++ ObjC++ Var(warn_redundant_decls) Warning
+Warn about multiple declarations of the same object.
+
+Wredundant-move
+C++ ObjC++ Var(warn_redundant_move) Warning LangEnabledBy(C++ ObjC++,Wextra)
+Warn about redundant calls to std::move.
+
+Wregister
+C++ ObjC++ Var(warn_register) Warning
+Warn about uses of register storage specifier.
+
+Wreorder
+C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn when the compiler reorders code.
+
+Wreturn-type
+C ObjC C++ ObjC++ Var(warn_return_type) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Init(-1)
+Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++).
+
+Wscalar-storage-order
+C ObjC C++ ObjC++ Var(warn_scalar_storage_order) Init(1) Warning
+Warn on suspicious constructs involving reverse scalar storage order.
+
+Wselector
+ObjC ObjC++ Var(warn_selector) Warning
+Warn if a selector has multiple methods.
+
+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.
+
+Wshadow-ivar
+ObjC ObjC++ Var(warn_shadow_ivar) EnabledBy(Wshadow) Init(1) Warning
+Warn if a local declaration hides an instance variable.
+
+Wshift-overflow
+C ObjC C++ ObjC++ Warning Alias(Wshift-overflow=, 1, 0)
+Warn if left shift of a signed value overflows.
+
+Wshift-overflow=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_shift_overflow) Init(-1) Warning IntegerRange(0, 2)
+Warn if left shift of a signed value overflows.
+
+Wshift-count-negative
+C ObjC C++ ObjC++ Var(warn_shift_count_negative) Init(1) Warning
+Warn if shift count is negative.
+
+Wshift-count-overflow
+C ObjC C++ ObjC++ Var(warn_shift_count_overflow) Init(1) Warning
+Warn if shift count >= width of type.
+
+Wshift-negative-value
+C ObjC C++ ObjC++ Var(warn_shift_negative_value) Init(-1) Warning
+Warn if left shifting a negative value.
+
+Warith-conversion
+C ObjC C++ ObjC++ Var(warn_arith_conv) Warning
+Warn if conversion of the result of arithmetic might change the value even though converting the operands cannot.
+
+Wsign-compare
+C ObjC C++ ObjC++ Var(warn_sign_compare) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn about signed-unsigned comparisons.
+
+Wsign-compare
+C ObjC C++ ObjC++ EnabledBy(Wextra)
+;
+
+Wsign-conversion
+C ObjC C++ ObjC++ Var(warn_sign_conversion) Warning LangEnabledBy(C ObjC,Wconversion)
+Warn for implicit type conversions between signed and unsigned integers.
+
+Wsign-promo
+C++ ObjC++ Var(warn_sign_promo) Warning
+Warn when overload promotes from unsigned to signed.
+
+Wstrict-null-sentinel
+C++ ObjC++ Warning Var(warn_strict_null_sentinel)
+Warn about uncasted NULL used as sentinel.
+
+Wstrict-prototypes
+C ObjC Var(warn_strict_prototypes) Warning
+Warn about unprototyped function declarations.
+
+Wstrict-aliasing=
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 3, 0) IntegerRange(0, 3)
+;
+
+Wstrict-overflow=
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0) IntegerRange(0, 5)
+;
+
+Wstrict-selector-match
+ObjC ObjC++ Var(warn_strict_selector_match) Warning
+Warn if type signatures of candidate methods do not match exactly.
+
+Wsync-nand
+C C++ Var(warn_sync_nand) Init(1) Warning
+Warn when __sync_fetch_and_nand and __sync_nand_and_fetch built-in functions are used.
+
+Wsynth
+C++ ObjC++ Var(warn_synth) Warning
+Deprecated. This switch has no effect.
+
+Wsystem-headers
+C ObjC C++ ObjC++ Warning
+; Documented in common.opt
+
+Wtautological-compare
+C ObjC C++ ObjC++ Var(warn_tautological_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn if a comparison always evaluates to true or false.
+
+Wterminate
+C++ ObjC++ Warning Var(warn_terminate) Init(1)
+Warn if a throw expression will always result in a call to terminate().
+
+Wtraditional
+C ObjC CPP(cpp_warn_traditional) CppReason(CPP_W_TRADITIONAL) Var(warn_traditional) Init(0) Warning
+Warn about features not present in traditional C.
+
+Wtraditional-conversion
+C ObjC Var(warn_traditional_conversion) Warning
+Warn of prototypes causing type conversions different from what would happen in the absence of prototype.
+
+Wtrigraphs
+C ObjC C++ ObjC++ CPP(warn_trigraphs) CppReason(CPP_W_TRIGRAPHS) Var(cpp_warn_trigraphs) Init(2) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn if trigraphs are encountered that might affect the meaning of the program.
+
+Wundeclared-selector
+ObjC ObjC++ Var(warn_undeclared_selector) Warning
+Warn about @selector()s without previously declared methods.
+
+Wundef
+C ObjC C++ ObjC++ CPP(warn_undef) CppReason(CPP_W_UNDEF) Var(cpp_warn_undef) Init(0) Warning
+Warn if an undefined macro is used in an #if directive.
+
+Wuninitialized
+C ObjC C++ ObjC++ LTO LangEnabledBy(C ObjC C++ ObjC++ LTO,Wall)
+;
+
+Wmaybe-uninitialized
+C ObjC C++ ObjC++ LTO LangEnabledBy(C ObjC C++ ObjC++ LTO,Wall)
+;
+
+Wunknown-pragmas
+C ObjC C++ ObjC++ Warning Var(warn_unknown_pragmas) LangEnabledBy(C ObjC C++ ObjC++,Wall, 1, 0)
+Warn about unrecognized pragmas.
+
+Wunsuffixed-float-constants
+C ObjC Var(warn_unsuffixed_float_constants) Warning
+Warn about unsuffixed float constants.
+
+Wunused
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall)
+; documented in common.opt
+
+Wunused-local-typedefs
+C ObjC C++ ObjC++ Var(warn_unused_local_typedefs) Warning EnabledBy(Wunused)
+Warn when typedefs locally defined in a function are not used.
+
+Wunused-macros
+C ObjC C++ ObjC++ CppReason(CPP_W_UNUSED_MACROS) Var(cpp_warn_unused_macros) Warning
+Warn about macros defined in the main file that are not used.
+
+Wunused-result
+C ObjC C++ ObjC++ Var(warn_unused_result) Init(1) Warning
+Warn if a caller of a function, marked with attribute warn_unused_result, does not use its return value.
+
+Wunused-variable
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wunused)
+; documented in common.opt
+
+Wunused-const-variable
+C ObjC C++ ObjC++ Warning Alias(Wunused-const-variable=, 2, 0)
+Warn when a const variable is unused.
+
+Wunused-const-variable=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_unused_const_variable) Warning LangEnabledBy(C ObjC,Wunused-variable, 1, 0) IntegerRange(0, 2)
+Warn when a const variable is unused.
+
+; Defining this option here in addition to common.opt is necessary
+; in order for the default -Wall setting of -Wuse-after-free=2 to take
+; effect.
+
+Wuse-after-free=
+LangEnabledBy(C ObjC C++ LTO ObjC++, Wall,2,0)
+; in common.opt
+
+Wvariadic-macros
+C ObjC C++ ObjC++ CPP(warn_variadic_macros) CppReason(CPP_W_VARIADIC_MACROS) Var(cpp_warn_variadic_macros) Init(0) Warning LangEnabledBy(C ObjC C++ ObjC++,Wpedantic || Wtraditional)
+Warn about using variadic macros.
+
+Wvarargs
+C ObjC C++ ObjC++ Warning Var(warn_varargs) Init(1)
+Warn about questionable usage of the macros used to retrieve variable arguments.
+
+Wvexing-parse
+C++ ObjC++ Warning Var(warn_vexing_parse) Init(1)
+Warn about the most vexing parse syntactic ambiguity.
+
+Wvla
+C ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning
+Warn if a variable length array is used.
+
+Wvla-larger-than=
+C ObjC C++ LTO ObjC++ Var(warn_vla_limit) Warning Joined Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX)
+-Wvla-larger-than=<number> Warn on unbounded uses of variable-length
+arrays, and on bounded uses of variable-length arrays whose bound can be
+larger than <number> bytes.
+
+Wno-vla-larger-than
+C ObjC C++ LTO ObjC++ Alias(Wvla-larger-than=,18446744073709551615EiB,none) Warning
+Disable Wvla-larger-than= warning. Equivalent to Wvla-larger-than=<SIZE_MAX> or larger.
+
+Wvla-parameter
+C ObjC C++ ObjC++ Var(warn_vla_parameter) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn about mismatched declarations of VLA parameters.
+
+Wvolatile
+C++ ObjC++ Var(warn_volatile) Warning
+Warn about deprecated uses of volatile qualifier.
+
+Wvolatile-register-var
+C ObjC C++ ObjC++ Var(warn_volatile_register_var) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
+Warn when a register variable is declared volatile.
+
+Wvirtual-inheritance
+C++ ObjC++ Var(warn_virtual_inheritance) Warning
+Warn on direct virtual inheritance.
+
+Wvirtual-move-assign
+C++ ObjC++ Var(warn_virtual_move_assign) Warning Init(1)
+Warn if a virtual base has a non-trivial move assignment operator.
+
+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.
+
+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.
+
+Wuseless-cast
+C++ ObjC++ Var(warn_useless_cast) Warning
+Warn about useless casts.
+
+Wsubobject-linkage
+C++ ObjC++ Var(warn_subobject_linkage) Warning Init(1)
+Warn if a class type has a base or a field whose type uses the anonymous namespace or depends on a type with no linkage.
+
+Wduplicate-decl-specifier
+C ObjC Var(warn_duplicate_decl_specifier) Warning LangEnabledBy(C ObjC,Wall)
+Warn when a declaration has duplicate const, volatile, restrict or _Atomic specifier.
+
+Wrestrict
+C ObjC C++ ObjC++ Var(warn_restrict) Warning LangEnabledBy(C ObjC C++ ObjC++, Wall)
+Warn when an argument passed to a restrict-qualified parameter aliases with
+another argument.
+
+ansi
+C ObjC C++ ObjC++
+A synonym for -std=c89 (for C) or -std=c++98 (for C++).
+
+d
+C ObjC C++ ObjC++ Joined
+; Documented in common.opt. FIXME - what about -dI, -dD, -dN and -dD?
+
+fabi-compat-version=
+C++ ObjC++ Joined RejectNegative UInteger Var(flag_abi_compat_version) Init(-1)
+The version of the C++ ABI used for -Wabi warnings and link compatibility aliases.
+
+faccess-control
+C++ ObjC++ Var(flag_access_control) Init(1)
+Enforce class member access control semantics.
+
+fada-spec-parent=
+C ObjC C++ ObjC++ RejectNegative Joined Var(ada_specs_parent)
+-fada-spec-parent=unit Dump Ada specs as child units of given parent.
+
+faligned-new
+C++ ObjC++ Alias(faligned-new=,1,0)
+Support C++17 allocation of over-aligned types.
+
+faligned-new=
+C++ ObjC++ Joined RejectNegative Var(aligned_new_threshold) UInteger Init(-1)
+-faligned-new=<N> Use C++17 over-aligned type allocation for alignments greater than N.
+
+fall-virtual
+C++ ObjC++ WarnRemoved
+
+fallow-parameterless-variadic-functions
+C ObjC Var(flag_allow_parameterless_variadic_functions)
+Allow variadic functions without named parameter.
+
+falt-external-templates
+C++ ObjC++ WarnRemoved
+No longer supported.
+
+fasm
+C ObjC C++ ObjC++ Var(flag_no_asm, 0)
+Recognize the \"asm\" keyword.
+
+; Define extra predefined macros for use in libgcc.
+fbuilding-libgcc
+C ObjC C++ ObjC++ Undocumented Var(flag_building_libgcc)
+
+fbuiltin
+C ObjC C++ ObjC++ Var(flag_no_builtin, 0)
+Recognize built-in functions.
+
+fbuiltin-
+C ObjC C++ ObjC++ Joined
+
+fcanonical-system-headers
+C ObjC C++ ObjC++
+Where shorter, use canonicalized paths to systems headers.
+
+fchar8_t
+C++ ObjC++ Var(flag_char8_t) Init(-1)
+Enable the char8_t fundamental type and use it as the type for UTF-8 string
+and character literals.
+
+fcheck-pointer-bounds
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-check-incomplete-type
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-zero-input-bounds-for-main
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-first-field-has-own-bounds
+C ObjC C++ ObjC++ LTO WarnRemoved RejectNegative
+Removed in GCC 9. This switch has no effect.
+
+fchkp-narrow-bounds
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-narrow-to-innermost-array
+C ObjC C++ ObjC++ LTO WarnRemoved RejectNegative
+Removed in GCC 9. This switch has no effect.
+
+fchkp-flexible-struct-trailing-arrays
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-optimize
+C ObjC C++ ObjC++ LTO WarnRemoved
+
+fchkp-use-fast-string-functions
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-use-nochk-string-functions
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-use-static-bounds
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-use-static-const-bounds
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-treat-zero-dynamic-size-as-infinite
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-check-read
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-check-write
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-store-bounds
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-instrument-calls
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-instrument-marked-only
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fchkp-use-wrappers
+C ObjC C++ ObjC++ LTO WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+static-libmpx
+Driver WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+static-libmpxwrappers
+Driver WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+fcilkplus
+C ObjC C++ ObjC++ LTO Undocumented Ignore
+Removed in GCC 8. This switch has no effect.
+
+fconcepts
+C++ ObjC++ Var(flag_concepts)
+Enable support for C++ concepts.
+
+fconcepts-ts
+C++ ObjC++ Var(flag_concepts_ts) Init(0)
+Enable certain features present in the Concepts TS.
+
+fconcepts-diagnostics-depth=
+C++ ObjC++ Joined RejectNegative UInteger Var(concepts_diagnostics_max_depth) Init(1)
+Specify maximum error replay depth during recursive diagnosis of a constraint satisfaction failure.
+
+fcond-mismatch
+C ObjC C++ ObjC++
+Allow the arguments of the '?' operator to have different types.
+
+fconserve-space
+C++ ObjC++ Ignore
+Does nothing. Preserved for backward compatibility.
+
+fconstant-string-class=
+ObjC ObjC++ Joined MissingArgError(no class name specified with %qs)
+-fconst-string-class=<name> Use class <name> for constant strings.
+
+fconstexpr-depth=
+C++ ObjC++ Joined RejectNegative UInteger Var(max_constexpr_depth) Init(512)
+-fconstexpr-depth=<number> Specify maximum constexpr recursion depth.
+
+fconstexpr-cache-depth=
+C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_cache_depth) Init(8)
+-fconstexpr-cache-depth=<number> Specify maximum constexpr recursion cache depth.
+
+fconstexpr-fp-except
+C++ ObjC++ Var(flag_constexpr_fp_except) Init(0)
+Allow IEC559 floating point exceptions in constant expressions.
+
+fconstexpr-loop-limit=
+C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
+-fconstexpr-loop-limit=<number> Specify maximum constexpr loop iteration count.
+
+fconstexpr-ops-limit=
+C++ ObjC++ Joined RejectNegative Host_Wide_Int Var(constexpr_ops_limit) Init(33554432)
+-fconstexpr-ops-limit=<number> Specify maximum number of constexpr operations during a single constexpr evaluation.
+
+fcoroutines
+C++ LTO Var(flag_coroutines)
+Enable C++ coroutines (experimental).
+
+fdebug-cpp
+C ObjC C++ ObjC++
+Emit debug annotations during preprocessing.
+
+fdeduce-init-list
+C++ ObjC++ Ignore
+Does nothing. Preserved for backward compatibility.
+
+fdeclone-ctor-dtor
+C++ ObjC++ Var(flag_declone_ctor_dtor) Init(-1)
+Factor complex constructors and destructors to favor space over speed.
+
+fdefault-inline
+C++ ObjC++ Ignore
+Does nothing. Preserved for backward compatibility.
+
+fdiagnostics-show-template-tree
+C++ ObjC++ Var(flag_diagnostics_show_template_tree) Init(0)
+Print hierarchical comparisons when template types are mismatched.
+
+fdirectives-only
+C ObjC C++ ObjC++
+Preprocess directives only.
+
+fdollars-in-identifiers
+C ObjC C++ ObjC++
+Permit '$' as an identifier character.
+
+fmacro-prefix-map=
+C ObjC C++ ObjC++ Joined RejectNegative
+-fmacro-prefix-map=<old>=<new> Map one directory name to another in __FILE__, __BASE_FILE__, and __builtin_FILE().
+
+fdump-ada-spec
+C ObjC C++ ObjC++ RejectNegative Var(flag_dump_ada_spec)
+Write all declarations as Ada code transitively.
+
+fdump-ada-spec-slim
+C ObjC C++ ObjC++ RejectNegative Var(flag_dump_ada_spec_slim)
+Write all declarations as Ada code for the given file only.
+
+felide-constructors
+C++ ObjC++ Var(flag_elide_constructors) Init(1)
+
+felide-type
+C++ ObjC++ Var(flag_elide_type) Init(1)
+Do not elide common elements in template comparisons.
+
+fenforce-eh-specs
+C++ ObjC++ Var(flag_enforce_eh_specs) Init(1)
+Generate code to check exception specifications.
+
+fenum-int-equiv
+C++ ObjC++ WarnRemoved
+
+fexec-charset=
+C ObjC C++ ObjC++ Joined RejectNegative
+-fexec-charset=<cset> Convert all strings and character constants to character set <cset>.
+
+fextended-identifiers
+C ObjC C++ ObjC++
+Permit universal character names (\\u and \\U) in identifiers.
+
+finput-charset=
+C ObjC C++ ObjC++ Joined RejectNegative
+-finput-charset=<cset> Specify the default character set for source files.
+
+fextern-tls-init
+C++ ObjC++ Var(flag_extern_tls_init) Init(-1)
+Support dynamic initialization of thread-local variables in a different translation unit.
+
+fexternal-templates
+C++ ObjC++ WarnRemoved
+
+ffold-simple-inlines
+C++ ObjC++ Optimization Var(flag_fold_simple_inlines)
+Fold calls to simple inline functions.
+
+ffor-scope
+C++ ObjC++ WarnRemoved
+
+ffreestanding
+C ObjC C++ ObjC++
+Do not assume that standard C libraries and \"main\" exist.
+
+fgnu-keywords
+C++ ObjC++ Var(flag_no_gnu_keywords, 0)
+Recognize GNU-defined keywords.
+
+fgnu-runtime
+ObjC ObjC++ LTO RejectNegative Var(flag_next_runtime,0) Init(NEXT_OBJC_RUNTIME)
+Generate code for GNU runtime environment.
+
+fgnu89-inline
+C ObjC Var(flag_gnu89_inline) Init(-1)
+Use traditional GNU semantics for inline functions.
+
+fguiding-decls
+C++ ObjC++ WarnRemoved
+
+fhandle-exceptions
+C++ ObjC++ Optimization Alias(fexceptions) Warn({%<-fhandle-exceptions%> has been renamed %<-fexceptions%> (and is now on by default)})
+
+fhonor-std
+C++ ObjC++ WarnRemoved
+
+fhosted
+C ObjC
+Assume normal C execution environment.
+
+fhuge-objects
+C++ ObjC++ WarnRemoved
+No longer supported.
+
+fimplement-inlines
+C++ ObjC++ Var(flag_implement_inlines) Init(1)
+Export functions even if they can be inlined.
+
+fimplicit-constexpr
+C++ ObjC++ Var(flag_implicit_constexpr)
+Make inline functions constexpr by default.
+
+fimplicit-inline-templates
+C++ ObjC++ Var(flag_implicit_inline_templates) Init(1)
+Emit implicit instantiations of inline templates.
+
+fimplicit-templates
+C++ ObjC++ Var(flag_implicit_templates) Init(1)
+Emit implicit instantiations of templates.
+
+fnew-inheriting-ctors
+C++ ObjC++ Var(flag_new_inheriting_ctors) Init(1)
+Implement C++17 inheriting constructor semantics.
+
+ffriend-injection
+C++ ObjC++ WarnRemoved
+
+fkeep-inline-dllexport
+C C++ ObjC ObjC++ Var(flag_keep_inline_dllexport) Init(1) Condition(TARGET_DLLIMPORT_DECL_ATTRIBUTES)
+Don't emit dllexported inline functions unless needed.
+
+flabels-ok
+C++ ObjC++ WarnRemoved
+
+flax-vector-conversions
+C ObjC C++ ObjC++ Var(flag_lax_vector_conversions)
+Allow implicit conversions between vectors with differing numbers of subparts and/or differing element types.
+
+fmodules-ts
+C++ ObjC++ Var(flag_modules) Integer Init(0)
+Enable C++ modules-ts (experimental).
+
+fno-modules
+C++ ObjC++ Undocumented RejectNegative Var(flag_modules,0) Integer
+;; undocumented
+
+fmodule-header
+C++ ObjC RejectNegative Var(flag_header_unit,0) Integer
+Enable C++ header module (experimental).
+
+fmodule-header=
+C++ ObjC++ Joined RejectNegative Undocumented
+
+fmodule-implicit-inline
+C++ ObjC++ Var(flag_module_implicit_inline,0) Integer
+Member functions defined within their class are inline in module purview.
+
+fmodule-only
+C++ ObjC RejectNegative Var(flag_module_only) Integer
+Only emit Compiled Module Interface.
+
+fmodule-mapper=
+C++ ObjC++ Joined RejectNegative MissingArgError(missing mapper)
+Mapper for module to CMI files.
+
+fmodule-lazy
+C++ ObjC++ Var(flag_module_lazy) Init(1)
+Enable lazy module importing.
+
+fmodule-version-ignore
+C++ ObjC Var(flag_module_version_ignore) Integer
+; undocumented, Very dangerous, but occasionally useful
+
+Winvalid-imported-macros
+C++ ObjC++ Var(warn_imported_macros) Warning
+Warn about macros that have conflicting header units definitions.
+
+flang-info-include-translate
+C++ Var(note_include_translate_yes)
+Note #include directives translated to import declarations.
+
+flang-info-include-translate-not
+C++ Var(note_include_translate_no)
+Note #include directives not translated to import declarations, and not known to be textual.
+
+flang-info-include-translate=
+C++ Joined RejectNegative MissingArgError(missing header name)
+Note a #include translation of a specific header.
+
+flang-info-module-cmi
+C++ Var(note_module_cmi_yes)
+Note Compiled Module Interface pathnames.
+
+flang-info-module-cmi=
+C++ Joined RejectNegative MissingArgError(missing module name)
+Note Compiled Module Interface pathname of a specific module or header-unit.
+
+fmax-include-depth=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger
+fmax-include-depth=<number> Set the maximum depth of the nested #include.
+
+fms-extensions
+C ObjC C++ ObjC++ Var(flag_ms_extensions)
+Don't warn about uses of Microsoft extensions.
+
+fmudflap
+C ObjC C++ ObjC++ WarnRemoved
+
+fmudflapth
+C ObjC C++ ObjC++ WarnRemoved
+
+fmudflapir
+C ObjC C++ ObjC++ WarnRemoved
+
+fname-mangling-version-
+C++ ObjC++ Joined WarnRemoved
+
+fnew-abi
+C++ ObjC++ WarnRemoved
+
+fnew-ttp-matching
+C++ ObjC++ Var(flag_new_ttp)
+Implement resolution of DR 150 for matching of template template arguments.
+
+fnext-runtime
+ObjC ObjC++ LTO RejectNegative Var(flag_next_runtime)
+Generate code for NeXT (Apple Mac OS X) runtime environment.
+
+fnil-receivers
+ObjC ObjC++ Var(flag_nil_receivers) Init(1)
+Assume that receivers of Objective-C messages may be nil.
+
+flocal-ivars
+ObjC ObjC++ Var(flag_local_ivars) Init(1)
+Allow access to instance variables as if they were local declarations within instance method implementations.
+
+fivar-visibility=
+ObjC ObjC++ Joined RejectNegative Enum(ivar_visibility) Var(default_ivar_visibility) Init(IVAR_VISIBILITY_PROTECTED)
+-fvisibility=[private|protected|public|package] Set the default symbol visibility.
+
+Enum
+Name(ivar_visibility) Type(enum ivar_visibility) UnknownError(unrecognized ivar visibility value %qs)
+
+EnumValue
+Enum(ivar_visibility) String(private) Value(IVAR_VISIBILITY_PRIVATE)
+
+EnumValue
+Enum(ivar_visibility) String(protected) Value(IVAR_VISIBILITY_PROTECTED)
+
+EnumValue
+Enum(ivar_visibility) String(public) Value(IVAR_VISIBILITY_PUBLIC)
+
+EnumValue
+Enum(ivar_visibility) String(package) Value(IVAR_VISIBILITY_PACKAGE)
+
+fnonansi-builtins
+C++ ObjC++ Var(flag_no_nonansi_builtin, 0)
+
+fnonnull-objects
+C++ ObjC++ WarnRemoved
+
+fnothrow-opt
+C++ ObjC++ Optimization Var(flag_nothrow_opt)
+Treat a throw() exception specification as noexcept to improve code size.
+
+fobjc-abi-version=
+ObjC ObjC++ LTO Joined RejectNegative UInteger Var(flag_objc_abi)
+Specify which ABI to use for Objective-C family code and meta-data generation.
+
+; Generate special '- .cxx_construct' and '- .cxx_destruct' methods
+; to initialize any non-POD ivars in Objective-C++ classes.
+fobjc-call-cxx-cdtors
+ObjC++ Var(flag_objc_call_cxx_cdtors)
+Generate special Objective-C methods to initialize/destroy non-POD C++ ivars, if needed.
+
+fobjc-direct-dispatch
+ObjC ObjC++ Var(flag_objc_direct_dispatch)
+Allow fast jumps to the message dispatcher.
+
+; Nonzero means that we will allow new ObjC exception syntax (@throw,
+; @try, etc.) in source code.
+fobjc-exceptions
+ObjC ObjC++ Var(flag_objc_exceptions)
+Enable Objective-C exception and synchronization syntax.
+
+fobjc-gc
+ObjC ObjC++ LTO Var(flag_objc_gc)
+Enable garbage collection (GC) in Objective-C/Objective-C++ programs.
+
+fobjc-nilcheck
+ObjC ObjC++ Var(flag_objc_nilcheck,1)
+Enable inline checks for nil receivers with the NeXT runtime and ABI version 2.
+
+; Nonzero means that we generate NeXT setjmp based exceptions.
+fobjc-sjlj-exceptions
+ObjC ObjC++ Var(flag_objc_sjlj_exceptions) Init(-1)
+Enable Objective-C setjmp exception handling runtime.
+
+fobjc-std=objc1
+ObjC ObjC++ Var(flag_objc1_only)
+Conform to the Objective-C 1.0 language as implemented in GCC 4.0.
+
+fopenacc
+C ObjC C++ ObjC++ LTO Var(flag_openacc)
+Enable OpenACC.
+
+fopenacc-dim=
+C ObjC C++ ObjC++ LTO Joined Var(flag_openacc_dims)
+Specify default OpenACC compute dimensions.
+
+fopenmp
+C ObjC C++ ObjC++ LTO Var(flag_openmp)
+Enable OpenMP (implies -frecursive in Fortran).
+
+fopenmp-simd
+C ObjC C++ ObjC++ Var(flag_openmp_simd)
+Enable OpenMP's SIMD directives.
+
+foperator-names
+C++ ObjC++
+Recognize C++ keywords like \"compl\" and \"xor\".
+
+foptional-diags
+C++ ObjC++ Ignore
+Does nothing. Preserved for backward compatibility.
+
+fpch-deps
+C ObjC C++ ObjC++
+
+fpch-preprocess
+C ObjC C++ ObjC++
+Look for and use PCH files even when preprocessing.
+
+fpermissive
+C++ ObjC++ Var(flag_permissive)
+Downgrade conformance errors to warnings.
+
+fplan9-extensions
+C ObjC Var(flag_plan9_extensions)
+Enable Plan 9 language extensions.
+
+fpreprocessed
+C ObjC C++ ObjC++
+Treat the input file as already preprocessed.
+
+ftrack-macro-expansion
+C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+; converted into ftrack-macro-expansion=
+
+ftrack-macro-expansion=
+C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+-ftrack-macro-expansion=<0|1|2> Track locations of tokens coming from macro expansion and display them in error messages.
+
+fpretty-templates
+C++ ObjC++ Var(flag_pretty_templates) Init(1)
+Do not pretty-print template specializations as the template signature followed by the arguments.
+
+fprintf-return-value
+C ObjC C++ ObjC++ LTO Optimization Var(flag_printf_return_value) Init(1)
+Treat known sprintf return values as constants.
+
+freplace-objc-classes
+ObjC ObjC++ LTO Var(flag_replace_objc_classes)
+Used in Fix-and-Continue mode to indicate that object files may be swapped in at runtime.
+
+frepo
+C++ ObjC++ WarnRemoved
+Removed in GCC 10. This switch has no effect.
+
+frtti
+C++ ObjC++ Optimization Var(flag_rtti) Init(1)
+Generate run time type descriptor information.
+
+fshort-enums
+C ObjC C++ ObjC++ LTO Optimization Var(flag_short_enums)
+Use the narrowest integer type possible for enumeration types.
+
+fshort-wchar
+C ObjC C++ ObjC++ LTO Optimization Var(flag_short_wchar)
+Force the underlying type for \"wchar_t\" to be \"unsigned short\".
+
+fsigned-bitfields
+C ObjC C++ ObjC++ Var(flag_signed_bitfields) Init(1)
+When \"signed\" or \"unsigned\" is not given make the bitfield signed.
+
+fsigned-char
+C ObjC C++ ObjC++ LTO Var(flag_signed_char)
+Make \"char\" signed by default.
+
+fsized-deallocation
+C++ ObjC++ Var(flag_sized_deallocation) Init(-1)
+Enable C++14 sized deallocation support.
+
+fsquangle
+C++ ObjC++ WarnRemoved
+
+fsso-struct=
+C ObjC Joined RejectNegative Enum(sso_struct) Var(default_sso) Init(SSO_NATIVE)
+-fsso-struct=[big-endian|little-endian|native] Set the default scalar storage order.
+
+Enum
+Name(sso_struct) Type(enum scalar_storage_order_kind) UnknownError(unrecognized scalar storage order value %qs)
+
+EnumValue
+Enum(sso_struct) String(big-endian) Value(SSO_BIG_ENDIAN)
+
+EnumValue
+Enum(sso_struct) String(little-endian) Value(SSO_LITTLE_ENDIAN)
+
+EnumValue
+Enum(sso_struct) String(native) Value(SSO_NATIVE)
+
+fstats
+C++ ObjC++ Var(flag_detailed_statistics)
+Display statistics accumulated during compilation.
+
+fstrict-enums
+C++ ObjC++ Optimization Var(flag_strict_enums)
+Assume that values of enumeration type are always within the minimum range of that type.
+
+fstrict-prototype
+C++ ObjC++ WarnRemoved
+
+fstrong-eval-order
+C++ ObjC++ Common Alias(fstrong-eval-order=, all, none)
+Follow the C++17 evaluation order requirements for assignment expressions,
+shift, member function calls, etc.
+
+fstrong-eval-order=
+C++ ObjC++ Common Var(flag_strong_eval_order) Joined Enum(strong_eval_order) RejectNegative Init(-1)
+Follow the C++17 evaluation order requirements for assignment expressions,
+shift, member function calls, etc.
+
+Enum
+Name(strong_eval_order) Type(int)
+
+EnumValue
+Enum(strong_eval_order) String(none) Value(0)
+
+EnumValue
+Enum(strong_eval_order) String(some) Value(1)
+
+EnumValue
+Enum(strong_eval_order) String(all) Value(2)
+
+ftemplate-backtrace-limit=
+C++ ObjC++ Joined RejectNegative UInteger Var(template_backtrace_limit) Init(10)
+Set the maximum number of template instantiation notes for a single warning or error.
+
+ftemplate-depth-
+C++ ObjC++ Joined RejectNegative Undocumented Alias(ftemplate-depth=)
+
+ftemplate-depth=
+C++ ObjC++ Joined RejectNegative UInteger
+-ftemplate-depth=<number> Specify maximum template instantiation depth.
+
+fthis-is-variable
+C++ ObjC++ WarnRemoved
+
+fthreadsafe-statics
+C++ ObjC++ Optimization Var(flag_threadsafe_statics) Init(1)
+-fno-threadsafe-statics Do not generate thread-safe code for initializing local statics.
+
+funsigned-bitfields
+C ObjC C++ ObjC++ Var(flag_signed_bitfields, 0)
+When \"signed\" or \"unsigned\" is not given make the bitfield unsigned.
+
+funsigned-char
+C ObjC C++ ObjC++ LTO Var(flag_signed_char, 0)
+Make \"char\" unsigned by default.
+
+fuse-cxa-atexit
+C++ ObjC++ Var(flag_use_cxa_atexit) Init(DEFAULT_USE_CXA_ATEXIT)
+Use __cxa_atexit to register destructors.
+
+fuse-cxa-get-exception-ptr
+C++ ObjC++ Var(flag_use_cxa_get_exception_ptr) Init(2)
+Use __cxa_get_exception_ptr in exception handling.
+
+fvisibility-inlines-hidden
+C++ ObjC++
+Marks all inlined functions and methods as having hidden visibility.
+
+fvisibility-ms-compat
+C++ ObjC++ Var(flag_visibility_ms_compat)
+Changes visibility to match Microsoft Visual Studio by default.
+
+fvtable-gc
+C++ ObjC++ WarnRemoved
+No longer supported.
+
+fvtable-thunks
+C++ ObjC++ WarnRemoved
+No longer supported.
+
+fweak
+C++ ObjC++ Var(flag_weak) Init(1)
+Emit common-like symbols as weak symbols.
+
+fwide-exec-charset=
+C ObjC C++ ObjC++ Joined RejectNegative
+-fwide-exec-charset=<cset> Convert all wide strings and character constants to character set <cset>.
+
+fworking-directory
+C ObjC C++ ObjC++ Var(flag_working_directory) Init(-1)
+Generate a #line directive pointing at the current working directory.
+
+fxref
+C++ ObjC++ WarnRemoved
+No longer supported.
+
+fzero-link
+ObjC ObjC++ Var(flag_zero_link)
+Generate lazy class lookup (via objc_getClass()) for use in Zero-Link mode.
+
+gen-decls
+ObjC ObjC++ Driver Var(flag_gen_declaration) RejectNegative
+Dump declarations to a .decl file.
+
+femit-struct-debug-baseonly
+C ObjC C++ ObjC++
+-femit-struct-debug-baseonly Aggressive reduced debug info for structs.
+
+femit-struct-debug-reduced
+C ObjC C++ ObjC++
+-femit-struct-debug-reduced Conservative reduced debug info for structs.
+
+femit-struct-debug-detailed=
+C ObjC C++ ObjC++ Joined
+-femit-struct-debug-detailed=<spec-list> Detailed reduced debug info for structs.
+
+fext-numeric-literals
+C++ ObjC++ Var(flag_ext_numeric_literals) Init(1)
+Interpret imaginary, fixed-point, or other gnu number suffix as the corresponding
+number literal rather than a user-defined number literal.
+
+idirafter
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+-idirafter <dir> Add <dir> to the end of the system include path.
+
+imacros
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
+-imacros <file> Accept definition of macros in <file>.
+
+imultilib
+C ObjC C++ ObjC++ Joined Separate
+-imultilib <dir> Set <dir> to be the multilib include subdirectory.
+
+include
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing filename after %qs)
+-include <file> Include the contents of <file> before other files.
+
+iprefix
+C ObjC C++ ObjC++ Joined Separate
+-iprefix <path> Specify <path> as a prefix for next two options.
+
+isysroot
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+-isysroot <dir> Set <dir> to be the system root directory.
+
+isystem
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+-isystem <dir> Add <dir> to the start of the system include path.
+
+iquote
+C ObjC C++ ObjC++ Joined Separate MissingArgError(missing path after %qs)
+-iquote <dir> Add <dir> to the end of the quote include path.
+
+iwithprefix
+C ObjC C++ ObjC++ Joined Separate
+-iwithprefix <dir> Add <dir> to the end of the system include path.
+
+iwithprefixbefore
+C ObjC C++ ObjC++ Joined Separate
+-iwithprefixbefore <dir> Add <dir> to the end of the main include path.
+
+lang-asm
+C Undocumented RejectDriver
+
+no-integrated-cpp
+Driver
+
+nostdinc
+C ObjC C++ ObjC++
+Do not search standard system include directories (those specified with -isystem will still be used).
+
+nostdinc++
+C++ ObjC++
+Do not search standard system include directories for C++.
+
+o
+C Joined Separate
+; Documented in common.opt
+
+pedantic
+C ObjC C++ ObjC++ Alias(Wpedantic)
+; Documented in common.opt
+
+print-objc-runtime-info
+ObjC ObjC++
+Generate C header of platform-specific features.
+
+remap
+C ObjC C++ ObjC++
+Remap file names when including files.
+
+std=c++98
+C++ ObjC++
+Conform to the ISO 1998 C++ standard revised by the 2003 technical corrigendum.
+
+std=c++03
+C++ ObjC++ Alias(std=c++98)
+Conform to the ISO 1998 C++ standard revised by the 2003 technical corrigendum.
+
+std=c++11
+C++ ObjC++
+Conform to the ISO 2011 C++ standard.
+
+std=c++0x
+C++ ObjC++ Alias(std=c++11) Undocumented
+Deprecated in favor of -std=c++11.
+
+std=c++1y
+C++ ObjC++ Alias(std=c++14) Undocumented
+Deprecated in favor of -std=c++14.
+
+std=c++14
+C++ ObjC++
+Conform to the ISO 2014 C++ standard.
+
+std=c++1z
+C++ ObjC++ Alias(std=c++17) Undocumented
+Deprecated in favor of -std=c++17.
+
+std=c++17
+C++ ObjC++
+Conform to the ISO 2017 C++ standard.
+
+std=c++2a
+C++ ObjC++ Alias(std=c++20) Undocumented
+Conform to the ISO 2020 C++ standard (experimental and incomplete support).
+
+std=c++20
+C++ ObjC++
+Conform to the ISO 2020 C++ standard (experimental and incomplete support).
+
+std=c++2b
+C++ ObjC++ Alias(std=c++23)
+Conform to the ISO 2023 C++ draft standard (experimental and incomplete support).
+
+std=c++23
+C++ ObjC++ Undocumented
+Conform to the ISO 2023 C++ draft standard (experimental and incomplete support).
+
+std=c11
+C ObjC
+Conform to the ISO 2011 C standard.
+
+std=c1x
+C ObjC Alias(std=c11)
+Deprecated in favor of -std=c11.
+
+std=c17
+C ObjC
+Conform to the ISO 2017 C standard (published in 2018).
+
+std=c18
+C ObjC Alias(std=c17)
+Conform to the ISO 2017 C standard (published in 2018).
+
+std=c2x
+C ObjC
+Conform to the ISO 202X C standard draft (experimental and incomplete support).
+
+std=c89
+C ObjC Alias(std=c90)
+Conform to the ISO 1990 C standard.
+
+std=c90
+C ObjC
+Conform to the ISO 1990 C standard.
+
+std=c99
+C ObjC
+Conform to the ISO 1999 C standard.
+
+std=c9x
+C ObjC Alias(std=c99)
+Deprecated in favor of -std=c99.
+
+std=gnu++98
+C++ ObjC++
+Conform to the ISO 1998 C++ standard revised by the 2003 technical
+corrigendum with GNU extensions.
+
+std=gnu++03
+C++ ObjC++ Alias(std=gnu++98)
+Conform to the ISO 1998 C++ standard revised by the 2003 technical
+corrigendum with GNU extensions.
+
+std=gnu++11
+C++ ObjC++
+Conform to the ISO 2011 C++ standard with GNU extensions.
+
+std=gnu++0x
+C++ ObjC++ Alias(std=gnu++11) Undocumented
+Deprecated in favor of -std=gnu++11.
+
+std=gnu++1y
+C++ ObjC++ Alias(std=gnu++14) Undocumented
+Deprecated in favor of -std=gnu++14.
+
+std=gnu++14
+C++ ObjC++
+Conform to the ISO 2014 C++ standard with GNU extensions.
+
+std=gnu++1z
+C++ ObjC++ Alias(std=gnu++17) Undocumented
+Deprecated in favor of -std=gnu++17.
+
+std=gnu++17
+C++ ObjC++
+Conform to the ISO 2017 C++ standard with GNU extensions.
+
+std=gnu++2a
+C++ ObjC++ Alias(std=gnu++20) Undocumented
+Conform to the ISO 2020 C++ standard with GNU extensions (experimental and incomplete support).
+
+std=gnu++20
+C++ ObjC++
+Conform to the ISO 2020 C++ standard with GNU extensions (experimental and incomplete support).
+
+std=gnu++2b
+C++ ObjC++ Alias(std=gnu++23)
+Conform to the ISO 2023 C++ draft standard with GNU extensions (experimental and incomplete support).
+
+std=gnu++23
+C++ ObjC++ Undocumented
+Conform to the ISO 2023 C++ draft standard with GNU extensions (experimental and incomplete support).
+
+std=gnu11
+C ObjC
+Conform to the ISO 2011 C standard with GNU extensions.
+
+std=gnu1x
+C ObjC Alias(std=gnu11)
+Deprecated in favor of -std=gnu11.
+
+std=gnu17
+C ObjC
+Conform to the ISO 2017 C standard (published in 2018) with GNU extensions.
+
+std=gnu18
+C ObjC Alias(std=gnu17)
+Conform to the ISO 2017 C standard (published in 2018) with GNU extensions.
+
+std=gnu2x
+C ObjC
+Conform to the ISO 202X C standard draft with GNU extensions (experimental and incomplete support).
+
+std=gnu89
+C ObjC Alias(std=gnu90)
+Conform to the ISO 1990 C standard with GNU extensions.
+
+std=gnu90
+C ObjC
+Conform to the ISO 1990 C standard with GNU extensions.
+
+std=gnu99
+C ObjC
+Conform to the ISO 1999 C standard with GNU extensions.
+
+std=gnu9x
+C ObjC Alias(std=gnu99)
+Deprecated in favor of -std=gnu99.
+
+std=iso9899:1990
+C ObjC Alias(std=c90)
+Conform to the ISO 1990 C standard.
+
+std=iso9899:199409
+C ObjC
+Conform to the ISO 1990 C standard as amended in 1994.
+
+std=iso9899:1999
+C ObjC Alias(std=c99)
+Conform to the ISO 1999 C standard.
+
+std=iso9899:199x
+C ObjC Alias(std=c99)
+Deprecated in favor of -std=iso9899:1999.
+
+std=iso9899:2011
+C ObjC Alias(std=c11)
+Conform to the ISO 2011 C standard.
+
+std=iso9899:2017
+C ObjC Alias(std=c17)
+Conform to the ISO 2017 C standard (published in 2018).
+
+std=iso9899:2018
+C ObjC Alias(std=c17)
+Conform to the ISO 2017 C standard (published in 2018).
+
+stdlib=
+Driver C++ ObjC++ Common Condition(ENABLE_STDLIB_OPTION) Var(flag_stdlib_kind) Joined Enum(stdlib_kind) RejectNegative Init(1)
+-stdlib=[libstdc++|libc++] The standard library to be used for C++ headers
+and runtime.
+
+Enum
+Name(stdlib_kind) Type(int)
+
+EnumValue
+Enum(stdlib_kind) String(libstdc++) Value(1)
+
+EnumValue
+Enum(stdlib_kind) String(libc++) Value(2)
+
+traditional
+Driver
+
+traditional-cpp
+C ObjC C++ ObjC++
+Enable traditional preprocessing.
+
+trigraphs
+C ObjC C++ ObjC++
+-trigraphs Support ISO C trigraphs.
+
+undef
+C ObjC C++ ObjC++ Var(flag_undef)
+Do not predefine system-specific and GCC-specific macros.
+
+v
+C ObjC C++ ObjC++
+; Documented in common.opt
+
+w
+C ObjC C++ ObjC++
+; Documented in common.opt
+
+; This comment is to ensure we retain the blank line above.
diff --git a/support/cpp/gcc/c-family/cppspec.cc b/support/cpp/gcc/c-family/cppspec.cc
new file mode 100644
index 000000000..a8d1e0255
--- /dev/null
+++ b/support/cpp/gcc/c-family/cppspec.cc
@@ -0,0 +1,200 @@
+/* Specific flags and argument handling of the C preprocessor.
+ 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.
+
+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 "opt-suggestions.h"
+#include "gcc.h"
+#include "opts.h"
+
+/* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
+ is a customized version of the gcc driver. It forces -E; -S and -c
+ are errors. It defaults to -x c for files with unrecognized
+ extensions, unless -x options appear in argv, in which case we
+ assume the user knows what they're doing. If no explicit input is
+ mentioned, it will read stdin. */
+
+/* Suffixes for known sorts of input files. Note that we do not list
+ files which are normally considered to have been preprocessed already,
+ since the user's expectation is that `cpp' always preprocesses. */
+static const char *const known_suffixes[] =
+{
+ ".c", ".C", ".S", ".m",
+ ".cc", ".cxx", ".cpp", ".cp", ".c++",
+ ".sx",
+ NULL
+};
+
+/* Filter the command line before processing by the gcc driver proper. */
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+ unsigned int *in_decoded_options_count,
+ int *in_added_libraries ATTRIBUTE_UNUSED)
+{
+ struct cl_decoded_option *decoded_options = *in_decoded_options;
+ unsigned int argc = *in_decoded_options_count;
+
+ /* Do we need to read stdin? */
+ int read_stdin = 1;
+
+ /* Do we need to insert -E? */
+ int need_E = 1;
+
+ /* Have we seen an input file? */
+ int seen_input = 0;
+
+ /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
+ 0 means unnecessary. */
+ unsigned int lang_c_here = 0;
+ unsigned int lang_S_here = 0;
+ unsigned int o_here = 0;
+
+ /* Do we need to fix up an input file with an unrecognized suffix? */
+ int need_fixups = 1;
+
+ unsigned int i, j;
+ struct cl_decoded_option *new_decoded_options;
+ unsigned int new_argc;
+ extern int is_cpp_driver;
+
+ is_cpp_driver = 1;
+
+ /* First pass. If we see an -S or -c, barf. If we see an input file,
+ turn off read_stdin. If we see a second input file, it is actually
+ the output file. If we see a third input file, barf. */
+ for (i = 1; i < argc; i++)
+ {
+ switch (decoded_options[i].opt_index)
+ {
+ case OPT_E:
+ need_E = 0;
+ break;
+
+ case OPT_S:
+ case OPT_c:
+ fatal_error (input_location,
+ "%qs is not a valid option to the preprocessor",
+ decoded_options[i].orig_option_with_args_text);
+ return;
+
+ case OPT_x:
+ need_fixups = 0;
+ break;
+
+ case OPT_SPECIAL_input_file:
+ {
+ const char *file = decoded_options[i].arg;
+
+ if (strcmp (file, "-") == 0)
+ read_stdin = 0;
+ else
+ {
+ seen_input++;
+ if (seen_input == 3)
+ {
+ fatal_error (input_location, "too many input files");
+ return;
+ }
+ else if (seen_input == 2)
+ {
+ o_here = i;
+ }
+ else
+ {
+ read_stdin = 0;
+ if (need_fixups)
+ {
+ int l = strlen (file);
+ int known = 0;
+ const char *const *suff;
+
+ for (suff = known_suffixes; *suff; suff++)
+ if (!strcmp (*suff, &file[l - strlen(*suff)]))
+ {
+ known = 1;
+ break;
+ }
+
+ if (! known)
+ {
+ /* .s files are a special case; we have to
+ treat them like .S files so
+ -D__ASSEMBLER__ will be in effect. */
+ if (!strcmp (".s", &file[l - 2]))
+ lang_S_here = i;
+ else
+ lang_c_here = i;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ /* If we don't need to edit the command line, we can bail early. */
+
+ new_argc = argc + need_E + read_stdin + !!lang_c_here + !!lang_S_here;
+
+ if (new_argc == argc && !o_here)
+ return;
+
+ new_decoded_options = XNEWVEC (struct cl_decoded_option, new_argc);
+
+ new_decoded_options[0] = decoded_options[0];
+ j = 1;
+
+ if (need_E)
+ generate_option (OPT_E, NULL, 1, CL_DRIVER, &new_decoded_options[j++]);
+
+ for (i = 1; i < argc; i++, j++)
+ {
+ if (i == lang_c_here)
+ generate_option (OPT_x, "c", 1, CL_DRIVER, &new_decoded_options[j++]);
+ else if (i == lang_S_here)
+ generate_option (OPT_x, "assembler-with-cpp", 1, CL_DRIVER,
+ &new_decoded_options[j++]);
+ else if (i == o_here)
+ {
+ generate_option (OPT_o, decoded_options[i].arg, 1, CL_DRIVER,
+ &new_decoded_options[j]);
+ continue;
+ }
+
+ new_decoded_options[j] = decoded_options[i];
+ }
+
+ if (read_stdin)
+ generate_option_input_file ("-", &new_decoded_options[j++]);
+
+ *in_decoded_options_count = new_argc;
+ *in_decoded_options = new_decoded_options;
+}
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+int lang_specific_pre_link (void)
+{
+ return 0; /* Not used for cpp. */
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+int lang_specific_extra_outfiles = 0; /* Not used for cpp. */
diff --git a/support/cpp/gcc/c-family/known-headers.h b/support/cpp/gcc/c-family/known-headers.h
new file mode 100644
index 000000000..65ed6f9a5
--- /dev/null
+++ b/support/cpp/gcc/c-family/known-headers.h
@@ -0,0 +1,44 @@
+/* Support for suggestions about missing #include directives.
+ Copyright (C) 2017-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_KNOWN_HEADERS_H
+#define GCC_KNOWN_HEADERS_H
+
+extern const char *get_c_stdlib_header_for_name (const char *name);
+extern const char *get_cp_stdlib_header_for_name (const char *name);
+
+extern const char *get_c_stdlib_header_for_string_macro_name (const char *n);
+extern const char *get_cp_stdlib_header_for_string_macro_name (const char *n);
+
+/* Subclass of deferred_diagnostic for suggesting to the user
+ that they have missed a #include. */
+
+class suggest_missing_header : public deferred_diagnostic
+{
+ public:
+ suggest_missing_header (location_t loc, const char *name,
+ const char *header_hint);
+ ~suggest_missing_header ();
+
+ private:
+ const char *m_name_str;
+ const char *m_header_hint;
+};
+
+#endif /* GCC_KNOWN_HEADERS_H */
diff --git a/support/cpp/gcc/c-family/name-hint.h b/support/cpp/gcc/c-family/name-hint.h
new file mode 100644
index 000000000..df733e7e6
--- /dev/null
+++ b/support/cpp/gcc/c-family/name-hint.h
@@ -0,0 +1,128 @@
+/* Support for offering suggestions for handling unrecognized names.
+ Copyright (C) 2016-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_NAME_HINT_H
+#define GCC_NAME_HINT_H
+
+/* This header uses std::unique_ptr, but <memory> can't be directly
+ included due to issues with macros. Hence it must be included from
+ system.h by defining INCLUDE_MEMORY in any source file using it. */
+
+#ifndef INCLUDE_MEMORY
+# error "You must define INCLUDE_MEMORY before including system.h to use name-hint.h"
+#endif
+
+enum lookup_name_fuzzy_kind {
+ /* Names of types. */
+ FUZZY_LOOKUP_TYPENAME,
+
+ /* Names of function decls. */
+ FUZZY_LOOKUP_FUNCTION_NAME,
+
+ /* Any name. */
+ FUZZY_LOOKUP_NAME
+};
+
+/* A deferred_diagnostic is a wrapper around optional extra diagnostics
+ that we may want to bundle into a name_hint.
+
+ The diagnostic is emitted by the subclass destructor, which should
+ check that is_suppressed_p () is not true. */
+
+class deferred_diagnostic
+{
+ public:
+ virtual ~deferred_diagnostic () {}
+
+ location_t get_location () const { return m_loc; }
+
+ /* Call this if the corresponding warning was not emitted,
+ in which case we should also not emit the deferred_diagnostic. */
+ void suppress ()
+ {
+ m_suppress = true;
+ }
+
+ bool is_suppressed_p () const { return m_suppress; }
+
+ protected:
+ deferred_diagnostic (location_t loc)
+ : m_loc (loc), m_suppress (false) {}
+
+ private:
+ location_t m_loc;
+ bool m_suppress;
+};
+
+/* A name_hint is an optional string suggestion, along with an
+ optional deferred_diagnostic.
+ For example:
+
+ error: unknown foo named 'bar'
+
+ if the SUGGESTION is "baz", then one might print:
+
+ error: unknown foo named 'bar'; did you mean 'baz'?
+
+ and the deferred_diagnostic allows for additional (optional)
+ diagnostics e.g.:
+
+ note: did you check behind the couch?
+
+ The deferred_diagnostic is emitted by its destructor, when the
+ name_hint goes out of scope. */
+
+class name_hint
+{
+public:
+ name_hint () : m_suggestion (NULL), m_deferred () {}
+
+ name_hint (const char *suggestion, deferred_diagnostic *deferred)
+ : m_suggestion (suggestion), m_deferred (deferred)
+ {
+ }
+
+ const char *suggestion () const { return m_suggestion; }
+
+ /* Does this name_hint have a suggestion or a deferred diagnostic? */
+ operator bool () const { return (m_suggestion != NULL
+ || m_deferred != NULL); }
+
+ /* Take ownership of this name_hint's deferred_diagnostic, for use
+ in chaining up deferred diagnostics. */
+ std::unique_ptr<deferred_diagnostic> take_deferred () { return move (m_deferred); }
+
+ /* Call this on a name_hint if the corresponding warning was not emitted,
+ in which case we should also not emit the deferred_diagnostic. */
+
+ void suppress ()
+ {
+ if (m_deferred)
+ m_deferred->suppress ();
+ }
+
+private:
+ const char *m_suggestion;
+ std::unique_ptr<deferred_diagnostic> m_deferred;
+};
+
+extern name_hint lookup_name_fuzzy (tree, enum lookup_name_fuzzy_kind,
+ location_t);
+
+#endif /* ! GCC_NAME_HINT_H */
diff --git a/support/cpp/gcc/c/Make-lang.in b/support/cpp/gcc/c/Make-lang.in
new file mode 100644
index 000000000..4690be3ac
--- /dev/null
+++ b/support/cpp/gcc/c/Make-lang.in
@@ -0,0 +1,219 @@
+# Top level -*- makefile -*- fragment for GNU C - C language.
+# Copyright (C) 1994-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 provides the language dependent support in the main Makefile.
+# Each language makefile fragment must provide the following targets:
+#
+# foo.all.cross, foo.start.encap, foo.rest.encap,
+# foo.install-common, foo.install-man, foo.install-info, foo.install-pdf,
+# foo.install-html, foo.info, foo.dvi, foo.pdf, foo.html, foo.uninstall,
+# foo.mostlyclean, foo.clean, foo.distclean,
+# foo.maintainer-clean, foo.stage1, foo.stage2, foo.stage3, foo.stage4
+#
+# where `foo' is the name of the language.
+#
+# It should also provide rules for:
+#
+# - making any compiler driver (eg: gcc)
+# - the compiler proper (eg: cc1)
+# - define the names for selecting the language in LANGUAGES.
+
+#
+# Define the names for selecting c in LANGUAGES.
+c: cc1$(exeext)
+c.serial = cc1$(exeext)
+
+# Tell GNU make to ignore these if they exist.
+.PHONY: c gcc
+
+# The C front end driver. This is different from the drivers for other
+# front ends, because there is no C language specific driver (i.e. nothing
+# is to cc1 as e.g. g++ is to cc1plus, or gfortran is to f951).
+CFLAGS-c/gccspec.o += $(DRIVER_DEFINES)
+
+# The C compiler itself.
+
+# Language-specific object files for C and Objective C.
+C_AND_OBJC_OBJS = \
+ c/c-errors.o \
+ c/c-convert.o \
+ c/gimple-parser.o \
+ c/c-objc-common.o \
+ $(C_COMMON_OBJS)
+ # c/c-aux-info.o
+ # $(C_TARGET_OBJS)
+ # c/c-parser.o
+ # c/c-fold.o
+
+# Language-specific object files for C.
+C_OBJS = \
+ c-family/c-common.o \
+ c/c-lang.o \
+ $(C_AND_OBJC_OBJS)
+# c-family/stub-objc.o
+c_OBJS = $(C_OBJS) cc1-checksum.o c/gccspec.o
+
+# Use strict warnings for this front end.
+c-warn = $(STRICT_WARN)
+
+ifeq ($(if $(wildcard ../stage_current),$(shell cat \
+ ../stage_current)),stageautofeedback)
+$(C_OBJS): ALL_COMPILERFLAGS += -fauto-profile=cc1.fda
+$(C_OBJS): cc1.fda
+endif
+
+# compute checksum over all object files and the options
+# re-use the checksum from the prev-final stage so it passes
+# the bootstrap comparison and allows comparing of the cc1 binary
+cc1-checksum.cc : build/genchecksum$(build_exeext) checksum-options \
+ $(C_OBJS) $(BACKEND) $(LIBDEPS)
+ if [ -f ../stage_final ] \
+ && cmp -s ../stage_current ../stage_final; then \
+ cp ../prev-gcc/cc1-checksum.cc cc1-checksum.cc; \
+ else \
+ build/genchecksum$(build_exeext) $(C_OBJS) \
+ $(BACKEND) \
+ $(LIBDEPS) \
+ checksum-options > cc1-checksum.cc.tmp && \
+ $(srcdir)/../move-if-change cc1-checksum.cc.tmp cc1-checksum.cc; \
+ fi
+
+cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+ @$(call LINK_PROGRESS,$(INDEX.c),start)
+ $(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
+ cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.c),end)
+
+cc1.fda: ../stage1-gcc/cc1$(exeext) ../prev-gcc/$(PERF_DATA)
+ $(CREATE_GCOV) -binary ../stage1-gcc/cc1$(exeext) -gcov cc1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1
+
+#
+# Build hooks:
+
+c.info:
+c.dvi:
+c.pdf:
+c.html:
+c.install-info:
+c.install-dvi:
+c.install-pdf:
+c.install-html:
+c.all.cross:
+c.start.encap:
+c.rest.encap:
+c.srcinfo:
+c.srcextra: gengtype-lex.cc
+ -cp -p $^ $(srcdir)
+c.tags: force
+ cd $(srcdir)/c; $(ETAGS) -o TAGS.sub *.c *.h; \
+ $(ETAGS) --include TAGS.sub --include ../TAGS.sub
+c.man:
+c.srcman:
+
+# C selftests
+
+# If C is enabled, require the selftests to be run for it
+# at each stage of the build:
+selftest-c: s-selftest-c
+
+C_SELFTEST_FLAGS = -xc $(SELFTEST_FLAGS)
+C_SELFTEST_DEPS = cc1$(exeext) $(SELFTEST_DEPS)
+
+# Run the C selftests:
+s-selftest-c: $(C_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(C_SELFTEST_FLAGS)
+ $(STAMP) $@
+
+# Convenience methods for running C selftests under gdb:
+.PHONY: selftest-c-gdb
+selftest-c-gdb: $(C_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(C_SELFTEST_FLAGS) \
+ -wrapper gdb,--args
+
+.PHONY: selftest-gdb
+selftest-gdb: selftest-c-gdb
+
+# Convenience methods for running C selftests under valgrind:
+.PHONY: selftest-c-valgrind
+selftest-c-valgrind: $(C_SELFTEST_DEPS)
+ $(GCC_FOR_TARGET) $(C_SELFTEST_FLAGS) \
+ -wrapper valgrind,--leak-check=full
+
+.PHONY: selftest-valgrind
+selftest-valgrind: selftest-c-valgrind
+
+# List of targets that can use the generic check- rule and its // variant.
+lang_checks += check-gcc
+lang_checks_parallelized += check-gcc
+# For description see the check_$lang_parallelize comment in gcc/Makefile.in.
+check_gcc_parallelize=10000
+
+# 'make check' in gcc/ looks for check-c. Redirect it to check-gcc.
+check-c : check-gcc
+
+#
+# Install hooks:
+# cc1 is installed elsewhere as part of $(COMPILERS).
+
+c.install-common:
+c.install-man:
+
+c.install-plugin: installdirs
+# Install import library.
+ifeq ($(plugin_implib),yes)
+ $(mkinstalldirs) $(DESTDIR)$(plugin_resourcesdir)
+ $(INSTALL_DATA) cc1$(exeext).a $(DESTDIR)$(plugin_resourcesdir)/cc1$(exeext).a
+endif
+
+c.uninstall:
+
+#
+# Clean hooks:
+# A lot of the ancillary files are deleted by the main makefile.
+# We just have to delete files specific to us.
+
+c.mostlyclean:
+ -rm -f cc1$(exeext)
+ -rm -f c/*$(objext)
+ -rm -f c/*$(coverageexts)
+ -rm -f cc1.fda
+c.clean:
+c.distclean:
+ -rm -f c/config.status c/Makefile
+c.maintainer-clean:
+#
+# Stage hooks:
+# The main makefile has already created stage?/cp.
+
+c.stage1: stage1-start
+ -mv c/*$(objext) stage1/c
+c.stage2: stage2-start
+ -mv c/*$(objext) stage2/c
+c.stage3: stage3-start
+ -mv c/*$(objext) stage3/c
+c.stage4: stage4-start
+ -mv c/*$(objext) stage4/c
+c.stageprofile: stageprofile-start
+ -mv c/*$(objext) stageprofile/c
+c.stagefeedback: stagefeedback-start
+ -mv c/*$(objext) stagefeedback/c
+c.autostageprofile: autostageprofile-start
+ -mv c/*$(objext) autostageprofile/c
+c.autostagefeedback: autostagefeedback-start
+ -mv c/*$(objext) autostagefeedback/c
diff --git a/support/cpp/gcc/c/c-convert.cc b/support/cpp/gcc/c/c-convert.cc
new file mode 100644
index 000000000..883841ccc
--- /dev/null
+++ b/support/cpp/gcc/c/c-convert.cc
@@ -0,0 +1,214 @@
+/* Language-level data type conversion for GNU C.
+ 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/>. */
+
+
+/* This file contains the functions for converting C expressions
+ to different data types. The only entry point is `convert'.
+ Every language front end must have a `convert' function
+ but what kind of conversions it does will depend on the language. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "c-tree.h"
+#include "convert.h"
+#include "langhooks.h"
+// #include "ubsan.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "asan.h"
+
+/* Change of width--truncation and extension of integers or reals--
+ is represented with NOP_EXPR. Proper functioning of many things
+ assumes that no other conversions can be NOP_EXPRs.
+
+ Conversion between integer and pointer is represented with CONVERT_EXPR.
+ Converting integer to real uses FLOAT_EXPR
+ and real to integer uses FIX_TRUNC_EXPR.
+
+ Here is a list of all the functions that assume that widening and
+ narrowing is always done with a NOP_EXPR:
+ In convert.cc, convert_to_integer.
+ In c-typeck.cc, build_binary_op (boolean ops), and
+ c_common_truthvalue_conversion.
+ In expr.cc: expand_expr, for operands of a MULT_EXPR.
+ In fold-const.cc: fold.
+ In tree.cc: get_narrower and get_unwidened. */
+
+/* Subroutines of `convert'. */
+
+
+
+/* Create an expression whose value is that of EXPR,
+ converted to type TYPE. The TREE_TYPE of the value
+ is always TYPE. This function implements all reasonable
+ conversions; callers should filter out those that are
+ not permitted by the language being compiled.
+ INIT_CONST is true if the conversion is for arithmetic types for a static
+ initializer and folding must apply accordingly (discarding floating-point
+ exceptions and assuming the default rounding mode is in effect). */
+
+static tree
+c_convert (tree type, tree expr, bool init_const)
+{
+ (void) type;
+ (void) expr;
+ (void) init_const;
+ gcc_assert(0);
+ return tree();
+#if 0 // sdcpp
+ tree e = expr;
+ enum tree_code code = TREE_CODE (type);
+ const char *invalid_conv_diag;
+ tree ret;
+ location_t loc = EXPR_LOCATION (expr);
+
+ if (type == error_mark_node
+ || error_operand_p (expr))
+ return error_mark_node;
+
+ if ((invalid_conv_diag
+ = targetm.invalid_conversion (TREE_TYPE (expr), type)))
+ {
+ error (invalid_conv_diag);
+ return error_mark_node;
+ }
+
+ if (type == TREE_TYPE (expr))
+ return expr;
+ ret = targetm.convert_to_type (type, expr);
+ if (ret)
+ return ret;
+
+ STRIP_TYPE_NOPS (e);
+
+ if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))
+ && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE
+ || TREE_CODE (e) == COMPLEX_EXPR))
+ return fold_convert_loc (loc, type, expr);
+ if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
+ return error_mark_node;
+ if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
+ {
+ error ("void value not ignored as it ought to be");
+ return error_mark_node;
+ }
+
+ switch (code)
+ {
+ case VOID_TYPE:
+ return fold_convert_loc (loc, type, e);
+
+ case INTEGER_TYPE:
+ case ENUMERAL_TYPE:
+ if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
+ && current_function_decl != NULL_TREE
+ && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ && COMPLETE_TYPE_P (type))
+ {
+ expr = save_expr (expr);
+ expr = c_fully_fold (expr, init_const, NULL);
+ tree check = ubsan_instrument_float_cast (loc, type, expr);
+ expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
+ if (check == NULL_TREE)
+ return expr;
+ return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
+ }
+ ret = convert_to_integer (type, e);
+ goto maybe_fold;
+
+ case BOOLEAN_TYPE:
+ return fold_convert_loc
+ (loc, type, c_objc_common_truthvalue_conversion (input_location, expr));
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ ret = convert_to_pointer (type, e);
+ goto maybe_fold;
+
+ case REAL_TYPE:
+ ret = convert_to_real (type, e);
+ goto maybe_fold;
+
+ case FIXED_POINT_TYPE:
+ ret = convert_to_fixed (type, e);
+ goto maybe_fold;
+
+ case COMPLEX_TYPE:
+ ret = convert_to_complex (type, e);
+ goto maybe_fold;
+
+ case VECTOR_TYPE:
+ if (gnu_vector_type_p (type)
+ || gnu_vector_type_p (TREE_TYPE (e))
+ /* Allow conversions between compatible non-GNU vector types
+ when -flax-vector-conversions is passed. The whole purpose
+ of the option is to bend the normal type rules and accept
+ nonconforming code. */
+ || (flag_lax_vector_conversions
+ && VECTOR_TYPE_P (TREE_TYPE (e))
+ && vector_types_convertible_p (type, TREE_TYPE (e), false)))
+ {
+ ret = convert_to_vector (type, e);
+ goto maybe_fold;
+ }
+ break;
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
+ return e;
+ break;
+
+ default:
+ break;
+
+ maybe_fold:
+ if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
+ ret = init_const ? fold_init (ret) : fold (ret);
+ return ret;
+ }
+
+ error ("conversion to non-scalar type requested");
+ return error_mark_node;
+#endif
+}
+
+/* Create an expression whose value is that of EXPR, converted to type TYPE.
+ The TREE_TYPE of the value is always TYPE. This function implements all
+ reasonable conversions; callers should filter out those that are not
+ permitted by the language being compiled. */
+
+tree
+convert (tree type, tree expr)
+{
+ return c_convert (type, expr, false);
+}
+
+/* Create an expression whose value is that of EXPR, converted to type TYPE, in
+ a static initializer. The TREE_TYPE of the value is always TYPE. This
+ function implements all reasonable conversions; callers should filter out
+ those that are not permitted by the language being compiled. */
+
+tree
+convert_init (tree type, tree expr)
+{
+ return c_convert (type, expr, true);
+}
diff --git a/support/cpp/gcc/c/c-errors.cc b/support/cpp/gcc/c/c-errors.cc
new file mode 100644
index 000000000..c5d669916
--- /dev/null
+++ b/support/cpp/gcc/c/c-errors.cc
@@ -0,0 +1,164 @@
+/* Various diagnostic subroutines for the GNU C language.
+ Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@codesourcery.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.
+
+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 "c-tree.h"
+#include "opts.h"
+#include "diagnostic.h" // sdcpp
+
+/* Issue an ISO C11 pedantic warning MSGID if -pedantic outside C2X mode,
+ otherwise issue warning MSGID if -Wc11-c2X-compat is specified.
+ This function is supposed to be used for matters that are allowed in
+ ISO C2X but not supported in ISO C11, thus we explicitly don't pedwarn
+ when C2X is specified. */
+
+bool
+pedwarn_c11 (location_t location, int opt, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ bool warned = false;
+ rich_location richloc (line_table, location);
+
+ va_start (ap, gmsgid);
+ /* If desired, issue the C11/C2X compat warning, which is more specific
+ than -pedantic. */
+ if (warn_c11_c2x_compat > 0)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ (pedantic && !flag_isoc2x)
+ ? DK_PEDWARN : DK_WARNING);
+ diagnostic.option_index = OPT_Wc11_c2x_compat;
+ warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
+ }
+ /* -Wno-c11-c2x-compat suppresses even the pedwarns. */
+ else if (warn_c11_c2x_compat == 0)
+ ;
+ /* For -pedantic outside C2X, issue a pedwarn. */
+ else if (pedantic && !flag_isoc2x)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
+ diagnostic.option_index = opt;
+ warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
+ }
+ va_end (ap);
+ return warned;
+}
+
+/* Issue an ISO C99 pedantic warning MSGID if -pedantic outside C11 mode,
+ otherwise issue warning MSGID if -Wc99-c11-compat is specified.
+ This function is supposed to be used for matters that are allowed in
+ ISO C11 but not supported in ISO C99, thus we explicitly don't pedwarn
+ when C11 is specified. */
+
+bool
+pedwarn_c99 (location_t location, int opt, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ bool warned = false;
+ rich_location richloc (line_table, location);
+
+ va_start (ap, gmsgid);
+ /* If desired, issue the C99/C11 compat warning, which is more specific
+ than -pedantic. */
+ if (warn_c99_c11_compat > 0)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ (pedantic && !flag_isoc11)
+ ? DK_PEDWARN : DK_WARNING);
+ diagnostic.option_index = OPT_Wc99_c11_compat;
+ warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
+ }
+ /* -Wno-c99-c11-compat suppresses even the pedwarns. */
+ else if (warn_c99_c11_compat == 0)
+ ;
+ /* For -pedantic outside C11, issue a pedwarn. */
+ else if (pedantic && !flag_isoc11)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
+ diagnostic.option_index = opt;
+ warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
+ }
+ va_end (ap);
+ return warned;
+}
+
+/* Issue an ISO C90 pedantic warning MSGID if -pedantic outside C99 mode,
+ otherwise issue warning MSGID if -Wc90-c99-compat is specified, or if
+ a specific option such as -Wlong-long is specified.
+ This function is supposed to be used for matters that are allowed in
+ ISO C99 but not supported in ISO C90, thus we explicitly don't pedwarn
+ when C99 is specified. (There is no flag_c90.) */
+
+bool
+pedwarn_c90 (location_t location, int opt, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ bool warned = false;
+ rich_location richloc (line_table, location);
+
+ va_start (ap, gmsgid);
+ /* Warnings such as -Wvla are the most specific ones. */
+ if (opt != OPT_Wpedantic)
+ {
+ int opt_var = *(int *) option_flag_var (opt, &global_options);
+ if (opt_var == 0)
+ goto out;
+ else if (opt_var > 0)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ (pedantic && !flag_isoc99)
+ ? DK_PEDWARN : DK_WARNING);
+ diagnostic.option_index = opt;
+ diagnostic_report_diagnostic (global_dc, &diagnostic);
+ warned = true;
+ goto out;
+ }
+ }
+ /* Maybe we want to issue the C90/C99 compat warning, which is more
+ specific than -pedantic. */
+ if (warn_c90_c99_compat > 0)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc,
+ (pedantic && !flag_isoc99)
+ ? DK_PEDWARN : DK_WARNING);
+ diagnostic.option_index = OPT_Wc90_c99_compat;
+ diagnostic_report_diagnostic (global_dc, &diagnostic);
+ }
+ /* -Wno-c90-c99-compat suppresses the pedwarns. */
+ else if (warn_c90_c99_compat == 0)
+ ;
+ /* For -pedantic outside C99, issue a pedwarn. */
+ else if (pedantic && !flag_isoc99)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN);
+ diagnostic.option_index = opt;
+ diagnostic_report_diagnostic (global_dc, &diagnostic);
+ warned = true;
+ }
+out:
+ va_end (ap);
+ return warned;
+}
diff --git a/support/cpp/gcc/c/c-lang.cc b/support/cpp/gcc/c/c-lang.cc
new file mode 100644
index 000000000..e5779b9c2
--- /dev/null
+++ b/support/cpp/gcc/c/c-lang.cc
@@ -0,0 +1,154 @@
+/* Language-specific hook definitions for C front end.
+ Copyright (C) 1991-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 "c-tree.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "c-objc-common.h"
+
+#include "../c-family/c-pragma.h" // sdcpp BUG
+#include "../c-family/c-common.h" // sdcpp BUG
+
+enum c_language_kind c_language = clk_c;
+#if 0 // sdcpp
+
+
+
+
+/* Lang hooks common to C and ObjC are declared in c-objc-common.h;
+ consequently, there should be very few hooks below. */
+
+#undef LANG_HOOKS_NAME
+#define LANG_HOOKS_NAME "GNU C"
+#endif
+
+#define untested() (fprintf(stderr,"@@#\n@@@:%s:%u:%s\n", \
+ __FILE__, __LINE__, __func__))
+
+#if 1
+/* SDCC specific
+ pedantic_parse_number pragma */
+static void
+do_pragma_pedantic_parse_number (cpp_reader *pfile)
+{ untested();
+ const cpp_token *tok = cpp_get_token (pfile);
+ cpp_options* opts = cpp_get_options(pfile);
+
+ if (tok->type == CPP_PLUS)
+ {
+ ++opts->pedantic_parse_number;
+ }
+ else if (tok->type == CPP_MINUS)
+ {
+ --opts->pedantic_parse_number;
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "invalid #pragma pedantic_parse_number directive, need '+' or '-'");
+ }
+}
+
+/* SDCC _asm specific
+ switch _asm block preprocessing on / off */
+static void
+do_pragma_preproc_asm (cpp_reader *pfile)
+{ untested();
+ const cpp_token *tok = cpp_get_token (pfile);
+ cpp_options* opts = cpp_get_options(pfile);
+
+ if (tok->type == CPP_PLUS)
+ {
+ ++opts->preproc_asm;
+ }
+ else if (tok->type == CPP_MINUS)
+ {
+ --opts->preproc_asm;
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "invalid #pragma preproc_asm directive, need '+' or '-'");
+ }
+}
+
+#endif
+#undef LANG_HOOKS_INIT
+#define LANG_HOOKS_INIT c_objc_common_init
+#undef LANG_HOOKS_INIT_OPTIONS
+void
+sdcpp_init_options (unsigned int decoded_options_count ATTRIBUTE_UNUSED,
+ struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
+{
+ c_common_init_options(decoded_options_count, decoded_options);
+
+#if 0 // TODO
+ /* Kevin abuse for SDCC. */
+ cpp_register_pragma(parse_in, 0, "sdcc_hash", do_pragma_sdcc_hash, false);
+#endif
+
+ /* SDCC _asm specific */
+ cpp_register_pragma(parse_in, 0, "preproc_asm", do_pragma_preproc_asm, false);
+ /* SDCC specific */
+ cpp_register_pragma(parse_in, 0, "pedantic_parse_number", do_pragma_pedantic_parse_number, false);
+}
+
+// call the above instead of c_common_init_options
+#define LANG_HOOKS_INIT_OPTIONS sdcpp_init_options
+
+#if 0 // sdcpp
+#undef LANG_HOOKS_INIT_TS
+#define LANG_HOOKS_INIT_TS c_common_init_ts
+
+#if CHECKING_P
+#undef LANG_HOOKS_RUN_LANG_SELFTESTS
+#define LANG_HOOKS_RUN_LANG_SELFTESTS selftest::run_c_tests
+#endif /* #if CHECKING_P */
+
+#undef LANG_HOOKS_GET_SUBSTRING_LOCATION
+#define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
+
+#endif
+/* Each front end provides its own lang hook initializer. */
+struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Implementation of LANG_HOOKS_RUN_LANG_SELFTESTS for the C frontend. */
+
+void
+run_c_tests (void)
+{
+ /* Run selftests shared within the C family. */
+ c_family_tests ();
+
+ /* Additional C-specific tests. */
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+// sdcpp #include "gtype-c.h"
diff --git a/support/cpp/gcc/c/c-lang.h b/support/cpp/gcc/c/c-lang.h
new file mode 100644
index 000000000..7bdab47bd
--- /dev/null
+++ b/support/cpp/gcc/c/c-lang.h
@@ -0,0 +1,67 @@
+/* Definitions for C language specific types.
+ Copyright (C) 2009-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_C_LANG_H
+#define GCC_C_LANG_H
+
+#include "c-family/c-common.h"
+
+/* In a RECORD_TYPE, a sorted array of the fields of the type, not a
+ tree for size reasons. */
+struct GTY(()) sorted_fields_type {
+ int len;
+ tree GTY((length ("%h.len"))) elts[1];
+};
+
+struct GTY(()) lang_type {
+ /* In a RECORD_TYPE, a sorted array of the fields of the type. */
+ struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
+ /* In an ENUMERAL_TYPE, the min and max values. */
+ tree enum_min;
+ tree enum_max;
+ /* In a RECORD_TYPE, information specific to Objective-C, such
+ as a list of adopted protocols or a pointer to a corresponding
+ @interface. See objc/objc-act.h for details. */
+ tree objc_info;
+};
+
+struct GTY(()) lang_decl {
+ char dummy;
+};
+
+/* Save and restore the variables in this file and elsewhere
+ that keep track of the progress of compilation of the current function.
+ Used for nested functions. */
+
+struct GTY(()) language_function {
+ struct c_language_function base;
+ unsigned char x_in_statement;
+ struct c_switch * GTY((skip)) x_switch_stack;
+ struct c_arg_info * GTY((skip)) arg_info;
+ int returns_value;
+ int returns_null;
+ int returns_abnormally;
+ int warn_about_return_type;
+};
+
+/* If non-zero, implicit "omp declare target" attribute is added into the
+ attribute lists. */
+extern GTY(()) int current_omp_declare_target_attribute;
+
+#endif /* ! GCC_C_LANG_H */
diff --git a/support/cpp/gcc/c/c-objc-common.cc b/support/cpp/gcc/c/c-objc-common.cc
new file mode 100644
index 000000000..cf32a4f52
--- /dev/null
+++ b/support/cpp/gcc/c/c-objc-common.cc
@@ -0,0 +1,405 @@
+/* Some code common to C and ObjC front ends.
+ Copyright (C) 2001-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 "c-tree.h"
+#include "intl.h"
+#include "c-family/c-pretty-print.h"
+#include "tree-pretty-print.h"
+// sdcpp #include "gimple-pretty-print.h"
+#include "langhooks.h"
+// sdcpp #include "c-objc-common.h"
+#include "gcc-rich-location.h"
+#include "stringpool.h"
+#include "attribs.h"
+
+#if 0 // sdcpp
+static bool c_tree_printer (pretty_printer *, text_info *, const char *,
+ int, bool, bool, bool, bool *, const char **);
+
+bool
+c_missing_noreturn_ok_p (tree decl)
+{
+ /* A missing noreturn is not ok for freestanding implementations and
+ ok for the `main' function in hosted implementations. */
+ return flag_hosted && MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
+}
+
+/* Called from check_global_declaration. */
+
+bool
+c_warn_unused_global_decl (const_tree decl)
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
+ return false;
+ if (DECL_IN_SYSTEM_HEADER (decl))
+ return false;
+
+ return true;
+}
+#endif // sdcpp
+
+/* Initialization common to C and Objective-C front ends. */
+bool
+c_objc_common_init (void)
+{
+ // sdcpp c_init_decl_processing ();
+
+ return c_common_init ();
+}
+
+/* Decide whether it's worth saying that TYPE is also known as some other
+ type. Return the other type if so, otherwise return TYPE. */
+
+#if 0 // sdcpp
+static tree
+get_aka_type (tree type)
+{
+ if (type == error_mark_node)
+ return type;
+
+ tree result;
+ if (typedef_variant_p (type))
+ {
+ /* Saying that "foo" is also known as "struct foo" or
+ "struct <anonymous>" is unlikely to be useful, since users of
+ structure-like types would already know that they're structures.
+ The same applies to unions and enums; in general, printing the
+ tag is only useful if it has a different name. */
+ tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+ tree_code code = TREE_CODE (orig_type);
+ tree orig_id = TYPE_IDENTIFIER (orig_type);
+ if ((code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
+ && (!orig_id || TYPE_IDENTIFIER (type) == orig_id))
+ return type;
+
+ if (!user_facing_original_type_p (type))
+ return type;
+
+ result = get_aka_type (orig_type);
+ }
+ else
+ {
+ tree canonical = TYPE_CANONICAL (type);
+ if (canonical && TREE_CODE (type) != TREE_CODE (canonical))
+ return canonical;
+
+ /* Recursive calls might choose a middle ground between TYPE
+ (which has no typedefs stripped) and CANONICAL (which has
+ all typedefs stripped). So try to reuse TYPE or CANONICAL if
+ convenient, but be prepared to create a new type if necessary. */
+ switch (TREE_CODE (type))
+ {
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ {
+ tree target_type = get_aka_type (TREE_TYPE (type));
+
+ if (target_type == TREE_TYPE (type))
+ return type;
+
+ if (canonical && target_type == TREE_TYPE (canonical))
+ return canonical;
+
+ result = (TREE_CODE (type) == POINTER_TYPE
+ ? build_pointer_type (target_type)
+ : build_reference_type (target_type));
+ break;
+ }
+
+ case ARRAY_TYPE:
+ {
+ tree element_type = get_aka_type (TREE_TYPE (type));
+ tree index_type = (TYPE_DOMAIN (type)
+ ? get_aka_type (TYPE_DOMAIN (type))
+ : NULL_TREE);
+
+ if (element_type == TREE_TYPE (type)
+ && index_type == TYPE_DOMAIN (type))
+ return type;
+
+ if (canonical
+ && element_type == TREE_TYPE (canonical)
+ && index_type == TYPE_DOMAIN (canonical))
+ return canonical;
+
+ result = build_array_type (element_type, index_type,
+ TYPE_TYPELESS_STORAGE (type));
+ break;
+ }
+
+ case FUNCTION_TYPE:
+ {
+ tree return_type = get_aka_type (TREE_TYPE (type));
+
+ tree args = TYPE_ARG_TYPES (type);
+ if (args == error_mark_node)
+ return type;
+
+ auto_vec<tree, 32> arg_types;
+ bool type_ok_p = true;
+ while (args && args != void_list_node)
+ {
+ tree arg_type = get_aka_type (TREE_VALUE (args));
+ arg_types.safe_push (arg_type);
+ type_ok_p &= (arg_type == TREE_VALUE (args));
+ args = TREE_CHAIN (args);
+ }
+
+ if (type_ok_p && return_type == TREE_TYPE (type))
+ return type;
+
+ unsigned int i;
+ tree arg_type;
+ FOR_EACH_VEC_ELT_REVERSE (arg_types, i, arg_type)
+ args = tree_cons (NULL_TREE, arg_type, args);
+ result = build_function_type (return_type, args);
+ break;
+ }
+
+ default:
+ return canonical ? canonical : type;
+ }
+ }
+ return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
+ TYPE_QUALS (type));
+}
+
+/* Print T to CPP. */
+
+static void
+print_type (c_pretty_printer *cpp, tree t, bool *quoted)
+{
+ if (t == error_mark_node)
+ {
+ pp_string (cpp, _("{erroneous}"));
+ return;
+ }
+
+ gcc_assert (TYPE_P (t));
+ struct obstack *ob = pp_buffer (cpp)->obstack;
+ char *p = (char *) obstack_base (ob);
+ /* Remember the end of the initial dump. */
+ int len = obstack_object_size (ob);
+
+ tree name = TYPE_NAME (t);
+ if (name && TREE_CODE (name) == TYPE_DECL && DECL_NAME (name))
+ pp_identifier (cpp, lang_hooks.decl_printable_name (name, 2));
+ else
+ cpp->type_id (t);
+
+ /* If we're printing a type that involves typedefs, also print the
+ stripped version. But sometimes the stripped version looks
+ exactly the same, so we don't want it after all. To avoid
+ printing it in that case, we play ugly obstack games. */
+ tree aka_type = get_aka_type (t);
+ if (aka_type != t)
+ {
+ c_pretty_printer cpp2;
+ /* Print the stripped version into a temporary printer. */
+ cpp2.type_id (aka_type);
+ struct obstack *ob2 = cpp2.buffer->obstack;
+ /* Get the stripped version from the temporary printer. */
+ const char *aka = (char *) obstack_base (ob2);
+ int aka_len = obstack_object_size (ob2);
+ int type1_len = obstack_object_size (ob) - len;
+
+ /* If they are identical, bail out. */
+ if (aka_len == type1_len && memcmp (p + len, aka, aka_len) == 0)
+ return;
+
+ /* They're not, print the stripped version now. */
+ if (*quoted)
+ pp_end_quote (cpp, pp_show_color (cpp));
+ pp_c_whitespace (cpp);
+ pp_left_brace (cpp);
+ pp_c_ws_string (cpp, _("aka"));
+ pp_c_whitespace (cpp);
+ if (*quoted)
+ pp_begin_quote (cpp, pp_show_color (cpp));
+ cpp->type_id (aka_type);
+ if (*quoted)
+ pp_end_quote (cpp, pp_show_color (cpp));
+ pp_right_brace (cpp);
+ /* No further closing quotes are needed. */
+ *quoted = false;
+ }
+}
+
+/* Called during diagnostic message formatting process to print a
+ source-level entity onto BUFFER. The meaning of the format specifiers
+ is as follows:
+ %D: a general decl,
+ %E: an identifier or expression,
+ %F: a function declaration,
+ %T: a type.
+ %V: a list of type qualifiers from a tree.
+ %v: an explicit list of type qualifiers
+ %#v: an explicit list of type qualifiers of a function type.
+
+ Please notice when called, the `%' part was already skipped by the
+ diagnostic machinery. */
+static bool
+c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
+ int precision, bool wide, bool set_locus, bool hash,
+ bool *quoted, const char **)
+{
+#if 0 //sdcpp
+ (void) pp; (void) text; (void) spec; (void) precision; (void) wide;
+ (void) set_locus; (void) hash; (void) quoted;
+#else // sdcpp
+ tree t = NULL_TREE;
+ // FIXME: the next cast should be a dynamic_cast, when it is permitted.
+ c_pretty_printer *cpp = (c_pretty_printer *) pp;
+ pp->padding = pp_none;
+
+ if (precision != 0 || wide)
+ return false;
+
+ if (*spec != 'v')
+ {
+ t = va_arg (*text->args_ptr, tree);
+ if (set_locus)
+ text->set_location (0, DECL_SOURCE_LOCATION (t),
+ SHOW_RANGE_WITH_CARET);
+ }
+
+ switch (*spec)
+ {
+ case 'D':
+ if (VAR_P (t) && DECL_HAS_DEBUG_EXPR_P (t))
+ {
+ t = DECL_DEBUG_EXPR (t);
+ if (!DECL_P (t))
+ {
+ cpp->expression (t);
+ return true;
+ }
+ }
+ /* FALLTHRU */
+
+ case 'F':
+ if (DECL_NAME (t))
+ {
+ pp_identifier (cpp, lang_hooks.decl_printable_name (t, 2));
+ return true;
+ }
+ break;
+
+ case 'T':
+ print_type (cpp, t, quoted);
+ return true;
+
+ case 'E':
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ pp_identifier (cpp, IDENTIFIER_POINTER (t));
+ else
+ cpp->expression (t);
+ return true;
+
+ case 'V':
+ pp_c_type_qualifier_list (cpp, t);
+ return true;
+
+ case 'v':
+ pp_c_cv_qualifiers (cpp, va_arg (*text->args_ptr, int), hash);
+ return true;
+
+ default:
+ return false;
+ }
+
+ pp_string (cpp, _("({anonymous})"));
+#endif //sdcpp
+ return true;
+}
+
+/* C-specific implementation of range_label::get_text () vfunc for
+ range_label_for_type_mismatch. */
+
+label_text
+range_label_for_type_mismatch::get_text (unsigned /*range_idx*/) const
+{
+ if (m_labelled_type == NULL_TREE)
+ return label_text::borrow (NULL);
+
+ c_pretty_printer cpp;
+ bool quoted = false;
+ print_type (&cpp, m_labelled_type, &quoted);
+ return label_text::take (xstrdup (pp_formatted_text (&cpp)));
+}
+
+
+/* In C and ObjC, all decls have "C" linkage. */
+bool
+has_c_linkage (const_tree decl ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+void
+c_initialize_diagnostics (diagnostic_context *context)
+{
+ pretty_printer *base = context->printer;
+ c_pretty_printer *pp = XNEW (c_pretty_printer);
+ context->printer = new (pp) c_pretty_printer ();
+
+ /* It is safe to free this object because it was previously XNEW()'d. */
+ base->~pretty_printer ();
+ XDELETE (base);
+
+ c_common_diagnostics_set_defaults (context);
+ diagnostic_format_decoder (context) = &c_tree_printer;
+}
+
+int
+c_types_compatible_p (tree x, tree y)
+{
+ return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
+}
+
+/* Determine if the type is a vla type for the backend. */
+
+bool
+c_vla_unspec_p (tree x, tree fn ATTRIBUTE_UNUSED)
+{
+ return c_vla_type_p (x);
+}
+
+/* Special routine to get the alias set of T for C. */
+
+alias_set_type
+c_get_alias_set (tree t)
+{
+ /* Allow aliasing between enumeral types and the underlying
+ integer type. This is required since those are compatible types. */
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ {
+ tree t1 = c_common_type_for_size (tree_to_uhwi (TYPE_SIZE (t)),
+ /* short-cut commoning to signed
+ type. */
+ false);
+ return get_alias_set (t1);
+ }
+
+ return c_common_get_alias_set (t);
+}
+#endif // sdcpp
diff --git a/support/cpp/gcc/c/c-objc-common.h b/support/cpp/gcc/c/c-objc-common.h
new file mode 100644
index 000000000..869e6787b
--- /dev/null
+++ b/support/cpp/gcc/c/c-objc-common.h
@@ -0,0 +1,127 @@
+/* Language hooks common to C and ObjC front ends.
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Ziemowit Laski <zlaski@apple.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.
+
+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_C_OBJC_COMMON
+#define GCC_C_OBJC_COMMON
+
+/* Lang hooks that are shared between C and ObjC are defined here. Hooks
+ specific to C or ObjC go in c-lang.cc and objc/objc-lang.cc, respectively. */
+
+#undef LANG_HOOKS_IDENTIFIER_SIZE
+#define LANG_HOOKS_IDENTIFIER_SIZE C_SIZEOF_STRUCT_LANG_IDENTIFIER
+#undef LANG_HOOKS_FINISH
+#define LANG_HOOKS_FINISH c_common_finish
+#undef LANG_HOOKS_OPTION_LANG_MASK
+#define LANG_HOOKS_OPTION_LANG_MASK c_common_option_lang_mask
+#undef LANG_HOOKS_COMPLAIN_WRONG_LANG_P
+#define LANG_HOOKS_COMPLAIN_WRONG_LANG_P c_common_complain_wrong_lang_p
+#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
+#define LANG_HOOKS_INIT_OPTIONS_STRUCT c_common_init_options_struct
+#undef LANG_HOOKS_INIT_OPTIONS
+#define LANG_HOOKS_INIT_OPTIONS c_common_init_options // does this work?
+#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
+#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
+#undef LANG_HOOKS_HANDLE_OPTION
+#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
+#undef LANG_HOOKS_POST_OPTIONS
+#define LANG_HOOKS_POST_OPTIONS c_common_post_options
+#undef LANG_HOOKS_GET_ALIAS_SET
+#define LANG_HOOKS_GET_ALIAS_SET c_get_alias_set
+#undef LANG_HOOKS_PARSE_FILE
+#define LANG_HOOKS_PARSE_FILE c_common_parse_file
+#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
+#define LANG_HOOKS_FINISH_INCOMPLETE_DECL hook_void_tree // sdcpp c_finish_incomplete_decl
+#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL hook_bool_const_tree_false // sdcpp c_warn_unused_global_decl
+#undef LANG_HOOKS_PRINT_IDENTIFIER
+#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
+#undef LANG_HOOKS_TYPES_COMPATIBLE_P
+#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
+#undef LANG_HOOKS_MISSING_NORETURN_OK_P
+#define LANG_HOOKS_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
+#undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
+#define LANG_HOOKS_BLOCK_MAY_FALLTHRU c_block_may_fallthru
+#undef LANG_HOOKS_BUILTIN_FUNCTION
+#define LANG_HOOKS_BUILTIN_FUNCTION NULL // sdcpp c_builtin_function
+#undef LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE
+#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE NULL // sdcpp c_builtin_function_ext_scope
+#undef LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL
+#define LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL \
+ NULL // sdcpp c_simulate_builtin_function_decl
+#undef LANG_HOOKS_EMITS_BEGIN_STMT
+#define LANG_HOOKS_EMITS_BEGIN_STMT true
+#undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
+#define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
+
+/* Attribute hooks. */
+#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
+#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
+
+#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
+#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
+
+#undef LANG_HOOKS_SIMULATE_ENUM_DECL
+#define LANG_HOOKS_SIMULATE_ENUM_DECL NULL // sdcpp c_simulate_enum_decl
+#undef LANG_HOOKS_SIMULATE_RECORD_DECL
+#define LANG_HOOKS_SIMULATE_RECORD_DECL NULL // sdcpp c_simulate_record_decl
+#undef LANG_HOOKS_TYPE_FOR_MODE
+#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
+#undef LANG_HOOKS_TYPE_FOR_SIZE
+#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
+#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR NULL // sdcpp c_incomplete_type_error
+#undef LANG_HOOKS_TYPE_PROMOTES_TO
+#define LANG_HOOKS_TYPE_PROMOTES_TO NULL // sdcpp c_type_promotes_to
+#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
+#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
+#undef LANG_HOOKS_TO_TARGET_CHARSET
+#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
+#undef LANG_HOOKS_EXPR_TO_DECL
+#define LANG_HOOKS_EXPR_TO_DECL NULL // sdcpp c_expr_to_decl
+
+/* The C front end's scoping structure is very different from
+ that expected by the language-independent code; it is best
+ to disable getdecls.
+ This means it must also provide its own write_globals. */
+
+#undef LANG_HOOKS_GETDECLS
+#define LANG_HOOKS_GETDECLS hook_tree_void_null
+
+/* Hooks for tree gimplification. */
+#undef LANG_HOOKS_GIMPLIFY_EXPR
+#define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr
+
+#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
+#define LANG_HOOKS_OMP_PREDETERMINED_SHARING NULL // c_omp_predetermined_sharing
+
+#undef LANG_HOOKS_OMP_PREDETERMINED_MAPPING
+#define LANG_HOOKS_OMP_PREDETERMINED_MAPPING NULL // c_omp_predetermined_mapping
+
+#undef LANG_HOOKS_OMP_CLAUSE_COPY_CTOR
+#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR NULL // c_omp_clause_copy_ctor
+
+#undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
+#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP NULL // c_omp_clause_copy_ctor
+
+#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
+#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P hook_bool_tree_tree_false // c_vla_unspec_p
+#endif /* GCC_C_OBJC_COMMON */
diff --git a/support/cpp/gcc/c/c-parser.h b/support/cpp/gcc/c/c-parser.h
new file mode 100644
index 000000000..ab14d7101
--- /dev/null
+++ b/support/cpp/gcc/c/c-parser.h
@@ -0,0 +1,200 @@
+/* Declarations for the parser for C and Objective-C.
+ Copyright (C) 1987-2022 Free Software Foundation, Inc.
+
+ Parser actions based on the old Bison parser; structure somewhat
+ influenced by and fragments based on the C++ parser.
+
+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_C_PARSER_H
+#define GCC_C_PARSER_H
+
+#include "c-family/c-common.h"
+#include "c-family/c-pragma.h"
+
+/* The C lexer intermediates between the lexer in cpplib and c-lex.cc
+ and the C parser. Unlike the C++ lexer, the parser structure
+ stores the lexer information instead of using a separate structure.
+ Identifiers are separated into ordinary identifiers, type names,
+ keywords and some other Objective-C types of identifiers, and some
+ look-ahead is maintained.
+
+ ??? It might be a good idea to lex the whole file up front (as for
+ C++). It would then be possible to share more of the C and C++
+ lexer code, if desired. */
+
+/* More information about the type of a CPP_NAME token. */
+enum c_id_kind {
+ /* An ordinary identifier. */
+ C_ID_ID,
+ /* An identifier declared as a typedef name. */
+ C_ID_TYPENAME,
+ /* An identifier declared as an Objective-C class name. */
+ C_ID_CLASSNAME,
+ /* An address space identifier. */
+ C_ID_ADDRSPACE,
+ /* Not an identifier. */
+ C_ID_NONE
+};
+
+/* A single C token after string literal concatenation and conversion
+ of preprocessing tokens to tokens. */
+struct GTY (()) c_token {
+ /* The kind of token. */
+ ENUM_BITFIELD (cpp_ttype) type : 8;
+ /* If this token is a CPP_NAME, this value indicates whether also
+ declared as some kind of type. Otherwise, it is C_ID_NONE. */
+ ENUM_BITFIELD (c_id_kind) id_kind : 8;
+ /* If this token is a keyword, this value indicates which keyword.
+ Otherwise, this value is RID_MAX. */
+ ENUM_BITFIELD (rid) keyword : 8;
+ /* If this token is a CPP_PRAGMA, this indicates the pragma that
+ was seen. Otherwise it is PRAGMA_NONE. */
+ ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
+ /* The location at which this token was found. */
+ location_t location;
+ /* The value associated with this token, if any. */
+ tree value;
+ /* Token flags. */
+ unsigned char flags;
+
+ source_range get_range () const
+ {
+ return get_range_from_loc (line_table, location);
+ }
+
+ location_t get_finish () const
+ {
+ return get_range ().m_finish;
+ }
+};
+
+/* The parser. */
+struct c_parser;
+
+/* Possibly kinds of declarator to parse. */
+enum c_dtr_syn {
+ /* A normal declarator with an identifier. */
+ C_DTR_NORMAL,
+ /* An abstract declarator (maybe empty). */
+ C_DTR_ABSTRACT,
+ /* A parameter declarator: may be either, but after a type name does
+ not redeclare a typedef name as an identifier if it can
+ alternatively be interpreted as a typedef name; see DR#009,
+ applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
+ following DR#249. For example, given a typedef T, "int T" and
+ "int *T" are valid parameter declarations redeclaring T, while
+ "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
+ abstract declarators rather than involving redundant parentheses;
+ the same applies with attributes inside the parentheses before
+ "T". */
+ C_DTR_PARM
+};
+
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+ used for the bottom of the stack. */
+enum c_parser_prec {
+ PREC_NONE,
+ PREC_LOGOR,
+ PREC_LOGAND,
+ PREC_BITOR,
+ PREC_BITXOR,
+ PREC_BITAND,
+ PREC_EQ,
+ PREC_REL,
+ PREC_SHIFT,
+ PREC_ADD,
+ PREC_MULT,
+ NUM_PRECS
+};
+
+enum c_lookahead_kind {
+ /* Always treat unknown identifiers as typenames. */
+ cla_prefer_type,
+
+ /* Could be parsing a nonabstract declarator. Only treat an identifier
+ as a typename if followed by another identifier or a star. */
+ cla_nonabstract_decl,
+
+ /* Never treat identifiers as typenames. */
+ cla_prefer_id
+};
+
+
+extern c_token * c_parser_peek_token (c_parser *parser);
+extern c_token * c_parser_peek_2nd_token (c_parser *parser);
+extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n);
+extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
+ const char *msgid,
+ location_t matching_location = UNKNOWN_LOCATION,
+ bool type_is_unique=true);
+extern bool c_parser_error (c_parser *parser, const char *gmsgid);
+extern void c_parser_consume_token (c_parser *parser);
+extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
+ const char *msgid,
+ location_t = UNKNOWN_LOCATION);
+extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
+bool c_parser_next_tokens_start_declaration (c_parser *parser);
+bool c_token_starts_typename (c_token *token);
+
+/* Abstraction to avoid defining c_parser here which messes up gengtype
+ output wrt ObjC due to vec<c_token> routines being put in gtype-c.h
+ but not gtype-objc.h. */
+extern c_token * c_parser_tokens_buf (c_parser *parser, unsigned n);
+extern bool c_parser_error (c_parser *parser);
+extern void c_parser_set_error (c_parser *parser, bool);
+
+/* A bit of a hack to have this here. It would be better in a c-decl.h. */
+extern bool old_style_parameter_scope (void);
+
+/* Return true if the next token from PARSER has the indicated
+ TYPE. */
+
+static inline bool
+c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
+{
+ return c_parser_peek_token (parser)->type == type;
+}
+
+/* Return true if the next token from PARSER does not have the
+ indicated TYPE. */
+
+static inline bool
+c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
+{
+ return !c_parser_next_token_is (parser, type);
+}
+
+/* Return true if the next token from PARSER is the indicated
+ KEYWORD. */
+
+static inline bool
+c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
+{
+ return c_parser_peek_token (parser)->keyword == keyword;
+}
+
+struct c_expr c_parser_string_literal (c_parser *, bool, bool);
+extern struct c_declarator *
+c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+ bool *seen_id);
+extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
+ bool, bool, bool, bool, bool,
+ enum c_lookahead_kind);
+extern struct c_type_name *c_parser_type_name (c_parser *, bool = false);
+
+#endif
diff --git a/support/cpp/gcc/c/c-tree.h b/support/cpp/gcc/c/c-tree.h
new file mode 100644
index 000000000..469d59f87
--- /dev/null
+++ b/support/cpp/gcc/c/c-tree.h
@@ -0,0 +1,857 @@
+/* Definitions for C parsing and type checking.
+ 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/>. */
+
+#ifndef GCC_C_TREE_H
+#define GCC_C_TREE_H
+
+#include "c-family/c-common.h"
+#if 0 // sdcpp
+#include "diagnostic.h"
+
+/* struct lang_identifier is private to c-decl.cc, but langhooks.cc needs to
+ know how big it is. This is sanity-checked in c-decl.cc. */
+#endif // sdcpp
+#define C_SIZEOF_STRUCT_LANG_IDENTIFIER \
+ (sizeof (struct c_common_identifier) + 3 * sizeof (void *))
+#if 0 // sdcpp
+
+/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */
+#define C_TYPE_FIELDS_READONLY(TYPE) TREE_LANG_FLAG_1 (TYPE)
+
+/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is volatile. */
+#define C_TYPE_FIELDS_VOLATILE(TYPE) TREE_LANG_FLAG_2 (TYPE)
+
+/* In a RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE
+ nonzero if the definition of the type has already started. */
+#define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
+
+/* In an incomplete RECORD_TYPE, UNION_TYPE or ENUMERAL_TYPE, a list of
+ variable declarations whose type would be completed by completing
+ that type. */
+#define C_TYPE_INCOMPLETE_VARS(TYPE) \
+ TYPE_LANG_SLOT_1 (TREE_CHECK4 (TYPE, RECORD_TYPE, UNION_TYPE, \
+ QUAL_UNION_TYPE, ENUMERAL_TYPE))
+
+/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
+ keyword. C_RID_CODE (node) is then the RID_* value of the keyword. */
+#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
+
+/* Record whether a type or decl was written with nonconstant size.
+ Note that TYPE_SIZE may have simplified to a constant. */
+#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
+#define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
+
+/* Record whether a type is defined inside a struct or union type.
+ This is used for -Wc++-compat. */
+#define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE)
+
+/* Record whether a typedef for type `int' was actually `signed int'. */
+#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
+
+/* For a FUNCTION_DECL, nonzero if it was defined without an explicit
+ return type. */
+#define C_FUNCTION_IMPLICIT_INT(EXP) DECL_LANG_FLAG_1 (EXP)
+
+/* For a FUNCTION_DECL, nonzero if it was an implicit declaration. */
+#define C_DECL_IMPLICIT(EXP) DECL_LANG_FLAG_2 (EXP)
+
+/* For a PARM_DECL, nonzero if it was declared as an array. */
+#define C_ARRAY_PARAMETER(NODE) DECL_LANG_FLAG_0 (NODE)
+
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in but has
+ been declared. */
+#define C_DECL_DECLARED_BUILTIN(EXP) \
+ DECL_LANG_FLAG_3 (FUNCTION_DECL_CHECK (EXP))
+
+/* For FUNCTION_DECLs, evaluates true if the decl is built-in, has a
+ built-in prototype and does not have a non-built-in prototype. */
+#define C_DECL_BUILTIN_PROTOTYPE(EXP) \
+ DECL_LANG_FLAG_6 (FUNCTION_DECL_CHECK (EXP))
+
+/* Record whether a decl was declared register. This is strictly a
+ front-end flag, whereas DECL_REGISTER is used for code generation;
+ they may differ for structures with volatile fields. */
+#define C_DECL_REGISTER(EXP) DECL_LANG_FLAG_4 (EXP)
+
+/* Record whether a decl was used in an expression anywhere except an
+ unevaluated operand of sizeof / typeof / alignof. This is only
+ used for functions declared static but not defined, though outside
+ sizeof and typeof it is set for other function decls as well. */
+#define C_DECL_USED(EXP) DECL_LANG_FLAG_5 (FUNCTION_DECL_CHECK (EXP))
+
+/* Record whether a variable has been declared threadprivate by
+ #pragma omp threadprivate. */
+#define C_DECL_THREADPRIVATE_P(DECL) DECL_LANG_FLAG_3 (VAR_DECL_CHECK (DECL))
+
+/* Set on VAR_DECLs for compound literals. */
+#define C_DECL_COMPOUND_LITERAL_P(DECL) \
+ DECL_LANG_FLAG_5 (VAR_DECL_CHECK (DECL))
+
+/* Nonzero for a decl which either doesn't exist or isn't a prototype.
+ N.B. Could be simplified if all built-in decls had complete prototypes
+ (but this is presently difficult because some of them need FILE*). */
+#define C_DECL_ISNT_PROTOTYPE(EXP) \
+ (EXP == 0 \
+ || (!prototype_p (TREE_TYPE (EXP)) \
+ && !fndecl_built_in_p (EXP)))
+
+/* For FUNCTION_TYPE, a hidden list of types of arguments. The same as
+ TYPE_ARG_TYPES for functions with prototypes, but created for functions
+ without prototypes. */
+#define TYPE_ACTUAL_ARG_TYPES(NODE) \
+ TYPE_LANG_SLOT_1 (FUNCTION_TYPE_CHECK (NODE))
+
+/* For a CONSTRUCTOR, whether some initializer contains a
+ subexpression meaning it is not a constant expression. */
+#define CONSTRUCTOR_NON_CONST(EXPR) TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (EXPR))
+
+/* For a SAVE_EXPR, nonzero if the operand of the SAVE_EXPR has already
+ been folded. */
+#define SAVE_EXPR_FOLDED_P(EXP) TREE_LANG_FLAG_1 (SAVE_EXPR_CHECK (EXP))
+
+/* Record parser information about an expression that is irrelevant
+ for code generation alongside a tree representing its value. */
+struct c_expr
+{
+ /* The value of the expression. */
+ tree value;
+ /* Record the original unary/binary operator of an expression, which may
+ have been changed by fold, STRING_CST for unparenthesized string
+ constants, C_MAYBE_CONST_EXPR for __builtin_constant_p calls
+ (even if parenthesized), for subexpressions, and for non-constant
+ initializers, or ERROR_MARK for other expressions (including
+ parenthesized expressions). */
+ enum tree_code original_code;
+ /* If not NULL, the original type of an expression. This will
+ differ from the type of the value field for an enum constant.
+ The type of an enum constant is a plain integer type, but this
+ field will be the enum type. */
+ tree original_type;
+
+ /* The source range of this expression. This is redundant
+ for node values that have locations, but not all node kinds
+ have locations (e.g. constants, and references to params, locals,
+ etc), so we stash a copy here. */
+ source_range src_range;
+
+ /* Access to the first and last locations within the source spelling
+ of this expression. */
+ location_t get_start () const { return src_range.m_start; }
+ location_t get_finish () const { return src_range.m_finish; }
+
+ location_t get_location () const
+ {
+ if (EXPR_HAS_LOCATION (value))
+ return EXPR_LOCATION (value);
+ else
+ return make_location (get_start (), get_start (), get_finish ());
+ }
+
+ /* Set the value to error_mark_node whilst ensuring that src_range
+ is initialized. */
+ void set_error ()
+ {
+ value = error_mark_node;
+ src_range.m_start = UNKNOWN_LOCATION;
+ src_range.m_finish = UNKNOWN_LOCATION;
+ }
+};
+
+/* Type alias for struct c_expr. This allows to use the structure
+ inside the VEC types. */
+typedef struct c_expr c_expr_t;
+
+/* A kind of type specifier. Note that this information is currently
+ only used to distinguish tag definitions, tag references and typeof
+ uses. */
+enum c_typespec_kind {
+ /* No typespec. This appears only in struct c_declspec. */
+ ctsk_none,
+ /* A reserved keyword type specifier. */
+ ctsk_resword,
+ /* A reference to a tag, previously declared, such as "struct foo".
+ This includes where the previous declaration was as a different
+ kind of tag, in which case this is only valid if shadowing that
+ tag in an inner scope. */
+ ctsk_tagref,
+ /* Likewise, with standard attributes present in the reference. */
+ ctsk_tagref_attrs,
+ /* A reference to a tag, not previously declared in a visible
+ scope. */
+ ctsk_tagfirstref,
+ /* Likewise, with standard attributes present in the reference. */
+ ctsk_tagfirstref_attrs,
+ /* A definition of a tag such as "struct foo { int a; }". */
+ ctsk_tagdef,
+ /* A typedef name. */
+ ctsk_typedef,
+ /* An ObjC-specific kind of type specifier. */
+ ctsk_objc,
+ /* A typeof specifier, or _Atomic ( type-name ). */
+ ctsk_typeof
+};
+
+/* A type specifier: this structure is created in the parser and
+ passed to declspecs_add_type only. */
+struct c_typespec {
+ /* What kind of type specifier this is. */
+ enum c_typespec_kind kind;
+ /* Whether the expression has operands suitable for use in constant
+ expressions. */
+ bool expr_const_operands;
+ /* The specifier itself. */
+ tree spec;
+ /* An expression to be evaluated before the type specifier, in the
+ case of typeof specifiers, or NULL otherwise or if no such
+ expression is required for a particular typeof specifier. In
+ particular, when typeof is applied to an expression of variably
+ modified type, that expression must be evaluated in order to
+ determine array sizes that form part of the type, but the
+ expression itself (as opposed to the array sizes) forms no part
+ of the type and so needs to be recorded separately. */
+ tree expr;
+};
+
+/* A storage class specifier. */
+enum c_storage_class {
+ csc_none,
+ csc_auto,
+ csc_extern,
+ csc_register,
+ csc_static,
+ csc_typedef
+};
+
+/* A type specifier keyword "void", "_Bool", "char", "int", "float",
+ "double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum",
+ or none of these. */
+enum c_typespec_keyword {
+ cts_none,
+ cts_void,
+ cts_bool,
+ cts_char,
+ cts_int,
+ cts_float,
+ cts_int_n,
+ cts_double,
+ cts_dfloat32,
+ cts_dfloat64,
+ cts_dfloat128,
+ cts_floatn_nx,
+ cts_fract,
+ cts_accum,
+ cts_auto_type
+};
+
+/* This enum lists all the possible declarator specifiers, storage
+ class or attribute that a user can write. There is at least one
+ enumerator per possible declarator specifier in the struct
+ c_declspecs below.
+
+ It is used to index the array of declspec locations in struct
+ c_declspecs. */
+enum c_declspec_word {
+ cdw_typespec /* A catch-all for a typespec. */,
+ cdw_storage_class /* A catch-all for a storage class */,
+ cdw_attributes,
+ cdw_typedef,
+ cdw_explicit_signed,
+ cdw_deprecated,
+ cdw_default_int,
+ cdw_long,
+ cdw_long_long,
+ cdw_short,
+ cdw_signed,
+ cdw_unsigned,
+ cdw_complex,
+ cdw_inline,
+ cdw_noreturn,
+ cdw_thread,
+ cdw_const,
+ cdw_volatile,
+ cdw_restrict,
+ cdw_atomic,
+ cdw_saturating,
+ cdw_alignas,
+ cdw_address_space,
+ cdw_gimple,
+ cdw_rtl,
+ cdw_number_of_elements /* This one must always be the last
+ enumerator. */
+};
+
+enum c_declspec_il {
+ cdil_none,
+ cdil_gimple, /* __GIMPLE */
+ cdil_gimple_cfg, /* __GIMPLE(cfg) */
+ cdil_gimple_ssa, /* __GIMPLE(ssa) */
+ cdil_rtl /* __RTL */
+};
+
+/* A sequence of declaration specifiers in C. When a new declaration
+ specifier is added, please update the enum c_declspec_word above
+ accordingly. */
+struct c_declspecs {
+ location_t locations[cdw_number_of_elements];
+ /* The type specified, if a single type specifier such as a struct,
+ union or enum specifier, typedef name or typeof specifies the
+ whole type, or NULL_TREE if none or a keyword such as "void" or
+ "char" is used. Does not include qualifiers. */
+ tree type;
+ /* Any expression to be evaluated before the type, from a typeof
+ specifier. */
+ tree expr;
+ /* The attributes from a typedef decl. */
+ tree decl_attr;
+ /* When parsing, the GNU attributes and prefix standard attributes.
+ Outside the parser, this will be NULL; attributes (possibly from
+ multiple lists) will be passed separately. */
+ tree attrs;
+ /* When parsing, postfix standard attributes (which appertain to the
+ type specified by the preceding declaration specifiers, unlike
+ prefix standard attributes which appertain to the declaration or
+ declarations as a whole). */
+ tree postfix_attrs;
+ /* The pass to start compiling a __GIMPLE or __RTL function with. */
+ char *gimple_or_rtl_pass;
+ /* ENTRY BB count. */
+ profile_count entry_bb_count;
+ /* The base-2 log of the greatest alignment required by an _Alignas
+ specifier, in bytes, or -1 if no such specifiers with nonzero
+ alignment. */
+ int align_log;
+ /* For the __intN declspec, this stores the index into the int_n_* arrays. */
+ int int_n_idx;
+ /* For the _FloatN and _FloatNx declspec, this stores the index into
+ the floatn_nx_types array. */
+ int floatn_nx_idx;
+ /* The storage class specifier, or csc_none if none. */
+ enum c_storage_class storage_class;
+ /* Any type specifier keyword used such as "int", not reflecting
+ modifiers such as "short", or cts_none if none. */
+ ENUM_BITFIELD (c_typespec_keyword) typespec_word : 8;
+ /* The kind of type specifier if one has been seen, ctsk_none
+ otherwise. */
+ ENUM_BITFIELD (c_typespec_kind) typespec_kind : 4;
+ ENUM_BITFIELD (c_declspec_il) declspec_il : 3;
+ /* Whether any expressions in typeof specifiers may appear in
+ constant expressions. */
+ BOOL_BITFIELD expr_const_operands : 1;
+ /* Whether any declaration specifiers have been seen at all. */
+ BOOL_BITFIELD declspecs_seen_p : 1;
+ /* Whether any declaration specifiers other than standard attributes
+ have been seen at all. If only standard attributes have been
+ seen, this is an attribute-declaration. */
+ BOOL_BITFIELD non_std_attrs_seen_p : 1;
+ /* Whether something other than a storage class specifier or
+ attribute has been seen. This is used to warn for the
+ obsolescent usage of storage class specifiers other than at the
+ start of the list. (Doing this properly would require function
+ specifiers to be handled separately from storage class
+ specifiers.) */
+ BOOL_BITFIELD non_sc_seen_p : 1;
+ /* Whether the type is specified by a typedef or typeof name. */
+ BOOL_BITFIELD typedef_p : 1;
+ /* Whether the type is explicitly "signed" or specified by a typedef
+ whose type is explicitly "signed". */
+ BOOL_BITFIELD explicit_signed_p : 1;
+ /* Whether the specifiers include a deprecated typedef. */
+ BOOL_BITFIELD deprecated_p : 1;
+ /* Whether the specifiers include an unavailable typedef. */
+ BOOL_BITFIELD unavailable_p : 1;
+ /* Whether the type defaulted to "int" because there were no type
+ specifiers. */
+ BOOL_BITFIELD default_int_p : 1;
+ /* Whether "long" was specified. */
+ BOOL_BITFIELD long_p : 1;
+ /* Whether "long" was specified more than once. */
+ BOOL_BITFIELD long_long_p : 1;
+ /* Whether "short" was specified. */
+ BOOL_BITFIELD short_p : 1;
+ /* Whether "signed" was specified. */
+ BOOL_BITFIELD signed_p : 1;
+ /* Whether "unsigned" was specified. */
+ BOOL_BITFIELD unsigned_p : 1;
+ /* Whether "complex" was specified. */
+ BOOL_BITFIELD complex_p : 1;
+ /* Whether "inline" was specified. */
+ BOOL_BITFIELD inline_p : 1;
+ /* Whether "_Noreturn" was speciied. */
+ BOOL_BITFIELD noreturn_p : 1;
+ /* Whether "__thread" or "_Thread_local" was specified. */
+ BOOL_BITFIELD thread_p : 1;
+ /* Whether "__thread" rather than "_Thread_local" was specified. */
+ BOOL_BITFIELD thread_gnu_p : 1;
+ /* Whether "const" was specified. */
+ BOOL_BITFIELD const_p : 1;
+ /* Whether "volatile" was specified. */
+ BOOL_BITFIELD volatile_p : 1;
+ /* Whether "restrict" was specified. */
+ BOOL_BITFIELD restrict_p : 1;
+ /* Whether "_Atomic" was specified. */
+ BOOL_BITFIELD atomic_p : 1;
+ /* Whether "_Sat" was specified. */
+ BOOL_BITFIELD saturating_p : 1;
+ /* Whether any alignment specifier (even with zero alignment) was
+ specified. */
+ BOOL_BITFIELD alignas_p : 1;
+ /* The address space that the declaration belongs to. */
+ addr_space_t address_space;
+};
+
+/* The various kinds of declarators in C. */
+enum c_declarator_kind {
+ /* An identifier. */
+ cdk_id,
+ /* A function. */
+ cdk_function,
+ /* An array. */
+ cdk_array,
+ /* A pointer. */
+ cdk_pointer,
+ /* Parenthesized declarator with nested attributes. */
+ cdk_attrs
+};
+
+struct c_arg_tag {
+ /* The argument name. */
+ tree id;
+ /* The type of the argument. */
+ tree type;
+};
+
+
+/* Information about the parameters in a function declarator. */
+struct c_arg_info {
+ /* A list of parameter decls. */
+ tree parms;
+ /* A list of structure, union and enum tags defined. */
+ vec<c_arg_tag, va_gc> *tags;
+ /* A list of argument types to go in the FUNCTION_TYPE. */
+ tree types;
+ /* A list of non-parameter decls (notably enumeration constants)
+ defined with the parameters. */
+ tree others;
+ /* A compound expression of VLA sizes from the parameters, or NULL.
+ In a function definition, these are used to ensure that
+ side-effects in sizes of arrays converted to pointers (such as a
+ parameter int i[n++]) take place; otherwise, they are
+ ignored. */
+ tree pending_sizes;
+ /* True when these arguments had [*]. */
+ BOOL_BITFIELD had_vla_unspec : 1;
+};
+
+/* A declarator. */
+struct c_declarator {
+ /* The kind of declarator. */
+ enum c_declarator_kind kind;
+ location_t id_loc; /* Currently only set for cdk_id, cdk_array. */
+ /* Except for cdk_id, the contained declarator. For cdk_id, NULL. */
+ struct c_declarator *declarator;
+ union {
+ /* For identifiers. */
+ struct {
+ /* An IDENTIFIER_NODE, or NULL_TREE if an abstract
+ declarator. */
+ tree id;
+ /* Any attributes (which apply to the declaration rather than to
+ the type described by the outer declarators). */
+ tree attrs;
+ } id;
+ /* For functions. */
+ struct c_arg_info *arg_info;
+ /* For arrays. */
+ struct {
+ /* The array dimension, or NULL for [] and [*]. */
+ tree dimen;
+ /* The qualifiers inside []. */
+ int quals;
+ /* The attributes (currently ignored) inside []. */
+ tree attrs;
+ /* Whether [static] was used. */
+ BOOL_BITFIELD static_p : 1;
+ /* Whether [*] was used. */
+ BOOL_BITFIELD vla_unspec_p : 1;
+ } array;
+ /* For pointers, the qualifiers on the pointer type. */
+ int pointer_quals;
+ /* For attributes. */
+ tree attrs;
+ } u;
+};
+
+/* A type name. */
+struct c_type_name {
+ /* The declaration specifiers. */
+ struct c_declspecs *specs;
+ /* The declarator. */
+ struct c_declarator *declarator;
+};
+
+/* A parameter. */
+struct c_parm {
+ /* The declaration specifiers, minus any prefix attributes. */
+ struct c_declspecs *specs;
+ /* The attributes. */
+ tree attrs;
+ /* The declarator. */
+ struct c_declarator *declarator;
+ /* The location of the parameter. */
+ location_t loc;
+};
+
+/* Used when parsing an enum. Initialized by start_enum. */
+struct c_enum_contents
+{
+ /* While defining an enum type, this is 1 plus the last enumerator
+ constant value. */
+ tree enum_next_value;
+
+ /* Nonzero means that there was overflow computing enum_next_value. */
+ int enum_overflow;
+};
+
+/* A type of reference to a static identifier in an inline
+ function. */
+enum c_inline_static_type {
+ /* Identifier with internal linkage used in function that may be an
+ inline definition (i.e., file-scope static). */
+ csi_internal,
+ /* Modifiable object with static storage duration defined in
+ function that may be an inline definition (i.e., local
+ static). */
+ csi_modifiable
+};
+
+
+/* in c-parser.cc */
+extern void c_parse_init (void);
+extern bool c_keyword_starts_typename (enum rid keyword);
+
+/* in c-aux-info.cc */
+extern void gen_aux_info_record (tree, int, int, int);
+
+/* in c-decl.cc */
+struct c_spot_bindings;
+class c_struct_parse_info;
+extern struct obstack parser_obstack;
+/* Set to IN_ITERATION_STMT if parsing an iteration-statement,
+ to IN_OMP_BLOCK if parsing OpenMP structured block and
+ IN_OMP_FOR if parsing OpenMP loop. If parsing a switch statement,
+ this is bitwise ORed with IN_SWITCH_STMT, unless parsing an
+ iteration-statement, OpenMP block or loop within that switch. */
+#define IN_SWITCH_STMT 1
+#define IN_ITERATION_STMT 2
+#define IN_OMP_BLOCK 4
+#define IN_OMP_FOR 8
+#define IN_OBJC_FOREACH 16
+extern unsigned char in_statement;
+
+extern bool switch_statement_break_seen_p;
+
+#endif // sdcpp
+extern bool global_bindings_p (void);
+extern tree pushdecl (tree);
+extern void push_scope (void);
+extern tree pop_scope (void);
+extern void c_bindings_start_stmt_expr (struct c_spot_bindings *);
+extern void c_bindings_end_stmt_expr (struct c_spot_bindings *);
+#if 0 // sdcpp
+
+extern void record_inline_static (location_t, tree, tree,
+ enum c_inline_static_type);
+extern void c_init_decl_processing (void);
+#endif // sdcpp
+extern void c_print_identifier (FILE *, tree, int);
+#if 0 // sdcpp
+extern int quals_from_declspecs (const struct c_declspecs *);
+extern struct c_declarator *build_array_declarator (location_t, tree,
+ struct c_declspecs *,
+ bool, bool);
+extern tree build_enumerator (location_t, location_t, struct c_enum_contents *,
+ tree, tree);
+extern tree check_for_loop_decls (location_t, bool);
+extern void mark_forward_parm_decls (void);
+extern void declare_parm_level (void);
+extern void undeclared_variable (location_t, tree);
+extern tree lookup_label_for_goto (location_t, tree);
+extern tree declare_label (tree);
+extern tree define_label (location_t, tree);
+extern struct c_spot_bindings *c_get_switch_bindings (void);
+extern void c_release_switch_bindings (struct c_spot_bindings *);
+extern bool c_check_switch_jump_warnings (struct c_spot_bindings *,
+ location_t, location_t);
+extern void finish_decl (tree, location_t, tree, tree, tree);
+extern tree finish_enum (tree, tree, tree);
+extern void finish_function (location_t = input_location);
+extern tree finish_struct (location_t, tree, tree, tree,
+ class c_struct_parse_info *);
+extern tree c_simulate_enum_decl (location_t, const char *,
+ vec<string_int_pair> *);
+extern tree c_simulate_record_decl (location_t, const char *,
+ array_slice<const tree>);
+extern struct c_arg_info *build_arg_info (void);
+extern struct c_arg_info *get_parm_info (bool, tree);
+extern tree grokfield (location_t, struct c_declarator *,
+ struct c_declspecs *, tree, tree *);
+extern tree groktypename (struct c_type_name *, tree *, bool *);
+extern tree grokparm (const struct c_parm *, tree *);
+extern tree implicitly_declare (location_t, tree);
+extern void keep_next_level (void);
+extern void pending_xref_error (void);
+extern void c_push_function_context (void);
+extern void c_pop_function_context (void);
+extern void push_parm_decl (const struct c_parm *, tree *);
+extern struct c_declarator *set_array_declarator_inner (struct c_declarator *,
+ struct c_declarator *);
+extern tree c_builtin_function (tree);
+extern tree c_builtin_function_ext_scope (tree);
+extern tree c_simulate_builtin_function_decl (tree);
+extern void c_warn_unused_attributes (tree);
+extern tree c_warn_type_attributes (tree);
+extern void shadow_tag (const struct c_declspecs *);
+extern void shadow_tag_warned (const struct c_declspecs *, int);
+extern tree start_enum (location_t, struct c_enum_contents *, tree);
+extern bool start_function (struct c_declspecs *, struct c_declarator *, tree);
+extern tree start_decl (struct c_declarator *, struct c_declspecs *, bool,
+ tree, location_t * = NULL);
+extern tree start_struct (location_t, enum tree_code, tree,
+ class c_struct_parse_info **);
+extern void store_parm_decls (void);
+extern void store_parm_decls_from (struct c_arg_info *);
+extern void temp_store_parm_decls (tree, tree);
+extern void temp_pop_parm_decls (void);
+extern tree xref_tag (enum tree_code, tree);
+extern struct c_typespec parser_xref_tag (location_t, enum tree_code, tree,
+ bool, tree);
+extern struct c_parm *build_c_parm (struct c_declspecs *, tree,
+ struct c_declarator *, location_t);
+extern struct c_declarator *build_attrs_declarator (tree,
+ struct c_declarator *);
+extern struct c_declarator *build_function_declarator (struct c_arg_info *,
+ struct c_declarator *);
+extern struct c_declarator *build_id_declarator (tree);
+extern struct c_declarator *make_pointer_declarator (struct c_declspecs *,
+ struct c_declarator *);
+extern struct c_declspecs *build_null_declspecs (void);
+extern struct c_declspecs *declspecs_add_qual (location_t,
+ struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_type (location_t,
+ struct c_declspecs *,
+ struct c_typespec);
+extern struct c_declspecs *declspecs_add_scspec (location_t,
+ struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_attrs (location_t,
+ struct c_declspecs *, tree);
+extern struct c_declspecs *declspecs_add_addrspace (location_t,
+ struct c_declspecs *,
+ addr_space_t);
+extern struct c_declspecs *declspecs_add_alignas (location_t,
+ struct c_declspecs *, tree);
+extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
+
+/* in c-objc-common.cc */
+#endif // sdcpp
+extern bool c_objc_common_init (void);
+extern bool c_missing_noreturn_ok_p (tree);
+extern bool c_warn_unused_global_decl (const_tree);
+extern void c_initialize_diagnostics (diagnostic_context *);
+extern bool c_vla_unspec_p (tree x, tree fn);
+extern alias_set_type c_get_alias_set (tree);
+#if 0 // sdcpp
+
+/* in c-typeck.cc */
+extern int in_alignof;
+extern int in_sizeof;
+extern int in_typeof;
+extern bool c_in_omp_for;
+
+extern tree c_last_sizeof_arg;
+extern location_t c_last_sizeof_loc;
+
+extern struct c_switch *c_switch_stack;
+
+extern bool char_type_p (tree);
+extern tree c_objc_common_truthvalue_conversion (location_t, tree);
+extern tree require_complete_type (location_t, tree);
+extern bool same_translation_unit_p (const_tree, const_tree);
+extern int comptypes (tree, tree);
+extern int comptypes_check_different_types (tree, tree, bool *);
+extern bool c_vla_type_p (const_tree);
+extern bool c_mark_addressable (tree, bool = false);
+extern void c_incomplete_type_error (location_t, const_tree, const_tree);
+extern tree c_type_promotes_to (tree);
+extern struct c_expr default_function_array_conversion (location_t,
+ struct c_expr);
+extern struct c_expr default_function_array_read_conversion (location_t,
+ struct c_expr);
+extern struct c_expr convert_lvalue_to_rvalue (location_t, struct c_expr,
+ bool, bool);
+extern tree decl_constant_value_1 (tree, bool);
+extern void mark_exp_read (tree);
+extern tree composite_type (tree, tree);
+extern tree build_component_ref (location_t, tree, tree, location_t);
+extern tree build_array_ref (location_t, tree, tree);
+extern tree build_external_ref (location_t, tree, bool, tree *);
+extern void pop_maybe_used (bool);
+extern struct c_expr c_expr_sizeof_expr (location_t, struct c_expr);
+extern struct c_expr c_expr_sizeof_type (location_t, struct c_type_name *);
+extern struct c_expr parser_build_unary_op (location_t, enum tree_code,
+ struct c_expr);
+extern struct c_expr parser_build_binary_op (location_t,
+ enum tree_code, struct c_expr,
+ struct c_expr);
+extern tree build_conditional_expr (location_t, tree, bool, tree, tree,
+ location_t, tree, tree, location_t);
+extern tree build_compound_expr (location_t, tree, tree);
+extern tree c_cast_expr (location_t, struct c_type_name *, tree);
+extern tree build_c_cast (location_t, tree, tree);
+extern void store_init_value (location_t, tree, tree, tree);
+extern void maybe_warn_string_init (location_t, tree, struct c_expr);
+extern void start_init (tree, tree, int, rich_location *);
+extern void finish_init (void);
+extern void really_start_incremental_init (tree);
+extern void finish_implicit_inits (location_t, struct obstack *);
+extern void push_init_level (location_t, int, struct obstack *);
+extern struct c_expr pop_init_level (location_t, int, struct obstack *,
+ location_t);
+extern void set_init_index (location_t, tree, tree, struct obstack *);
+extern void set_init_label (location_t, tree, location_t, struct obstack *);
+extern void process_init_element (location_t, struct c_expr, bool,
+ struct obstack *);
+extern tree build_compound_literal (location_t, tree, tree, bool,
+ unsigned int);
+extern void check_compound_literal_type (location_t, struct c_type_name *);
+extern tree c_start_switch (location_t, location_t, tree, bool);
+extern void c_finish_switch (tree, tree);
+extern tree build_asm_expr (location_t, tree, tree, tree, tree, tree, bool,
+ bool);
+extern tree build_asm_stmt (bool, tree);
+#endif // sdcpp
+extern int c_types_compatible_p (tree, tree);
+#if 0 // sdcpp
+extern tree c_begin_compound_stmt (bool);
+extern tree c_end_compound_stmt (location_t, tree, bool);
+extern void c_finish_if_stmt (location_t, tree, tree, tree);
+extern void c_finish_loop (location_t, location_t, tree, location_t, tree,
+ tree, tree, tree, bool);
+extern tree c_begin_stmt_expr (void);
+extern tree c_finish_stmt_expr (location_t, tree);
+extern tree c_process_expr_stmt (location_t, tree);
+extern tree c_finish_expr_stmt (location_t, tree);
+extern tree c_finish_return (location_t, tree, tree);
+extern tree c_finish_bc_stmt (location_t, tree, bool);
+extern tree c_finish_goto_label (location_t, tree);
+extern tree c_finish_goto_ptr (location_t, c_expr val);
+extern tree c_expr_to_decl (tree, bool *, bool *);
+extern tree c_finish_omp_construct (location_t, enum tree_code, tree, tree);
+extern tree c_finish_oacc_data (location_t, tree, tree);
+extern tree c_finish_oacc_host_data (location_t, tree, tree);
+extern tree c_begin_omp_parallel (void);
+extern tree c_finish_omp_parallel (location_t, tree, tree);
+extern tree c_begin_omp_task (void);
+extern tree c_finish_omp_task (location_t, tree, tree);
+extern void c_finish_omp_cancel (location_t, tree);
+extern void c_finish_omp_cancellation_point (location_t, tree);
+extern tree c_finish_omp_clauses (tree, enum c_omp_region_type);
+extern tree c_build_va_arg (location_t, tree, location_t, tree);
+extern tree c_finish_transaction (location_t, tree, int);
+extern bool c_tree_equal (tree, tree);
+extern tree c_build_function_call_vec (location_t, const vec<location_t>&,
+ tree, vec<tree, va_gc> *,
+ vec<tree, va_gc> *);
+extern tree c_omp_clause_copy_ctor (tree, tree, tree);
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+ a return statement that specifies a return value is seen. */
+
+extern int current_function_returns_value;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+ a return statement with no argument is seen. */
+
+extern int current_function_returns_null;
+
+/* Set to 0 at beginning of a function definition, set to 1 if
+ a call to a noreturn function is seen. */
+
+extern int current_function_returns_abnormally;
+
+/* In c-decl.cc */
+
+/* Tell the binding oracle what kind of binding we are looking for. */
+
+enum c_oracle_request
+{
+ C_ORACLE_SYMBOL,
+ C_ORACLE_TAG,
+ C_ORACLE_LABEL
+};
+
+/* If this is non-NULL, then it is a "binding oracle" which can lazily
+ create bindings when needed by the C compiler. The oracle is told
+ the name and type of the binding to create. It can call pushdecl
+ or the like to ensure the binding is visible; or do nothing,
+ leaving the binding untouched. c-decl.cc takes note of when the
+ oracle has been called and will not call it again if it fails to
+ create a given binding. */
+
+typedef void c_binding_oracle_function (enum c_oracle_request, tree identifier);
+
+extern c_binding_oracle_function *c_binding_oracle;
+
+extern void c_finish_incomplete_decl (tree);
+extern tree c_omp_reduction_id (enum tree_code, tree);
+extern tree c_omp_reduction_decl (tree);
+extern tree c_omp_reduction_lookup (tree, tree);
+extern tree c_check_omp_declare_reduction_r (tree *, int *, void *);
+extern bool c_check_in_current_scope (tree);
+extern void c_pushtag (location_t, tree, tree);
+extern void c_bind (location_t, tree, bool);
+extern bool tag_exists_p (enum tree_code, tree);
+
+/* In c-errors.cc */
+extern bool pedwarn_c90 (location_t, int opt, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+extern bool pedwarn_c99 (location_t, int opt, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+extern bool pedwarn_c11 (location_t, int opt, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+
+extern void
+set_c_expr_source_range (c_expr *expr,
+ location_t start, location_t finish);
+
+extern void
+set_c_expr_source_range (c_expr *expr,
+ source_range src_range);
+
+/* In c-fold.cc */
+extern vec<tree> incomplete_record_decls;
+
+#if CHECKING_P
+namespace selftest {
+ extern void run_c_tests (void);
+} // namespace selftest
+#endif /* #if CHECKING_P */
+
+
+#endif // sdcpp
+#endif /* ! GCC_C_TREE_H */
diff --git a/support/cpp/gcc/c/config-lang.in b/support/cpp/gcc/c/config-lang.in
new file mode 100644
index 000000000..4526f634b
--- /dev/null
+++ b/support/cpp/gcc/c/config-lang.in
@@ -0,0 +1,32 @@
+# Top level configure fragment for GNU C - C language.
+# Copyright (C) 1994-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/>.
+
+# Configure looks for the existence of this file to auto-config each language.
+# We define several parameters used by configure:
+#
+# language - name of language as it would appear in $(LANGUAGES)
+# compilers - value to add to $(COMPILERS)
+
+language="c"
+
+compilers="cc1\$(exeext)"
+
+target_libs=
+
+gtfiles="\$(srcdir)/c/c-lang.cc \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.cc \$(srcdir)/c-family/c-common.cc \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.cc \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.cc \$(srcdir)/c-family/c-format.cc \$(srcdir)/c/c-objc-common.cc \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.cc \$(srcdir)/c/c-lang.h"
diff --git a/support/cpp/gcc/c/gimple-parser.cc b/support/cpp/gcc/c/gimple-parser.cc
new file mode 100644
index 000000000..48630b0fb
--- /dev/null
+++ b/support/cpp/gcc/c/gimple-parser.cc
@@ -0,0 +1 @@
+// dummy
diff --git a/support/cpp/gcc/cc1_dummies.cc b/support/cpp/gcc/cc1_dummies.cc
new file mode 100644
index 000000000..291e3c395
--- /dev/null
+++ b/support/cpp/gcc/cc1_dummies.cc
@@ -0,0 +1,318 @@
+// dummies for function used in cc1
+
+#define SDCPP_DUMMY_FCT() fprintf(stderr, "unreachable dummy in cc1%s\n", __func__); gcc_assert(false)
+#define untested() fprintf(stderr, "untested in cc1: %s\n", __func__)
+#define CC1_DUMMIES
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+
+#include "tree-core.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+
+#include "incpath.h"
+#include "c/c-parser.h"
+#include "substring-locations.h"
+#include "pass_manager.h"
+
+void bitmap_obstack_free(bitmap_head*)
+{ SDCPP_DUMMY_FCT();
+}
+void bitmap_obstack_release(bitmap_obstack*)
+{ SDCPP_DUMMY_FCT();
+}
+tree build_tree_list(tree_node*, tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return tree();
+}
+bool c_block_may_fallthru(tree_node const*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void c_common_read_pch(cpp_reader*, char const*, int, char const*)
+{ SDCPP_DUMMY_FCT();
+}
+int c_common_valid_pch(cpp_reader*, char const*, int)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+bool c_dump_tree(void*, tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int c_get_alias_set(tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int c_initialize_diagnostics(diagnostic_context*)
+{
+ return 0;
+}
+int c_gimplify_expr(tree_node**, gimple**, gimple**)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int c_missing_noreturn_ok_p(tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void c_parse_file()
+{ SDCPP_DUMMY_FCT();
+}
+void c_parse_final_cleanups()
+{ SDCPP_DUMMY_FCT();
+}
+void c_print_identifier(FILE*, tree_node*, int)
+{ SDCPP_DUMMY_FCT();
+}
+void c_stddef_cpp_builtins()
+{ SDCPP_DUMMY_FCT();
+}
+int c_types_compatible_p(tree_node*, tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void default_options_optimization(gcc_options*, gcc_options*, cl_decoded_option*, unsigned int, unsigned int, unsigned int, cl_option_handlers const*, diagnostic_context*)
+{
+}
+void define_language_independent_builtin_macros(cpp_reader*)
+{ untested();
+}
+void dump_end(int, FILE*)
+{ SDCPP_DUMMY_FCT();
+}
+void dbg_cnt_list_all_counters()
+{ SDCPP_DUMMY_FCT();
+}
+FILE* dump_begin(int, dump_flag*, int)
+{ SDCPP_DUMMY_FCT();
+ return NULL;
+}
+void dump_profile_report()
+{ SDCPP_DUMMY_FCT();
+}
+void dump_go_spec_init(char const*, const struct gcc_debug_hooks*)
+{ SDCPP_DUMMY_FCT();
+}
+bool dwarf2out_default_as_loc_support()
+{
+ return false;
+}
+bool dwarf2out_default_as_locview_support()
+{
+ return false;
+}
+void dwarf2out_do_cfi_asm()
+{ SDCPP_DUMMY_FCT();
+}
+void emergency_dump_function()
+{ untested();
+}
+void finalize_plugins()
+{
+}
+void gcc::dump_manager::register_dumps()
+{
+}
+int get_identifier(char const*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int ggc_mark_stringpool()
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int ggc_purge_stringpool()
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void gt_clear_caches()
+{ SDCPP_DUMMY_FCT();
+}
+void gt_ggc_m_S(void const*)
+{ SDCPP_DUMMY_FCT();
+}
+void gt_pch_note_reorder (void*, void*, gt_handle_reorder)
+{ SDCPP_DUMMY_FCT();
+}
+void gt_pch_p_S(void*, void*, void (*)(void*, void*, void*), void*)
+{ SDCPP_DUMMY_FCT();
+}
+int gt_pch_restore_stringpool()
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int gt_pch_save_stringpool()
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int hook_int_const_tree_int(tree_node const*, int)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void init_stringpool()
+{
+}
+void initialize_plugins()
+{
+}
+bool lang_GNU_C()
+{
+ return true;
+}
+void lhd_append_data(void const*, unsigned long, void*)
+{ SDCPP_DUMMY_FCT();
+}
+void lhd_begin_section(char const*)
+{ SDCPP_DUMMY_FCT();
+}
+bool lhd_decl_ok_for_sibcall(tree_node const*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+const char* lhd_decl_printable_name(tree_node*, int)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void lhd_do_nothing()
+{ untested();
+}
+void lhd_do_nothing_t(tree_node*)
+{ SDCPP_DUMMY_FCT();
+}
+const char* lhd_dwarf_name(tree_node*, int)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void lhd_end_section()
+{ SDCPP_DUMMY_FCT();
+}
+const char* lhd_get_substring_location(substring_loc const&, unsigned int*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void lhd_overwrite_decl_assembler_name(tree_node*, tree_node*)
+{ SDCPP_DUMMY_FCT();
+}
+void lhd_print_error_function(diagnostic_context*, char const*, diagnostic_info*)
+{ untested();
+}
+void lhd_print_tree_nothing(FILE*, tree_node*, int)
+{ SDCPP_DUMMY_FCT();
+}
+void lhd_set_decl_assembler_name(tree_node*)
+{ SDCPP_DUMMY_FCT();
+}
+int lhd_tree_dump_type_quals(tree_node const*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+size_t lhd_tree_size(tree_code)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+int lhd_type_dwarf_attribute(tree_node const*, int)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+bool names_builtin_p(char const*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void parse_basever(int*, int*, int*)
+{ SDCPP_DUMMY_FCT();
+}
+void pch_cpp_save_state()
+{
+}
+void pch_init()
+{ SDCPP_DUMMY_FCT();
+}
+void pop_file_scope()
+{ SDCPP_DUMMY_FCT();
+}
+void print_plugins_help(FILE*, char const*)
+{
+ // no-op
+}
+void push_file_scope()
+{ SDCPP_DUMMY_FCT();
+}
+int pushdecl(tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+void tree_diagnostics_defaults(diagnostic_context*)
+{
+}
+tree lhd_enum_underlying_base_type(tree_node const*)
+{ SDCPP_DUMMY_FCT();
+ return tree();
+}
+tree lhd_make_node(tree_code)
+{ SDCPP_DUMMY_FCT();
+ return tree();
+}
+tree* lhd_omp_get_decl_init(tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return 0;
+}
+tree lhd_pass_through_t(tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return tree();
+}
+void lhd_register_dumps(gcc::dump_manager*)
+{ untested();
+}
+tree lhd_return_null_const_tree(tree_node const*)
+{ SDCPP_DUMMY_FCT();
+ return tree();
+}
+tree lhd_unit_size_without_reusable_padding(tree_node*)
+{ SDCPP_DUMMY_FCT();
+ return tree();
+}
+void statistics_early_init()
+{
+}
+void virt_loc_aware_diagnostic_finalizer(diagnostic_context*, diagnostic_info*)
+{ untested();
+}
+void warn_if_plugins()
+{ untested();
+}
+/*----------------------------------------------------------------------*/
+namespace gcc{
+pass_manager::~pass_manager ()
+{ SDCPP_DUMMY_FCT();
+}
+pass_manager::pass_manager (context*)
+{ SDCPP_DUMMY_FCT();
+}
+dump_manager::~dump_manager()
+{ SDCPP_DUMMY_FCT();
+}
+dump_manager::dump_manager()
+{
+}
+}
+/*----------------------------------------------------------------------*/
+int after_memory_report;
+FILE *dump_file = NULL;
+extern const struct attribute_spec c_common_format_attribute_table[] =
+{
+ { "dummy", 3, 3, false, true, true, false,
+ NULL, NULL } };
+extern const struct attribute_spec c_common_attribute_table[] = {
+ { "dummy", 1, 1, false, true, false, true,
+ NULL, NULL } };
+struct ht *ident_hash;
+/*----------------------------------------------------------------------*/
+ggc_root_tab my_ggc_root_tab;
+const struct ggc_root_tab * const gt_ggc_deletable_rtab[] = { &my_ggc_root_tab };
+const struct ggc_root_tab * const gt_ggc_rtab[] = { &my_ggc_root_tab };
+const struct ggc_root_tab * const gt_pch_scalar_rtab[] = { &my_ggc_root_tab };
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
diff --git a/support/cpp/gcc/cfg-flags.def b/support/cpp/gcc/cfg-flags.def
new file mode 100644
index 000000000..a2c067651
--- /dev/null
+++ b/support/cpp/gcc/cfg-flags.def
@@ -0,0 +1,191 @@
+/* Flags on basic blocks and edges.
+ 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/>. */
+
+/* This file defines flags that may appear on basic blocks or on
+ edges. Source files define DEF_BASIC_BLOCK_FLAG or DEF_EDGE_FLAG
+ appropriately before including this file. */
+
+#if !defined(DEF_BASIC_BLOCK_FLAG) && !defined(DEF_EDGE_FLAG)
+#error "You must define DEF_BASIC_BLOCK_FLAG or DEF_EDGE_FLAG"
+#endif
+
+#ifdef DEF_BASIC_BLOCK_FLAG
+
+/* Masks for basic_block.flags.
+
+ The format of this file is: DEF_BASIC_BLOCK_FLAG(NAME, IDX).
+ NAME is the name of the basic block flag. A flag BB_#NAME will be
+ created and the name is used in dump_edge_info.
+ IDX is a sequence number that is used to determine the value
+ of the flag, which is 1 << IDX).
+
+ BB_HOT_PARTITION and BB_COLD_PARTITION should be preserved throughout
+ the compilation, so they are never cleared.
+
+ All other flags may be cleared by clear_bb_flags(). It is generally
+ a bad idea to rely on any flags being up-to-date. */
+
+/* Only set on blocks that have just been created by create_bb. */
+DEF_BASIC_BLOCK_FLAG(NEW, 0)
+
+/* Set by find_unreachable_blocks. Do not rely on this being set in any
+ pass. */
+DEF_BASIC_BLOCK_FLAG(REACHABLE, 1)
+
+/* Set for blocks in an irreducible loop by loop analysis. */
+DEF_BASIC_BLOCK_FLAG(IRREDUCIBLE_LOOP, 2)
+
+/* Set on blocks that may actually not be single-entry single-exit block. */
+DEF_BASIC_BLOCK_FLAG(SUPERBLOCK, 3)
+
+/* Set on basic blocks that the scheduler should not touch. This is used
+ by SMS to prevent other schedulers from messing with the loop schedule. */
+DEF_BASIC_BLOCK_FLAG(DISABLE_SCHEDULE, 4)
+
+/* Set on blocks that should be put in a hot section. */
+DEF_BASIC_BLOCK_FLAG(HOT_PARTITION, 5)
+
+/* Set on blocks that should be put in a cold section. */
+DEF_BASIC_BLOCK_FLAG(COLD_PARTITION, 6)
+
+/* Set on block that was duplicated. */
+DEF_BASIC_BLOCK_FLAG(DUPLICATED, 7)
+
+/* Set if the label at the top of this block is the target of a non-local goto. */
+DEF_BASIC_BLOCK_FLAG(NON_LOCAL_GOTO_TARGET, 8)
+
+/* Set on blocks that are in RTL format. */
+DEF_BASIC_BLOCK_FLAG(RTL, 9)
+
+/* Set on blocks that are forwarder blocks.
+ Only used in cfgcleanup.cc. */
+DEF_BASIC_BLOCK_FLAG(FORWARDER_BLOCK, 10)
+
+/* Set on blocks that cannot be threaded through.
+ Only used for jump threading. */
+DEF_BASIC_BLOCK_FLAG(NONTHREADABLE_BLOCK, 11)
+
+/* Set on blocks that were modified in some way. This bit is set in
+ df_set_bb_dirty, but not cleared by df_analyze, so it can be used
+ to test whether a block has been modified prior to a df_analyze call. */
+DEF_BASIC_BLOCK_FLAG(MODIFIED, 12)
+
+/* A general visited flag for passes to use. */
+DEF_BASIC_BLOCK_FLAG(VISITED, 13)
+
+/* Set on blocks that are in a transaction. This is calculated on
+ demand, and is available after calling compute_transaction_bits(). */
+DEF_BASIC_BLOCK_FLAG(IN_TRANSACTION, 14)
+
+#endif
+
+#ifdef DEF_EDGE_FLAG
+
+/* Masks for edge.flags.
+
+ The format of this file is: DEF_EDGE_FLAG(NAME, IDX, STRING).
+ NAME is the name of the edge flag. A flag EDGE_#NAME will be
+ created and the name is used in dump_edge_info.
+ IDX is a sequence number that is used to determine the value
+ of the flag, which is 1 << IDX). */
+
+/* 'Straight line' flow. In GIMPLE and in cfglayout mode, all normal
+ edges are fallthru edges. In cfgrtl mode, this flag really means
+ that control flow falls through to the next basic block in the line. */
+DEF_EDGE_FLAG(FALLTHRU, 0)
+
+/* Strange flow, like a computed jump or exception handling. Usually
+ this means that the edge cannot be split. */
+DEF_EDGE_FLAG(ABNORMAL, 1)
+
+/* Edge out of a basic block that ends with a CALL_INSN with abnormal
+ exit, like an exception or a non-local goto.
+ ABNORMAL_CALL edges also have ABNORMAL set.
+ This flag is only used for the RTL CFG. */
+DEF_EDGE_FLAG(ABNORMAL_CALL, 2)
+
+/* Exception edge. Exception handling edges represent possible control
+ transfers from a trapping instruction to an exception handler.
+ EH edges also have ABNORMAL set for the RTL CFG. */
+DEF_EDGE_FLAG(EH, 3)
+
+/* Never merge blocks via this edge. This is used for exception handling,
+ to prevent merging away edges to the post-landing-pad basic block.
+ This flag is only used for the RTL CFG. */
+DEF_EDGE_FLAG(PRESERVE, 4)
+
+/* Not a real edge. This is used to connect parts of the CFG that do
+ not halt, such as infinite loops and noreturn functions, to the
+ EXIT_BLOCK, so that traversing of the reverse CFG is possible. */
+DEF_EDGE_FLAG(FAKE, 5)
+
+/* A back edge, marked in a depth-first search of the CFG. Back edges
+ are hints that this edge may be part of a loop in the CFG. */
+DEF_EDGE_FLAG(DFS_BACK, 6)
+
+/* Edge in a part of the CFG that is an irreducible loop. */
+DEF_EDGE_FLAG(IRREDUCIBLE_LOOP, 7)
+
+/* Edge taken when controlling predicate is nonzero.
+ This is only used for the GIMPLE CFG. */
+DEF_EDGE_FLAG(TRUE_VALUE, 8)
+
+/* Edge taken when controlling predicate is zero.
+ This is only used for the GIMPLE CFG. */
+DEF_EDGE_FLAG(FALSE_VALUE, 9)
+
+/* Edge is executable. This is only used in GIMPLE SSA-CCP and VRP.
+ This is only used for the GIMPLE CFG. */
+DEF_EDGE_FLAG(EXECUTABLE, 10)
+
+/* Edge crosses between hot and cold sections, when we do partitioning.
+ This flag is only used for the RTL CFG. */
+DEF_EDGE_FLAG(CROSSING, 11)
+
+/* Edge from a sibcall CALL_INSN to exit.
+ SIBCALL edges also have ABNORMAL set.
+ This flag is only used for the RTL CFG. */
+DEF_EDGE_FLAG(SIBCALL, 12)
+
+/* Candidate for straight line flow. Only used in bb-reorder.cc.
+ This flag is only used for the RTL CFG. */
+DEF_EDGE_FLAG(CAN_FALLTHRU, 13)
+
+/* Exit of a loop. This is only used in ifcvt.cc.
+ This flag is only used for the RTL CFG. */
+DEF_EDGE_FLAG(LOOP_EXIT, 14)
+
+/* Uninstrumented edge out of a GIMPLE_TRANSACTION statement. */
+DEF_EDGE_FLAG(TM_UNINSTRUMENTED, 15)
+
+/* Abort (over) edge out of a GIMPLE_TRANSACTION statement. */
+DEF_EDGE_FLAG(TM_ABORT, 16)
+
+/* An edge we should ignore. It should be entirely local to
+ passes. ie, it is never set on any edge upon the completion
+ of any pass. */
+DEF_EDGE_FLAG(IGNORE, 17)
+
+#endif
+
+/*
+Local variables:
+mode:c
+End:
+*/
diff --git a/support/cpp/gcc/cfg.h b/support/cpp/gcc/cfg.h
new file mode 100644
index 000000000..d32c6d407
--- /dev/null
+++ b/support/cpp/gcc/cfg.h
@@ -0,0 +1,188 @@
+/* Control flow graph manipulation code header file.
+ Copyright (C) 2014-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/>. */
+
+#if 0 // sdcpp ndef GCC_CFG_H
+#define GCC_CFG_H
+
+#include "dominance.h"
+
+/* What sort of profiling information we have. */
+enum profile_status_d
+{
+ PROFILE_ABSENT,
+ PROFILE_GUESSED,
+ PROFILE_READ,
+ PROFILE_LAST /* Last value, used by profile streaming. */
+};
+
+/* A structure to group all the per-function control flow graph data.
+ The x_* prefixing is necessary because otherwise references to the
+ fields of this struct are interpreted as the defines for backward
+ source compatibility following the definition of this struct. */
+struct GTY(()) control_flow_graph {
+ /* Block pointers for the exit and entry of a function.
+ These are always the head and tail of the basic block list. */
+ basic_block x_entry_block_ptr;
+ basic_block x_exit_block_ptr;
+
+ /* Index by basic block number, get basic block struct info. */
+ vec<basic_block, va_gc> *x_basic_block_info;
+
+ /* Number of basic blocks in this flow graph. */
+ int x_n_basic_blocks;
+
+ /* Number of edges in this flow graph. */
+ int x_n_edges;
+
+ /* The first free basic block number. */
+ int x_last_basic_block;
+
+ /* UIDs for LABEL_DECLs. */
+ int last_label_uid;
+
+ /* Mapping of labels to their associated blocks. At present
+ only used for the gimple CFG. */
+ vec<basic_block, va_gc> *x_label_to_block_map;
+
+ enum profile_status_d x_profile_status;
+
+ /* Whether the dominators and the postdominators are available. */
+ enum dom_state x_dom_computed[2];
+
+ /* Number of basic blocks in the dominance tree. */
+ unsigned x_n_bbs_in_dom_tree[2];
+
+ /* Maximal number of entities in the single jumptable. Used to estimate
+ final flowgraph size. */
+ int max_jumptable_ents;
+
+ /* Maximal count of BB in function. */
+ profile_count count_max;
+
+ /* Dynamically allocated edge/bb flags. */
+ int edge_flags_allocated;
+ int bb_flags_allocated;
+};
+
+
+extern void init_flow (function *);
+extern void free_cfg (function *);
+extern basic_block alloc_block (void);
+extern void link_block (basic_block, basic_block);
+extern void unlink_block (basic_block);
+extern void compact_blocks (void);
+extern void expunge_block (basic_block);
+extern edge unchecked_make_edge (basic_block, basic_block, int);
+extern edge cached_make_edge (sbitmap, basic_block, basic_block, int);
+extern edge make_edge (basic_block, basic_block, int);
+extern edge make_single_succ_edge (basic_block, basic_block, int);
+extern void remove_edge_raw (edge);
+extern void redirect_edge_succ (edge, basic_block);
+extern void redirect_edge_pred (edge, basic_block);
+extern void clear_bb_flags (void);
+extern void dump_edge_info (FILE *, edge, dump_flags_t, int);
+extern void debug (edge_def &ref);
+extern void debug (edge_def *ptr);
+extern void alloc_aux_for_blocks (int);
+extern void clear_aux_for_blocks (void);
+extern void free_aux_for_blocks (void);
+extern void alloc_aux_for_edge (edge, int);
+extern void alloc_aux_for_edges (int);
+extern void clear_aux_for_edges (void);
+extern void free_aux_for_edges (void);
+extern void debug_bb (basic_block);
+extern basic_block debug_bb_n (int);
+extern void debug_bb (basic_block, dump_flags_t);
+extern basic_block debug_bb_n (int, dump_flags_t);
+extern void dump_bb_info (FILE *, basic_block, int, dump_flags_t, bool, bool);
+extern void brief_dump_cfg (FILE *, dump_flags_t);
+extern void update_bb_profile_for_threading (basic_block, profile_count, edge);
+extern void scale_bbs_frequencies_profile_count (basic_block *, int,
+ profile_count, profile_count);
+extern void scale_bbs_frequencies (basic_block *, int, profile_probability);
+extern void initialize_original_copy_tables (void);
+extern void reset_original_copy_tables (void);
+extern void free_original_copy_tables (void);
+extern bool original_copy_tables_initialized_p (void);
+extern void set_bb_original (basic_block, basic_block);
+extern basic_block get_bb_original (basic_block);
+extern void set_bb_copy (basic_block, basic_block);
+extern basic_block get_bb_copy (basic_block);
+void set_loop_copy (class loop *, class loop *);
+class loop *get_loop_copy (class loop *);
+
+/* Generic RAII class to allocate a bit from storage of integer type T.
+ The allocated bit is accessible as mask with the single bit set
+ via the conversion operator to T. */
+
+template <class T>
+class auto_flag
+{
+public:
+ /* static assert T is integer type of max HOST_WIDE_INT precision. */
+ auto_flag (T *sptr)
+ {
+ m_sptr = sptr;
+ int free_bit = ffs_hwi (~*sptr);
+ /* If there are no unset bits... */
+ if (free_bit == 0)
+ gcc_unreachable ();
+ m_flag = HOST_WIDE_INT_1U << (free_bit - 1);
+ /* ...or if T is signed and thus the complement is sign-extended,
+ check if we ran out of bits. We could spare us this bit
+ if we could use C++11 std::make_unsigned<T>::type to pass
+ ~*sptr to ffs_hwi. */
+ if (m_flag == 0)
+ gcc_unreachable ();
+ gcc_checking_assert ((*sptr & m_flag) == 0);
+ *sptr |= m_flag;
+ }
+ ~auto_flag ()
+ {
+ gcc_checking_assert ((*m_sptr & m_flag) == m_flag);
+ *m_sptr &= ~m_flag;
+ }
+ operator T () const { return m_flag; }
+private:
+ T *m_sptr;
+ T m_flag;
+};
+
+/* RAII class to allocate an edge flag for temporary use. You have
+ to clear the flag from all edges when you are finished using it. */
+
+#if 0 // sdcpp
+class auto_edge_flag : public auto_flag<int>
+{
+public:
+ auto_edge_flag (function *fun)
+ : auto_flag<int> (&fun->cfg->edge_flags_allocated) {}
+};
+
+/* RAII class to allocate a bb flag for temporary use. You have
+ to clear the flag from all edges when you are finished using it. */
+class auto_bb_flag : public auto_flag<int>
+{
+public:
+ auto_bb_flag (function *fun)
+ : auto_flag<int> (&fun->cfg->bb_flags_allocated) {}
+};
+#endif // sdcpp
+
+#endif /* GCC_CFG_H */
diff --git a/support/cpp/gcc/cfgloop.h b/support/cpp/gcc/cfgloop.h
new file mode 100644
index 000000000..a01eb109d
--- /dev/null
+++ b/support/cpp/gcc/cfgloop.h
@@ -0,0 +1,944 @@
+/* Natural loop functions
+ 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/>. */
+
+#if 0 //sdcpp ndef GCC_CFGLOOP_H
+#define GCC_CFGLOOP_H
+
+#include "cfgloopmanip.h"
+
+/* Structure to hold decision about unrolling/peeling. */
+enum lpt_dec
+{
+ LPT_NONE,
+ LPT_UNROLL_CONSTANT,
+ LPT_UNROLL_RUNTIME,
+ LPT_UNROLL_STUPID
+};
+
+struct GTY (()) lpt_decision {
+ enum lpt_dec decision;
+ unsigned times;
+};
+
+/* The type of extend applied to an IV. */
+enum iv_extend_code
+{
+ IV_SIGN_EXTEND,
+ IV_ZERO_EXTEND,
+ IV_UNKNOWN_EXTEND
+};
+
+/* The structure describing a bound on number of iterations of a loop. */
+
+class GTY ((chain_next ("%h.next"))) nb_iter_bound {
+public:
+ /* The statement STMT is executed at most ... */
+ gimple *stmt;
+
+ /* ... BOUND + 1 times (BOUND must be an unsigned constant).
+ The + 1 is added for the following reasons:
+
+ a) 0 would otherwise be unused, while we would need to care more about
+ overflows (as MAX + 1 is sometimes produced as the estimate on number
+ of executions of STMT).
+ b) it is consistent with the result of number_of_iterations_exit. */
+ widest_int bound;
+
+ /* True if, after executing the statement BOUND + 1 times, we will
+ leave the loop; that is, all the statements after it are executed at most
+ BOUND times. */
+ bool is_exit;
+
+ /* The next bound in the list. */
+ class nb_iter_bound *next;
+};
+
+/* Description of the loop exit. */
+
+struct GTY ((for_user)) loop_exit {
+ /* The exit edge. */
+ edge e;
+
+ /* Previous and next exit in the list of the exits of the loop. */
+ struct loop_exit *prev;
+ struct loop_exit *next;
+
+ /* Next element in the list of loops from that E exits. */
+ struct loop_exit *next_e;
+};
+
+struct loop_exit_hasher : ggc_ptr_hash<loop_exit>
+{
+ typedef edge compare_type;
+
+ static hashval_t hash (loop_exit *);
+ static bool equal (loop_exit *, edge);
+ static void remove (loop_exit *);
+};
+
+typedef class loop *loop_p;
+
+/* An integer estimation of the number of iterations. Estimate_state
+ describes what is the state of the estimation. */
+enum loop_estimation
+{
+ /* Estimate was not computed yet. */
+ EST_NOT_COMPUTED,
+ /* Estimate is ready. */
+ EST_AVAILABLE,
+ EST_LAST
+};
+
+/* The structure describing non-overflow control induction variable for
+ loop's exit edge. */
+struct GTY ((chain_next ("%h.next"))) control_iv {
+ tree base;
+ tree step;
+ struct control_iv *next;
+};
+
+/* Structure to hold information for each natural loop. */
+class GTY ((chain_next ("%h.next"))) loop {
+public:
+ /* Index into loops array. Note indices will never be reused after loop
+ is destroyed. */
+ int num;
+
+ /* Number of loop insns. */
+ unsigned ninsns;
+
+ /* Basic block of loop header. */
+ basic_block header;
+
+ /* Basic block of loop latch. */
+ basic_block latch;
+
+ /* For loop unrolling/peeling decision. */
+ struct lpt_decision lpt_decision;
+
+ /* Average number of executed insns per iteration. */
+ unsigned av_ninsns;
+
+ /* Number of blocks contained within the loop. */
+ unsigned num_nodes;
+
+ /* Superloops of the loop, starting with the outermost loop. */
+ vec<loop_p, va_gc> *superloops;
+
+ /* The first inner (child) loop or NULL if innermost loop. */
+ class loop *inner;
+
+ /* Link to the next (sibling) loop. */
+ class loop *next;
+
+ /* Auxiliary info specific to a pass. */
+ PTR GTY ((skip (""))) aux;
+
+ /* The number of times the latch of the loop is executed. This can be an
+ INTEGER_CST, or a symbolic expression representing the number of
+ iterations like "N - 1", or a COND_EXPR containing the runtime
+ conditions under which the number of iterations is non zero.
+
+ Don't access this field directly: number_of_latch_executions
+ computes and caches the computed information in this field. */
+ tree nb_iterations;
+
+ /* An integer guaranteed to be greater or equal to nb_iterations. Only
+ valid if any_upper_bound is true. */
+ widest_int nb_iterations_upper_bound;
+
+ widest_int nb_iterations_likely_upper_bound;
+
+ /* An integer giving an estimate on nb_iterations. Unlike
+ nb_iterations_upper_bound, there is no guarantee that it is at least
+ nb_iterations. */
+ widest_int nb_iterations_estimate;
+
+ /* If > 0, an integer, where the user asserted that for any
+ I in [ 0, nb_iterations ) and for any J in
+ [ I, min ( I + safelen, nb_iterations ) ), the Ith and Jth iterations
+ of the loop can be safely evaluated concurrently. */
+ int safelen;
+
+ /* Preferred vectorization factor for the loop if non-zero. */
+ int simdlen;
+
+ /* Constraints are generally set by consumers and affect certain
+ semantics of niter analyzer APIs. Currently the APIs affected are
+ number_of_iterations_exit* functions and their callers. One typical
+ use case of constraints is to vectorize possibly infinite loop:
+
+ 1) Compute niter->assumptions by calling niter analyzer API and
+ record it as possible condition for loop versioning.
+ 2) Clear buffered result of niter/scev analyzer.
+ 3) Set constraint LOOP_C_FINITE assuming the loop is finite.
+ 4) Analyze data references. Since data reference analysis depends
+ on niter/scev analyzer, the point is that niter/scev analysis
+ is done under circumstance of LOOP_C_FINITE constraint.
+ 5) Version the loop with niter->assumptions computed in step 1).
+ 6) Vectorize the versioned loop in which niter->assumptions is
+ checked to be true.
+ 7) Update constraints in versioned loops so that niter analyzer
+ in following passes can use it.
+
+ Note consumers are usually the loop optimizers and it is consumers'
+ responsibility to set/clear constraints correctly. Failing to do
+ that might result in hard to track down bugs in niter/scev consumers. */
+ unsigned constraints;
+
+ /* An integer estimation of the number of iterations. Estimate_state
+ describes what is the state of the estimation. */
+ ENUM_BITFIELD(loop_estimation) estimate_state : 8;
+
+ unsigned any_upper_bound : 1;
+ unsigned any_estimate : 1;
+ unsigned any_likely_upper_bound : 1;
+
+ /* True if the loop can be parallel. */
+ unsigned can_be_parallel : 1;
+
+ /* True if -Waggressive-loop-optimizations warned about this loop
+ already. */
+ unsigned warned_aggressive_loop_optimizations : 1;
+
+ /* True if this loop should never be vectorized. */
+ unsigned dont_vectorize : 1;
+
+ /* True if we should try harder to vectorize this loop. */
+ unsigned force_vectorize : 1;
+
+ /* True if the loop is part of an oacc kernels region. */
+ unsigned in_oacc_kernels_region : 1;
+
+ /* True if the loop is known to be finite. This is a localized
+ flag_finite_loops or similar pragmas state. */
+ unsigned finite_p : 1;
+
+ /* The number of times to unroll the loop. 0 means no information given,
+ just do what we always do. A value of 1 means do not unroll the loop.
+ A value of USHRT_MAX means unroll with no specific unrolling factor.
+ Other values means unroll with the given unrolling factor. */
+ unsigned short unroll;
+
+ /* If this loop was inlined the main clique of the callee which does
+ not need remapping when copying the loop body. */
+ unsigned short owned_clique;
+
+ /* For SIMD loops, this is a unique identifier of the loop, referenced
+ by IFN_GOMP_SIMD_VF, IFN_GOMP_SIMD_LANE and IFN_GOMP_SIMD_LAST_LANE
+ builtins. */
+ tree simduid;
+
+ /* In loop optimization, it's common to generate loops from the original
+ loop. This field records the index of the original loop which can be
+ used to track the original loop from newly generated loops. This can
+ be done by calling function get_loop (cfun, orig_loop_num). Note the
+ original loop could be destroyed for various reasons thus no longer
+ exists, as a result, function call to get_loop returns NULL pointer.
+ In this case, this field should not be used and needs to be cleared
+ whenever possible. */
+ int orig_loop_num;
+
+ /* Upper bound on number of iterations of a loop. */
+ class nb_iter_bound *bounds;
+
+ /* Non-overflow control ivs of a loop. */
+ struct control_iv *control_ivs;
+
+ /* Head of the cyclic list of the exits of the loop. */
+ struct loop_exit *exits;
+
+ /* Number of iteration analysis data for RTL. */
+ class niter_desc *simple_loop_desc;
+
+ /* For sanity checking during loop fixup we record here the former
+ loop header for loops marked for removal. Note that this prevents
+ the basic-block from being collected but its index can still be
+ reused. */
+ basic_block former_header;
+};
+
+/* Set if the loop is known to be infinite. */
+#define LOOP_C_INFINITE (1 << 0)
+/* Set if the loop is known to be finite without any assumptions. */
+#define LOOP_C_FINITE (1 << 1)
+
+/* Set C to the LOOP constraint. */
+static inline void
+loop_constraint_set (class loop *loop, unsigned c)
+{
+ loop->constraints |= c;
+}
+
+/* Clear C from the LOOP constraint. */
+static inline void
+loop_constraint_clear (class loop *loop, unsigned c)
+{
+ loop->constraints &= ~c;
+}
+
+/* Check if C is set in the LOOP constraint. */
+static inline bool
+loop_constraint_set_p (class loop *loop, unsigned c)
+{
+ return (loop->constraints & c) == c;
+}
+
+/* Flags for state of loop structure. */
+enum
+{
+ LOOPS_HAVE_PREHEADERS = 1,
+ LOOPS_HAVE_SIMPLE_LATCHES = 2,
+ LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS = 4,
+ LOOPS_HAVE_RECORDED_EXITS = 8,
+ LOOPS_MAY_HAVE_MULTIPLE_LATCHES = 16,
+ LOOP_CLOSED_SSA = 32,
+ LOOPS_NEED_FIXUP = 64,
+ LOOPS_HAVE_FALLTHRU_PREHEADERS = 128
+};
+
+#define LOOPS_NORMAL (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES \
+ | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
+#define AVOID_CFG_MODIFICATIONS (LOOPS_MAY_HAVE_MULTIPLE_LATCHES)
+
+/* Structure to hold CFG information about natural loops within a function. */
+struct GTY (()) loops {
+ /* State of loops. */
+ int state;
+
+ /* Array of the loops. */
+ vec<loop_p, va_gc> *larray;
+
+ /* Maps edges to the list of their descriptions as loop exits. Edges
+ whose sources or destinations have loop_father == NULL (which may
+ happen during the cfg manipulations) should not appear in EXITS. */
+ hash_table<loop_exit_hasher> *GTY(()) exits;
+
+ /* Pointer to root of loop hierarchy tree. */
+ class loop *tree_root;
+};
+
+/* Loop recognition. */
+bool bb_loop_header_p (basic_block);
+void init_loops_structure (struct function *, struct loops *, unsigned);
+extern struct loops *flow_loops_find (struct loops *);
+extern void disambiguate_loops_with_multiple_latches (void);
+extern void flow_loops_free (struct loops *);
+extern void flow_loops_dump (FILE *,
+ void (*)(const class loop *, FILE *, int), int);
+extern void flow_loop_dump (const class loop *, FILE *,
+ void (*)(const class loop *, FILE *, int), int);
+class loop *alloc_loop (void);
+extern void flow_loop_free (class loop *);
+int flow_loop_nodes_find (basic_block, class loop *);
+unsigned fix_loop_structure (bitmap changed_bbs);
+bool mark_irreducible_loops (void);
+void release_recorded_exits (function *);
+void record_loop_exits (void);
+void rescan_loop_exit (edge, bool, bool);
+void sort_sibling_loops (function *);
+
+/* Loop data structure manipulation/querying. */
+extern void flow_loop_tree_node_add (class loop *, class loop *,
+ class loop * = NULL);
+extern void flow_loop_tree_node_remove (class loop *);
+extern bool flow_loop_nested_p (const class loop *, const class loop *);
+extern bool flow_bb_inside_loop_p (const class loop *, const_basic_block);
+extern class loop * find_common_loop (class loop *, class loop *);
+class loop *superloop_at_depth (class loop *, unsigned);
+struct eni_weights;
+extern int num_loop_insns (const class loop *);
+extern int average_num_loop_insns (const class loop *);
+extern unsigned get_loop_level (const class loop *);
+extern bool loop_exit_edge_p (const class loop *, const_edge);
+extern bool loop_exits_to_bb_p (class loop *, basic_block);
+extern bool loop_exits_from_bb_p (class loop *, basic_block);
+extern void mark_loop_exit_edges (void);
+extern dump_user_location_t get_loop_location (class loop *loop);
+
+/* Loops & cfg manipulation. */
+extern basic_block *get_loop_body (const class loop *);
+extern unsigned get_loop_body_with_size (const class loop *, basic_block *,
+ unsigned);
+extern basic_block *get_loop_body_in_dom_order (const class loop *);
+extern basic_block *get_loop_body_in_bfs_order (const class loop *);
+extern basic_block *get_loop_body_in_custom_order (const class loop *,
+ int (*) (const void *, const void *));
+extern basic_block *get_loop_body_in_custom_order (const class loop *, void *,
+ int (*) (const void *, const void *, void *));
+
+extern auto_vec<edge> get_loop_exit_edges (const class loop *, basic_block * = NULL);
+extern edge single_exit (const class loop *);
+extern edge single_likely_exit (class loop *loop, const vec<edge> &);
+extern unsigned num_loop_branches (const class loop *);
+
+extern edge loop_preheader_edge (const class loop *);
+extern edge loop_latch_edge (const class loop *);
+
+extern void add_bb_to_loop (basic_block, class loop *);
+extern void remove_bb_from_loops (basic_block);
+
+extern void cancel_loop_tree (class loop *);
+extern void delete_loop (class loop *);
+
+
+extern void verify_loop_structure (void);
+
+/* Loop analysis. */
+extern bool just_once_each_iteration_p (const class loop *, const_basic_block);
+gcov_type expected_loop_iterations_unbounded (const class loop *,
+ bool *read_profile_p = NULL, bool by_profile_only = false);
+extern unsigned expected_loop_iterations (class loop *);
+extern rtx doloop_condition_get (rtx_insn *);
+
+void mark_loop_for_removal (loop_p);
+
+/* Induction variable analysis. */
+
+/* The description of induction variable. The things are a bit complicated
+ due to need to handle subregs and extends. The value of the object described
+ by it can be obtained as follows (all computations are done in extend_mode):
+
+ Value in i-th iteration is
+ delta + mult * extend_{extend_mode} (subreg_{mode} (base + i * step)).
+
+ If first_special is true, the value in the first iteration is
+ delta + mult * base
+
+ If extend = UNKNOWN, first_special must be false, delta 0, mult 1 and value is
+ subreg_{mode} (base + i * step)
+
+ The get_iv_value function can be used to obtain these expressions.
+
+ ??? Add a third mode field that would specify the mode in that inner
+ computation is done, which would enable it to be different from the
+ outer one? */
+
+class rtx_iv
+{
+public:
+ /* Its base and step (mode of base and step is supposed to be extend_mode,
+ see the description above). */
+ rtx base, step;
+
+ /* The type of extend applied to it (IV_SIGN_EXTEND, IV_ZERO_EXTEND,
+ or IV_UNKNOWN_EXTEND). */
+ enum iv_extend_code extend;
+
+ /* Operations applied in the extended mode. */
+ rtx delta, mult;
+
+ /* The mode it is extended to. */
+ scalar_int_mode extend_mode;
+
+ /* The mode the variable iterates in. */
+ scalar_int_mode mode;
+
+ /* Whether the first iteration needs to be handled specially. */
+ unsigned first_special : 1;
+};
+
+/* The description of an exit from the loop and of the number of iterations
+ till we take the exit. */
+
+class GTY(()) niter_desc
+{
+public:
+ /* The edge out of the loop. */
+ edge out_edge;
+
+ /* The other edge leading from the condition. */
+ edge in_edge;
+
+ /* True if we are able to say anything about number of iterations of the
+ loop. */
+ bool simple_p;
+
+ /* True if the loop iterates the constant number of times. */
+ bool const_iter;
+
+ /* Number of iterations if constant. */
+ uint64_t niter;
+
+ /* Assumptions under that the rest of the information is valid. */
+ rtx assumptions;
+
+ /* Assumptions under that the loop ends before reaching the latch,
+ even if value of niter_expr says otherwise. */
+ rtx noloop_assumptions;
+
+ /* Condition under that the loop is infinite. */
+ rtx infinite;
+
+ /* Whether the comparison is signed. */
+ bool signed_p;
+
+ /* The mode in that niter_expr should be computed. */
+ scalar_int_mode mode;
+
+ /* The number of iterations of the loop. */
+ rtx niter_expr;
+};
+
+extern void iv_analysis_loop_init (class loop *);
+extern bool iv_analyze (rtx_insn *, scalar_int_mode, rtx, class rtx_iv *);
+extern bool iv_analyze_result (rtx_insn *, rtx, class rtx_iv *);
+extern bool iv_analyze_expr (rtx_insn *, scalar_int_mode, rtx,
+ class rtx_iv *);
+extern rtx get_iv_value (class rtx_iv *, rtx);
+extern bool biv_p (rtx_insn *, scalar_int_mode, rtx);
+extern void iv_analysis_done (void);
+
+extern class niter_desc *get_simple_loop_desc (class loop *loop);
+extern void free_simple_loop_desc (class loop *loop);
+
+static inline class niter_desc *
+simple_loop_desc (class loop *loop)
+{
+ return loop->simple_loop_desc;
+}
+
+/* Accessors for the loop structures. */
+
+/* Returns the loop with index NUM from FNs loop tree. */
+
+#if 0 // sdcpp
+static inline class loop *
+get_loop (struct function *fn, unsigned num)
+{
+ return (*loops_for_fn (fn)->larray)[num];
+}
+#endif
+
+/* Returns the number of superloops of LOOP. */
+
+static inline unsigned
+loop_depth (const class loop *loop)
+{
+ return vec_safe_length (loop->superloops);
+}
+
+/* Returns the immediate superloop of LOOP, or NULL if LOOP is the outermost
+ loop. */
+
+static inline class loop *
+loop_outer (const class loop *loop)
+{
+ unsigned n = vec_safe_length (loop->superloops);
+
+ if (n == 0)
+ return NULL;
+
+ return (*loop->superloops)[n - 1];
+}
+
+/* Returns true if LOOP has at least one exit edge. */
+
+static inline bool
+loop_has_exit_edges (const class loop *loop)
+{
+ return loop->exits->next->e != NULL;
+}
+
+/* Returns the list of loops in FN. */
+
+#if 0 // sdcpp
+inline vec<loop_p, va_gc> *
+get_loops (struct function *fn)
+{
+ struct loops *loops = loops_for_fn (fn);
+ if (!loops)
+ return NULL;
+
+ return loops->larray;
+}
+#endif // sdcpp
+
+/* Returns the number of loops in FN (including the removed
+ ones and the fake loop that forms the root of the loop tree). */
+
+static inline unsigned
+number_of_loops (struct function *fn)
+{
+ struct loops *loops = loops_for_fn (fn);
+ if (!loops)
+ return 0;
+
+ return vec_safe_length (loops->larray);
+}
+
+/* Returns true if state of the loops satisfies all properties
+ described by FLAGS. */
+
+static inline bool
+loops_state_satisfies_p (function *fn, unsigned flags)
+{
+ return (loops_for_fn (fn)->state & flags) == flags;
+}
+
+static inline bool
+loops_state_satisfies_p (unsigned flags)
+{
+ return loops_state_satisfies_p (cfun, flags);
+}
+
+/* Sets FLAGS to the loops state. */
+
+static inline void
+loops_state_set (function *fn, unsigned flags)
+{
+ loops_for_fn (fn)->state |= flags;
+}
+
+static inline void
+loops_state_set (unsigned flags)
+{
+ loops_state_set (cfun, flags);
+}
+
+/* Clears FLAGS from the loops state. */
+
+static inline void
+loops_state_clear (function *fn, unsigned flags)
+{
+ loops_for_fn (fn)->state &= ~flags;
+}
+
+#if 0 // sdcpp
+static inline void
+loops_state_clear (unsigned flags)
+{
+ if (!current_loops)
+ return;
+ loops_state_clear (cfun, flags);
+}
+
+/* Check loop structure invariants, if internal consistency checks are
+ enabled. */
+
+static inline void
+checking_verify_loop_structure (void)
+{
+ /* VERIFY_LOOP_STRUCTURE essentially asserts that no loops need fixups.
+
+ The loop optimizers should never make changes to the CFG which
+ require loop fixups. But the low level CFG manipulation code may
+ set the flag conservatively.
+
+ Go ahead and clear the flag here. That avoids the assert inside
+ VERIFY_LOOP_STRUCTURE, and if there is an inconsistency in the loop
+ structures VERIFY_LOOP_STRUCTURE will detect it.
+
+ This also avoid the compile time cost of excessive fixups. */
+ loops_state_clear (LOOPS_NEED_FIXUP);
+ if (flag_checking)
+ verify_loop_structure ();
+}
+#endif // sdcpp
+
+/* Loop iterators. */
+
+/* Flags for loop iteration. */
+
+enum li_flags
+{
+ LI_INCLUDE_ROOT = 1, /* Include the fake root of the loop tree. */
+ LI_FROM_INNERMOST = 2, /* Iterate over the loops in the reverse order,
+ starting from innermost ones. */
+ LI_ONLY_INNERMOST = 4 /* Iterate only over innermost loops. */
+};
+
+/* Provide the functionality of std::as_const to support range-based for
+ to use const iterator. (We can't use std::as_const itself because it's
+ a C++17 feature.) */
+template <typename T>
+constexpr const T &
+as_const (T &t)
+{
+ return t;
+}
+
+/* A list for visiting loops, which contains the loop numbers instead of
+ the loop pointers. If the loop ROOT is offered (non-null), the visiting
+ will start from it, otherwise it would start from the tree_root of
+ loops_for_fn (FN) instead. The scope is restricted in function FN and
+ the visiting order is specified by FLAGS. */
+
+class loops_list
+{
+public:
+ loops_list (function *fn, unsigned flags, class loop *root = nullptr);
+
+ template <typename T> class Iter
+ {
+ public:
+ Iter (const loops_list &l, unsigned idx) : list (l), curr_idx (idx)
+ {
+ fill_curr_loop ();
+ }
+
+ T operator* () const { return curr_loop; }
+
+ Iter &
+ operator++ ()
+ {
+ if (curr_idx < list.to_visit.length ())
+ {
+ /* Bump the index and fill a new one. */
+ curr_idx++;
+ fill_curr_loop ();
+ }
+ else
+ gcc_assert (!curr_loop);
+
+ return *this;
+ }
+
+ bool
+ operator!= (const Iter &rhs) const
+ {
+ return this->curr_idx != rhs.curr_idx;
+ }
+
+ private:
+ /* Fill the current loop starting from the current index. */
+ void fill_curr_loop ();
+
+ /* Reference to the loop list to visit. */
+ const loops_list &list;
+
+ /* The current index in the list to visit. */
+ unsigned curr_idx;
+
+ /* The loop implied by the current index. */
+ class loop *curr_loop;
+ };
+
+ using iterator = Iter<class loop *>;
+ using const_iterator = Iter<const class loop *>;
+
+ iterator
+ begin ()
+ {
+ return iterator (*this, 0);
+ }
+
+ iterator
+ end ()
+ {
+ return iterator (*this, to_visit.length ());
+ }
+
+ const_iterator
+ begin () const
+ {
+ return const_iterator (*this, 0);
+ }
+
+ const_iterator
+ end () const
+ {
+ return const_iterator (*this, to_visit.length ());
+ }
+
+private:
+ /* Walk loop tree starting from ROOT as the visiting order specified
+ by FLAGS. */
+ void walk_loop_tree (class loop *root, unsigned flags);
+
+ /* The function we are visiting. */
+ function *fn;
+
+ /* The list of loops to visit. */
+ auto_vec<int, 16> to_visit;
+};
+
+/* Starting from current index CURR_IDX (inclusive), find one index
+ which stands for one valid loop and fill the found loop as CURR_LOOP,
+ if we can't find one, set CURR_LOOP as null. */
+
+#if 0 // sdcpp
+template <typename T>
+inline void
+loops_list::Iter<T>::fill_curr_loop ()
+{
+ int anum;
+
+ while (this->list.to_visit.iterate (this->curr_idx, &anum))
+ {
+ class loop *loop = get_loop (this->list.fn, anum);
+ if (loop)
+ {
+ curr_loop = loop;
+ return;
+ }
+ this->curr_idx++;
+ }
+
+ curr_loop = nullptr;
+}
+#endif
+
+/* Set up the loops list to visit according to the specified
+ function scope FN and iterating order FLAGS. If ROOT is
+ not null, the visiting would start from it, otherwise it
+ will start from tree_root of loops_for_fn (FN). */
+
+inline loops_list::loops_list (function *fn, unsigned flags, class loop *root)
+{
+ struct loops *loops = loops_for_fn (fn);
+ gcc_assert (!root || loops);
+
+ /* Check mutually exclusive flags should not co-exist. */
+ unsigned checked_flags = LI_ONLY_INNERMOST | LI_FROM_INNERMOST;
+ gcc_assert ((flags & checked_flags) != checked_flags);
+
+ this->fn = fn;
+ if (!loops)
+ return;
+
+ class loop *tree_root = root ? root : loops->tree_root;
+
+ this->to_visit.reserve_exact (number_of_loops (fn));
+
+ /* When root is tree_root of loops_for_fn (fn) and the visiting
+ order is LI_ONLY_INNERMOST, we would like to use linear
+ search here since it has a more stable bound than the
+ walk_loop_tree. */
+ if (flags & LI_ONLY_INNERMOST && tree_root == loops->tree_root)
+ {
+ gcc_assert (tree_root->num == 0);
+ if (tree_root->inner == NULL)
+ {
+ if (flags & LI_INCLUDE_ROOT)
+ this->to_visit.quick_push (0);
+
+ return;
+ }
+
+ class loop *aloop;
+ unsigned int i;
+ for (i = 1; vec_safe_iterate (loops->larray, i, &aloop); i++)
+ if (aloop != NULL && aloop->inner == NULL)
+ this->to_visit.quick_push (aloop->num);
+ }
+ else
+ walk_loop_tree (tree_root, flags);
+}
+
+/* The properties of the target. */
+struct target_cfgloop {
+ /* Number of available registers. */
+ unsigned x_target_avail_regs;
+
+ /* Number of available registers that are call-clobbered. */
+ unsigned x_target_clobbered_regs;
+
+ /* Number of registers reserved for temporary expressions. */
+ unsigned x_target_res_regs;
+
+ /* The cost for register when there still is some reserve, but we are
+ approaching the number of available registers. */
+ unsigned x_target_reg_cost[2];
+
+ /* The cost for register when we need to spill. */
+ unsigned x_target_spill_cost[2];
+};
+
+extern struct target_cfgloop default_target_cfgloop;
+#if SWITCHABLE_TARGET
+extern struct target_cfgloop *this_target_cfgloop;
+#else
+#define this_target_cfgloop (&default_target_cfgloop)
+#endif
+
+#define target_avail_regs \
+ (this_target_cfgloop->x_target_avail_regs)
+#define target_clobbered_regs \
+ (this_target_cfgloop->x_target_clobbered_regs)
+#define target_res_regs \
+ (this_target_cfgloop->x_target_res_regs)
+#define target_reg_cost \
+ (this_target_cfgloop->x_target_reg_cost)
+#define target_spill_cost \
+ (this_target_cfgloop->x_target_spill_cost)
+
+/* Register pressure estimation for induction variable optimizations & loop
+ invariant motion. */
+extern unsigned estimate_reg_pressure_cost (unsigned, unsigned, bool, bool);
+extern void init_set_costs (void);
+
+/* Loop optimizer initialization. */
+extern void loop_optimizer_init (unsigned);
+extern void loop_optimizer_finalize (function *, bool = false);
+inline void
+loop_optimizer_finalize ()
+{
+ loop_optimizer_finalize (cfun);
+}
+
+/* Optimization passes. */
+enum
+{
+ UAP_UNROLL = 1, /* Enables unrolling of loops if it seems profitable. */
+ UAP_UNROLL_ALL = 2 /* Enables unrolling of all loops. */
+};
+
+extern void doloop_optimize_loops (void);
+extern void move_loop_invariants (void);
+extern auto_vec<basic_block> get_loop_hot_path (const class loop *loop);
+
+/* Returns the outermost loop of the loop nest that contains LOOP.*/
+static inline class loop *
+loop_outermost (class loop *loop)
+{
+ unsigned n = vec_safe_length (loop->superloops);
+
+ if (n <= 1)
+ return loop;
+
+ return (*loop->superloops)[1];
+}
+
+extern void record_niter_bound (class loop *, const widest_int &, bool, bool);
+extern HOST_WIDE_INT get_estimated_loop_iterations_int (class loop *);
+extern HOST_WIDE_INT get_max_loop_iterations_int (const class loop *);
+extern HOST_WIDE_INT get_likely_max_loop_iterations_int (class loop *);
+extern bool get_estimated_loop_iterations (class loop *loop, widest_int *nit);
+extern bool get_max_loop_iterations (const class loop *loop, widest_int *nit);
+extern bool get_likely_max_loop_iterations (class loop *loop, widest_int *nit);
+extern int bb_loop_depth (const_basic_block);
+
+/* Converts VAL to widest_int. */
+
+static inline widest_int
+gcov_type_to_wide_int (gcov_type val)
+{
+ HOST_WIDE_INT a[2];
+
+ a[0] = (unsigned HOST_WIDE_INT) val;
+ /* If HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_WIDEST_INT, avoid shifting by
+ the size of type. */
+ val >>= HOST_BITS_PER_WIDE_INT - 1;
+ val >>= 1;
+ a[1] = (unsigned HOST_WIDE_INT) val;
+
+ return widest_int::from_array (a, 2);
+}
+#endif /* GCC_CFGLOOP_H */
diff --git a/support/cpp/gcc/cgraph.h b/support/cpp/gcc/cgraph.h
new file mode 100644
index 000000000..9cc111421
--- /dev/null
+++ b/support/cpp/gcc/cgraph.h
@@ -0,0 +1,3579 @@
+/* Callgraph handling code.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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/>. */
+
+#if 0 // sdcpp ndef GCC_CGRAPH_H
+#define GCC_CGRAPH_H
+
+#include "profile-count.h"
+#include "ipa-ref.h"
+#include "plugin-api.h"
+#include "ipa-param-manipulation.h"
+
+extern void debuginfo_early_init (void);
+extern void debuginfo_init (void);
+extern void debuginfo_fini (void);
+extern void debuginfo_start (void);
+extern void debuginfo_stop (void);
+extern void debuginfo_early_start (void);
+extern void debuginfo_early_stop (void);
+
+class ipa_opt_pass_d;
+typedef ipa_opt_pass_d *ipa_opt_pass;
+
+/* Symbol table consists of functions and variables.
+ TODO: add labels and CONST_DECLs. */
+enum symtab_type
+{
+ SYMTAB_SYMBOL,
+ SYMTAB_FUNCTION,
+ SYMTAB_VARIABLE
+};
+
+/* Section names are stored as reference counted strings in GGC safe hashtable
+ (to make them survive through PCH). */
+
+struct GTY((for_user)) section_hash_entry
+{
+ int ref_count;
+ char *name; /* As long as this datastructure stays in GGC, we cannot put
+ string at the tail of structure of GGC dies in horrible
+ way */
+};
+
+struct section_name_hasher : ggc_ptr_hash<section_hash_entry>
+{
+ typedef const char *compare_type;
+
+ static hashval_t hash (section_hash_entry *);
+ static bool equal (section_hash_entry *, const char *);
+};
+
+enum availability
+{
+ /* Not yet set by cgraph_function_body_availability. */
+ AVAIL_UNSET,
+ /* Function body/variable initializer is unknown. */
+ AVAIL_NOT_AVAILABLE,
+ /* Function body/variable initializer is known but might be replaced
+ by a different one from other compilation unit and thus needs to
+ be dealt with a care. Like AVAIL_NOT_AVAILABLE it can have
+ arbitrary side effects on escaping variables and functions, while
+ like AVAILABLE it might access static variables. */
+ AVAIL_INTERPOSABLE,
+ /* Function body/variable initializer is known and will be used in final
+ program. */
+ AVAIL_AVAILABLE,
+ /* Function body/variable initializer is known and all it's uses are
+ explicitly visible within current unit (i.e. it's address is never taken
+ and it is not exported to other units). Currently used only for
+ functions. */
+ AVAIL_LOCAL
+};
+
+/* Classification of symbols WRT partitioning. */
+enum symbol_partitioning_class
+{
+ /* External declarations are ignored by partitioning algorithms and they are
+ added into the boundary later via compute_ltrans_boundary. */
+ SYMBOL_EXTERNAL,
+ /* Partitioned symbols are put into one of partitions. */
+ SYMBOL_PARTITION,
+ /* Duplicated symbols (such as comdat or constant pool references) are
+ copied into every node needing them via add_symbol_to_partition. */
+ SYMBOL_DUPLICATE
+};
+
+/* Base of all entries in the symbol table.
+ The symtab_node is inherited by cgraph and varpol nodes. */
+struct GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
+ chain_next ("%h.next"), chain_prev ("%h.previous")))
+ symtab_node
+{
+public:
+ friend class symbol_table;
+
+ /* Constructor. */
+ explicit symtab_node (symtab_type t)
+ : type (t), resolution (LDPR_UNKNOWN), definition (false), alias (false),
+ transparent_alias (false), weakref (false), cpp_implicit_alias (false),
+ symver (false), analyzed (false), writeonly (false),
+ refuse_visibility_changes (false), externally_visible (false),
+ no_reorder (false), force_output (false), forced_by_abi (false),
+ unique_name (false), implicit_section (false), body_removed (false),
+ semantic_interposition (flag_semantic_interposition),
+ used_from_other_partition (false), in_other_partition (false),
+ address_taken (false), in_init_priority_hash (false),
+ need_lto_streaming (false), offloadable (false), ifunc_resolver (false),
+ order (false), next_sharing_asm_name (NULL),
+ previous_sharing_asm_name (NULL), same_comdat_group (NULL), ref_list (),
+ alias_target (NULL), lto_file_data (NULL), aux (NULL),
+ x_comdat_group (NULL_TREE), x_section (NULL)
+ {}
+
+ /* Return name. */
+ const char *name () const;
+
+ /* Return dump name. */
+ const char *dump_name () const;
+
+ /* Return asm name. */
+ const char *asm_name () const;
+
+ /* Return dump name with assembler name. */
+ const char *dump_asm_name () const;
+
+ /* Return visibility name. */
+ const char *get_visibility_string () const;
+
+ /* Return type_name name. */
+ const char *get_symtab_type_string () const;
+
+ /* Add node into symbol table. This function is not used directly, but via
+ cgraph/varpool node creation routines. */
+ void register_symbol (void);
+
+ /* Remove symbol from symbol table. */
+ void remove (void);
+
+ /* Dump symtab node to F. */
+ void dump (FILE *f);
+
+ /* Dump symtab callgraph in graphviz format. */
+ void dump_graphviz (FILE *f);
+
+ /* Dump symtab node to stderr. */
+ void DEBUG_FUNCTION debug (void);
+
+ /* Verify consistency of node. */
+ void DEBUG_FUNCTION verify (void);
+
+ /* Return ipa reference from this symtab_node to
+ REFERRED_NODE or REFERRED_VARPOOL_NODE. USE_TYPE specify type
+ of the use and STMT the statement (if it exists). */
+ ipa_ref *create_reference (symtab_node *referred_node,
+ enum ipa_ref_use use_type);
+
+ /* Return ipa reference from this symtab_node to
+ REFERRED_NODE or REFERRED_VARPOOL_NODE. USE_TYPE specify type
+ of the use and STMT the statement (if it exists). */
+ ipa_ref *create_reference (symtab_node *referred_node,
+ enum ipa_ref_use use_type, gimple *stmt);
+
+ /* If VAL is a reference to a function or a variable, add a reference from
+ this symtab_node to the corresponding symbol table node. Return the new
+ reference or NULL if none was created. */
+ ipa_ref *maybe_create_reference (tree val, gimple *stmt);
+
+ /* Clone all references from symtab NODE to this symtab_node. */
+ void clone_references (symtab_node *node);
+
+ /* Remove all stmt references in non-speculative references.
+ Those are not maintained during inlining & clonning.
+ The exception are speculative references that are updated along
+ with callgraph edges associated with them. */
+ void clone_referring (symtab_node *node);
+
+ /* Clone reference REF to this symtab_node and set its stmt to STMT. */
+ ipa_ref *clone_reference (ipa_ref *ref, gimple *stmt);
+
+ /* Find the structure describing a reference to REFERRED_NODE
+ and associated with statement STMT. */
+ ipa_ref *find_reference (symtab_node *referred_node, gimple *stmt,
+ unsigned int lto_stmt_uid);
+
+ /* Remove all references that are associated with statement STMT. */
+ void remove_stmt_references (gimple *stmt);
+
+ /* Remove all stmt references in non-speculative references.
+ Those are not maintained during inlining & clonning.
+ The exception are speculative references that are updated along
+ with callgraph edges associated with them. */
+ void clear_stmts_in_references (void);
+
+ /* Remove all references in ref list. */
+ void remove_all_references (void);
+
+ /* Remove all referring items in ref list. */
+ void remove_all_referring (void);
+
+ /* Dump references in ref list to FILE. */
+ void dump_references (FILE *file);
+
+ /* Dump referring in list to FILE. */
+ void dump_referring (FILE *);
+
+ /* Get number of references for this node. */
+ inline unsigned num_references (void)
+ {
+ return ref_list.references.length ();
+ }
+
+ /* Iterates I-th reference in the list, REF is also set. */
+ ipa_ref *iterate_reference (unsigned i, ipa_ref *&ref);
+
+ /* Iterates I-th referring item in the list, REF is also set. */
+ ipa_ref *iterate_referring (unsigned i, ipa_ref *&ref);
+
+ /* Iterates I-th referring alias item in the list, REF is also set. */
+ ipa_ref *iterate_direct_aliases (unsigned i, ipa_ref *&ref);
+
+ /* Return true if symtab node and TARGET represents
+ semantically equivalent symbols. */
+ bool semantically_equivalent_p (symtab_node *target);
+
+ /* Classify symbol symtab node for partitioning. */
+ enum symbol_partitioning_class get_partitioning_class (void);
+
+ /* Return comdat group. */
+ tree get_comdat_group ()
+ {
+ return x_comdat_group;
+ }
+
+ /* Return comdat group as identifier_node. */
+ tree get_comdat_group_id ()
+ {
+ if (x_comdat_group && TREE_CODE (x_comdat_group) != IDENTIFIER_NODE)
+ x_comdat_group = DECL_ASSEMBLER_NAME (x_comdat_group);
+ return x_comdat_group;
+ }
+
+ /* Set comdat group. */
+ void set_comdat_group (tree group)
+ {
+ gcc_checking_assert (!group || TREE_CODE (group) == IDENTIFIER_NODE
+ || DECL_P (group));
+ x_comdat_group = group;
+ }
+
+ /* Return section as string. */
+ const char * get_section () const
+ {
+ if (!x_section)
+ return NULL;
+ return x_section->name;
+ }
+
+ /* Remove node from same comdat group. */
+ void remove_from_same_comdat_group (void);
+
+ /* Add this symtab_node to the same comdat group that OLD is in. */
+ void add_to_same_comdat_group (symtab_node *old_node);
+
+ /* Dissolve the same_comdat_group list in which NODE resides. */
+ void dissolve_same_comdat_group_list (void);
+
+ /* Return true when symtab_node is known to be used from other (non-LTO)
+ object file. Known only when doing LTO via linker plugin. */
+ bool used_from_object_file_p (void);
+
+ /* Walk the alias chain to return the symbol NODE is alias of.
+ If NODE is not an alias, return NODE.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+ symtab_node *ultimate_alias_target (enum availability *avail = NULL,
+ struct symtab_node *ref = NULL);
+
+ /* Return next reachable static symbol with initializer after NODE. */
+ inline symtab_node *next_defined_symbol (void);
+
+ /* Add reference recording that symtab node is alias of TARGET.
+ If TRANSPARENT is true make the alias to be transparent alias.
+ The function can fail in the case of aliasing cycles; in this case
+ it returns false. */
+ bool resolve_alias (symtab_node *target, bool transparent = false);
+
+ /* C++ FE sometimes change linkage flags after producing same
+ body aliases. */
+ void fixup_same_cpp_alias_visibility (symtab_node *target);
+
+ /* Call callback on symtab node and aliases associated to this node.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. */
+ bool call_for_symbol_and_aliases (bool (*callback) (symtab_node *, void *),
+ void *data,
+ bool include_overwrite);
+
+ /* If node cannot be interposable by static or dynamic linker to point to
+ different definition, return this symbol. Otherwise look for alias with
+ such property and if none exists, introduce new one. */
+ symtab_node *noninterposable_alias (void);
+
+ /* Return node that alias is aliasing. */
+ inline symtab_node *get_alias_target (void);
+
+ /* Return DECL that alias is aliasing. */
+ inline tree get_alias_target_tree ();
+
+ /* Set section for symbol and its aliases. */
+ void set_section (const char *section);
+
+ /* Like set_section, but copying the section name from another node. */
+ void set_section (const symtab_node &other);
+
+ /* Set section, do not recurse into aliases.
+ When one wants to change section of symbol and its aliases,
+ use set_section. */
+ void set_section_for_node (const char *section);
+
+ /* Like set_section_for_node, but copying the section name from another
+ node. */
+ void set_section_for_node (const symtab_node &other);
+
+ /* Set initialization priority to PRIORITY. */
+ void set_init_priority (priority_type priority);
+
+ /* Return the initialization priority. */
+ priority_type get_init_priority ();
+
+ /* Return availability of NODE when referenced from REF. */
+ enum availability get_availability (symtab_node *ref = NULL);
+
+ /* During LTO stream-in this predicate can be used to check whether node
+ in question prevails in the linking to save some memory usage. */
+ bool prevailing_p (void);
+
+ /* Return true if NODE binds to current definition in final executable
+ when referenced from REF. If REF is NULL return conservative value
+ for any reference. */
+ bool binds_to_current_def_p (symtab_node *ref = NULL);
+
+ /* Make DECL local. */
+ void make_decl_local (void);
+
+ /* Copy visibility from N. */
+ void copy_visibility_from (symtab_node *n);
+
+ /* Return desired alignment of the definition. This is NOT alignment useful
+ to access THIS, because THIS may be interposable and DECL_ALIGN should
+ be used instead. It however must be guaranteed when output definition
+ of THIS. */
+ unsigned int definition_alignment ();
+
+ /* Return true if alignment can be increased. */
+ bool can_increase_alignment_p ();
+
+ /* Increase alignment of symbol to ALIGN. */
+ void increase_alignment (unsigned int align);
+
+ /* Return true if list contains an alias. */
+ bool has_aliases_p (void);
+
+ /* Return true when the symbol is real symbol, i.e. it is not inline clone
+ or abstract function kept for debug info purposes only. */
+ bool real_symbol_p (void);
+
+ /* Return true when the symbol needs to be output to the LTO symbol table. */
+ bool output_to_lto_symbol_table_p (void);
+
+ /* Determine if symbol declaration is needed. That is, visible to something
+ either outside this translation unit, something magic in the system
+ configury. This function is used just during symbol creation. */
+ bool needed_p (void);
+
+ /* Return true if this symbol is a function from the C frontend specified
+ directly in RTL form (with "__RTL"). */
+ bool native_rtl_p () const;
+
+ /* Return true when there are references to the node. */
+ bool referred_to_p (bool include_self = true);
+
+ /* Return true if symbol can be discarded by linker from the binary.
+ Assume that symbol is used (so there is no need to take into account
+ garbage collecting linkers)
+
+ This can happen for comdats, commons and weaks when they are prevailed
+ by other definition at static linking time. */
+ inline bool
+ can_be_discarded_p (void)
+ {
+ return ((DECL_EXTERNAL (decl)
+ && !in_other_partition)
+ || ((get_comdat_group ()
+ || DECL_COMMON (decl)
+ || (DECL_SECTION_NAME (decl) && DECL_WEAK (decl)))
+ && ((resolution != LDPR_PREVAILING_DEF
+ && resolution != LDPR_PREVAILING_DEF_IRONLY_EXP)
+ || flag_incremental_link)
+ && resolution != LDPR_PREVAILING_DEF_IRONLY));
+ }
+
+ /* Return true if NODE is local to a particular COMDAT group, and must not
+ be named from outside the COMDAT. This is used for C++ decloned
+ constructors. */
+ inline bool comdat_local_p (void)
+ {
+ return (same_comdat_group && !TREE_PUBLIC (decl));
+ }
+
+ /* Return true if ONE and TWO are part of the same COMDAT group. */
+ inline bool in_same_comdat_group_p (symtab_node *target);
+
+ /* Return true if symbol is known to be nonzero. */
+ bool nonzero_address ();
+
+ /* Return 0 if symbol is known to have different address than S2,
+ Return 1 if symbol is known to have same address as S2,
+ return 2 otherwise.
+
+ If MEMORY_ACCESSED is true, assume that both memory pointer to THIS
+ and S2 is going to be accessed. This eliminates the situations when
+ either THIS or S2 is NULL and is useful for comparing bases when deciding
+ about memory aliasing. */
+ int equal_address_to (symtab_node *s2, bool memory_accessed = false);
+
+ /* Return true if symbol's address may possibly be compared to other
+ symbol's address. */
+ bool address_matters_p ();
+
+ /* Return true if NODE's address can be compared. This use properties
+ of NODE only and does not look if the address is actually taken in
+ interesting way. For that use ADDRESS_MATTERS_P instead. */
+ bool address_can_be_compared_p (void);
+
+ /* Return symbol table node associated with DECL, if any,
+ and NULL otherwise. */
+ static inline symtab_node *get (const_tree decl)
+ {
+ /* Check that we are called for sane type of object - functions
+ and static or external variables. */
+ gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
+ || in_lto_p)));
+ /* Check that the mapping is sane - perhaps this check can go away,
+ but at the moment frontends tends to corrupt the mapping by calling
+ memcpy/memset on the tree nodes. */
+ gcc_checking_assert (!decl->decl_with_vis.symtab_node
+ || decl->decl_with_vis.symtab_node->decl == decl);
+ return decl->decl_with_vis.symtab_node;
+ }
+
+ /* Try to find a symtab node for declaration DECL and if it does not
+ exist or if it corresponds to an inline clone, create a new one. */
+ static inline symtab_node * get_create (tree node);
+
+ /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
+ Return NULL if there's no such node. */
+ static symtab_node *get_for_asmname (const_tree asmname);
+
+ /* Verify symbol table for internal consistency. */
+ static DEBUG_FUNCTION void verify_symtab_nodes (void);
+
+ /* Perform internal consistency checks, if they are enabled. */
+ static inline void checking_verify_symtab_nodes (void);
+
+ /* Type of the symbol. */
+ ENUM_BITFIELD (symtab_type) type : 8;
+
+ /* The symbols resolution. */
+ ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
+
+ /*** Flags representing the symbol type. ***/
+
+ /* True when symbol corresponds to a definition in current unit.
+ set via finalize_function or finalize_decl */
+ unsigned definition : 1;
+ /* True when symbol is an alias.
+ Set by assemble_alias. */
+ unsigned alias : 1;
+ /* When true the alias is translated into its target symbol either by GCC
+ or assembler (it also may just be a duplicate declaration of the same
+ linker name).
+
+ Currently transparent aliases come in three different flavors
+ - aliases having the same assembler name as their target (aka duplicated
+ declarations). In this case the assembler names compare via
+ assembler_names_equal_p and weakref is false
+ - aliases that are renamed at a time being output to final file
+ by varasm.cc. For those DECL_ASSEMBLER_NAME have
+ IDENTIFIER_TRANSPARENT_ALIAS set and thus also their assembler
+ name must be unique.
+ Weakrefs belong to this category when we target assembler without
+ .weakref directive.
+ - weakrefs that are renamed by assembler via .weakref directive.
+ In this case the alias may or may not be definition (depending if
+ target declaration was seen by the compiler), weakref is set.
+ Unless we are before renaming statics, assembler names are different.
+
+ Given that we now support duplicate declarations, the second option is
+ redundant and will be removed. */
+ unsigned transparent_alias : 1;
+ /* True when alias is a weakref. */
+ unsigned weakref : 1;
+ /* C++ frontend produce same body aliases and extra name aliases for
+ virtual functions and vtables that are obviously equivalent.
+ Those aliases are bit special, especially because C++ frontend
+ visibility code is so ugly it cannot get them right at first time
+ and their visibility needs to be copied from their "masters" at
+ the end of parsing. */
+ unsigned cpp_implicit_alias : 1;
+ /* The alias is a symbol version. */
+ unsigned symver : 1;
+ /* Set once the definition was analyzed. The list of references and
+ other properties are built during analysis. */
+ unsigned analyzed : 1;
+ /* Set for write-only variables. */
+ unsigned writeonly : 1;
+ /* Visibility of symbol was used for further optimization; do not
+ permit further changes. */
+ unsigned refuse_visibility_changes : 1;
+
+ /*** Visibility and linkage flags. ***/
+
+ /* Set when function is visible by other units. */
+ unsigned externally_visible : 1;
+ /* Don't reorder to other symbols having this set. */
+ unsigned no_reorder : 1;
+ /* The symbol will be assumed to be used in an invisible way (like
+ by an toplevel asm statement). */
+ unsigned force_output : 1;
+ /* Like FORCE_OUTPUT, but in the case it is ABI requiring the symbol to be
+ exported. Unlike FORCE_OUTPUT this flag gets cleared to symbols promoted
+ to static and it does not inhibit optimization. */
+ unsigned forced_by_abi : 1;
+ /* True when the name is known to be unique and thus it does not need mangling. */
+ unsigned unique_name : 1;
+ /* Specify whether the section was set by user or by
+ compiler via -ffunction-sections. */
+ unsigned implicit_section : 1;
+ /* True when body and other characteristics have been removed by
+ symtab_remove_unreachable_nodes. */
+ unsigned body_removed : 1;
+ /* True when symbol should comply to -fsemantic-interposition flag. */
+ unsigned semantic_interposition : 1;
+
+ /*** WHOPR Partitioning flags.
+ These flags are used at ltrans stage when only part of the callgraph is
+ available. ***/
+
+ /* Set when variable is used from other LTRANS partition. */
+ unsigned used_from_other_partition : 1;
+ /* Set when function is available in the other LTRANS partition.
+ During WPA output it is used to mark nodes that are present in
+ multiple partitions. */
+ unsigned in_other_partition : 1;
+
+
+
+ /*** other flags. ***/
+
+ /* Set when symbol has address taken. */
+ unsigned address_taken : 1;
+ /* Set when init priority is set. */
+ unsigned in_init_priority_hash : 1;
+
+ /* Set when symbol needs to be streamed into LTO bytecode for LTO, or in case
+ of offloading, for separate compilation for a different target. */
+ unsigned need_lto_streaming : 1;
+
+ /* Set when symbol can be streamed into bytecode for offloading. */
+ unsigned offloadable : 1;
+
+ /* Set when symbol is an IFUNC resolver. */
+ unsigned ifunc_resolver : 1;
+
+
+ /* Ordering of all symtab entries. */
+ int order;
+
+ /* Declaration representing the symbol. */
+ tree decl;
+
+ /* Linked list of symbol table entries starting with symtab_nodes. */
+ symtab_node *next;
+ symtab_node *previous;
+
+ /* Linked list of symbols with the same asm name. There may be multiple
+ entries for single symbol name during LTO, because symbols are renamed
+ only after partitioning.
+
+ Because inline clones are kept in the assembler name has, they also produce
+ duplicate entries.
+
+ There are also several long standing bugs where frontends and builtin
+ code produce duplicated decls. */
+ symtab_node *next_sharing_asm_name;
+ symtab_node *previous_sharing_asm_name;
+
+ /* Circular list of nodes in the same comdat group if non-NULL. */
+ symtab_node *same_comdat_group;
+
+ /* Vectors of referring and referenced entities. */
+ ipa_ref_list GTY((skip)) ref_list;
+
+ /* Alias target. May be either DECL pointer or ASSEMBLER_NAME pointer
+ depending to what was known to frontend on the creation time.
+ Once alias is resolved, this pointer become NULL. */
+ tree alias_target;
+
+ /* File stream where this node is being written to. */
+ struct lto_file_decl_data * lto_file_data;
+
+ PTR GTY ((skip)) aux;
+
+ /* Comdat group the symbol is in. Can be private if GGC allowed that. */
+ tree x_comdat_group;
+
+ /* Section name. Again can be private, if allowed. */
+ section_hash_entry *x_section;
+
+protected:
+ /* Dump base fields of symtab nodes to F. Not to be used directly. */
+ void dump_base (FILE *);
+
+ /* Verify common part of symtab node. */
+ bool DEBUG_FUNCTION verify_base (void);
+
+ /* Remove node from symbol table. This function is not used directly, but via
+ cgraph/varpool node removal routines. */
+ void unregister (struct clone_info *);
+
+ /* Return the initialization and finalization priority information for
+ DECL. If there is no previous priority information, a freshly
+ allocated structure is returned. */
+ struct symbol_priority_map *priority_info (void);
+
+ /* Worker for call_for_symbol_and_aliases_1. */
+ bool call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *, void *),
+ void *data,
+ bool include_overwrite);
+private:
+ /* Workers for set_section. */
+ static bool set_section_from_string (symtab_node *n, void *s);
+ static bool set_section_from_node (symtab_node *n, void *o);
+
+ /* Worker for symtab_resolve_alias. */
+ static bool set_implicit_section (symtab_node *n, void *);
+
+ /* Worker searching noninterposable alias. */
+ static bool noninterposable_alias (symtab_node *node, void *data);
+
+ /* Worker for ultimate_alias_target. */
+ symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL,
+ symtab_node *ref = NULL);
+
+ /* Get dump name with normal or assembly name. */
+ const char *get_dump_name (bool asm_name_p) const;
+};
+
+inline void
+symtab_node::checking_verify_symtab_nodes (void)
+{
+ if (flag_checking)
+ symtab_node::verify_symtab_nodes ();
+}
+
+/* Walk all aliases for NODE. */
+#define FOR_EACH_ALIAS(NODE, ALIAS) \
+ for (unsigned ALIAS##_iter_ = 0; \
+ (NODE)->iterate_direct_aliases (ALIAS##_iter_, ALIAS); \
+ ALIAS##_iter_++)
+
+/* This is the information that is put into the cgraph local structure
+ to recover a function. */
+struct lto_file_decl_data;
+
+extern const char * const cgraph_availability_names[];
+extern const char * const ld_plugin_symbol_resolution_names[];
+extern const char * const tls_model_names[];
+
+/* Represent which DECL tree (or reference to such tree)
+ will be replaced by another tree while versioning. */
+struct GTY(()) ipa_replace_map
+{
+ /* The new (replacing) tree. */
+ tree new_tree;
+ /* Parameter number to replace, when old_tree is NULL. */
+ int parm_num;
+ /* Set if the newly added reference should not be an address one, but a load
+ one from the operand of the ADDR_EXPR in NEW_TREE. This is for cases when
+ the corresponding parameter p is used only as *p. */
+ unsigned force_load_ref : 1;
+};
+
+enum cgraph_simd_clone_arg_type
+{
+ SIMD_CLONE_ARG_TYPE_VECTOR,
+ SIMD_CLONE_ARG_TYPE_UNIFORM,
+ /* These are only for integer/pointer arguments passed by value. */
+ SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP,
+ SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP,
+ /* These 6 are only for reference type arguments or arguments passed
+ by reference. */
+ SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP,
+ SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP,
+ SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP,
+ SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP,
+ SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP,
+ SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP,
+ SIMD_CLONE_ARG_TYPE_MASK
+};
+
+/* Function arguments in the original function of a SIMD clone.
+ Supplementary data for `struct simd_clone'. */
+
+struct GTY(()) cgraph_simd_clone_arg {
+ /* Original function argument as it originally existed in
+ DECL_ARGUMENTS. */
+ tree orig_arg;
+
+ /* orig_arg's function (or for extern functions type from
+ TYPE_ARG_TYPES). */
+ tree orig_type;
+
+ /* If argument is a vector, this holds the vector version of
+ orig_arg that after adjusting the argument types will live in
+ DECL_ARGUMENTS. Otherwise, this is NULL.
+
+ This basically holds:
+ vector(simdlen) __typeof__(orig_arg) new_arg. */
+ tree vector_arg;
+
+ /* vector_arg's type (or for extern functions new vector type. */
+ tree vector_type;
+
+ /* If argument is a vector, this holds the array where the simd
+ argument is held while executing the simd clone function. This
+ is a local variable in the cloned function. Its content is
+ copied from vector_arg upon entry to the clone.
+
+ This basically holds:
+ __typeof__(orig_arg) simd_array[simdlen]. */
+ tree simd_array;
+
+ /* A SIMD clone's argument can be either linear (constant or
+ variable), uniform, or vector. */
+ enum cgraph_simd_clone_arg_type arg_type;
+
+ /* Variable alignment if available, otherwise 0. */
+ unsigned int alignment;
+
+ /* For arg_type SIMD_CLONE_ARG_TYPE_LINEAR_*CONSTANT_STEP this is
+ the constant linear step, if arg_type is
+ SIMD_CLONE_ARG_TYPE_LINEAR_*VARIABLE_STEP, this is index of
+ the uniform argument holding the step, otherwise 0. */
+ HOST_WIDE_INT linear_step;
+};
+
+/* Specific data for a SIMD function clone. */
+
+#if 0 // sdcpp
+struct GTY(()) cgraph_simd_clone {
+ /* Number of words in the SIMD lane associated with this clone. */
+ poly_uint64 simdlen;
+
+ /* Number of annotated function arguments in `args'. This is
+ usually the number of named arguments in FNDECL. */
+ unsigned int nargs;
+
+ /* Max hardware vector size in bits for integral vectors. */
+ poly_uint64 vecsize_int;
+
+ /* Max hardware vector size in bits for floating point vectors. */
+ poly_uint64 vecsize_float;
+
+ /* Machine mode of the mask argument(s), if they are to be passed
+ as bitmasks in integer argument(s). VOIDmode if masks are passed
+ as vectors of characteristic type. */
+ machine_mode mask_mode;
+
+ /* The mangling character for a given vector size. This is used
+ to determine the ISA mangling bit as specified in the Intel
+ Vector ABI. */
+ unsigned char vecsize_mangle;
+
+ /* True if this is the masked, in-branch version of the clone,
+ otherwise false. */
+ unsigned int inbranch : 1;
+
+ /* Doubly linked list of SIMD clones. */
+ cgraph_node *prev_clone, *next_clone;
+
+ /* Original cgraph node the SIMD clones were created for. */
+ cgraph_node *origin;
+
+ /* Annotated function arguments for the original function. */
+ cgraph_simd_clone_arg GTY((length ("%h.nargs"))) args[1];
+};
+#else
+struct GTY(()) cgraph_simd_clone;
+#endif // sdcpp
+
+/* Function Multiversioning info. */
+struct GTY((for_user)) cgraph_function_version_info {
+ /* The cgraph_node for which the function version info is stored. */
+ cgraph_node *this_node;
+ /* Chains all the semantically identical function versions. The
+ first function in this chain is the version_info node of the
+ default function. */
+ cgraph_function_version_info *prev;
+ /* If this version node corresponds to a dispatcher for function
+ versions, this points to the version info node of the default
+ function, the first node in the chain. */
+ cgraph_function_version_info *next;
+ /* If this node corresponds to a function version, this points
+ to the dispatcher function decl, which is the function that must
+ be called to execute the right function version at run-time.
+
+ If this cgraph node is a dispatcher (if dispatcher_function is
+ true, in the cgraph_node struct) for function versions, this
+ points to resolver function, which holds the function body of the
+ dispatcher. The dispatcher decl is an alias to the resolver
+ function decl. */
+ tree dispatcher_resolver;
+};
+
+#define DEFCIFCODE(code, type, string) CIF_ ## code,
+/* Reasons for inlining failures. */
+
+enum cgraph_inline_failed_t {
+#include "cif-code.def"
+ CIF_N_REASONS
+};
+
+enum cgraph_inline_failed_type_t
+{
+ CIF_FINAL_NORMAL = 0,
+ CIF_FINAL_ERROR
+};
+
+struct cgraph_edge;
+
+struct cgraph_edge_hasher : ggc_ptr_hash<cgraph_edge>
+{
+ typedef gimple *compare_type;
+
+ static hashval_t hash (cgraph_edge *);
+ static hashval_t hash (gimple *);
+ static bool equal (cgraph_edge *, gimple *);
+};
+
+/* The cgraph data structure.
+ Each function decl has assigned cgraph_node listing callees and callers. */
+
+struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
+{
+ friend class symbol_table;
+
+ /* Constructor. */
+ explicit cgraph_node (int uid)
+ : symtab_node (SYMTAB_FUNCTION), callees (NULL), callers (NULL),
+ indirect_calls (NULL),
+ next_sibling_clone (NULL), prev_sibling_clone (NULL), clones (NULL),
+ clone_of (NULL), call_site_hash (NULL), former_clone_of (NULL),
+ simdclone (NULL), simd_clones (NULL), ipa_transforms_to_apply (vNULL),
+ inlined_to (NULL), rtl (NULL),
+ count (profile_count::uninitialized ()),
+ count_materialization_scale (REG_BR_PROB_BASE), profile_id (0),
+ unit_id (0), tp_first_run (0), thunk (false),
+ used_as_abstract_origin (false),
+ lowered (false), process (false), frequency (NODE_FREQUENCY_NORMAL),
+ only_called_at_startup (false), only_called_at_exit (false),
+ tm_clone (false), dispatcher_function (false), calls_comdat_local (false),
+ icf_merged (false), nonfreeing_fn (false), merged_comdat (false),
+ merged_extern_inline (false), parallelized_function (false),
+ split_part (false), indirect_call_target (false), local (false),
+ versionable (false), can_change_signature (false),
+ redefined_extern_inline (false), tm_may_enter_irr (false),
+ ipcp_clone (false), declare_variant_alt (false),
+ calls_declare_variant_alt (false), m_uid (uid), m_summary_id (-1)
+ {}
+
+ /* Remove the node from cgraph and all inline clones inlined into it.
+ Skip however removal of FORBIDDEN_NODE and return true if it needs to be
+ removed. This allows to call the function from outer loop walking clone
+ tree. */
+ bool remove_symbol_and_inline_clones (cgraph_node *forbidden_node = NULL);
+
+ /* Record all references from cgraph_node that are taken
+ in statement STMT. */
+ void record_stmt_references (gimple *stmt);
+
+ /* Like cgraph_set_call_stmt but walk the clone tree and update all
+ clones sharing the same function body.
+ When WHOLE_SPECULATIVE_EDGES is true, all three components of
+ speculative edge gets updated. Otherwise we update only direct
+ call. */
+ void set_call_stmt_including_clones (gimple *old_stmt, gcall *new_stmt,
+ bool update_speculative = true);
+
+ /* Walk the alias chain to return the function cgraph_node is alias of.
+ Walk through thunk, too.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+ cgraph_node *function_symbol (enum availability *avail = NULL,
+ struct symtab_node *ref = NULL);
+
+ /* Walk the alias chain to return the function cgraph_node is alias of.
+ Walk through non virtual thunks, too. Thus we return either a function
+ or a virtual thunk node.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+ cgraph_node *function_or_virtual_thunk_symbol
+ (enum availability *avail = NULL,
+ struct symtab_node *ref = NULL);
+
+ /* Create node representing clone of N executed COUNT times. Decrease
+ the execution counts from original node too.
+ The new clone will have decl set to DECL that may or may not be the same
+ as decl of N.
+
+ When UPDATE_ORIGINAL is true, the counts are subtracted from the original
+ function's profile to reflect the fact that part of execution is handled
+ by node.
+ When CALL_DUPLICATION_HOOK is true, the ipa passes are acknowledged about
+ the new clone. Otherwise the caller is responsible for doing so later.
+
+ If the new node is being inlined into another one, NEW_INLINED_TO should be
+ the outline function the new one is (even indirectly) inlined to.
+ All hooks will see this in node's inlined_to, when invoked.
+ Can be NULL if the node is not inlined. SUFFIX is string that is appended
+ to the original name. */
+ cgraph_node *create_clone (tree decl, profile_count count,
+ bool update_original,
+ vec<cgraph_edge *> redirect_callers,
+ bool call_duplication_hook,
+ cgraph_node *new_inlined_to,
+ ipa_param_adjustments *param_adjustments,
+ const char *suffix = NULL);
+
+ /* Create callgraph node clone with new declaration. The actual body will be
+ copied later at compilation stage. The name of the new clone will be
+ constructed from the name of the original node, SUFFIX and NUM_SUFFIX. */
+ cgraph_node *create_virtual_clone (const vec<cgraph_edge *> &redirect_callers,
+ vec<ipa_replace_map *, va_gc> *tree_map,
+ ipa_param_adjustments *param_adjustments,
+ const char * suffix, unsigned num_suffix);
+
+ /* Remove the node from the tree of virtual and inline clones and make it a
+ standalone node - not a clone any more. */
+ void remove_from_clone_tree ();
+
+ /* cgraph node being removed from symbol table; see if its entry can be
+ replaced by other inline clone. */
+ cgraph_node *find_replacement (struct clone_info *);
+
+ /* Create a new cgraph node which is the new version of
+ callgraph node. REDIRECT_CALLERS holds the callers
+ edges which should be redirected to point to
+ NEW_VERSION. ALL the callees edges of the node
+ are cloned to the new version node. Return the new
+ version node.
+
+ If non-NULL BLOCK_TO_COPY determine what basic blocks
+ was copied to prevent duplications of calls that are dead
+ in the clone.
+
+ SUFFIX is string that is appended to the original name. */
+
+ cgraph_node *create_version_clone (tree new_decl,
+ vec<cgraph_edge *> redirect_callers,
+ bitmap bbs_to_copy,
+ const char *suffix = NULL);
+
+ /* Perform function versioning.
+ Function versioning includes copying of the tree and
+ a callgraph update (creating a new cgraph node and updating
+ its callees and callers).
+
+ REDIRECT_CALLERS varray includes the edges to be redirected
+ to the new version.
+
+ TREE_MAP is a mapping of tree nodes we want to replace with
+ new ones (according to results of prior analysis).
+
+ If non-NULL ARGS_TO_SKIP determine function parameters to remove
+ from new version.
+ If SKIP_RETURN is true, the new version will return void.
+ If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
+ If non_NULL NEW_ENTRY determine new entry BB of the clone.
+
+ If TARGET_ATTRIBUTES is non-null, when creating a new declaration,
+ add the attributes to DECL_ATTRIBUTES. And call valid_attribute_p
+ that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET
+ of the declaration.
+
+ If VERSION_DECL is set true, use clone_function_name_numbered for the
+ function clone. Otherwise, use clone_function_name.
+
+ Return the new version's cgraph node. */
+ cgraph_node *create_version_clone_with_body
+ (vec<cgraph_edge *> redirect_callers,
+ vec<ipa_replace_map *, va_gc> *tree_map,
+ ipa_param_adjustments *param_adjustments,
+ bitmap bbs_to_copy, basic_block new_entry_block, const char *clone_name,
+ tree target_attributes = NULL_TREE, bool version_decl = true);
+
+ /* Insert a new cgraph_function_version_info node into cgraph_fnver_htab
+ corresponding to cgraph_node. */
+ cgraph_function_version_info *insert_new_function_version (void);
+
+ /* Get the cgraph_function_version_info node corresponding to node. */
+ cgraph_function_version_info *function_version (void);
+
+ /* Discover all functions and variables that are trivially needed, analyze
+ them as well as all functions and variables referred by them */
+ void analyze (void);
+
+ /* Add thunk alias into callgraph. The alias declaration is ALIAS and it
+ aliases DECL with an adjustments made into the first parameter.
+ See comments in struct symtab-thunks.h for detail on the parameters. */
+ cgraph_node * create_thunk (tree alias, tree, bool this_adjusting,
+ HOST_WIDE_INT fixed_offset,
+ HOST_WIDE_INT virtual_value,
+ HOST_WIDE_INT indirect_offset,
+ tree virtual_offset,
+ tree real_alias);
+
+
+ /* Return node that alias is aliasing. */
+ inline cgraph_node *get_alias_target (void);
+
+ /* Given function symbol, walk the alias chain to return the function node
+ is alias of. Do not walk through thunks.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+
+ cgraph_node *ultimate_alias_target (availability *availability = NULL,
+ symtab_node *ref = NULL);
+
+ /* Call expand_thunk on all callers that are thunks and analyze those
+ nodes that were expanded. */
+ void expand_all_artificial_thunks ();
+
+ /* Assemble thunks and aliases associated to node. */
+ void assemble_thunks_and_aliases (void);
+
+ /* Expand function specified by node. */
+ void expand (void);
+
+ /* As an GCC extension we allow redefinition of the function. The
+ semantics when both copies of bodies differ is not well defined.
+ We replace the old body with new body so in unit at a time mode
+ we always use new body, while in normal mode we may end up with
+ old body inlined into some functions and new body expanded and
+ inlined in others. */
+ void reset (void);
+
+ /* Creates a wrapper from cgraph_node to TARGET node. Thunk is used for this
+ kind of wrapper method. */
+ void create_wrapper (cgraph_node *target);
+
+ /* Verify cgraph nodes of the cgraph node. */
+ void DEBUG_FUNCTION verify_node (void);
+
+ /* Remove function from symbol table. */
+ void remove (void);
+
+ /* Dump call graph node to file F. */
+ void dump (FILE *f);
+
+ /* Dump call graph node to file F. */
+ void dump_graphviz (FILE *f);
+
+ /* Dump call graph node to stderr. */
+ void DEBUG_FUNCTION debug (void);
+
+ /* When doing LTO, read cgraph_node's body from disk if it is not already
+ present. */
+ bool get_untransformed_body ();
+
+ /* Prepare function body. When doing LTO, read cgraph_node's body from disk
+ if it is not already present. When some IPA transformations are scheduled,
+ apply them. */
+ bool get_body ();
+
+ void materialize_clone (void);
+
+ /* Release memory used to represent body of function.
+ Use this only for functions that are released before being translated to
+ target code (i.e. RTL). Functions that are compiled to RTL and beyond
+ are free'd in final.cc via free_after_compilation(). */
+ void release_body (bool keep_arguments = false);
+
+ /* Return the DECL_STRUCT_FUNCTION of the function. */
+ struct function *get_fun () const;
+
+ /* Bring cgraph node local. */
+ void make_local (void);
+
+ /* Likewise indicate that a node is having address taken. */
+ void mark_address_taken (void);
+
+ /* Set finalization priority to PRIORITY. */
+ void set_fini_priority (priority_type priority);
+
+ /* Return the finalization priority. */
+ priority_type get_fini_priority (void);
+
+ /* Create edge from a given function to CALLEE in the cgraph. */
+ cgraph_edge *create_edge (cgraph_node *callee,
+ gcall *call_stmt, profile_count count,
+ bool cloning_p = false);
+
+ /* Create an indirect edge with a yet-undetermined callee where the call
+ statement destination is a formal parameter of the caller with index
+ PARAM_INDEX. */
+ cgraph_edge *create_indirect_edge (gcall *call_stmt, int ecf_flags,
+ profile_count count,
+ bool cloning_p = false);
+
+ /* Like cgraph_create_edge walk the clone tree and update all clones sharing
+ same function body. If clones already have edge for OLD_STMT; only
+ update the edge same way as cgraph_set_call_stmt_including_clones does. */
+ void create_edge_including_clones (cgraph_node *callee,
+ gimple *old_stmt, gcall *stmt,
+ profile_count count,
+ cgraph_inline_failed_t reason);
+
+ /* Return the callgraph edge representing the GIMPLE_CALL statement
+ CALL_STMT. */
+ cgraph_edge *get_edge (gimple *call_stmt);
+
+ /* Collect all callers of cgraph_node and its aliases that are known to lead
+ to NODE (i.e. are not overwritable) and that are not thunks. */
+ auto_vec<cgraph_edge *> collect_callers (void);
+
+ /* Remove all callers from the node. */
+ void remove_callers (void);
+
+ /* Remove all callees from the node. */
+ void remove_callees (void);
+
+ /* Return function availability. See cgraph.h for description of individual
+ return values. */
+ enum availability get_availability (symtab_node *ref = NULL);
+
+ /* Set TREE_NOTHROW on cgraph_node's decl and on aliases of the node
+ if any to NOTHROW. */
+ bool set_nothrow_flag (bool nothrow);
+
+ /* SET DECL_IS_MALLOC on cgraph_node's decl and on aliases of the node
+ if any. */
+ bool set_malloc_flag (bool malloc_p);
+
+ /* SET TREE_THIS_VOLATILE on cgraph_node's decl and on aliases of the node
+ if any. */
+ bool set_noreturn_flag (bool noreturn_p);
+
+ /* If SET_CONST is true, mark function, aliases and thunks to be ECF_CONST.
+ If SET_CONST if false, clear the flag.
+
+ When setting the flag be careful about possible interposition and
+ do not set the flag for functions that can be interposed and set pure
+ flag for functions that can bind to other definition.
+
+ Return true if any change was done. */
+
+ bool set_const_flag (bool set_const, bool looping);
+
+ /* Set DECL_PURE_P on cgraph_node's decl and on aliases of the node
+ if any to PURE.
+
+ When setting the flag, be careful about possible interposition.
+ Return true if any change was done. */
+
+ bool set_pure_flag (bool pure, bool looping);
+
+ /* Call callback on function and aliases associated to the function.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. */
+
+ bool call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
+ void *),
+ void *data, bool include_overwritable);
+
+ /* Call callback on cgraph_node, thunks and aliases associated to NODE.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. When EXCLUDE_VIRTUAL_THUNKS is true, virtual thunks are
+ skipped. */
+ bool call_for_symbol_thunks_and_aliases (bool (*callback) (cgraph_node *node,
+ void *data),
+ void *data,
+ bool include_overwritable,
+ bool exclude_virtual_thunks = false);
+
+ /* Likewise indicate that a node is needed, i.e. reachable via some
+ external means. */
+ inline void mark_force_output (void);
+
+ /* Return true when function can be marked local. */
+ bool local_p (void);
+
+ /* Return true if cgraph_node can be made local for API change.
+ Extern inline functions and C++ COMDAT functions can be made local
+ at the expense of possible code size growth if function is used in multiple
+ compilation units. */
+ bool can_be_local_p (void);
+
+ /* Return true when cgraph_node cannot return or throw and thus
+ it is safe to ignore its side effects for IPA analysis. */
+ bool cannot_return_p (void);
+
+ /* Return true when function cgraph_node and all its aliases are only called
+ directly.
+ i.e. it is not externally visible, address was not taken and
+ it is not used in any other non-standard way. */
+ bool only_called_directly_p (void);
+
+ /* Return true when function is only called directly or it has alias.
+ i.e. it is not externally visible, address was not taken and
+ it is not used in any other non-standard way. */
+ inline bool only_called_directly_or_aliased_p (void);
+
+ /* Return true when function cgraph_node can be expected to be removed
+ from program when direct calls in this compilation unit are removed.
+
+ As a special case COMDAT functions are
+ cgraph_can_remove_if_no_direct_calls_p while the are not
+ cgraph_only_called_directly_p (it is possible they are called from other
+ unit)
+
+ This function behaves as cgraph_only_called_directly_p because eliminating
+ all uses of COMDAT function does not make it necessarily disappear from
+ the program unless we are compiling whole program or we do LTO. In this
+ case we know we win since dynamic linking will not really discard the
+ linkonce section.
+
+ If WILL_INLINE is true, assume that function will be inlined into all the
+ direct calls. */
+ bool will_be_removed_from_program_if_no_direct_calls_p
+ (bool will_inline = false);
+
+ /* Return true when function can be removed from callgraph
+ if all direct calls and references are eliminated. The function does
+ not take into account comdat groups. */
+ bool can_remove_if_no_direct_calls_and_refs_p (void);
+
+ /* Return true when function cgraph_node and its aliases can be removed from
+ callgraph if all direct calls are eliminated.
+ If WILL_INLINE is true, assume that function will be inlined into all the
+ direct calls. */
+ bool can_remove_if_no_direct_calls_p (bool will_inline = false);
+
+ /* Return true when callgraph node is a function with Gimple body defined
+ in current unit. Functions can also be define externally or they
+ can be thunks with no Gimple representation.
+
+ Note that at WPA stage, the function body may not be present in memory. */
+ inline bool has_gimple_body_p (void);
+
+ /* Return true if this node represents a former, i.e. an expanded, thunk. */
+ bool former_thunk_p (void);
+
+ /* Check if function calls comdat local. This is used to recompute
+ calls_comdat_local flag after function transformations. */
+ bool check_calls_comdat_local_p ();
+
+ /* Return true if function should be optimized for size. */
+ enum optimize_size_level optimize_for_size_p (void);
+
+ /* Dump the callgraph to file F. */
+ static void dump_cgraph (FILE *f);
+
+ /* Dump the call graph to stderr. */
+ static inline
+ void debug_cgraph (void)
+ {
+ dump_cgraph (stderr);
+ }
+
+ /* Get unique identifier of the node. */
+ inline int get_uid ()
+ {
+ return m_uid;
+ }
+
+ /* Get summary id of the node. */
+ inline int get_summary_id ()
+ {
+ return m_summary_id;
+ }
+
+ /* Record that DECL1 and DECL2 are semantically identical function
+ versions. */
+ static void record_function_versions (tree decl1, tree decl2);
+
+ /* Remove the cgraph_function_version_info and cgraph_node for DECL. This
+ DECL is a duplicate declaration. */
+ static void delete_function_version_by_decl (tree decl);
+
+ /* Add the function FNDECL to the call graph.
+ Unlike finalize_function, this function is intended to be used
+ by middle end and allows insertion of new function at arbitrary point
+ of compilation. The function can be either in high, low or SSA form
+ GIMPLE.
+
+ The function is assumed to be reachable and have address taken (so no
+ API breaking optimizations are performed on it).
+
+ Main work done by this function is to enqueue the function for later
+ processing to avoid need the passes to be re-entrant. */
+ static void add_new_function (tree fndecl, bool lowered);
+
+ /* Return callgraph node for given symbol and check it is a function. */
+ static inline cgraph_node *get (const_tree decl)
+ {
+ gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ return dyn_cast <cgraph_node *> (symtab_node::get (decl));
+ }
+
+ /* DECL has been parsed. Take it, queue it, compile it at the whim of the
+ logic in effect. If NO_COLLECT is true, then our caller cannot stand to
+ have the garbage collector run at the moment. We would need to either
+ create a new GC context, or just not compile right now. */
+ static void finalize_function (tree, bool);
+
+ /* Return cgraph node assigned to DECL. Create new one when needed. */
+ static cgraph_node * create (tree decl);
+
+ /* Try to find a call graph node for declaration DECL and if it does not
+ exist or if it corresponds to an inline clone, create a new one. */
+ static cgraph_node * get_create (tree);
+
+ /* Return local info for the compiled function. */
+ static cgraph_node *local_info_node (tree decl);
+
+ /* Return RTL info for the compiled function. */
+ static struct cgraph_rtl_info *rtl_info (const_tree);
+
+ /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
+ Return NULL if there's no such node. */
+ static cgraph_node *get_for_asmname (tree asmname);
+
+ /* Attempt to mark ALIAS as an alias to DECL. Return alias node if
+ successful and NULL otherwise.
+ Same body aliases are output whenever the body of DECL is output,
+ and cgraph_node::get (ALIAS) transparently
+ returns cgraph_node::get (DECL). */
+ static cgraph_node * create_same_body_alias (tree alias, tree decl);
+
+ /* Verify whole cgraph structure. */
+ static void DEBUG_FUNCTION verify_cgraph_nodes (void);
+
+ /* Verify cgraph, if consistency checking is enabled. */
+ static inline void checking_verify_cgraph_nodes (void);
+
+ /* Worker to bring NODE local. */
+ static bool make_local (cgraph_node *node, void *);
+
+ /* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing
+ the function body is associated
+ with (not necessarily cgraph_node (DECL). */
+ static cgraph_node *create_alias (tree alias, tree target);
+
+ /* Return true if NODE has thunk. */
+ static bool has_thunk_p (cgraph_node *node, void *);
+
+ cgraph_edge *callees;
+ cgraph_edge *callers;
+ /* List of edges representing indirect calls with a yet undetermined
+ callee. */
+ cgraph_edge *indirect_calls;
+ cgraph_node *next_sibling_clone;
+ cgraph_node *prev_sibling_clone;
+ cgraph_node *clones;
+ cgraph_node *clone_of;
+ /* For functions with many calls sites it holds map from call expression
+ to the edge to speed up cgraph_edge function. */
+ hash_table<cgraph_edge_hasher> *GTY(()) call_site_hash;
+ /* Declaration node used to be clone of. */
+ tree former_clone_of;
+
+ /* If this is a SIMD clone, this points to the SIMD specific
+ information for it. */
+ cgraph_simd_clone *simdclone;
+ /* If this function has SIMD clones, this points to the first clone. */
+ cgraph_node *simd_clones;
+
+ /* Interprocedural passes scheduled to have their transform functions
+ applied next time we execute local pass on them. We maintain it
+ per-function in order to allow IPA passes to introduce new functions. */
+ vec<ipa_opt_pass, va_heap, vl_ptr> GTY((skip)) ipa_transforms_to_apply;
+
+ /* For inline clones this points to the function they will be
+ inlined into. */
+ cgraph_node *inlined_to;
+
+ struct cgraph_rtl_info *rtl;
+
+ /* Expected number of executions: calculated in profile.cc. */
+ profile_count count;
+ /* How to scale counts at materialization time; used to merge
+ LTO units with different number of profile runs. */
+ int count_materialization_scale;
+ /* ID assigned by the profiling. */
+ unsigned int profile_id;
+ /* ID of the translation unit. */
+ int unit_id;
+ /* Time profiler: first run of function. */
+ int tp_first_run;
+
+ /* True when symbol is a thunk. */
+ unsigned thunk : 1;
+ /* Set when decl is an abstract function pointed to by the
+ ABSTRACT_DECL_ORIGIN of a reachable function. */
+ unsigned used_as_abstract_origin : 1;
+ /* Set once the function is lowered (i.e. its CFG is built). */
+ unsigned lowered : 1;
+ /* Set once the function has been instantiated and its callee
+ lists created. */
+ unsigned process : 1;
+ /* How commonly executed the node is. Initialized during branch
+ probabilities pass. */
+ ENUM_BITFIELD (node_frequency) frequency : 2;
+ /* True when function can only be called at startup (from static ctor). */
+ unsigned only_called_at_startup : 1;
+ /* True when function can only be called at startup (from static dtor). */
+ unsigned only_called_at_exit : 1;
+ /* True when function is the transactional clone of a function which
+ is called only from inside transactions. */
+ /* ?? We should be able to remove this. We have enough bits in
+ cgraph to calculate it. */
+ unsigned tm_clone : 1;
+ /* True if this decl is a dispatcher for function versions. */
+ unsigned dispatcher_function : 1;
+ /* True if this decl calls a COMDAT-local function. This is set up in
+ compute_fn_summary and inline_call. */
+ unsigned calls_comdat_local : 1;
+ /* True if node has been created by merge operation in IPA-ICF. */
+ unsigned icf_merged: 1;
+ /* True if call to node can't result in a call to free, munmap or
+ other operation that could make previously non-trapping memory
+ accesses trapping. */
+ unsigned nonfreeing_fn : 1;
+ /* True if there was multiple COMDAT bodies merged by lto-symtab. */
+ unsigned merged_comdat : 1;
+ /* True if this def was merged with extern inlines. */
+ unsigned merged_extern_inline : 1;
+ /* True if function was created to be executed in parallel. */
+ unsigned parallelized_function : 1;
+ /* True if function is part split out by ipa-split. */
+ unsigned split_part : 1;
+ /* True if the function appears as possible target of indirect call. */
+ unsigned indirect_call_target : 1;
+ /* Set when function is visible in current compilation unit only and
+ its address is never taken. */
+ unsigned local : 1;
+ /* False when there is something makes versioning impossible. */
+ unsigned versionable : 1;
+ /* False when function calling convention and signature cannot be changed.
+ This is the case when __builtin_apply_args is used. */
+ unsigned can_change_signature : 1;
+ /* True when the function has been originally extern inline, but it is
+ redefined now. */
+ unsigned redefined_extern_inline : 1;
+ /* True if the function may enter serial irrevocable mode. */
+ unsigned tm_may_enter_irr : 1;
+ /* True if this was a clone created by ipa-cp. */
+ unsigned ipcp_clone : 1;
+ /* True if this is the deferred declare variant resolution artificial
+ function. */
+ unsigned declare_variant_alt : 1;
+ /* True if the function calls declare_variant_alt functions. */
+ unsigned calls_declare_variant_alt : 1;
+
+private:
+ /* Unique id of the node. */
+ int m_uid;
+
+ /* Summary id that is recycled. */
+ int m_summary_id;
+
+ /* Worker for call_for_symbol_and_aliases. */
+ bool call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
+ void *),
+ void *data, bool include_overwritable);
+};
+
+/* A cgraph node set is a collection of cgraph nodes. A cgraph node
+ can appear in multiple sets. */
+struct cgraph_node_set_def
+{
+ hash_map<cgraph_node *, size_t> *map;
+ vec<cgraph_node *> nodes;
+};
+
+typedef cgraph_node_set_def *cgraph_node_set;
+typedef struct varpool_node_set_def *varpool_node_set;
+
+struct varpool_node;
+
+/* A varpool node set is a collection of varpool nodes. A varpool node
+ can appear in multiple sets. */
+struct varpool_node_set_def
+{
+ hash_map<varpool_node *, size_t> * map;
+ vec<varpool_node *> nodes;
+};
+
+/* Iterator structure for cgraph node sets. */
+struct cgraph_node_set_iterator
+{
+ cgraph_node_set set;
+ unsigned index;
+};
+
+/* Iterator structure for varpool node sets. */
+struct varpool_node_set_iterator
+{
+ varpool_node_set set;
+ unsigned index;
+};
+
+/* Context of polymorphic call. It represent information about the type of
+ instance that may reach the call. This is used by ipa-devirt walkers of the
+ type inheritance graph. */
+
+class GTY(()) ipa_polymorphic_call_context {
+public:
+ /* The called object appears in an object of type OUTER_TYPE
+ at offset OFFSET. When information is not 100% reliable, we
+ use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT speculative_offset;
+ tree outer_type;
+ tree speculative_outer_type;
+ /* True if outer object may be in construction or destruction. */
+ unsigned maybe_in_construction : 1;
+ /* True if outer object may be of derived type. */
+ unsigned maybe_derived_type : 1;
+ /* True if speculative outer object may be of derived type. We always
+ speculate that construction does not happen. */
+ unsigned speculative_maybe_derived_type : 1;
+ /* True if the context is invalid and all calls should be redirected
+ to BUILTIN_UNREACHABLE. */
+ unsigned invalid : 1;
+ /* True if the outer type is dynamic. */
+ unsigned dynamic : 1;
+
+ /* Build empty "I know nothing" context. */
+ ipa_polymorphic_call_context ();
+ /* Build polymorphic call context for indirect call E. */
+ ipa_polymorphic_call_context (cgraph_edge *e);
+ /* Build polymorphic call context for IP invariant CST.
+ If specified, OTR_TYPE specify the type of polymorphic call
+ that takes CST+OFFSET as a parameter. */
+ ipa_polymorphic_call_context (tree cst, tree otr_type = NULL,
+ HOST_WIDE_INT offset = 0);
+ /* Build context for pointer REF contained in FNDECL at statement STMT.
+ if INSTANCE is non-NULL, return pointer to the object described by
+ the context. */
+ ipa_polymorphic_call_context (tree fndecl, tree ref, gimple *stmt,
+ tree *instance = NULL);
+
+ /* Look for vtable stores or constructor calls to work out dynamic type
+ of memory location. */
+ bool get_dynamic_type (tree, tree, tree, gimple *, unsigned *);
+
+ /* Make context non-speculative. */
+ void clear_speculation ();
+
+ /* Produce context specifying all derived types of OTR_TYPE. If OTR_TYPE is
+ NULL, the context is set to dummy "I know nothing" setting. */
+ void clear_outer_type (tree otr_type = NULL);
+
+ /* Walk container types and modify context to point to actual class
+ containing OTR_TYPE (if non-NULL) as base class.
+ Return true if resulting context is valid.
+
+ When CONSIDER_PLACEMENT_NEW is false, reject contexts that may be made
+ valid only via allocation of new polymorphic type inside by means
+ of placement new.
+
+ When CONSIDER_BASES is false, only look for actual fields, not base types
+ of TYPE. */
+ bool restrict_to_inner_class (tree otr_type,
+ bool consider_placement_new = true,
+ bool consider_bases = true);
+
+ /* Adjust all offsets in contexts by given number of bits. */
+ void offset_by (HOST_WIDE_INT);
+ /* Use when we cannot track dynamic type change. This speculatively assume
+ type change is not happening. */
+ void possible_dynamic_type_change (bool, tree otr_type = NULL);
+ /* Assume that both THIS and a given context is valid and strengthen THIS
+ if possible. Return true if any strengthening was made.
+ If actual type the context is being used in is known, OTR_TYPE should be
+ set accordingly. This improves quality of combined result. */
+ bool combine_with (ipa_polymorphic_call_context, tree otr_type = NULL);
+ bool meet_with (ipa_polymorphic_call_context, tree otr_type = NULL);
+
+ /* Return TRUE if context is fully useless. */
+ bool useless_p () const;
+ /* Return TRUE if this context conveys the same information as X. */
+ bool equal_to (const ipa_polymorphic_call_context &x) const;
+
+ /* Dump human readable context to F. If NEWLINE is true, it will be
+ terminated by a newline. */
+ void dump (FILE *f, bool newline = true) const;
+ void DEBUG_FUNCTION debug () const;
+
+ /* LTO streaming. */
+ void stream_out (struct output_block *) const;
+ void stream_in (class lto_input_block *, class data_in *data_in);
+
+private:
+ bool combine_speculation_with (tree, HOST_WIDE_INT, bool, tree);
+ bool meet_speculation_with (tree, HOST_WIDE_INT, bool, tree);
+ void set_by_decl (tree, HOST_WIDE_INT);
+ bool set_by_invariant (tree, tree, HOST_WIDE_INT);
+ bool speculation_consistent_p (tree, HOST_WIDE_INT, bool, tree) const;
+ void make_speculative (tree otr_type = NULL);
+};
+
+/* Structure containing additional information about an indirect call. */
+
+class GTY(()) cgraph_indirect_call_info
+{
+public:
+ /* When agg_content is set, an offset where the call pointer is located
+ within the aggregate. */
+ HOST_WIDE_INT offset;
+ /* Context of the polymorphic call; use only when POLYMORPHIC flag is set. */
+ ipa_polymorphic_call_context context;
+ /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */
+ HOST_WIDE_INT otr_token;
+ /* Type of the object from OBJ_TYPE_REF_OBJECT. */
+ tree otr_type;
+ /* Index of the parameter that is called. */
+ int param_index;
+ /* ECF flags determined from the caller. */
+ int ecf_flags;
+
+ /* Number of speculative call targets, it's less than GCOV_TOPN_VALUES. */
+ unsigned num_speculative_call_targets : 16;
+
+ /* Set when the call is a virtual call with the parameter being the
+ associated object pointer rather than a simple direct call. */
+ unsigned polymorphic : 1;
+ /* Set when the call is a call of a pointer loaded from contents of an
+ aggregate at offset. */
+ unsigned agg_contents : 1;
+ /* Set when this is a call through a member pointer. */
+ unsigned member_ptr : 1;
+ /* When the agg_contents bit is set, this one determines whether the
+ destination is loaded from a parameter passed by reference. */
+ unsigned by_ref : 1;
+ /* When the agg_contents bit is set, this one determines whether we can
+ deduce from the function body that the loaded value from the reference is
+ never modified between the invocation of the function and the load
+ point. */
+ unsigned guaranteed_unmodified : 1;
+ /* For polymorphic calls this specify whether the virtual table pointer
+ may have changed in between function entry and the call. */
+ unsigned vptr_changed : 1;
+};
+
+class GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
+ for_user)) cgraph_edge
+{
+public:
+ friend struct cgraph_node;
+ friend class symbol_table;
+
+ /* Remove EDGE from the cgraph. */
+ static void remove (cgraph_edge *edge);
+
+ /* Change field call_stmt of edge E to NEW_STMT. If UPDATE_SPECULATIVE and E
+ is any component of speculative edge, then update all components.
+ Speculations can be resolved in the process and EDGE can be removed and
+ deallocated. Return the edge that now represents the call. */
+ static cgraph_edge *set_call_stmt (cgraph_edge *e, gcall *new_stmt,
+ bool update_speculative = true);
+
+ /* Redirect callee of the edge to N. The function does not update underlying
+ call expression. */
+ void redirect_callee (cgraph_node *n);
+
+ /* If the edge does not lead to a thunk, simply redirect it to N. Otherwise
+ create one or more equivalent thunks for N and redirect E to the first in
+ the chain. Note that it is then necessary to call
+ n->expand_all_artificial_thunks once all callers are redirected. */
+ void redirect_callee_duplicating_thunks (cgraph_node *n);
+
+ /* Make an indirect edge with an unknown callee an ordinary edge leading to
+ CALLEE. Speculations can be resolved in the process and EDGE can be
+ removed and deallocated. Return the edge that now represents the
+ call. */
+ static cgraph_edge *make_direct (cgraph_edge *edge, cgraph_node *callee);
+
+ /* Turn edge into speculative call calling N2. Update
+ the profile so the direct call is taken COUNT times
+ with FREQUENCY. speculative_id is used to link direct calls with their
+ corresponding IPA_REF_ADDR references when representing speculative calls.
+ */
+ cgraph_edge *make_speculative (cgraph_node *n2, profile_count direct_count,
+ unsigned int speculative_id = 0);
+
+ /* Speculative call consists of an indirect edge and one or more
+ direct edge+ref pairs. Speculative will expand to the following sequence:
+
+ if (call_dest == target1) // reference to target1
+ target1 (); // direct call to target1
+ else if (call_dest == target2) // reference to targt2
+ target2 (); // direct call to target2
+ else
+ call_dest (); // indirect call
+
+ Before the expansion we will have indirect call and the direct call+ref
+ pairs all linked to single statement.
+
+ Note that ref may point to different symbol than the corresponding call
+ becuase the speculated edge may have been optimized (redirected to
+ a clone) or inlined.
+
+ Given an edge which is part of speculative call, return the first
+ direct call edge in the speculative call sequence.
+
+ In the example above called on any cgraph edge in the sequence it will
+ return direct call to target1. */
+ cgraph_edge *first_speculative_call_target ();
+
+ /* Return next speculative call target or NULL if there is none.
+ All targets are required to form an interval in the callee list.
+
+ In example above, if called on call to target1 it will return call to
+ target2. */
+ cgraph_edge *next_speculative_call_target ()
+ {
+ cgraph_edge *e = this;
+ gcc_checking_assert (speculative && callee);
+
+ if (e->next_callee && e->next_callee->speculative
+ && e->next_callee->call_stmt == e->call_stmt
+ && e->next_callee->lto_stmt_uid == e->lto_stmt_uid)
+ return e->next_callee;
+ return NULL;
+ }
+
+ /* When called on any edge in the speculative call return the (unique)
+ indirect call edge in the speculative call sequence. */
+ cgraph_edge *speculative_call_indirect_edge ()
+ {
+ gcc_checking_assert (speculative);
+ if (!callee)
+ return this;
+ for (cgraph_edge *e2 = caller->indirect_calls;
+ true; e2 = e2->next_callee)
+ if (e2->speculative
+ && call_stmt == e2->call_stmt
+ && lto_stmt_uid == e2->lto_stmt_uid)
+ return e2;
+ }
+
+ /* When called on any edge in speculative call and when given any target
+ of ref which is speculated to it returns the corresponding direct call.
+
+ In example above if called on function target2 it will return call to
+ target2. */
+ cgraph_edge *speculative_call_for_target (cgraph_node *);
+
+ /* Return REF corresponding to direct call in the specualtive call
+ sequence. */
+ ipa_ref *speculative_call_target_ref ()
+ {
+ ipa_ref *ref;
+
+ gcc_checking_assert (speculative);
+ for (unsigned int i = 0; caller->iterate_reference (i, ref); i++)
+ if (ref->speculative && ref->speculative_id == speculative_id
+ && ref->stmt == (gimple *)call_stmt
+ && ref->lto_stmt_uid == lto_stmt_uid)
+ return ref;
+ gcc_unreachable ();
+ }
+
+ /* Speculative call edge turned out to be direct call to CALLEE_DECL. Remove
+ the speculative call sequence and return edge representing the call, the
+ original EDGE can be removed and deallocated. It is up to caller to
+ redirect the call as appropriate. Return the edge that now represents the
+ call.
+
+ For "speculative" indirect call that contains multiple "speculative"
+ targets (i.e. edge->indirect_info->num_speculative_call_targets > 1),
+ decrease the count and only remove current direct edge.
+
+ If no speculative direct call left to the speculative indirect call, remove
+ the speculative of both the indirect call and corresponding direct edge.
+
+ It is up to caller to iteratively resolve each "speculative" direct call
+ and redirect the call as appropriate. */
+ static cgraph_edge *resolve_speculation (cgraph_edge *edge,
+ tree callee_decl = NULL);
+
+ /* If necessary, change the function declaration in the call statement
+ associated with edge E so that it corresponds to the edge callee.
+ Speculations can be resolved in the process and EDGE can be removed and
+ deallocated.
+
+ The edge could be one of speculative direct call generated from speculative
+ indirect call. In this circumstance, decrease the speculative targets
+ count (i.e. num_speculative_call_targets) and redirect call stmt to the
+ corresponding i-th target. If no speculative direct call left to the
+ speculative indirect call, remove "speculative" of the indirect call and
+ also redirect stmt to it's final direct target.
+
+ It is up to caller to iteratively transform each "speculative"
+ direct call as appropriate. */
+ static gimple *redirect_call_stmt_to_callee (cgraph_edge *e);
+
+ /* Create clone of edge in the node N represented
+ by CALL_EXPR the callgraph. */
+ cgraph_edge * clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid,
+ profile_count num, profile_count den,
+ bool update_original);
+
+ /* Verify edge count and frequency. */
+ bool verify_count ();
+
+ /* Return true when call of edge cannot lead to return from caller
+ and thus it is safe to ignore its side effects for IPA analysis
+ when computing side effects of the caller. */
+ bool cannot_lead_to_return_p (void);
+
+ /* Return true when the edge represents a direct recursion. */
+ bool recursive_p (void);
+
+ /* Return true if the edge may be considered hot. */
+ bool maybe_hot_p (void);
+
+ /* Get unique identifier of the edge. */
+ inline int get_uid ()
+ {
+ return m_uid;
+ }
+
+ /* Get summary id of the edge. */
+ inline int get_summary_id ()
+ {
+ return m_summary_id;
+ }
+
+ /* Rebuild cgraph edges for current function node. This needs to be run after
+ passes that don't update the cgraph. */
+ static unsigned int rebuild_edges (void);
+
+ /* Rebuild cgraph references for current function node. This needs to be run
+ after passes that don't update the cgraph. */
+ static void rebuild_references (void);
+
+ /* During LTO stream in this can be used to check whether call can possibly
+ be internal to the current translation unit. */
+ bool possibly_call_in_translation_unit_p (void);
+
+ /* Return num_speculative_targets of this edge. */
+ int num_speculative_call_targets_p (void);
+
+ /* Expected number of executions: calculated in profile.cc. */
+ profile_count count;
+ cgraph_node *caller;
+ cgraph_node *callee;
+ cgraph_edge *prev_caller;
+ cgraph_edge *next_caller;
+ cgraph_edge *prev_callee;
+ cgraph_edge *next_callee;
+ gcall *call_stmt;
+ /* Additional information about an indirect call. Not cleared when an edge
+ becomes direct. */
+ cgraph_indirect_call_info *indirect_info;
+ PTR GTY ((skip (""))) aux;
+ /* When equal to CIF_OK, inline this call. Otherwise, points to the
+ explanation why function was not inlined. */
+ enum cgraph_inline_failed_t inline_failed;
+ /* The stmt_uid of call_stmt. This is used by LTO to recover the call_stmt
+ when the function is serialized in. */
+ unsigned int lto_stmt_uid;
+ /* speculative id is used to link direct calls with their corresponding
+ IPA_REF_ADDR references when representing speculative calls. */
+ unsigned int speculative_id : 16;
+ /* Whether this edge was made direct by indirect inlining. */
+ unsigned int indirect_inlining_edge : 1;
+ /* Whether this edge describes an indirect call with an undetermined
+ callee. */
+ unsigned int indirect_unknown_callee : 1;
+ /* Whether this edge is still a dangling */
+ /* True if the corresponding CALL stmt cannot be inlined. */
+ unsigned int call_stmt_cannot_inline_p : 1;
+ /* Can this call throw externally? */
+ unsigned int can_throw_external : 1;
+ /* Edges with SPECULATIVE flag represents indirect calls that was
+ speculatively turned into direct (i.e. by profile feedback).
+ The final code sequence will have form:
+
+ if (call_target == expected_fn)
+ expected_fn ();
+ else
+ call_target ();
+
+ Every speculative call is represented by three components attached
+ to a same call statement:
+ 1) a direct call (to expected_fn)
+ 2) an indirect call (to call_target)
+ 3) a IPA_REF_ADDR reference to expected_fn.
+
+ Optimizers may later redirect direct call to clone, so 1) and 3)
+ do not need to necessarily agree with destination. */
+ unsigned int speculative : 1;
+ /* Set to true when caller is a constructor or destructor of polymorphic
+ type. */
+ unsigned in_polymorphic_cdtor : 1;
+
+ /* Return true if call must bind to current definition. */
+ bool binds_to_current_def_p ();
+
+ /* Expected frequency of executions within the function.
+ When set to CGRAPH_FREQ_BASE, the edge is expected to be called once
+ per function call. The range is 0 to CGRAPH_FREQ_MAX. */
+ int frequency ();
+
+ /* Expected frequency of executions within the function. */
+ sreal sreal_frequency ();
+private:
+ /* Unique id of the edge. */
+ int m_uid;
+
+ /* Summary id that is recycled. */
+ int m_summary_id;
+
+ /* Remove the edge from the list of the callers of the callee. */
+ void remove_caller (void);
+
+ /* Remove the edge from the list of the callees of the caller. */
+ void remove_callee (void);
+
+ /* Set callee N of call graph edge and add it to the corresponding set of
+ callers. */
+ void set_callee (cgraph_node *n);
+
+ /* Output flags of edge to a file F. */
+ void dump_edge_flags (FILE *f);
+
+ /* Dump edge to stderr. */
+ void DEBUG_FUNCTION debug (void);
+
+ /* Verify that call graph edge corresponds to DECL from the associated
+ statement. Return true if the verification should fail. */
+ bool verify_corresponds_to_fndecl (tree decl);
+};
+
+#define CGRAPH_FREQ_BASE 1000
+#define CGRAPH_FREQ_MAX 100000
+
+/* The varpool data structure.
+ Each static variable decl has assigned varpool_node. */
+
+struct GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node
+{
+ /* Constructor. */
+ explicit varpool_node ()
+ : symtab_node (SYMTAB_VARIABLE), output (0), dynamically_initialized (0),
+ tls_model (TLS_MODEL_NONE), used_by_single_function (0)
+ {}
+
+ /* Dump given varpool node to F. */
+ void dump (FILE *f);
+
+ /* Dump given varpool node to stderr. */
+ void DEBUG_FUNCTION debug (void);
+
+ /* Remove variable from symbol table. */
+ void remove (void);
+
+ /* Remove node initializer when it is no longer needed. */
+ void remove_initializer (void);
+
+ void analyze (void);
+
+ /* Return variable availability. */
+ availability get_availability (symtab_node *ref = NULL);
+
+ /* When doing LTO, read variable's constructor from disk if
+ it is not already present. */
+ tree get_constructor (void);
+
+ /* Return true if variable has constructor that can be used for folding. */
+ bool ctor_useable_for_folding_p (void);
+
+ /* For given variable pool node, walk the alias chain to return the function
+ the variable is alias of. Do not walk through thunks.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+ inline varpool_node *ultimate_alias_target
+ (availability *availability = NULL, symtab_node *ref = NULL);
+
+ /* Return node that alias is aliasing. */
+ inline varpool_node *get_alias_target (void);
+
+ /* Output one variable, if necessary. Return whether we output it. */
+ bool assemble_decl (void);
+
+ /* For variables in named sections make sure get_variable_section
+ is called before we switch to those sections. Then section
+ conflicts between read-only and read-only requiring relocations
+ sections can be resolved. */
+ void finalize_named_section_flags (void);
+
+ /* Call callback on varpool symbol and aliases associated to varpool symbol.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. */
+ bool call_for_symbol_and_aliases (bool (*callback) (varpool_node *, void *),
+ void *data,
+ bool include_overwritable);
+
+ /* Return true when variable should be considered externally visible. */
+ bool externally_visible_p (void);
+
+ /* Return true when all references to variable must be visible
+ in ipa_ref_list.
+ i.e. if the variable is not externally visible or not used in some magic
+ way (asm statement or such).
+ The magic uses are all summarized in force_output flag. */
+ inline bool all_refs_explicit_p ();
+
+ /* Return true when variable can be removed from variable pool
+ if all direct calls are eliminated. */
+ inline bool can_remove_if_no_refs_p (void);
+
+ /* Add the variable DECL to the varpool.
+ Unlike finalize_decl function is intended to be used
+ by middle end and allows insertion of new variable at arbitrary point
+ of compilation. */
+ static void add (tree decl);
+
+ /* Return varpool node for given symbol and check it is a function. */
+ static inline varpool_node *get (const_tree decl);
+
+ /* Mark DECL as finalized. By finalizing the declaration, frontend instruct
+ the middle end to output the variable to asm file, if needed or externally
+ visible. */
+ static void finalize_decl (tree decl);
+
+ /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
+ Extra name aliases are output whenever DECL is output. */
+ static varpool_node * create_extra_name_alias (tree alias, tree decl);
+
+ /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful.
+ Extra name aliases are output whenever DECL is output. */
+ static varpool_node * create_alias (tree, tree);
+
+ /* Dump the variable pool to F. */
+ static void dump_varpool (FILE *f);
+
+ /* Dump the variable pool to stderr. */
+ static void DEBUG_FUNCTION debug_varpool (void);
+
+ /* Allocate new callgraph node and insert it into basic data structures. */
+ static varpool_node *create_empty (void);
+
+ /* Return varpool node assigned to DECL. Create new one when needed. */
+ static varpool_node *get_create (tree decl);
+
+ /* Given an assembler name, lookup node. */
+ static varpool_node *get_for_asmname (tree asmname);
+
+ /* Set when variable is scheduled to be assembled. */
+ unsigned output : 1;
+
+ /* Set if the variable is dynamically initialized, except for
+ function local statics. */
+ unsigned dynamically_initialized : 1;
+
+ ENUM_BITFIELD(tls_model) tls_model : 3;
+
+ /* Set if the variable is known to be used by single function only.
+ This is computed by ipa_single_use pass and used by late optimizations
+ in places where optimization would be valid for local static variable
+ if we did not do any inter-procedural code movement. */
+ unsigned used_by_single_function : 1;
+
+private:
+ /* Assemble thunks and aliases associated to varpool node. */
+ void assemble_aliases (void);
+
+ /* Worker for call_for_node_and_aliases. */
+ bool call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, void *),
+ void *data,
+ bool include_overwritable);
+};
+
+/* Every top level asm statement is put into a asm_node. */
+
+struct GTY(()) asm_node {
+ /* Next asm node. */
+ asm_node *next;
+ /* String for this asm node. */
+ tree asm_str;
+ /* Ordering of all cgraph nodes. */
+ int order;
+};
+
+/* Report whether or not THIS symtab node is a function, aka cgraph_node. */
+
+template <>
+template <>
+inline bool
+is_a_helper <cgraph_node *>::test (symtab_node *p)
+{
+ return p && p->type == SYMTAB_FUNCTION;
+}
+
+/* Report whether or not THIS symtab node is a variable, aka varpool_node. */
+
+template <>
+template <>
+inline bool
+is_a_helper <varpool_node *>::test (symtab_node *p)
+{
+ return p && p->type == SYMTAB_VARIABLE;
+}
+
+typedef void (*cgraph_edge_hook)(cgraph_edge *, void *);
+typedef void (*cgraph_node_hook)(cgraph_node *, void *);
+typedef void (*varpool_node_hook)(varpool_node *, void *);
+typedef void (*cgraph_2edge_hook)(cgraph_edge *, cgraph_edge *, void *);
+typedef void (*cgraph_2node_hook)(cgraph_node *, cgraph_node *, void *);
+
+struct cgraph_edge_hook_list;
+struct cgraph_node_hook_list;
+struct varpool_node_hook_list;
+struct cgraph_2edge_hook_list;
+struct cgraph_2node_hook_list;
+
+/* Map from a symbol to initialization/finalization priorities. */
+struct GTY(()) symbol_priority_map {
+ priority_type init;
+ priority_type fini;
+};
+
+enum symtab_state
+{
+ /* Frontend is parsing and finalizing functions. */
+ PARSING,
+ /* Callgraph is being constructed. It is safe to add new functions. */
+ CONSTRUCTION,
+ /* Callgraph is being streamed-in at LTO time. */
+ LTO_STREAMING,
+ /* Callgraph is built and early IPA passes are being run. */
+ IPA,
+ /* Callgraph is built and all functions are transformed to SSA form. */
+ IPA_SSA,
+ /* All inline decisions are done; it is now possible to remove extern inline
+ functions and virtual call targets. */
+ IPA_SSA_AFTER_INLINING,
+ /* Functions are now ordered and being passed to RTL expanders. */
+ EXPANSION,
+ /* All cgraph expansion is done. */
+ FINISHED
+};
+
+struct asmname_hasher : ggc_ptr_hash <symtab_node>
+{
+ typedef const_tree compare_type;
+
+ static hashval_t hash (symtab_node *n);
+ static bool equal (symtab_node *n, const_tree t);
+};
+
+/* Core summaries maintained about symbols. */
+
+struct thunk_info;
+template <class T> class function_summary;
+typedef function_summary <thunk_info *> thunk_summary;
+
+struct clone_info;
+template <class T> class function_summary;
+typedef function_summary <clone_info *> clone_summary;
+
+class GTY((tag ("SYMTAB"))) symbol_table
+{
+public:
+ friend struct symtab_node;
+ friend struct cgraph_node;
+ friend struct cgraph_edge;
+
+ symbol_table ():
+ cgraph_count (0), cgraph_max_uid (1), cgraph_max_summary_id (0),
+ edges_count (0), edges_max_uid (1), edges_max_summary_id (0),
+ cgraph_released_summary_ids (), edge_released_summary_ids (),
+ nodes (NULL), asmnodes (NULL), asm_last_node (NULL),
+ order (0), max_unit (0), global_info_ready (false), state (PARSING),
+ function_flags_ready (false), cpp_implicit_aliases_done (false),
+ section_hash (NULL), assembler_name_hash (NULL), init_priority_hash (NULL),
+ dump_file (NULL), ipa_clones_dump_file (NULL), cloned_nodes (),
+ m_thunks (NULL), m_clones (NULL),
+ m_first_edge_removal_hook (NULL), m_first_cgraph_removal_hook (NULL),
+ m_first_edge_duplicated_hook (NULL), m_first_cgraph_duplicated_hook (NULL),
+ m_first_cgraph_insertion_hook (NULL), m_first_varpool_insertion_hook (NULL),
+ m_first_varpool_removal_hook (NULL)
+ {
+ }
+
+ /* Initialize callgraph dump file. */
+ void initialize (void);
+
+ /* Register a top-level asm statement ASM_STR. */
+ inline asm_node *finalize_toplevel_asm (tree asm_str);
+
+ /* Analyze the whole compilation unit once it is parsed completely. */
+ void finalize_compilation_unit (void);
+
+ /* C++ frontend produce same body aliases all over the place, even before PCH
+ gets streamed out. It relies on us linking the aliases with their function
+ in order to do the fixups, but ipa-ref is not PCH safe. Consequently we
+ first produce aliases without links, but once C++ FE is sure it won't
+ stream PCH we build the links via this function. */
+ void process_same_body_aliases (void);
+
+ /* Perform simple optimizations based on callgraph. */
+ void compile (void);
+
+ /* Process CGRAPH_NEW_FUNCTIONS and perform actions necessary to add these
+ functions into callgraph in a way so they look like ordinary reachable
+ functions inserted into callgraph already at construction time. */
+ void process_new_functions (void);
+
+ /* Register a symbol NODE. */
+ inline void register_symbol (symtab_node *node);
+
+ inline void
+ clear_asm_symbols (void)
+ {
+ asmnodes = NULL;
+ asm_last_node = NULL;
+ }
+
+ /* Perform reachability analysis and reclaim all unreachable nodes. */
+ bool remove_unreachable_nodes (FILE *file);
+
+ /* Optimization of function bodies might've rendered some variables as
+ unnecessary so we want to avoid these from being compiled. Re-do
+ reachability starting from variables that are either externally visible
+ or was referred from the asm output routines. */
+ void remove_unreferenced_decls (void);
+
+ /* Unregister a symbol NODE. */
+ inline void unregister (symtab_node *node);
+
+ /* Allocate new callgraph node and insert it into basic data structures. */
+ cgraph_node *create_empty (void);
+
+ /* Release a callgraph NODE. */
+ void release_symbol (cgraph_node *node);
+
+ /* Output all variables enqueued to be assembled. */
+ bool output_variables (void);
+
+ /* Weakrefs may be associated to external decls and thus not output
+ at expansion time. Emit all necessary aliases. */
+ void output_weakrefs (void);
+
+ /* Return first static symbol with definition. */
+ inline symtab_node *first_symbol (void);
+
+ /* Return first assembler symbol. */
+ inline asm_node *
+ first_asm_symbol (void)
+ {
+ return asmnodes;
+ }
+
+ /* Return first static symbol with definition. */
+ inline symtab_node *first_defined_symbol (void);
+
+ /* Return first variable. */
+ inline varpool_node *first_variable (void);
+
+ /* Return next variable after NODE. */
+ inline varpool_node *next_variable (varpool_node *node);
+
+ /* Return first static variable with initializer. */
+ inline varpool_node *first_static_initializer (void);
+
+ /* Return next static variable with initializer after NODE. */
+ inline varpool_node *next_static_initializer (varpool_node *node);
+
+ /* Return first static variable with definition. */
+ inline varpool_node *first_defined_variable (void);
+
+ /* Return next static variable with definition after NODE. */
+ inline varpool_node *next_defined_variable (varpool_node *node);
+
+ /* Return first function with body defined. */
+ inline cgraph_node *first_defined_function (void);
+
+ /* Return next function with body defined after NODE. */
+ inline cgraph_node *next_defined_function (cgraph_node *node);
+
+ /* Return first function. */
+ inline cgraph_node *first_function (void);
+
+ /* Return next function. */
+ inline cgraph_node *next_function (cgraph_node *node);
+
+ /* Return first function with body defined. */
+ cgraph_node *first_function_with_gimple_body (void);
+
+ /* Return next reachable static variable with initializer after NODE. */
+ inline cgraph_node *next_function_with_gimple_body (cgraph_node *node);
+
+ /* Register HOOK to be called with DATA on each removed edge. */
+ cgraph_edge_hook_list *add_edge_removal_hook (cgraph_edge_hook hook,
+ void *data);
+
+ /* Remove ENTRY from the list of hooks called on removing edges. */
+ void remove_edge_removal_hook (cgraph_edge_hook_list *entry);
+
+ /* Register HOOK to be called with DATA on each removed node. */
+ cgraph_node_hook_list *add_cgraph_removal_hook (cgraph_node_hook hook,
+ void *data);
+
+ /* Remove ENTRY from the list of hooks called on removing nodes. */
+ void remove_cgraph_removal_hook (cgraph_node_hook_list *entry);
+
+ /* Register HOOK to be called with DATA on each removed node. */
+ varpool_node_hook_list *add_varpool_removal_hook (varpool_node_hook hook,
+ void *data);
+
+ /* Remove ENTRY from the list of hooks called on removing nodes. */
+ void remove_varpool_removal_hook (varpool_node_hook_list *entry);
+
+ /* Register HOOK to be called with DATA on each inserted node. */
+ cgraph_node_hook_list *add_cgraph_insertion_hook (cgraph_node_hook hook,
+ void *data);
+
+ /* Remove ENTRY from the list of hooks called on inserted nodes. */
+ void remove_cgraph_insertion_hook (cgraph_node_hook_list *entry);
+
+ /* Register HOOK to be called with DATA on each inserted node. */
+ varpool_node_hook_list *add_varpool_insertion_hook (varpool_node_hook hook,
+ void *data);
+
+ /* Remove ENTRY from the list of hooks called on inserted nodes. */
+ void remove_varpool_insertion_hook (varpool_node_hook_list *entry);
+
+ /* Register HOOK to be called with DATA on each duplicated edge. */
+ cgraph_2edge_hook_list *add_edge_duplication_hook (cgraph_2edge_hook hook,
+ void *data);
+ /* Remove ENTRY from the list of hooks called on duplicating edges. */
+ void remove_edge_duplication_hook (cgraph_2edge_hook_list *entry);
+
+ /* Register HOOK to be called with DATA on each duplicated node. */
+ cgraph_2node_hook_list *add_cgraph_duplication_hook (cgraph_2node_hook hook,
+ void *data);
+
+ /* Remove ENTRY from the list of hooks called on duplicating nodes. */
+ void remove_cgraph_duplication_hook (cgraph_2node_hook_list *entry);
+
+ /* Call all edge removal hooks. */
+ void call_edge_removal_hooks (cgraph_edge *e);
+
+ /* Call all node insertion hooks. */
+ void call_cgraph_insertion_hooks (cgraph_node *node);
+
+ /* Call all node removal hooks. */
+ void call_cgraph_removal_hooks (cgraph_node *node);
+
+ /* Call all node duplication hooks. */
+ void call_cgraph_duplication_hooks (cgraph_node *node, cgraph_node *node2);
+
+ /* Call all edge duplication hooks. */
+ void call_edge_duplication_hooks (cgraph_edge *cs1, cgraph_edge *cs2);
+
+ /* Call all node removal hooks. */
+ void call_varpool_removal_hooks (varpool_node *node);
+
+ /* Call all node insertion hooks. */
+ void call_varpool_insertion_hooks (varpool_node *node);
+
+ /* Arrange node to be first in its entry of assembler_name_hash. */
+ void symtab_prevail_in_asm_name_hash (symtab_node *node);
+
+ /* Initialize asm name hash unless. */
+ void symtab_initialize_asm_name_hash (void);
+
+ /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */
+ void change_decl_assembler_name (tree decl, tree name);
+
+ /* Dump symbol table to F. */
+ void dump (FILE *f);
+
+ /* Dump symbol table to F in graphviz format. */
+ void dump_graphviz (FILE *f);
+
+ /* Dump symbol table to stderr. */
+ void DEBUG_FUNCTION debug (void);
+
+ /* Assign a new summary ID for the callgraph NODE. */
+ inline int assign_summary_id (cgraph_node *node)
+ {
+ if (!cgraph_released_summary_ids.is_empty ())
+ node->m_summary_id = cgraph_released_summary_ids.pop ();
+ else
+ node->m_summary_id = cgraph_max_summary_id++;
+
+ return node->m_summary_id;
+ }
+
+ /* Assign a new summary ID for the callgraph EDGE. */
+ inline int assign_summary_id (cgraph_edge *edge)
+ {
+ if (!edge_released_summary_ids.is_empty ())
+ edge->m_summary_id = edge_released_summary_ids.pop ();
+ else
+ edge->m_summary_id = edges_max_summary_id++;
+
+ return edge->m_summary_id;
+ }
+
+ /* Return true if assembler names NAME1 and NAME2 leads to the same symbol
+ name. */
+ static bool assembler_names_equal_p (const char *name1, const char *name2);
+
+ int cgraph_count;
+ int cgraph_max_uid;
+ int cgraph_max_summary_id;
+
+ int edges_count;
+ int edges_max_uid;
+ int edges_max_summary_id;
+
+ /* Vector of released summary IDS for cgraph nodes. */
+ vec<int> GTY ((skip)) cgraph_released_summary_ids;
+
+ /* Vector of released summary IDS for cgraph nodes. */
+ vec<int> GTY ((skip)) edge_released_summary_ids;
+
+ /* Return symbol used to separate symbol name from suffix. */
+ static char symbol_suffix_separator ();
+
+ symtab_node* GTY(()) nodes;
+ asm_node* GTY(()) asmnodes;
+ asm_node* GTY(()) asm_last_node;
+
+ /* The order index of the next symtab node to be created. This is
+ used so that we can sort the cgraph nodes in order by when we saw
+ them, to support -fno-toplevel-reorder. */
+ int order;
+
+ /* Maximal unit ID used. */
+ int max_unit;
+
+ /* Set when whole unit has been analyzed so we can access global info. */
+ bool global_info_ready;
+ /* What state callgraph is in right now. */
+ enum symtab_state state;
+ /* Set when the cgraph is fully build and the basic flags are computed. */
+ bool function_flags_ready;
+
+ bool cpp_implicit_aliases_done;
+
+ /* Hash table used to hold sections. */
+ hash_table<section_name_hasher> *GTY(()) section_hash;
+
+ /* Hash table used to convert assembler names into nodes. */
+ hash_table<asmname_hasher> *assembler_name_hash;
+
+ /* Hash table used to hold init priorities. */
+ hash_map<symtab_node *, symbol_priority_map> *init_priority_hash;
+
+ FILE* GTY ((skip)) dump_file;
+
+ FILE* GTY ((skip)) ipa_clones_dump_file;
+
+ hash_set <const cgraph_node *> GTY ((skip)) cloned_nodes;
+
+ /* Thunk annotations. */
+ thunk_summary *m_thunks;
+
+ /* Virtual clone annotations. */
+ clone_summary *m_clones;
+
+private:
+ /* Allocate a cgraph_edge structure and fill it with data according to the
+ parameters of which only CALLEE can be NULL (when creating an indirect
+ call edge). CLONING_P should be set if properties that are copied from an
+ original edge should not be calculated. */
+ cgraph_edge *create_edge (cgraph_node *caller, cgraph_node *callee,
+ gcall *call_stmt, profile_count count,
+ bool indir_unknown_callee, bool cloning_p);
+
+ /* Put the edge onto the free list. */
+ void free_edge (cgraph_edge *e);
+
+ /* Insert NODE to assembler name hash. */
+ void insert_to_assembler_name_hash (symtab_node *node, bool with_clones);
+
+ /* Remove NODE from assembler name hash. */
+ void unlink_from_assembler_name_hash (symtab_node *node, bool with_clones);
+
+ /* Hash asmnames ignoring the user specified marks. */
+ static hashval_t decl_assembler_name_hash (const_tree asmname);
+
+ /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
+ static bool decl_assembler_name_equal (tree decl, const_tree asmname);
+
+ friend struct asmname_hasher;
+
+ /* List of hooks triggered when an edge is removed. */
+ cgraph_edge_hook_list * GTY((skip)) m_first_edge_removal_hook;
+ /* List of hooks trigger_red when a cgraph node is removed. */
+ cgraph_node_hook_list * GTY((skip)) m_first_cgraph_removal_hook;
+ /* List of hooks triggered when an edge is duplicated. */
+ cgraph_2edge_hook_list * GTY((skip)) m_first_edge_duplicated_hook;
+ /* List of hooks triggered when a node is duplicated. */
+ cgraph_2node_hook_list * GTY((skip)) m_first_cgraph_duplicated_hook;
+ /* List of hooks triggered when an function is inserted. */
+ cgraph_node_hook_list * GTY((skip)) m_first_cgraph_insertion_hook;
+ /* List of hooks triggered when an variable is inserted. */
+ varpool_node_hook_list * GTY((skip)) m_first_varpool_insertion_hook;
+ /* List of hooks triggered when a node is removed. */
+ varpool_node_hook_list * GTY((skip)) m_first_varpool_removal_hook;
+};
+
+extern GTY(()) symbol_table *symtab;
+
+extern vec<cgraph_node *> cgraph_new_nodes;
+
+inline hashval_t
+asmname_hasher::hash (symtab_node *n)
+{
+ return symbol_table::decl_assembler_name_hash
+ (DECL_ASSEMBLER_NAME (n->decl));
+}
+
+inline bool
+asmname_hasher::equal (symtab_node *n, const_tree t)
+{
+ return symbol_table::decl_assembler_name_equal (n->decl, t);
+}
+
+/* In cgraph.cc */
+void cgraph_cc_finalize (void);
+void release_function_body (tree);
+cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
+
+void cgraph_update_edges_for_call_stmt (gimple *, tree, gimple *);
+bool cgraph_function_possibly_inlined_p (tree);
+
+const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
+cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t);
+
+/* In cgraphunit.cc */
+void cgraphunit_cc_finalize (void);
+int tp_first_run_node_cmp (const void *pa, const void *pb);
+
+/* In symtab-thunks.cc */
+void symtab_thunks_cc_finalize (void);
+
+/* Initialize datastructures so DECL is a function in lowered gimple form.
+ IN_SSA is true if the gimple is in SSA. */
+basic_block init_lowered_empty_function (tree, bool, profile_count);
+
+tree thunk_adjust (gimple_stmt_iterator *, tree, bool, HOST_WIDE_INT, tree,
+ HOST_WIDE_INT);
+/* In cgraphclones.cc */
+
+tree clone_function_name_numbered (const char *name, const char *suffix);
+tree clone_function_name_numbered (tree decl, const char *suffix);
+tree clone_function_name (const char *name, const char *suffix,
+ unsigned long number);
+tree clone_function_name (tree decl, const char *suffix,
+ unsigned long number);
+tree clone_function_name (tree decl, const char *suffix);
+
+void tree_function_versioning (tree, tree, vec<ipa_replace_map *, va_gc> *,
+ ipa_param_adjustments *,
+ bool, bitmap, basic_block);
+
+void dump_callgraph_transformation (const cgraph_node *original,
+ const cgraph_node *clone,
+ const char *suffix);
+/* In cgraphbuild.cc */
+int compute_call_stmt_bb_frequency (tree, basic_block bb);
+void record_references_in_initializer (tree, bool);
+
+/* In ipa.cc */
+void cgraph_build_static_cdtor (char which, tree body, int priority);
+bool ipa_discover_variable_flags (void);
+
+/* In varpool.cc */
+tree ctor_for_folding (tree);
+
+/* In ipa-inline-analysis.cc */
+void initialize_inline_failed (struct cgraph_edge *);
+bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining);
+
+/* Return true when the symbol is real symbol, i.e. it is not inline clone
+ or abstract function kept for debug info purposes only. */
+inline bool
+symtab_node::real_symbol_p (void)
+{
+ cgraph_node *cnode;
+
+ if (DECL_ABSTRACT_P (decl))
+ return false;
+ if (transparent_alias && definition)
+ return false;
+ if (!is_a <cgraph_node *> (this))
+ return true;
+ cnode = dyn_cast <cgraph_node *> (this);
+ if (cnode->inlined_to)
+ return false;
+ return true;
+}
+
+/* Return true if DECL should have entry in symbol table if used.
+ Those are functions and static & external variables. */
+
+static inline bool
+decl_in_symtab_p (const_tree decl)
+{
+ return (TREE_CODE (decl) == FUNCTION_DECL
+ || (TREE_CODE (decl) == VAR_DECL
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))));
+}
+
+inline bool
+symtab_node::in_same_comdat_group_p (symtab_node *target)
+{
+ symtab_node *source = this;
+
+ if (cgraph_node *cn = dyn_cast <cgraph_node *> (target))
+ {
+ if (cn->inlined_to)
+ source = cn->inlined_to;
+ }
+ if (cgraph_node *cn = dyn_cast <cgraph_node *> (target))
+ {
+ if (cn->inlined_to)
+ target = cn->inlined_to;
+ }
+
+ return source->get_comdat_group () == target->get_comdat_group ();
+}
+
+/* Return node that alias is aliasing. */
+
+inline symtab_node *
+symtab_node::get_alias_target (void)
+{
+ ipa_ref *ref = NULL;
+ iterate_reference (0, ref);
+ gcc_checking_assert (ref->use == IPA_REF_ALIAS);
+ return ref->referred;
+}
+
+/* Return the DECL (or identifier) that alias is aliasing. Unlike the above,
+ this works whether or not the alias has been analyzed already. */
+
+inline tree
+symtab_node::get_alias_target_tree ()
+{
+ if (alias_target)
+ return alias_target;
+ return get_alias_target ()->decl;
+}
+
+/* Return next reachable static symbol with initializer after the node. */
+
+inline symtab_node *
+symtab_node::next_defined_symbol (void)
+{
+ symtab_node *node1 = next;
+
+ for (; node1; node1 = node1->next)
+ if (node1->definition)
+ return node1;
+
+ return NULL;
+}
+
+/* Iterates I-th reference in the list, REF is also set. */
+
+inline ipa_ref *
+symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
+{
+ ref_list.references.iterate (i, &ref);
+
+ return ref;
+}
+
+/* Iterates I-th referring item in the list, REF is also set. */
+
+inline ipa_ref *
+symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
+{
+ ref_list.referring.iterate (i, &ref);
+
+ return ref;
+}
+
+/* Iterates I-th referring alias item in the list, REF is also set. */
+
+inline ipa_ref *
+symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
+{
+ ref_list.referring.iterate (i, &ref);
+
+ if (ref && ref->use != IPA_REF_ALIAS)
+ return NULL;
+
+ return ref;
+}
+
+/* Return true if list contains an alias. */
+
+inline bool
+symtab_node::has_aliases_p (void)
+{
+ ipa_ref *ref = NULL;
+
+ return (iterate_direct_aliases (0, ref) != NULL);
+}
+
+/* Return true when RESOLUTION indicate that linker will use
+ the symbol from non-LTO object files. */
+
+inline bool
+resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
+{
+ return (resolution == LDPR_PREVAILING_DEF
+ || resolution == LDPR_PREEMPTED_REG
+ || resolution == LDPR_RESOLVED_EXEC
+ || resolution == LDPR_RESOLVED_DYN);
+}
+
+/* Return true when symtab_node is known to be used from other (non-LTO)
+ object file. Known only when doing LTO via linker plugin. */
+
+inline bool
+symtab_node::used_from_object_file_p (void)
+{
+ if (!TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+ return false;
+ if (resolution_used_from_other_file_p (resolution))
+ return true;
+ return false;
+}
+
+/* Return varpool node for given symbol and check it is a function. */
+
+inline varpool_node *
+varpool_node::get (const_tree decl)
+{
+ gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
+ return dyn_cast<varpool_node *> (symtab_node::get (decl));
+}
+
+/* Register a symbol NODE. */
+
+inline void
+symbol_table::register_symbol (symtab_node *node)
+{
+ node->next = nodes;
+ node->previous = NULL;
+
+ if (nodes)
+ nodes->previous = node;
+ nodes = node;
+
+ node->order = order++;
+}
+
+/* Register a top-level asm statement ASM_STR. */
+
+asm_node *
+symbol_table::finalize_toplevel_asm (tree asm_str)
+{
+ asm_node *node;
+
+ node = ggc_cleared_alloc<asm_node> ();
+ node->asm_str = asm_str;
+ node->order = order++;
+ node->next = NULL;
+
+ if (asmnodes == NULL)
+ asmnodes = node;
+ else
+ asm_last_node->next = node;
+
+ asm_last_node = node;
+ return node;
+}
+
+/* Unregister a symbol NODE. */
+inline void
+symbol_table::unregister (symtab_node *node)
+{
+ if (node->previous)
+ node->previous->next = node->next;
+ else
+ nodes = node->next;
+
+ if (node->next)
+ node->next->previous = node->previous;
+
+ node->next = NULL;
+ node->previous = NULL;
+}
+
+/* Release a callgraph NODE with UID and put in to the list of free nodes. */
+
+inline void
+symbol_table::release_symbol (cgraph_node *node)
+{
+ cgraph_count--;
+ if (node->m_summary_id != -1)
+ cgraph_released_summary_ids.safe_push (node->m_summary_id);
+ ggc_free (node);
+}
+
+/* Return first static symbol with definition. */
+inline symtab_node *
+symbol_table::first_symbol (void)
+{
+ return nodes;
+}
+
+/* Walk all symbols. */
+#define FOR_EACH_SYMBOL(node) \
+ for ((node) = symtab->first_symbol (); (node); (node) = (node)->next)
+
+/* Return first static symbol with definition. */
+inline symtab_node *
+symbol_table::first_defined_symbol (void)
+{
+ symtab_node *node;
+
+ for (node = nodes; node; node = node->next)
+ if (node->definition)
+ return node;
+
+ return NULL;
+}
+
+/* Walk all symbols with definitions in current unit. */
+#define FOR_EACH_DEFINED_SYMBOL(node) \
+ for ((node) = symtab->first_defined_symbol (); (node); \
+ (node) = node->next_defined_symbol ())
+
+/* Return first variable. */
+inline varpool_node *
+symbol_table::first_variable (void)
+{
+ symtab_node *node;
+ for (node = nodes; node; node = node->next)
+ if (varpool_node *vnode = dyn_cast <varpool_node *> (node))
+ return vnode;
+ return NULL;
+}
+
+/* Return next variable after NODE. */
+inline varpool_node *
+symbol_table::next_variable (varpool_node *node)
+{
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
+ if (varpool_node *vnode1 = dyn_cast <varpool_node *> (node1))
+ return vnode1;
+ return NULL;
+}
+/* Walk all variables. */
+#define FOR_EACH_VARIABLE(node) \
+ for ((node) = symtab->first_variable (); \
+ (node); \
+ (node) = symtab->next_variable ((node)))
+
+/* Return first static variable with initializer. */
+inline varpool_node *
+symbol_table::first_static_initializer (void)
+{
+ symtab_node *node;
+ for (node = nodes; node; node = node->next)
+ {
+ varpool_node *vnode = dyn_cast <varpool_node *> (node);
+ if (vnode && DECL_INITIAL (node->decl))
+ return vnode;
+ }
+ return NULL;
+}
+
+/* Return next static variable with initializer after NODE. */
+inline varpool_node *
+symbol_table::next_static_initializer (varpool_node *node)
+{
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
+ {
+ varpool_node *vnode1 = dyn_cast <varpool_node *> (node1);
+ if (vnode1 && DECL_INITIAL (node1->decl))
+ return vnode1;
+ }
+ return NULL;
+}
+
+/* Walk all static variables with initializer set. */
+#define FOR_EACH_STATIC_INITIALIZER(node) \
+ for ((node) = symtab->first_static_initializer (); (node); \
+ (node) = symtab->next_static_initializer (node))
+
+/* Return first static variable with definition. */
+inline varpool_node *
+symbol_table::first_defined_variable (void)
+{
+ symtab_node *node;
+ for (node = nodes; node; node = node->next)
+ {
+ varpool_node *vnode = dyn_cast <varpool_node *> (node);
+ if (vnode && vnode->definition)
+ return vnode;
+ }
+ return NULL;
+}
+
+/* Return next static variable with definition after NODE. */
+inline varpool_node *
+symbol_table::next_defined_variable (varpool_node *node)
+{
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
+ {
+ varpool_node *vnode1 = dyn_cast <varpool_node *> (node1);
+ if (vnode1 && vnode1->definition)
+ return vnode1;
+ }
+ return NULL;
+}
+/* Walk all variables with definitions in current unit. */
+#define FOR_EACH_DEFINED_VARIABLE(node) \
+ for ((node) = symtab->first_defined_variable (); (node); \
+ (node) = symtab->next_defined_variable (node))
+
+/* Return first function with body defined. */
+inline cgraph_node *
+symbol_table::first_defined_function (void)
+{
+ symtab_node *node;
+ for (node = nodes; node; node = node->next)
+ {
+ cgraph_node *cn = dyn_cast <cgraph_node *> (node);
+ if (cn && cn->definition)
+ return cn;
+ }
+ return NULL;
+}
+
+/* Return next function with body defined after NODE. */
+inline cgraph_node *
+symbol_table::next_defined_function (cgraph_node *node)
+{
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
+ {
+ cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1);
+ if (cn1 && cn1->definition)
+ return cn1;
+ }
+ return NULL;
+}
+
+/* Walk all functions with body defined. */
+#define FOR_EACH_DEFINED_FUNCTION(node) \
+ for ((node) = symtab->first_defined_function (); (node); \
+ (node) = symtab->next_defined_function ((node)))
+
+/* Return first function. */
+inline cgraph_node *
+symbol_table::first_function (void)
+{
+ symtab_node *node;
+ for (node = nodes; node; node = node->next)
+ if (cgraph_node *cn = dyn_cast <cgraph_node *> (node))
+ return cn;
+ return NULL;
+}
+
+/* Return next function. */
+inline cgraph_node *
+symbol_table::next_function (cgraph_node *node)
+{
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
+ if (cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1))
+ return cn1;
+ return NULL;
+}
+
+/* Return first function with body defined. */
+inline cgraph_node *
+symbol_table::first_function_with_gimple_body (void)
+{
+ symtab_node *node;
+ for (node = nodes; node; node = node->next)
+ {
+ cgraph_node *cn = dyn_cast <cgraph_node *> (node);
+ if (cn && cn->has_gimple_body_p ())
+ return cn;
+ }
+ return NULL;
+}
+
+/* Return next reachable static variable with initializer after NODE. */
+inline cgraph_node *
+symbol_table::next_function_with_gimple_body (cgraph_node *node)
+{
+ symtab_node *node1 = node->next;
+ for (; node1; node1 = node1->next)
+ {
+ cgraph_node *cn1 = dyn_cast <cgraph_node *> (node1);
+ if (cn1 && cn1->has_gimple_body_p ())
+ return cn1;
+ }
+ return NULL;
+}
+
+/* Walk all functions. */
+#define FOR_EACH_FUNCTION(node) \
+ for ((node) = symtab->first_function (); (node); \
+ (node) = symtab->next_function ((node)))
+
+/* Return true when callgraph node is a function with Gimple body defined
+ in current unit. Functions can also be define externally or they
+ can be thunks with no Gimple representation.
+
+ Note that at WPA stage, the function body may not be present in memory. */
+
+inline bool
+cgraph_node::has_gimple_body_p (void)
+{
+ return definition && !thunk && !alias;
+}
+
+/* Walk all functions with body defined. */
+#define FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) \
+ for ((node) = symtab->first_function_with_gimple_body (); (node); \
+ (node) = symtab->next_function_with_gimple_body (node))
+
+/* Uniquize all constants that appear in memory.
+ Each constant in memory thus far output is recorded
+ in `const_desc_table'. */
+
+struct GTY((for_user)) constant_descriptor_tree {
+ /* A MEM for the constant. */
+ rtx rtl;
+
+ /* The value of the constant. */
+ tree value;
+
+ /* Hash of value. Computing the hash from value each time
+ hashfn is called can't work properly, as that means recursive
+ use of the hash table during hash table expansion. */
+ hashval_t hash;
+};
+
+/* Return true when function is only called directly or it has alias.
+ i.e. it is not externally visible, address was not taken and
+ it is not used in any other non-standard way. */
+
+inline bool
+cgraph_node::only_called_directly_or_aliased_p (void)
+{
+ gcc_assert (!inlined_to);
+ return (!force_output && !address_taken
+ && !ifunc_resolver
+ && !used_from_other_partition
+ && !DECL_VIRTUAL_P (decl)
+ && !DECL_STATIC_CONSTRUCTOR (decl)
+ && !DECL_STATIC_DESTRUCTOR (decl)
+ && !used_from_object_file_p ()
+ && !externally_visible);
+}
+
+/* Return true when function can be removed from callgraph
+ if all direct calls are eliminated. */
+
+inline bool
+cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
+{
+ gcc_checking_assert (!inlined_to);
+ /* Extern inlines can always go, we will use the external definition. */
+ if (DECL_EXTERNAL (decl))
+ return true;
+ /* When function is needed, we cannot remove it. */
+ if (force_output || used_from_other_partition)
+ return false;
+ if (DECL_STATIC_CONSTRUCTOR (decl)
+ || DECL_STATIC_DESTRUCTOR (decl))
+ return false;
+ /* Only COMDAT functions can be removed if externally visible. */
+ if (externally_visible
+ && ((!DECL_COMDAT (decl) || ifunc_resolver)
+ || forced_by_abi
+ || used_from_object_file_p ()))
+ return false;
+ return true;
+}
+
+/* Verify cgraph, if consistency checking is enabled. */
+
+inline void
+cgraph_node::checking_verify_cgraph_nodes (void)
+{
+ if (flag_checking)
+ cgraph_node::verify_cgraph_nodes ();
+}
+
+/* Return true when variable can be removed from variable pool
+ if all direct calls are eliminated. */
+
+inline bool
+varpool_node::can_remove_if_no_refs_p (void)
+{
+ if (DECL_EXTERNAL (decl))
+ return true;
+ return (!force_output && !used_from_other_partition
+ && ((DECL_COMDAT (decl)
+ && !forced_by_abi
+ && !used_from_object_file_p ())
+ || !externally_visible
+ || DECL_HAS_VALUE_EXPR_P (decl)));
+}
+
+/* Return true when all references to variable must be visible in ipa_ref_list.
+ i.e. if the variable is not externally visible or not used in some magic
+ way (asm statement or such).
+ The magic uses are all summarized in force_output flag. */
+
+inline bool
+varpool_node::all_refs_explicit_p ()
+{
+ return (definition
+ && !externally_visible
+ && !used_from_other_partition
+ && !force_output);
+}
+
+struct tree_descriptor_hasher : ggc_ptr_hash<constant_descriptor_tree>
+{
+ static hashval_t hash (constant_descriptor_tree *);
+ static bool equal (constant_descriptor_tree *, constant_descriptor_tree *);
+};
+
+/* Constant pool accessor function. */
+hash_table<tree_descriptor_hasher> *constant_pool_htab (void);
+
+/* Return node that alias is aliasing. */
+
+inline cgraph_node *
+cgraph_node::get_alias_target (void)
+{
+ return dyn_cast <cgraph_node *> (symtab_node::get_alias_target ());
+}
+
+/* Return node that alias is aliasing. */
+
+inline varpool_node *
+varpool_node::get_alias_target (void)
+{
+ return dyn_cast <varpool_node *> (symtab_node::get_alias_target ());
+}
+
+/* Walk the alias chain to return the symbol NODE is alias of.
+ If NODE is not an alias, return NODE.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+
+inline symtab_node *
+symtab_node::ultimate_alias_target (enum availability *availability,
+ symtab_node *ref)
+{
+ if (!alias)
+ {
+ if (availability)
+ *availability = get_availability (ref);
+ return this;
+ }
+
+ return ultimate_alias_target_1 (availability, ref);
+}
+
+/* Given function symbol, walk the alias chain to return the function node
+ is alias of. Do not walk through thunks.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+
+inline cgraph_node *
+cgraph_node::ultimate_alias_target (enum availability *availability,
+ symtab_node *ref)
+{
+ cgraph_node *n = dyn_cast <cgraph_node *>
+ (symtab_node::ultimate_alias_target (availability, ref));
+ if (!n && availability)
+ *availability = AVAIL_NOT_AVAILABLE;
+ return n;
+}
+
+/* For given variable pool node, walk the alias chain to return the function
+ the variable is alias of. Do not walk through thunks.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain.
+ When REF is non-NULL, assume that reference happens in symbol REF
+ when determining the availability. */
+
+inline varpool_node *
+varpool_node::ultimate_alias_target (availability *availability,
+ symtab_node *ref)
+{
+ varpool_node *n = dyn_cast <varpool_node *>
+ (symtab_node::ultimate_alias_target (availability, ref));
+
+ if (!n && availability)
+ *availability = AVAIL_NOT_AVAILABLE;
+ return n;
+}
+
+/* Set callee N of call graph edge and add it to the corresponding set of
+ callers. */
+
+inline void
+cgraph_edge::set_callee (cgraph_node *n)
+{
+ prev_caller = NULL;
+ if (n->callers)
+ n->callers->prev_caller = this;
+ next_caller = n->callers;
+ n->callers = this;
+ callee = n;
+}
+
+/* Return true when the edge represents a direct recursion. */
+
+inline bool
+cgraph_edge::recursive_p (void)
+{
+ cgraph_node *c = callee->ultimate_alias_target ();
+ if (caller->inlined_to)
+ return caller->inlined_to->decl == c->decl;
+ else
+ return caller->decl == c->decl;
+}
+
+/* Remove the edge from the list of the callers of the callee. */
+
+inline void
+cgraph_edge::remove_callee (void)
+{
+ gcc_assert (!indirect_unknown_callee);
+ if (prev_caller)
+ prev_caller->next_caller = next_caller;
+ if (next_caller)
+ next_caller->prev_caller = prev_caller;
+ if (!prev_caller)
+ callee->callers = next_caller;
+}
+
+/* Return true if call must bind to current definition. */
+
+inline bool
+cgraph_edge::binds_to_current_def_p ()
+{
+ if (callee)
+ return callee->binds_to_current_def_p (caller);
+ else
+ return false;
+}
+
+/* Expected frequency of executions within the function.
+ When set to CGRAPH_FREQ_BASE, the edge is expected to be called once
+ per function call. The range is 0 to CGRAPH_FREQ_MAX. */
+
+inline int
+cgraph_edge::frequency ()
+{
+ return count.to_cgraph_frequency (caller->inlined_to
+ ? caller->inlined_to->count
+ : caller->count);
+}
+
+
+/* Return true if the TM_CLONE bit is set for a given FNDECL. */
+static inline bool
+decl_is_tm_clone (const_tree fndecl)
+{
+ cgraph_node *n = cgraph_node::get (fndecl);
+ if (n)
+ return n->tm_clone;
+ return false;
+}
+
+/* Likewise indicate that a node is needed, i.e. reachable via some
+ external means. */
+
+inline void
+cgraph_node::mark_force_output (void)
+{
+ force_output = 1;
+ gcc_checking_assert (!inlined_to);
+}
+
+/* Return true if function should be optimized for size. */
+
+inline enum optimize_size_level
+cgraph_node::optimize_for_size_p (void)
+{
+ if (opt_for_fn (decl, optimize_size))
+ return OPTIMIZE_SIZE_MAX;
+ if (count == profile_count::zero ())
+ return OPTIMIZE_SIZE_MAX;
+ if (frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
+ return OPTIMIZE_SIZE_BALANCED;
+ else
+ return OPTIMIZE_SIZE_NO;
+}
+
+/* Return symtab_node for NODE or create one if it is not present
+ in symtab. */
+
+inline symtab_node *
+symtab_node::get_create (tree node)
+{
+ if (TREE_CODE (node) == VAR_DECL)
+ return varpool_node::get_create (node);
+ else
+ return cgraph_node::get_create (node);
+}
+
+/* Return availability of NODE when referenced from REF. */
+
+inline enum availability
+symtab_node::get_availability (symtab_node *ref)
+{
+ if (is_a <cgraph_node *> (this))
+ return dyn_cast <cgraph_node *> (this)->get_availability (ref);
+ else
+ return dyn_cast <varpool_node *> (this)->get_availability (ref);
+}
+
+/* Call callback on symtab node and aliases associated to this node.
+ When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. */
+
+inline bool
+symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ if (include_overwritable
+ || get_availability () > AVAIL_INTERPOSABLE)
+ {
+ if (callback (this, data))
+ return true;
+ }
+ if (has_aliases_p ())
+ return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+ return false;
+}
+
+/* Call callback on function and aliases associated to the function.
+ When INCLUDE_OVERWRITABLE is false, overwritable symbols are
+ skipped. */
+
+inline bool
+cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ if (include_overwritable
+ || get_availability () > AVAIL_INTERPOSABLE)
+ {
+ if (callback (this, data))
+ return true;
+ }
+ if (has_aliases_p ())
+ return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+ return false;
+}
+
+/* Call callback on varpool symbol and aliases associated to varpool symbol.
+ When INCLUDE_OVERWRITABLE is false, overwritable symbols are
+ skipped. */
+
+inline bool
+varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ if (include_overwritable
+ || get_availability () > AVAIL_INTERPOSABLE)
+ {
+ if (callback (this, data))
+ return true;
+ }
+ if (has_aliases_p ())
+ return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+ return false;
+}
+
+/* Return true if reference may be used in address compare. */
+
+inline bool
+ipa_ref::address_matters_p ()
+{
+ if (use != IPA_REF_ADDR)
+ return false;
+ /* Addresses taken from virtual tables are never compared. */
+ if (is_a <varpool_node *> (referring)
+ && DECL_VIRTUAL_P (referring->decl))
+ return false;
+ return referred->address_can_be_compared_p ();
+}
+
+/* Build polymorphic call context for indirect call E. */
+
+inline
+ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
+{
+ gcc_checking_assert (e->indirect_info->polymorphic);
+ *this = e->indirect_info->context;
+}
+
+/* Build empty "I know nothing" context. */
+
+inline
+ipa_polymorphic_call_context::ipa_polymorphic_call_context ()
+{
+ clear_speculation ();
+ clear_outer_type ();
+ invalid = false;
+}
+
+/* Make context non-speculative. */
+
+inline void
+ipa_polymorphic_call_context::clear_speculation ()
+{
+ speculative_outer_type = NULL;
+ speculative_offset = 0;
+ speculative_maybe_derived_type = false;
+}
+
+/* Produce context specifying all derived types of OTR_TYPE. If OTR_TYPE is
+ NULL, the context is set to dummy "I know nothing" setting. */
+
+inline void
+ipa_polymorphic_call_context::clear_outer_type (tree otr_type)
+{
+ outer_type = otr_type ? TYPE_MAIN_VARIANT (otr_type) : NULL;
+ offset = 0;
+ maybe_derived_type = true;
+ maybe_in_construction = true;
+ dynamic = true;
+}
+
+/* Adjust all offsets in contexts by OFF bits. */
+
+inline void
+ipa_polymorphic_call_context::offset_by (HOST_WIDE_INT off)
+{
+ if (outer_type)
+ offset += off;
+ if (speculative_outer_type)
+ speculative_offset += off;
+}
+
+/* Return TRUE if context is fully useless. */
+
+inline bool
+ipa_polymorphic_call_context::useless_p () const
+{
+ return (!outer_type && !speculative_outer_type);
+}
+
+/* When using fprintf (or similar), problems can arise with
+ transient generated strings. Many string-generation APIs
+ only support one result being alive at once (e.g. by
+ returning a pointer to a statically-allocated buffer).
+
+ If there is more than one generated string within one
+ fprintf call: the first string gets evicted or overwritten
+ by the second, before fprintf is fully evaluated.
+ See e.g. PR/53136.
+
+ This function provides a workaround for this, by providing
+ a simple way to create copies of these transient strings,
+ without the need to have explicit cleanup:
+
+ fprintf (dumpfile, "string 1: %s string 2:%s\n",
+ xstrdup_for_dump (EXPR_1),
+ xstrdup_for_dump (EXPR_2));
+
+ This is actually a simple wrapper around ggc_strdup, but
+ the name documents the intent. We require that no GC can occur
+ within the fprintf call. */
+
+static inline const char *
+xstrdup_for_dump (const char *transient_str)
+{
+ return ggc_strdup (transient_str);
+}
+
+/* During LTO stream-in this predicate can be used to check whether node
+ in question prevails in the linking to save some memory usage. */
+inline bool
+symtab_node::prevailing_p (void)
+{
+ return definition && ((!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
+ || previous_sharing_asm_name == NULL);
+}
+
+extern GTY(()) symbol_table *saved_symtab;
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* An RAII-style class for use in selftests for temporarily using a different
+ symbol_table, so that such tests can be isolated from each other. */
+
+class symbol_table_test
+{
+ public:
+ /* Constructor. Override "symtab". */
+ symbol_table_test ();
+
+ /* Destructor. Restore the saved_symtab. */
+ ~symbol_table_test ();
+};
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
+
+#endif /* GCC_CGRAPH_H */
diff --git a/support/cpp/gcc/cif-code.def b/support/cpp/gcc/cif-code.def
new file mode 100644
index 000000000..ea604e16c
--- /dev/null
+++ b/support/cpp/gcc/cif-code.def
@@ -0,0 +1,144 @@
+/* This file contains the definitions of the cgraph_inline_failed_t
+ enums used in GCC.
+
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+ Contributed by Doug Kwan <dougkwan@google.com>
+
+This file is part of GCC.
+
+GCC is free software you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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/>. */
+
+/* The format of this file is
+ DEFCIFCODE(code, string).
+
+ Where symbol is the enumeration name without the ``''.
+ The argument STRING is a explain the failure. Except for OK,
+ which is a NULL pointer. */
+
+/* Inlining successful. This must be the first code. */
+DEFCIFCODE(OK, CIF_FINAL_NORMAL, NULL)
+
+/* Inlining failed for an unspecified reason. */
+DEFCIFCODE(UNSPECIFIED, CIF_FINAL_ERROR, "")
+
+/* Function has not be considered for inlining. This is the code for
+ functions that have not been rejected for inlining yet. */
+DEFCIFCODE(FUNCTION_NOT_CONSIDERED, CIF_FINAL_NORMAL,
+ N_("function not considered for inlining"))
+
+/* Caller is compiled with optimizations disabled. */
+DEFCIFCODE(FUNCTION_NOT_OPTIMIZED, CIF_FINAL_ERROR,
+ N_("caller is not optimized"))
+
+/* Inlining failed owing to unavailable function body. */
+DEFCIFCODE(BODY_NOT_AVAILABLE, CIF_FINAL_ERROR,
+ N_("function body not available"))
+
+/* Extern inline function that has been redefined. */
+DEFCIFCODE(REDEFINED_EXTERN_INLINE, CIF_FINAL_ERROR,
+ N_("redefined extern inline functions are not considered for "
+ "inlining"))
+
+/* Function is not inlinable. */
+DEFCIFCODE(FUNCTION_NOT_INLINABLE, CIF_FINAL_ERROR,
+ N_("function not inlinable"))
+
+/* Function is overwritable. */
+DEFCIFCODE(OVERWRITABLE, CIF_FINAL_ERROR,
+ N_("function body can be overwritten at link time"))
+
+/* Function is not an inlining candidate. */
+DEFCIFCODE(FUNCTION_NOT_INLINE_CANDIDATE, CIF_FINAL_NORMAL,
+ N_("function not inline candidate"))
+
+/* Inlining failed because of various limit parameters. */
+DEFCIFCODE(LARGE_FUNCTION_GROWTH_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param large-function-growth limit reached"))
+DEFCIFCODE(LARGE_STACK_FRAME_GROWTH_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param large-stack-frame-growth limit reached"))
+DEFCIFCODE(MAX_INLINE_INSNS_SINGLE_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param max-inline-insns-single limit reached"))
+DEFCIFCODE(MAX_INLINE_INSNS_AUTO_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param max-inline-insns-auto limit reached"))
+DEFCIFCODE(INLINE_UNIT_GROWTH_LIMIT, CIF_FINAL_NORMAL,
+ N_("--param inline-unit-growth limit reached"))
+
+/* Recursive inlining. */
+DEFCIFCODE(RECURSIVE_INLINING, CIF_FINAL_NORMAL,
+ N_("recursive inlining"))
+
+/* Call is unlikely. */
+DEFCIFCODE(UNLIKELY_CALL, CIF_FINAL_NORMAL,
+ N_("call is unlikely and code size would grow"))
+
+/* Call is considered never executed. */
+DEFCIFCODE(NEVER_CALL, CIF_FINAL_NORMAL,
+ N_("call is considered never executed and code size would grow"))
+
+/* Function is not declared as inline. */
+DEFCIFCODE(NOT_DECLARED_INLINED, CIF_FINAL_NORMAL,
+ N_("function not declared inline and code size would grow"))
+
+/* Caller and callee disagree on the arguments. */
+DEFCIFCODE(LTO_MISMATCHED_DECLARATIONS, CIF_FINAL_ERROR,
+ N_("mismatched declarations during linktime optimization"))
+
+/* Caller is variadic thunk. */
+DEFCIFCODE(VARIADIC_THUNK, CIF_FINAL_ERROR,
+ N_("variadic thunk call"))
+
+/* Call was originally indirect. */
+DEFCIFCODE(ORIGINALLY_INDIRECT_CALL, CIF_FINAL_NORMAL,
+ N_("originally indirect function call not considered for inlining"))
+
+/* Ths edge represents an indirect edge with a yet-undetermined callee . */
+DEFCIFCODE(INDIRECT_UNKNOWN_CALL, CIF_FINAL_NORMAL,
+ N_("indirect function call with a yet undetermined callee"))
+
+/* We can't inline different EH personalities together. */
+DEFCIFCODE(EH_PERSONALITY, CIF_FINAL_ERROR,
+ N_("exception handling personality mismatch"))
+
+/* We can't inline if the callee can throw non-call exceptions but the
+ caller cannot. */
+DEFCIFCODE(NON_CALL_EXCEPTIONS, CIF_FINAL_ERROR,
+ N_("non-call exception handling mismatch"))
+
+/* We can't inline because of mismatched target specific options. */
+DEFCIFCODE(TARGET_OPTION_MISMATCH, CIF_FINAL_ERROR,
+ N_("target specific option mismatch"))
+
+/* We can't inline because of mismatched optimization levels. */
+DEFCIFCODE(OPTIMIZATION_MISMATCH, CIF_FINAL_ERROR,
+ N_("optimization level attribute mismatch"))
+
+/* We can't inline because the callee refers to comdat-local symbols. */
+DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_NORMAL,
+ N_("callee refers to comdat-local symbols"))
+
+/* We can't inline because of mismatched caller/callee
+ sanitizer attributes. */
+DEFCIFCODE(SANITIZE_ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
+ N_("sanitizer function attribute mismatch"))
+
+/* We can't inline because the user requests only static functions
+ but the function has external linkage for live patching purpose. */
+DEFCIFCODE(EXTERN_LIVE_ONLY_STATIC, CIF_FINAL_ERROR,
+ N_("function has external linkage when the user requests only"
+ " inlining static for live patching"))
+
+/* We proved that the call is unreachable. */
+DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
+ N_("unreachable"))
diff --git a/support/cpp/gcc/color-macros.h b/support/cpp/gcc/color-macros.h
new file mode 100644
index 000000000..d144b3466
--- /dev/null
+++ b/support/cpp/gcc/color-macros.h
@@ -0,0 +1,108 @@
+/* Terminal color manipulation macros.
+ Copyright (C) 2005-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_COLOR_MACROS_H
+#define GCC_COLOR_MACROS_H
+
+/* Select Graphic Rendition (SGR, "\33[...m") strings. */
+/* Also Erase in Line (EL) to Right ("\33[K") by default. */
+/* Why have EL to Right after SGR?
+ -- The behavior of line-wrapping when at the bottom of the
+ terminal screen and at the end of the current line is often
+ such that a new line is introduced, entirely cleared with
+ the current background color which may be different from the
+ default one (see the boolean back_color_erase terminfo(5)
+ capability), thus scrolling the display by one line.
+ The end of this new line will stay in this background color
+ even after reverting to the default background color with
+ "\33[m', unless it is explicitly cleared again with "\33[K"
+ (which is the behavior the user would instinctively expect
+ from the whole thing). There may be some unavoidable
+ background-color flicker at the end of this new line because
+ of this (when timing with the monitor's redraw is just right).
+ -- The behavior of HT (tab, "\t") is usually the same as that of
+ Cursor Forward Tabulation (CHT) with a default parameter
+ of 1 ("\33[I"), i.e., it performs pure movement to the next
+ tab stop, without any clearing of either content or screen
+ attributes (including background color); try
+ printf 'asdfqwerzxcv\rASDF\tZXCV\n'
+ in a bash(1) shell to demonstrate this. This is not what the
+ user would instinctively expect of HT (but is ok for CHT).
+ The instinctive behavior would include clearing the terminal
+ cells that are skipped over by HT with blank cells in the
+ current screen attributes, including background color;
+ the boolean dest_tabs_magic_smso terminfo(5) capability
+ indicates this saner behavior for HT, but only some rare
+ terminals have it (although it also indicates a special
+ glitch with standout mode in the Teleray terminal for which
+ it was initially introduced). The remedy is to add "\33K"
+ after each SGR sequence, be it START (to fix the behavior
+ of any HT after that before another SGR) or END (to fix the
+ behavior of an HT in default background color that would
+ follow a line-wrapping at the bottom of the screen in another
+ background color, and to complement doing it after START).
+ Piping GCC's output through a pager such as less(1) avoids
+ any HT problems since the pager performs tab expansion.
+
+ Generic disadvantages of this remedy are:
+ -- Some very rare terminals might support SGR but not EL (nobody
+ will use "gcc -fdiagnostics-color" on a terminal that does not
+ support SGR in the first place).
+ -- Having these extra control sequences might somewhat complicate
+ the task of any program trying to parse "gcc -fdiagnostics-color"
+ output in order to extract structuring information from it.
+ A specific disadvantage to doing it after SGR START is:
+ -- Even more possible background color flicker (when timing
+ with the monitor's redraw is just right), even when not at the
+ bottom of the screen.
+ There are no additional disadvantages specific to doing it after
+ SGR END.
+
+ It would be impractical for GCC to become a full-fledged
+ terminal program linked against ncurses or the like, so it will
+ not detect terminfo(5) capabilities. */
+
+#define COLOR_SEPARATOR ";"
+#define COLOR_NONE "00"
+#define COLOR_BOLD "01"
+#define COLOR_UNDERSCORE "04"
+#define COLOR_BLINK "05"
+#define COLOR_REVERSE "07"
+#define COLOR_FG_BLACK "30"
+#define COLOR_FG_RED "31"
+#define COLOR_FG_GREEN "32"
+#define COLOR_FG_YELLOW "33"
+#define COLOR_FG_BLUE "34"
+#define COLOR_FG_MAGENTA "35"
+#define COLOR_FG_CYAN "36"
+#define COLOR_FG_WHITE "37"
+#define COLOR_BG_BLACK "40"
+#define COLOR_BG_RED "41"
+#define COLOR_BG_GREEN "42"
+#define COLOR_BG_YELLOW "43"
+#define COLOR_BG_BLUE "44"
+#define COLOR_BG_MAGENTA "45"
+#define COLOR_BG_CYAN "46"
+#define COLOR_BG_WHITE "47"
+#define SGR_START "\33["
+#define SGR_END "m\33[K"
+#define SGR_SEQ(str) SGR_START str SGR_END
+#define SGR_RESET SGR_SEQ("")
+
+#endif /* GCC_COLOR_MACROS_H */
diff --git a/support/cpp/gcc/common.md b/support/cpp/gcc/common.md
new file mode 100644
index 000000000..c73a333dd
--- /dev/null
+++ b/support/cpp/gcc/common.md
@@ -0,0 +1,95 @@
+;; Common GCC machine description file, shared by all targets.
+;; Copyright (C) 2014-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/>. */
+
+(define_register_constraint "r" "GENERAL_REGS"
+ "Matches any general register.")
+
+(define_memory_constraint "TARGET_MEM_CONSTRAINT"
+ "Matches any valid memory."
+ (and (match_code "mem")
+ (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op))")))
+
+(define_memory_constraint "o"
+ "Matches an offsettable memory reference."
+ (and (match_code "mem")
+ (match_test "offsettable_nonstrict_memref_p (op)")))
+
+;; "V" matches TARGET_MEM_CONSTRAINTs that are rejected by "o".
+;; This means that it is not a memory constraint in the usual sense,
+;; since reloading the address into a base register would make the
+;; address offsettable.
+(define_constraint "V"
+ "Matches a non-offsettable memory reference."
+ (and (match_code "mem")
+ (match_test "memory_address_addr_space_p (GET_MODE (op), XEXP (op, 0),
+ MEM_ADDR_SPACE (op))")
+ (not (match_test "offsettable_nonstrict_memref_p (op)"))))
+
+;; Like "V", this is not a memory constraint, since reloading the address
+;; into a base register would cause it not to match.
+(define_constraint "<"
+ "Matches a pre-dec or post-dec operand."
+ (and (match_code "mem")
+ (ior (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC")
+ (match_test "GET_CODE (XEXP (op, 0)) == POST_DEC"))))
+
+;; See the comment for "<".
+(define_constraint ">"
+ "Matches a pre-inc or post-inc operand."
+ (and (match_code "mem")
+ (ior (match_test "GET_CODE (XEXP (op, 0)) == PRE_INC")
+ (match_test "GET_CODE (XEXP (op, 0)) == POST_INC"))))
+
+(define_address_constraint "p"
+ "Matches a general address."
+ (match_test "address_operand (op, VOIDmode)"))
+
+(define_constraint "i"
+ "Matches a general integer constant."
+ (and (match_test "CONSTANT_P (op)")
+ (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+
+(define_constraint "s"
+ "Matches a symbolic integer constant."
+ (and (match_test "CONSTANT_P (op)")
+ (match_test "!CONST_SCALAR_INT_P (op)")
+ (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+
+(define_constraint "n"
+ "Matches a non-symbolic integer constant."
+ (and (match_test "CONST_SCALAR_INT_P (op)")
+ (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+
+(define_constraint "E"
+ "Matches a floating-point constant."
+ (ior (match_test "CONST_DOUBLE_AS_FLOAT_P (op)")
+ (match_test "GET_CODE (op) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT")))
+
+;; There is no longer a distinction between "E" and "F".
+(define_constraint "F"
+ "Matches a floating-point constant."
+ (ior (match_test "CONST_DOUBLE_AS_FLOAT_P (op)")
+ (match_test "GET_CODE (op) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT")))
+
+(define_constraint "X"
+ "Matches anything."
+ (match_test "true"))
diff --git a/support/cpp/gcc/common.opt b/support/cpp/gcc/common.opt
new file mode 100644
index 000000000..2fe4e3511
--- /dev/null
+++ b/support/cpp/gcc/common.opt
@@ -0,0 +1,3617 @@
+; Options for the language- and target-independent parts of the compiler.
+
+; Copyright (C) 2003-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/>.
+
+; See the GCC internals manual (options.texi) for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+Variable
+int target_flags
+
+Variable
+int optimize
+
+Variable
+int optimize_size
+
+Variable
+int optimize_debug
+
+; Not used directly to control optimizations, only to save -Ofast
+; setting for "optimize" attributes.
+Variable
+int optimize_fast
+
+; True if this is the lto front end. This is used to disable gimple
+; generation and lowering passes that are normally run on the output
+; of a front end. These passes must be bypassed for lto since they
+; have already been done before the gimple was written.
+Variable
+bool in_lto_p = false
+
+; This variable is set to non-0 only by LTO front-end. 1 indicates that
+; the output produced will be used for incremental linking (thus weak symbols
+; can still be bound) and 2 indicates that the IL is going to be linked and
+; and output to LTO object file.
+Variable
+enum incremental_link flag_incremental_link = INCREMENTAL_LINK_NONE
+
+; 0 means straightforward implementation of complex divide acceptable.
+; 1 means wide ranges of inputs must work for complex divide.
+; 2 means C99-like requirements for complex multiply and divide.
+Variable
+int flag_complex_method = 1
+
+Variable
+int flag_default_complex_method = 1
+
+; Language specific warning pass for unused results.
+Variable
+bool flag_warn_unused_result = false
+
+; Nonzero if we should write GIMPLE bytecode for link-time optimization.
+Variable
+int flag_generate_lto
+
+; Nonzero if we should write GIMPLE bytecode for offload compilation.
+Variable
+int flag_generate_offload = 0
+
+; Nonzero means we should be saving declaration info into a .X file.
+Variable
+int flag_gen_aux_info = 0
+
+; Nonzero if we are compiling code for a shared library, zero for
+; executable.
+Variable
+int flag_shlib
+
+; These three are really VEC(char_p,heap) *.
+
+Variable
+void *flag_instrument_functions_exclude_functions
+
+Variable
+void *flag_instrument_functions_exclude_files
+
+Variable
+void *flag_ignored_attributes
+
+; Generic structs (e.g. templates not explicitly specialized)
+; may not have a compilation unit associated with them, and so
+; may need to be treated differently from ordinary structs.
+;
+; Structs only handled by reference (indirectly), will also usually
+; not need as much debugging information.
+
+Variable
+enum debug_struct_file debug_struct_ordinary[DINFO_USAGE_NUM_ENUMS] = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }
+
+Variable
+enum debug_struct_file debug_struct_generic[DINFO_USAGE_NUM_ENUMS] = { DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY, DINFO_STRUCT_FILE_ANY }
+
+; True if we should exit after parsing options.
+Variable
+bool exit_after_options
+
+; Type(s) of debugging information we are producing (if any). See
+; flag-types.h for the definitions of the different possible types of
+; debugging information.
+Variable
+uint32_t write_symbols = NO_DEBUG
+
+; Level of debugging information we are producing. See flag-types.h
+; for the definitions of the different possible levels.
+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
+enum ctf_debug_info_levels ctf_debug_info_level = CTFINFO_LEVEL_NONE
+
+; Original value of maximum field alignment in bytes, specified via
+; -fpack-struct=<value>.
+Variable
+unsigned int initial_max_fld_align = TARGET_DEFAULT_PACK_STRUCT
+
+; Type of stack check.
+Variable
+enum stack_check_type flag_stack_check = NO_STACK_CHECK
+
+; True if stack usage information needs to be computed.
+Variable
+bool flag_stack_usage_info = false
+
+; -dA causes debug commentary information to be produced in
+; the generated assembly code (to make it more readable). This option
+; is generally only of use to those who actually need to read the
+; generated assembly code (perhaps while debugging the compiler itself).
+; Currently, this switch is only used by dwarf2out.cc; however, it is intended
+; to be a catchall for printing debug information in the assembler file.
+Variable
+int flag_debug_asm
+
+; Balance between GNAT encodings and standard DWARF to emit.
+Variable
+enum dwarf_gnat_encodings gnat_encodings = DWARF_GNAT_ENCODINGS_DEFAULT
+
+; -dP causes the rtl to be emitted as a comment in assembly.
+Variable
+int flag_dump_rtl_in_asm
+
+; Whether -da was passed (used only in handle_common_deferred_options).
+Variable
+bool flag_dump_all_passed
+
+; Other flags saying which kinds of debugging dump have been requested.
+
+Variable
+int rtl_dump_and_exit
+
+Variable
+int flag_print_asm_name
+
+; Name of top-level original source file (what was input to cpp).
+; This comes from the #-command at the beginning of the actual input.
+; If there isn't any there, then this is the cc1 input file name.
+Variable
+const char *main_input_filename
+
+; Pointer to base name in main_input_filename, with directories and a
+; single final extension removed, and the length of this base
+; name.
+
+Variable
+const char *main_input_basename
+
+Variable
+int main_input_baselength
+
+; The base name used for auxiliary output files.
+; dump_base_name minus dump_base_ext.
+
+Variable
+const char *aux_base_name
+
+; Which options have been printed by --help.
+Variable
+char *help_printed
+
+; Which enums have been printed by --help. 0 = not printed, no
+; relevant options seen, 1 = relevant option seen, not yet printed, 2
+; = printed.
+Variable
+char *help_enum_printed
+
+; The number of columns for --help output.
+Variable
+unsigned int help_columns
+
+; Whether this options structure has been through finish_options
+Variable
+bool flag_opts_finished
+
+; What the sanitizer should instrument
+Variable
+unsigned int flag_sanitize
+
+; What sanitizers should recover from errors
+Variable
+unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS | SANITIZE_KERNEL_HWADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN)
+
+; Flag whether a prefix has been added to dump_base_name
+Variable
+bool dump_base_name_prefixed = false
+
+; What subset of registers should be zeroed on function return
+Variable
+unsigned int flag_zero_call_used_regs
+
+###
+Driver
+
+-assemble
+Driver Alias(S)
+
+-compile
+Driver Alias(c)
+
+-completion=
+Common Driver Joined Undocumented
+Provide bash completion for options starting with provided string.
+
+-coverage
+Driver Alias(coverage)
+
+-debug
+Common Alias(g)
+
+-dump
+Common Separate Alias(d)
+
+-dump=
+Common Joined Alias(d)
+
+-dumpbase
+Driver Common Separate Alias(dumpbase)
+
+-dumpbase-ext
+Driver Common Separate Alias(dumpbase-ext)
+
+-dumpdir
+Driver Common Separate Alias(dumpdir)
+
+-entry
+Driver Separate Alias(e)
+
+-entry=
+Driver Joined Alias(e)
+
+-extra-warnings
+Common Warning Alias(Wextra)
+
+-for-assembler
+Driver Separate Alias(Xassembler)
+
+-for-assembler=
+Driver JoinedOrMissing Alias(Xassembler)
+
+-for-linker
+Driver Separate Alias(Xlinker)
+
+-for-linker=
+Driver JoinedOrMissing Alias(Xlinker)
+
+-force-link
+Driver Separate Alias(u)
+
+-force-link=
+Driver Joined Alias(u)
+
+-help
+Common Driver Var(help_flag)
+Display this information.
+
+-help=
+Common Driver Joined
+--help=<class> Display descriptions of a specific class of options. <class> is one or more of optimizers, target, warnings, undocumented, params.
+
+-language
+Driver Separate Alias(x)
+
+-language=
+Driver Joined Alias(x)
+
+-library-directory
+Driver Separate Alias(L)
+
+-library-directory=
+Driver Joined Alias(L)
+
+-no-canonical-prefixes
+Driver Alias(no-canonical-prefixes)
+
+-no-standard-libraries
+Driver Alias(nostdlib)
+
+-no-sysroot-suffix
+Driver Var(no_sysroot_suffix)
+
+-no-warnings
+Common Alias(w)
+
+-optimize
+Common Alias(O)
+
+-output
+Common Driver Separate Alias(o) MissingArgError(missing filename after %qs)
+
+-output=
+Common Driver Joined Alias(o) MissingArgError(missing filename after %qs)
+
+-pass-exit-codes
+Driver Alias(pass-exit-codes)
+
+-pedantic
+Common Alias(Wpedantic)
+
+-pedantic-errors
+Common Alias(pedantic-errors)
+
+-pie
+Driver Alias(pie)
+
+-static-pie
+Driver Alias(static-pie)
+
+-pipe
+Driver Alias(pipe)
+
+-prefix
+Driver Separate Alias(B)
+
+-prefix=
+Driver JoinedOrMissing Alias(B)
+
+-preprocess
+Driver Alias(E)
+
+-print-file-name
+Driver Separate Alias(print-file-name=)
+
+-print-file-name=
+Driver JoinedOrMissing Alias(print-file-name=)
+
+-print-libgcc-file-name
+Driver Alias(print-libgcc-file-name)
+
+-print-multi-directory
+Driver Alias(print-multi-directory)
+
+-print-multi-lib
+Driver Alias(print-multi-lib)
+
+-print-multi-os-directory
+Driver Alias(print-multi-os-directory)
+
+-print-multiarch
+Driver Alias(print-multiarch)
+
+-print-prog-name
+Driver Separate Alias(print-prog-name=)
+
+-print-prog-name=
+Driver JoinedOrMissing Alias(print-prog-name=)
+
+-print-search-dirs
+Driver Alias(print-search-dirs)
+
+-print-sysroot
+Driver Alias(print-sysroot)
+
+-print-sysroot-headers-suffix
+Driver Alias(print-sysroot-headers-suffix)
+
+-profile
+Common Alias(p)
+
+-save-temps
+Driver Alias(save-temps)
+
+-shared
+Driver Alias(shared)
+
+-specs
+Driver Separate Alias(specs=)
+
+-specs=
+Driver Joined Alias(specs=)
+
+-static
+Driver Alias(static)
+
+-symbolic
+Driver Alias(symbolic)
+
+-target-help
+Common Driver
+Display target specific command line options (including assembler and linker options).
+
+-time
+Driver Alias(time)
+
+-verbose
+Driver Alias(v)
+
+;; The driver used to convert options such as --help into forms such
+;; as -fhelp; the following four entries are for compatibility with
+;; any direct uses of those (undocumented) -f forms
+fhelp
+Common Driver Alias(-help)
+
+fhelp=
+Common Driver Joined Alias(-help=)
+
+ftarget-help
+Common Driver Alias(-target-help)
+
+fversion
+Common Driver Alias(-version)
+
+-obj-ext
+Common Driver Separate Alias(-obj-ext=)
+
+-obj-ext=
+Common Driver JoinedOrMissing CPP(obj_ext) Var(var_obj_ext) Init(".o")
+Define object file extension, used for generation of make dependencies
+
+-sysroot
+Driver Separate Alias(-sysroot=)
+
+-sysroot=
+Driver JoinedOrMissing
+
+-version
+Common Driver
+
+B
+Driver Joined Separate
+
+E
+Driver
+
+L
+Driver Joined Separate
+
+N
+Driver
+
+O
+Common JoinedOrMissing Optimization
+-O<number> Set optimization level to <number>.
+
+Os
+Common Optimization
+Optimize for space rather than speed.
+
+Ofast
+Common Optimization
+Optimize for speed disregarding exact standards compliance.
+
+Og
+Common Optimization
+Optimize for debugging experience rather than speed or size.
+
+Oz
+Common Optimization
+Optimize for space aggressively rather than speed.
+
+Q
+Driver
+
+Qn
+Driver Negative(Qy)
+
+Qy
+Driver Negative(Qn)
+
+R
+Driver Joined Separate
+
+S
+Driver
+
+T
+Driver Joined Separate
+
+Tbss
+Driver Separate
+
+Tbss=
+Driver Joined
+
+Tdata
+Driver Separate
+
+Tdata=
+Driver Joined
+
+Ttext
+Driver Separate
+
+Ttext=
+Driver Joined
+
+W
+Common RejectNegative Warning Alias(Wextra)
+This switch is deprecated; use -Wextra instead.
+
+Wa,
+Driver JoinedOrMissing RejectNegative
+
+Wl,
+Driver JoinedOrMissing RejectNegative
+
+Wp,
+Driver JoinedOrMissing RejectNegative
+
+Waggregate-return
+Common Var(warn_aggregate_return) Warning
+Warn about returning structures, unions or arrays.
+
+Waggressive-loop-optimizations
+Common Var(warn_aggressive_loop_optimizations) Init(1) Warning
+Warn if a loop with constant number of iterations triggers undefined behavior.
+
+Warray-bounds
+Common Var(warn_array_bounds) Warning
+Warn if an array is accessed out of bounds.
+
+Warray-bounds=
+Common Joined RejectNegative UInteger Var(warn_array_bounds) Warning IntegerRange(0, 2)
+Warn if an array is accessed out of bounds.
+
+Wuse-after-free
+Common Var(warn_use_after_free) Warning
+Warn for uses of pointers to deallocated storage.
+
+Wuse-after-free=
+Common Joined RejectNegative UInteger Var(warn_use_after_free) Warning IntegerRange(0, 3)
+Warn for uses of pointers to deallocated storage.
+
+Wattributes
+Common Var(warn_attributes) Init(1) Warning
+Warn about inappropriate attribute usage.
+
+Wattributes=
+Common Joined
+Do not warn about specified attributes.
+
+Wattribute-alias
+Common Alias(Wattribute_alias=, 1, 0) Warning
+Warn about type safety and similar errors and mismatches in declarations with alias attributes.
+
+Wattribute-alias=
+Common Joined RejectNegative UInteger Var(warn_attribute_alias) Init(1) Warning IntegerRange(0, 2)
+Warn about type safety and similar errors and mismatches in declarations with alias attributes.
+
+Wcannot-profile
+Common Var(warn_cannot_profile) Init(1) Warning
+Warn when profiling instrumentation was requested, but could not be applied to
+a certain function.
+
+Wcast-align
+Common Var(warn_cast_align) Warning
+Warn about pointer casts which increase alignment.
+
+Wcast-align=strict
+Common Var(warn_cast_align,2) Warning
+Warn about pointer casts which increase alignment.
+
+Wcpp
+Common Var(warn_cpp) Init(1) Warning
+Warn when a #warning directive is encountered.
+
+Wattribute-warning
+Common Var(warn_attribute_warning) Init(1) Warning
+Warn about uses of __attribute__((warning)) declarations.
+
+Wdeprecated
+Common Var(warn_deprecated) Init(1) Warning
+Warn if a deprecated compiler feature, class, method, or field is used.
+
+Wdeprecated-declarations
+Common Var(warn_deprecated_decl) Init(1) Warning
+Warn about uses of __attribute__((deprecated)) declarations.
+
+Wdisabled-optimization
+Common Var(warn_disabled_optimization) Warning
+Warn when an optimization pass is disabled.
+
+Werror
+Common Var(warnings_are_errors)
+Treat all warnings as errors.
+
+Werror=
+Common Joined
+Treat specified warning as error.
+
+Wextra
+Common Var(extra_warnings) Warning
+Print extra (possibly unwanted) warnings.
+
+Wfatal-errors
+Common Var(flag_fatal_errors)
+Exit on the first error occurred.
+
+Wframe-larger-than=
+Common RejectNegative Joined Host_Wide_Int ByteSize Warning Var(warn_frame_larger_than_size) Init(HOST_WIDE_INT_MAX)
+-Wframe-larger-than=<byte-size> Warn if a function's stack frame requires in excess of <byte-size>.
+
+Wno-frame-larger-than
+Common Alias(Wframe-larger-than=,18446744073709551615EiB,none) Warning
+Disable -Wframe-larger-than= warning. Equivalent to -Wframe-larger-than=<SIZE_MAX> or larger.
+
+Wfree-nonheap-object
+Common Var(warn_free_nonheap_object) Init(1) Warning
+Warn when attempting to free a non-heap object.
+
+Whsa
+Common Ignore Warning
+Does nothing. Preserved for backward compatibility.
+
+Wimplicit-fallthrough
+Common Alias(Wimplicit-fallthrough=,3,0) Warning
+
+Wimplicit-fallthrough=
+Common Var(warn_implicit_fallthrough) RejectNegative Joined UInteger Warning IntegerRange(0, 5)
+Warn when a switch case falls through.
+
+Winfinite-recursion
+Var(warn_infinite_recursion) Warning
+Warn for infinitely recursive calls.
+
+Winline
+Common Var(warn_inline) Warning Optimization
+Warn when an inlined function cannot be inlined.
+
+Winvalid-memory-model
+Common Var(warn_invalid_memory_model) Init(1) Warning
+Warn when an atomic memory model parameter is known to be outside the valid range.
+
+Wlarger-than-
+Common RejectNegative Joined Warning Undocumented Alias(Wlarger-than=)
+
+Wlarger-than=
+Common RejectNegative Joined Host_Wide_Int ByteSize Warning Var(warn_larger_than_size) Init(HOST_WIDE_INT_MAX)
+-Wlarger-than=<byte-size> Warn if an object's size exceeds <byte-size>.
+
+Wno-larger-than
+Common Alias(Wlarger-than=,18446744073709551615EiB,none) Warning
+Disable -Wlarger-than= warning. Equivalent to -Wlarger-than=<SIZE_MAX> or larger.
+
+Wnonnull-compare
+Var(warn_nonnull_compare) Warning
+Warn if comparing pointer parameter with nonnull attribute with NULL.
+
+Wnull-dereference
+Common Var(warn_null_dereference) Warning
+Warn if dereferencing a NULL pointer may lead to erroneous or undefined behavior.
+
+Wunsafe-loop-optimizations
+Common Ignore Warning
+Does nothing. Preserved for backward compatibility.
+
+Wmissing-noreturn
+Common Warning Alias(Wsuggest-attribute=noreturn)
+
+Wodr
+Common Var(warn_odr_violations) Init(1) Warning
+Warn about some C++ One Definition Rule violations during link time optimization.
+
+Woverflow
+Common Var(warn_overflow) Init(1) Warning
+Warn about overflow in arithmetic expressions.
+
+Wlto-type-mismatch
+Common Var(warn_lto_type_mismatch) Init(1) Warning
+During link time optimization warn about mismatched types of global declarations.
+
+Wpacked
+Common Var(warn_packed) Warning
+Warn when the packed attribute has no effect on struct layout.
+
+Wpadded
+Common Var(warn_padded) Warning
+Warn when padding is required to align structure members.
+
+Wpedantic
+Common Var(pedantic) Init(0) Warning
+Issue warnings needed for strict compliance to the standard.
+
+Wreturn-local-addr
+Common Var(warn_return_local_addr) Init(1) Warning
+Warn about returning a pointer/reference to a local or temporary variable.
+
+Wshadow
+Common Var(warn_shadow) Warning
+Warn when one variable shadows another. Same as -Wshadow=global.
+
+Wshadow=global
+Common Warning Alias(Wshadow)
+Warn when one variable shadows another (globally).
+
+Wshadow=local
+Common Var(warn_shadow_local) Warning EnabledBy(Wshadow)
+Warn when one local variable shadows another local variable or parameter.
+
+Wshadow-local
+Common Warning Undocumented Alias(Wshadow=local)
+
+Wshadow=compatible-local
+Common Var(warn_shadow_compatible_local) Warning EnabledBy(Wshadow=local)
+Warn when one local variable shadows another local variable or parameter of compatible type.
+
+Wshadow-compatible-local
+Common Warning Undocumented Alias(Wshadow=compatible-local)
+
+Wstack-protector
+Common Var(warn_stack_protect) Warning
+Warn when not issuing stack smashing protection for some reason.
+
+Wstack-usage=
+Common Joined RejectNegative Host_Wide_Int ByteSize Var(warn_stack_usage) Warning Init(HOST_WIDE_INT_MAX)
+-Wstack-usage=<byte-size> Warn if stack usage might exceed <byte-size>.
+
+Wno-stack-usage
+Common Alias(Wstack-usage=,18446744073709551615EiB,none) Warning
+Disable Wstack-usage= warning. Equivalent to Wstack-usage=<SIZE_MAX> or larger.
+
+Wstrict-aliasing
+Common Warning
+Warn about code which might break strict aliasing rules.
+
+Wstrict-aliasing=
+Common Joined RejectNegative UInteger Var(warn_strict_aliasing) Warning
+Warn about code which might break strict aliasing rules.
+
+Wstrict-overflow
+Common Warning
+Warn about optimizations that assume that signed overflow is undefined.
+
+Wstrict-overflow=
+Common Joined RejectNegative UInteger Var(warn_strict_overflow) Warning
+Warn about optimizations that assume that signed overflow is undefined.
+
+Wsuggest-attribute=cold
+Common Var(warn_suggest_attribute_cold) Warning
+Warn about functions which might be candidates for __attribute__((cold)).
+
+Wsuggest-attribute=const
+Common Var(warn_suggest_attribute_const) Warning
+Warn about functions which might be candidates for __attribute__((const)).
+
+Wsuggest-attribute=pure
+Common Var(warn_suggest_attribute_pure) Warning
+Warn about functions which might be candidates for __attribute__((pure)).
+
+Wsuggest-attribute=noreturn
+Common Var(warn_suggest_attribute_noreturn) Warning
+Warn about functions which might be candidates for __attribute__((noreturn)).
+
+Wsuggest-attribute=malloc
+Common Var(warn_suggest_attribute_malloc) Warning
+Warn about functions which might be candidates for __attribute__((malloc)).
+
+Wsuggest-final-types
+Common Var(warn_suggest_final_types) Warning
+Warn about C++ polymorphic types where adding final keyword would improve code quality.
+
+Wsuggest-final-methods
+Common Var(warn_suggest_final_methods) Warning
+Warn about C++ virtual methods where adding final keyword would improve code quality.
+
+Wswitch-unreachable
+Common Var(warn_switch_unreachable) Warning Init(1)
+Warn about statements between switch's controlling expression and the first
+case.
+
+Wsystem-headers
+Common Var(warn_system_headers) Warning
+Do not suppress warnings from system headers.
+
+Wtrampolines
+Common Var(warn_trampolines) Warning
+Warn whenever a trampoline is generated.
+
+Wtrivial-auto-var-init
+Common Var(warn_trivial_auto_var_init) Warning Init(0)
+Warn about cases where -ftrivial-auto-var-init cannot initialize an auto variable.
+
+Wtype-limits
+Common Var(warn_type_limits) Warning EnabledBy(Wextra)
+Warn if a comparison is always true or always false due to the limited range of the data type.
+
+Wuninitialized
+Common Var(warn_uninitialized) Warning EnabledBy(Wextra)
+Warn about uninitialized automatic variables.
+
+Wmaybe-uninitialized
+Common Var(warn_maybe_uninitialized) Warning EnabledBy(Wuninitialized)
+Warn about maybe uninitialized automatic variables.
+
+Wunreachable-code
+Common Ignore Warning
+Does nothing. Preserved for backward compatibility.
+
+Wunused
+Common Var(warn_unused) Init(0) Warning
+Enable all -Wunused- warnings.
+
+Wunused-but-set-parameter
+Common Var(warn_unused_but_set_parameter) Warning EnabledBy(Wunused && Wextra)
+Warn when a function parameter is only set, otherwise unused.
+
+Wunused-but-set-variable
+Common Var(warn_unused_but_set_variable) Warning EnabledBy(Wunused)
+Warn when a variable is only set, otherwise unused.
+
+Wunused-function
+Common Var(warn_unused_function) Warning EnabledBy(Wunused)
+Warn when a function is unused.
+
+Wunused-label
+Common Var(warn_unused_label) Warning EnabledBy(Wunused)
+Warn when a label is unused.
+
+Wunused-parameter
+Common Var(warn_unused_parameter) Warning EnabledBy(Wunused && Wextra)
+Warn when a function parameter is unused.
+
+Wunused-value
+Common Var(warn_unused_value) Warning EnabledBy(Wunused)
+Warn when an expression value is unused.
+
+Wunused-variable
+Common Var(warn_unused_variable) Warning EnabledBy(Wunused)
+Warn when a variable is unused.
+
+Wcoverage-mismatch
+Common Var(warn_coverage_mismatch) Init(1) Warning
+Warn in case profiles in -fprofile-use do not match.
+
+Wcoverage-invalid-line-number
+Common Var(warn_coverage_invalid_linenum) Init(1) Warning
+Warn in case a function ends earlier than it begins due to an invalid linenum macros.
+
+Wmissing-profile
+Common Var(warn_missing_profile) Init(1) Warning
+Warn in case profiles in -fprofile-use do not exist.
+
+Wvector-operation-performance
+Common Var(warn_vector_operation_performance) Warning
+Warn when a vector operation is compiled outside the SIMD.
+
+Wtsan
+Common Var(warn_tsan) Init(1) Warning
+Warn about unsupported features in ThreadSanitizer.
+
+Xassembler
+Driver Separate
+
+Xlinker
+Driver Separate
+
+Xpreprocessor
+Driver Separate
+
+Z
+Driver
+
+aux-info
+Common Separate Var(aux_info_file_name)
+-aux-info <file> Emit declaration information into <file>.
+
+aux-info=
+Common Joined Alias(aux-info)
+
+coverage
+Driver
+
+c
+Driver
+
+d
+Common Joined
+-d<letters> Enable dumps from specific passes of the compiler.
+
+dumpbase
+Driver Common Separate Var(dump_base_name)
+-dumpbase <file> Set the file basename to be used for dumps.
+
+dumpbase-ext
+Driver Common Separate Var(dump_base_ext)
+-dumpbase-ext .<ext> Drop a trailing .<ext> from the dump basename to name auxiliary output files.
+
+dumpdir
+Driver Common Separate Var(dump_dir_name)
+-dumpdir <dir> Set the directory name to be used for dumps.
+
+dumpmachine
+Driver
+
+dumpspecs
+Driver
+
+dumpversion
+Driver
+
+dumpfullversion
+Driver
+
+e
+Driver Joined Separate
+
+; This option has historically been passed down to the linker by an
+; accident of a %{e*} spec, so ensure it continues to be passed down
+; as a single option. The supported option for this purpose is
+; -rdynamic. See PR 47390.
+export-dynamic
+Driver Undocumented
+
+; The version of the C++ ABI in use. The following values are allowed:
+;
+; 0: The version of the ABI believed most conformant with the C++ ABI
+; specification. This ABI may change as bugs are discovered and fixed.
+; Therefore, 0 will not necessarily indicate the same ABI in different
+; versions of G++.
+;
+; 1: The version of the ABI first used in G++ 3.2. No longer selectable.
+;
+; 2: The version of the ABI first used in G++ 3.4, and the default
+; until GCC 4.9.
+;
+; 3: The version of the ABI that fixes the missing underscore
+; in template non-type arguments of pointer type.
+;
+; 4: The version of the ABI that introduces unambiguous mangling of
+; vector types. First selectable in G++ 4.5.
+;
+; 5: The version of the ABI that ignores attribute const/noreturn
+; in function pointer mangling, and corrects mangling of decltype and
+; function parameters used in other parameters and the return type.
+; First selectable in G++ 4.6.
+;
+; 6: The version of the ABI that doesn't promote scoped enums to int and
+; changes the mangling of template argument packs, const/static_cast,
+; prefix ++ and --, and a class scope function used as a template
+; argument.
+; First selectable in G++ 4.7.
+;
+; 7: The version of the ABI that treats nullptr_t as a builtin type and
+; corrects the mangling of lambdas in default argument scope.
+; First selectable in G++ 4.8.
+;
+; 8: The version of the ABI that corrects the substitution behavior of
+; function types with function-cv-qualifiers.
+; First selectable in G++ 4.9 and default in G++ 5.
+;
+; 9: The version of the ABI that corrects the alignment of nullptr_t.
+; First selectable and default in G++ 5.2.
+;
+; 10: The version of the ABI that mangles attributes that affect type
+; identity, such as ia32 calling convention attributes (stdcall, etc.)
+; Default in G++ 6 (set in c_common_post_options).
+;
+; 11: The version of the ABI that corrects mangling of sizeof... expressions
+; and introduces new inheriting constructor handling.
+; Default in G++ 7.
+;
+; 12: Corrects the calling convention for classes with only deleted copy/move
+; constructors and changes passing/returning of empty records.
+; Default in G++ 8.1.
+;
+; 13: Fixes the accidental change in 12 to the calling convention for classes
+; with deleted copy constructor and trivial move constructor.
+; Default in G++ 8.2.
+;
+; 14: Corrects the mangling of nullptr expression.
+; Default in G++ 10.
+;
+; 15: Corrects G++ 10 ABI tag regression [PR98481].
+; Available, but not default, in G++ 10.3.
+;
+; 16: Changes the mangling of __alignof__ to be distinct from that of alignof.
+; Adds missing 'on' in mangling of operator names in some cases.
+; Default in G++ 11.
+;
+; 17: Fixes layout of classes that inherit from aggregate classes with default
+; member initializers in C++14 and up.
+; Default in G++ 12.
+;
+; Additional positive integers will be assigned as new versions of
+; the ABI become the default version of the ABI.
+fabi-version=
+Common Joined RejectNegative UInteger Var(flag_abi_version) Init(0)
+The version of the C++ ABI in use.
+
+faggressive-loop-optimizations
+Common Var(flag_aggressive_loop_optimizations) Optimization Init(1)
+Aggressively optimize loops using language constraints.
+
+falign-functions
+Common Var(flag_align_functions) Optimization
+Align the start of functions.
+
+falign-functions=
+Common RejectNegative Joined Var(str_align_functions) Optimization
+
+flimit-function-alignment
+Common Var(flag_limit_function_alignment) Optimization Init(0)
+
+falign-jumps
+Common Var(flag_align_jumps) Optimization
+Align labels which are only reached by jumping.
+
+falign-jumps=
+Common RejectNegative Joined Var(str_align_jumps) Optimization
+
+falign-labels
+Common Var(flag_align_labels) Optimization
+Align all labels.
+
+falign-labels=
+Common RejectNegative Joined Var(str_align_labels) Optimization
+
+falign-loops
+Common Var(flag_align_loops) Optimization
+Align the start of loops.
+
+falign-loops=
+Common RejectNegative Joined Var(str_align_loops) Optimization
+
+fallow-store-data-races
+Common Var(flag_store_data_races) Optimization
+Allow the compiler to introduce new data races on stores.
+
+fanalyzer
+Common Var(flag_analyzer)
+Enable static analysis pass.
+
+fargument-alias
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fargument-noalias
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fargument-noalias-global
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fargument-noalias-anything
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fsanitize=
+Common Driver Joined
+Select what to sanitize.
+
+fsanitize-coverage=
+Common Joined Enum(sanitize_coverage) Var(flag_sanitize_coverage) EnumBitSet
+Select type of coverage sanitization.
+
+Enum
+Name(sanitize_coverage) Type(int)
+
+EnumValue
+Enum(sanitize_coverage) String(trace-pc) Value(SANITIZE_COV_TRACE_PC)
+
+EnumValue
+Enum(sanitize_coverage) String(trace-cmp) Value(SANITIZE_COV_TRACE_CMP)
+
+fasan-shadow-offset=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fasan-shadow-offset=<number> Use custom shadow memory offset.
+
+fsanitize-sections=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fsanitize-sections=<sec1,sec2,...> Sanitize global variables
+in user-defined sections.
+
+fsanitize-recover=
+Common Joined
+After diagnosing undefined behavior attempt to continue execution.
+
+fsanitize-recover
+Common
+This switch is deprecated; use -fsanitize-recover= instead.
+
+fsanitize-address-use-after-scope
+Common Driver Var(flag_sanitize_address_use_after_scope) Init(0)
+
+fsanitize-undefined-trap-on-error
+Common Driver Var(flag_sanitize_undefined_trap_on_error) Init(0)
+Use trap instead of a library function for undefined behavior sanitization.
+
+fasynchronous-unwind-tables
+Common Var(flag_asynchronous_unwind_tables) Optimization
+Generate unwind tables that are exact at each instruction boundary.
+
+fauto-inc-dec
+Common Var(flag_auto_inc_dec) Init(1) Optimization
+Generate auto-inc/dec instructions.
+
+fauto-profile
+Common Var(flag_auto_profile)
+Use sample profile information for call graph node weights. The default
+profile file is fbdata.afdo in 'pwd'.
+
+fauto-profile=
+Common Joined RejectNegative Var(auto_profile_file)
+Use sample profile information for call graph node weights. The profile
+file is specified in the argument.
+
+; -fcheck-bounds causes gcc to generate array bounds checks.
+; For C, C++ and ObjC: defaults off.
+; For Java: defaults to on.
+; For Fortran: defaults to off.
+fbounds-check
+Common Var(flag_bounds_check)
+Generate code to check bounds before indexing arrays.
+
+fbranch-count-reg
+Common Var(flag_branch_on_count_reg) Optimization
+Replace add, compare, branch with branch on count register.
+
+fbranch-probabilities
+Common Var(flag_branch_probabilities) Optimization
+Use profiling information for branch probabilities.
+
+fbranch-target-load-optimize
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fbranch-target-load-optimize2
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fbtr-bb-exclusive
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fcallgraph-info
+Common RejectNegative Var(flag_callgraph_info) Init(NO_CALLGRAPH_INFO);
+Output callgraph information on a per-file basis.
+
+fcallgraph-info=
+Common RejectNegative Joined
+Output callgraph information on a per-file basis with decorations.
+
+fcall-saved-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fcall-saved-<register> Mark <register> as being preserved across functions.
+
+fcall-used-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fcall-used-<register> Mark <register> as being corrupted by function calls.
+
+; Nonzero for -fcaller-saves: allocate values in regs that need to
+; be saved across function calls, if that produces overall better code.
+; Optional now, so people can test it.
+fcaller-saves
+Common Var(flag_caller_saves) Optimization
+Save registers around function calls.
+
+fcheck-data-deps
+Common Ignore
+This switch is deprecated; do not use.
+
+fcheck-new
+Common Var(flag_check_new)
+Check the return value of new in C++.
+
+fchecking
+Common Var(flag_checking) Init(CHECKING_P ? ENABLE_EXTRA_CHECKING ? 2 : 1 : 0)
+Perform internal consistency checkings.
+
+fchecking=
+Common Joined RejectNegative UInteger Var(flag_checking)
+Perform internal consistency checkings.
+
+fcode-hoisting
+Common Var(flag_code_hoisting) Optimization
+Enable code hoisting.
+
+fcombine-stack-adjustments
+Common Var(flag_combine_stack_adjustments) Optimization
+Looks for opportunities to reduce stack adjustments and stack references.
+
+fcommon
+Common Var(flag_no_common,0) Init(1)
+Put uninitialized globals in the common section.
+
+fcompare-debug
+Driver
+; Converted by the driver to -fcompare-debug= options.
+
+fcompare-debug=
+Common Driver JoinedOrMissing RejectNegative Var(flag_compare_debug_opt)
+-fcompare-debug[=<opts>] Compile with and without e.g. -gtoggle, and compare the final-insns dump.
+
+fcompare-debug-second
+Common Driver RejectNegative Var(flag_compare_debug)
+Run only the second compilation of -fcompare-debug.
+
+fcompare-elim
+Common Var(flag_compare_elim_after_reload) Optimization
+Perform comparison elimination after register allocation has finished.
+
+fconserve-stack
+Common Var(flag_conserve_stack) Optimization
+Do not perform optimizations increasing noticeably stack usage.
+
+fcprop-registers
+Common Var(flag_cprop_registers) Optimization
+Perform a register copy-propagation optimization pass.
+
+fcrossjumping
+Common Var(flag_crossjumping) Optimization
+Perform cross-jumping optimization.
+
+fcse-follow-jumps
+Common Var(flag_cse_follow_jumps) Optimization
+When running CSE, follow jumps to their targets.
+
+fcse-skip-blocks
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fcx-limited-range
+Common Var(flag_cx_limited_range) Optimization SetByCombined
+Omit range reduction step when performing complex division.
+
+fcx-fortran-rules
+Common Var(flag_cx_fortran_rules) Optimization
+Complex multiplication and division follow Fortran rules.
+
+fdata-sections
+Common Var(flag_data_sections)
+Place data items into their own section.
+
+fdbg-cnt-list
+Common Var(flag_dbg_cnt_list)
+List all available debugging counters with their limits and counts.
+
+fdbg-cnt=
+Common RejectNegative Joined Var(common_deferred_options) Defer
+-fdbg-cnt=<counter>[:<lower_limit1>-]<upper_limit1>[:<lower_limit2>-<upper_limit2>:...][,<counter>:...] Set the debug counter limit.
+
+fdebug-prefix-map=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdebug-prefix-map=<old>=<new> Map one directory name to another in debug information.
+
+ffile-prefix-map=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-ffile-prefix-map=<old>=<new> Map one directory name to another in compilation result.
+
+fdebug-types-section
+Common Var(flag_debug_types_section) Init(0)
+Output .debug_types section when using DWARF v4 debuginfo.
+
+; Nonzero for -fdefer-pop: don't pop args after each function call
+; instead save them up to pop many calls' args with one insns.
+fdefer-pop
+Common Var(flag_defer_pop) Optimization
+Defer popping functions args from stack until later.
+
+fdelayed-branch
+Common Var(flag_delayed_branch) Optimization
+Attempt to fill delay slots of branch instructions.
+
+fdelete-dead-exceptions
+Common Var(flag_delete_dead_exceptions) Init(0) Optimization
+Delete dead instructions that may throw exceptions.
+
+fdelete-null-pointer-checks
+Common Var(flag_delete_null_pointer_checks) Init(-1) Optimization
+Delete useless null pointer checks.
+
+fdevirtualize-at-ltrans
+Common Var(flag_ltrans_devirtualize)
+Stream extra data to support more aggressive devirtualization in LTO local transformation mode.
+
+fdevirtualize-speculatively
+Common Var(flag_devirtualize_speculatively) Optimization
+Perform speculative devirtualization.
+
+fdevirtualize
+Common Var(flag_devirtualize) Optimization
+Try to convert virtual calls to direct ones.
+
+fdiagnostics-show-location=
+Common Joined RejectNegative Enum(diagnostic_prefixing_rule)
+-fdiagnostics-show-location=[once|every-line] How often to emit source location at the beginning of line-wrapped diagnostics.
+
+; Required for these enum values.
+SourceInclude
+pretty-print.h
+
+Enum
+Name(diagnostic_prefixing_rule) Type(int)
+
+EnumValue
+Enum(diagnostic_prefixing_rule) String(once) Value(DIAGNOSTICS_SHOW_PREFIX_ONCE)
+
+EnumValue
+Enum(diagnostic_prefixing_rule) String(every-line) Value(DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE)
+
+fdiagnostics-show-caret
+Common Var(flag_diagnostics_show_caret) Init(1)
+Show the source line with a caret indicating the column.
+
+fdiagnostics-show-labels
+Common Var(flag_diagnostics_show_labels) Init(1)
+Show labels annotating ranges of source code when showing source.
+
+fdiagnostics-show-line-numbers
+Common Var(flag_diagnostics_show_line_numbers) Init(1)
+Show line numbers in the left margin when showing source.
+
+fdiagnostics-color
+Common Alias(fdiagnostics-color=,always,never)
+;
+
+fdiagnostics-color=
+Driver Common Joined RejectNegative Var(flag_diagnostics_show_color) Enum(diagnostic_color_rule) Init(DIAGNOSTICS_COLOR_NO)
+-fdiagnostics-color=[never|always|auto] Colorize diagnostics.
+
+; Required for these enum values.
+SourceInclude
+diagnostic-color.h
+
+Enum
+Name(diagnostic_color_rule) Type(int)
+
+EnumValue
+Enum(diagnostic_color_rule) String(never) Value(DIAGNOSTICS_COLOR_NO)
+
+EnumValue
+Enum(diagnostic_color_rule) String(always) Value(DIAGNOSTICS_COLOR_YES)
+
+EnumValue
+Enum(diagnostic_color_rule) String(auto) Value(DIAGNOSTICS_COLOR_AUTO)
+
+fdiagnostics-urls=
+Driver Common Joined RejectNegative Var(flag_diagnostics_show_urls) Enum(diagnostic_url_rule) Init(DIAGNOSTICS_URL_AUTO)
+-fdiagnostics-urls=[never|always|auto] Embed URLs in diagnostics.
+
+; Required for these enum values.
+SourceInclude
+diagnostic-url.h
+
+Enum
+Name(diagnostic_url_rule) Type(int)
+
+EnumValue
+Enum(diagnostic_url_rule) String(never) Value(DIAGNOSTICS_URL_NO)
+
+EnumValue
+Enum(diagnostic_url_rule) String(always) Value(DIAGNOSTICS_URL_YES)
+
+EnumValue
+Enum(diagnostic_url_rule) String(auto) Value(DIAGNOSTICS_URL_AUTO)
+
+fdiagnostics-column-unit=
+Common Joined RejectNegative Enum(diagnostics_column_unit)
+-fdiagnostics-column-unit=[display|byte] Select whether column numbers are output as display columns (default) or raw bytes.
+
+fdiagnostics-column-origin=
+Common Joined RejectNegative UInteger
+-fdiagnostics-column-origin=<number> Set the number of the first column. The default is 1-based as per GNU style, but some utilities may expect 0-based, for example.
+
+fdiagnostics-format=
+Common Joined RejectNegative Enum(diagnostics_output_format)
+-fdiagnostics-format=[text|json] Select output format.
+
+fdiagnostics-escape-format=
+Common Joined RejectNegative Enum(diagnostics_escape_format)
+-fdiagnostics-escape-format=[unicode|bytes] Select how to escape non-printable-ASCII bytes in the source for diagnostics that suggest it.
+
+; Required for these enum values.
+SourceInclude
+diagnostic.h
+
+Enum
+Name(diagnostics_column_unit) Type(int)
+
+EnumValue
+Enum(diagnostics_column_unit) String(display) Value(DIAGNOSTICS_COLUMN_UNIT_DISPLAY)
+
+EnumValue
+Enum(diagnostics_column_unit) String(byte) Value(DIAGNOSTICS_COLUMN_UNIT_BYTE)
+
+Enum
+Name(diagnostics_escape_format) Type(int)
+
+EnumValue
+Enum(diagnostics_escape_format) String(unicode) Value(DIAGNOSTICS_ESCAPE_FORMAT_UNICODE)
+
+EnumValue
+Enum(diagnostics_escape_format) String(bytes) Value(DIAGNOSTICS_ESCAPE_FORMAT_BYTES)
+
+Enum
+Name(diagnostics_output_format) Type(int)
+
+EnumValue
+Enum(diagnostics_output_format) String(text) Value(DIAGNOSTICS_OUTPUT_FORMAT_TEXT)
+
+EnumValue
+Enum(diagnostics_output_format) String(json) Value(DIAGNOSTICS_OUTPUT_FORMAT_JSON)
+
+fdiagnostics-parseable-fixits
+Common Var(flag_diagnostics_parseable_fixits)
+Print fix-it hints in machine-readable form.
+
+fdiagnostics-generate-patch
+Common Var(flag_diagnostics_generate_patch)
+Print fix-it hints to stderr in unified diff format.
+
+fdiagnostics-show-option
+Common Var(flag_diagnostics_show_option) Init(1)
+Amend appropriate diagnostic messages with the command line option that controls them.
+
+fdiagnostics-show-cwe
+Common Var(flag_diagnostics_show_cwe) Init(1)
+Print CWE identifiers for diagnostic messages, where available.
+
+fdiagnostics-path-format=
+Common Joined RejectNegative Var(flag_diagnostics_path_format) Enum(diagnostic_path_format) Init(DPF_INLINE_EVENTS)
+Specify how to print any control-flow path associated with a diagnostic.
+
+fdiagnostics-plain-output
+Driver Common RejectNegative
+Turn off any diagnostics features that complicate the output, such as line numbers, color, and warning URLs.
+
+ftabstop=
+Common Joined RejectNegative UInteger
+-ftabstop=<number> Distance between tab stops for column reporting.
+
+Enum
+Name(diagnostic_path_format) Type(int)
+
+EnumValue
+Enum(diagnostic_path_format) String(none) Value(DPF_NONE)
+
+EnumValue
+Enum(diagnostic_path_format) String(separate-events) Value(DPF_SEPARATE_EVENTS)
+
+EnumValue
+Enum(diagnostic_path_format) String(inline-events) Value(DPF_INLINE_EVENTS)
+
+fdiagnostics-show-path-depths
+Common Var(flag_diagnostics_show_path_depths) Init(0)
+Show stack depths of events in paths.
+
+fdiagnostics-minimum-margin-width=
+Common Joined UInteger Var(diagnostics_minimum_margin_width) Init(6)
+Set minimum width of left margin of source code when showing source.
+
+fdisable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdisable-[tree|rtl|ipa]-<pass>=range1+range2 Disable an optimization pass.
+
+fenable-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fenable-[tree|rtl|ipa]-<pass>=range1+range2 Enable an optimization pass.
+
+fdump-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fdump-<type> Dump various compiler internals to a file.
+
+fdump-final-insns
+Driver RejectNegative
+
+fdump-final-insns=
+Common RejectNegative Joined Var(flag_dump_final_insns)
+-fdump-final-insns=filename Dump to filename the insns at the end of translation.
+
+fdump-go-spec=
+Common RejectNegative Joined Var(flag_dump_go_spec)
+-fdump-go-spec=filename Write all declarations to file as Go code.
+
+fdump-noaddr
+Common Var(flag_dump_noaddr)
+Suppress output of addresses in debugging dumps.
+
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occurred.
+
+fdump-internal-locations
+Common Var(flag_dump_locations) Init(0)
+Dump detailed information on GCC's internal representation of source code locations.
+
+fdump-passes
+Common Var(flag_dump_passes) Init(0)
+Dump optimization passes.
+
+fdump-unnumbered
+Common Var(flag_dump_unnumbered)
+Suppress output of instruction numbers, line number notes and addresses in debugging dumps.
+
+fdump-unnumbered-links
+Common Var(flag_dump_unnumbered_links)
+Suppress output of previous and next insn numbers in debugging dumps.
+
+fdwarf2-cfi-asm
+Common Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
+Enable CFI tables via GAS assembler directives.
+
+fearly-inlining
+Common Var(flag_early_inlining) Init(1) Optimization
+Perform early inlining.
+
+feliminate-dwarf2-dups
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fipa-sra
+Common Var(flag_ipa_sra) Init(0) Optimization
+Perform interprocedural reduction of aggregates.
+
+feliminate-unused-debug-symbols
+Common Var(flag_debug_only_used_symbols) Init(1)
+Perform unused symbol elimination in debug info.
+
+feliminate-unused-debug-types
+Common Var(flag_eliminate_unused_debug_types) Init(1)
+Perform unused type elimination in debug info.
+
+femit-class-debug-always
+Common Var(flag_emit_class_debug_always) Init(0)
+Do not suppress C++ class debug information.
+
+fexceptions
+Common Var(flag_exceptions) Optimization EnabledBy(fnon-call-exceptions)
+Enable exception handling.
+
+fexpensive-optimizations
+Common Var(flag_expensive_optimizations) Optimization
+Perform a number of minor, expensive optimizations.
+
+fexcess-precision=
+Common Joined RejectNegative Enum(excess_precision) Var(flag_excess_precision) Init(EXCESS_PRECISION_DEFAULT) Optimization SetByCombined
+-fexcess-precision=[fast|standard|16] Specify handling of excess floating-point precision.
+
+Enum
+Name(excess_precision) Type(enum excess_precision) UnknownError(unknown excess precision style %qs)
+
+EnumValue
+Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
+
+EnumValue
+Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
+
+EnumValue
+Enum(excess_precision) String(16) Value(EXCESS_PRECISION_FLOAT16)
+
+; Whether we permit the extended set of values for FLT_EVAL_METHOD
+; introduced in ISO/IEC TS 18661-3, or limit ourselves to those in C99/C11.
+fpermitted-flt-eval-methods=
+Common Joined RejectNegative Enum(permitted_flt_eval_methods) Var(flag_permitted_flt_eval_methods) Init(PERMITTED_FLT_EVAL_METHODS_DEFAULT)
+-fpermitted-flt-eval-methods=[c11|ts-18661] Specify which values of FLT_EVAL_METHOD are permitted.
+
+Enum
+Name(permitted_flt_eval_methods) Type(enum permitted_flt_eval_methods) UnknownError(unknown specification for the set of FLT_EVAL_METHOD values to permit %qs)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(c11) Value(PERMITTED_FLT_EVAL_METHODS_C11)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(ts-18661-3) Value(PERMITTED_FLT_EVAL_METHODS_TS_18661)
+
+ffast-math
+Common Optimization
+
+ffat-lto-objects
+Common Var(flag_fat_lto_objects)
+Output lto objects containing both the intermediate language and binary output.
+
+ffinite-math-only
+Common Var(flag_finite_math_only) Optimization SetByCombined
+Assume no NaNs or infinities are generated.
+
+ffinite-loops
+Common Var(flag_finite_loops) Optimization Init(0)
+Assume that loops with an exit will terminate and not loop indefinitely.
+
+ffixed-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-ffixed-<register> Mark <register> as being unavailable to the compiler.
+
+ffloat-store
+Common Var(flag_float_store) Optimization
+Don't allocate floats and doubles in extended-precision registers.
+
+fforce-addr
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fforward-propagate
+Common Var(flag_forward_propagate) Optimization
+Perform a forward propagation pass on RTL.
+
+ffp-contract=
+Common Joined RejectNegative Enum(fp_contract_mode) Var(flag_fp_contract_mode) Init(FP_CONTRACT_FAST) Optimization
+-ffp-contract=[off|on|fast] Perform floating-point expression contraction.
+
+Enum
+Name(fp_contract_mode) Type(enum fp_contract_mode) UnknownError(unknown floating point contraction style %qs)
+
+EnumValue
+Enum(fp_contract_mode) String(off) Value(FP_CONTRACT_OFF)
+
+; Not implemented, fall back to conservative FP_CONTRACT_OFF.
+EnumValue
+Enum(fp_contract_mode) String(on) Value(FP_CONTRACT_OFF)
+
+EnumValue
+Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST)
+
+ffp-int-builtin-inexact
+Common Var(flag_fp_int_builtin_inexact) Init(1) Optimization
+Allow built-in functions ceil, floor, round, trunc to raise \"inexact\" exceptions.
+
+; Nonzero means don't put addresses of constant functions in registers.
+; Used for compiling the Unix kernel, where strange substitutions are
+; done on the assembly output.
+ffunction-cse
+Common Var(flag_no_function_cse,0) Optimization
+Allow function addresses to be held in registers.
+
+ffunction-sections
+Common Var(flag_function_sections)
+Place each function into its own section.
+
+fgcse
+Common Var(flag_gcse) Optimization
+Perform global common subexpression elimination.
+
+fgcse-lm
+Common Var(flag_gcse_lm) Init(1) Optimization
+Perform enhanced load motion during global common subexpression elimination.
+
+fgcse-sm
+Common Var(flag_gcse_sm) Init(0) Optimization
+Perform store motion after global common subexpression elimination.
+
+fgcse-las
+Common Var(flag_gcse_las) Init(0) Optimization
+Perform redundant load after store elimination in global common subexpression
+elimination.
+
+fgcse-after-reload
+Common Var(flag_gcse_after_reload) Optimization
+Perform global common subexpression elimination after register allocation has
+finished.
+
+Enum
+Name(dwarf_gnat_encodings) Type(int)
+
+EnumValue
+Enum(dwarf_gnat_encodings) String(all) Value(DWARF_GNAT_ENCODINGS_ALL)
+
+EnumValue
+Enum(dwarf_gnat_encodings) String(gdb) Value(DWARF_GNAT_ENCODINGS_GDB)
+
+EnumValue
+Enum(dwarf_gnat_encodings) String(minimal) Value(DWARF_GNAT_ENCODINGS_MINIMAL)
+
+fgnat-encodings=
+Common Enum(dwarf_gnat_encodings) Joined RejectNegative Undocumented Var(gnat_encodings)
+-fgnat-encodings=[all|gdb|minimal] Select the balance between GNAT encodings and standard DWARF emitted in the debug information.
+
+; This option is not documented yet as its semantics will change.
+fgraphite
+Common Var(flag_graphite) Optimization
+Enable in and out of Graphite representation.
+
+fgraphite-identity
+Common Var(flag_graphite_identity) Optimization
+Enable Graphite Identity transformation.
+
+fhoist-adjacent-loads
+Common Var(flag_hoist_adjacent_loads) Optimization
+Enable hoisting adjacent loads to encourage generating conditional move
+instructions.
+
+fkeep-gc-roots-live
+Common Undocumented Var(flag_keep_gc_roots_live) Optimization
+; Always keep a pointer to a live memory block
+
+flarge-source-files
+Common Var(flag_large_source_files) Init(0)
+Improve GCC's ability to track column numbers in large source files,
+at the expense of slower compilation.
+
+floop-parallelize-all
+Common Var(flag_loop_parallelize_all) Optimization
+Mark all loops as parallel.
+
+floop-strip-mine
+Common Alias(floop-nest-optimize)
+Enable loop nest transforms. Same as -floop-nest-optimize.
+
+floop-interchange
+Common Var(flag_loop_interchange) Optimization
+Enable loop interchange on trees.
+
+floop-block
+Common Alias(floop-nest-optimize)
+Enable loop nest transforms. Same as -floop-nest-optimize.
+
+floop-unroll-and-jam
+Common Var(flag_unroll_jam) Optimization
+Perform unroll-and-jam on loops.
+
+fgnu-tm
+Common Var(flag_tm)
+Enable support for GNU transactional memory.
+
+fgnu-unique
+Common Var(flag_gnu_unique) Init(1)
+Use STB_GNU_UNIQUE if supported by the assembler.
+
+floop-flatten
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+floop-nest-optimize
+Common Var(flag_loop_nest_optimize) Optimization
+Enable the loop nest optimizer.
+
+fstrict-volatile-bitfields
+Common Var(flag_strict_volatile_bitfields) Init(-1) Optimization
+Force bitfield accesses to match their type width.
+
+fstore-merging
+Common Var(flag_store_merging) Optimization
+Merge adjacent stores.
+
+fguess-branch-probability
+Common Var(flag_guess_branch_prob) Optimization
+Enable guessing of branch probabilities.
+
+fharden-compares
+Common Var(flag_harden_compares) Optimization
+Harden conditionals not used in branches, checking reversed conditions.
+
+fharden-conditional-branches
+Common Var(flag_harden_conditional_branches) Optimization
+Harden conditional branches by checking reversed conditions.
+
+; Nonzero means ignore `#ident' directives. 0 means handle them.
+; Generate position-independent code for executables if possible
+; On SVR4 targets, it also controls whether or not to emit a
+; string identifying the compiler.
+fident
+Common Var(flag_no_ident,0)
+Process #ident directives.
+
+fif-conversion
+Common Var(flag_if_conversion) Optimization
+Perform conversion of conditional jumps to branchless equivalents.
+
+fif-conversion2
+Common Var(flag_if_conversion2) Optimization
+Perform conversion of conditional jumps to conditional execution.
+
+fstack-reuse=
+Common Joined RejectNegative Enum(stack_reuse_level) Var(flag_stack_reuse) Init(SR_ALL) Optimization
+-fstack-reuse=[all|named_vars|none] Set stack reuse level for local variables.
+
+Enum
+Name(stack_reuse_level) Type(enum stack_reuse_level) UnknownError(unknown Stack Reuse Level %qs)
+
+EnumValue
+Enum(stack_reuse_level) String(all) Value(SR_ALL)
+
+EnumValue
+Enum(stack_reuse_level) String(named_vars) Value(SR_NAMED_VARS)
+
+EnumValue
+Enum(stack_reuse_level) String(none) Value(SR_NONE)
+
+ftree-loop-if-convert
+Common Var(flag_tree_loop_if_convert) Init(-1) Optimization
+Convert conditional jumps in innermost loops to branchless equivalents.
+
+ftree-loop-if-convert-stores
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+; -finhibit-size-directive inhibits output of .size for ELF.
+; This is used only for compiling crtstuff.c,
+; and it may be extended to other effects
+; needed for crtstuff.c on other systems.
+finhibit-size-directive
+Common Var(flag_inhibit_size_directive)
+Do not generate .size directives.
+
+findirect-inlining
+Common Var(flag_indirect_inlining) Optimization
+Perform indirect inlining.
+
+; General flag to enable inlining. Specifying -fno-inline will disable
+; all inlining apart from always-inline functions.
+finline
+Common Var(flag_no_inline,0) Init(0) Optimization
+Enable inlining of function declared \"inline\", disabling disables all inlining.
+
+finline-small-functions
+Common Var(flag_inline_small_functions) Optimization
+Integrate functions into their callers when code size is known not to grow.
+
+finline-functions
+Common Var(flag_inline_functions) Optimization
+Integrate functions not declared \"inline\" into their callers when profitable.
+
+finline-functions-called-once
+Common Var(flag_inline_functions_called_once) Optimization
+Integrate functions only required by their single caller.
+
+finline-limit-
+Common RejectNegative Joined Alias(finline-limit=)
+
+finline-limit=
+Common RejectNegative Joined UInteger
+-finline-limit=<number> Limit the size of inlined functions to <number>.
+
+finline-atomics
+Common Var(flag_inline_atomics) Init(1) Optimization
+Inline __atomic operations when a lock free instruction sequence is available.
+
+fcf-protection
+Common RejectNegative Alias(fcf-protection=,full)
+
+fcf-protection=
+Common Joined RejectNegative Enum(cf_protection_level) Var(flag_cf_protection) Init(CF_NONE)
+-fcf-protection=[full|branch|return|none|check] Instrument functions with checks to verify jump/call/return control-flow transfer
+instructions have valid targets.
+
+Enum
+Name(cf_protection_level) Type(enum cf_protection_level) UnknownError(unknown Control-Flow Protection Level %qs)
+
+EnumValue
+Enum(cf_protection_level) String(full) Value(CF_FULL)
+
+EnumValue
+Enum(cf_protection_level) String(branch) Value(CF_BRANCH)
+
+EnumValue
+Enum(cf_protection_level) String(return) Value(CF_RETURN)
+
+EnumValue
+Enum(cf_protection_level) String(check) Value(CF_CHECK)
+
+EnumValue
+Enum(cf_protection_level) String(none) Value(CF_NONE)
+
+finstrument-functions
+Common Var(flag_instrument_function_entry_exit)
+Instrument function entry and exit with profiling calls.
+
+finstrument-functions-exclude-function-list=
+Common RejectNegative Joined
+-finstrument-functions-exclude-function-list=name,... Do not instrument listed functions.
+
+finstrument-functions-exclude-file-list=
+Common RejectNegative Joined
+-finstrument-functions-exclude-file-list=filename,... Do not instrument functions listed in files.
+
+fipa-cp
+Common Var(flag_ipa_cp) Optimization
+Perform interprocedural constant propagation.
+
+fipa-cp-clone
+Common Var(flag_ipa_cp_clone) Optimization
+Perform cloning to make Interprocedural constant propagation stronger.
+
+fipa-cp-alignment
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fipa-bit-cp
+Common Var(flag_ipa_bit_cp) Optimization
+Perform interprocedural bitwise constant propagation.
+
+fipa-modref
+Common Var(flag_ipa_modref) Optimization
+Perform interprocedural modref analysis.
+
+fipa-profile
+Common Var(flag_ipa_profile) Init(0) Optimization
+Perform interprocedural profile propagation.
+
+fipa-pta
+Common Var(flag_ipa_pta) Init(0) Optimization
+Perform interprocedural points-to analysis.
+
+fipa-pure-const
+Common Var(flag_ipa_pure_const) Init(0) Optimization
+Discover pure and const functions.
+
+fipa-icf
+Common Var(flag_ipa_icf) Optimization
+Perform Identical Code Folding for functions and read-only variables.
+
+fipa-icf-functions
+Common Var(flag_ipa_icf_functions) Optimization
+Perform Identical Code Folding for functions.
+
+fipa-icf-variables
+Common Var(flag_ipa_icf_variables) Optimization
+Perform Identical Code Folding for variables.
+
+fipa-reference
+Common Var(flag_ipa_reference) Init(0) Optimization
+Discover read-only and non addressable static variables.
+
+fipa-reference-addressable
+Common Var(flag_ipa_reference_addressable) Init(0) Optimization
+Discover read-only, write-only and non-addressable static variables.
+
+fipa-stack-alignment
+Common Var(flag_ipa_stack_alignment) Init(1) Optimization
+Reduce stack alignment on call sites if possible.
+
+fipa-matrix-reorg
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fipa-struct-reorg
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fipa-vrp
+Common Var(flag_ipa_vrp) Optimization
+Perform IPA Value Range Propagation.
+
+fira-algorithm=
+Common Joined RejectNegative Enum(ira_algorithm) Var(flag_ira_algorithm) Init(IRA_ALGORITHM_CB) Optimization
+-fira-algorithm=[CB|priority] Set the used IRA algorithm.
+
+fipa-strict-aliasing
+Common Var(flag_ipa_strict_aliasing) Init(1) Optimization
+Assume strict aliasing rules apply across (uninlined) function boundaries.
+
+Enum
+Name(ira_algorithm) Type(enum ira_algorithm) UnknownError(unknown IRA algorithm %qs)
+
+EnumValue
+Enum(ira_algorithm) String(CB) Value(IRA_ALGORITHM_CB)
+
+EnumValue
+Enum(ira_algorithm) String(priority) Value(IRA_ALGORITHM_PRIORITY)
+
+fira-region=
+Common Joined RejectNegative Enum(ira_region) Var(flag_ira_region) Init(IRA_REGION_ONE) Optimization
+-fira-region=[one|all|mixed] Set regions for IRA.
+
+Enum
+Name(ira_region) Type(enum ira_region) UnknownError(unknown IRA region %qs)
+
+EnumValue
+Enum(ira_region) String(one) Value(IRA_REGION_ONE)
+
+EnumValue
+Enum(ira_region) String(all) Value(IRA_REGION_ALL)
+
+EnumValue
+Enum(ira_region) String(mixed) Value(IRA_REGION_MIXED)
+
+fira-hoist-pressure
+Common Var(flag_ira_hoist_pressure) Init(1) Optimization
+Use IRA based register pressure calculation
+in RTL hoist optimizations.
+
+fira-loop-pressure
+Common Var(flag_ira_loop_pressure) Optimization
+Use IRA based register pressure calculation
+in RTL loop optimizations.
+
+fira-share-save-slots
+Common Var(flag_ira_share_save_slots) Init(1) Optimization
+Share slots for saving different hard registers.
+
+fira-share-spill-slots
+Common Var(flag_ira_share_spill_slots) Init(1) Optimization
+Share stack slots for spilled pseudo-registers.
+
+fira-verbose=
+Common RejectNegative Joined UInteger Var(flag_ira_verbose) Init(5)
+-fira-verbose=<number> Control IRA's level of diagnostic messages.
+
+fivopts
+Common Var(flag_ivopts) Init(1) Optimization
+Optimize induction variables on trees.
+
+fjump-tables
+Common Var(flag_jump_tables) Init(1) Optimization
+Use jump tables for sufficiently large switch statements.
+
+fbit-tests
+Common Var(flag_bit_tests) Init(1) Optimization
+Use bit tests for sufficiently large switch statements.
+
+fkeep-inline-functions
+Common Var(flag_keep_inline_functions)
+Generate code for functions even if they are fully inlined.
+
+fkeep-static-functions
+Common Var(flag_keep_static_functions)
+Generate code for static functions even if they are never called.
+
+fkeep-static-consts
+Common Var(flag_keep_static_consts) Init(1)
+Emit static const variables even if they are not used.
+
+fleading-underscore
+Common Var(flag_leading_underscore) Init(-1)
+Give external symbols a leading underscore.
+
+floop-optimize
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+flra-remat
+Common Var(flag_lra_remat) Optimization
+Do CFG-sensitive rematerialization in LRA.
+
+flto
+Common
+Enable link-time optimization.
+
+flto=
+Common RejectNegative Joined Var(flag_lto)
+Link-time optimization with number of parallel jobs or jobserver.
+
+Enum
+Name(lto_partition_model) Type(enum lto_partition_model) UnknownError(unknown LTO partitioning model %qs)
+
+EnumValue
+Enum(lto_partition_model) String(none) Value(LTO_PARTITION_NONE)
+
+EnumValue
+Enum(lto_partition_model) String(one) Value(LTO_PARTITION_ONE)
+
+EnumValue
+Enum(lto_partition_model) String(balanced) Value(LTO_PARTITION_BALANCED)
+
+EnumValue
+Enum(lto_partition_model) String(1to1) Value(LTO_PARTITION_1TO1)
+
+EnumValue
+Enum(lto_partition_model) String(max) Value(LTO_PARTITION_MAX)
+
+flto-partition=
+Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_BALANCED)
+Specify the algorithm to partition symbols and vars at linktime.
+
+; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
+flto-compression-level=
+Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 19)
+-flto-compression-level=<number> Use zlib/zstd compression level <number> for IL.
+
+flto-odr-type-merging
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+flto-report
+Common Var(flag_lto_report) Init(0)
+Report various link-time optimization statistics.
+
+flto-report-wpa
+Common Var(flag_lto_report_wpa) Init(0)
+Report various link-time optimization statistics for WPA only.
+
+fmath-errno
+Common Var(flag_errno_math) Init(1) Optimization SetByCombined
+Set errno after built-in math functions.
+
+fmax-errors=
+Common Joined RejectNegative UInteger Var(flag_max_errors)
+-fmax-errors=<number> Maximum number of errors to report.
+
+fmem-report
+Common Var(mem_report)
+Report on permanent memory allocation.
+
+fmem-report-wpa
+Common Var(mem_report_wpa)
+Report on permanent memory allocation in WPA only.
+
+; This will attempt to merge constant section constants, if 1 only
+; string constants and constants from constant pool, if 2 also constant
+; variables.
+fmerge-all-constants
+Common Var(flag_merge_constants,2) Init(1)
+Attempt to merge identical constants and constant variables.
+
+fmerge-constants
+Common Var(flag_merge_constants,1)
+Attempt to merge identical constants across compilation units.
+
+fmerge-debug-strings
+Common Var(flag_merge_debug_strings) Init(1)
+Attempt to merge identical debug strings across compilation units.
+
+fmessage-length=
+Common RejectNegative Joined UInteger
+-fmessage-length=<number> Limit diagnostics to <number> characters per line. 0 suppresses line-wrapping.
+
+fmodulo-sched
+Common Var(flag_modulo_sched) Optimization
+Perform SMS based modulo scheduling before the first scheduling pass.
+
+fmodulo-sched-allow-regmoves
+Common Var(flag_modulo_sched_allow_regmoves) Optimization
+Perform SMS based modulo scheduling with register moves allowed.
+
+fmove-loop-invariants
+Common Var(flag_move_loop_invariants) Optimization
+Move loop invariant computations out of loops.
+
+fmove-loop-stores
+Common Var(flag_move_loop_stores) Optimization
+Move stores out of loops.
+
+fdce
+Common Var(flag_dce) Init(1) Optimization
+Use the RTL dead code elimination pass.
+
+fdse
+Common Var(flag_dse) Init(0) Optimization
+Use the RTL dead store elimination pass.
+
+freschedule-modulo-scheduled-loops
+Common Var(flag_resched_modulo_sched) Optimization
+Enable/Disable the traditional scheduling in loops that already passed modulo scheduling.
+
+fnon-call-exceptions
+Common Var(flag_non_call_exceptions) Optimization
+Support synchronous non-call exceptions.
+
+foffload=
+Driver Joined MissingArgError(targets missing after %qs)
+
+foffload-options=
+Common Driver Joined MissingArgError(options or targets=options missing after %qs)
+-foffload-options=<targets>=<options> Specify options for the offloading targets.
+
+foffload-abi=
+Common Joined RejectNegative Enum(offload_abi)
+-foffload-abi=[lp64|ilp32] Set the ABI to use in an offload compiler.
+
+Enum
+Name(offload_abi) Type(enum offload_abi) UnknownError(unknown offload ABI %qs)
+
+EnumValue
+Enum(offload_abi) String(ilp32) Value(OFFLOAD_ABI_ILP32)
+
+EnumValue
+Enum(offload_abi) String(lp64) Value(OFFLOAD_ABI_LP64)
+
+fomit-frame-pointer
+Common Var(flag_omit_frame_pointer) Optimization
+When possible do not generate stack frames.
+
+fopt-info
+Common Var(flag_opt_info) Optimization
+Enable all optimization info dumps on stderr.
+
+fopt-info-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fopt-info[-<type>=filename] Dump compiler optimization details.
+
+fsave-optimization-record
+Common Var(flag_save_optimization_record) Optimization
+Write a SRCFILE.opt-record.json file detailing what optimizations were performed.
+
+foptimize-register-move
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+foptimize-sibling-calls
+Common Var(flag_optimize_sibling_calls) Optimization
+Optimize sibling and tail recursive calls.
+
+fpartial-inlining
+Common Var(flag_partial_inlining) Optimization
+Perform partial inlining.
+
+fpre-ipa-mem-report
+Common Var(pre_ipa_mem_report)
+Report on memory allocation before interprocedural optimization.
+
+fpost-ipa-mem-report
+Common Var(post_ipa_mem_report)
+Report on memory allocation before interprocedural optimization.
+
+fpack-struct
+Common Var(flag_pack_struct) Optimization
+Pack structure members together without holes.
+
+fpack-struct=
+Common RejectNegative Joined UInteger Optimization
+-fpack-struct=<number> Set initial maximum structure member alignment.
+
+fpcc-struct-return
+Common Var(flag_pcc_struct_return,1) Init(DEFAULT_PCC_STRUCT_RETURN)
+Return small aggregates in memory, not registers.
+
+fpeel-loops
+Common Var(flag_peel_loops) Optimization
+Perform loop peeling.
+
+fpeephole
+Common Var(flag_no_peephole,0) Optimization
+Enable machine specific peephole optimizations.
+
+fpeephole2
+Common Var(flag_peephole2) Optimization
+Enable an RTL peephole pass before sched2.
+
+fPIC
+Common Var(flag_pic,2) Negative(fPIE) Init(-1)
+Generate position-independent code if possible (large mode).
+
+fPIE
+Common Var(flag_pie,2) Negative(fpic) Init(-1)
+Generate position-independent code for executables if possible (large mode).
+
+fpic
+Common Var(flag_pic,1) Negative(fpie) Init(-1)
+Generate position-independent code if possible (small mode).
+
+fpie
+Common Var(flag_pie,1) Negative(fPIC) Init(-1)
+Generate position-independent code for executables if possible (small mode).
+
+fplt
+Common Var(flag_plt) Init(1) Optimization
+Use PLT for PIC calls (-fno-plt: load the address from GOT at call site).
+
+fplugin=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+Specify a plugin to load.
+
+fplugin-arg-
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fplugin-arg-<name>-<key>[=<value>] Specify argument <key>=<value> for plugin <name>.
+
+fpredictive-commoning
+Common Var(flag_predictive_commoning) Optimization
+Run predictive commoning optimization.
+
+fprefetch-loop-arrays
+Common Var(flag_prefetch_loop_arrays) Init(-1) Optimization
+Generate prefetch instructions, if available, for arrays in loops.
+
+fprofile
+Common Var(profile_flag)
+Enable basic program profiling code.
+
+fprofile-abs-path
+Common Var(profile_abs_path_flag)
+Generate absolute source path names for gcov.
+
+fprofile-arcs
+Common Var(profile_arc_flag)
+Insert arc-based program profiling code.
+
+fprofile-dir=
+Common Joined RejectNegative Var(profile_data_prefix)
+Set the top-level directory for storing the profile data.
+The default is 'pwd'.
+
+fprofile-note=
+Common Joined RejectNegative Var(profile_note_location)
+Select the name for storing the profile note file.
+
+fprofile-correction
+Common Var(flag_profile_correction)
+Enable correction of flow inconsistent profile data input.
+
+fprofile-update=
+Common Joined RejectNegative Enum(profile_update) Var(flag_profile_update) Init(PROFILE_UPDATE_SINGLE)
+-fprofile-update=[single|atomic|prefer-atomic] Set the profile update method.
+
+fprofile-filter-files=
+Common Joined RejectNegative Var(flag_profile_filter_files)
+Instrument only functions from files whose name matches any of the regular expressions (separated by semi-colons).
+
+fprofile-exclude-files=
+Common Joined RejectNegative Var(flag_profile_exclude_files)
+Instrument only functions from files whose name does not match any of the regular expressions (separated by semi-colons).
+
+Enum
+Name(profile_reproducibility) Type(enum profile_reproducibility) UnknownError(unknown profile reproducibility method %qs)
+
+EnumValue
+Enum(profile_reproducibility) String(serial) Value(PROFILE_REPRODUCIBILITY_SERIAL)
+
+EnumValue
+Enum(profile_reproducibility) String(parallel-runs) Value(PROFILE_REPRODUCIBILITY_PARALLEL_RUNS)
+
+EnumValue
+Enum(profile_reproducibility) String(multithreaded) Value(PROFILE_REPRODUCIBILITY_MULTITHREADED)
+
+fprofile-reproducible=
+Common Joined RejectNegative Var(flag_profile_reproducible) Enum(profile_reproducibility) Init(PROFILE_REPRODUCIBILITY_SERIAL)
+-fprofile-reproducible=[serial|parallel-runs|multithreaded] Control level of reproducibility of profile gathered by -fprofile-generate.
+
+Enum
+Name(profile_update) Type(enum profile_update) UnknownError(unknown profile update method %qs)
+
+EnumValue
+Enum(profile_update) String(single) Value(PROFILE_UPDATE_SINGLE)
+
+EnumValue
+Enum(profile_update) String(atomic) Value(PROFILE_UPDATE_ATOMIC)
+
+EnumValue
+Enum(profile_update) String(prefer-atomic) Value(PROFILE_UPDATE_PREFER_ATOMIC)
+
+fprofile-prefix-path=
+Common Joined RejectNegative Var(profile_prefix_path)
+Remove prefix from absolute path before mangling name for -fprofile-generate= and -fprofile-use=.
+
+fprofile-prefix-map=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fprofile-prefix-map=<old>=<new> Map one directory name to another in GCOV coverage result.
+
+fprofile-generate
+Common
+Enable common options for generating profile info for profile feedback directed optimizations.
+
+fprofile-generate=
+Common Joined RejectNegative
+Enable common options for generating profile info for profile feedback directed optimizations, and set -fprofile-dir=.
+
+fprofile-info-section
+Common RejectNegative
+Register the profile information in the .gcov_info section instead of using a constructor/destructor.
+
+fprofile-info-section=
+Common Joined RejectNegative Var(profile_info_section)
+Register the profile information in the specified section instead of using a constructor/destructor.
+
+fprofile-partial-training
+Common Var(flag_profile_partial_training) Optimization
+Do not assume that functions never executed during the train run are cold.
+
+fprofile-use
+Common Var(flag_profile_use)
+Enable common options for performing profile feedback directed optimizations.
+
+fprofile-use=
+Common Joined RejectNegative
+Enable common options for performing profile feedback directed optimizations, and set -fprofile-dir=.
+
+fprofile-values
+Common Var(flag_profile_values)
+Insert code to profile values of expressions.
+
+fprofile-report
+Common Var(profile_report)
+Report on consistency of profile.
+
+fprofile-reorder-functions
+Common Var(flag_profile_reorder_functions) Optimization
+Enable function reordering that improves code placement.
+
+fpatchable-function-entry=
+Common Var(flag_patchable_function_entry) Joined Optimization
+Insert NOP instructions at each function entry.
+
+frandom-seed
+Common Var(common_deferred_options) Defer
+
+frandom-seed=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-frandom-seed=<string> Make compile reproducible using <string>.
+
+; This switch causes the command line that was used to create an
+; object file to be recorded into the object file. The exact format
+; of this recording is target and binary file format dependent.
+; It is related to the -fverbose-asm switch, but that switch only
+; records information in the assembler output file as comments, so
+; they never reach the object file.
+frecord-gcc-switches
+Common Var(flag_record_gcc_switches)
+Record gcc command line switches in the object file.
+
+freg-struct-return
+Common Var(flag_pcc_struct_return,0) Optimization
+Return small aggregates in registers.
+
+fregmove
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+flifetime-dse
+Common Var(flag_lifetime_dse,2) Init(2) Optimization
+Tell DSE that the storage for a C++ object is dead when the constructor
+starts and when the destructor finishes.
+
+flifetime-dse=
+Common Joined RejectNegative UInteger Var(flag_lifetime_dse) Optimization IntegerRange(0, 2)
+
+flive-patching
+Common RejectNegative Alias(flive-patching=,inline-clone) Optimization
+
+flive-patching=
+Common Joined RejectNegative Enum(live_patching_level) Var(flag_live_patching) Init(LIVE_PATCHING_NONE) Optimization
+-flive-patching=[inline-only-static|inline-clone] Control IPA
+optimizations to provide a safe compilation for live-patching. At the same
+time, provides multiple-level control on the enabled IPA optimizations.
+
+Enum
+Name(live_patching_level) Type(enum live_patching_level) UnknownError(unknown Live-Patching Level %qs)
+
+EnumValue
+Enum(live_patching_level) String(inline-only-static) Value(LIVE_PATCHING_INLINE_ONLY_STATIC)
+
+EnumValue
+Enum(live_patching_level) String(inline-clone) Value(LIVE_PATCHING_INLINE_CLONE)
+
+fallocation-dce
+Common Var(flag_allocation_dce) Init(1) Optimization
+Tell DCE to remove unused C++ allocations.
+
+flive-range-shrinkage
+Common Var(flag_live_range_shrinkage) Init(0) Optimization
+Relief of register pressure through live range shrinkage.
+
+frename-registers
+Common Var(flag_rename_registers) Optimization EnabledBy(funroll-loops)
+Perform a register renaming optimization pass.
+
+fschedule-fusion
+Common Var(flag_schedule_fusion) Init(2) Optimization
+Perform a target dependent instruction fusion optimization pass.
+
+freorder-blocks
+Common Var(flag_reorder_blocks) Optimization
+Reorder basic blocks to improve code placement.
+
+freorder-blocks-algorithm=
+Common Joined RejectNegative Enum(reorder_blocks_algorithm) Var(flag_reorder_blocks_algorithm) Init(REORDER_BLOCKS_ALGORITHM_SIMPLE) Optimization
+-freorder-blocks-algorithm=[simple|stc] Set the used basic block reordering algorithm.
+
+Enum
+Name(reorder_blocks_algorithm) Type(enum reorder_blocks_algorithm) UnknownError(unknown basic block reordering algorithm %qs)
+
+EnumValue
+Enum(reorder_blocks_algorithm) String(simple) Value(REORDER_BLOCKS_ALGORITHM_SIMPLE)
+
+EnumValue
+Enum(reorder_blocks_algorithm) String(stc) Value(REORDER_BLOCKS_ALGORITHM_STC)
+
+freorder-blocks-and-partition
+Common Var(flag_reorder_blocks_and_partition) Optimization
+Reorder basic blocks and partition into hot and cold sections.
+
+freorder-functions
+Common Var(flag_reorder_functions) Optimization
+Reorder functions to improve code placement.
+
+frerun-cse-after-loop
+Common Var(flag_rerun_cse_after_loop) Optimization
+Add a common subexpression elimination pass after loop optimizations.
+
+frerun-loop-opt
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+frounding-math
+Common Var(flag_rounding_math) Optimization SetByCombined
+Disable optimizations that assume default FP rounding behavior.
+
+fsched-interblock
+Common Var(flag_schedule_interblock) Init(1) Optimization
+Enable scheduling across basic blocks.
+
+fsched-pressure
+Common Var(flag_sched_pressure) Init(0) Optimization
+Enable register pressure sensitive insn scheduling.
+
+fsched-spec
+Common Var(flag_schedule_speculative) Init(1) Optimization
+Allow speculative motion of non-loads.
+
+fsched-spec-load
+Common Var(flag_schedule_speculative_load) Optimization
+Allow speculative motion of some loads.
+
+fsched-spec-load-dangerous
+Common Var(flag_schedule_speculative_load_dangerous) Optimization
+Allow speculative motion of more loads.
+
+fsched-verbose=
+Common RejectNegative Joined UInteger Var(sched_verbose_param) Init(1)
+-fsched-verbose=<number> Set the verbosity level of the scheduler.
+
+fsched2-use-superblocks
+Common Var(flag_sched2_use_superblocks) Optimization
+If scheduling post reload, do superblock scheduling.
+
+fsched2-use-traces
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fschedule-insns
+Common Var(flag_schedule_insns) Optimization
+Reschedule instructions before register allocation.
+
+fschedule-insns2
+Common Var(flag_schedule_insns_after_reload) Optimization
+Reschedule instructions after register allocation.
+
+; This flag should be on when a target implements non-trivial
+; scheduling hooks, maybe saving some information for its own sake.
+; On IA64, for example, this is used for correct bundling.
+fselective-scheduling
+Common Var(flag_selective_scheduling) Optimization
+Schedule instructions using selective scheduling algorithm.
+
+fselective-scheduling2
+Common Var(flag_selective_scheduling2) Optimization
+Run selective scheduling after reload.
+
+fself-test=
+Common Undocumented Joined Var(flag_self_test)
+Run self-tests, using the given path to locate test files.
+
+fsel-sched-pipelining
+Common Var(flag_sel_sched_pipelining) Init(0) Optimization
+Perform software pipelining of inner loops during selective scheduling.
+
+fsel-sched-pipelining-outer-loops
+Common Var(flag_sel_sched_pipelining_outer_loops) Init(0) Optimization
+Perform software pipelining of outer loops during selective scheduling.
+
+fsel-sched-reschedule-pipelined
+Common Var(flag_sel_sched_reschedule_pipelined) Init(0) Optimization
+Reschedule pipelined regions without pipelining.
+
+fsemantic-interposition
+Common Var(flag_semantic_interposition) Init(1) Optimization
+Allow interposing function (or variables) by ones with different semantics (or initializer) respectively by dynamic linker.
+
+; sched_stalled_insns means that insns can be moved prematurely from the queue
+; of stalled insns into the ready list.
+fsched-stalled-insns
+Common Var(flag_sched_stalled_insns) Optimization UInteger
+Allow premature scheduling of queued insns.
+
+fsched-stalled-insns=
+Common RejectNegative Joined UInteger Optimization
+-fsched-stalled-insns=<number> Set number of queued insns that can be prematurely scheduled.
+
+; sched_stalled_insns_dep controls how many recently scheduled cycles will
+; be examined for a dependency on a stalled insn that is candidate for
+; premature removal from the queue of stalled insns into the ready list (has
+; an effect only if the flag 'sched_stalled_insns' is set).
+fsched-stalled-insns-dep
+Common Var(flag_sched_stalled_insns_dep,1) Init(1) Optimization UInteger
+Set dependence distance checking in premature scheduling of queued insns.
+
+fsched-stalled-insns-dep=
+Common RejectNegative Joined UInteger Optimization
+-fsched-stalled-insns-dep=<number> Set dependence distance checking in premature scheduling of queued insns.
+
+fsched-group-heuristic
+Common Var(flag_sched_group_heuristic) Init(1) Optimization
+Enable the group heuristic in the scheduler.
+
+fsched-critical-path-heuristic
+Common Var(flag_sched_critical_path_heuristic) Init(1) Optimization
+Enable the critical path heuristic in the scheduler.
+
+fsched-spec-insn-heuristic
+Common Var(flag_sched_spec_insn_heuristic) Init(1) Optimization
+Enable the speculative instruction heuristic in the scheduler.
+
+fsched-rank-heuristic
+Common Var(flag_sched_rank_heuristic) Init(1) Optimization
+Enable the rank heuristic in the scheduler.
+
+fsched-last-insn-heuristic
+Common Var(flag_sched_last_insn_heuristic) Init(1) Optimization
+Enable the last instruction heuristic in the scheduler.
+
+fsched-dep-count-heuristic
+Common Var(flag_sched_dep_count_heuristic) Init(1) Optimization
+Enable the dependent count heuristic in the scheduler.
+
+fsection-anchors
+Common Var(flag_section_anchors) Optimization
+Access data in the same section from shared anchor points.
+
+fsee
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fzee
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+free
+Common Var(flag_ree) Init(0) Optimization
+Turn on Redundant Extensions Elimination pass.
+
+fshow-column
+Common Var(flag_show_column) Init(1)
+Show column numbers in diagnostics, when available. Default on.
+
+fshrink-wrap
+Common Var(flag_shrink_wrap) Optimization
+Emit function prologues only before parts of the function that need it,
+rather than at the top of the function.
+
+fshrink-wrap-separate
+Common Var(flag_shrink_wrap_separate) Init(1) Optimization
+Shrink-wrap parts of the prologue and epilogue separately.
+
+fsignaling-nans
+Common Var(flag_signaling_nans) Optimization SetByCombined
+Disable optimizations observable by IEEE signaling NaNs.
+
+fsigned-zeros
+Common Var(flag_signed_zeros) Init(1) Optimization SetByCombined
+Disable floating point optimizations that ignore the IEEE signedness of zero.
+
+fsingle-precision-constant
+Common Var(flag_single_precision_constant) Optimization
+Convert floating point constants to single precision constants.
+
+fsplit-ivs-in-unroller
+Common Var(flag_split_ivs_in_unroller) Init(1) Optimization
+Split lifetimes of induction variables when loops are unrolled.
+
+fsplit-stack
+Common Var(flag_split_stack) Init(-1)
+Generate discontiguous stack frames.
+
+fsplit-wide-types
+Common Var(flag_split_wide_types) Optimization
+Split wide types into independent registers.
+
+fsplit-wide-types-early
+Common Var(flag_split_wide_types_early) Optimization
+Split wide types into independent registers earlier.
+
+fssa-backprop
+Common Var(flag_ssa_backprop) Init(1) Optimization
+Enable backward propagation of use properties at the SSA level.
+
+fssa-phiopt
+Common Var(flag_ssa_phiopt) Optimization
+Optimize conditional patterns using SSA PHI nodes.
+
+fstdarg-opt
+Common Var(flag_stdarg_opt) Init(1) Optimization
+Optimize amount of stdarg registers saved to stack at start of function.
+
+fvariable-expansion-in-unroller
+Common Var(flag_variable_expansion_in_unroller) Optimization
+Apply variable expansion when loops are unrolled.
+
+fstack-check=
+Common RejectNegative Joined Optimization
+-fstack-check=[no|generic|specific] Insert stack checking code into the program.
+
+fstack-check
+Common Alias(fstack-check=, specific, no)
+Insert stack checking code into the program. Same as -fstack-check=specific.
+
+fstack-clash-protection
+Common Var(flag_stack_clash_protection) Optimization
+Insert code to probe each page of stack space as it is allocated to protect
+from stack-clash style attacks.
+
+fstack-limit
+Common Var(common_deferred_options) Defer
+
+fstack-limit-register=
+Common RejectNegative Joined Var(common_deferred_options) Defer
+-fstack-limit-register=<register> Trap if the stack goes past <register>.
+
+fstack-limit-symbol=
+Common RejectNegative Joined Var(common_deferred_options) Defer
+-fstack-limit-symbol=<name> Trap if the stack goes past symbol <name>.
+
+fstack-protector
+Common Var(flag_stack_protect, 1) Init(-1) Optimization
+Use propolice as a stack protection method.
+
+fstack-protector-all
+Common RejectNegative Var(flag_stack_protect, 2) Init(-1) Optimization
+Use a stack protection method for every function.
+
+fstack-protector-strong
+Common RejectNegative Var(flag_stack_protect, 3) Init(-1) Optimization
+Use a smart stack protection method for certain functions.
+
+fstack-protector-explicit
+Common RejectNegative Var(flag_stack_protect, 4) Optimization
+Use stack protection method only for functions with the stack_protect attribute.
+
+fstack-usage
+Common RejectNegative Var(flag_stack_usage)
+Output stack usage information on a per-function basis.
+
+fstrength-reduce
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+; Nonzero if we should do (language-dependent) alias analysis.
+; Typically, this analysis will assume that expressions of certain
+; types do not alias expressions of certain other types. Only used
+; if alias analysis (in general) is enabled.
+fstrict-aliasing
+Common Var(flag_strict_aliasing) Optimization
+Assume strict aliasing rules apply.
+
+fstrict-overflow
+Common
+Treat signed overflow as undefined. Negated as -fwrapv -fwrapv-pointer.
+
+fsync-libcalls
+Common Var(flag_sync_libcalls) Init(1)
+Implement __atomic operations via libcalls to legacy __sync functions.
+
+fsyntax-only
+Common Var(flag_syntax_only)
+Check for syntax errors, then stop.
+
+ftest-coverage
+Common Var(flag_test_coverage)
+Create data files needed by \"gcov\".
+
+fthread-jumps
+Common Var(flag_thread_jumps) Optimization
+Perform jump threading optimizations.
+
+ftime-report
+Common Var(time_report)
+Report the time taken by each compiler pass.
+
+ftime-report-details
+Common Var(time_report_details)
+Record times taken by sub-phases separately.
+
+ftls-model=
+Common Joined RejectNegative Enum(tls_model) Var(flag_tls_default) Init(TLS_MODEL_GLOBAL_DYNAMIC)
+-ftls-model=[global-dynamic|local-dynamic|initial-exec|local-exec] Set the default thread-local storage code generation model.
+
+Enum
+Name(tls_model) Type(enum tls_model) UnknownError(unknown TLS model %qs)
+
+EnumValue
+Enum(tls_model) String(global-dynamic) Value(TLS_MODEL_GLOBAL_DYNAMIC)
+
+EnumValue
+Enum(tls_model) String(local-dynamic) Value(TLS_MODEL_LOCAL_DYNAMIC)
+
+EnumValue
+Enum(tls_model) String(initial-exec) Value(TLS_MODEL_INITIAL_EXEC)
+
+EnumValue
+Enum(tls_model) String(local-exec) Value(TLS_MODEL_LOCAL_EXEC)
+
+ftoplevel-reorder
+Common Var(flag_toplevel_reorder) Init(2) Optimization
+Reorder top level functions, variables, and asms.
+
+ftracer
+Common Var(flag_tracer) Optimization
+Perform superblock formation via tail duplication.
+
+ftrampolines
+Common Var(flag_trampolines) Init(0)
+For targets that normally need trampolines for nested functions, always
+generate them instead of using descriptors.
+
+; Zero means that floating-point math operations cannot generate a
+; (user-visible) trap. This is the case, for example, in nonstop
+; IEEE 754 arithmetic.
+ftrapping-math
+Common Var(flag_trapping_math) Init(1) Optimization SetByCombined
+Assume floating-point operations can trap.
+
+ftrapv
+Common Var(flag_trapv) Optimization
+Trap for signed overflow in addition, subtraction and multiplication.
+
+ftree-ccp
+Common Var(flag_tree_ccp) Optimization
+Enable SSA-CCP optimization on trees.
+
+ftree-bit-ccp
+Common Var(flag_tree_bit_ccp) Optimization
+Enable SSA-BIT-CCP optimization on trees.
+
+ftree-store-ccp
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+ftree-ch
+Common Var(flag_tree_ch) Optimization
+Enable loop header copying on trees.
+
+ftree-coalesce-inlined-vars
+Common Ignore RejectNegative
+Does nothing. Preserved for backward compatibility.
+
+ftree-coalesce-vars
+Common Var(flag_tree_coalesce_vars) Optimization
+Enable SSA coalescing of user variables.
+
+ftree-copyrename
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+ftree-copy-prop
+Common Var(flag_tree_copy_prop) Optimization
+Enable copy propagation on trees.
+
+ftree-store-copy-prop
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+ftree-cselim
+Common Var(flag_tree_cselim) Optimization
+Transform condition stores into unconditional ones.
+
+ftree-switch-conversion
+Common Var(flag_tree_switch_conversion) Optimization
+Perform conversions of switch initializations.
+
+ftree-dce
+Common Var(flag_tree_dce) Optimization
+Enable SSA dead code elimination optimization on trees.
+
+ftree-dominator-opts
+Common Var(flag_tree_dom) Optimization
+Enable dominator optimizations.
+
+ftree-tail-merge
+Common Var(flag_tree_tail_merge) Optimization
+Enable tail merging on trees.
+
+ftree-dse
+Common Var(flag_tree_dse) Optimization
+Enable dead store elimination.
+
+ftree-forwprop
+Common Var(flag_tree_forwprop) Init(1) Optimization
+Enable forward propagation on trees.
+
+ftree-fre
+Common Var(flag_tree_fre) Optimization
+Enable Full Redundancy Elimination (FRE) on trees.
+
+foptimize-strlen
+Common Var(flag_optimize_strlen) Optimization
+Enable string length optimizations on trees.
+
+fisolate-erroneous-paths-dereference
+Common Var(flag_isolate_erroneous_paths_dereference) Optimization
+Detect paths that trigger erroneous or undefined behavior due to
+dereferencing a null pointer. Isolate those paths from the main control
+flow and turn the statement with erroneous or undefined behavior into a trap.
+
+fisolate-erroneous-paths-attribute
+Common Var(flag_isolate_erroneous_paths_attribute) Optimization
+Detect paths that trigger erroneous or undefined behavior due to a null value
+being used in a way forbidden by a returns_nonnull or nonnull
+attribute. Isolate those paths from the main control flow and turn the
+statement with erroneous or undefined behavior into a trap.
+
+ftree-loop-distribution
+Common Var(flag_tree_loop_distribution) Optimization
+Enable loop distribution on trees.
+
+ftree-loop-distribute-patterns
+Common Var(flag_tree_loop_distribute_patterns) Optimization
+Enable loop distribution for patterns transformed into a library call.
+
+ftree-loop-im
+Common Var(flag_tree_loop_im) Init(1) Optimization
+Enable loop invariant motion on trees.
+
+ftree-loop-linear
+Common Alias(floop-nest-optimize)
+Enable loop nest transforms. Same as -floop-nest-optimize.
+
+ftree-loop-ivcanon
+Common Var(flag_tree_loop_ivcanon) Init(1) Optimization
+Create canonical induction variables in loops.
+
+ftree-loop-optimize
+Common Var(flag_tree_loop_optimize) Init(1) Optimization
+Enable loop optimizations on tree level.
+
+ftree-parallelize-loops=
+Common Joined RejectNegative UInteger Var(flag_tree_parallelize_loops) Init(1) Optimization
+-ftree-parallelize-loops=<number> Enable automatic parallelization of loops.
+
+ftree-phiprop
+Common Var(flag_tree_phiprop) Init(1) Optimization
+Enable hoisting loads from conditional pointers.
+
+ftree-pre
+Common Var(flag_tree_pre) Optimization
+Enable SSA-PRE optimization on trees.
+
+ftree-partial-pre
+Common Var(flag_tree_partial_pre) Optimization
+In SSA-PRE optimization on trees, enable partial-partial redundancy elimination.
+
+ftree-pta
+Common Var(flag_tree_pta) Optimization
+Perform function-local points-to analysis on trees.
+
+ftree-reassoc
+Common Var(flag_tree_reassoc) Init(1) Optimization
+Enable reassociation on tree level.
+
+ftree-salias
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+ftree-sink
+Common Var(flag_tree_sink) Optimization
+Enable SSA code sinking on trees.
+
+ftree-slsr
+Common Var(flag_tree_slsr) Optimization
+Perform straight-line strength reduction.
+
+ftree-sra
+Common Var(flag_tree_sra) Optimization
+Perform scalar replacement of aggregates.
+
+ftree-ter
+Common Var(flag_tree_ter) Optimization
+Replace temporary expressions in the SSA->normal pass.
+
+ftree-lrs
+Common Var(flag_tree_live_range_split) Optimization
+Perform live range splitting during the SSA->normal pass.
+
+ftree-vrp
+Common Var(flag_tree_vrp) Init(0) Optimization
+Perform Value Range Propagation on trees.
+
+fsplit-paths
+Common Var(flag_split_paths) Init(0) Optimization
+Split paths leading to loop backedges.
+
+funconstrained-commons
+Common Var(flag_unconstrained_commons) Optimization
+Assume common declarations may be overridden with ones with a larger
+trailing array.
+
+funit-at-a-time
+Common Var(flag_unit_at_a_time) Init(1)
+Compile whole compilation unit at a time.
+
+funroll-loops
+Common Var(flag_unroll_loops) Optimization EnabledBy(funroll-all-loops)
+Perform loop unrolling when iteration count is known.
+
+funroll-all-loops
+Common Var(flag_unroll_all_loops) Optimization
+Perform loop unrolling for all loops.
+
+funroll-completely-grow-size
+Undocumented Var(flag_cunroll_grow_size) Optimization
+; Internal undocumented flag, allow size growth during complete unrolling
+
+; Nonzero means that loop optimizer may assume that the induction variables
+; that control loops do not overflow and that the loops with nontrivial
+; exit condition are not infinite
+funsafe-loop-optimizations
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+fassociative-math
+Common Var(flag_associative_math) SetByCombined Optimization
+Allow optimization for floating-point arithmetic which may change the
+result of the operation due to rounding.
+
+freciprocal-math
+Common Var(flag_reciprocal_math) SetByCombined Optimization
+Same as -fassociative-math for expressions which include division.
+
+; Nonzero means that unsafe floating-point math optimizations are allowed
+; for the sake of speed. IEEE compliance is not guaranteed, and operations
+; are allowed to assume that their arguments and results are "normal"
+; (e.g., nonnegative for SQRT).
+funsafe-math-optimizations
+Common Var(flag_unsafe_math_optimizations) Optimization SetByCombined
+Allow math optimizations that may violate IEEE or ISO standards.
+
+funswitch-loops
+Common Var(flag_unswitch_loops) Optimization
+Perform loop unswitching.
+
+fsplit-loops
+Common Var(flag_split_loops) Optimization
+Perform loop splitting.
+
+fversion-loops-for-strides
+Common Var(flag_version_loops_for_strides) Optimization
+Version loops based on whether indices have a stride of one.
+
+funwind-tables
+Common Var(flag_unwind_tables) Optimization
+Just generate unwind tables for exception handling.
+
+fuse-ld=bfd
+Common Driver Negative(fuse-ld=gold)
+Use the bfd linker instead of the default linker.
+
+fuse-ld=gold
+Common Driver Negative(fuse-ld=bfd)
+Use the gold linker instead of the default linker.
+
+fuse-ld=lld
+Common Driver Negative(fuse-ld=lld)
+Use the lld LLVM linker instead of the default linker.
+
+fuse-ld=mold
+Common Driver Negative(fuse-ld=mold)
+Use the Modern linker (MOLD) linker instead of the default linker.
+
+fuse-linker-plugin
+Common Undocumented Var(flag_use_linker_plugin)
+
+; Positive if we should track variables, negative if we should run
+; the var-tracking pass only to discard debug annotations, zero if
+; we're not to run it.
+fvar-tracking
+Common Var(flag_var_tracking) PerFunction EnabledBy(fvar-tracking-uninit)
+Perform variable tracking.
+
+; Positive if we should track variables at assignments, negative if
+; we should run the var-tracking pass only to discard debug
+; annotations.
+fvar-tracking-assignments
+Common Var(flag_var_tracking_assignments) PerFunction
+Perform variable tracking by annotating assignments.
+
+; Nonzero if we should toggle flag_var_tracking_assignments after
+; processing options and computing its default. */
+fvar-tracking-assignments-toggle
+Common Var(flag_var_tracking_assignments_toggle) PerFunction
+Toggle -fvar-tracking-assignments.
+
+; Positive if we should track uninitialized variables, negative if
+; we should run the var-tracking pass only to discard debug
+; annotations.
+fvar-tracking-uninit
+Common Var(flag_var_tracking_uninit) PerFunction
+Perform variable tracking and also tag variables that are uninitialized.
+
+; Alias to enable both -ftree-loop-vectorize and -ftree-slp-vectorize.
+ftree-vectorize
+Common Var(flag_tree_vectorize) Optimization
+Enable vectorization on trees.
+
+ftree-vectorizer-verbose=
+Common Joined RejectNegative Ignore
+Does nothing. Preserved for backward compatibility.
+
+ftree-loop-vectorize
+Common Var(flag_tree_loop_vectorize) Optimization EnabledBy(ftree-vectorize)
+Enable loop vectorization on trees.
+
+ftree-slp-vectorize
+Common Var(flag_tree_slp_vectorize) Optimization EnabledBy(ftree-vectorize)
+Enable basic block vectorization (SLP) on trees.
+
+fvect-cost-model=
+Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Optimization
+-fvect-cost-model=[unlimited|dynamic|cheap|very-cheap] Specifies the cost model for vectorization.
+
+fsimd-cost-model=
+Common Joined RejectNegative Enum(vect_cost_model) Var(flag_simd_cost_model) Init(VECT_COST_MODEL_UNLIMITED) Optimization
+-fsimd-cost-model=[unlimited|dynamic|cheap|very-cheap] Specifies the vectorization cost model for code marked with a simd directive.
+
+Enum
+Name(vect_cost_model) Type(enum vect_cost_model) UnknownError(unknown vectorizer cost model %qs)
+
+EnumValue
+Enum(vect_cost_model) String(unlimited) Value(VECT_COST_MODEL_UNLIMITED)
+
+EnumValue
+Enum(vect_cost_model) String(dynamic) Value(VECT_COST_MODEL_DYNAMIC)
+
+EnumValue
+Enum(vect_cost_model) String(cheap) Value(VECT_COST_MODEL_CHEAP)
+
+EnumValue
+Enum(vect_cost_model) String(very-cheap) Value(VECT_COST_MODEL_VERY_CHEAP)
+
+fvect-cost-model
+Common Alias(fvect-cost-model=,dynamic,unlimited)
+Enables the dynamic vectorizer cost model. Preserved for backward compatibility.
+
+ftree-vect-loop-version
+Common Ignore
+Does nothing. Preserved for backward compatibility.
+
+ftree-scev-cprop
+Common Var(flag_tree_scev_cprop) Init(1) Optimization
+Enable copy propagation of scalar-evolution information.
+
+ftrivial-auto-var-init=
+Common Joined RejectNegative Enum(auto_init_type) Var(flag_auto_var_init) Init(AUTO_INIT_UNINITIALIZED) Optimization
+-ftrivial-auto-var-init=[uninitialized|pattern|zero] Add initializations to automatic variables.
+
+Enum
+Name(auto_init_type) Type(enum auto_init_type) UnknownError(unrecognized automatic variable initialization type %qs)
+
+EnumValue
+Enum(auto_init_type) String(uninitialized) Value(AUTO_INIT_UNINITIALIZED)
+
+EnumValue
+Enum(auto_init_type) String(pattern) Value(AUTO_INIT_PATTERN)
+
+EnumValue
+Enum(auto_init_type) String(zero) Value(AUTO_INIT_ZERO)
+
+; -fverbose-asm causes extra commentary information to be produced in
+; the generated assembly code (to make it more readable). This option
+; is generally only of use to those who actually need to read the
+; generated assembly code (perhaps while debugging the compiler itself).
+; -fno-verbose-asm, the default, causes the extra information
+; to not be added and is useful when comparing two assembler files.
+fverbose-asm
+Common Var(flag_verbose_asm)
+Add extra commentary to assembler output.
+
+fvisibility=
+Common Joined RejectNegative Enum(symbol_visibility) Var(default_visibility) Init(VISIBILITY_DEFAULT)
+-fvisibility=[default|internal|hidden|protected] Set the default symbol visibility.
+
+Enum
+Name(symbol_visibility) Type(enum symbol_visibility) UnknownError(unrecognized visibility value %qs)
+
+EnumValue
+Enum(symbol_visibility) String(default) Value(VISIBILITY_DEFAULT)
+
+EnumValue
+Enum(symbol_visibility) String(internal) Value(VISIBILITY_INTERNAL)
+
+EnumValue
+Enum(symbol_visibility) String(hidden) Value(VISIBILITY_HIDDEN)
+
+EnumValue
+Enum(symbol_visibility) String(protected) Value(VISIBILITY_PROTECTED)
+
+fvtable-verify=
+Common Joined RejectNegative Enum(vtv_priority) Var(flag_vtable_verify) Init(VTV_NO_PRIORITY)
+Validate vtable pointers before using them.
+
+Enum
+Name(vtv_priority) Type(enum vtv_priority) UnknownError(unknown vtable verify initialization priority %qs)
+
+EnumValue
+Enum(vtv_priority) String(none) Value(VTV_NO_PRIORITY)
+
+EnumValue
+Enum(vtv_priority) String(std) Value(VTV_STANDARD_PRIORITY)
+
+EnumValue
+Enum(vtv_priority) String(preinit) Value(VTV_PREINIT_PRIORITY)
+
+fvtv-counts
+Common Var(flag_vtv_counts)
+Output vtable verification counters.
+
+fvtv-debug
+Common Var(flag_vtv_debug)
+Output vtable verification pointer sets information.
+
+fvpt
+Common Var(flag_value_profile_transformations) Optimization
+Use expression value profiles in optimizations.
+
+fweb
+Common Var(flag_web) Optimization EnabledBy(funroll-loops)
+Construct webs and split unrelated uses of single variable.
+
+ftree-builtin-call-dce
+Common Var(flag_tree_builtin_call_dce) Init(0) Optimization
+Enable conditional dead code elimination for builtin calls.
+
+fwhole-program
+Common Var(flag_whole_program) Init(0)
+Perform whole program optimizations.
+
+fwrapv-pointer
+Common Var(flag_wrapv_pointer) Optimization
+Assume pointer overflow wraps around.
+
+fwrapv
+Common Var(flag_wrapv) Optimization
+Assume signed arithmetic overflow wraps around.
+
+fzero-initialized-in-bss
+Common Var(flag_zero_initialized_in_bss) Init(1)
+Put zero initialized data in the bss section.
+
+fzero-call-used-regs=
+Common RejectNegative Joined
+Clear call-used registers upon function return.
+
+g
+Common Driver RejectNegative JoinedOrMissing
+Generate debug information in default format.
+
+gas-loc-support
+Common Driver Var(dwarf2out_as_loc_support)
+Assume assembler support for (DWARF2+) .loc directives.
+
+gas-locview-support
+Common Driver Var(dwarf2out_as_locview_support)
+Assume assembler support for view in (DWARF2+) .loc directives.
+
+gcoff
+Common Driver WarnRemoved
+Does nothing. Preserved for backward compatibility.
+
+gcoff1
+Common Driver WarnRemoved
+Does nothing. Preserved for backward compatibility.
+
+gcoff2
+Common Driver WarnRemoved
+Does nothing. Preserved for backward compatibility.
+
+gcoff3
+Common Driver WarnRemoved
+Does nothing. Preserved for backward compatibility.
+
+gcolumn-info
+Common Driver Var(debug_column_info,1) Init(1)
+Record DW_AT_decl_column and DW_AT_call_column in DWARF.
+
+; The CTF generation process feeds off DWARF dies. This option implicitly
+; updates the debug_info_level to DINFO_LEVEL_NORMAL.
+gctf
+Common Driver RejectNegative JoinedOrMissing
+Generate CTF debug information at default level.
+
+gbtf
+Common Driver RejectNegative JoinedOrMissing
+Generate BTF debug information at default level.
+
+gdwarf
+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)
+Generate debug information in DWARF v2 (or later) format.
+
+gdwarf32
+Common Driver Var(dwarf_offset_size,4) Init(4) RejectNegative
+Use 32-bit DWARF format when emitting DWARF debug information.
+
+gdwarf64
+Common Driver Var(dwarf_offset_size,8) RejectNegative
+Use 64-bit DWARF format when emitting DWARF debug information.
+
+ggdb
+Common Driver JoinedOrMissing
+Generate debug information in default extended format.
+
+ginline-points
+Common Driver Var(debug_inline_points)
+Generate extended entry point information for inlined functions.
+
+ginternal-reset-location-views
+Common Driver Var(debug_internal_reset_location_views) Init(2)
+Compute locview reset points based on insn length estimates.
+
+gno-
+RejectNegative Joined Undocumented
+; Catch the gno- prefix, so it doesn't backtrack to g<level>.
+
+gno-pubnames
+Common Driver Negative(gpubnames) Var(debug_generate_pub_sections, 0) Init(-1)
+Don't generate DWARF pubnames and pubtypes sections.
+
+gpubnames
+Common Driver Negative(ggnu-pubnames) Var(debug_generate_pub_sections, 1)
+Generate DWARF pubnames and pubtypes sections.
+
+ggnu-pubnames
+Common Driver Negative(gno-pubnames) Var(debug_generate_pub_sections, 2)
+Generate DWARF pubnames and pubtypes sections with GNU extensions.
+
+grecord-gcc-switches
+Common Driver Var(dwarf_record_gcc_switches) Init(1)
+Record gcc command line switches in DWARF DW_AT_producer.
+
+gsplit-dwarf
+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.
+
+gstabs+
+Common Driver JoinedOrMissing Negative(gvms)
+Generate debug information in extended STABS format.
+
+gstatement-frontiers
+Common Driver Var(debug_nonbind_markers_p) PerFunction
+Emit progressive recommended breakpoint locations.
+
+gstrict-dwarf
+Common Driver Var(dwarf_strict) Init(0)
+Don't emit DWARF additions beyond selected version.
+
+gdescribe-dies
+Common Driver Var(flag_describe_dies) Init(0)
+Add description attributes to some DWARF DIEs that have no name attribute.
+
+gtoggle
+Common Driver Var(flag_gtoggle)
+Toggle debug information generation.
+
+gvariable-location-views
+Common Driver Var(debug_variable_location_views, 1)
+Augment variable location lists with progressive views.
+
+gvariable-location-views=incompat5
+Common Driver RejectNegative Var(debug_variable_location_views, -1) Init(2)
+
+gvms
+Common Driver JoinedOrMissing Negative(gxcoff)
+Generate debug information in VMS format.
+
+gxcoff
+Common Driver JoinedOrMissing Negative(gxcoff+)
+Generate debug information in XCOFF format.
+
+gxcoff+
+Common Driver JoinedOrMissing Negative(gdwarf)
+Generate debug information in extended XCOFF format.
+
+Enum
+Name(compressed_debug_sections) Type(int)
+
+; Since -gz= is completely handled in specs, the values aren't used and we
+; assign arbitrary constants.
+EnumValue
+Enum(compressed_debug_sections) String(none) Value(0)
+
+EnumValue
+Enum(compressed_debug_sections) String(zlib) Value(1)
+
+EnumValue
+Enum(compressed_debug_sections) String(zlib-gnu) Value(2)
+
+gz
+Common Driver
+Generate compressed debug sections.
+
+gz=
+Common Driver RejectNegative Joined Enum(compressed_debug_sections)
+-gz=<format> Generate compressed debug sections in format <format>.
+
+h
+Driver Joined Separate
+
+iplugindir=
+Common Joined Var(plugindir_string) Init(0)
+-iplugindir=<dir> Set <dir> to be the default plugin directory.
+
+imultiarch
+Common Joined Separate RejectDriver Var(imultiarch) Init(0)
+-imultiarch <dir> Set <dir> to be the multiarch include subdirectory.
+
+l
+Driver Joined Separate
+
+n
+Driver
+
+no-canonical-prefixes
+Driver
+
+nodefaultlibs
+Driver
+
+nostartfiles
+Driver
+
+nolibc
+Driver
+
+nostdlib
+Driver
+
+o
+Common Driver Joined Separate Var(asm_file_name) MissingArgError(missing filename after %qs)
+-o <file> Place output into <file>.
+
+p
+Common Var(profile_flag)
+Enable function profiling.
+
+pass-exit-codes
+Driver Var(pass_exit_codes)
+
+pedantic
+Common Alias(Wpedantic)
+
+pedantic-errors
+Common Var(flag_pedantic_errors)
+Like -pedantic but issue them as errors.
+
+pg
+Driver
+
+pipe
+Driver Var(use_pipes)
+
+print-file-name=
+Driver JoinedOrMissing Var(print_file_name)
+
+print-libgcc-file-name
+Driver
+
+print-multi-directory
+Driver Var(print_multi_directory)
+
+print-multi-lib
+Driver Var(print_multi_lib)
+
+print-multi-os-directory
+Driver Var(print_multi_os_directory)
+
+print-multiarch
+Driver Var(print_multiarch)
+
+print-prog-name=
+Driver JoinedOrMissing Var(print_prog_name)
+
+print-search-dirs
+Driver Var(print_search_dirs)
+
+print-sysroot
+Driver Var(print_sysroot)
+
+print-sysroot-headers-suffix
+Driver Var(print_sysroot_headers_suffix)
+
+quiet
+Common Var(quiet_flag) RejectDriver
+Do not display functions compiled or elapsed time.
+
+r
+Driver
+
+s
+Driver
+
+save-temps
+Driver
+
+save-temps=
+Driver Joined
+
+t
+Driver
+
+time
+Driver Var(report_times)
+
+time=
+Driver JoinedOrMissing
+
+u
+Driver Joined Separate
+
+undef
+Driver
+; C option, but driver must not handle as "-u ndef".
+
+v
+Common Driver Var(verbose_flag)
+Enable verbose output.
+
+version
+Common Var(version_flag) RejectDriver
+Display the compiler's version.
+
+w
+Common Var(inhibit_warnings)
+Suppress warnings.
+
+wrapper
+Driver Separate Var(wrapper_string)
+
+x
+Driver Joined Separate
+
+shared
+Driver RejectNegative Negative(static-pie)
+Create a shared library.
+
+shared-libgcc
+Driver
+
+specs
+Driver Separate Alias(specs=)
+
+specs=
+Driver Joined
+
+static
+Driver
+
+static-libgcc
+Driver
+
+static-libgfortran
+Driver
+; Documented for Fortran, but always accepted by driver.
+
+static-libphobos
+Driver
+; Documented for D, but always accepted by driver.
+
+static-libstdc++
+Driver
+
+static-libgo
+Driver
+; Documented for Go, but always accepted by driver.
+
+static-libasan
+Driver
+
+static-libhwasan
+Driver
+
+static-libtsan
+Driver
+
+static-liblsan
+Driver
+
+static-libubsan
+Driver
+
+symbolic
+Driver
+
+no-pie
+Driver RejectNegative Negative(shared)
+Don't create a dynamically linked position independent executable.
+
+pie
+Driver RejectNegative Negative(no-pie)
+Create a dynamically linked position independent executable.
+
+static-pie
+Driver RejectNegative Negative(pie)
+Create a static position independent executable.
+
+z
+Driver Joined Separate
+
+fipa-ra
+Common Var(flag_ipa_ra) Optimization
+Use caller save register across calls if possible.
+
+; This comment is to ensure we retain the blank line above.
diff --git a/support/cpp/gcc/common/common-target-def.h b/support/cpp/gcc/common/common-target-def.h
new file mode 100644
index 000000000..ab39f30e2
--- /dev/null
+++ b/support/cpp/gcc/common/common-target-def.h
@@ -0,0 +1,20 @@
+/* Default initializers for common target hooks.
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "common/common-target-hooks-def.h"
+#include "hooks.h"
+#include "common/common-targhooks.h"
diff --git a/support/cpp/gcc/common/common-target-hooks-def.h b/support/cpp/gcc/common/common-target-hooks-def.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/support/cpp/gcc/common/common-target-hooks-def.h
diff --git a/support/cpp/gcc/common/common-target.def b/support/cpp/gcc/common/common-target.def
new file mode 100644
index 000000000..c4d1144c4
--- /dev/null
+++ b/support/cpp/gcc/common/common-target.def
@@ -0,0 +1,111 @@
+/* Target hook definitions for common hooks.
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* See target-hooks-macros.h for details of macros that should be
+ provided by the including file, and how to use them here. */
+#include "target-hooks-macros.h"
+
+#undef HOOK_TYPE
+#define HOOK_TYPE "Common Target Hook"
+
+HOOK_VECTOR (TARGETM_COMMON_INITIALIZER, gcc_targetm_common)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+/* Handle target switch DECODED for options structures OPTS and
+ OPTS_SET, at location LOC. Return true if the switch was valid. */
+DEFHOOK
+(handle_option,
+ "",
+ bool, (struct gcc_options *opts, struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ location_t loc),
+ default_target_handle_option)
+
+DEFHOOK
+(option_init_struct,
+"Set target-dependent initial values of fields in @var{opts}.",
+ void, (struct gcc_options *opts),
+ hook_void_gcc_optionsp)
+
+/* Set default optimizations for the target. */
+DEFHOOKPOD
+(option_optimization_table,
+ "",
+ const struct default_options *, empty_optimization_table)
+
+/* The initial value of target_flags. */
+DEFHOOKPOD
+(default_target_flags,
+ "",
+ int, 0)
+
+/* Determine the type of unwind info to emit for exceptions. */
+DEFHOOK
+(except_unwind_info,
+ "",
+ enum unwind_info_type, (struct gcc_options *opts),
+ default_except_unwind_info)
+
+DEFHOOK
+(supports_split_stack,
+ "Whether this target supports splitting the stack when the options\n\
+described in @var{opts} have been passed. This is called\n\
+after options have been parsed, so the target may reject splitting\n\
+the stack in some configurations. The default version of this hook\n\
+returns false. If @var{report} is true, this function may issue a warning\n\
+or error; if @var{report} is false, it must simply return a value",
+ bool, (bool report, struct gcc_options *opts),
+ hook_bool_bool_gcc_optionsp_false)
+
+DEFHOOK
+(get_valid_option_values,
+"The hook is used for options that have a non-trivial list of\n\
+possible option values. OPTION_CODE is option code of opt_code\n\
+enum type. PREFIX is used for bash completion and allows an implementation\n\
+to return more specific completion based on the prefix. All string values\n\
+should be allocated from heap memory and consumers should release them.\n\
+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)
+
+/* Leave the boolean fields at the end. */
+
+/* True if unwinding tables should be generated by default. */
+DEFHOOKPOD
+(unwind_tables_default,
+ "",
+ bool, false)
+
+/* True if arbitrary sections are supported. */
+DEFHOOKPOD
+(have_named_sections,
+ "",
+ bool, true)
+
+DEFHOOKPOD
+(always_strip_dotdot,
+ "True if @file{..} components should always be removed from directory names\n\
+computed relative to GCC's internal directories, false (default) if such\n\
+components should be preserved and directory names containing them passed\n\
+to other tools such as the linker.",
+ bool, false)
+
+HOOK_VECTOR_END (C90_EMPTY_HACK)
+
+#undef HOOK_PREFIX
diff --git a/support/cpp/gcc/common/common-target.h b/support/cpp/gcc/common/common-target.h
new file mode 100644
index 000000000..e90b02cfd
--- /dev/null
+++ b/support/cpp/gcc/common/common-target.h
@@ -0,0 +1,71 @@
+/* Data structure definitions for common hooks.
+ Copyright (C) 2010-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+#ifndef GCC_COMMON_TARGET_H
+#define GCC_COMMON_TARGET_H
+
+
+/* Sets of optimization levels at which an option may be enabled by
+ default_options_optimization. */
+enum opt_levels
+{
+ OPT_LEVELS_NONE, /* No levels (mark end of array). */
+ OPT_LEVELS_ALL, /* All levels (used by targets to disable options
+ enabled in target-independent code). */
+ OPT_LEVELS_0_ONLY, /* -O0 only. */
+ OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */
+ OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */
+ OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */
+ OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */
+ OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */
+ OPT_LEVELS_3_PLUS, /* -O3 and above. */
+ OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */
+ OPT_LEVELS_SIZE, /* -Os only. */
+ OPT_LEVELS_FAST /* -Ofast only. */
+};
+
+/* Description of options to enable by default at given levels. */
+struct default_options
+{
+ /* The levels at which to enable the option. */
+ enum opt_levels levels;
+
+ /* The option index and argument or enabled/disabled sense of the
+ option, as passed to handle_generated_option. If ARG is NULL and
+ the option allows a negative form, the option is considered to be
+ passed in negative form when the optimization level is not one of
+ those in LEVELS (in order to handle changes to the optimization
+ level with the "optimize" attribute). */
+ size_t opt_index;
+ const char *arg;
+ int value;
+};
+
+#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
+#define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS;
+#define DEFHOOK_UNDOC DEFHOOK
+#define HOOKSTRUCT(FRAGMENT) FRAGMENT
+
+#include "common-target.def"
+
+extern struct gcc_targetm_common targetm_common;
+
+#endif /* GCC_C_TARGET_H */
diff --git a/support/cpp/gcc/common/common-targhooks.cc b/support/cpp/gcc/common/common-targhooks.cc
new file mode 100644
index 000000000..46f5c61e4
--- /dev/null
+++ b/support/cpp/gcc/common/common-targhooks.cc
@@ -0,0 +1,92 @@
+/* Default common target hook functions.
+ Copyright (C) 2003-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-targhooks.h"
+#include "opts.h"
+
+/* Determine the exception handling mechanism for the target. */
+
+enum unwind_info_type
+default_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED)
+{
+ /* Obey the configure switch to turn on sjlj exceptions. */
+#ifdef CONFIG_SJLJ_EXCEPTIONS
+ if (CONFIG_SJLJ_EXCEPTIONS)
+ return UI_SJLJ;
+#endif
+
+ /* ??? Change all users to the hook, then poison this. */
+#ifdef DWARF2_UNWIND_INFO
+ if (DWARF2_UNWIND_INFO)
+ return UI_DWARF2;
+#endif
+
+ return UI_SJLJ;
+}
+
+/* To be used by targets that force dwarf2 unwind enabled. */
+
+enum unwind_info_type
+dwarf2_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED)
+{
+ /* Obey the configure switch to turn on sjlj exceptions. */
+#ifdef CONFIG_SJLJ_EXCEPTIONS
+ if (CONFIG_SJLJ_EXCEPTIONS)
+ return UI_SJLJ;
+#endif
+
+ return UI_DWARF2;
+}
+
+/* To be used by targets that force sjlj unwind enabled. */
+
+enum unwind_info_type
+sjlj_except_unwind_info (struct gcc_options *opts ATTRIBUTE_UNUSED)
+{
+ return UI_SJLJ;
+}
+
+/* Default version of TARGET_HANDLE_OPTION. */
+
+bool
+default_target_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED,
+ struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
+ location_t loc ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+/* Default version of TARGET_GET_VALID_OPTION_VALUES. */
+
+vec<const char *>
+default_get_valid_option_values (int, const char *)
+{
+ return vec<const char *> ();
+}
+
+const struct default_options empty_optimization_table[] =
+ {
+ { OPT_LEVELS_NONE, 0, NULL, 0 }
+ };
diff --git a/support/cpp/gcc/common/common-targhooks.h b/support/cpp/gcc/common/common-targhooks.h
new file mode 100644
index 000000000..cd49c7db1
--- /dev/null
+++ b/support/cpp/gcc/common/common-targhooks.h
@@ -0,0 +1,35 @@
+/* Default common target hook functions.
+ Copyright (C) 2003-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_COMMON_TARGHOOKS_H
+#define GCC_COMMON_TARGHOOKS_H
+
+extern enum unwind_info_type default_except_unwind_info (struct gcc_options *);
+extern enum unwind_info_type dwarf2_except_unwind_info (struct gcc_options *);
+extern enum unwind_info_type sjlj_except_unwind_info (struct gcc_options *);
+
+extern bool default_target_handle_option (struct gcc_options *,
+ struct gcc_options *,
+ const struct cl_decoded_option *,
+ location_t);
+extern vec<const char *> default_get_valid_option_values (int, const char *);
+
+extern const struct default_options empty_optimization_table[];
+
+#endif
diff --git a/support/cpp/gcc/common/config/default-common.cc b/support/cpp/gcc/common/config/default-common.cc
new file mode 100644
index 000000000..d57ad07c5
--- /dev/null
+++ b/support/cpp/gcc/common/config/default-common.cc
@@ -0,0 +1,33 @@
+/* Default common target hooks initializer.
+ 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "common/common-target.h"
+#include "common/common-target-def.h"
+
+/* Do not include tm.h or tm_p.h here; if it is useful for a target to
+ define some macros for the initializer in a header without defining
+ targetm_common itself (for example, because of interactions with
+ some hooks depending on the target OS and others on the target
+ architecture), create a separate tm_common.h for only the relevant
+ definitions. */
+
+// struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
diff --git a/support/cpp/gcc/common/config/dummy/dummy-cpuinfo.h b/support/cpp/gcc/common/config/dummy/dummy-cpuinfo.h
new file mode 100644
index 000000000..3f6d2013d
--- /dev/null
+++ b/support/cpp/gcc/common/config/dummy/dummy-cpuinfo.h
@@ -0,0 +1,255 @@
+/* Get CPU type and Features for x86 processors.
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ Contributed by Sriraman Tallam (tmsriram@google.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Processor Vendor and Models. */
+
+enum processor_vendor
+{
+ VENDOR_INTEL = 1,
+ VENDOR_AMD,
+ VENDOR_OTHER,
+ VENDOR_CENTAUR,
+ VENDOR_CYRIX,
+ VENDOR_NSC,
+ BUILTIN_VENDOR_MAX = VENDOR_OTHER,
+ VENDOR_MAX
+};
+
+/* Any new types or subtypes have to be inserted at the end. */
+
+enum processor_types
+{
+ INTEL_BONNELL = 1,
+ INTEL_CORE2,
+ INTEL_COREI7,
+ AMDFAM10H,
+ AMDFAM15H,
+ INTEL_SILVERMONT,
+ INTEL_KNL,
+ AMD_BTVER1,
+ AMD_BTVER2,
+ AMDFAM17H,
+ INTEL_KNM,
+ INTEL_GOLDMONT,
+ INTEL_GOLDMONT_PLUS,
+ INTEL_TREMONT,
+ AMDFAM19H,
+ CPU_TYPE_MAX,
+ BUILTIN_CPU_TYPE_MAX = CPU_TYPE_MAX
+};
+
+enum processor_subtypes
+{
+ INTEL_COREI7_NEHALEM = 1,
+ INTEL_COREI7_WESTMERE,
+ INTEL_COREI7_SANDYBRIDGE,
+ AMDFAM10H_BARCELONA,
+ AMDFAM10H_SHANGHAI,
+ AMDFAM10H_ISTANBUL,
+ AMDFAM15H_BDVER1,
+ AMDFAM15H_BDVER2,
+ AMDFAM15H_BDVER3,
+ AMDFAM15H_BDVER4,
+ AMDFAM17H_ZNVER1,
+ INTEL_COREI7_IVYBRIDGE,
+ INTEL_COREI7_HASWELL,
+ INTEL_COREI7_BROADWELL,
+ INTEL_COREI7_SKYLAKE,
+ INTEL_COREI7_SKYLAKE_AVX512,
+ INTEL_COREI7_CANNONLAKE,
+ INTEL_COREI7_ICELAKE_CLIENT,
+ INTEL_COREI7_ICELAKE_SERVER,
+ AMDFAM17H_ZNVER2,
+ INTEL_COREI7_CASCADELAKE,
+ INTEL_COREI7_TIGERLAKE,
+ INTEL_COREI7_COOPERLAKE,
+ INTEL_COREI7_SAPPHIRERAPIDS,
+ INTEL_COREI7_ALDERLAKE,
+ AMDFAM19H_ZNVER3,
+ INTEL_COREI7_ROCKETLAKE,
+ CPU_SUBTYPE_MAX
+};
+
+/* Priority of i386 features, greater value is higher priority. This is
+ used to decide the order in which function dispatch must happen. For
+ instance, a version specialized for SSE4.2 should be checked for dispatch
+ before a version for SSE3, as SSE4.2 implies SSE3. */
+enum feature_priority
+{
+ P_NONE = 0,
+ P_MMX,
+ P_SSE,
+ P_SSE2,
+ P_X86_64_BASELINE,
+ P_SSE3,
+ P_SSSE3,
+ P_PROC_SSSE3,
+ P_SSE4_A,
+ P_PROC_SSE4_A,
+ P_SSE4_1,
+ P_SSE4_2,
+ P_PROC_SSE4_2,
+ P_POPCNT,
+ P_X86_64_V2,
+ P_AES,
+ P_PCLMUL,
+ P_AVX,
+ P_PROC_AVX,
+ P_BMI,
+ P_PROC_BMI,
+ P_FMA4,
+ P_XOP,
+ P_PROC_XOP,
+ P_FMA,
+ P_PROC_FMA,
+ P_BMI2,
+ P_AVX2,
+ P_PROC_AVX2,
+ P_X86_64_V3,
+ P_AVX512F,
+ P_PROC_AVX512F,
+ P_X86_64_V4,
+ P_PROC_DYNAMIC
+};
+
+/* ISA Features supported. New features have to be inserted at the end. */
+
+enum processor_features
+{
+ FEATURE_CMOV = 0,
+ FEATURE_MMX,
+ FEATURE_POPCNT,
+ FEATURE_SSE,
+ FEATURE_SSE2,
+ FEATURE_SSE3,
+ FEATURE_SSSE3,
+ FEATURE_SSE4_1,
+ FEATURE_SSE4_2,
+ FEATURE_AVX,
+ FEATURE_AVX2,
+ FEATURE_SSE4_A,
+ FEATURE_FMA4,
+ FEATURE_XOP,
+ FEATURE_FMA,
+ FEATURE_AVX512F,
+ FEATURE_BMI,
+ FEATURE_BMI2,
+ FEATURE_AES,
+ FEATURE_PCLMUL,
+ FEATURE_AVX512VL,
+ FEATURE_AVX512BW,
+ FEATURE_AVX512DQ,
+ FEATURE_AVX512CD,
+ FEATURE_AVX512ER,
+ FEATURE_AVX512PF,
+ FEATURE_AVX512VBMI,
+ FEATURE_AVX512IFMA,
+ FEATURE_AVX5124VNNIW,
+ FEATURE_AVX5124FMAPS,
+ FEATURE_AVX512VPOPCNTDQ,
+ FEATURE_AVX512VBMI2,
+ FEATURE_GFNI,
+ FEATURE_VPCLMULQDQ,
+ FEATURE_AVX512VNNI,
+ FEATURE_AVX512BITALG,
+ FEATURE_AVX512BF16,
+ FEATURE_AVX512VP2INTERSECT,
+ FEATURE_3DNOW,
+ FEATURE_3DNOWP,
+ FEATURE_ADX,
+ FEATURE_ABM,
+ FEATURE_CLDEMOTE,
+ FEATURE_CLFLUSHOPT,
+ FEATURE_CLWB,
+ FEATURE_CLZERO,
+ FEATURE_CMPXCHG16B,
+ FEATURE_CMPXCHG8B,
+ FEATURE_ENQCMD,
+ FEATURE_F16C,
+ FEATURE_FSGSBASE,
+ FEATURE_FXSAVE,
+ FEATURE_HLE,
+ FEATURE_IBT,
+ FEATURE_LAHF_LM,
+ FEATURE_LM,
+ FEATURE_LWP,
+ FEATURE_LZCNT,
+ FEATURE_MOVBE,
+ FEATURE_MOVDIR64B,
+ FEATURE_MOVDIRI,
+ FEATURE_MWAITX,
+ FEATURE_OSXSAVE,
+ FEATURE_PCONFIG,
+ FEATURE_PKU,
+ FEATURE_PREFETCHWT1,
+ FEATURE_PRFCHW,
+ FEATURE_PTWRITE,
+ FEATURE_RDPID,
+ FEATURE_RDRND,
+ FEATURE_RDSEED,
+ FEATURE_RTM,
+ FEATURE_SERIALIZE,
+ FEATURE_SGX,
+ FEATURE_SHA,
+ FEATURE_SHSTK,
+ FEATURE_TBM,
+ FEATURE_TSXLDTRK,
+ FEATURE_VAES,
+ FEATURE_WAITPKG,
+ FEATURE_WBNOINVD,
+ FEATURE_XSAVE,
+ FEATURE_XSAVEC,
+ FEATURE_XSAVEOPT,
+ FEATURE_XSAVES,
+ FEATURE_AMX_TILE,
+ FEATURE_AMX_INT8,
+ FEATURE_AMX_BF16,
+ FEATURE_UINTR,
+ FEATURE_HRESET,
+ FEATURE_KL,
+ FEATURE_AESKLE,
+ FEATURE_WIDEKL,
+ FEATURE_AVXVNNI,
+ FEATURE_AVX512FP16,
+ FEATURE_X86_64_BASELINE,
+ FEATURE_X86_64_V2,
+ FEATURE_X86_64_V3,
+ FEATURE_X86_64_V4,
+ CPU_FEATURE_MAX
+};
+
+/* Size of __cpu_features2 array in libgcc/config/i386/cpuinfo.c. */
+#define SIZE_OF_CPU_FEATURES ((CPU_FEATURE_MAX - 1) / 32)
+
+/* These are the values for vendor types, cpu types and subtypes. Cpu
+ types and subtypes should be subtracted by the corresponding start
+ value. */
+
+#define M_CPU_TYPE_START (BUILTIN_VENDOR_MAX)
+#define M_CPU_SUBTYPE_START \
+ (M_CPU_TYPE_START + BUILTIN_CPU_TYPE_MAX)
+#define M_VENDOR(a) (a)
+#define M_CPU_TYPE(a) (M_CPU_TYPE_START + a)
+#define M_CPU_SUBTYPE(a) (M_CPU_SUBTYPE_START + a)
diff --git a/support/cpp/gcc/config.build b/support/cpp/gcc/config.build
new file mode 100644
index 000000000..30559b957
--- /dev/null
+++ b/support/cpp/gcc/config.build
@@ -0,0 +1,87 @@
+# GCC build-specific configuration file.
+# 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/>.
+
+# This is the GCC build-specific configuration file
+# where a configuration type is mapped to different system-specific
+# definitions and files. This is invoked by the autoconf-generated
+# configure script. Putting it in a separate shell file lets us skip
+# running autoconf when modifying build-specific information.
+
+# This file switches on the shell variable ${build}. As much of this
+# as possible should be replaced with autoconf tests in the future.
+
+# This file sets the following shell variables for use by the
+# autoconf-generated configure script:
+#
+# build_xm_defines List of macros to define when compiling for the
+# build machine.
+#
+# build_xm_file List of files to include when compiling for the
+# build machine.
+#
+# build_install_headers_dir
+# Target to use when installing header files.
+#
+# build_exeext Set to the suffix, if the build machine requires
+# executables to have a file name suffix.
+
+# Default settings.
+build_xm_file=
+build_xm_defines=
+build_exeext=
+build_install_headers_dir=install-headers-tar
+build_file_translate=
+
+# System-specific settings.
+case $build in
+ hppa1.0-*-hpux1[01]* | \
+ hppa*64*-*-hpux11* | \
+ hppa1.1-*-hpux11* | \
+ hppa2*-*-hpux11* )
+ build_install_headers_dir=install-headers-cpio
+ ;;
+ i[34567]86-*-cygwin* | x86_64-*-cygwin* )
+ build_xm_file=i386/xm-cygwin.h
+ build_exeext=.exe
+ ;;
+ i[34567]86-*-mingw32* | x86_64-*-mingw*)
+ build_xm_file=i386/xm-mingw32.h
+ build_exeext=.exe
+ t=`(CMD //c echo /c) 2>/dev/null`
+ case $t in ?:*)
+ build_file_translate="CMD //c"
+ ;;
+ esac
+ ;;
+ i[34567]86-pc-msdosdjgpp*)
+ build_xm_file=i386/xm-djgpp.h
+ build_exeext=.exe
+ ;;
+ *-*-sysv*)
+ # All other System V variants.
+ build_install_headers_dir=install-headers-cpio
+ ;;
+ *-*-*vms*)
+ # All OpenVMS targets.
+ build_xm_file="vms/xm-vms.h"
+ build_exeext=.exe
+ build_install_headers_dir=install-headers-cp
+ ;;
+esac
+
diff --git a/support/cpp/gcc/config.gcc b/support/cpp/gcc/config.gcc
new file mode 100644
index 000000000..1a9e4eb59
--- /dev/null
+++ b/support/cpp/gcc/config.gcc
@@ -0,0 +1,5918 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+# GCC target-specific configuration file.
+# 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/>.
+
+# This is the GCC target-specific configuration file
+# where a configuration type is mapped to different system-specific
+# definitions and files. This is invoked by the autoconf-generated
+# configure script. Putting it in a separate shell file lets us skip
+# running autoconf when modifying target-specific information.
+
+# When you change the cases in the OS or target switches, consider
+# updating ../libgcc/config.host also.
+
+# This file switches on the shell variable ${target}, and also uses the
+# following shell variables:
+#
+# with_* Various variables as set by configure.
+#
+# enable_threads Either the name, yes or no depending on whether
+# threads support was requested.
+#
+# default_use_cxa_atexit
+# The default value for the $enable___cxa_atexit
+# variable. enable___cxa_atexit needs to be set to
+# "yes" for the correct operation of C++ destructors
+# but it relies upon the presence of a non-standard C
+# library function called __cxa_atexit.
+# Since not all C libraries provide __cxa_atexit the
+# default value of $default_use_cxa_atexit is set to
+# "no" except for targets which are known to be OK.
+#
+# default_gnu_indirect_function
+# The default value for the $enable_gnu_indirect_function
+# variable. enable_gnu_indirect_function relies
+# upon the presence of a non-standard gnu ifunc support
+# in the assembler, linker and dynamic linker.
+# Since not all libraries provide the dynamic linking
+# support, the default value of
+# $default_gnu_indirect_function is set to
+# "no" except for targets which are known to be OK.
+#
+# gas_flag Either yes or no depending on whether GNU as was
+# requested.
+#
+# gnu_ld_flag Either yes or no depending on whether GNU ld was
+# requested.
+
+# This file sets the following shell variables for use by the
+# autoconf-generated configure script:
+#
+# cpu_type The name of the cpu, if different from the first
+# chunk of the canonical target name.
+#
+# tm_defines List of target macros to define for all compilations.
+#
+# 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"
+# Note that the preferred order is:
+# - specific target header "${cpu_type}/${cpu_type.h}"
+# - generic headers like dbxelf.h 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}.
+#
+# It is possible to include automatically-generated
+# build-directory files by prefixing them with "./".
+# All other files should relative to $srcdir/config.
+#
+# tm_p_file Location of file with declarations for functions
+# in $out_file.
+#
+# tm_d_file A list of headers with definitions of target hook
+# macros for the D compiler.
+#
+# out_file The name of the machine description C support
+# file, if different from "$cpu_type/$cpu_type.c".
+#
+# common_out_file The name of the source file for code shared between
+# the compiler proper and the driver.
+#
+# md_file The name of the machine-description file, if
+# different from "$cpu_type/$cpu_type.md".
+#
+# tmake_file A list of machine-description-specific
+# makefile-fragments, if different from
+# "$cpu_type/t-$cpu_type".
+#
+# extra_modes The name of the file containing a list of extra
+# machine modes, if necessary and different from
+# "$cpu_type/$cpu_type-modes.def".
+#
+# extra_objs List of extra objects that should be linked into
+# the compiler proper (cc1, cc1obj, cc1plus)
+# depending on target.
+#
+# extra_gcc_objs List of extra objects that should be linked into
+# the compiler driver (gcc) depending on target.
+#
+# extra_headers List of used header files from the directory
+# config/${cpu_type}.
+#
+# user_headers_inc_next_pre
+# List of header file names of internal gcc header
+# files, which should be prefixed by an include_next.
+# user_headers_inc_next_post
+# List of header file names of internal gcc header
+# files, which should be postfixed by an include_next.
+# use_gcc_tgmath If set, add tgmath.h to the list of used header
+# files.
+#
+# use_gcc_stdint If "wrap", install a version of stdint.h that
+# wraps the system's copy for hosted compilations;
+# if "provide", provide a version of systems without
+# such a system header; otherwise "none", do not
+# provide such a header at all.
+#
+# extra_programs List of extra executables compiled for this target
+# machine, used when linking.
+#
+# extra_options List of target-dependent .opt files.
+#
+# c_target_objs List of extra target-dependent objects that be
+# linked into the C compiler only.
+#
+# cxx_target_objs List of extra target-dependent objects that be
+# linked into the C++ compiler only.
+#
+# d_target_objs List of extra target-dependent objects that be
+# linked into the D compiler only.
+#
+# fortran_target_objs List of extra target-dependent objects that be
+# linked into the fortran compiler only.
+#
+# target_gtfiles List of extra source files with type information.
+#
+# xm_defines List of macros to define when compiling for the
+# target machine.
+#
+# xm_file List of files to include when compiling for the
+# target machine.
+#
+# use_collect2 Set to yes or no, depending on whether collect2
+# will be used.
+#
+# target_cpu_default Set to override the default target model.
+#
+# gdb_needs_out_file_path
+# Set to yes if gdb needs a dir command with
+# `dirname $out_file`.
+#
+# thread_file Set to control which thread package to use.
+#
+# gas Set to yes or no depending on whether the target
+# system normally uses GNU as.
+#
+# configure_default_options
+# Set to an initializer for configure_default_options
+# in configargs.h, based on --with-cpu et cetera.
+#
+# native_system_header_dir
+# Where system header files are found for this
+# target. This defaults to /usr/include. If
+# the --with-sysroot configure option or the
+# --sysroot command line option is used this
+# will be relative to the sysroot.
+# target_type_format_char
+# The default character to be used for formatting
+# the attribute in a
+# .type symbol_name, ${t_t_f_c}<property>
+# directive.
+
+# The following variables are used in each case-construct to build up the
+# outgoing variables:
+#
+# gnu_ld Set to yes or no depending on whether the target
+# system normally uses GNU ld.
+#
+# target_has_targetcm Set to yes or no depending on whether the target
+# has its own definition of targetcm.
+#
+# target_has_targetm_common Set to yes or no depending on whether the
+# target has its own definition of targetm_common.
+#
+# target_has_targetdm Set to yes or no depending on whether the target
+# has its own definition of targetdm.
+
+out_file=
+common_out_file=
+tmake_file=
+extra_headers=
+user_headers_inc_next_pre=
+user_headers_inc_next_post=
+use_gcc_tgmath=yes
+use_gcc_stdint=none
+extra_programs=
+extra_objs=
+extra_gcc_objs=
+extra_options=
+c_target_objs=
+cxx_target_objs=
+d_target_objs=
+fortran_target_objs=
+target_has_targetcm=no
+target_has_targetm_common=yes
+target_has_targetdm=no
+tm_defines=
+xm_defines=
+# Set this to force installation and use of collect2.
+use_collect2=
+# Set this to override the default target model.
+target_cpu_default=
+# Set this if gdb needs a dir command with `dirname $out_file`
+gdb_needs_out_file_path=
+# Set this to control which thread package will be used.
+thread_file=
+# Reinitialize these from the flag values every loop pass, since some
+# configure entries modify them.
+gas="$gas_flag"
+gnu_ld="$gnu_ld_flag"
+default_use_cxa_atexit=no
+default_gnu_indirect_function=no
+target_gtfiles=
+need_64bit_isa=
+native_system_header_dir=/usr/include
+target_type_format_char='@'
+
+# Don't carry these over build->host->target. Please.
+xm_file=
+md_file=
+
+# Obsolete configurations.
+case ${target} in
+ tile*-*-* \
+ | cr16-*-* \
+ | hppa[12]*-*-hpux10* \
+ | hppa[12]*-*-hpux11* \
+ | m32c-*-rtems* \
+ )
+ if test "x$enable_obsolete" != xyes; then
+ echo "*** Configuration ${target} is obsolete." >&2
+ echo "*** Specify --enable-obsolete to build it anyway." >&2
+ echo "*** Support will be REMOVED in the next major release of GCC," >&2
+ echo "*** unless a maintainer comes forward." >&2
+ exit 1
+ fi;;
+esac
+
+# Unsupported targets list. Do not put an entry in this list unless
+# it would otherwise be caught by a more permissive pattern. The list
+# should be in alphabetical order.
+case ${target} in
+ # Avoid special cases that are not obsolete
+ arm*-*-*eabi* \
+ )
+ ;;
+ arm*-wince-pe* \
+ | arm*-*-ecos-elf \
+ | arm*-*-elf \
+ | arm*-*-linux* \
+ | arm*-*-uclinux* \
+ | cris-*-linux* \
+ | crisv32-*-* \
+ | i[34567]86-go32-* \
+ | i[34567]86-*-go32* \
+ | m32r-*-linux* \
+ | m32rle-*-linux* \
+ | m68k*-*-openbsd* \
+ | m68k-*-uclinuxoldabi* \
+ | mips64orion*-*-rtems* \
+ | pdp11-*-bsd \
+ | powerpc*-*-linux*paired* \
+ | powerpc*-*-*spe* \
+ | sparc-hal-solaris2* \
+ | spu*-*-* \
+ | thumb-*-* \
+ | *-*-freebsd[12] | *-*-freebsd[1234].* \
+ | *-*-freebsd*aout* \
+ | *-*-linux*aout* \
+ | *-*-linux*coff* \
+ | *-*-linux*libc1* \
+ | *-*-linux*oldld* \
+ | *-*-rtemsaout* \
+ | *-*-rtemscoff* \
+ | *-*-solaris2 \
+ | *-*-solaris2.[0-9] \
+ | *-*-solaris2.[0-9].* \
+ | *-*-solaris2.10* \
+ | *-*-sysv* \
+ | vax-*-vms* \
+ )
+ echo "*** Configuration ${target} not supported" 1>&2
+ exit 1
+ ;;
+esac
+
+# Set default cpu_type, tm_file, tm_p_file and xm_file so it can be
+# updated in each machine entry. Also set default extra_headers for some
+# machines.
+tm_p_file=
+cpu_type=`echo ${target} | sed 's/-.*$//'`
+cpu_type=s390--
+cpu_is_64bit=
+case ${target} in
+m32c*-*-*)
+ cpu_type=m32c
+ tmake_file=m32c/t-m32c
+ target_has_targetm_common=no
+ ;;
+aarch64*-*-*)
+ cpu_type=aarch64
+ extra_headers="arm_fp16.h arm_neon.h arm_bf16.h arm_acle.h arm_sve.h"
+ c_target_objs="aarch64-c.o"
+ cxx_target_objs="aarch64-c.o"
+ d_target_objs="aarch64-d.o"
+ extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o aarch64-sve-builtins-sve2.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o aarch64-cc-fusion.o"
+ target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.cc \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
+ target_has_targetm_common=yes
+ ;;
+alpha*-*-*)
+ cpu_type=alpha
+ extra_options="${extra_options} g.opt"
+ ;;
+amdgcn*)
+ cpu_type=gcn
+ use_gcc_stdint=wrap
+ ;;
+am33_2.0-*-linux*)
+ cpu_type=mn10300
+ ;;
+arc*-*-*)
+ cpu_type=arc
+ c_target_objs="arc-c.o"
+ cxx_target_objs="arc-c.o"
+ extra_options="${extra_options} arc/arc-tables.opt g.opt"
+ extra_headers="arc-simd.h"
+ ;;
+arm*-*-*)
+ cpu_type=arm
+ extra_objs="arm-builtins.o arm-mve-builtins.o aarch-common.o"
+ extra_headers="mmintrin.h arm_neon.h arm_acle.h arm_fp16.h arm_cmse.h arm_bf16.h arm_mve_types.h arm_mve.h arm_cde.h"
+ target_type_format_char='%'
+ c_target_objs="arm-c.o"
+ cxx_target_objs="arm-c.o"
+ d_target_objs="arm-d.o"
+ extra_options="${extra_options} arm/arm-tables.opt"
+ target_gtfiles="\$(srcdir)/config/arm/arm-builtins.cc \$(srcdir)/config/arm/arm-mve-builtins.h \$(srcdir)/config/arm/arm-mve-builtins.cc"
+ ;;
+avr-*-*)
+ cpu_type=avr
+ c_target_objs="avr-c.o"
+ cxx_target_objs="avr-c.o"
+ ;;
+bfin*-*)
+ cpu_type=bfin
+ ;;
+bpf-*-*)
+ cpu_type=bpf
+ ;;
+frv*) cpu_type=frv
+ extra_options="${extra_options} g.opt"
+ ;;
+ft32*) cpu_type=ft32
+ target_has_targetm_common=no
+ ;;
+moxie*) cpu_type=moxie
+ target_has_targetm_common=no
+ ;;
+fido-*-*)
+ cpu_type=m68k
+ extra_headers=math-68881.h
+ extra_options="${extra_options} m68k/m68k-tables.opt"
+ ;;
+i[34567]86-*-* | x86_64-*-*)
+ cpu_type=i386
+ c_target_objs="i386-c.o"
+ cxx_target_objs="i386-c.o"
+ d_target_objs="i386-d.o"
+ extra_objs="x86-tune-sched.o x86-tune-sched-bd.o x86-tune-sched-atom.o x86-tune-sched-core.o i386-options.o i386-builtins.o i386-expand.o i386-features.o"
+ target_gtfiles="\$(srcdir)/config/i386/i386-builtins.cc \$(srcdir)/config/i386/i386-expand.cc \$(srcdir)/config/i386/i386-options.cc"
+ extra_options="${extra_options} fused-madd.opt"
+ extra_headers="cpuid.h mmintrin.h mm3dnow.h xmmintrin.h emmintrin.h
+ pmmintrin.h tmmintrin.h ammintrin.h smmintrin.h
+ nmmintrin.h bmmintrin.h fma4intrin.h wmmintrin.h
+ immintrin.h x86intrin.h avxintrin.h xopintrin.h
+ ia32intrin.h cross-stdarg.h lwpintrin.h popcntintrin.h
+ lzcntintrin.h bmiintrin.h bmi2intrin.h tbmintrin.h
+ avx2intrin.h avx512fintrin.h fmaintrin.h f16cintrin.h
+ rtmintrin.h xtestintrin.h rdseedintrin.h prfchwintrin.h
+ adxintrin.h fxsrintrin.h xsaveintrin.h xsaveoptintrin.h
+ avx512cdintrin.h avx512erintrin.h avx512pfintrin.h
+ shaintrin.h clflushoptintrin.h xsavecintrin.h
+ xsavesintrin.h avx512dqintrin.h avx512bwintrin.h
+ avx512vlintrin.h avx512vlbwintrin.h avx512vldqintrin.h
+ avx512ifmaintrin.h avx512ifmavlintrin.h avx512vbmiintrin.h
+ avx512vbmivlintrin.h avx5124fmapsintrin.h avx5124vnniwintrin.h
+ avx512vpopcntdqintrin.h clwbintrin.h mwaitxintrin.h
+ clzerointrin.h pkuintrin.h sgxintrin.h cetintrin.h
+ gfniintrin.h cet.h avx512vbmi2intrin.h
+ avx512vbmi2vlintrin.h avx512vnniintrin.h
+ avx512vnnivlintrin.h vaesintrin.h vpclmulqdqintrin.h
+ avx512vpopcntdqvlintrin.h avx512bitalgintrin.h
+ pconfigintrin.h wbnoinvdintrin.h movdirintrin.h
+ waitpkgintrin.h cldemoteintrin.h avx512bf16vlintrin.h
+ avx512bf16intrin.h enqcmdintrin.h serializeintrin.h
+ avx512vp2intersectintrin.h avx512vp2intersectvlintrin.h
+ tsxldtrkintrin.h amxtileintrin.h amxint8intrin.h
+ amxbf16intrin.h x86gprintrin.h uintrintrin.h
+ hresetintrin.h keylockerintrin.h avxvnniintrin.h
+ mwaitintrin.h avx512fp16intrin.h avx512fp16vlintrin.h"
+ ;;
+ia64-*-*)
+ extra_headers=ia64intrin.h
+ extra_options="${extra_options} g.opt fused-madd.opt"
+ ;;
+hppa*-*-*)
+ cpu_type=pa
+ ;;
+lm32*)
+ extra_options="${extra_options} g.opt"
+ ;;
+m32r*-*-*)
+ cpu_type=m32r
+ extra_options="${extra_options} g.opt"
+ ;;
+m68k-*-*)
+ extra_headers=math-68881.h
+ extra_options="${extra_options} m68k/m68k-tables.opt"
+ ;;
+microblaze*-*-*)
+ cpu_type=microblaze
+ extra_options="${extra_options} g.opt"
+ ;;
+mips*-*-*)
+ cpu_type=mips
+ d_target_objs="mips-d.o"
+ extra_headers="loongson.h loongson-mmiintrin.h msa.h"
+ extra_objs="frame-header-opt.o"
+ extra_options="${extra_options} g.opt fused-madd.opt mips/mips-tables.opt"
+ ;;
+loongarch*-*-*)
+ cpu_type=loongarch
+ extra_headers="larchintrin.h"
+ extra_objs="loongarch-c.o loongarch-builtins.o loongarch-cpu.o loongarch-opts.o loongarch-def.o"
+ extra_gcc_objs="loongarch-driver.o loongarch-cpu.o loongarch-opts.o loongarch-def.o"
+ extra_options="${extra_options} g.opt fused-madd.opt"
+ ;;
+nds32*)
+ cpu_type=nds32
+ extra_headers="nds32_intrinsic.h nds32_isr.h nds32_init.inc"
+ case ${target} in
+ nds32*-*-linux*)
+ extra_options="${extra_options} nds32/nds32-linux.opt"
+ ;;
+ nds32*-*-elf*)
+ extra_options="${extra_options} nds32/nds32-elf.opt"
+ ;;
+ *)
+ ;;
+ esac
+ extra_objs="nds32-cost.o nds32-intrinsic.o nds32-isr.o nds32-md-auxiliary.o nds32-pipelines-auxiliary.o nds32-predicates.o nds32-memory-manipulation.o nds32-fp-as-gp.o nds32-relax-opt.o nds32-utils.o"
+ ;;
+nios2-*-*)
+ cpu_type=nios2
+ extra_options="${extra_options} g.opt"
+ ;;
+nvptx-*-*)
+ cpu_type=nvptx
+ c_target_objs="nvptx-c.o"
+ cxx_target_objs="nvptx-c.o"
+ extra_options="${extra_options} nvptx/nvptx-gen.opt"
+ ;;
+or1k*-*-*)
+ cpu_type=or1k
+ ;;
+powerpc*-*-*)
+ cpu_type=rs6000
+ extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o"
+ extra_objs="${extra_objs} rs6000-call.o rs6000-pcrel-opt.o"
+ extra_objs="${extra_objs} rs6000-builtins.o rs6000-builtin.o"
+ extra_headers="ppc-asm.h altivec.h htmintrin.h htmxlintrin.h"
+ extra_headers="${extra_headers} bmi2intrin.h bmiintrin.h"
+ extra_headers="${extra_headers} xmmintrin.h mm_malloc.h emmintrin.h"
+ extra_headers="${extra_headers} mmintrin.h x86intrin.h"
+ extra_headers="${extra_headers} pmmintrin.h tmmintrin.h smmintrin.h"
+ extra_headers="${extra_headers} nmmintrin.h immintrin.h x86gprintrin.h"
+ extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h"
+ extra_headers="${extra_headers} amo.h"
+ case x$with_cpu in
+ xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower10|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500)
+ cpu_is_64bit=yes
+ ;;
+ esac
+ extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.cc \$(srcdir)/config/rs6000/rs6000-call.cc"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-pcrel-opt.cc"
+ target_gtfiles="$target_gtfiles ./rs6000-builtins.h"
+ ;;
+pru-*-*)
+ cpu_type=pru
+ ;;
+riscv*)
+ cpu_type=riscv
+ extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o"
+ d_target_objs="riscv-d.o"
+ ;;
+rs6000*-*-*)
+ extra_options="${extra_options} g.opt fused-madd.opt rs6000/rs6000-tables.opt"
+ extra_objs="rs6000-string.o rs6000-p8swap.o rs6000-logue.o"
+ extra_objs="${extra_objs} rs6000-call.o rs6000-pcrel-opt.o"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-logue.cc \$(srcdir)/config/rs6000/rs6000-call.cc"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/rs6000/rs6000-pcrel-opt.cc"
+ ;;
+sparc*-*-*)
+ cpu_type=sparc
+ c_target_objs="sparc-c.o"
+ cxx_target_objs="sparc-c.o"
+ d_target_objs="sparc-d.o"
+ extra_headers="visintrin.h"
+ ;;
+s390*-*-*)
+ cpu_type=s390
+ d_target_objs="s390-d.o"
+ extra_options="${extra_options} fused-madd.opt"
+ extra_headers="s390intrin.h htmintrin.h htmxlintrin.h vecintrin.h"
+ ;;
+# Note the 'l'; we need to be able to match e.g. "shle" or "shl".
+sh[123456789lbe]*-*-* | sh-*-*)
+ cpu_type=sh
+ extra_options="${extra_options} fused-madd.opt"
+ extra_objs="${extra_objs} sh_treg_combine.o sh-mem.o sh_optimize_sett_clrt.o"
+ ;;
+v850*-*-*)
+ cpu_type=v850
+ ;;
+tic6x-*-*)
+ cpu_type=c6x
+ extra_headers="c6x_intrinsics.h"
+ extra_options="${extra_options} c6x/c6x-tables.opt"
+ ;;
+xtensa*-*-*)
+ extra_options="${extra_options} fused-madd.opt"
+ ;;
+tilegx*-*-*)
+ cpu_type=tilegx
+ ;;
+tilepro*-*-*)
+ cpu_type=tilepro
+ ;;
+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
+
+extra_modes=
+if test -f ${srcdir}/config/${cpu_type}/${cpu_type}-modes.def
+then
+ extra_modes=${cpu_type}/${cpu_type}-modes.def
+fi
+if test -f ${srcdir}/config/${cpu_type}/${cpu_type}.opt
+then
+ extra_options="${extra_options} ${cpu_type}/${cpu_type}.opt"
+fi
+
+case ${target} in
+aarch64*-*-*)
+ tm_p_file="${tm_p_file} arm/aarch-common-protos.h"
+ case ${with_abi} in
+ "")
+ if test "x$with_multilib_list" = xilp32; then
+ tm_file="aarch64/biarchilp32.h ${tm_file}"
+ else
+ tm_file="aarch64/biarchlp64.h ${tm_file}"
+ fi
+ ;;
+ ilp32)
+ tm_file="aarch64/biarchilp32.h ${tm_file}"
+ ;;
+ lp64)
+ tm_file="aarch64/biarchlp64.h ${tm_file}"
+ ;;
+ *)
+ echo "Unknown ABI used in --with-abi=$with_abi"
+ exit 1
+ esac
+ ;;
+i[34567]86-*-*)
+ if test "x$with_abi" != x; then
+ echo "This target does not support --with-abi."
+ exit 1
+ fi
+ ;;
+x86_64-*-darwin*)
+ ;;
+x86_64-*-*)
+ case ${with_abi} in
+ "")
+ if test "x$with_multilib_list" = xmx32; then
+ tm_file="i386/biarchx32.h ${tm_file}"
+ else
+ tm_file="i386/biarch64.h ${tm_file}"
+ fi
+ ;;
+ 64 | m64)
+ tm_file="i386/biarch64.h ${tm_file}"
+ ;;
+ x32 | mx32)
+ tm_file="i386/biarchx32.h ${tm_file}"
+ ;;
+ *)
+ echo "Unknown ABI used in --with-abi=$with_abi"
+ exit 1
+ esac
+ ;;
+arm*-*-*)
+ tm_p_file="arm/arm-flags.h ${tm_p_file} arm/aarch-common-protos.h"
+ ;;
+esac
+
+# On a.out targets, we need to use collect2.
+case ${target} in
+*-*-*aout*)
+ use_collect2=yes
+ ;;
+esac
+
+# Common C libraries.
+tm_defines="$tm_defines LIBC_GLIBC=1 LIBC_UCLIBC=2 LIBC_BIONIC=3 LIBC_MUSL=4"
+
+# 32-bit x86 processors supported by --with-arch=. Each processor
+# MUST be separated by exactly one space.
+x86_archs="athlon athlon-4 athlon-fx athlon-mp athlon-tbird \
+athlon-xp k6 k6-2 k6-3 geode c3 c3-2 winchip-c6 winchip2 i386 i486 \
+i586 i686 pentium pentium-m pentium-mmx pentium2 pentium3 pentium3m \
+pentium4 pentium4m pentiumpro prescott lakemont samuel-2 nehemiah \
+c7 esther"
+
+# 64-bit x86 processors supported by --with-arch=. Each processor
+# MUST be separated by exactly one space.
+x86_64_archs="amdfam10 athlon64 athlon64-sse3 barcelona bdver1 bdver2 \
+bdver3 bdver4 znver1 znver2 znver3 btver1 btver2 k8 k8-sse3 opteron \
+opteron-sse3 nocona core2 corei7 corei7-avx core-avx-i core-avx2 atom \
+slm nehalem westmere sandybridge ivybridge haswell broadwell bonnell \
+silvermont knl knm skylake-avx512 cannonlake icelake-client icelake-server \
+skylake goldmont goldmont-plus tremont cascadelake tigerlake cooperlake \
+sapphirerapids alderlake rocketlake eden-x2 nano nano-1000 nano-2000 nano-3000 \
+nano-x2 eden-x4 nano-x4 x86-64 x86-64-v2 x86-64-v3 x86-64-v4 native"
+
+# Additional x86 processors supported by --with-cpu=. Each processor
+# MUST be separated by exactly one space.
+x86_cpus="generic intel"
+
+# Common parts for widely ported systems.
+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]*\).*'`
+ macos_maj=10
+ if test x"${macos_min}" = x; then
+ macos_min=0
+ fi
+ def_ld64=85.2
+ # Tools hosted on earlier versions of Darwin constrained all object
+ # alignment to be 2^15 or smaller. From Darwin11 (macOS 10.7) the
+ # alignment of non-common is allowed to be up to 2^28. Note that the
+ # larger alignment is permitted when targeting 10.6 from 10.7 so that
+ # the constraint only need be applied per host (and only if the host
+ # is Darwin).
+ case ${host} in
+ *-*-darwin[4-9]* | *-*-darwin10*)
+ tm_defines="$tm_defines L2_MAX_OFILE_ALIGNMENT=15U"
+ ;;
+ *)
+ tm_defines="$tm_defines L2_MAX_OFILE_ALIGNMENT=28U"
+ ;;
+ esac
+ case ${target} in
+ # Darwin 4 to 19 correspond to macOS 10.0 to 10.15
+ *-*-darwin[4-9]* | *-*-darwin1[0-9]*)
+ macos_min=`expr $darwin_maj - 4`
+ ;;
+ *-*-darwin2*)
+ # Darwin 20 corresponds to macOS 11, Darwin 21 to macOS 12.
+ macos_maj=`expr $darwin_maj - 9`
+ def_ld64=609.0
+ ;;
+ *-*-darwin)
+ case ${cpu_type} in
+ aarch64) macos_maj=11 ;;
+ x86_64) macos_min=6 ;;
+ *) macos_min=5 ;;
+ esac
+ case ${host} in
+ *-*-darwin*) tm_defines="$tm_defines DARWIN_USE_KERNEL_VERS" ;;
+ *)
+ # If configuring a cross-compiler then we will have set some
+ # default above, but it is probably not what was intended.
+ echo "Warning: Using ${target} is only suitable for Darwin hosts" 1>&2
+ echo "configure with an explicit target version" 1>&2
+ ;;
+ esac
+ ;;
+ *)
+ echo "Error: configuring for an unreleased macOS version ${target}" 1>&2
+ exit 1
+ ;;
+ esac
+ tm_defines="$tm_defines DEF_MIN_OSX_VERSION=\\\"${macos_maj}.${macos_min}\\\""
+ tm_defines="$tm_defines DEF_LD64=\\\"${def_ld64}\\\""
+ tm_file="${tm_file} ${cpu_type}/darwin.h"
+ tm_p_file="${tm_p_file} darwin-protos.h"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/darwin.cc"
+ extra_options="${extra_options} rpath.opt darwin.opt"
+ c_target_objs="${c_target_objs} darwin-c.o"
+ cxx_target_objs="${cxx_target_objs} darwin-c.o"
+ d_target_objs="${d_target_objs} darwin-d.o"
+ fortran_target_objs="darwin-f.o"
+ target_has_targetcm=yes
+ target_has_targetdm=yes
+ extra_objs="${extra_objs} darwin.o"
+ extra_gcc_objs="darwin-driver.o"
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ case ${enable_threads} in
+ "" | yes | posix) thread_file='posix' ;;
+ esac
+ ;;
+*-*-dragonfly*)
+ gas=yes
+ gnu_ld=yes
+ tmake_file="t-slibgcc"
+ case ${enable_threads} in
+ "" | yes | posix)
+ thread_file='posix'
+ ;;
+ no | single)
+ # Let these non-posix thread selections fall through if requested
+ ;;
+ *)
+ echo 'Unknown thread configuration for DragonFly BSD'
+ exit 1
+ ;;
+ esac
+ extra_options="$extra_options rpath.opt dragonfly.opt"
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ d_target_objs="${d_target_objs} dragonfly-d.o"
+ tmake_file="${tmake_file} t-dragonfly"
+ target_has_targetdm=yes
+ ;;
+*-*-freebsd*)
+ # This is the generic ELF configuration of FreeBSD. Later
+ # machine-specific sections may refine and add to this
+ # configuration.
+ #
+ # Due to tm_file entry ordering issues that vary between cpu
+ # architectures, we only define fbsd_tm_file to allow the
+ # machine-specific section to dictate the final order of all
+ # entries of tm_file with the minor exception that components
+ # of the tm_file set here will always be of the form:
+ #
+ # freebsd<version_number>.h [freebsd-<conf_option>.h ...] freebsd-spec.h freebsd.h
+ #
+ # The machine-specific section should not tamper with this
+ # ordering but may order all other entries of tm_file as it
+ # pleases around the provided core setting.
+ gas=yes
+ gnu_ld=yes
+ fbsd_major=`echo ${target} | sed -e 's/.*freebsd//g' | sed -e 's/\..*//g'`
+ if test "$fbsd_major" = ""; then
+ echo "Specify the major version number of the targeted FreeBSD release"
+ echo "like this: --target=amd64-unknown-freebsd10.1"
+ exit 1
+ fi
+ tm_defines="${tm_defines} FBSD_MAJOR=${fbsd_major}"
+ tmake_file="t-slibgcc"
+ case ${enable_threads} in
+ no)
+ fbsd_tm_file="${fbsd_tm_file} freebsd-nthr.h"
+ ;;
+ "" | yes | posix)
+ thread_file='posix'
+ ;;
+ *)
+ echo 'Unknown thread configuration for FreeBSD'
+ exit 1
+ ;;
+ esac
+ fbsd_tm_file="${fbsd_tm_file} freebsd-spec.h freebsd.h freebsd-stdint.h"
+ extra_options="$extra_options rpath.opt freebsd.opt"
+ case ${target} in
+ *-*-freebsd[345].*)
+ :;;
+ *)
+ default_use_cxa_atexit=yes;;
+ esac
+ use_gcc_stdint=wrap
+ d_target_objs="${d_target_objs} freebsd-d.o"
+ tmake_file="${tmake_file} t-freebsd"
+ target_has_targetdm=yes
+ ;;
+*-*-fuchsia*)
+ native_system_header_dir=/include
+ ;;
+*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu | *-*-uclinuxfdpiceabi)
+ extra_options="$extra_options gnu-user.opt"
+ gas=yes
+ gnu_ld=yes
+ case ${enable_threads} in
+ "" | yes | posix) thread_file='posix' ;;
+ esac
+ tmake_file="t-slibgcc"
+ case $target in
+ *-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-kopensolaris*-gnu)
+ :;;
+ *-*-gnu*)
+ native_system_header_dir=/include
+ ;;
+ esac
+ # Linux C libraries selection switch: glibc / uclibc / bionic.
+ # uclibc and bionic aren't usable for GNU/Hurd and neither for GNU/k*BSD.
+ case $target in
+ *linux*)
+ tm_p_file="${tm_p_file} linux-protos.h"
+ tmake_file="${tmake_file} t-linux"
+ extra_objs="${extra_objs} linux.o"
+ extra_options="${extra_options} linux.opt"
+ ;;
+ esac
+ case $target in
+ *-*-*android*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_BIONIC"
+ ;;
+ *-*-*uclibc* | *-*-uclinuxfdpiceabi)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+ ;;
+ *-*-*musl*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_MUSL"
+ ;;
+ *)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+ ;;
+ esac
+ # Assume that glibc or uClibc or Bionic are being used and so __cxa_atexit
+ # is provided.
+ default_use_cxa_atexit=yes
+ use_gcc_tgmath=no
+ use_gcc_stdint=wrap
+ # Enable compilation for Android by default for *android* targets.
+ case $target in
+ *-*-*android*)
+ tm_defines="$tm_defines ANDROID_DEFAULT=1"
+ ;;
+ *)
+ tm_defines="$tm_defines ANDROID_DEFAULT=0"
+ ;;
+ esac
+ c_target_objs="${c_target_objs} glibc-c.o"
+ cxx_target_objs="${cxx_target_objs} glibc-c.o"
+ d_target_objs="${d_target_objs} glibc-d.o"
+ tmake_file="${tmake_file} t-glibc"
+ target_has_targetcm=yes
+ target_has_targetdm=yes
+ case $target in
+ *-*-*uclibc* | *-*-uclinuxfdpiceabi)
+ ;;
+ *)
+ # Linux targets always support .init_array.
+ gcc_cv_initfini_array=yes
+ ;;
+ esac
+ ;;
+*-*-netbsd*)
+ tm_p_file="${tm_p_file} netbsd-protos.h"
+ tmake_file="t-netbsd t-slibgcc"
+ extra_objs="${extra_objs} netbsd.o"
+ d_target_objs="${d_target_objs} netbsd-d.o"
+ gas=yes
+ gnu_ld=yes
+ use_gcc_stdint=wrap
+ case ${enable_threads} in
+ "" | yes | posix) thread_file='posix' ;;
+ esac
+ nbsd_tm_file="netbsd.h netbsd-stdint.h netbsd-elf.h"
+ default_use_cxa_atexit=yes
+ target_has_targetdm=yes
+ case ${target} in
+ arm*-* | i[34567]86-* | powerpc*-* | sparc*-* | x86_64-*)
+ default_gnu_indirect_function=yes
+ ;;
+ esac
+ ;;
+*-*-openbsd*)
+ tmake_file="t-openbsd"
+ case ${enable_threads} in
+ yes)
+ thread_file='posix'
+ ;;
+ esac
+ case ${target} in
+ *-*-openbsd4.[3-9]|*-*-openbsd[5-9]*)
+ default_use_cxa_atexit=yes
+ ;;
+ esac
+ d_target_objs="${d_target_objs} openbsd-d.o"
+ target_has_targetdm=yes
+ ;;
+*-*-phoenix*)
+ gas=yes
+ gnu_ld=yes
+ default_use_cxa_atexit=yes
+ ;;
+*-*-rtems*)
+ case ${enable_threads} in
+ "" | yes | rtems) thread_file='rtems' ;;
+ posix) thread_file='posix' ;;
+ no) ;;
+ *)
+ echo 'Unknown thread configuration for RTEMS'
+ exit 1
+ ;;
+ esac
+ tmake_file="${tmake_file} t-rtems"
+ extra_options="${extra_options} rtems.opt"
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ ;;
+*-*-uclinux*)
+ extra_options="$extra_options gnu-user.opt"
+ use_gcc_stdint=wrap
+ case ${enable_threads} in
+ "" | yes | posix) thread_file='posix' ;;
+ esac
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC SINGLE_LIBC"
+ ;;
+*-*-rdos*)
+ use_gcc_stdint=wrap
+ ;;
+*-*-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_tail="${cpu_type}/sol2.h sol2.h"
+ sol2_tm_file="${sol2_tm_file_head} ${sol2_tm_file_tail}"
+ case ${target} in
+ *-*-solaris2.1[1-9]*)
+ # __cxa_atexit was introduced in Solaris 11.4.
+ default_use_cxa_atexit=yes
+ ;;
+ esac
+ use_gcc_stdint=wrap
+ if test x$gnu_ld = xyes; then
+ tm_file="usegld.h ${tm_file}"
+ fi
+ if test x$gas = xyes; then
+ tm_file="usegas.h ${tm_file}"
+ fi
+ tm_p_file="${tm_p_file} sol2-protos.h"
+ tmake_file="${tmake_file} t-sol2 t-slibgcc"
+ c_target_objs="${c_target_objs} sol2-c.o"
+ cxx_target_objs="${cxx_target_objs} sol2-c.o sol2-cxx.o"
+ d_target_objs="${d_target_objs} sol2-d.o"
+ extra_objs="${extra_objs} sol2.o sol2-stubs.o"
+ extra_options="${extra_options} sol2.opt"
+ case ${enable_threads}:${have_pthread_h}:${have_thread_h} in
+ "":yes:* | yes:yes:* )
+ thread_file=posix
+ ;;
+ esac
+ target_has_targetdm=yes
+ ;;
+*-*-*vms*)
+ extra_options="${extra_options} vms/vms.opt"
+ xmake_file=vms/x-vms
+ tmake_file="vms/t-vms t-slibgcc"
+ extra_objs="vms.o"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/vms/vms.cc"
+ tm_p_file="${tm_p_file} vms/vms-protos.h"
+ xm_file="vms/xm-vms.h"
+ c_target_objs="vms-c.o"
+ cxx_target_objs="vms-c.o"
+ fortran_target_objs="vms-f.o"
+ use_gcc_stdint=provide
+ tm_file="${tm_file} vms/vms-stdint.h"
+ if test x$gnu_ld != xyes; then
+ # Build wrappers for native case.
+ extra_programs="ld\$(exeext) ar\$(exeext)"
+ tmake_file="$tmake_file vms/t-vmsnative"
+ fi
+ ;;
+*-*-vxworks*)
+ tmake_file=t-vxworks
+ xm_defines=POSIX
+
+ extra_options="${extra_options} vxworks.opt"
+ extra_objs="$extra_objs vxworks.o"
+
+ c_target_objs="${c_target_objs} vxworks-c.o"
+ cxx_target_objs="${cxx_target_objs} vxworks-c.o"
+ extra_headers="${extra_headers} ../vxworks/vxworks-predef.h"
+ target_has_targetcm="yes"
+
+ # This private header exposes a consistent interface for checks on
+ # the VxWorks version our runtime header files need to perform, based on
+ # what the system headers adverstise:
+
+ extra_headers="${extra_headers} ../vxworks/_vxworks-versions.h"
+
+ # Starting from VxWorks 7, the system comes with a Dinkumware
+ # environment which requires the inclusion of "yvals.h" before other
+ # system headers. We provide wrapped versions of a few headers to
+ # accomodate such constraints:
+
+ extra_headers="${extra_headers} ../vxworks/_yvals.h"
+ extra_headers="${extra_headers} ../vxworks/_yvals-wrapper.h"
+
+ extra_headers="${extra_headers} ../vxworks/math.h ../vxworks/complex.h"
+ extra_headers="${extra_headers} ../vxworks/inttypes.h ../vxworks/setjmp.h"
+
+ # We provide (a tailored version of) stdint.h
+ tm_file="${tm_file} vxworks-stdint.h"
+ use_gcc_stdint=provide
+
+ case ${enable_threads} in
+ no) ;;
+ "" | yes | vxworks) thread_file='vxworks' ;;
+ *) echo 'Unknown thread configuration for VxWorks'; exit 1 ;;
+ esac
+
+ # A few common macro definitions conveying general characteristics
+ # of the configuration at hand. Note that by VxWorks 7, we mean the
+ # the SR6xx major update or beyond in vendor parlance:
+
+ case $target in
+ *-*-vxworks7*)
+ tm_defines="$tm_defines TARGET_VXWORKS7=1"
+ ;;
+ esac
+ case $target in
+ *64-*-vxworks*)
+ tm_defines="$tm_defines TARGET_VXWORKS64=1"
+ ;;
+ esac
+
+ # Then a few build configuration controls for VxWorks 7, which
+ # has specificities on top of which we aim to provide more complete
+ # C++ support:
+
+ case $target in
+ *-*-vxworks7*)
+ # VxWorks 7 always has init/fini_array support and it is simpler to
+ # just leverage this, sticking to what the system toolchain does:
+ gcc_cv_initfini_array=yes
+ ;;
+ esac
+ ;;
+*-*-elf|arc*-*-elf*)
+ # Assume that newlib is being used and so __cxa_atexit is provided.
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ ;;
+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} aarch64/aarch64-elf.h aarch64/aarch64-errata.h aarch64/aarch64-elf-raw.h"
+ tmake_file="${tmake_file} aarch64/t-aarch64"
+ case $target in
+ aarch64-*-elf*)
+ use_gcc_stdint=wrap
+ ;;
+ aarch64-*-fuchsia*)
+ tm_file="${tm_file} fuchsia.h"
+ ;;
+ aarch64-*-rtems*)
+ tm_file="${tm_file} aarch64/rtems.h rtems.h"
+ ;;
+ esac
+ case $target in
+ aarch64_be-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ aarch64_multilibs="${with_multilib_list}"
+ if test "$aarch64_multilibs" = "default"; then
+ aarch64_multilibs="lp64,ilp32"
+ fi
+ aarch64_multilibs=`echo $aarch64_multilibs | sed -e 's/,/ /g'`
+ for aarch64_multilib in ${aarch64_multilibs}; do
+ case ${aarch64_multilib} in
+ ilp32 | lp64 )
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${aarch64_multilib}"
+ ;;
+ *)
+ echo "--with-multilib-list=${aarch64_multilib} not supported."
+ exit 1
+ esac
+ done
+ 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} 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} 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} 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"
+ case $target in
+ aarch64_be-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ aarch64_multilibs="${with_multilib_list}"
+ if test "$aarch64_multilibs" = "default"; then
+ # TODO: turn on ILP32 multilib build after its support is mature.
+ # aarch64_multilibs="lp64,ilp32"
+ aarch64_multilibs="lp64"
+ fi
+ aarch64_multilibs=`echo $aarch64_multilibs | sed -e 's/,/ /g'`
+ for aarch64_multilib in ${aarch64_multilibs}; do
+ case ${aarch64_multilib} in
+ ilp32 | lp64 )
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${aarch64_multilib}"
+ ;;
+ *)
+ echo "--with-multilib-list=${aarch64_multilib} not supported."
+ exit 1
+ esac
+ done
+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'`
+ ;;
+aarch64*-wrs-vxworks*)
+ tm_file="${tm_file} elfos.h aarch64/aarch64-elf.h"
+ tm_file="${tm_file} vx-common.h vxworks.h aarch64/aarch64-vxworks.h"
+ tmake_file="${tmake_file} aarch64/t-aarch64 aarch64/t-aarch64-vxworks"
+ ;;
+alpha*-*-linux*)
+ tm_file="elfos.h ${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h glibc-stdint.h"
+ tmake_file="${tmake_file} alpha/t-linux alpha/t-alpha"
+ extra_options="${extra_options} alpha/elf.opt"
+ ;;
+alpha*-*-netbsd*)
+ tm_file="elfos.h ${tm_file} ${nbsd_tm_file} alpha/elf.h alpha/netbsd.h"
+ tmake_file="${tmake_file} alpha/t-alpha"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt \
+ alpha/elf.opt"
+ ;;
+alpha*-*-openbsd*)
+ tm_defines="${tm_defines} OBSD_HAS_DECLARE_FUNCTION_NAME OBSD_HAS_DECLARE_FUNCTION_SIZE OBSD_HAS_DECLARE_OBJECT"
+ tm_file="elfos.h alpha/alpha.h alpha/elf.h openbsd.h openbsd-stdint.h alpha/openbsd.h openbsd-libpthread.h"
+ tmake_file="${tmake_file} alpha/t-alpha"
+ extra_options="${extra_options} openbsd.opt alpha/elf.opt"
+ # default x-alpha is only appropriate for dec-osf.
+ ;;
+alpha*-dec-*vms*)
+ tm_file="${tm_file} vms/vms.h alpha/vms.h"
+ 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}"
+ tmake_file="arc/t-multilib arc/t-arc"
+ extra_gcc_objs="driver-arc.o"
+ if test "x$with_cpu" != x; then
+ tm_defines="${tm_defines} TARGET_CPU_BUILD=PROCESSOR_$with_cpu"
+ fi
+ if test x${with_endian} = x; then
+ case ${target} in
+ arc*be-*-* | arc*eb-*-*) with_endian=big ;;
+ *) with_endian=little ;;
+ esac
+ fi
+ case ${with_endian} in
+ big|little) ;;
+ *) echo "with_endian=${with_endian} not supported."; exit 1 ;;
+ esac
+ case ${with_endian} in
+ big*) tm_file="arc/big.h ${tm_file}"
+ 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}"
+ tmake_file="${tmake_file} arc/t-multilib-linux arc/t-arc"
+ extra_gcc_objs="driver-arc.o"
+ if test "x$with_cpu" != x; then
+ tm_defines="${tm_defines} TARGET_CPU_BUILD=PROCESSOR_$with_cpu"
+ fi
+ if test x${with_endian} = x; then
+ case ${target} in
+ arc*be-*-* | arc*eb-*-*) with_endian=big ;;
+ *) with_endian=little ;;
+ esac
+ fi
+ case ${with_endian} in
+ big|little) ;;
+ *) echo "with_endian=${with_endian} not supported."; exit 1 ;;
+ esac
+ case ${with_endian} in
+ big*) tm_file="arc/big.h ${tm_file}"
+ esac
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+ ;;
+arm-wrs-vxworks7*)
+ # We only support VxWorks 7 now on ARM, post SR600. Pre SR600
+ # VxWorks 7 was transitory and major versions prior to 7 were based
+ # on long deprecated ABI, not supported at all any more regardless
+ # of VxWorks.
+ extra_options="${extra_options} arm/vxworks.opt"
+ tmake_file="${tmake_file} arm/t-arm arm/t-vxworks arm/t-bpabi"
+ tm_file="elfos.h arm/elf.h arm/bpabi.h arm/aout.h ${tm_file}"
+ tm_file="${tm_file} vx-common.h vxworks.h arm/vxworks.h"
+ target_cpu_cname="generic-armv7-a"
+ need_64bit_hwint=yes
+ ;;
+arm*-*-freebsd*) # ARM FreeBSD EABI
+ tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h"
+ case $target in
+ arm*b-*-freebsd*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ tmake_file="${tmake_file} arm/t-arm arm/t-bpabi"
+ tm_file="${tm_file} arm/bpabi.h arm/freebsd.h arm/aout.h arm/arm.h"
+ case $target in
+ armv6*-*-freebsd*)
+ target_cpu_cname="arm1176jzf-s"
+ if test $fbsd_major -ge 11; then
+ tm_defines="${tm_defines} TARGET_FREEBSD_ARM_HARD_FLOAT=1"
+ fi
+ ;;
+ armv7*-*-freebsd*)
+ target_cpu_cname="generic-armv7-a"
+ tm_defines="${tm_defines} TARGET_FREEBSD_ARM_HARD_FLOAT=1"
+ ;;
+ *)
+ target_cpu_cname="arm9"
+ ;;
+ esac
+ with_tls=${with_tls:-gnu}
+ ;;
+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"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ case ${target} in
+ arm*eb-*) tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" ;;
+ esac
+ case ${target} in
+ arm*-*-netbsdelf-*eabi*)
+ tm_file="$tm_file arm/bpabi.h arm/netbsd-elf.h arm/netbsd-eabi.h"
+ tmake_file="$tmake_file arm/t-bpabi arm/t-netbsdeabi"
+ ;;
+ *)
+ tm_file="$tm_file arm/netbsd-elf.h"
+ tmake_file="$tmake_file arm/t-netbsd"
+ ;;
+ esac
+ tm_file="${tm_file} arm/aout.h arm/arm.h"
+ case ${target} in
+ arm*-*-netbsdelf-*eabihf*)
+ # Hard-float requires at least Arm v5te
+ target_cpu_cname="arm10e"
+ tm_defines="${tm_defines} TARGET_DEFAULT_FLOAT_ABI=ARM_FLOAT_ABI_HARD"
+ ;;
+ esac
+ case ${target} in
+ armv6*) target_cpu_cname="arm1176jzf-s";;
+ armv7*) target_cpu_cname="generic-armv7-a";;
+ 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"
+ extra_options="${extra_options} linux-android.opt"
+ case $target in
+ arm*b-*-linux*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi arm/t-linux-eabi"
+ tm_file="$tm_file arm/bpabi.h arm/linux-eabi.h arm/aout.h arm/arm.h"
+ case $target in
+ arm*-*-uclinuxfdpiceabi)
+ tm_file="$tm_file arm/uclinuxfdpiceabi.h"
+ ;;
+ esac
+ # Generation of floating-point instructions requires at least ARMv5te.
+ if [ "$with_float" = "hard" -o "$with_float" = "softfp" ] ; then
+ target_cpu_cname="arm10e"
+ else
+ target_cpu_cname="arm10tdmi"
+ fi
+ # Define multilib configuration for arm-linux-androideabi.
+ case ${target} in
+ *-androideabi)
+ tmake_file="$tmake_file arm/t-linux-androideabi"
+ ;;
+ esac
+ # The EABI requires the use of __cxa_atexit.
+ default_use_cxa_atexit=yes
+ 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"
+ 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"
+ # The EABI requires the use of __cxa_atexit.
+ default_use_cxa_atexit=yes
+ ;;
+arm*-*-phoenix*)
+ tm_file="elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
+ tm_file="${tm_file} newlib-stdint.h phoenix.h"
+ tm_file="${tm_file} arm/aout.h arm/arm.h"
+ tmake_file="${tmake_file} arm/t-arm arm/t-bpabi arm/t-phoenix"
+ target_cpu_cname="arm7tdmi"
+ ;;
+arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems* | arm*-*-fuchsia*)
+ case ${target} in
+ arm*eb-*-eabi*)
+ 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"
+ tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf"
+ target_cpu_cname="arm7tdmi"
+ case ${target} in
+ arm*-*-eabi*)
+ tm_file="$tm_file newlib-stdint.h"
+ tmake_file="${tmake_file} arm/t-bpabi"
+ use_gcc_stdint=wrap
+ ;;
+ arm*-*-fuchsia*)
+ tm_file="${tm_file} fuchsia.h arm/fuchsia-elf.h glibc-stdint.h"
+ tmake_file="${tmake_file} arm/t-bpabi arm/t-fuchsia"
+ target_cpu_cname="generic-armv7-a"
+ ;;
+ arm*-*-rtems*)
+ tm_file="${tm_file} arm/rtems.h rtems.h newlib-stdint.h"
+ tmake_file="${tmake_file} arm/t-bpabi arm/t-rtems"
+ ;;
+ arm*-*-symbianelf*)
+ tm_file="${tm_file} arm/symbian.h"
+ # We do not include t-bpabi for Symbian OS because the system
+ # provides its own implementation of the BPABI functions.
+ tmake_file="${tmake_file} arm/t-symbian"
+ target_cpu_cname="arm10tdmi"
+ ;;
+ esac
+ 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"
+ if test x${with_avrlibc} != xno; then
+ tm_file="${tm_file} ${cpu_type}/avrlibc.h"
+ tm_defines="${tm_defines} WITH_AVRLIBC"
+ fi
+ # Work out avr_double_comparison which is 2 or 3 and is used in
+ # target hook FLOAT_LIB_COMPARE_RETURNS_BOOL to determine whether
+ # DFmode comparisons return 3-state or 2-state results.
+ case y${with_double_comparison} in
+ y | ytristate)
+ avr_double_comparison=3
+ ;;
+ ybool | ylibf7)
+ avr_double_comparison=2
+ ;;
+ *)
+ echo "Error: --with-double-comparison= can only be used with: 'tristate', 'bool', 'libf7'" 1>&2
+ exit 1
+ ;;
+ esac
+ case "y${with_libf7}" in
+ yno)
+ # avr_double_comparison as set above.
+ ;;
+ ylibgcc)
+ avr_double_comparison=2
+ tm_defines="${tm_defines} WITH_LIBF7_LIBGCC"
+ ;;
+ y | yyes | ymath-symbols)
+ avr_double_comparison=2
+ tm_defines="${tm_defines} WITH_LIBF7_LIBGCC"
+ tm_defines="${tm_defines} WITH_LIBF7_MATH"
+ tm_defines="${tm_defines} WITH_LIBF7_MATH_SYMBOLS"
+ ;;
+ ymath)
+ avr_double_comparison=2
+ tm_defines="${tm_defines} WITH_LIBF7_LIBGCC"
+ tm_defines="${tm_defines} WITH_LIBF7_MATH"
+ ;;
+ *)
+ echo "Error: --with-libf7=${with_libf7} but can only be used with: 'libgcc', 'math', 'math-symbols', 'yes', 'no'" 1>&2
+ exit 1
+ ;;
+ esac
+ tm_defines="${tm_defines} WITH_DOUBLE_COMPARISON=${avr_double_comparison}"
+ case y${with_double} in
+ y32)
+ avr_double=32
+ tm_defines="${tm_defines} HAVE_DOUBLE32"
+ ;;
+ y64)
+ avr_double=64
+ tm_defines="${tm_defines} HAVE_DOUBLE64"
+ ;;
+ y64,32)
+ avr_double=64
+ avr_double_multilib=1
+ tm_defines="${tm_defines} HAVE_DOUBLE32"
+ tm_defines="${tm_defines} HAVE_DOUBLE64"
+ tm_defines="${tm_defines} HAVE_DOUBLE_MULTILIB"
+ ;;
+ y | y32,64)
+ avr_double=32
+ avr_double_multilib=1
+ tm_defines="${tm_defines} HAVE_DOUBLE32"
+ tm_defines="${tm_defines} HAVE_DOUBLE64"
+ tm_defines="${tm_defines} HAVE_DOUBLE_MULTILIB"
+ ;;
+ *)
+ echo "Error: --with-double= can only be used with: '32', '32,64', '64,32', '64'" 1>&2
+ exit 1
+ ;;
+ esac
+ case y${with_long_double} in
+ y32)
+ avr_long_double=32
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+ ;;
+ y64)
+ avr_long_double=64
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+ ;;
+ y | y64,32)
+ avr_long_double=64
+ avr_long_double_multilib=1
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE_MULTILIB"
+ ;;
+ y32,64)
+ avr_long_double=32
+ avr_long_double_multilib=1
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE_MULTILIB"
+ ;;
+ ydouble)
+ avr_long_double=${avr_double}
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE_IS_DOUBLE"
+ if test y${avr_double_multilib} = y1; then
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+ else
+ tm_defines="${tm_defines} HAVE_LONG_DOUBLE${avr_long_double}"
+ fi
+ ;;
+ *)
+ echo "Error: --with-long_double= can only be used with: '32', '32,64', '64,32', '64', 'double'" 1>&2
+ exit 1
+ ;;
+ esac
+ if test ${avr_long_double}x${avr_long_double_multilib}y${avr_double_multilib}z = 32xy1z; then
+ if test y${with_long_double} != ydouble; then
+ echo "Error: --with-double=${with_double} requests a multilib for double, but long double is always 32 bits wide due to --with-long-double=${with_long_double}" 1>&2
+ exit 1
+ fi
+ fi
+ if test ${avr_double}x${avr_long_double_multilib}y${avr_double_multilib}z = 64x1yz; then
+ echo "Error: --with-long-double=${with_long_double} requests a multilib for long double, but double is always 64 bits wide due to --with-double=64" 1>&2
+ exit 1
+ fi
+ if test y${avr_double}${avr_long_double} = y6432; then
+ echo "Error: double default of 64 bits from --with-double=${with_double} conflicts with default of 32 bits for long double from --with-long-double=${with_long_double}" 1>&2
+ exit 1
+ fi
+ tm_defines="${tm_defines} WITH_DOUBLE${avr_double}"
+ tm_defines="${tm_defines} WITH_LONG_DOUBLE${avr_long_double}"
+ tmake_file="${tmake_file} avr/t-avr avr/t-multilib"
+ use_gcc_stdint=wrap
+ extra_gcc_objs="driver-avr.o avr-devices.o"
+ extra_objs="avr-devices.o avr-log.o"
+ ;;
+bfin*-elf*)
+ tm_file="${tm_file} dbxelf.h 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"
+ 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"
+ 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"
+ tmake_file="${tmake_file} bfin/t-rtems"
+ ;;
+bfin*-*)
+ tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h"
+ use_collect2=no
+ use_gcc_stdint=wrap
+ ;;
+bpf-*-*)
+ tm_file="elfos.h ${tm_file}"
+ tmake_file="${tmake_file} bpf/t-bpf"
+ use_collect2=no
+ extra_headers="bpf-helpers.h"
+ use_gcc_stdint=provide
+ 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"
+ gas=yes
+ extra_options="${extra_options} cris/elf.opt"
+ use_gcc_stdint=wrap
+ ;;
+csky-*-*)
+ if test x${with_endian} != x; then
+ case ${with_endian} in
+ big|little) ;;
+ *)
+ echo "with_endian=${with_endian} not supported."
+ exit 1
+ ;;
+ esac
+ fi
+ if test x${with_float} != x; then
+ case ${with_float} in
+ soft | hard) ;;
+ *) echo
+ "Unknown floating point type used in --with-float=$with_float"
+ exit 1
+ ;;
+ esac
+ fi
+ tm_file="csky/csky.h"
+ md_file="csky/csky.md"
+ out_file="csky/csky.cc"
+ tm_p_file="${tm_p_file} csky/csky-protos.h"
+ extra_options="${extra_options} csky/csky_tables.opt"
+
+ if test x${enable_tpf_debug} = xyes; then
+ tm_defines="${tm_defines} ENABLE_TPF_DEBUG"
+ fi
+
+ case ${target} in
+ csky-*-elf*)
+ tm_file="dbxelf.h 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"
+ tmake_file="${tmake_file} csky/t-csky csky/t-csky-linux"
+
+ case ${target} in
+ csky-*-linux-gnu*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+ ;;
+ csky-*-linux-uclibc*)
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_UCLIBC"
+ default_use_cxa_atexit=no
+ ;;
+ *)
+ echo "Unknown target $target"
+ exit 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "Unknown target $target"
+ exit 1
+ ;;
+ esac
+ ;;
+epiphany-*-elf | epiphany-*-rtems*)
+ tm_file="dbxelf.h elfos.h ${tm_file}"
+ tmake_file="${tmake_file} epiphany/t-epiphany"
+ case ${target} in
+ epiphany-*-rtems*)
+ tm_file="${tm_file} epiphany/rtems.h rtems.h newlib-stdint.h"
+ ;;
+ *)
+ tm_file="${tm_file} newlib-stdint.h"
+ ;;
+ esac
+ extra_options="${extra_options} fused-madd.opt"
+ extra_objs="${extra_objs} mode-switch-use.o resolve-sw-modes.o"
+ tm_defines="${tm_defines} EPIPHANY_STACK_OFFSET=${with_stack_offset:-8}"
+ extra_headers="epiphany_intrinsics.h"
+ ;;
+fr30-*-elf)
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ ;;
+frv-*-elf)
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file=frv/t-frv
+ ;;
+frv-*-*linux*)
+ tm_file="dbxelf.h 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}"
+ tmake_file="${tmake_file} ft32/t-ft32"
+ ;;
+amdgcn-*-amdhsa)
+ tm_file="elfos.h gcn/gcn-hsa.h gcn/gcn.h newlib-stdint.h"
+ tmake_file="gcn/t-gcn-hsa"
+ native_system_header_dir=/include
+ extra_modes=gcn/gcn-modes.def
+ extra_objs="${extra_objs} gcn-tree.o"
+ extra_gcc_objs="driver-gcn.o"
+ case "$host" in
+ x86_64*-*-linux-gnu )
+ if test "$ac_cv_search_dlopen" != no; then
+ extra_programs="${extra_programs} gcn-run\$(exeext)"
+ fi
+ ;;
+ esac
+ if test x$enable_as_accelerator = xyes; then
+ extra_programs="${extra_programs} mkoffload\$(exeext)"
+ tm_file="${tm_file} gcn/offload.h"
+ fi
+ # Force .init_array support.
+ gcc_cv_initfini_array=yes
+ thread_file=gcn
+ ;;
+moxie-*-elf)
+ gas=yes
+ gnu_ld=yes
+ tm_file="dbxelf.h 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"
+ 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"
+ ;;
+moxie-*-moxiebox*)
+ gas=yes
+ gnu_ld=yes
+ tm_file="${tm_file} dbxelf.h elfos.h moxie/moxiebox.h newlib-stdint.h"
+ tmake_file="${tmake_file} moxie/t-moxiebox"
+ ;;
+h8300-*-elf*)
+ tmake_file="h8300/t-h8300"
+ tm_file="h8300/h8300.h elfos.h newlib-stdint.h h8300/elf.h"
+ ;;
+h8300-*-linux*)
+ tmake_file="${tmake_file} h8300/t-h8300 h8300/t-linux"
+ tm_file="h8300/h8300.h elfos.h gnu-user.h linux.h glibc-stdint.h h8300/linux.h"
+ ;;
+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 \
+ 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"
+ d_target_objs="${d_target_objs} pa-d.o"
+ gas=yes gnu_ld=yes
+ ;;
+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 \
+ 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 \
+ pa/pa-openbsd.h pa/pa32-regs.h pa/pa32-openbsd.h"
+ extra_options="${extra_options} openbsd.opt"
+ tmake_file="pa/t-pa"
+ d_target_objs="${d_target_objs} pa-d.o"
+ gas=yes
+ gnu_ld=yes
+ ;;
+hppa*-*-netbsd*)
+ target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS"
+ tm_file="${tm_file} dbxelf.h 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 \
+ pa/pa64-regs.h pa/pa-hpux.h pa/pa-hpux1010.h \
+ pa/pa-hpux11.h"
+ case ${target} in
+ *-*-hpux11.[12]*)
+ tm_file="${tm_file} pa/pa-hpux1111.h pa/pa-64.h pa/pa64-hpux.h"
+ extra_options="${extra_options} pa/pa-hpux1111.opt"
+ ;;
+ *-*-hpux11.[3-9]*)
+ tm_file="${tm_file} pa/pa-hpux1131.h pa/pa-64.h pa/pa64-hpux.h"
+ extra_options="${extra_options} pa/pa-hpux1131.opt"
+ ;;
+ *)
+ tm_file="${tm_file} pa/pa-64.h pa/pa64-hpux.h"
+ ;;
+ esac
+ extra_options="${extra_options} pa/pa-hpux.opt \
+ pa/pa-hpux1010.opt pa/pa64-hpux.opt hpux11.opt"
+ 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
+ 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
+ ;;
+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
+ ;;
+i[34567]86-*-darwin*)
+ need_64bit_isa=yes
+ # Baseline choice for a machine that allows m64 support.
+ with_cpu=${with_cpu:-core2}
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin32-biarch t-slibgcc"
+ tm_file="${cpu_type}/darwin32-biarch.h ${tm_file} "
+ ;;
+x86_64-*-darwin1[89]* | x86_64-*-darwin2*)
+ # Only 64b from now
+ tm_defines="${tm_defines} TARGET_64BIT_DEFAULT=(OPTION_MASK_ISA_64BIT|OPTION_MASK_ABI_64)"
+ tm_defines="${tm_defines} TARGET_BI_ARCH=0"
+ with_cpu=${with_cpu:-core2}
+ tmake_file="${tmake_file} t-slibgcc"
+ ;;
+x86_64-*-darwin*)
+ with_cpu=${with_cpu:-core2}
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin64-biarch t-slibgcc"
+ 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"
+ ;;
+i[34567]86-*-elf*)
+ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.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"
+ ;;
+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"
+ ;;
+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"
+ ;;
+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"
+ 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"
+ 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"
+ 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"
+ ;;
+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"
+ ;;
+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"
+ 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"
+ 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} 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} openbsd.h openbsd-stdint.h openbsd-libpthread.h i386/x86-64.h i386/openbsdelf.h"
+ extra_options="${extra_options} openbsd.opt"
+ gas=yes
+ gnu_ld=yes
+ ;;
+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"
+ case ${target} in
+ i[34567]86-*-linux*)
+ tm_file="${tm_file} linux.h linux-android.h"
+ extra_options="${extra_options} linux-android.opt"
+ if test x$enable_targets = xall; then
+ tm_file="${tm_file} i386/x86-64.h i386/gnu-user-common.h i386/gnu-user64.h i386/linux-common.h i386/linux64.h"
+ tm_defines="${tm_defines} TARGET_BI_ARCH=1"
+ tmake_file="${tmake_file} i386/t-linux64"
+ x86_multilibs="${with_multilib_list}"
+ if test "$x86_multilibs" = "default"; then
+ x86_multilibs="m64,m32"
+ fi
+ x86_multilibs=`echo $x86_multilibs | sed -e 's/,/ /g'`
+ for x86_multilib in ${x86_multilibs}; do
+ case ${x86_multilib} in
+ m32 | m64 | mx32)
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${x86_multilib}"
+ ;;
+ *)
+ echo "--with-multilib-list=${x86_with_multilib} not supported."
+ exit 1
+ esac
+ done
+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'`
+ need_64bit_isa=yes
+ if test x$with_cpu = x; then
+ if test x$with_cpu_64 = x; then
+ with_cpu_64=generic
+ fi
+ else
+ case " $x86_cpus $x86_archs $x86_64_archs " in
+ *" $with_cpu "*)
+ ;;
+ *)
+ echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2
+ echo "$x86_cpus $x86_archs $x86_64_archs " 1>&2
+ exit 1
+ ;;
+ esac
+ fi
+ else
+ tm_file="${tm_file} i386/gnu-user-common.h i386/gnu-user.h i386/linux-common.h i386/linux.h"
+ fi
+ ;;
+ i[34567]86-*-kfreebsd*-gnu)
+ tm_file="${tm_file} i386/gnu-user-common.h i386/gnu-user.h kfreebsd-gnu.h i386/kfreebsd-gnu.h"
+ ;;
+ i[34567]86-*-kopensolaris*-gnu)
+ tm_file="${tm_file} i386/gnu-user-common.h i386/gnu-user.h kopensolaris-gnu.h i386/kopensolaris-gnu.h"
+ ;;
+ i[34567]86-*-gnu*)
+ tm_file="$tm_file i386/gnu-user-common.h i386/gnu-user.h gnu.h i386/gnu.h"
+ ;;
+ 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 \
+ i386/x86-64.h i386/gnu-user-common.h i386/gnu-user64.h"
+ case ${target} in
+ x86_64-*-linux*)
+ tm_file="${tm_file} linux.h linux-android.h i386/linux-common.h i386/linux64.h"
+ extra_options="${extra_options} linux-android.opt"
+ ;;
+ x86_64-*-kfreebsd*-gnu)
+ tm_file="${tm_file} kfreebsd-gnu.h i386/kfreebsd-gnu64.h"
+ ;;
+ esac
+ tmake_file="${tmake_file} i386/t-linux64"
+ x86_multilibs="${with_multilib_list}"
+ if test "$x86_multilibs" = "default"; then
+ case ${with_abi} in
+ x32 | mx32)
+ x86_multilibs="mx32"
+ ;;
+ *)
+ x86_multilibs="m64,m32"
+ ;;
+ esac
+ fi
+ x86_multilibs=`echo $x86_multilibs | sed -e 's/,/ /g'`
+ for x86_multilib in ${x86_multilibs}; do
+ case ${x86_multilib} in
+ m32 | m64 | mx32)
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${x86_multilib}"
+ ;;
+ *)
+ echo "--with-multilib-list=${x86_with_multilib} not supported."
+ exit 1
+ esac
+ done
+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'`
+ ;;
+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"
+ native_system_header_dir=/dev/env/DJDIR/include
+ extra_options="${extra_options} i386/djgpp.opt"
+ gnu_ld=yes
+ gas=yes
+ use_gcc_stdint=wrap
+ ;;
+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"
+ tmake_file="${tmake_file} t-lynx"
+ extra_options="${extra_options} lynx.opt"
+ thread_file=lynx
+ gnu_ld=yes
+ 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"
+ 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"
+ tmake_file="${tmake_file} i386/t-rtems"
+ ;;
+i[34567]86-*-solaris2* | x86_64-*-solaris2*)
+ # Set default arch_32 to pentium4, tune_32 to generic like the other
+ # i386 targets, although config.guess defaults to i386-pc-solaris2*.
+ with_arch_32=${with_arch_32:-pentium4}
+ with_tune_32=${with_tune_32:-generic}
+ tm_file="${tm_file} i386/unix.h i386/att.h ${sol2_tm_file_head} i386/x86-64.h ${sol2_tm_file_tail}"
+ tm_defines="${tm_defines} TARGET_BI_ARCH=1"
+ tmake_file="$tmake_file i386/t-sol2"
+ need_64bit_isa=yes
+ if test x$with_cpu = x; then
+ if test x$with_cpu_64 = x; then
+ with_cpu_64=generic
+ fi
+ else
+ case " $x86_cpus $x86_archs $x86_64_archs " in
+ *" $with_cpu "*)
+ ;;
+ *)
+ echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2
+ echo "$x86_cpus $x86_archs $x86_64_archs" 1>&2
+ exit 1
+ ;;
+ esac
+ fi
+ ;;
+i[4567]86-wrs-vxworks*|x86_64-wrs-vxworks7*)
+ tm_file="${tm_file} i386/unix.h i386/att.h elfos.h"
+ case ${target} in
+ x86_64-*)
+ need_64bit_isa=yes
+ tm_file="${tm_file} i386/x86-64.h"
+ ;;
+ esac
+ tm_file="${tm_file} vx-common.h"
+ case ${target} in
+ *-vxworksae*)
+ tm_file="${tm_file} vxworksae.h i386/vxworks.h i386/vxworksae.h"
+ tmake_file="${tmake_file} i386/t-vxworks i386/t-vxworksae"
+ ;;
+ *)
+ tm_file="${tm_file} vxworks.h i386/vxworks.h"
+ tmake_file="${tmake_file} i386/t-vxworks"
+ ;;
+ 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"
+ xm_file=i386/xm-cygwin.h
+ tmake_file="${tmake_file} i386/t-cygming t-slibgcc"
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/i386/winnt.cc"
+ extra_options="${extra_options} i386/cygming.opt i386/cygwin.opt"
+ extra_objs="${extra_objs} winnt.o winnt-stubs.o"
+ c_target_objs="${c_target_objs} msformat-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
+ d_target_objs="${d_target_objs} winnt-d.o"
+ target_has_targetdm="yes"
+ if test x$enable_threads = xyes; then
+ thread_file='posix'
+ fi
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ ;;
+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"
+ 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"
+ extra_options="${extra_options} i386/cygming.opt i386/cygwin.opt"
+ extra_objs="${extra_objs} winnt.o winnt-stubs.o"
+ c_target_objs="${c_target_objs} msformat-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
+ d_target_objs="${d_target_objs} winnt-d.o"
+ target_has_targetdm="yes"
+ if test x$enable_threads = xyes; then
+ thread_file='posix'
+ fi
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ 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"
+ xm_file=i386/xm-mingw32.h
+ c_target_objs="${c_target_objs} winnt-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-c.o"
+ d_target_objs="${d_target_objs} winnt-d.o"
+ target_has_targetcm="yes"
+ target_has_targetdm="yes"
+ case ${target} in
+ x86_64-*-* | *-w64-*)
+ need_64bit_isa=yes
+ ;;
+ *)
+ ;;
+ esac
+ if test x$enable_threads = xposix ; then
+ tm_file="${tm_file} i386/mingw-pthread.h"
+ fi
+ tm_file="${tm_file} i386/mingw32.h"
+ # This makes the logic if mingw's or the w64 feature set has to be used
+ case ${target} in
+ *-w64-*)
+ user_headers_inc_next_post="${user_headers_inc_next_post} float.h"
+ user_headers_inc_next_pre="${user_headers_inc_next_pre} stddef.h stdarg.h"
+ tm_file="${tm_file} i386/mingw-w64.h"
+ if test x$enable_targets = xall; then
+ tm_defines="${tm_defines} TARGET_BI_ARCH=1"
+ if test x$with_cpu = x; then
+ if test x$with_cpu_64 = x; then
+ with_cpu_64=generic
+ fi
+ else
+ case " $x86_cpus $x86_archs $x86_64_archs " in
+ *" $with_cpu "*)
+ ;;
+ *)
+ echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2
+ echo "$x86_cpus $x86_archs $x86_64_archs" 1>&2
+ exit 1
+ ;;
+ esac
+ fi
+ fi
+ ;;
+ *)
+ ;;
+ esac
+ tm_file="${tm_file} i386/mingw-stdint.h"
+ tmake_file="${tmake_file} t-winnt i386/t-cygming t-slibgcc"
+ case ${target} in
+ x86_64-w64-*)
+ tmake_file="${tmake_file} i386/t-mingw-w64"
+ ;;
+ i[34567]86-w64-*)
+ tmake_file="${tmake_file} i386/t-mingw-w32"
+ ;;
+ esac
+ native_system_header_dir=/mingw/include
+ target_gtfiles="$target_gtfiles \$(srcdir)/config/i386/winnt.cc"
+ extra_options="${extra_options} i386/cygming.opt i386/mingw.opt"
+ case ${target} in
+ *-w64-*)
+ extra_options="${extra_options} i386/mingw-w64.opt"
+ ;;
+ *)
+ ;;
+ esac
+ extra_objs="${extra_objs} winnt.o winnt-stubs.o"
+ c_target_objs="${c_target_objs} msformat-c.o"
+ cxx_target_objs="${cxx_target_objs} winnt-cxx.o msformat-c.o"
+ gas=yes
+ gnu_ld=yes
+ default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
+ case ${enable_threads} in
+ "" | yes | win32)
+ thread_file='win32'
+ ;;
+ posix)
+ thread_file='posix'
+ ;;
+ esac
+ case ${target} in
+ *mingw32crt*)
+ tm_file="${tm_file} i386/crtdll.h"
+ ;;
+ *mingw32msv* | *mingw*)
+ ;;
+ esac
+ ;;
+x86_64-*-fuchsia*)
+ tmake_file="${tmake_file} i386/t-x86_64-elf"
+ 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"
+ tmake_file="ia64/t-ia64"
+ target_cpu_default="0"
+ if test x$gas = xyes
+ then
+ target_cpu_default="${target_cpu_default}|MASK_GNU_AS"
+ fi
+ if test x$gnu_ld = xyes
+ then
+ target_cpu_default="${target_cpu_default}|MASK_GNU_LD"
+ fi
+ ;;
+ia64*-*-freebsd*)
+ tm_file="${tm_file} dbxelf.h 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"
+ 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"
+ tmake_file="ia64/t-ia64 ia64/t-hpux t-slibgcc"
+ target_cpu_default="MASK_GNU_AS"
+ case x$enable_threads in
+ x | xyes | xposix )
+ thread_file=posix
+ ;;
+ esac
+ use_collect2=no
+ c_target_objs="ia64-c.o"
+ cxx_target_objs="ia64-c.o"
+ extra_options="${extra_options} ia64/ilp32.opt hpux11.opt"
+ use_gcc_stdint=wrap
+ tm_file="${tm_file} hpux-stdint.h"
+ case ${target} in
+ *-*-hpux11.3*)
+ tm_file="${tm_file} ia64/hpux-unix2003.h"
+ ;;
+ esac
+ ;;
+ia64-hp-*vms*)
+ tm_file="${tm_file} elfos.h ia64/sysv4.h vms/vms.h ia64/vms.h"
+ tmake_file="${tmake_file} ia64/t-ia64"
+ target_cpu_default="0"
+ if test x$gas = xyes
+ then
+ target_cpu_default="${target_cpu_default}|MASK_GNU_AS"
+ fi
+ extra_options="${extra_options} ia64/vms.opt"
+ ;;
+iq2000*-*-elf*)
+ tm_file="elfos.h newlib-stdint.h iq2000/iq2000.h"
+ out_file=iq2000/iq2000.cc
+ md_file=iq2000/iq2000.md
+ ;;
+lm32-*-elf*)
+ tm_file="dbxelf.h 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"
+ 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"
+ tmake_file="${tmake_file} lm32/t-lm32"
+ ;;
+m32r-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ ;;
+m32rle-*-elf*)
+ tm_file="elfos.h newlib-stdint.h m32r/little.h ${tm_file}"
+ ;;
+m68k-*-elf* | fido-*-elf*)
+ case ${target} in
+ fido-*-elf*)
+ # Check that $with_cpu makes sense.
+ case $with_cpu in
+ "" | "fidoa")
+ ;;
+ *)
+ echo "Cannot accept --with-cpu=$with_cpu"
+ exit 1
+ ;;
+ esac
+ with_cpu=fidoa
+ ;;
+ *)
+ default_m68k_cpu=68020
+ 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_defines="${tm_defines} MOTOROLA=1"
+ tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf"
+ # Add multilibs for targets other than fido.
+ case ${target} in
+ fido-*-elf*)
+ ;;
+ *)
+ tmake_file="$tmake_file m68k/t-mlibs"
+ ;;
+ esac
+ ;;
+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"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+ tm_defines="${tm_defines} MOTOROLA=1 CHAR_FAST8=1 SHORT_FAST16=1"
+ ;;
+m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux
+ # with uClibc, using the new GNU/Linux-style
+ # 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"
+ extra_options="${extra_options} m68k/uclinux.opt"
+ tm_defines="${tm_defines} MOTOROLA=1"
+ tmake_file="m68k/t-floatlib m68k/t-uclinux m68k/t-mlibs"
+ ;;
+m68k-*-linux*) # Motorola m68k's running GNU/Linux
+ # with ELF format using glibc 2
+ # aka the GNU/Linux C library 6.
+ 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"
+ 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"
+ ;;
+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_defines="${tm_defines} MOTOROLA=1"
+ ;;
+mcore-*-elf)
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} mcore/mcore-elf.h"
+ tmake_file=mcore/t-mcore
+ inhibit_libc=true
+ ;;
+microblaze*-linux*)
+ case $target in
+ microblazeel-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=0"
+ ;;
+ microblaze-*)
+ 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} glibc-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"
+ tmake_file="${tmake_file} microblaze/t-microblaze-linux"
+ ;;
+microblaze*-*-rtems*)
+ case $target in
+ microblazeel-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=0"
+ ;;
+ microblaze-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321"
+ ;;
+ esac
+ tm_file="${tm_file} dbxelf.h"
+ 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"
+ tmake_file="${tmake_file} microblaze/t-microblaze"
+ tmake_file="${tmake_file} microblaze/t-rtems"
+ ;;
+microblaze*-*-elf)
+ case $target in
+ microblazeel-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=0"
+ ;;
+ microblaze-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=4321"
+ ;;
+ esac
+ tm_file="${tm_file} dbxelf.h 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"
+ ;;
+riscv*-*-linux*)
+ tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} riscv/linux.h"
+ case "x${enable_multilib}" in
+ xno) ;;
+ xyes) tmake_file="${tmake_file} riscv/t-linux-multilib" ;;
+ *) echo "Unknown value for enable_multilib"; exit 1
+ esac
+ tmake_file="${tmake_file} riscv/t-riscv riscv/t-linux"
+ gnu_ld=yes
+ gas=yes
+ case $target in
+ riscv32be-*|riscv64be-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+ ;;
+riscv*-*-elf* | riscv*-*-rtems*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
+ case ${target} in
+ *-*-rtems*)
+ tm_file="${tm_file} riscv/rtems.h rtems.h"
+ tmake_file="${tmake_file} riscv/t-rtems"
+ ;;
+ *)
+ if test "x${with_multilib_generator}" == xdefault; then
+ case "x${enable_multilib}" in
+ xno) ;;
+ xyes) tmake_file="${tmake_file} riscv/t-elf-multilib" ;;
+ *) echo "Unknown value for enable_multilib"; exit 1
+ esac
+ fi
+ esac
+ tmake_file="${tmake_file} riscv/t-riscv"
+ gnu_ld=yes
+ gas=yes
+ case $target in
+ riscv32be-*|riscv64be-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+ ;;
+riscv*-*-freebsd*)
+ tm_file="${tm_file} elfos.h ${fbsd_tm_file} riscv/freebsd.h"
+ tmake_file="${tmake_file} riscv/t-riscv"
+ gnu_ld=yes
+ gas=yes
+ case $target in
+ riscv32be-*|riscv64be-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+ ;;
+
+loongarch*-*-linux*)
+ tm_file="dbxelf.h 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"
+ gnu_ld=yes
+ gas=yes
+
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+ ;;
+
+mips*-*-netbsd*) # NetBSD/mips, either endian.
+ target_cpu_default="MASK_ABICALLS"
+ tm_file="elfos.h ${tm_file} mips/elf.h ${nbsd_tm_file} mips/netbsd.h"
+ 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"
+ 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"
+ with_arch_32="mips32r6"
+ with_arch_64="mips64r6"
+ gnu_ld=yes
+ 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"
+ 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"
+ with_arch_32="mips32r2"
+ with_arch_64="mips64r2"
+ gnu_ld=yes
+ 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"
+ extra_options="${extra_options} linux-android.opt"
+ case ${target} in
+ mipsisa32r6*)
+ default_mips_arch=mips32r6
+ ;;
+ mipsisa32r2*)
+ default_mips_arch=mips32r2
+ ;;
+ mipsisa32*)
+ default_mips_arch=mips32
+ ;;
+ mips64el-st-linux-gnu)
+ default_mips_abi=n32
+ tm_file="${tm_file} mips/st.h"
+ tmake_file="${tmake_file} mips/t-st"
+ enable_mips_multilibs="yes"
+ ;;
+ mips64octeon*-*-linux*)
+ default_mips_abi=n32
+ tm_defines="${tm_defines} MIPS_CPU_STRING_DEFAULT=\\\"octeon\\\""
+ target_cpu_default=MASK_SOFT_FLOAT_ABI
+ enable_mips_multilibs="yes"
+ ;;
+ mipsisa64r6*-*-linux-gnuabi64)
+ default_mips_abi=64
+ default_mips_arch=mips64r6
+ enable_mips_multilibs="yes"
+ ;;
+ mipsisa64r6*-*-linux*)
+ default_mips_abi=n32
+ default_mips_arch=mips64r6
+ enable_mips_multilibs="yes"
+ ;;
+ mipsisa64r2*-*-linux-gnuabi64)
+ default_mips_abi=64
+ default_mips_arch=mips64r2
+ enable_mips_multilibs="yes"
+ ;;
+ mipsisa64r2*-*-linux*)
+ default_mips_abi=n32
+ default_mips_arch=mips64r2
+ enable_mips_multilibs="yes"
+ ;;
+ mips64*-*-linux-gnuabi64 | mipsisa64*-*-linux-gnuabi64)
+ default_mips_abi=64
+ enable_mips_multilibs="yes"
+ ;;
+ mips64*-*-linux* | mipsisa64*-*-linux*)
+ default_mips_abi=n32
+ enable_mips_multilibs="yes"
+ ;;
+ esac
+ if test x$enable_targets = xall; then
+ enable_mips_multilibs="yes"
+ fi
+ if test x$enable_mips_multilibs = xyes; then
+ tmake_file="${tmake_file} mips/t-linux64"
+ fi
+ ;;
+mips*-mti-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h mips/sde.h mips/mti-elf.h"
+ tmake_file="mips/t-mti-elf"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32"
+ with_arch_32="mips32r2"
+ with_arch_64="mips64r2"
+ ;;
+mips*-img-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h mips/sde.h mips/mti-elf.h"
+ tmake_file="mips/t-img-elf"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32"
+ with_arch_32="mips32r6"
+ with_arch_64="mips64r6"
+ ;;
+mips*-sde-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h mips/sde.h"
+ tmake_file="mips/t-sde"
+ extra_options="${extra_options} mips/sde.opt"
+ case "${with_newlib}" in
+ yes)
+ # newlib / libgloss.
+ ;;
+ *)
+ # MIPS toolkit libraries.
+ tm_file="$tm_file mips/sdemtk.h"
+ tmake_file="$tmake_file mips/t-sdemtk"
+ case ${enable_threads} in
+ "" | yes | mipssde)
+ thread_file='mipssde'
+ ;;
+ esac
+ ;;
+ esac
+ case ${target} in
+ mipsisa32r6*)
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6 MIPS_ABI_DEFAULT=ABI_32"
+ ;;
+ mipsisa32r2*)
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2 MIPS_ABI_DEFAULT=ABI_32"
+ ;;
+ mipsisa32*)
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32 MIPS_ABI_DEFAULT=ABI_32"
+ ;;
+ mipsisa64r6*)
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6 MIPS_ABI_DEFAULT=ABI_N32"
+ ;;
+ mipsisa64r2*)
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2 MIPS_ABI_DEFAULT=ABI_N32"
+ ;;
+ mipsisa64*)
+ tm_defines="MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_ABI_DEFAULT=ABI_N32"
+ ;;
+ esac
+ ;;
+mipsisa32-*-elf* | mipsisa32el-*-elf* | \
+mipsisa32r2-*-elf* | mipsisa32r2el-*-elf* | \
+mipsisa32r6-*-elf* | mipsisa32r6el-*-elf* | \
+mipsisa64-*-elf* | mipsisa64el-*-elf* | \
+mipsisa64r2-*-elf* | mipsisa64r2el-*-elf* | \
+mipsisa64r6-*-elf* | mipsisa64r6el-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
+ tmake_file="mips/t-isa3264"
+ case ${target} in
+ mipsisa32r6*)
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6"
+ ;;
+ mipsisa32r2*)
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2"
+ ;;
+ mipsisa32*)
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32"
+ ;;
+ mipsisa64r6*)
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6"
+ ;;
+ mipsisa64r2*)
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2"
+ ;;
+ mipsisa64*)
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64"
+ ;;
+ esac
+ case ${target} in
+ mipsisa32*-*-elfoabi*)
+ tm_defines="${tm_defines} MIPS_ABI_DEFAULT=ABI_32"
+ tm_file="${tm_file} mips/elfoabi.h"
+ ;;
+ mipsisa64*-*-elfoabi*)
+ tm_defines="${tm_defines} MIPS_ABI_DEFAULT=ABI_O64"
+ tm_file="${tm_file} mips/elfoabi.h"
+ ;;
+ *-*-elf*)
+ tm_defines="${tm_defines} MIPS_ABI_DEFAULT=ABI_EABI"
+ ;;
+ esac
+ ;;
+mipsisa64sr71k-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
+ tmake_file=mips/t-sr71k
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_CPU_STRING_DEFAULT=\\\"sr71000\\\" MIPS_ABI_DEFAULT=ABI_EABI"
+ ;;
+mipsisa64sb1-*-elf* | mipsisa64sb1el-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
+ tmake_file="mips/t-elf mips/t-sb1"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64"
+ ;;
+mips-*-elf* | mipsel-*-elf* | mipsr5900-*-elf* | mipsr5900el-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
+ tmake_file="mips/t-elf"
+ ;;
+mips64r5900-*-elf* | mips64r5900el-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/n32-elf.h"
+ tmake_file="mips/t-elf"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3 MIPS_ABI_DEFAULT=ABI_N32"
+ ;;
+mips64-*-elf* | mips64el-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
+ tmake_file="mips/t-elf"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3 MIPS_ABI_DEFAULT=ABI_O64"
+ ;;
+mips64vr-*-elf* | mips64vrel-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/vr.h mips/elf.h"
+ tmake_file=mips/t-vr
+ tm_defines="${tm_defines} MIPS_ABI_DEFAULT=ABI_EABI"
+ ;;
+mips64orion-*-elf* | mips64orionel-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elforion.h mips/elf.h"
+ tmake_file="mips/t-elf"
+ tm_defines="${tm_defines} MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3 MIPS_ABI_DEFAULT=ABI_O64"
+ ;;
+mips*-*-rtems*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/rtems.h rtems.h"
+ tmake_file="${tmake_file} mips/t-elf mips/t-rtems"
+ ;;
+mips-wrs-vxworks)
+ tm_file="elfos.h ${tm_file} mips/elf.h vx-common.h vxworks.h mips/vxworks.h"
+ tmake_file="${tmake_file} mips/t-vxworks"
+ ;;
+mipstx39-*-elf* | mipstx39el-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file} mips/r3900.h mips/elf.h"
+ tmake_file="mips/t-r3900"
+ ;;
+mmix-knuth-mmixware)
+ tm_file="${tm_file} newlib-stdint.h"
+ use_gcc_stdint=wrap
+ ;;
+mn10300-*-*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ use_collect2=no
+ use_gcc_stdint=wrap
+ ;;
+msp430-*-*)
+ tm_file="dbxelf.h 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"
+ extra_objs="${extra_objs} msp430-devices.o"
+ extra_gcc_objs="driver-msp430.o msp430-devices.o"
+ # Enable .init_array unless it has been explicitly disabled.
+ # The MSP430 EABI mandates the use of .init_array, and the Newlib CRT
+ # code since mid-2019 expects it.
+ if test x${disable_initfini_array} != xyes; then
+ gcc_cv_initfini_array=yes
+ fi
+ case ${target} in
+ msp430-*-elfbare)
+ # __cxa_atexit increases code size, and we don't need to support
+ # dynamic shared objects on MSP430, so regular Newlib atexit is a
+ # fine replacement as it also supports registration of more than 32
+ # functions.
+ default_use_cxa_atexit=no
+ # This target does not match the generic *-*-elf case above which
+ # sets use_gcc_stdint=wrap, so explicitly set it here.
+ use_gcc_stdint=wrap
+ ;;
+ esac
+ ;;
+nds32*-*-*)
+ target_cpu_default="0"
+ tm_defines="${tm_defines}"
+ case ${target} in
+ nds32le*-*-*)
+ ;;
+ nds32be-*-*)
+ target_cpu_default="${target_cpu_default}|MASK_BIG_ENDIAN"
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ case ${target} in
+ nds32*-*-elf*)
+ tm_file="dbxelf.h 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"
+ tmake_file="${tmake_file} nds32/t-nds32 nds32/t-linux"
+ gcc_cv_initfini_array=yes
+ ;;
+ esac
+
+ # Handle --enable-default-relax setting.
+ if test x${enable_default_relax} = xyes; then
+ tm_defines="${tm_defines} TARGET_DEFAULT_RELAX=1"
+ fi
+ # Handle --with-ext-dsp
+ if test x${with_ext_dsp} = xyes; then
+ tm_defines="${tm_defines} TARGET_DEFAULT_EXT_DSP=1"
+ fi
+ ;;
+nios2-*-*)
+ tm_file="elfos.h ${tm_file}"
+ tmake_file="${tmake_file} nios2/t-nios2"
+ case ${target} in
+ nios2-*-linux*)
+ tm_file="${tm_file} gnu-user.h linux.h glibc-stdint.h nios2/linux.h "
+ ;;
+ nios2-*-elf*)
+ tm_file="${tm_file} newlib-stdint.h nios2/elf.h"
+ extra_options="${extra_options} nios2/elf.opt"
+ ;;
+ nios2-*-rtems*)
+ tm_file="${tm_file} newlib-stdint.h nios2/rtems.h rtems.h"
+ tmake_file="${tmake_file} t-rtems nios2/t-rtems"
+ ;;
+ esac
+ ;;
+nvptx-*)
+ tm_file="${tm_file} newlib-stdint.h"
+ use_gcc_stdint=wrap
+ tmake_file="nvptx/t-nvptx"
+ if test x$enable_as_accelerator = xyes; then
+ extra_programs="${extra_programs} mkoffload\$(exeext)"
+ tm_file="${tm_file} nvptx/offload.h"
+ fi
+ ;;
+or1k*-*-*)
+ tm_file="elfos.h ${tm_file}"
+ tmake_file="${tmake_file} or1k/t-or1k"
+ # Force .init_array support. The configure script cannot always
+ # automatically detect that GAS supports it, yet we require it.
+ gcc_cv_initfini_array=yes
+
+ # Handle --with-multilib-list=...
+ or1k_multilibs="${with_multilib_list}"
+ if test "$or1k_multilibs" = "default"; then
+ or1k_multilibs="mcmov,msoft-mul,msoft-div"
+ fi
+ or1k_multilibs=`echo $or1k_multilibs | sed -e 's/,/ /g'`
+ for or1k_multilib in ${or1k_multilibs}; do
+ case ${or1k_multilib} in
+ mcmov | msext | msfimm | \
+ mror | mrori | \
+ mhard-float | mdouble-float | munordered-float | msoft-float | \
+ mhard-div | mhard-mul | \
+ msoft-div | msoft-mul )
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG},${or1k_multilib}"
+ ;;
+ *)
+ echo "--with-multilib-list=${with_multilib_list} not supported."
+ exit 1
+ esac
+ done
+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's/^,//'`
+
+ case ${target} in
+ or1k*-*-linux*)
+ tm_file="${tm_file} gnu-user.h linux.h glibc-stdint.h"
+ tm_file="${tm_file} or1k/linux.h"
+ ;;
+ or1k*-*-elf*)
+ tm_file="${tm_file} newlib-stdint.h or1k/elf.h"
+ extra_options="${extra_options} or1k/elf.opt"
+ ;;
+ or1k*-*-rtems*)
+ tm_file="${tm_file} newlib-stdint.h or1k/rtems.h rtems.h"
+ tmake_file="${tmake_file} or1k/t-rtems"
+ ;;
+ esac
+ ;;
+pdp11-*-*)
+ tm_file="${tm_file} newlib-stdint.h"
+ use_gcc_stdint=wrap
+ ;;
+# port not yet contributed
+#powerpc-*-openbsd*)
+# tmake_file="${tmake_file} rs6000/t-fprules"
+# extra_headers=
+# ;;
+powerpc-*-darwin*)
+ extra_options="${extra_options} ${cpu_type}/darwin.opt"
+ case ${target} in
+ *-darwin1[0-9]* | *-darwin9*)
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin32-biarch"
+ tm_file="${tm_file} ${cpu_type}/darwin32-biarch.h"
+ ;;
+ *-darwin8*)
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin32-biarch"
+ tm_file="${tm_file} ${cpu_type}/darwin32-biarch.h"
+ ;;
+ *-darwin7*)
+ tm_file="${tm_file} ${cpu_type}/darwin7.h"
+ ;;
+ *-darwin[456]*)
+ # Earlier - ingle arch, with 32b only
+ # OS X 10.0, the first edition is Darwin4
+ ;;
+ esac
+ tmake_file="${tmake_file} t-slibgcc"
+ ;;
+powerpc64-*-darwin*)
+ extra_options="${extra_options} ${cpu_type}/darwin.opt"
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin64-biarch t-slibgcc"
+ 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"
+ extra_options="${extra_options} rs6000/sysv4.opt"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
+ case ${target} in
+ powerpc*le-*-*)
+ tm_file="${tm_file} rs6000/sysv4le.h" ;;
+ esac
+ case ${target} in
+ powerpc64*)
+ tm_file="${tm_file} rs6000/default64.h rs6000/freebsd64.h"
+ tmake_file="${tmake_file} rs6000/t-freebsd64"
+ extra_options="${extra_options} rs6000/linux64.opt"
+ if test $fbsd_major -ge 13; then
+ tm_defines="${tm_defines} TARGET_FREEBSD32_SECURE_PLT=1"
+ fi
+ ;;
+ *)
+ if test $fbsd_major -ge 13; then
+ tm_file="rs6000/secureplt.h ${tm_file}"
+ fi
+ tm_file="${tm_file} rs6000/freebsd.h"
+ ;;
+ 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"
+ 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"
+ 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"
+ 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"
+ 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"
+ 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"
+ 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"
+ 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"
+ extra_options="${extra_options} rs6000/sysv4.opt"
+ tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-ppccomm"
+ extra_objs="$extra_objs rs6000-linux.o"
+ case ${target} in
+ powerpc*le-*-*)
+ tm_file="${tm_file} rs6000/sysv4le.h" ;;
+ esac
+ case ${target}:${with_cpu} in
+ powerpc64*: | powerpc64*:native) cpu_is_64bit=yes ;;
+ esac
+ maybe_biarch=${cpu_is_64bit}
+ case ${enable_targets} in
+ *powerpc64*) maybe_biarch=yes ;;
+ all) maybe_biarch=yes ;;
+ esac
+ case ${target}:${enable_targets}:${maybe_biarch} in
+ powerpc64-* | powerpc-*:*:yes | *:*powerpc64-*:yes | *:all:yes \
+ | powerpc64le*:*powerpcle* | powerpc64le*:*powerpc-* \
+ | powerpcle-*:*powerpc64le*:yes)
+ if test x$cpu_is_64bit = xyes; then
+ tm_file="${tm_file} rs6000/default64.h"
+ fi
+ tm_file="rs6000/biarch64.h ${tm_file} rs6000/linux64.h glibc-stdint.h"
+ tmake_file="$tmake_file rs6000/t-linux64"
+ case ${target} in
+ powerpc*le-*-*)
+ tmake_file="$tmake_file rs6000/t-linux64le"
+ case ${enable_targets} in
+ all | *powerpc64-* | *powerpc-*)
+ tmake_file="$tmake_file rs6000/t-linux64lebe" ;;
+ esac ;;
+ *)
+ case ${enable_targets} in
+ all | *powerpc64le-* | *powerpcle-*)
+ tmake_file="$tmake_file rs6000/t-linux64bele" ;;
+ esac ;;
+ esac
+ extra_options="${extra_options} rs6000/linux64.opt"
+ ;;
+ powerpc64*)
+ tm_file="${tm_file} rs6000/default64.h rs6000/linux64.h glibc-stdint.h"
+ extra_options="${extra_options} rs6000/linux64.opt"
+ tmake_file="${tmake_file} rs6000/t-linux"
+ ;;
+ *)
+ tm_file="${tm_file} rs6000/linux.h glibc-stdint.h"
+ tmake_file="${tmake_file} rs6000/t-ppcos rs6000/t-linux"
+ ;;
+ esac
+ case ${target} in
+ powerpc*-*-linux*ppc476*)
+ tm_file="${tm_file} rs6000/476.h"
+ extra_options="${extra_options} rs6000/476.opt" ;;
+ powerpc*-*-linux*altivec*)
+ tm_file="${tm_file} rs6000/linuxaltivec.h" ;;
+ esac
+ case ${target} in
+ *-linux*-musl*)
+ enable_secureplt=yes ;;
+ esac
+ if test x${enable_secureplt} = xyes; then
+ tm_file="rs6000/secureplt.h ${tm_file}"
+ fi
+ ;;
+powerpc*-wrs-vxworks7r*)
+
+ # Wind River 7 post SR0600 is mostly like Linux so we setup
+ # our config in a very similar fashion and adjust to a few
+ # specificities.
+
+ # The system compiler is configured with secureplt by default.
+ tm_file="${tm_file} rs6000/secureplt.h"
+
+ tm_file="${tm_file} elfos.h gnu-user.h linux.h freebsd-spec.h"
+ tm_file="${tm_file} rs6000/sysv4.h rs6000/biarch64.h rs6000/default64.h rs6000/linux64.h"
+ tm_file="${tm_file} vx-common.h vxworks.h rs6000/vxworks.h"
+
+ extra_options="${extra_options} rs6000/sysv4.opt linux.opt rs6000/linux64.opt"
+
+ tmake_file="${tmake_file} t-linux rs6000/t-linux64 rs6000/t-fprules rs6000/t-ppccomm"
+ tmake_file="${tmake_file} rs6000/t-vxworks"
+
+ tm_defines="$tm_defines DEFAULT_LIBC=LIBC_GLIBC"
+ extra_objs="$extra_objs linux.o rs6000-linux.o"
+ ;;
+powerpc-wrs-vxworks*)
+ tm_file="${tm_file} elfos.h gnu-user.h freebsd-spec.h rs6000/sysv4.h"
+ tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-ppccomm rs6000/t-vxworks"
+ extra_options="${extra_options} rs6000/sysv4.opt"
+ extra_headers="${extra_headers} ppc-asm.h"
+ case ${target} in
+ *-vxworksmils*)
+ tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/vxworksmils.h"
+ tmake_file="${tmake_file} rs6000/t-vxworksmils"
+ ;;
+ *-vxworksae*)
+ tm_file="${tm_file} vx-common.h vxworksae.h rs6000/vxworks.h rs6000/vxworksae.h"
+ tmake_file="${tmake_file} rs6000/t-vxworksae"
+ ;;
+ *-vxworks*)
+ tm_file="${tm_file} vx-common.h vxworks.h rs6000/vxworks.h"
+ ;;
+ esac
+ ;;
+powerpc-*-lynxos*)
+ xm_defines=POSIX
+ tm_file="${tm_file} dbxelf.h 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
+ gnu_ld=yes
+ 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"
+ 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"
+ 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"
+ tmake_file="rs6000/t-fprules rs6000/t-ppcgas rs6000/t-ppccomm"
+ extra_options="${extra_options} rs6000/sysv4.opt"
+ use_gcc_stdint=wrap
+ ;;
+pru*-*-*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file="${tmake_file} pru/t-pru"
+ extra_objs="pru-pragma.o pru-passes.o"
+ use_gcc_stdint=wrap
+ ;;
+rs6000-ibm-aix7.1.* | powerpc-ibm-aix7.1.*)
+ tmake_file="rs6000/t-aix52 t-slibgcc"
+ if test x$cpu_is_64bit = xyes; then
+ tm_file="${tm_file} rs6000/biarch64.h"
+ tmake_file="rs6000/t-aix64 t-slibgcc"
+ fi
+ tm_file="${tm_file} rs6000/aix.h rs6000/aix71.h rs6000/xcoff.h rs6000/aix-stdint.h"
+ extra_options="${extra_options} rs6000/aix64.opt"
+ use_collect2=yes
+ thread_file='aix'
+ use_gcc_stdint=wrap
+ default_use_cxa_atexit=yes
+ ;;
+rs6000-ibm-aix7.2.* | powerpc-ibm-aix7.2.*)
+ tmake_file="rs6000/t-aix52 t-slibgcc"
+ if test x$cpu_is_64bit = xyes; then
+ tm_file="${tm_file} rs6000/biarch64.h"
+ tmake_file="rs6000/t-aix64 t-slibgcc"
+ fi
+ tm_file="${tm_file} rs6000/aix.h rs6000/aix72.h rs6000/xcoff.h rs6000/aix-stdint.h"
+ extra_options="${extra_options} rs6000/aix64.opt"
+ use_collect2=yes
+ thread_file='aix'
+ use_gcc_stdint=wrap
+ default_use_cxa_atexit=yes
+ ;;
+rs6000-ibm-aix[789].* | powerpc-ibm-aix[789].*)
+ tmake_file="rs6000/t-aix52 t-slibgcc"
+ if test x$cpu_is_64bit = xyes; then
+ tm_file="${tm_file} rs6000/biarch64.h"
+ tmake_file="rs6000/t-aix64 t-slibgcc"
+ fi
+ tm_file="${tm_file} rs6000/aix.h rs6000/aix73.h rs6000/xcoff.h rs6000/aix-stdint.h"
+ extra_options="${extra_options} rs6000/aix64.opt"
+ use_collect2=yes
+ thread_file='aix'
+ use_gcc_stdint=wrap
+ default_use_cxa_atexit=yes
+ ;;
+rl78-*-elf*)
+ tm_file="elfos.h newlib-stdint.h ${tm_file}"
+ target_has_targetm_common=no
+ c_target_objs="rl78-c.o"
+ cxx_target_objs="rl78-c.o"
+ tmake_file="${tmake_file} rl78/t-rl78"
+ ;;
+rx-*-elf*)
+ tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
+ tmake_file="${tmake_file} rx/t-rx"
+ extra_options="${extra_options} rx/elf.opt"
+ ;;
+rx-*-linux*)
+ tm_file="elfos.h linux.h glibc-stdint.h rx/linux.h ../../libgcc/config/rx/rx-abi.h"
+ 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"
+ 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
+ tmake_file="${tmake_file} s390/t-linux64"
+ fi
+ 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_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"
+ md_file=s390/s390.md
+ extra_modes=s390/s390-modes.def
+ out_file=s390/s390.cc
+ 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_p_file=s390/s390-protos.h
+ c_target_objs="${c_target_objs} s390-c.o"
+ cxx_target_objs="${cxx_target_objs} s390-c.o"
+ md_file=s390/s390.md
+ extra_modes=s390/s390-modes.def
+ out_file=s390/s390.cc
+ thread_file='tpf'
+ extra_options="${extra_options} s390/tpf.opt"
+ tmake_file="${tmake_file} s390/t-s390"
+ ;;
+sh-*-elf* | sh[12346l]*-*-elf* | \
+ sh-*-linux* | sh[2346lbe]*-*-linux* | \
+ sh-*-netbsdelf* | shl*-*-netbsdelf*)
+ tmake_file="${tmake_file} sh/t-sh sh/t-elf"
+ if test x${with_endian} = x; then
+ case ${target} in
+ sh[1234]*be-*-* | sh[1234]*eb-*-*) with_endian=big ;;
+ shbe-*-* | sheb-*-*) with_endian=big,little ;;
+ sh[1234]l* | sh[34]*-*-linux*) with_endian=little ;;
+ shl* | sh*-*-linux* | \
+ sh-superh-elf) with_endian=little,big ;;
+ sh[1234]*-*-*) with_endian=big ;;
+ *) with_endian=big,little ;;
+ esac
+ fi
+ # TM_ENDIAN_CONFIG is used by t-sh to determine multilibs.
+ # First word : the default endian.
+ # Second word: the secondary endian (optional).
+ case ${with_endian} in
+ big) TM_ENDIAN_CONFIG=mb ;;
+ little) TM_ENDIAN_CONFIG=ml ;;
+ big,little) TM_ENDIAN_CONFIG="mb ml" ;;
+ little,big) TM_ENDIAN_CONFIG="ml mb" ;;
+ *) echo "with_endian=${with_endian} not supported."; exit 1 ;;
+ esac
+ case ${with_endian} in
+ little*) tm_file="sh/little.h ${tm_file}" ;;
+ esac
+ tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h"
+ case ${target} in
+ sh*-*-linux*) tmake_file="${tmake_file} sh/t-linux"
+ if test x$enable_fdpic = xyes; then
+ tm_defines="$tm_defines FDPIC_DEFAULT=1"
+ fi
+ tm_file="${tm_file} gnu-user.h linux.h glibc-stdint.h sh/linux.h" ;;
+ sh*-*-netbsd*)
+ tm_file="${tm_file} ${nbsd_tm_file} sh/netbsd-elf.h"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
+
+ ;;
+ sh*-superh-elf) if test x$with_libgloss != xno; then
+ with_libgloss=yes
+ tm_file="${tm_file} sh/newlib.h"
+ fi
+ tm_file="${tm_file} sh/embed-elf.h"
+ tm_file="${tm_file} sh/superh.h"
+ extra_options="${extra_options} sh/superh.opt" ;;
+ *) if test x$with_newlib = xyes \
+ && test x$with_libgloss = xyes; then
+ tm_file="${tm_file} sh/newlib.h"
+ fi
+ tm_file="${tm_file} sh/embed-elf.h" ;;
+ esac
+ case ${target} in
+ *-*-netbsd)
+ ;;
+ *-*-elf*)
+ tm_file="${tm_file} newlib-stdint.h"
+ ;;
+ esac
+ # sed el/eb endian suffixes away to avoid confusion with sh[23]e
+ case `echo ${target} | sed 's/e[lb]-/-/'` in
+ sh4a_single_only*) sh_cpu_target=sh4a-single-only ;;
+ sh4a_single*) sh_cpu_target=sh4a-single ;;
+ sh4a_nofpu*) sh_cpu_target=sh4a-nofpu ;;
+ sh4al) sh_cpu_target=sh4al ;;
+ sh4a*) sh_cpu_target=sh4a ;;
+ sh4_single_only*) sh_cpu_target=sh4-single-only ;;
+ sh4_single*) sh_cpu_target=sh4-single ;;
+ sh4_nofpu*) sh_cpu_target=sh4-nofpu ;;
+ sh4* | sh-superh-*) sh_cpu_target=sh4 ;;
+ sh3e*) sh_cpu_target=sh3e ;;
+ sh*-*-netbsd* | sh3*) sh_cpu_target=sh3 ;;
+ sh2a_single_only*) sh_cpu_target=sh2a-single-only ;;
+ sh2a_single*) sh_cpu_target=sh2a-single ;;
+ sh2a_nofpu*) sh_cpu_target=sh2a-nofpu ;;
+ sh2a*) sh_cpu_target=sh2a ;;
+ sh2e*) sh_cpu_target=sh2e ;;
+ sh2*) sh_cpu_target=sh2 ;;
+ *) sh_cpu_target=sh1 ;;
+ esac
+ # did the user say --without-fp ?
+ if test x$with_fp = xno; then
+ case ${sh_cpu_target} in
+ sh4al | sh1) ;;
+ sh4a* ) sh_cpu_target=sh4a-nofpu ;;
+ sh4*) sh_cpu_target=sh4-nofpu ;;
+ sh3*) sh_cpu_target=sh3 ;;
+ sh2a*) sh_cpu_target=sh2a-nofpu ;;
+ sh2*) sh_cpu_target=sh2 ;;
+ *) echo --without-fp not available for $target: ignored
+ esac
+ tm_defines="$tm_defines STRICT_NOFPU=1"
+ fi
+ sh_cpu_default="`echo $with_cpu|sed s/^m/sh/|tr A-Z_ a-z-`"
+ case $sh_cpu_default in
+ sh2a-single-only | sh2a-single | sh2a-nofpu | sh2a | \
+ sh4a-single-only | sh4a-single | sh4a-nofpu | sh4a | sh4al | \
+ sh4-single-only | sh4-single | sh4-nofpu | sh4 | sh4-300 | \
+ sh3e | sh3 | sh2e | sh2 | sh1) ;;
+ "") sh_cpu_default=${sh_cpu_target} ;;
+ *) echo "with_cpu=$with_cpu not supported"; exit 1 ;;
+ esac
+ sh_multilibs=${with_multilib_list}
+ if test "$sh_multilibs" = "default" ; then
+ case ${target} in
+ sh[1234]*) sh_multilibs=${sh_cpu_target} ;;
+ sh-superh-*) sh_multilibs=m4,m4-single,m4-single-only,m4-nofpu ;;
+ sh*-*-linux*) sh_multilibs=m1,m2,m2a,m3e,m4 ;;
+ sh*-*-netbsd*) sh_multilibs=m3,m3e,m4 ;;
+ *) sh_multilibs=m1,m2,m2e,m4,m4-single,m4-single-only,m2a,m2a-single ;;
+ esac
+ if test x$with_fp = xno; then
+ sh_multilibs="`echo $sh_multilibs|sed -e s/m4/sh4-nofpu/ -e s/,m4-[^,]*//g -e s/,m[23]e// -e s/m2a,m2a-single/m2a-nofpu/ -e s/m5-..m....,//g`"
+ fi
+ fi
+ target_cpu_default=SELECT_`echo ${sh_cpu_default}|tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
+ tm_defines=${tm_defines}' SH_MULTILIB_CPU_DEFAULT=\"'`echo $sh_cpu_default|sed s/sh/m/`'\"'
+ tm_defines="$tm_defines SUPPORT_`echo $sh_cpu_default | sed 's/^m/sh/' | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`=1"
+ sh_multilibs=`echo $sh_multilibs | sed -e 's/,/ /g' -e 's/^[Ss][Hh]/m/' -e 's/ [Ss][Hh]/ m/g' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ_ abcdefghijklmnopqrstuvwxyz-`
+ for sh_multilib in ${sh_multilibs}; do
+ case ${sh_multilib} in
+ m1 | m2 | m2e | m3 | m3e | \
+ m4 | m4-single | m4-single-only | m4-nofpu | m4-300 |\
+ m4a | m4a-single | m4a-single-only | m4a-nofpu | m4al | \
+ m2a | m2a-single | m2a-single-only | m2a-nofpu)
+ # TM_MULTILIB_CONFIG is used by t-sh for the non-endian multilib definition
+ # It is passed to MULTIILIB_OPTIONS verbatim.
+ TM_MULTILIB_CONFIG="${TM_MULTILIB_CONFIG}/${sh_multilib}"
+ tm_defines="$tm_defines SUPPORT_`echo $sh_multilib | sed 's/^m/sh/' | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`=1"
+ ;;
+ \!*) # TM_MULTILIB_EXCEPTIONS_CONFIG is used by t-sh
+ # It is passed the MULTILIB_EXCEPTIONS verbatim.
+ TM_MULTILIB_EXCEPTIONS_CONFIG="${TM_MULTILIB_EXCEPTIONS_CONFIG} `echo $sh_multilib | sed 's/^!//'`" ;;
+ *)
+ echo "with_multilib_list=${sh_multilib} not supported."
+ exit 1
+ ;;
+ esac
+ done
+ TM_MULTILIB_CONFIG=`echo $TM_MULTILIB_CONFIG | sed 's:^/::'`
+ if test x${enable_incomplete_targets} = xyes ; then
+ tm_defines="$tm_defines SUPPORT_SH1=1 SUPPORT_SH2E=1 SUPPORT_SH4=1 SUPPORT_SH4_SINGLE=1 SUPPORT_SH2A=1 SUPPORT_SH2A_SINGLE=1"
+ fi
+ tm_file="$tm_file ./sysroot-suffix.h"
+ tmake_file="$tmake_file t-sysroot-suffix"
+ ;;
+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"
+ ;;
+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"
+ case ${target} in
+ *-leon-*)
+ tmake_file="sparc/t-sparc sparc/t-leon"
+ ;;
+ *-leon[3-9]*)
+ tmake_file="sparc/t-sparc sparc/t-leon3"
+ ;;
+ *)
+ tmake_file="sparc/t-sparc sparc/t-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"
+ 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"
+ extra_options="${extra_options} sparc/long-double-switch.opt"
+ case ${target} in
+ *-leon-*)
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-leon"
+ ;;
+ *-leon[3-9]*)
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-leon3"
+ ;;
+ *)
+ tmake_file="${tmake_file} sparc/t-sparc"
+ ;;
+ esac
+ if test x$enable_targets = xall; then
+ tm_file="sparc/biarch64.h ${tm_file} sparc/linux64.h"
+ tmake_file="${tmake_file} sparc/t-linux64"
+ else
+ tm_file="${tm_file} sparc/linux.h"
+ tmake_file="${tmake_file} sparc/t-linux"
+ fi
+ ;;
+sparc-*-netbsdelf*)
+ tm_file="${tm_file} dbxelf.h 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*-*-solaris2*)
+ tm_file="sparc/biarch64.h ${tm_file} ${sol2_tm_file} sparc/tso.h"
+ case ${target} in
+ sparc64-*-* | sparcv9-*-*)
+ tm_file="sparc/default64.h ${tm_file}"
+ ;;
+ *)
+ test x$with_cpu != x || with_cpu=v9
+ ;;
+ esac
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-sol2"
+ ;;
+sparc-wrs-vxworks)
+ tm_file="${tm_file} elfos.h sparc/sysv4.h vx-common.h vxworks.h sparc/vxworks.h"
+ 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"
+ 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"
+ 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"
+ 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"
+ extra_options="${extra_options} sparc/long-double-switch.opt"
+ case "x$with_cpu" in
+ xultrasparc) ;;
+ x) with_cpu=ultrasparc ;;
+ *) echo "$with_cpu not supported for freebsd target"; exit 1 ;;
+ esac
+ tmake_file="${tmake_file} sparc/t-sparc"
+ ;;
+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"
+ 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="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h sparc/openbsd64.h"
+ extra_options="${extra_options} openbsd.opt"
+ extra_options="${extra_options}"
+ gas=yes gnu_ld=yes
+ with_cpu=ultrasparc
+ tmake_file="${tmake_file} sparc/t-sparc"
+ ;;
+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"
+ 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} ./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"
+ use_collect2=no
+ ;;
+tilegx*-*-linux*)
+ tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h tilegx/linux.h ${tm_file}"
+ tmake_file="${tmake_file} tilegx/t-tilegx"
+ extra_objs="${extra_objs} mul-tables.o"
+ c_target_objs="${c_target_objs} tilegx-c.o"
+ cxx_target_objs="${cxx_target_objs} tilegx-c.o"
+ extra_headers="feedback.h"
+ case $target in
+ tilegxbe-*)
+ tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
+ ;;
+ esac
+ ;;
+tilepro*-*-linux*)
+ tm_file="elfos.h gnu-user.h linux.h glibc-stdint.h tilepro/linux.h ${tm_file}"
+ tmake_file="${tmake_file} tilepro/t-tilepro"
+ extra_objs="${extra_objs} mul-tables.o"
+ c_target_objs="${c_target_objs} tilepro-c.o"
+ cxx_target_objs="${cxx_target_objs} tilepro-c.o"
+ extra_headers="feedback.h"
+ ;;
+v850-*-rtems*)
+ target_cpu_default="TARGET_CPU_generic"
+ tm_file="elfos.h v850/v850.h"
+ tm_file="${tm_file} v850/rtems.h rtems.h newlib-stdint.h"
+ tmake_file="${tmake_file} v850/t-v850"
+ tmake_file="${tmake_file} v850/t-rtems"
+ use_collect2=no
+ c_target_objs="v850-c.o"
+ cxx_target_objs="v850-c.o"
+ ;;
+v850*-*-*)
+ case ${target} in
+ v850e3v5-*-*)
+ target_cpu_default="TARGET_CPU_v850e3v5"
+ ;;
+ v850e2v3-*-*)
+ target_cpu_default="TARGET_CPU_v850e2v3"
+ ;;
+ v850e2-*-*)
+ target_cpu_default="TARGET_CPU_v850e2"
+ ;;
+ v850e1-*-* | v850es-*-*)
+ target_cpu_default="TARGET_CPU_v850e1"
+ ;;
+ v850e-*-*)
+ target_cpu_default="TARGET_CPU_v850e"
+ ;;
+ v850-*-*)
+ target_cpu_default="TARGET_CPU_generic"
+ ;;
+ esac
+ tm_file="elfos.h newlib-stdint.h v850/v850.h"
+ use_collect2=no
+ c_target_objs="v850-c.o"
+ cxx_target_objs="v850-c.o"
+ 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"
+ extra_options="${extra_options} vax/elf.opt"
+ ;;
+vax-*-netbsdelf*)
+ tm_file="${tm_file} elfos.h ${nbsd_tm_file} vax/elf.h vax/netbsd-elf.h"
+ extra_options="${extra_options} netbsd.opt netbsd-elf.opt vax/elf.opt"
+ 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"
+ 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_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
+ tmake_file="stormy16/t-stormy16"
+ ;;
+xtensa*-*-elf*)
+ tm_file="${tm_file} elfos.h newlib-stdint.h xtensa/elf.h"
+ extra_options="${extra_options} xtensa/elf.opt"
+ ;;
+xtensa*-*-linux*)
+ tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/linux.h"
+ tmake_file="${tmake_file} xtensa/t-xtensa"
+ ;;
+xtensa*-*-uclinux*)
+ tm_file="${tm_file} elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/uclinux.h"
+ tmake_file="${tmake_file} xtensa/t-xtensa"
+ extra_options="${extra_options} xtensa/uclinux.opt"
+ ;;
+am33_2.0-*-linux*)
+ tm_file="mn10300/mn10300.h elfos.h gnu-user.h linux.h glibc-stdint.h mn10300/linux.h"
+ 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"
+ cxx_target_objs="m32c-pragma.o"
+ ;;
+*)
+ echo "*** Configuration ${target} not supported" 1>&2
+ exit 1
+ ;;
+esac
+
+case ${target} in
+i[34567]86-*-linux* | x86_64-*-linux*)
+ tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
+ ;;
+i[34567]86-*-* | x86_64-*-*)
+ tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386"
+ ;;
+powerpc*-*-* | rs6000-*-*)
+ tm_file="${tm_file} ${cpu_type}/option-defaults.h"
+esac
+
+# non-glibc systems
+case ${target} in
+*-linux-musl*)
+ tmake_file="${tmake_file} t-musl"
+ ;;
+*-linux-uclibc*)
+ tmake_file="${tmake_file} t-uclibc"
+ ;;
+esac
+
+# Assume the existence of indirect function support and allow the use of the
+# resolver attribute.
+case ${target} in
+*-*-linux*android*|*-*-linux*uclibc*|*-*-linux*musl*)
+ ;;
+*-*-kfreebsd*-gnu | *-*-kopensolaris*-gnu)
+ ;;
+*-*-linux* | *-*-gnu*)
+ case ${target} in
+ aarch64*-* | arm*-* | i[34567]86-* | powerpc*-* | s390*-* | sparc*-* | x86_64-* | loongarch*-*)
+ default_gnu_indirect_function=yes
+ ;;
+ esac
+ ;;
+esac
+
+# Build mkoffload tool
+case ${target} in
+*-intelmic-* | *-intelmicemul-*)
+ tmake_file="${tmake_file} i386/t-intelmic"
+ tm_file="${tm_file} i386/intelmic-offload.h"
+ ;;
+esac
+
+if [ "$target_has_targetcm" = "no" ]; then
+ c_target_objs="$c_target_objs default-c.o"
+ cxx_target_objs="$cxx_target_objs default-c.o"
+fi
+
+if [ "$common_out_file" = "" ]; then
+ if [ "$target_has_targetm_common" = "yes" ]; then
+ common_out_file="$cpu_type/$cpu_type-common.cc"
+ else
+ common_out_file="default-common.cc"
+ fi
+fi
+
+if [ "$target_has_targetdm" = "no" ]; then
+ d_target_objs="$d_target_objs default-d.o"
+fi
+
+# Support for --with-cpu and related options (and a few unrelated options,
+# too).
+case ${with_cpu} in
+ yes | no)
+ echo "--with-cpu must be passed a value" 1>&2
+ exit 1
+ ;;
+esac
+
+# Set arch and cpu from ${target} and ${target_noncanonical}. Set cpu
+# to generic if there is no processor scheduler model for the target.
+arch=
+cpu=
+arch_without_sse2=no
+arch_without_64bit=no
+case ${target} in
+ i386-*-freebsd*)
+ if test $fbsd_major -ge 6; then
+ arch=i486
+ else
+ arch=i386
+ fi
+ cpu=generic
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ ;;
+ i386-*-netbsd*)
+ arch=i486
+ cpu=generic
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ ;;
+ i386-*-*)
+ arch=i386
+ cpu=i386
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ ;;
+ i486-*-*)
+ arch=i486
+ cpu=i486
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ ;;
+ i586-*-*)
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ case ${target_noncanonical} in
+ k6_2-*)
+ arch=k6-2
+ cpu=k6-2
+ ;;
+ k6_3-*)
+ arch=k6-3
+ cpu=k6-3
+ ;;
+ k6-*)
+ arch=k6
+ cpu=k6
+ ;;
+ pentium_mmx-*|winchip_c6-*|winchip2-*|c3-*)
+ arch=pentium-mmx
+ cpu=pentium-mmx
+ ;;
+ *)
+ arch=pentium
+ cpu=pentium
+ ;;
+ esac
+ ;;
+ i686-*-* | i786-*-*)
+ case ${target_noncanonical} in
+ znver1-*)
+ arch=znver1
+ cpu=znver1
+ ;;
+ znver2-*)
+ arch=znver2
+ cpu=znver2
+ ;;
+ znver3-*)
+ arch=znver3
+ cpu=znver3
+ ;;
+ bdver4-*)
+ arch=bdver4
+ cpu=bdver4
+ ;;
+ bdver3-*)
+ arch=bdver3
+ cpu=bdver3
+ ;;
+ bdver2-*)
+ arch=bdver2
+ cpu=bdver2
+ ;;
+ bdver1-*)
+ arch=bdver1
+ cpu=bdver1
+ ;;
+ btver1-*)
+ arch=btver1
+ cpu=btver1
+ ;;
+ btver2-*)
+ arch=btver2
+ cpu=btver2
+ ;;
+ amdfam10-*|barcelona-*)
+ arch=amdfam10
+ cpu=amdfam10
+ ;;
+ k8_sse3-*|opteron_sse3-*|athlon64_sse3-*)
+ arch=k8-sse3
+ cpu=k8-sse3
+ ;;
+ k8-*|opteron-*|athlon64-*|athlon_fx-*)
+ arch=k8
+ cpu=k8
+ ;;
+ athlon_xp-*|athlon_mp-*|athlon_4-*)
+ arch=athlon-4
+ cpu=athlon-4
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ ;;
+ athlon_tbird-*|athlon-*)
+ arch=athlon
+ cpu=athlon
+ arch_without_sse2=yes
+ ;;
+ geode-*)
+ arch=geode
+ cpu=geode
+ arch_without_sse2=yes
+ ;;
+ pentium2-*)
+ arch=pentium2
+ cpu=pentium2
+ arch_without_sse2=yes
+ ;;
+ pentium3-*|pentium3m-*)
+ arch=pentium3
+ cpu=pentium3
+ arch_without_sse2=yes
+ ;;
+ pentium4-*|pentium4m-*)
+ arch=pentium4
+ cpu=pentium4
+ ;;
+ prescott-*)
+ arch=prescott
+ cpu=prescott
+ ;;
+ nocona-*)
+ arch=nocona
+ cpu=nocona
+ ;;
+ atom-*)
+ arch=atom
+ cpu=atom
+ ;;
+ slm-*)
+ arch=slm
+ cpu=slm
+ ;;
+ core2-*)
+ arch=core2
+ cpu=core2
+ ;;
+ corei7-*)
+ arch=corei7
+ cpu=corei7
+ ;;
+ corei7_avx-*)
+ arch=corei7-avx
+ cpu=corei7-avx
+ ;;
+ pentium_m-*)
+ arch=pentium-m
+ cpu=pentium-m
+ ;;
+ pentiumpro-*)
+ arch=pentiumpro
+ cpu=pentiumpro
+ arch_without_sse2=yes
+ ;;
+ *)
+ arch=pentiumpro
+ cpu=generic
+ arch_without_sse2=yes
+ arch_without_64bit=yes
+ ;;
+ esac
+ ;;
+ x86_64-*-*)
+ case ${target_noncanonical} in
+ znver1-*)
+ arch=znver1
+ cpu=znver1
+ ;;
+ znver2-*)
+ arch=znver2
+ cpu=znver2
+ ;;
+ znver3-*)
+ arch=znver3
+ cpu=znver3
+ ;;
+ bdver4-*)
+ arch=bdver4
+ cpu=bdver4
+ ;;
+ bdver3-*)
+ arch=bdver3
+ cpu=bdver3
+ ;;
+ bdver2-*)
+ arch=bdver2
+ cpu=bdver2
+ ;;
+ bdver1-*)
+ arch=bdver1
+ cpu=bdver1
+ ;;
+ btver1-*)
+ arch=btver1
+ cpu=btver1
+ ;;
+ btver2-*)
+ arch=btver2
+ cpu=btver2
+ ;;
+ amdfam10-*|barcelona-*)
+ arch=amdfam10
+ cpu=amdfam10
+ ;;
+ k8_sse3-*|opteron_sse3-*|athlon64_sse3-*)
+ arch=k8-sse3
+ cpu=k8-sse3
+ ;;
+ k8-*|opteron-*|athlon_64-*)
+ arch=k8
+ cpu=k8
+ ;;
+ nocona-*)
+ arch=nocona
+ cpu=nocona
+ ;;
+ atom-*)
+ arch=atom
+ cpu=atom
+ ;;
+ slm-*)
+ arch=slm
+ cpu=slm
+ ;;
+ core2-*)
+ arch=core2
+ cpu=core2
+ ;;
+ corei7-*)
+ arch=corei7
+ cpu=corei7
+ ;;
+ *)
+ arch=x86-64
+ cpu=generic
+ ;;
+ esac
+ ;;
+esac
+
+# If there is no $with_cpu option, try to infer one from ${target}.
+# This block sets nothing except for with_cpu.
+if test x$with_cpu = x ; then
+ case ${target} in
+ i[34567]86-*-elfiamcu)
+ with_cpu=lakemont
+ ;;
+ i[34567]86-*-*|x86_64-*-*)
+ with_cpu=$cpu
+ ;;
+ alphaev6[78]*-*-*)
+ with_cpu=ev67
+ ;;
+ alphaev6*-*-*)
+ with_cpu=ev6
+ ;;
+ alphapca56*-*-*)
+ with_cpu=pca56
+ ;;
+ alphaev56*-*-*)
+ with_cpu=ev56
+ ;;
+ alphaev5*-*-*)
+ with_cpu=ev5
+ ;;
+ frv-*-*linux* | frv400-*-*linux*)
+ with_cpu=fr400
+ ;;
+ frv550-*-*linux*)
+ with_cpu=fr550
+ ;;
+ m68k*-*-*)
+ case "$with_arch" in
+ "cf")
+ with_cpu=${default_cf_cpu}
+ ;;
+ "" | "m68k")
+ with_cpu=m${default_m68k_cpu}
+ ;;
+ esac
+ ;;
+ sparc*-*-*)
+ case ${target} in
+ *-leon-*)
+ with_cpu=leon
+ ;;
+ *-leon[3-9]*)
+ with_cpu=leon3
+ ;;
+ *-leon[3-9]v7*)
+ with_cpu=leon3v7
+ ;;
+ *)
+ with_cpu="`echo ${target} | sed 's/-.*$//'`"
+ ;;
+ esac
+ ;;
+ visium-*-*)
+ with_cpu=gr5
+ ;;
+ esac
+
+ # Avoid overriding --with-cpu-32 and --with-cpu-64 values.
+ case ${target} in
+ i[34567]86-*-*|x86_64-*-*)
+ if test x$with_cpu_32 != x || test x$with_cpu_64 != x; then
+ if test x$with_cpu_32 = x; then
+ with_cpu_32=$with_cpu
+ fi
+ if test x$with_cpu_64 = x; then
+ with_cpu_64=$with_cpu
+ fi
+ with_cpu=
+ fi
+ ;;
+ esac
+fi
+
+# Support for --with-arch and related options (and a few unrelated options,
+# too).
+case ${with_arch} in
+ yes | no)
+ echo "--with-arch must be passed a value" 1>&2
+ exit 1
+ ;;
+esac
+
+# If there is no $with_arch option, try to infer one from ${target}.
+# This block sets nothing except for with_arch.
+if test x$with_arch = x ; then
+ case ${target} in
+ i[34567]86-*-darwin*|x86_64-*-darwin*)
+ # Default arch is set via TARGET_SUBTARGET32_ISA_DEFAULT
+ # and TARGET_SUBTARGET64_ISA_DEFAULT in config/i386/darwin.h.
+ ;;
+ i[34567]86-*-elfiamcu)
+ with_arch=lakemont
+ ;;
+ i[34567]86-*-*)
+ # --with-fpmath sets the default ISA to SSE2, which is the same
+ # ISA supported by Pentium 4.
+ if test x$with_fpmath = x || test $arch_without_sse2 = no; then
+ with_arch=$arch
+ else
+ with_arch=pentium4
+ fi
+ ;;
+ x86_64-*-*)
+ with_arch=$arch
+ ;;
+ mips64r5900-*-* | mips64r5900el-*-* | mipsr5900-*-* | mipsr5900el-*-*)
+ with_arch=r5900
+ ;;
+ mips*-*-vxworks)
+ with_arch=mips2
+ ;;
+ esac
+
+ # Avoid overriding --with-arch-32 and --with-arch-64 values.
+ case ${target} in
+ i[34567]86-*-darwin*|x86_64-*-darwin*)
+ # Default arch is set via TARGET_SUBTARGET32_ISA_DEFAULT
+ # and TARGET_SUBTARGET64_ISA_DEFAULT in config/i386/darwin.h.
+ ;;
+ i[34567]86-*-*|x86_64-*-*)
+ if test x$with_arch_32 != x || test x$with_arch_64 != x; then
+ if test x$with_arch_32 = x; then
+ with_arch_32=$with_arch
+ fi
+ if test x$with_arch_64 = x; then
+ if test $arch_without_64bit = yes; then
+ # Set the default 64bit arch to x86-64 if the default arch
+ # doesn't support 64bit.
+ with_arch_64=x86-64
+ else
+ with_arch_64=$with_arch
+ fi
+ fi
+ with_arch=
+ elif test $arch_without_64bit$need_64bit_isa = yesyes; then
+ # Set the default 64bit arch to x86-64 if the default arch
+ # doesn't support 64bit and we need 64bit ISA.
+ with_arch_32=$with_arch
+ with_arch_64=x86-64
+ with_arch=
+ fi
+ ;;
+ esac
+fi
+
+# Infer a default setting for --with-float.
+if test x$with_float = x; then
+ case ${target} in
+ mips64r5900-*-* | mips64r5900el-*-* | mipsr5900-*-* | mipsr5900el-*-*)
+ # The R5900 doesn't support 64-bit float. 32-bit float doesn't
+ # comply with IEEE 754.
+ with_float=soft
+ ;;
+ esac
+fi
+
+# Infer a default setting for --with-fpu.
+if test x$with_fpu = x; then
+ case ${target} in
+ mips64r5900-*-* | mips64r5900el-*-* | mipsr5900-*-* | mipsr5900el-*-*)
+ # The R5900 FPU only supports single precision.
+ with_fpu=single
+ ;;
+ esac
+fi
+
+# Support --with-fpmath.
+if test x$with_fpmath != x; then
+ case ${target} in
+ i[34567]86-*-* | x86_64-*-*)
+ case ${with_fpmath} in
+ avx)
+ tm_file="${tm_file} i386/avxmath.h"
+ ;;
+ sse)
+ tm_file="${tm_file} i386/ssemath.h"
+ ;;
+ *)
+ echo "Invalid --with-fpmath=$with_fpmath" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "--with-fpmath isn't supported for $target." 1>&2
+ exit 1
+ ;;
+ esac
+fi
+
+# Similarly for --with-schedule.
+if test x$with_schedule = x; then
+ case ${target} in
+ hppa1*)
+ # Override default PA8000 scheduling model.
+ with_schedule=7100LC
+ ;;
+ esac
+fi
+
+# Infer a default setting for --with-llsc.
+if test x$with_llsc = x; then
+ case ${target} in
+ mips*-*-linux*)
+ # The kernel emulates LL and SC where necessary.
+ with_llsc=yes
+ ;;
+ mips64r5900-*-* | mips64r5900el-*-* | mipsr5900-*-* | mipsr5900el-*-*)
+ # The R5900 doesn't support LL(D) and SC(D).
+ with_llsc=no
+ ;;
+ esac
+fi
+
+# Validate and mark as valid any --with options supported
+# by this target. In order to use a particular --with option
+# you must list it in supported_defaults; validating the value
+# is optional. This case statement should set nothing besides
+# supported_defaults.
+
+supported_defaults=
+case "${target}" in
+ aarch64*-*-*)
+ supported_defaults="abi cpu cpu_64 arch arch_64 tune tune_64"
+ if test x$with_cpu_64 != x && test x$with_cpu = x; then
+ with_cpu=$with_cpu_64
+ fi
+ if test x$with_arch_64 != x && test x$with_arch = x; then
+ with_arch=$with_arch_64
+ fi
+ if test x$with_tune_64 != x && test x$with_tune = x; then
+ with_tune=$with_tune_64
+ fi
+ for which in cpu arch tune; do
+ eval "val=\$with_$which"
+ base_val=`echo $val | sed -e 's/\+.*//'`
+ ext_val=`echo $val | sed -e 's/[a-z0-9.-]\+//'`
+
+ if [ $which = arch ]; then
+ def=aarch64-arches.def
+ pattern=AARCH64_ARCH
+ else
+ def=aarch64-cores.def
+ pattern=AARCH64_CORE
+ fi
+
+ ext_mask=AARCH64_CPU_DEFAULT_FLAGS
+
+ # Find the base CPU or ARCH id in aarch64-cores.def or
+ # aarch64-arches.def
+ if [ x"$base_val" = x ] \
+ || grep "^$pattern(\"$base_val\"," \
+ ${srcdir}/config/aarch64/$def \
+ > /dev/null; then
+
+ if [ $which = arch ]; then
+ base_id=`grep "^$pattern(\"$base_val\"," \
+ ${srcdir}/config/aarch64/$def | \
+ sed -e 's/^[^,]*,[ ]*//' | \
+ sed -e 's/,.*$//'`
+ # Extract the architecture flags from aarch64-arches.def
+ ext_mask=`grep "^$pattern(\"$base_val\"," \
+ ${srcdir}/config/aarch64/$def | \
+ sed -e 's/)$//' | \
+ sed -e 's/^.*,//'`
+ else
+ base_id=`grep "^$pattern(\"$base_val\"," \
+ ${srcdir}/config/aarch64/$def | \
+ sed -e 's/^[^,]*,[ ]*//' | \
+ sed -e 's/,.*$//'`
+ fi
+
+ # Disallow extensions in --with-tune=cortex-a53+crc.
+ if [ $which = tune ] && [ x"$ext_val" != x ]; then
+ echo "Architecture extensions not supported in --with-$which=$val" 1>&2
+ exit 1
+ fi
+
+ # Use the pre-processor to strip flatten the options.
+ # This makes the format less rigid than if we use
+ # grep and sed directly here.
+ opt_macro="AARCH64_OPT_EXTENSION(A, B, C, D, E, F)=A, B, C, D, E, F"
+ options_parsed="`$ac_cv_prog_CPP -D"$opt_macro" -x c \
+ ${srcdir}/config/aarch64/aarch64-option-extensions.def`"
+
+ # Match one element inside AARCH64_OPT_EXTENSION, we
+ # consume anything that's not a ,.
+ elem="[ ]*\([^,]\+\)[ ]*"
+
+ # Repeat the pattern for the number of entries in the
+ # AARCH64_OPT_EXTENSION, currently 6 times.
+ sed_patt="^$elem,$elem,$elem,$elem,$elem,$elem"
+
+ while [ x"$ext_val" != x ]
+ do
+ ext_val=`echo $ext_val | sed -e 's/\+//'`
+ ext=`echo $ext_val | sed -e 's/\+.*//'`
+ base_ext=`echo $ext | sed -e 's/^no//'`
+ opt_line=`echo -e "$options_parsed" | \
+ grep "^\"$base_ext\""`
+
+ if [ x"$base_ext" = x ] \
+ || [[ -n $opt_line ]]; then
+
+ # These regexp extract the elements based on
+ # their group match index in the regexp.
+ ext_canon=`echo -e "$opt_line" | \
+ sed -e "s/$sed_patt/\2/"`
+ ext_on=`echo -e "$opt_line" | \
+ sed -e "s/$sed_patt/\3/"`
+ ext_off=`echo -e "$opt_line" | \
+ sed -e "s/$sed_patt/\4/"`
+
+ if [ $ext = $base_ext ]; then
+ # Adding extension
+ ext_mask="("$ext_mask") | ("$ext_on" | "$ext_canon")"
+ else
+ # Removing extension
+ ext_mask="("$ext_mask") & ~("$ext_off" | "$ext_canon")"
+ fi
+
+ true
+ else
+ echo "Unknown extension used in --with-$which=$val" 1>&2
+ exit 1
+ fi
+ ext_val=`echo $ext_val | sed -e 's/[a-z0-9]\+//'`
+ done
+
+ ext_mask="(("$ext_mask") << TARGET_CPU_NBITS)"
+ if [ x"$base_id" != x ]; then
+ target_cpu_cname="TARGET_CPU_$base_id | $ext_mask"
+ fi
+ true
+ else
+ # Allow --with-$which=native.
+ if [ "$val" = native ]; then
+ true
+ else
+ echo "Unknown $which used in --with-$which=$val" 1>&2
+ exit 1
+ fi
+ fi
+ done
+ ;;
+
+ alpha*-*-*)
+ supported_defaults="cpu tune"
+ for which in cpu tune; do
+ eval "val=\$with_$which"
+ case "$val" in
+ "" \
+ | ev4 | ev45 | 21064 | ev5 | 21164 | ev56 | 21164a \
+ | pca56 | 21164PC | 21164pc | ev6 | 21264 | ev67 \
+ | 21264a)
+ ;;
+ *)
+ echo "Unknown CPU used in --with-$which=$val" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ ;;
+
+ arc*-*-*)
+ supported_defaults="cpu fpu"
+
+ new_cpu=hs38_linux
+ if [ x"$with_cpu" = x ] \
+ || grep -q -E "^ARC_CPU[[:blank:]]*\($with_cpu," \
+ ${srcdir}/config/arc/arc-cpus.def
+ then
+ # Ok
+ new_cpu=$with_cpu
+ else
+ echo "Unknown cpu used in --with-cpu=$with_cpu" 1>&2
+ exit 1
+ fi
+
+ # see if --with-fpu matches any of the supported FPUs
+ case "$with_fpu" in
+ "")
+ # OK
+ ;;
+ fpus | fpus_div | fpus_fma | fpus_all)
+ # OK if em or hs
+ flags_ok="[emhs]+"
+ ;;
+ fpuda | fpuda_div | fpuda_fma | fpuda_all)
+ # OK only em
+ flags_ok="em"
+ ;;
+ fpud | fpud_div | fpud_fma | fpud_all)
+ # OK only hs
+ flags_ok="hs"
+ ;;
+ *)
+ echo "Unknown floating point type used in "\
+ "--with-fpu=$with_fpu" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if [ -n "$flags_ok" ] \
+ && ! grep -q -E "^ARC_CPU[[:blank:]]*\($new_cpu,[[:blank:]]*$flags_ok," \
+ ${srcdir}/config/arc/arc-cpus.def
+ then
+ echo "Unknown floating point type used in "\
+ "--with-fpu=$with_fpu for cpu $new_cpu" 1>&2
+ exit 1
+ fi
+ ;;
+
+ avr-*-*)
+ # Handle --with-multilib-list.
+ if test "x${with_multilib_list}" != xdefault; then
+ TM_MULTILIB_CONFIG="${with_multilib_list}"
+ fi
+ ;;
+
+ csky-*-*)
+ supported_defaults="cpu endian float"
+ ;;
+
+ arm*-*-*)
+ supported_defaults="arch cpu float tune fpu abi mode tls"
+ for which in cpu tune arch; do
+ # See if it matches a supported value
+ eval "val=\$with_$which"
+ if [ x"$val" != x ]; then
+ cpu=`awk -f ${srcdir}/config/arm/parsecpu.awk \
+ -v cmd="chk$which $val" \
+ ${srcdir}/config/arm/arm-cpus.in`
+ if [ "$cpu" = "error" ]; then
+ echo "Unknown target in --with-$which=$val" 1>&2
+ exit 1
+ else
+ new_val=$cpu
+ eval "target_${which}_cname=$new_val"
+ echo "For $val real value is $new_val"
+ fi
+ fi
+ done
+
+ case "$with_float" in
+ "" \
+ | soft | hard | softfp)
+ # OK
+ ;;
+ *)
+ echo "Unknown floating point type used in --with-float=$with_float" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # see if --with-fpu matches any of the supported FPUs
+ if [ x"$with_fpu" != x ] ; then
+ val=$with_fpu
+ fpu=`awk -f ${srcdir}/config/arm/parsecpu.awk \
+ -v cmd="chkfpu $val" \
+ ${srcdir}/config/arm/arm-cpus.in`
+ if [ "$fpu" = "error" ]
+ then
+ echo "Unknown target in --with-fpu=$val" 1>&2
+ exit 1
+ fi
+ fi
+
+ case "$with_abi" in
+ "" \
+ | apcs-gnu | atpcs | aapcs | iwmmxt | aapcs-linux )
+ #OK
+ ;;
+ *)
+ echo "Unknown ABI used in --with-abi=$with_abi"
+ exit 1
+ ;;
+ esac
+
+ case "$with_mode" in
+ "" \
+ | arm | thumb )
+ #OK
+ ;;
+ *)
+ echo "Unknown mode used in --with-mode=$with_mode"
+ exit 1
+ ;;
+ esac
+
+ case "$with_tls" in
+ "" \
+ | gnu | gnu2)
+ # OK
+ ;;
+ *)
+ echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2
+ exit 1
+ ;;
+ esac
+
+ if test "x$with_arch" != x && test "x$with_cpu" != x; then
+ echo "Switch \"--with-arch\" may not be used with switch \"--with-cpu\"" 1>&2
+ exit 1
+ fi
+
+ if test "x$with_cpu" != x && test "x$with_tune" != x; then
+ echo "Switch \"--with-tune\" may not be used with switch \"--with-cpu\"" 1>&2
+ exit 1
+ fi
+
+ # Add extra multilibs
+ if test "x$with_multilib_list" != x; then
+ ml=
+ arm_multilibs=`echo $with_multilib_list | sed -e 's/,/ /g'`
+ if test "x${arm_multilibs}" != xdefault ; then
+ for arm_multilib in ${arm_multilibs}; do
+ case ${arm_multilib} in
+ aprofile|rmprofile)
+ tmake_profile_file="arm/t-multilib"
+ ;;
+ @*)
+ ml=`echo "X$arm_multilib" | sed '1s,^X@,,'`
+ if test -f "${srcdir}/config/arm/${ml}"; then
+ tmake_file="${tmake_file} arm/${ml}"
+ else
+ echo "Error: ${ml} does not exist in ${srcdir}/config/arm" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ echo "Error: --with-multilib-list=${with_multilib_list} not supported." 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ fi
+
+ if test "x${tmake_profile_file}" != x ; then
+ # arm/t-aprofile and arm/t-rmprofile are only
+ # designed to work without any with-cpu,
+ # with-arch, with-mode, with-fpu or with-float
+ # options.
+ if test "x$with_arch" != x \
+ || test "x$with_cpu" != x \
+ || test "x$with_float" != x \
+ || test "x$with_fpu" != x \
+ || test "x$with_mode" != x ; then
+ echo "Error: You cannot use any of --with-arch/cpu/fpu/float/mode with --with-multilib-list=${with_multilib_list}" 1>&2
+ exit 1
+ elif test "x$ml" != x ; then
+ echo "Error: You cannot use builtin multilib profiles along with custom ones" 1>&2
+ exit 1
+ fi
+ # But pass the default value for float-abi
+ # through to the multilib selector
+ with_float="soft"
+ tmake_file="${tmake_file} ${tmake_profile_file}"
+ TM_MULTILIB_CONFIG="$with_multilib_list"
+ fi
+ fi
+ target_cpu_cname=${target_cpu_cname:-arm7tdmi}
+ with_cpu=${with_cpu:-$target_cpu_cname}
+ ;;
+
+ fr*-*-*linux*)
+ supported_defaults=cpu
+ case "$with_cpu" in
+ fr400) ;;
+ fr550) ;;
+ *)
+ echo "Unknown cpu used in --with-cpu=$with_cpu" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ fido-*-* | m68k*-*-*)
+ supported_defaults="arch cpu"
+ case "$with_arch" in
+ "" | "m68k"| "cf")
+ m68k_arch_family="$with_arch"
+ ;;
+ *)
+ echo "Invalid --with-arch=$with_arch" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # We always have a $with_cpu setting here.
+ case "$with_cpu" in
+ "m68000" | "m68010" | "m68020" | "m68030" | "m68040" | "m68060")
+ m68k_cpu_ident=$with_cpu
+ ;;
+ "m68020-40")
+ m68k_cpu_ident=m68020
+ tm_defines="$tm_defines M68K_DEFAULT_TUNE=u68020_40"
+ ;;
+ "m68020-60")
+ m68k_cpu_ident=m68020
+ tm_defines="$tm_defines M68K_DEFAULT_TUNE=u68020_60"
+ ;;
+ *)
+ # We need the C identifier rather than the string.
+ m68k_cpu_ident=`awk -v arg="\"$with_cpu\"" \
+ 'BEGIN { FS="[ \t]*[,()][ \t]*" }; \
+ $1 == "M68K_DEVICE" && $2 == arg { print $3 }' \
+ ${srcdir}/config/m68k/m68k-devices.def`
+ if [ x"$m68k_cpu_ident" = x ] ; then
+ echo "Unknown CPU used in --with-cpu=$with_cpu" 1>&2
+ exit 1
+ fi
+ with_cpu="mcpu=$with_cpu"
+ ;;
+ esac
+ ;;
+
+ amdgcn-*-*)
+ supported_defaults="arch tune"
+
+ for which in arch tune; do
+ eval "val=\$with_$which"
+ case ${val} in
+ "" | fiji | gfx900 | gfx906 )
+ # OK
+ ;;
+ *)
+ echo "Unknown cpu used in --with-$which=$val." 1>&2
+ exit 1
+ ;;
+ esac
+ done
+ [ "x$with_arch" = x ] && with_arch=fiji
+ ;;
+
+ hppa*-*-*)
+ supported_defaults="arch schedule"
+
+ case "$with_arch" in
+ "" | 1.0 | 1.1 | 2.0)
+ # OK
+ ;;
+ *)
+ echo "Unknown architecture used in --with-arch=$with_arch" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "$with_schedule" in
+ "" | 700 | 7100 | 7100LC | 7200 | 7300 | 8000)
+ # OK
+ ;;
+ *)
+ echo "Unknown processor used in --with-schedule=$with_schedule." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ i[34567]86-*-* | x86_64-*-*)
+ supported_defaults="abi arch arch_32 arch_64 cpu cpu_32 cpu_64 tune tune_32 tune_64"
+ for which in arch arch_32 arch_64 cpu cpu_32 cpu_64 tune tune_32 tune_64; do
+ eval "val=\$with_$which"
+ case " $x86_archs " in
+ *" ${val} "*)
+ case "${target}" in
+ x86_64-*-*)
+ case "x$which" in
+ *_32)
+ ;;
+ *)
+ echo "CPU given in --with-$which=$val doesn't support 64bit mode." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ # OK
+ ;;
+ *)
+ if test x${val} != x; then
+ case " $x86_64_archs " in
+ *" ${val} "*)
+ # Disallow x86-64-v* for --with-cpu=/--with-tune=
+ case "x$which$val" in
+ xcpu*x86-64-v*|xtune*x86-64-v*)
+ echo "Unknown CPU given in --with-$which=$val." 1>&2
+ exit 1
+ ;;
+ *)
+ ;;
+ esac
+ # OK
+ ;;
+ *)
+ # Allow $x86_cpus --with-cpu=/--with-tune=
+ case "x$which" in
+ xcpu*|xtune*)
+ case " $x86_cpus " in
+ *" ${val} "*)
+ # OK
+ ;;
+ *)
+ echo "Unknown CPU given in --with-$which=$val." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *)
+ echo "Unknown CPU given in --with-$which=$val." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ done
+ ;;
+
+ riscv*-*-*)
+ supported_defaults="abi arch tune riscv_attribute isa_spec"
+
+ case "${target}" in
+ riscv-* | riscv32*) xlen=32 ;;
+ riscv64*) xlen=64 ;;
+ *) echo "Unsupported RISC-V target ${target}" 1>&2; exit 1 ;;
+ esac
+
+ case "${with_isa_spec}" in
+ ""|default|20191213|201912)
+ tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20191213"
+ with_isa_spec=20191213
+ ;;
+ 2.2)
+ tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2"
+ ;;
+ 20190608 | 201906)
+ tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20190608"
+ with_isa_spec=20190608
+ ;;
+ *)
+ echo "--with-isa-spec only accept 2.2, 20191213, 201912, 20190608 or 201906" 1>&2
+ exit 1
+ esac
+
+ case "${with_riscv_attribute}" in
+ yes)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
+ ;;
+ no)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=0"
+ ;;
+ ""|default)
+ tm_defines="${tm_defines} TARGET_RISCV_ATTRIBUTE=1"
+ ;;
+ *)
+ echo "--with-riscv-attribute=${with_riscv_attribute} is not supported. The argument must begin with yes, no or default." 1>&2
+ exit 1
+ ;;
+ esac
+
+
+ # Infer arch from --with-arch, --target, and --with-abi.
+ case "${with_arch}" in
+ rv32e* | rv32i* | rv32g* | rv64i* | rv64g*)
+ # OK.
+ ;;
+ "")
+ # Infer XLEN, but otherwise assume GC.
+ case "${with_abi}" in
+ ilp32e) with_arch="rv32e" ;;
+ ilp32 | ilp32f | ilp32d) with_arch="rv32gc" ;;
+ lp64 | lp64f | lp64d) with_arch="rv64gc" ;;
+ *) with_arch="rv${xlen}gc" ;;
+ esac
+ ;;
+ *)
+ echo "--with-arch=${with_arch} is not supported. The argument must begin with rv32e, rv32i, rv32g, rv64i, or rv64g." 1>&2
+ exit 1
+ ;;
+ esac
+ PYTHON=`which python || which python3 || which python2`
+ if test "x${PYTHON}" != x; then
+ with_arch=`${PYTHON} ${srcdir}/config/riscv/arch-canonicalize -misa-spec=${with_isa_spec} ${with_arch}`
+ fi
+ tm_defines="${tm_defines} TARGET_RISCV_DEFAULT_ARCH=${with_arch}"
+
+ # Make sure --with-abi is valid. If it was not specified,
+ # pick a default based on the ISA, preferring soft-float
+ # unless the D extension is present.
+ case "${with_abi}" in
+ ilp32 | ilp32e | ilp32f | ilp32d | lp64 | lp64f | lp64d)
+ ;;
+ "")
+ case "${with_arch}" in
+ rv32*d* | rv32g*) with_abi=ilp32d ;;
+ rv32e*) with_abi=ilp32e ;;
+ rv32*) with_abi=ilp32 ;;
+ rv64*d* | rv64g*) with_abi=lp64d ;;
+ rv64*) with_abi=lp64 ;;
+ esac
+ ;;
+ *)
+ echo "--with-abi=${with_abi} is not supported" 1>&2
+ exit 1
+ ;;
+ esac
+ tm_defines="${tm_defines} TARGET_RISCV_DEFAULT_ABI=${with_abi}"
+
+ # Make sure ABI and ISA are compatible.
+ case "${with_abi},${with_arch}" in
+ ilp32,rv32* | ilp32e,rv32e* \
+ | ilp32f,rv32*f* | ilp32f,rv32g* \
+ | ilp32d,rv32*d* | ilp32d,rv32g* \
+ | lp64,rv64* \
+ | lp64f,rv64*f* | lp64f,rv64g* \
+ | lp64d,rv64*d* | lp64d,rv64g*)
+ ;;
+ *)
+ echo "--with-abi=${with_abi} is not supported for ISA ${with_arch}" 1>&2
+ exit 1
+ ;;
+ esac
+ # Handle --with-multilib-generator.
+ if test "x${with_multilib_generator}" != xdefault; then
+ if test "x${with_multilib_list}" != xdefault; then
+ echo "--with-multilib-list= can't used with --with-multilib-generator= at same time" 1>&2
+ exit 1
+ fi
+ case "${target}" in
+ riscv*-*-elf*)
+ if ${srcdir}/config/riscv/multilib-generator \
+ -misa-spec=${with_isa_spec} \
+ `echo ${with_multilib_generator} | sed 's/;/ /g'`\
+ > t-multilib-config;
+ then
+ tmake_file="${tmake_file} riscv/t-withmultilib-generator"
+ else
+ echo "invalid option for --with-multilib-generator" 1>&2
+ exit 1
+ fi
+ ;;
+ *)
+ echo "--with-multilib-generator= is not supported for ${target}, only supported for riscv*-*-elf*" 1>&2
+ exit 1
+ ;;
+ esac
+ fi
+
+ # Handle --with-multilib-list.
+ if test "x${with_multilib_list}" != xdefault; then
+ tmake_file="${tmake_file} riscv/t-withmultilib"
+
+ case ${with_multilib_list} in
+ ilp32 | ilp32f | ilp32d \
+ | lp64 | lp64f | lp64d )
+ TM_MULTILIB_CONFIG="${with_arch},${with_multilib_list}"
+ ;;
+ *)
+ echo "--with-multilib-list=${with_multilib_list} not supported."
+ exit 1
+ esac
+ fi
+ ;;
+
+ mips*-*-*)
+ supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci lxc1-sxc1 madd4"
+
+ case ${with_float} in
+ "" | soft | hard)
+ # OK
+ ;;
+ *)
+ echo "Unknown floating point type used in --with-float=$with_float" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_fpu} in
+ "" | single | double)
+ # OK
+ ;;
+ *)
+ echo "Unknown fpu type used in --with-fpu=$with_fpu" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_nan} in
+ "" | 2008 | legacy)
+ # OK
+ ;;
+ *)
+ echo "Unknown NaN encoding used in --with-nan=$with_nan" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_fp_32} in
+ "" | 32 | xx | 64)
+ # OK
+ ;;
+ *)
+ echo "Unknown FP mode used in --with-fp-32=$with_fp_32" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_odd_spreg_32} in
+ yes)
+ with_odd_spreg_32="odd-spreg"
+ ;;
+ no)
+ with_odd_spreg_32="no-odd-spreg"
+ ;;
+ "")
+ # OK
+ ;;
+ *)
+ echo "Unknown odd-spreg-32 type used in --with-odd-spreg-32=$with_odd_spreg_32" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_abi} in
+ "" | 32 | o64 | n32 | 64 | eabi)
+ # OK
+ ;;
+ *)
+ echo "Unknown ABI used in --with-abi=$with_abi" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_divide} in
+ "" | breaks | traps)
+ # OK
+ ;;
+ *)
+ echo "Unknown division check type use in --with-divide=$with_divide" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_llsc} in
+ yes)
+ with_llsc=llsc
+ ;;
+ no)
+ with_llsc="no-llsc"
+ ;;
+ "")
+ # OK
+ ;;
+ *)
+ echo "Unknown llsc type used in --with-llsc" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_mips_plt} in
+ yes)
+ with_mips_plt=plt
+ ;;
+ no)
+ with_mips_plt=no-plt
+ ;;
+ "")
+ ;;
+ *)
+ echo "Unknown --with-mips-plt argument: $with_mips_plt" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_synci} in
+ yes)
+ with_synci=synci
+ ;;
+ no)
+ with_synci=no-synci
+ ;;
+ "")
+ ;;
+ *)
+ echo "Unknown synci type used in --with-synci" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_lxc1_sxc1} in
+ yes)
+ with_lxc1_sxc1=lxc1-sxc1
+ ;;
+ no)
+ with_lxc1_sxc1=no-lxc1-sxc1
+ ;;
+ "")
+ ;;
+ *)
+ echo "Unknown lxc1-sxc1 type used in --with-lxc1-sxc1" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_madd4} in
+ yes)
+ with_madd4=madd4
+ ;;
+ no)
+ with_madd4=no-madd4
+ ;;
+ "")
+ ;;
+ *)
+ echo "Unknown madd4 type used in --with-madd4" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ loongarch*-*-*)
+ supported_defaults="abi arch tune fpu"
+
+ # Local variables
+ unset \
+ abi_pattern abi_default \
+ abiext_pattern abiext_default \
+ arch_pattern arch_default \
+ fpu_pattern fpu_default \
+ tune_pattern tune_default \
+ triplet_os triplet_abi
+
+ # Infer ABI from the triplet.
+ case ${target} in
+ loongarch64-*-*-*f64)
+ abi_pattern="lp64d"
+ triplet_abi="f64"
+ ;;
+ loongarch64-*-*-*f32)
+ abi_pattern="lp64f"
+ triplet_abi="f32"
+ ;;
+ loongarch64-*-*-*sf)
+ abi_pattern="lp64s"
+ triplet_abi="sf"
+ ;;
+ loongarch64-*-*-*)
+ abi_pattern="lp64[dfs]"
+ abi_default="lp64d"
+ triplet_abi=""
+ ;;
+ *)
+ echo "Unsupported target ${target}." 1>&2
+ exit 1
+ ;;
+ esac
+
+ abiext_pattern="*"
+ abiext_default="base"
+
+ # Get the canonical triplet (multiarch specifier).
+ case ${target} in
+ *-linux-gnu*) triplet_os="linux-gnu";;
+ *-linux-musl*) triplet_os="linux-musl";;
+ *)
+ echo "Unsupported target ${target}." 1>&2
+ exit 1
+ ;;
+ esac
+
+ la_canonical_triplet="loongarch64-${triplet_os}${triplet_abi}"
+
+
+ # Perform initial sanity checks on --with-* options.
+ case ${with_arch} in
+ "" | loongarch64 | la464) ;; # OK, append here.
+ native)
+ if test x${host} != x${target}; then
+ echo "--with-arch=native is illegal for cross-compiler." 1>&2
+ exit 1
+ fi
+ ;;
+ "")
+ echo "Please set a default value for \${with_arch}" \
+ "according to your target triplet \"${target}\"." 1>&2
+ exit 1
+ ;;
+ *)
+ echo "Unknown arch in --with-arch=$with_arch" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_abi} in
+ "" | lp64d | lp64f | lp64s) ;; # OK, append here.
+ *)
+ echo "Unsupported ABI given in --with-abi=$with_abi" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_abiext} in
+ "" | base) ;; # OK, append here.
+ *)
+ echo "Unsupported ABI extention type $with_abiext" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case ${with_fpu} in
+ "" | none | 32 | 64) ;; # OK, append here.
+ 0)
+ # Convert "0" to "none" for upcoming checks.
+ with_fpu="none"
+ ;;
+ *)
+ echo "Unknown fpu type in --with-fpu=$with_fpu" 1>&2
+ exit 1
+ ;;
+ esac
+
+
+ # Set default value for with_abi.
+ case ${with_abi} in
+ "")
+ if test x${abi_default} != x; then
+ with_abi=${abi_default}
+ else
+ with_abi=${abi_pattern}
+ fi
+ ;;
+
+ *)
+ if echo "${with_abi}" | grep -E "^${abi_pattern}$" > /dev/null; then
+ : # OK
+ else
+ echo "Incompatible options:" \
+ "--with-abi=${with_abi} and --target=${target}." 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+
+ # Set default value for with_abiext (internal)
+ case ${with_abiext} in
+ "")
+ if test x${abiext_default} != x; then
+ with_abiext=${abiext_default}
+ else
+ with_abiext=${abiext_pattern}
+ fi
+ ;;
+
+ *)
+ if echo "${with_abiext}" | grep -E "^${abiext_pattern}$" > /dev/null; then
+ : # OK
+ else
+ echo "The ABI extension type \"${with_abiext}\"" \
+ "is incompatible with --target=${target}." 1>&2
+ exit 1
+ fi
+
+ ;;
+ esac
+
+ # Infer ISA-related default options from the ABI: pass 1
+ case ${with_abi}/${with_abiext} in
+ lp64*/base)
+ # architectures that support lp64* ABI
+ arch_pattern="native|loongarch64|la464"
+ # default architecture for lp64* ABI
+ arch_default="loongarch64"
+ ;;
+ *)
+ echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2
+ exit 1
+ ;;
+ esac
+
+ # Infer ISA-related default options from the ABI: pass 2
+ case ${with_abi}/${with_abiext} in
+ lp64d/base)
+ fpu_pattern="64"
+ ;;
+ lp64f/base)
+ fpu_pattern="32|64"
+ fpu_default="32"
+ ;;
+ lp64s/base)
+ fpu_pattern="none|32|64"
+ fpu_default="none"
+ ;;
+ *)
+ echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2
+ exit 1
+ ;;
+ esac
+
+ ## Set default value for with_arch.
+ case ${with_arch} in
+ "")
+ if test x${arch_default} != x; then
+ with_arch=${arch_default}
+ else
+ with_arch=${arch_pattern}
+ fi
+ ;;
+
+ *)
+ if echo "${with_arch}" | grep -E "^${arch_pattern}$" > /dev/null; then
+ : # OK
+ else
+ echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \
+ "--with-arch=${with_arch}." 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+
+ ## Set default value for with_fpu.
+ case ${with_fpu} in
+ "")
+ if test x${fpu_default} != x; then
+ with_fpu=${fpu_default}
+ else
+ with_fpu=${fpu_pattern}
+ fi
+ ;;
+
+ *)
+ if echo "${with_fpu}" | grep -E "^${fpu_pattern}$" > /dev/null; then
+ : # OK
+ else
+ echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \
+ "--with-fpu=${with_fpu}." 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+
+
+ # Infer default with_tune from with_arch: pass 1
+ case ${with_arch} in
+ native)
+ tune_pattern="*"
+ tune_default="native"
+ ;;
+ loongarch64)
+ tune_pattern="loongarch64|la464"
+ tune_default="la464"
+ ;;
+ *)
+ # By default, $with_tune == $with_arch
+ tune_pattern="$with_arch"
+ ;;
+ esac
+
+ ## Set default value for with_tune.
+ case ${with_tune} in
+ "")
+ if test x${tune_default} != x; then
+ with_tune=${tune_default}
+ else
+ with_tune=${tune_pattern}
+ fi
+ ;;
+
+ *)
+ if echo "${with_tune}" | grep -E "^${tune_pattern}$" > /dev/null; then
+ : # OK
+ else
+ echo "Incompatible options: --with-tune=${with_tune}" \
+ "and --with-arch=${with_arch}." 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+
+ # Handle --with-multilib-list.
+ if test x"${with_multilib_list}" = x \
+ || test x"${with_multilib_list}" = xno \
+ || test x"${with_multilib_list}" = xdefault \
+ || test x"${enable_multilib}" != xyes; then
+
+ with_multilib_list="${with_abi}/${with_abiext}"
+ fi
+
+ # Check if the configured default ABI combination is included in
+ # ${with_multilib_list}.
+ loongarch_multilib_list_sane=no
+
+ # This one goes to TM_MULTILIB_CONFIG, for use in t-linux.
+ loongarch_multilib_list_make=""
+
+ # This one goes to tm_defines, for use in loongarch-driver.c.
+ loongarch_multilib_list_c=""
+
+ # ${with_multilib_list} should not contain whitespaces,
+ # consecutive commas or slashes.
+ if echo "${with_multilib_list}" \
+ | grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null; then
+ echo "Invalid argument to --with-multilib-list." 1>&2
+ exit 1
+ fi
+
+ unset component idx elem_abi_base elem_abi_ext elem_tmp
+ for elem in $(echo "${with_multilib_list}" | tr ',' ' '); do
+ idx=0
+ while true; do
+ idx=$((idx + 1))
+ component=$(echo "${elem}" | awk -F'/' '{print $'"${idx}"'}')
+
+ case ${idx} in
+ 1)
+ # Component 1: Base ABI type
+ case ${component} in
+ lp64d) elem_tmp="ABI_BASE_LP64D,";;
+ lp64f) elem_tmp="ABI_BASE_LP64F,";;
+ lp64s) elem_tmp="ABI_BASE_LP64S,";;
+ *)
+ echo "Unknown base ABI \"${component}\" in --with-multilib-list." 1>&2
+ exit 1
+ ;;
+ esac
+ loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}"
+ loongarch_multilib_list_make="${loongarch_multilib_list_make}mabi=${component}"
+ elem_abi_base="${component}"
+ ;;
+
+ 2)
+ # Component 2: ABI extension type
+ case ${component} in
+ "" | base)
+ component="base"
+ elem_tmp="ABI_EXT_BASE,"
+ ;;
+ *)
+ echo "Unknown ABI extension \"${component}\" in --with-multilib-list." 1>&2
+ exit 1
+ ;;
+ esac
+ loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}"
+ loongarch_multilib_list_make="${loongarch_multilib_list_make}" # Add nothing for now.
+ elem_abi_ext="${component}"
+ ;;
+
+ *)
+ # Component 3 and on: optional stuff
+ case ${component} in
+ "")
+ # End of component list.
+ break
+ ;;
+ *)
+ echo "Unknown ABI \"${elem}\" in --with-multilib-list." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ done
+
+ if test x${elem_abi_base} = x${with_abi} \
+ && test x${elem_abi_ext} = x${with_abiext}; then
+ loongarch_multilib_list_sane=yes
+ fi
+ loongarch_multilib_list_make="${loongarch_multilib_list_make},"
+ done
+
+ # Check if the default ABI combination is in the default list.
+ if test x${loongarch_multilib_list_sane} = xno; then
+ if test x${with_abiext} = xbase; then
+ with_abiext=""
+ else
+ with_abiext="/${with_abiext}"
+ fi
+
+ echo "Default ABI combination (${with_abi}${with_abiext})" \
+ "not found in --with-multilib-list." 1>&2
+ exit 1
+ fi
+
+ # Remove the excessive appending comma.
+ loongarch_multilib_list_c=${loongarch_multilib_list_c%,}
+ loongarch_multilib_list_make=${loongarch_multilib_list_make%,}
+ ;;
+
+ nds32*-*-*)
+ supported_defaults="arch cpu nds32_lib float fpu_config"
+
+ # process --with-arch
+ case "${with_arch}" in
+ "" | v3 )
+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=0"
+ ;;
+ v2 | v2j | v3m)
+ # OK
+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=0"
+ ;;
+ v3f)
+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=1"
+ ;;
+ v3s)
+ tm_defines="${tm_defines} TARGET_ARCH_DEFAULT=2"
+
+ ;;
+ *)
+ echo "Cannot accept --with-arch=$with_arch, available values are: v2 v2j v3 v3m v3f v3s" 1>&2
+ exit 1
+ ;;
+ esac
+
+ case "${with_cpu}" in
+ "")
+ with_cpu=n9
+ ;;
+ n6 | n7 |n8 | e8 | s8 | n9 | n10 | d10 | n12 | n13 | n15)
+ # OK
+ ;;
+ *)
+ echo "Cannot accept --with-cpu=$with_cpu, available values are: n6 n7 n8 e8 s8 n9 n10 d10 n12 n13 n15" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # process --with-nds32-lib
+ case "${with_nds32_lib}" in
+ "")
+ case ${target} in
+ *-*-*uclibc*)
+ with_nds32_lib=ulibc
+ ;;
+ *-*-linux*)
+ with_nds32_lib=glibc
+ ;;
+ *)
+ with_nds32_lib=newlib
+ tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1"
+ ;;
+ esac
+ ;;
+ newlib)
+ # OK
+ tm_defines="${tm_defines} TARGET_DEFAULT_CTOR_DTOR=1"
+ ;;
+ mculib)
+ # OK
+ # for the arch=v3f or arch=v3s under mculib toolchain,
+ # we would like to set -fno-math-errno as default
+ case "${with_arch}" in
+ v3f | v3s)
+ tm_defines="${tm_defines} TARGET_DEFAULT_NO_MATH_ERRNO=1"
+ ;;
+ esac
+ ;;
+ glibc | uclibc)
+ # OK
+ ;;
+ *)
+ echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib glibc uclibc" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # process --with-float
+ case "${with_float}" in
+ "" | soft | hard)
+ # OK
+ ;;
+ *)
+ echo "Cannot accept --with-float=$with_float, available values are: soft hard" 1>&2
+ exit 1
+ ;;
+ esac
+
+ # process --with-config-fpu
+ case "${with_config_fpu}" in
+ "" | 0 | 1 | 2 | 3)
+ # OK
+ ;;
+ *)
+ echo "Cannot accept --with-config-fpu=$with_config_fpu, available values from 0 to 7" 1>&2
+ exit 1
+ ;;
+ esac
+
+
+ ;;
+ nios2*-*-*)
+ supported_defaults="arch"
+ case "$with_arch" in
+ "" | r1 | r2)
+ # OK
+ ;;
+ *)
+ echo "Unknown arch used in --with-arch=$with_arch" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ powerpc*-*-* | rs6000-*-*)
+ supported_defaults="abi cpu cpu_32 cpu_64 float tune tune_32 tune_64 advance_toolchain"
+
+ for which in cpu cpu_32 cpu_64 tune tune_32 tune_64; do
+ eval "val=\$with_$which"
+ case ${val} in
+ default32 | default64)
+ case $which in
+ cpu | tune)
+ ;;
+ *)
+ echo "$val only valid for --with-cpu and --with-tune." 1>&2
+ exit 1
+ ;;
+ esac
+ with_which="with_$which"
+ eval $with_which=
+ ;;
+ 405cr)
+ tm_defines="${tm_defines} CONFIG_PPC405CR"
+ eval "with_$which=405"
+ ;;
+ "" | common | native \
+ | power[3456789] | power10 | power5+ | power6x \
+ | powerpc | powerpc64 | powerpc64le \
+ | rs64 \
+ | 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \
+ | 476 | 476fp | 505 | 601 | 602 | 603 | 603e | ec603e \
+ | 604 | 604e | 620 | 630 | 740 | 750 | 7400 | 7450 \
+ | a2 | e300c[23] | 854[08] | e500mc | e500mc64 | e5500 | e6500 \
+ | titan | 801 | 821 | 823 | 860 | 970 | G3 | G4 | G5 | cell)
+ # OK
+ ;;
+ *)
+ echo "Unknown cpu used in --with-$which=$val." 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ case "$with_abi" in
+ "" | elfv1 | elfv2 )
+ #OK
+ ;;
+ *)
+ echo "Unknown ABI used in --with-abi=$with_abi"
+ exit 1
+ ;;
+ esac
+
+ if test "x$with_advance_toolchain" != x; then
+ if test -d "/opt/$with_advance_toolchain/." -a \
+ -d "/opt/$with_advance_toolchain/bin/." -a \
+ -d "/opt/$with_advance_toolchain/include/."; then
+
+ tm_file="$tm_file ./advance-toolchain.h"
+ (at="/opt/$with_advance_toolchain"
+ echo "/* Use Advance Toolchain $at */"
+ echo
+ echo "#undef LINK_OS_NEW_DTAGS_SPEC"
+ echo "#define LINK_OS_NEW_DTAGS_SPEC" \
+ "\"--enable-new-dtags\""
+ echo
+ echo "#undef DYNAMIC_LINKER_PREFIX"
+ echo "#define DYNAMIC_LINKER_PREFIX \"$at\""
+ echo
+ echo "#undef MD_EXEC_PREFIX"
+ echo "#define MD_EXEC_PREFIX \"$at/bin/\""
+ echo
+ echo "#undef MD_STARTFILE_PREFIX"
+ echo "#define MD_STARTFILE_PREFIX \"$prefix/lib/\""
+ echo
+ echo "#undef MD_STARTFILE_PREFIX_1"
+ echo "#define MD_STARTFILE_PREFIX_1 \"$at/lib/\"") \
+ > advance-toolchain.h
+ else
+ echo "Unknown advance-toolchain $with_advance_toolchain"
+ exit 1
+ fi
+ fi
+
+ # Set up the default long double format if the user changed it.
+ if test x$with_long_double_format = xieee; then
+ tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=1"
+
+ elif test x$with_long_double_format = xibm; then
+ tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=0"
+ fi
+ ;;
+
+ s390*-*-*)
+ supported_defaults="arch mode tune"
+
+ for which in arch tune; do
+ eval "val=\$with_$which"
+ case ${val} in
+ "" | native | z900 | z990 | z9-109 | z9-ec | z10 | z196 | zEC12 | z13 | z14 | z15 | z16 | arch5 | arch6 | arch7 | arch8 | arch9 | arch10 | arch11 | arch12 | arch13 | arch14 )
+ # OK
+ ;;
+ *)
+ echo "Unknown cpu used in --with-$which=$val." 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ case ${with_mode} in
+ "" | esa | zarch)
+ # OK
+ ;;
+ *)
+ echo "Unknown architecture mode used in --with-mode=$with_mode." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ sh[123456ble]*-*-* | sh-*-*)
+ supported_defaults="cpu"
+ case "`echo $with_cpu | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ_ abcdefghijklmnopqrstuvwxyz- | sed s/sh/m/`" in
+ "" | m1 | m2 | m2e | m3 | m3e | m4 | m4-single | m4-single-only | m4-nofpu )
+ # OK
+ ;;
+ m2a | m2a-single | m2a-single-only | m2a-nofpu)
+ ;;
+ m4a | m4a-single | m4a-single-only | m4a-nofpu | m4al)
+ ;;
+ *)
+ echo "Unknown CPU used in --with-cpu=$with_cpu, known values:" 1>&2
+ echo "m1 m2 m2e m3 m3e m4 m4-single m4-single-only m4-nofpu" 1>&2
+ echo "m4a m4a-single m4a-single-only m4a-nofpu m4al" 1>&2
+ echo "m2a m2a-single m2a-single-only m2a-nofpu" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ sparc*-*-*)
+ supported_defaults="cpu cpu_32 cpu_64 float tune tune_32 tune_64"
+
+ for which in cpu cpu_32 cpu_64 tune tune_32 tune_64; do
+ eval "val=\$with_$which"
+ case ${val} in
+ "" | sparc | sparcv9 | sparc64 \
+ | v7 | cypress \
+ | v8 | supersparc | hypersparc | leon | leon3 | leon3v7 \
+ | sparclite | f930 | f934 | sparclite86x \
+ | sparclet | tsc701 \
+ | v9 | ultrasparc | ultrasparc3 | niagara | niagara2 \
+ | niagara3 | niagara4 | niagara7 | m8)
+ # OK
+ ;;
+ *)
+ echo "Unknown cpu used in --with-$which=$val" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ case ${with_float} in
+ "" | soft | hard)
+ # OK
+ ;;
+ *)
+ echo "Unknown floating point type used in --with-float=$with_float" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ tic6x-*-*)
+ supported_defaults="arch"
+
+ case ${with_arch} in
+ "" | c62x | c64x | c64x+ | c67x | c67x+ | c674x)
+ # OK
+ ;;
+ *)
+ echo "Unknown arch used in --with-arch=$with_arch." 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+
+ v850*-*-*)
+ supported_defaults=cpu
+ case ${with_cpu} in
+ "" | v850e | v850e1 | v850e2 | v850es | v850e2v3 | v850e3v5)
+ # OK
+ ;;
+ *)
+ echo "Unknown cpu used in --with-cpu=$with_cpu" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+ visium-*-*)
+ supported_defaults="cpu"
+ case $with_cpu in
+ "" | gr5 | gr6)
+ ;;
+ *) echo "Unknown cpu used in --with-cpu=$with_cpu" 1>&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# Targets for which there is at least one VxWorks port should include
+# vxworks-dummy.h to allow safe references to various TARGET_VXWORKS kinds
+# of markers from other files in the port, including the vxworks*.h files to
+# distinguish VxWorks variants such as VxWorks 7 or 64).
+
+case ${target} in
+arm*-*-* | i[34567]86-*-* | mips*-*-* | powerpc*-*-* | sh*-*-* \
+| sparc*-*-* | x86_64-*-*)
+ tm_file="vxworks-dummy.h ${tm_file}"
+ ;;
+esac
+
+# Set some miscellaneous flags for particular targets.
+target_cpu_default2=
+case ${target} in
+ aarch64*-*-*)
+ if test x"$target_cpu_cname" != x
+ then
+ target_cpu_default2=$target_cpu_cname
+ fi
+ ;;
+
+ arm*-*-*)
+ if test x$with_cpu = x
+ then
+ echo "Don't know the target cpu" 1>&2
+ exit 1
+ else
+ target_cpu_default2="\\\"$with_cpu\\\""
+ fi
+ ;;
+
+ hppa*-*-*)
+ if test x$gas = xyes
+ then
+ target_cpu_default2="MASK_GAS"
+ fi
+ ;;
+
+ fido*-*-* | m68k*-*-*)
+ target_cpu_default2=$m68k_cpu_ident
+ tmake_file="m68k/t-opts $tmake_file"
+ if [ x"$m68k_arch_family" != x ]; then
+ tmake_file="m68k/t-$m68k_arch_family $tmake_file"
+ fi
+ ;;
+
+ i[34567]86-*-darwin* | x86_64-*-darwin*)
+ ;;
+ i[34567]86-*-linux* | x86_64-*-linux*)
+ extra_objs="${extra_objs} gnu-property.o"
+ tmake_file="$tmake_file i386/t-linux i386/t-gnu-property"
+ ;;
+ i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
+ tmake_file="$tmake_file i386/t-kfreebsd"
+ ;;
+ i[34567]86-*-gnu*)
+ tmake_file="$tmake_file i386/t-gnu"
+ ;;
+ i[34567]86-*-msdosdjgpp*)
+ tmake_file="${tmake_file} i386/t-djgpp"
+ ;;
+ i[34567]86-*-solaris2* | x86_64-*-solaris2*)
+ ;;
+ i[34567]86-*-cygwin* | x86_64-*-cygwin*)
+ ;;
+ i[34567]86-*-mingw* | x86_64-*-mingw*)
+ ;;
+ i[34567]86-*-dragonfly* | x86_64-*-dragonfly*)
+ ;;
+ i[34567]86-*-freebsd*)
+ ;;
+ x86_64-*-freebsd*)
+ tmake_file="${tmake_file} i386/t-freebsd64"
+ ;;
+ ia64*-*-linux*)
+ ;;
+
+ mips*-*-*)
+ if test x$gnu_ld = xyes
+ then
+ target_cpu_default2="MASK_SPLIT_ADDRESSES"
+ fi
+ case ${target} in
+ mips*el-*-*)
+ tm_defines="TARGET_ENDIAN_DEFAULT=0 $tm_defines"
+ ;;
+ esac
+ if test x$with_arch != x; then
+ default_mips_arch=$with_arch
+ fi
+ if test x$with_abi != x; then
+ default_mips_abi=$with_abi
+ fi
+ case ${default_mips_arch} in
+ mips1) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS1" ;;
+ mips2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS2" ;;
+ mips3) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS3" ;;
+ mips4) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS4" ;;
+ mips32) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32" ;;
+ mips32r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R2" ;;
+ mips32r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS32R6" ;;
+ mips64) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64" ;;
+ mips64r2) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R2" ;;
+ mips64r6) tm_defines="$tm_defines MIPS_ISA_DEFAULT=MIPS_ISA_MIPS64R6" ;;
+ esac
+ case ${default_mips_abi} in
+ 32) tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_32" ;;
+ o64) tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_O64" ;;
+ n32) tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_N32" ;;
+ 64) tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_64" ;;
+ eabi) tm_defines="$tm_defines MIPS_ABI_DEFAULT=ABI_EABI" ;;
+ esac
+ tmake_file="mips/t-mips $tmake_file"
+ ;;
+
+ loongarch*-*-*)
+ # Export canonical triplet.
+ tm_defines="${tm_defines} LA_MULTIARCH_TRIPLET=${la_canonical_triplet}"
+
+ # Define macro LA_DISABLE_MULTILIB if --disable-multilib
+ tm_defines="${tm_defines} TM_MULTILIB_LIST=${loongarch_multilib_list_c}"
+ if test x$enable_multilib = xyes; then
+ TM_MULTILIB_CONFIG="${loongarch_multilib_list_make}"
+ else
+ tm_defines="${tm_defines} LA_DISABLE_MULTILIB"
+ fi
+
+ # Let --with- flags initialize the enum variables from loongarch.opt.
+ # See macro definitions from loongarch-opts.h and loongarch-cpu.h.
+ case ${with_arch} in
+ native) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_NATIVE" ;;
+ la464) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LA464" ;;
+ loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;;
+ esac
+
+ case ${with_tune} in
+ native) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_NATIVE" ;;
+ la464) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LA464" ;;
+ loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;;
+ esac
+
+ case ${with_abi} in
+ lp64d) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;;
+ lp64f) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;;
+ lp64s) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;;
+ esac
+
+ case ${with_abiext} in
+ base) tm_defines="${tm_defines} DEFAULT_ABI_EXT=ABI_EXT_BASE" ;;
+ esac
+
+ case ${with_fpu} in
+ none) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NOFPU" ;;
+ 32) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU32" ;;
+ 64) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU64" ;;
+ esac
+
+ tmake_file="loongarch/t-loongarch $tmake_file"
+ ;;
+
+ powerpc*-*-* | rs6000-*-*)
+ # FIXME: The PowerPC port uses the value set at compile time,
+ # although it's only cosmetic.
+ if test "x$with_cpu" != x
+ then
+ target_cpu_default2="\\\"$with_cpu\\\""
+ fi
+ out_file="${cpu_type}/${cpu_type}.cc"
+ c_target_objs="${c_target_objs} ${cpu_type}-c.o"
+ cxx_target_objs="${cxx_target_objs} ${cpu_type}-c.o"
+ d_target_objs="${d_target_objs} ${cpu_type}-d.o"
+ tmake_file="${cpu_type}/t-${cpu_type} ${tmake_file}"
+ ;;
+
+ sh[123456ble]*-*-* | sh-*-*)
+ c_target_objs="${c_target_objs} sh-c.o"
+ cxx_target_objs="${cxx_target_objs} sh-c.o"
+ ;;
+
+ sparc*-*-*)
+ # Some standard aliases.
+ case x$with_cpu in
+ xsparc)
+ with_cpu=v7
+ ;;
+ xsparcv9 | xsparc64)
+ with_cpu=v9
+ ;;
+ esac
+
+ if test x$with_tune = x ; then
+ case ${target} in
+ *-leon-*)
+ with_tune=leon
+ ;;
+ *-leon[3-9]*)
+ with_tune=leon3
+ ;;
+ esac
+ fi
+
+ # The SPARC port checks this value at compile-time.
+ target_cpu_default2="TARGET_CPU_$with_cpu"
+ ;;
+
+ v850*-*-*)
+ case "x$with_cpu" in
+ x)
+ ;;
+ xv850e | xv850e1 | xv850e2 | xv850e2v3 | xv850e3v5)
+ target_cpu_default2="TARGET_CPU_$with_cpu"
+ ;;
+ xv850es)
+ target_cpu_default2="TARGET_CPU_v850e1"
+ ;;
+ esac
+ ;;
+ visium-*-*)
+ target_cpu_default2="TARGET_CPU_$with_cpu"
+ ;;
+esac
+
+t=
+all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls lxc1-sxc1 madd4 isa_spec"
+for option in $all_defaults
+do
+ eval "val=\$with_"`echo $option | sed s/-/_/g`
+ if test -n "$val"; then
+ case " $supported_defaults " in
+ *" $option "*)
+ ;;
+ *)
+ echo "This target does not support --with-$option." 2>&1
+ echo "Valid --with options are: $supported_defaults" 2>&1
+ exit 1
+ ;;
+ esac
+
+ if test "x$t" = x
+ then
+ t="{ \"$option\", \"$val\" }"
+ else
+ t="${t}, { \"$option\", \"$val\" }"
+ fi
+ fi
+done
+
+if test "x$t" = x
+then
+ configure_default_options="{ { NULL, NULL} }"
+else
+ configure_default_options="{ ${t} }"
+fi
+
+if test "$target_cpu_default2" != ""
+then
+ if test "$target_cpu_default" != ""
+ then
+ target_cpu_default="(${target_cpu_default}|${target_cpu_default2})"
+ else
+ target_cpu_default=$target_cpu_default2
+ fi
+fi
+
+case ${target} in
+i[34567]86-*-* | x86_64-*-*)
+ if test x$enable_as_accelerator = xyes; then
+ extra_programs="mkoffload\$(exeext)"
+ fi
+ ;;
+esac
diff --git a/support/cpp/gcc/config.host b/support/cpp/gcc/config.host
new file mode 100644
index 000000000..4ca300f11
--- /dev/null
+++ b/support/cpp/gcc/config.host
@@ -0,0 +1,301 @@
+# GCC host-specific configuration file.
+# 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/>.
+
+# This is the GCC host-specific configuration file
+# where a configuration type is mapped to different system-specific
+# definitions and files. This is invoked by the autoconf-generated
+# configure script. Putting it in a separate shell file lets us skip
+# running autoconf when modifying host-specific information.
+
+# This file switches on the shell variable ${host}. As much of this as
+# is reasonable should be replaced with autoconf tests in the future.
+
+# This file sets the following shell variables for use by the
+# autoconf-generated configure script:
+#
+# host_xm_file List of files to include when compiling for the
+# host machine.
+#
+# host_xm_defines List of macros to define when compiling for the
+# host machine.
+#
+# host_xmake_file List of host-specific makefile-fragments.
+#
+# host_exeext Set to the suffix, if the host machine requires
+# executables to have a file name suffix.
+#
+# host_extra_objs List of extra host-dependent objects that should
+# be linked into the compiler proper.
+#
+# host_extra_gcc_objs List of extra host-dependent objects that should
+# be linked into the gcc driver.
+#
+# out_host_hook_obj An object file that provides the host hooks.
+#
+# host_can_use_collect2 Set to yes normally; to no if the host cannot
+# link or otherwise use collect2
+#
+# use_long_long_for_widest_fast_int Set this to 'yes' if 'long long'
+# (or '__int64') is wider than 'long' but still
+# efficeiently supported by the host hardware.
+# Only affects compile speed. Default is 'no'.
+#
+# host_lto_plugin_soname Set this to the name to which the LTO linker
+# plugin gets compiled on this host, if it is
+# different from the default "liblto_plugin.so".
+
+# When setting any of these variables, check to see if a corresponding
+# variable is present in config.build; if so, you will likely want to
+# set it in both places.
+
+# Default settings.
+host_xm_file=
+host_xm_defines=
+host_xmake_file=
+host_exeext=
+host_extra_objs=
+host_extra_gcc_objs=
+out_host_hook_obj=host-default.o
+host_can_use_collect2=yes
+use_long_long_for_widest_fast_int=no
+host_lto_plugin_soname=liblto_plugin.so
+
+# Unsupported hosts list. Generally, only include hosts known to fail here,
+# since we allow hosts not listed to be supported generically.
+case ${host} in
+ i[34567]86-sequent-sysv \
+ | i[34567]86-sequent-sysv[123]* \
+ | i[34567]86-go32-* \
+ | i[34567]86-*-go32* \
+ | vax-*-vms*)
+ echo "*** Configuration for host ${host} not supported" 1>&2
+ exit 1
+ ;;
+esac
+
+# Common parts for widely ported systems.
+case ${host} in
+ *-darwin*)
+ # Generic darwin host support.
+ out_host_hook_obj=host-darwin.o
+ host_xmake_file="${host_xmake_file} x-darwin"
+ ;;
+esac
+
+case ${host} in
+ aarch64*-*-freebsd* | aarch64*-*-linux* | aarch64*-*-fuchsia* |\
+ aarch64*-*-darwin*)
+ case ${target} in
+ aarch64*-*-*)
+ host_extra_gcc_objs="driver-aarch64.o"
+ host_xmake_file="${host_xmake_file} aarch64/x-aarch64"
+ ;;
+ esac
+ ;;
+ arm*-*-freebsd* | arm*-*-netbsd* | arm*-*-linux* | arm*-*-fuchsia*)
+ case ${target} in
+ arm*-*-*)
+ host_extra_gcc_objs="driver-arm.o"
+ host_xmake_file="${host_xmake_file} arm/x-arm"
+ ;;
+ esac
+ ;;
+ alpha*-*-linux*)
+ case ${target} in
+ alpha*-*-linux*)
+ host_extra_gcc_objs="driver-alpha.o"
+ host_xmake_file="${host_xmake_file} alpha/x-alpha"
+ ;;
+ esac
+ ;;
+ i[34567]86-*-* \
+ | x86_64-*-* )
+ case ${target} in
+ i[34567]86-*-* \
+ | x86_64-*-* )
+ host_extra_gcc_objs="driver-i386.o"
+ host_xmake_file="${host_xmake_file} i386/x-i386"
+ ;;
+ esac
+ ;;
+ mips*-*-linux*)
+ case ${target} in
+ mips*-*-linux*)
+ host_extra_gcc_objs="driver-native.o"
+ host_xmake_file="${host_xmake_file} mips/x-native"
+ ;;
+ esac
+ ;;
+ rs6000-*-* \
+ | powerpc*-*-* )
+ case ${target} in
+ rs6000-*-* \
+ | powerpc*-*-* )
+ host_extra_gcc_objs="driver-rs6000.o"
+ host_xmake_file="${host_xmake_file} rs6000/x-rs6000"
+ ;;
+ esac
+ case ${host} in
+ *-*-linux* | *-*-freebsd*)
+ if test "${GCC}:${ac_cv_sizeof_long}" = yes:4; then
+ # On powerpc*-*-linux* use -Wl,--relax to link cc1,
+ # if ld is new enough, otherwise force -O1 in CFLAGS.
+ host_ppc_relax_xmake_file=
+ host_ld_ver=`${CC} -Wl,--version 2>/dev/null | sed 1q`
+ if echo "$host_ld_ver" | grep GNU > /dev/null; then
+ host_ld_date=`echo $host_ld_ver \
+ | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
+ if test 0"$host_ld_date" -gt 20080806; then
+ host_ppc_relax_xmake_file=rs6000/x-linux-relax
+ fi
+ fi
+ if test -z "${host_ppc_relax_xmake_file}"; then
+ host_ppc_relax_xmake_file=x-cflags-O1
+ fi
+ host_xmake_file="${host_xmake_file} ${host_ppc_relax_xmake_file}"
+ fi
+ ;;
+ esac
+ ;;
+ s390-*-* | s390x-*-*)
+ case ${target} in
+ s390-*-* | s390x-*-*)
+ host_extra_gcc_objs="driver-native.o"
+ host_xmake_file="${host_xmake_file} s390/x-native"
+ ;;
+ esac
+ ;;
+ sparc*-*-solaris2*)
+ case ${target} in
+ sparc*-*-solaris2*)
+ host_extra_gcc_objs="driver-sparc.o"
+ host_xmake_file="${host_xmake_file} sparc/x-sparc"
+ ;;
+ esac
+ ;;
+ sparc*-*-linux*)
+ case ${target} in
+ sparc*-*-linux*)
+ host_extra_gcc_objs="driver-sparc.o"
+ host_xmake_file="${host_xmake_file} sparc/x-sparc"
+ ;;
+ esac
+ ;;
+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"
+ ;;
+ hppa*-*-linux*)
+ out_host_hook_obj=host-hpux.o
+ host_xmake_file="${host_xmake_file} x-hpux"
+ ;;
+ i[34567]86-*-solaris2* | x86_64-*-solaris2*)
+ out_host_hook_obj=host-solaris.o
+ host_xmake_file="${host_xmake_file} x-solaris"
+ ;;
+ i[34567]86-pc-msdosdjgpp*)
+ host_xm_file=i386/xm-djgpp.h
+ host_exeext=.exe
+ # Shorten $target_noncanonical for 8.3 filename conventions.
+ case ${target} in
+ *pc-msdosdjgpp*)
+ target_noncanonical=djgpp
+ ;;
+ esac
+ ;;
+ i[34567]86-*-cygwin* | x86_64-*-cygwin*)
+ host_xm_file=i386/xm-cygwin.h
+ out_host_hook_obj=host-cygwin.o
+ host_xmake_file="${host_xmake_file} i386/x-cygwin"
+ host_exeext=.exe
+ host_lto_plugin_soname=cyglto_plugin.dll
+ ;;
+ i[34567]86-*-mingw32*)
+ host_xm_file=i386/xm-mingw32.h
+ host_xmake_file="${host_xmake_file} i386/x-mingw32"
+ host_exeext=.exe
+ out_host_hook_obj=host-mingw32.o
+ host_extra_gcc_objs="${host_extra_gcc_objs} driver-mingw32.o"
+ host_lto_plugin_soname=liblto_plugin.dll
+ ;;
+ x86_64-*-mingw*)
+ use_long_long_for_widest_fast_int=yes
+ host_xm_file=i386/xm-mingw32.h
+ host_xmake_file="${host_xmake_file} i386/x-mingw32"
+ host_exeext=.exe
+ out_host_hook_obj=host-mingw32.o
+ host_extra_gcc_objs="${host_extra_gcc_objs} driver-mingw32.o"
+ host_lto_plugin_soname=liblto_plugin.dll
+ ;;
+ aarch64*-*-darwin*)
+ out_host_hook_obj="${out_host_hook_obj} host-aarch64-darwin.o"
+ host_xmake_file="${host_xmake_file} aarch64/x-darwin"
+ ;;
+ i[34567]86-*-darwin* | x86_64-*-darwin*)
+ out_host_hook_obj="${out_host_hook_obj} host-i386-darwin.o"
+ host_xmake_file="${host_xmake_file} i386/x-darwin"
+ ;;
+ powerpc-*-darwin*)
+ out_host_hook_obj="${out_host_hook_obj} host-ppc-darwin.o"
+ host_xmake_file="${host_xmake_file} rs6000/x-darwin"
+ ;;
+ powerpc64-*-darwin*)
+ out_host_hook_obj="${out_host_hook_obj} host-ppc64-darwin.o"
+ host_xmake_file="${host_xmake_file} rs6000/x-darwin64"
+ ;;
+ rs6000-ibm-aix* | powerpc-ibm-aix*)
+ host_xmake_file="${host_xmake_file} rs6000/x-aix"
+ ;;
+ *-*-solaris2*)
+ out_host_hook_obj=host-solaris.o
+ host_xmake_file="${host_xmake_file} x-solaris"
+ ;;
+ *-*-linux*)
+ out_host_hook_obj=host-linux.o
+ host_xmake_file="${host_xmake_file} x-linux"
+ ;;
+ *-*-openbsd*)
+ out_host_hook_obj=host-openbsd.o
+ host_xmake_file="${host_xmake_file} x-openbsd"
+ ;;
+ *-*-netbsd*)
+ out_host_hook_obj=host-netbsd.o
+ host_xmake_file="${host_xmake_file} x-netbsd"
+ ;;
+ ia64-*-hpux*)
+ use_long_long_for_widest_fast_int=yes
+ out_host_hook_obj=host-hpux.o
+ host_xmake_file="${host_xmake_file} x-hpux"
+ ;;
+ *-*-*vms*)
+ host_xm_file="vms/xm-vms.h"
+ host_xmake_file=vms/x-vms
+ host_exeext=.exe
+ host_can_use_collect2=no
+ ;;
+esac
diff --git a/support/cpp/gcc/config.in b/support/cpp/gcc/config.in
new file mode 100644
index 000000000..64c27c9cf
--- /dev/null
+++ b/support/cpp/gcc/config.in
@@ -0,0 +1,2734 @@
+/* config.in. Generated from configure.ac by autoheader. */
+
+/* Define if this compiler should be built as the offload target compiler. */
+#ifndef USED_FOR_TARGET
+#undef ACCEL_COMPILER
+#endif
+
+
+/* Define if building universal (internal helper macro) */
+#ifndef USED_FOR_TARGET
+#undef AC_APPLE_UNIVERSAL_BUILD
+#endif
+
+
+/* Define to the assembler option to enable compressed debug sections. */
+#ifndef USED_FOR_TARGET
+#undef AS_COMPRESS_DEBUG_OPTION
+#endif
+
+
+/* Define to the assembler option to disable compressed debug sections. */
+#ifndef USED_FOR_TARGET
+#undef AS_NO_COMPRESS_DEBUG_OPTION
+#endif
+
+
+/* Define to the root for URLs about GCC changes. */
+#ifndef USED_FOR_TARGET
+#undef CHANGES_ROOT_URL
+#endif
+
+
+/* Define as the number of bits in a byte, if `limits.h' doesn't. */
+#ifndef USED_FOR_TARGET
+#undef CHAR_BIT
+#endif
+
+
+/* Define to 0/1 if you want more run-time sanity checks. This one gets a grab
+ bag of miscellaneous but relatively cheap checks. */
+#ifndef USED_FOR_TARGET
+#undef CHECKING_P
+#endif
+
+
+/* Define 0/1 to force the choice for exception handling model. */
+#ifndef USED_FOR_TARGET
+#undef CONFIG_SJLJ_EXCEPTIONS
+#endif
+
+
+/* Define to enable the use of a default assembler. */
+#ifndef USED_FOR_TARGET
+#undef DEFAULT_ASSEMBLER
+#endif
+
+
+/* Define to enable the use of a default debug linker. */
+#ifndef USED_FOR_TARGET
+#undef DEFAULT_DSYMUTIL
+#endif
+
+
+/* Define to enable the use of a default linker. */
+#ifndef USED_FOR_TARGET
+#undef DEFAULT_LINKER
+#endif
+
+
+/* Define to larger than zero set the default stack clash protector size. */
+#ifndef USED_FOR_TARGET
+#undef DEFAULT_STK_CLASH_GUARD_SIZE
+#endif
+
+
+/* Define if you want to use __cxa_atexit, rather than atexit, to register C++
+ destructors for local statics and global objects. This is essential for
+ fully standards-compliant handling of destructors, but requires
+ __cxa_atexit in libc. */
+#ifndef USED_FOR_TARGET
+#undef DEFAULT_USE_CXA_ATEXIT
+#endif
+
+
+/* The default for -fdiagnostics-color option */
+#ifndef USED_FOR_TARGET
+#undef DIAGNOSTICS_COLOR_DEFAULT
+#endif
+
+
+/* The default for -fdiagnostics-urls option */
+#ifndef USED_FOR_TARGET
+#undef DIAGNOSTICS_URLS_DEFAULT
+#endif
+
+
+/* Define to the root for documentation URLs. */
+#ifndef USED_FOR_TARGET
+#undef DOCUMENTATION_ROOT_URL
+#endif
+
+
+/* Define to the dsymutil version. */
+#ifndef USED_FOR_TARGET
+#undef DSYMUTIL_VERSION
+#endif
+
+
+/* Define 0/1 if static analyzer feature is enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_ANALYZER
+#endif
+
+
+/* Define if you want assertions enabled. This is a cheap check. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_ASSERT_CHECKING
+#endif
+
+
+/* Define to 1 to specify that we are using the BID decimal floating point
+ format instead of DPD */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_DECIMAL_BID_FORMAT
+#endif
+
+
+/* Define to 1 to enable decimal float extension to C. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_DECIMAL_FLOAT
+#endif
+
+
+/* Define if your target supports default PIE and it is enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_DEFAULT_PIE
+#endif
+
+
+/* Define if your target supports default stack protector and it is enabled.
+ */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_DEFAULT_SSP
+#endif
+
+
+/* Define if you want more run-time sanity checks for dataflow. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_DF_CHECKING
+#endif
+
+
+/* Define to 0/1 if you want extra run-time checking that might affect code
+ generation. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_EXTRA_CHECKING
+#endif
+
+
+/* Define to 1 to enable fixed-point arithmetic extension to C. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_FIXED_POINT
+#endif
+
+
+/* Define if you want fold checked that it never destructs its argument. This
+ is quite expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_FOLD_CHECKING
+#endif
+
+
+/* Define if you want the garbage collector to operate in maximally paranoid
+ mode, validating the entire heap and collecting garbage at every
+ opportunity. This is extremely expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_GC_ALWAYS_COLLECT
+#endif
+
+
+/* Define if you want the garbage collector to do object poisoning and other
+ memory allocation checks. This is quite expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_GC_CHECKING
+#endif
+
+
+/* Define if you want operations on GIMPLE (the basic data structure of the
+ high-level optimizers) to be checked for dynamic type safety at runtime.
+ This is moderately expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_GIMPLE_CHECKING
+#endif
+
+
+/* Define if gcc should always pass --build-id to linker. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_LD_BUILDID
+#endif
+
+
+/* Define to 1 to enable libquadmath support */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_LIBQUADMATH_SUPPORT
+#endif
+
+
+/* Define to enable LTO support. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_LTO
+#endif
+
+
+/* Define to 1 if translation of program messages to the user's native
+ language is requested. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_NLS
+#endif
+
+
+/* Define this to enable support for offloading. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_OFFLOADING
+#endif
+
+
+/* Define to enable plugin support. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_PLUGIN
+#endif
+
+
+/* Define if you want all operations on RTL (the basic data structure of the
+ optimizer and back end) to be checked for dynamic type safety at runtime.
+ This is quite expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_RTL_CHECKING
+#endif
+
+
+/* Define if you want RTL flag accesses to be checked against the RTL codes
+ that are supported for each access macro. This is relatively cheap. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_RTL_FLAG_CHECKING
+#endif
+
+
+/* Define if you want runtime assertions enabled. This is a cheap check. */
+#undef ENABLE_RUNTIME_CHECKING
+
+/* Define to enable evaluating float expressions with double precision in
+ standards-compatible mode on s390 targets. */
+#undef ENABLE_S390_EXCESS_FLOAT_PRECISION
+
+/* Define if the -stdlib= option should be enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_STDLIB_OPTION
+#endif
+
+
+/* Define if you want all operations on trees (the basic data structure of the
+ front ends) to be checked for dynamic type safety at runtime. This is
+ moderately expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_TREE_CHECKING
+#endif
+
+
+/* Define if you want all gimple types to be verified after gimplifiation.
+ This is cheap. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_TYPES_CHECKING
+#endif
+
+
+/* Define to get calls to the valgrind runtime enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_VALGRIND_ANNOTATIONS
+#endif
+
+
+/* Define if you want to run subprograms and generated programs through
+ valgrind (a memory checker). This is extremely expensive. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_VALGRIND_CHECKING
+#endif
+
+
+/* Define 0/1 if vtable verification feature is enabled. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_VTABLE_VERIFY
+#endif
+
+
+/* Define to 1 if installation paths should be looked up in the Windows
+ Registry. Ignored on non-Windows hosts. */
+#ifndef USED_FOR_TARGET
+#undef ENABLE_WIN32_REGISTRY
+#endif
+
+
+/* Define to the name of a file containing a list of extra machine modes for
+ this architecture. */
+#ifndef USED_FOR_TARGET
+#undef EXTRA_MODES_FILE
+#endif
+
+
+/* Define to enable detailed memory allocation stats gathering. */
+#ifndef USED_FOR_TARGET
+#undef GATHER_STATISTICS
+#endif
+
+
+/* Define to 1 if `TIOCGWINSZ' requires <sys/ioctl.h>. */
+#ifndef USED_FOR_TARGET
+#undef GWINSZ_IN_SYS_IOCTL
+#endif
+
+
+/* mcontext_t fields start with __ */
+#ifndef USED_FOR_TARGET
+#undef HAS_MCONTEXT_T_UNDERSCORES
+#endif
+
+
+/* Define if AF_INET6 supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AF_INET6
+#endif
+
+
+/* Define if AF_UNIX supported. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AF_UNIX
+#endif
+
+
+/* Define if your assembler supports architecture modifiers. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_ARCHITECTURE_MODIFIERS
+#endif
+
+
+/* Define if your avr assembler supports -mgcc-isr option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_AVR_MGCCISR_OPTION
+#endif
+
+
+/* Define if your avr assembler supports --mlink-relax option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_AVR_MLINK_RELAX_OPTION
+#endif
+
+
+/* Define if your avr assembler supports -mrmw option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_AVR_MRMW_OPTION
+#endif
+
+
+/* Define to the level of your assembler's compressed debug section support.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_COMPRESS_DEBUG
+#endif
+
+
+/* Define if your assembler supports the --debug-prefix-map option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DEBUG_PREFIX_MAP
+#endif
+
+
+/* Define if your assembler supports .module. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DOT_MODULE
+#endif
+
+
+/* Define if your assembler supports DSPR1 mult. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DSPR1_MULT
+#endif
+
+
+/* Define if your assembler supports .dtprelword. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DTPRELWORD
+#endif
+
+
+/* Define if your assembler supports dwarf2 .file/.loc directives, and
+ preserves file table indices exactly as given. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DWARF2_DEBUG_LINE
+#endif
+
+
+/* Define if your assembler supports views in dwarf2 .loc directives. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DWARF2_DEBUG_VIEW
+#endif
+
+
+/* Define if your assembler supports the R_PPC64_ENTRY relocation. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_ENTRY_MARKERS
+#endif
+
+
+/* Define if your assembler supports explicit relocations. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_EXPLICIT_RELOCS
+#endif
+
+
+/* Define if your assembler supports FMAF, HPC, and VIS 3.0 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_FMAF_HPC_VIS3
+#endif
+
+
+/* Define if your assembler supports the --gdwarf2 option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_GDWARF2_DEBUG_FLAG
+#endif
+
+
+/* Define if your assembler supports the --gdwarf-5 option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_GDWARF_5_DEBUG_FLAG
+#endif
+
+
+/* Define if your assembler supports .gnu_attribute. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_GNU_ATTRIBUTE
+#endif
+
+
+/* Define true if the assembler supports '.long foo@GOTOFF'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_GOTOFF_IN_DATA
+#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
+#endif
+
+
+/* Define if your assembler supports the subtraction of symbols in different
+ sections. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_DIFF_SECT_DELTA
+#endif
+
+
+/* Define if your assembler supports the ffreep mnemonic. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_FFREEP
+#endif
+
+
+/* Define if your assembler uses fildq and fistq mnemonics. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_FILDQ
+#endif
+
+
+/* Define if your assembler uses filds and fists mnemonics. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_FILDS
+#endif
+
+
+/* Define 0/1 if your assembler and linker support @GOT. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_GOT32X
+#endif
+
+
+/* Define if your assembler supports HLE prefixes. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_HLE
+#endif
+
+
+/* Define if your assembler supports interunit movq mnemonic. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_INTERUNIT_MOVQ
+#endif
+
+
+/* Define if your assembler supports the .quad directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_QUAD
+#endif
+
+
+/* Define if the assembler supports 'rep <insn>, lock <insn>'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_REP_LOCK_PREFIX
+#endif
+
+
+/* Define if your assembler supports the sahf mnemonic in 64bit mode. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_SAHF
+#endif
+
+
+/* Define if your assembler supports the swap suffix. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_SWAP
+#endif
+
+
+/* Define if your assembler and linker support @tlsgdplt. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_TLSGDPLT
+#endif
+
+
+/* Define to 1 if your assembler and linker support @tlsldm. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_TLSLDM
+#endif
+
+
+/* Define to 1 if your assembler and linker support @tlsldmplt. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_TLSLDMPLT
+#endif
+
+
+/* Define 0/1 if your assembler and linker support calling ___tls_get_addr via
+ GOT. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_TLS_GET_ADDR_GOT
+#endif
+
+
+/* Define if your assembler supports the 'ud2' mnemonic. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_IX86_UD2
+#endif
+
+
+/* Define if your assembler supports the lituse_jsrdirect relocation. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_JSRDIRECT_RELOCS
+#endif
+
+
+/* Define if your assembler supports .sleb128 and .uleb128. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_LEB128
+#endif
+
+
+/* Define if your assembler supports LEON instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_LEON
+#endif
+
+
+/* Define if the assembler won't complain about a line such as # 0 "" 2. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_LINE_ZERO
+#endif
+
+
+/* Define if your assembler supports ltoffx and ldxmov relocations. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_LTOFFX_LDXMOV_RELOCS
+#endif
+
+
+/* Define if your assembler supports the -mabi option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MABI_OPTION
+#endif
+
+
+/* Define if your assembler supports .machine and .machinemode. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MACHINE_MACHINEMODE
+#endif
+
+
+/* Define if the assembler understands -march=rv*_zifencei. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZIFENCEI
+#endif
+
+
+/* Define if your assembler supports mfcr field. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MFCRF
+#endif
+
+
+/* Define if the assembler understands -misa-spec=. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MISA_SPEC
+#endif
+
+
+/* Define if your Mac OS X assembler supports -mllvm -x86-pad-for-align=false.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MLLVM_X86_PAD_FOR_ALIGN
+#endif
+
+
+/* Define if your Mac OS X assembler supports the -mmacos-version-min option.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MMACOSX_VERSION_MIN_OPTION
+#endif
+
+
+/* Define if your assembler supports .mspabi_attribute. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MSPABI_ATTRIBUTE
+#endif
+
+
+/* Define if the assembler understands -mnan=. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_NAN
+#endif
+
+
+/* Define if your assembler supports %gotoff relocation syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_NIOS2_GOTOFF_RELOCATION
+#endif
+
+
+/* Define if your assembler supports the -no-mul-bug-abort option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_NO_MUL_BUG_ABORT_OPTION
+#endif
+
+
+/* Define if the assembler understands -mno-shared. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_NO_SHARED
+#endif
+
+
+/* Define if your assembler supports offsetable %lo(). */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_OFFSETABLE_LO10
+#endif
+
+
+/* Define if your assembler supports R_PPC*_PLTSEQ relocations. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_PLTSEQ
+#endif
+
+
+/* Define if your assembler supports .ref */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_REF
+#endif
+
+
+/* Define if your assembler supports R_PPC_REL16 relocs. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_REL16
+#endif
+
+
+/* Define if your assembler supports -relax option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_RELAX_OPTION
+#endif
+
+
+/* Define if your assembler supports .attribute. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_RISCV_ATTRIBUTE
+#endif
+
+
+/* Define if your assembler supports relocs needed by -fpic. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SMALL_PIC_RELOCS
+#endif
+
+
+/* Define if your assembler supports SPARC4 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC4
+#endif
+
+
+/* Define if your assembler supports SPARC5 and VIS 4.0 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC5_VIS4
+#endif
+
+
+/* Define if your assembler supports SPARC6 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC6
+#endif
+
+
+/* Define if your assembler and linker support GOTDATA_OP relocs. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC_GOTDATA_OP
+#endif
+
+
+/* Define if your assembler and linker support unaligned PC relative relocs.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC_UA_PCREL
+#endif
+
+
+/* Define if your assembler and linker support unaligned PC relative relocs
+ against hidden symbols. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC_UA_PCREL_HIDDEN
+#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
+#endif
+
+
+/* Define if your assembler supports vl/vst/vlm/vstm with an optional
+ alignment hint argument. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_VECTOR_LOADSTORE_ALIGNMENT_HINTS
+#endif
+
+
+/* Define if your assembler supports vl/vst/vlm/vstm with an optional
+ alignment hint argument on z13. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_VECTOR_LOADSTORE_ALIGNMENT_HINTS_ON_Z13
+#endif
+
+
+/* Define if your assembler supports VSX instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_VSX
+#endif
+
+
+/* Define if your assembler supports --gdwarf-4/--gdwarf-5 even with compiler
+ generated .debug_line. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_WORKING_DWARF_N_FLAG
+#endif
+
+
+/* Define if your assembler supports -xbrace_comment option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_XBRACE_COMMENT_OPTION
+#endif
+
+
+/* Define to 1 if you have the `atoq' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_ATOQ
+#endif
+
+
+/* Define to 1 if you have the `clearerr_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_CLEARERR_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `clock' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_CLOCK
+#endif
+
+
+/* Define if <time.h> defines clock_t. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_CLOCK_T
+#endif
+
+
+/* Define 0/1 if your assembler and linker support COMDAT groups. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_COMDAT_GROUP
+#endif
+
+
+/* Define to 1 if we found a declaration for 'abort', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_ABORT
+#endif
+
+
+/* Define to 1 if we found a declaration for 'asprintf', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_ASPRINTF
+#endif
+
+
+/* Define to 1 if we found a declaration for 'atof', otherwise define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_ATOF
+#endif
+
+
+/* Define to 1 if we found a declaration for 'atol', otherwise define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_ATOL
+#endif
+
+
+/* Define to 1 if we found a declaration for 'atoll', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_ATOLL
+#endif
+
+
+/* Define to 1 if you have the declaration of `basename(const char*)', and to
+ 0 if you don't. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_BASENAME
+#endif
+
+
+/* Define to 1 if we found a declaration for 'calloc', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_CALLOC
+#endif
+
+
+/* Define to 1 if we found a declaration for 'clearerr_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_CLEARERR_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'clock', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_CLOCK
+#endif
+
+
+/* Define to 1 if we found a declaration for 'errno', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_ERRNO
+#endif
+
+
+/* Define to 1 if we found a declaration for 'feof_unlocked', otherwise define
+ to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FEOF_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'ferror_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FERROR_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fflush_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FFLUSH_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'ffs', otherwise define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FFS
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fgetc_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FGETC_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fgets_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FGETS_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fileno_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FILENO_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fprintf_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FPRINTF_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fputc_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FPUTC_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fputs_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FPUTS_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fread_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FREAD_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'free', otherwise define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FREE
+#endif
+
+
+/* Define to 1 if we found a declaration for 'fwrite_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_FWRITE_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getchar_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETCHAR_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getcwd', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETCWD
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getc_unlocked', otherwise define
+ to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETC_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getenv', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETENV
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getopt', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETOPT
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getpagesize', otherwise define
+ to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETPAGESIZE
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getrlimit', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETRLIMIT
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getrusage', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETRUSAGE
+#endif
+
+
+/* Define to 1 if we found a declaration for 'getwd', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_GETWD
+#endif
+
+
+/* Define to 1 if we found a declaration for 'ldgetname', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_LDGETNAME
+#endif
+
+
+/* Define to 1 if we found a declaration for 'madvise', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_MADVISE
+#endif
+
+
+/* Define to 1 if we found a declaration for 'mallinfo', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_MALLINFO
+#endif
+
+
+/* Define to 1 if we found a declaration for 'mallinfo2', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_MALLINFO2
+#endif
+
+
+/* Define to 1 if we found a declaration for 'malloc', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_MALLOC
+#endif
+
+
+/* Define to 1 if we found a declaration for 'putchar_unlocked', otherwise
+ define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_PUTCHAR_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'putc_unlocked', otherwise define
+ to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_PUTC_UNLOCKED
+#endif
+
+
+/* Define to 1 if we found a declaration for 'realloc', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_REALLOC
+#endif
+
+
+/* Define to 1 if we found a declaration for 'sbrk', otherwise define to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_SBRK
+#endif
+
+
+/* Define to 1 if we found a declaration for 'setenv', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_SETENV
+#endif
+
+
+/* Define to 1 if we found a declaration for 'setrlimit', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_SETRLIMIT
+#endif
+
+
+/* Define to 1 if we found a declaration for 'sigaltstack', otherwise define
+ to 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_SIGALTSTACK
+#endif
+
+
+/* Define to 1 if we found a declaration for 'snprintf', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_SNPRINTF
+#endif
+
+
+/* Define to 1 if we found a declaration for 'stpcpy', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STPCPY
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strnlen', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRNLEN
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strsignal', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRSIGNAL
+#endif
+
+
+/* Define to 1 if you have the declaration of `strstr(const char*,const
+ char*)', and to 0 if you don't. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRSTR
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strtol', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRTOL
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strtoll', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRTOLL
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strtoul', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRTOUL
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strtoull', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRTOULL
+#endif
+
+
+/* Define to 1 if we found a declaration for 'strverscmp', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_STRVERSCMP
+#endif
+
+
+/* Define to 1 if we found a declaration for 'times', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_TIMES
+#endif
+
+
+/* Define to 1 if we found a declaration for 'unsetenv', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_UNSETENV
+#endif
+
+
+/* Define to 1 if we found a declaration for 'vasprintf', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_VASPRINTF
+#endif
+
+
+/* Define to 1 if we found a declaration for 'vsnprintf', otherwise define to
+ 0. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_VSNPRINTF
+#endif
+
+
+/* Define to 1 if you have the <direct.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DIRECT_H
+#endif
+
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DLFCN_H
+#endif
+
+
+/* Define to 1 if you have the <ext/hash_map> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_EXT_HASH_MAP
+#endif
+
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FCNTL_H
+#endif
+
+
+/* Define to 1 if you have the `feof_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FEOF_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `ferror_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FERROR_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fflush_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FFLUSH_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fgetc_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FGETC_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fgets_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FGETS_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fileno_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FILENO_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fork' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FORK
+#endif
+
+
+/* Define to 1 if you have the `fprintf_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FPRINTF_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fputc_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FPUTC_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fputs_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FPUTS_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fread_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FREAD_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `fstatat' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FSTATAT
+#endif
+
+
+/* Define to 1 if you have the <ftw.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FTW_H
+#endif
+
+
+/* Define to 1 if you have the `fwrite_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_FWRITE_UNLOCKED
+#endif
+
+
+/* Define if your assembler supports specifying the alignment of objects
+ allocated using the GAS .comm command. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_ALIGNED_COMM
+#endif
+
+
+/* Define if your Arm assembler permits context-specific feature extensions.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_ARM_EXTENDED_ARCH
+#endif
+
+
+/* Define if your assembler supports .balign and .p2align. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_BALIGN_AND_P2ALIGN
+#endif
+
+
+/* Define 0/1 if your assembler supports CFI directives. */
+#undef HAVE_GAS_CFI_DIRECTIVE
+
+/* Define 0/1 if your assembler supports .cfi_personality. */
+#undef HAVE_GAS_CFI_PERSONALITY_DIRECTIVE
+
+/* Define 0/1 if your assembler supports .cfi_sections. */
+#undef HAVE_GAS_CFI_SECTIONS_DIRECTIVE
+
+/* Define if your assembler supports the .loc discriminator sub-directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_DISCRIMINATOR
+#endif
+
+
+/* Define if your assembler supports @gnu_unique_object. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_GNU_UNIQUE_OBJECT
+#endif
+
+
+/* Define if your assembler and linker support .hidden. */
+#undef HAVE_GAS_HIDDEN
+
+/* Define if your assembler supports .lcomm with an alignment field. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_LCOMM_WITH_ALIGNMENT
+#endif
+
+
+/* Define if your assembler supports .literal16. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_LITERAL16
+#endif
+
+
+/* Define if your assembler supports the .loc is_stmt sub-directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_LOC_STMT
+#endif
+
+
+/* Define if your assembler supports specifying the maximum number of bytes to
+ skip when using the GAS .p2align command. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_MAX_SKIP_P2ALIGN
+#endif
+
+
+/* Define if your assembler supports the .set micromips directive */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_MICROMIPS
+#endif
+
+
+/* Define if your assembler supports .nsubspa comdat option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_NSUBSPA_COMDAT
+#endif
+
+
+/* Define if your assembler and linker support 32-bit section relative relocs
+ via '.secrel32 label'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_PE_SECREL32_RELOC
+#endif
+
+
+/* Define if your assembler supports specifying the exclude section flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SECTION_EXCLUDE
+#endif
+
+
+/* Define 0/1 if your assembler supports 'o' flag in .section directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SECTION_LINK_ORDER
+#endif
+
+
+/* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
+ flag. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_GNU_RETAIN
+#endif
+
+
+/* Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SHF_MERGE
+#endif
+
+
+/* Define if your assembler supports .subsection and .subsection -1 starts
+ emitting at the beginning of your section. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SUBSECTION_ORDERING
+#endif
+
+
+/* Define if your assembler supports .weak. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_WEAK
+#endif
+
+
+/* Define if your assembler supports .weakref. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_WEAKREF
+#endif
+
+
+/* Define if your assembler has fixed global_load functions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_GLOBAL_LOAD_FIXED
+#endif
+
+
+/* Define if your assembler expects amdgcn_target gfx908+xnack syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V3_SYNTAX
+#endif
+
+
+/* Define if your assembler expects amdgcn_target gfx908:xnack+ syntax. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_ASM_V4_SYNTAX
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for fiji. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_SRAM_ECC_FIJI
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for gfx900. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_SRAM_ECC_GFX900
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for gfx906. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_SRAM_ECC_GFX906
+#endif
+
+
+/* Define if your assembler allows -mattr=+sramecc for gfx908. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_SRAM_ECC_GFX908
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for fiji. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_FIJI
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx900. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX900
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx906. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX906
+#endif
+
+
+/* Define if your assembler allows -mattr=+xnack for gfx908. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GCN_XNACK_GFX908
+#endif
+
+
+/* Define to 1 if you have the `getchar_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GETCHAR_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `getc_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GETC_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `getrlimit' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GETRLIMIT
+#endif
+
+
+/* Define to 1 if you have the `getrusage' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GETRUSAGE
+#endif
+
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GETTIMEOFDAY
+#endif
+
+
+/* Define to 1 if using GNU as. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GNU_AS
+#endif
+
+
+/* Define if your system supports gnu indirect functions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GNU_INDIRECT_FUNCTION
+#endif
+
+
+/* Define to 1 if using GNU ld. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GNU_LD
+#endif
+
+
+/* Define if the gold linker supports split stack and is available as a
+ non-default */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GOLD_NON_DEFAULT_SPLIT_STACK
+#endif
+
+
+/* Define if you have the iconv() function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_ICONV
+#endif
+
+
+/* Define to 1 if you have the <iconv.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_ICONV_H
+#endif
+
+
+/* Define 0/1 if .init_array/.fini_array sections are available and working.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_INITFINI_ARRAY_SUPPORT
+#endif
+
+
+/* Define to 1 if the system has the type `intmax_t'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_INTMAX_T
+#endif
+
+
+/* Define to 1 if the system has the type `intptr_t'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_INTPTR_T
+#endif
+
+
+/* Define if you have a working <inttypes.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_INTTYPES_H
+#endif
+
+
+/* Define to 1 if you have the `kill' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_KILL
+#endif
+
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LANGINFO_CODESET
+#endif
+
+
+/* Define to 1 if you have the <langinfo.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LANGINFO_H
+#endif
+
+
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LC_MESSAGES
+#endif
+
+
+/* Define to 1 if you have the <ldfcn.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LDFCN_H
+#endif
+
+
+/* Define 0/1 if your linker supports the SHF_MERGE flag with section
+ alignment > 1. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_ALIGNED_SHF_MERGE
+#endif
+
+
+/* Define if your linker supports --as-needed/--no-as-needed or equivalent
+ options. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_AS_NEEDED
+#endif
+
+
+/* Define if your default avr linker script for avrxmega3 leaves .rodata in
+ flash. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
+#endif
+
+
+/* Define if your linker supports -z bndplt */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_BNDPLT_SUPPORT
+#endif
+
+
+/* Define if the PE linker has broken DWARF 5 support. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_BROKEN_PE_DWARF5
+#endif
+
+
+/* Define if your linker supports --build-id. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_BUILDID
+#endif
+
+
+/* Define if the linker supports clearing hardware capabilities via mapfile.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_CLEARCAP
+#endif
+
+
+/* Define to the level of your linker's compressed debug section support. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_COMPRESS_DEBUG
+#endif
+
+
+/* Define if your linker supports --demangle option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_DEMANGLE
+#endif
+
+
+/* Define 0/1 if your linker supports CIE v3 in .eh_frame. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_EH_FRAME_CIEV3
+#endif
+
+
+/* Define if your linker supports .eh_frame_hdr. */
+#undef HAVE_LD_EH_FRAME_HDR
+
+/* Define if your linker supports garbage collection of sections in presence
+ of EH frames. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_EH_GC_SECTIONS
+#endif
+
+
+/* Define if your linker has buggy garbage collection of sections support when
+ .text.startup.foo like sections are used. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_EH_GC_SECTIONS_BUG
+#endif
+
+
+/* Define if your PowerPC64 linker supports a large TOC. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_LARGE_TOC
+#endif
+
+
+/* Define if your PowerPC64 linker only needs function descriptor syms. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_NO_DOT_SYMS
+#endif
+
+
+/* Define if your linker can relax absolute .eh_frame personality pointers
+ into PC-relative form. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PERSONALITY_RELAXATION
+#endif
+
+
+/* Define if the PE linker supports --disable-dynamicbase option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PE_DISABLE_DYNAMICBASE
+#endif
+
+
+/* Define if your linker supports PIE option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PIE
+#endif
+
+
+/* Define 0/1 if your linker supports -pie option with copy reloc. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PIE_COPYRELOC
+#endif
+
+
+/* Define if your PowerPC linker has .gnu.attributes long double support. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE
+#endif
+
+
+/* Define if your linker supports --push-state/--pop-state */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_PUSHPOPSTATE_SUPPORT
+#endif
+
+
+/* Define if your linker links a mix of read-only and read-write sections into
+ a read-write section. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_RO_RW_SECTION_MIXING
+#endif
+
+
+/* Define if your linker supports the *_sol2 emulations. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_SOL2_EMULATION
+#endif
+
+
+/* Define if your linker supports -Bstatic/-Bdynamic or equivalent options. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_STATIC_DYNAMIC
+#endif
+
+
+/* Define if your linker supports --sysroot. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LD_SYSROOT
+#endif
+
+
+/* Define to 1 if you have the <limits.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LIMITS_H
+#endif
+
+
+/* Define to 1 if you have the <locale.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LOCALE_H
+#endif
+
+
+/* Define to 1 if the system has the type `long long'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LONG_LONG
+#endif
+
+
+/* Define to 1 if the system has the type `long long int'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LONG_LONG_INT
+#endif
+
+
+/* Define to the level of your linker's plugin support. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_LTO_PLUGIN
+#endif
+
+
+/* Define to 1 if you have the `madvise' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MADVISE
+#endif
+
+
+/* Define to 1 if you have the `mallinfo' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MALLINFO
+#endif
+
+
+/* Define to 1 if you have the `mallinfo2' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MALLINFO2
+#endif
+
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MALLOC_H
+#endif
+
+
+/* Define to 1 if you have the `mbstowcs' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MBSTOWCS
+#endif
+
+
+/* Define if valgrind's memcheck.h header is installed. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MEMCHECK_H
+#endif
+
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MEMORY_H
+#endif
+
+
+/* Define to 1 if you have the `mmap' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MMAP
+#endif
+
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MMAP_ANON
+#endif
+
+
+/* Define if mmap of /dev/zero works. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MMAP_DEV_ZERO
+#endif
+
+
+/* Define if read-only mmap of a plain file works. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MMAP_FILE
+#endif
+
+
+/* Define if GCC has been configured with --enable-newlib-nano-formatted-io.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_NEWLIB_NANO_FORMATTED_IO
+#endif
+
+
+/* Define to 1 if you have the `nl_langinfo' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_NL_LANGINFO
+#endif
+
+
+/* Define to 1 if you have the `popen' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_POPEN
+#endif
+
+
+/* Define to 1 if you have the `posix_fallocate' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_POSIX_FALLOCATE
+#endif
+
+
+/* Define to 1 if you have the `putchar_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_PUTCHAR_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `putc_unlocked' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_PUTC_UNLOCKED
+#endif
+
+
+/* Define to 1 if you have the `setlocale' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SETLOCALE
+#endif
+
+
+/* Define to 1 if you have the `setrlimit' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SETRLIMIT
+#endif
+
+
+/* Define if <sys/signal.h> defines sighandler_t */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SIGHANDLER_T
+#endif
+
+
+/* Define if the system-provided CRTs are present on Solaris. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SOLARIS_CRTS
+#endif
+
+
+/* Define to 1 if you have the <stddef.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STDDEF_H
+#endif
+
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STDINT_H
+#endif
+
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STDLIB_H
+#endif
+
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STRINGS_H
+#endif
+
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STRING_H
+#endif
+
+
+/* Define to 1 if you have the `strsignal' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STRSIGNAL
+#endif
+
+
+/* Define if <sys/times.h> defines struct tms. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_STRUCT_TMS
+#endif
+
+
+/* Define if <utility> defines std::swap. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SWAP_IN_UTILITY
+#endif
+
+
+/* Define to 1 if you have the `sysconf' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYSCONF
+#endif
+
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_FILE_H
+#endif
+
+
+/* Define to 1 if you have the <sys/locking.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_LOCKING_H
+#endif
+
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_MMAN_H
+#endif
+
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_PARAM_H
+#endif
+
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_RESOURCE_H
+#endif
+
+
+/* Define if your target C library provides sys/sdt.h */
+#undef HAVE_SYS_SDT_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_STAT_H
+#endif
+
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_TIMES_H
+#endif
+
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_TIME_H
+#endif
+
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_TYPES_H
+#endif
+
+
+/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_SYS_WAIT_H
+#endif
+
+
+/* Define to 1 if you have the `times' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_TIMES
+#endif
+
+
+/* Define to 1 if you have the <time.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_TIME_H
+#endif
+
+
+/* Define to 1 if you have the <tr1/unordered_map> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_TR1_UNORDERED_MAP
+#endif
+
+
+/* Define to 1 if the system has the type `uintmax_t'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UINTMAX_T
+#endif
+
+
+/* Define to 1 if the system has the type `uintptr_t'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UINTPTR_T
+#endif
+
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UNISTD_H
+#endif
+
+
+/* Define to 1 if you have the <unordered_map> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UNORDERED_MAP
+#endif
+
+
+/* Define to 1 if the system has the type `unsigned long long int'. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_UNSIGNED_LONG_LONG_INT
+#endif
+
+
+/* Define if valgrind's valgrind/memcheck.h header is installed. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_VALGRIND_MEMCHECK_H
+#endif
+
+
+/* Define to 1 if you have the `vfork' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_VFORK
+#endif
+
+
+/* Define to 1 if you have the <vfork.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_VFORK_H
+#endif
+
+
+/* Define to 1 if you have the <wchar.h> header file. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_WCHAR_H
+#endif
+
+
+/* Define to 1 if you have the `wcswidth' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_WCSWIDTH
+#endif
+
+
+/* Define to 1 if `fork' works. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_WORKING_FORK
+#endif
+
+
+/* Define this macro if mbstowcs does not crash when its first argument is
+ NULL. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_WORKING_MBSTOWCS
+#endif
+
+
+/* Define to 1 if `vfork' works. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_WORKING_VFORK
+#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
+#endif
+
+
+/* Define if isl is in use. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_isl
+#endif
+
+
+/* Define if F_SETLKW supported by fcntl. */
+#ifndef USED_FOR_TARGET
+#undef HOST_HAS_F_SETLKW
+#endif
+
+
+/* Define if _LK_LOC supported by _locking. */
+#ifndef USED_FOR_TARGET
+#undef HOST_HAS_LK_LOCK
+#endif
+
+
+/* Define if O_CLOEXEC supported by fcntl. */
+#ifndef USED_FOR_TARGET
+#undef HOST_HAS_O_CLOEXEC
+#endif
+
+
+/* Define as const if the declaration of iconv() needs const. */
+#ifndef USED_FOR_TARGET
+#undef ICONV_CONST
+#endif
+
+
+/* Define if int64_t uses long as underlying type. */
+#ifndef USED_FOR_TARGET
+#undef INT64_T_IS_LONG
+#endif
+
+
+/* Define to 1 if ld64 supports '-export_dynamic'. */
+#ifndef USED_FOR_TARGET
+#undef LD64_HAS_EXPORT_DYNAMIC
+#endif
+
+
+/* Define to 1 if ld64 supports '-platform_version'. */
+#ifndef USED_FOR_TARGET
+#undef LD64_HAS_PLATFORM_VERSION
+#endif
+
+
+/* Define to ld64 version. */
+#ifndef USED_FOR_TARGET
+#undef LD64_VERSION
+#endif
+
+
+/* Define to the linker option to ignore unused dependencies. */
+#ifndef USED_FOR_TARGET
+#undef LD_AS_NEEDED_OPTION
+#endif
+
+
+/* Define to the linker option to enable compressed debug sections. */
+#ifndef USED_FOR_TARGET
+#undef LD_COMPRESS_DEBUG_OPTION
+#endif
+
+
+/* Define to the linker option to enable use of shared objects. */
+#ifndef USED_FOR_TARGET
+#undef LD_DYNAMIC_OPTION
+#endif
+
+
+/* Define to the linker option to keep unused dependencies. */
+#ifndef USED_FOR_TARGET
+#undef LD_NO_AS_NEEDED_OPTION
+#endif
+
+
+/* Define to the linker option to disable use of shared objects. */
+#ifndef USED_FOR_TARGET
+#undef LD_STATIC_OPTION
+#endif
+
+
+/* The linker hash style */
+#ifndef USED_FOR_TARGET
+#undef LINKER_HASH_STYLE
+#endif
+
+
+/* Define to the name of the LTO plugin DSO that must be passed to the
+ linker's -plugin=LIB option. */
+#ifndef USED_FOR_TARGET
+#undef LTOPLUGINSONAME
+#endif
+
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#ifndef USED_FOR_TARGET
+#undef LT_OBJDIR
+#endif
+
+
+/* Define if we should link mingw executables with --large-address-aware */
+#ifndef USED_FOR_TARGET
+#undef MINGW_DEFAULT_LARGE_ADDR_AWARE
+#endif
+
+
+/* Value to set mingw's _dowildcard to. */
+#ifndef USED_FOR_TARGET
+#undef MINGW_DOWILDCARD
+#endif
+
+
+/* Define if host mkdir takes a single argument. */
+#ifndef USED_FOR_TARGET
+#undef MKDIR_TAKES_ONE_ARG
+#endif
+
+
+/* Define to 1 to if -foffload is defaulted */
+#ifndef USED_FOR_TARGET
+#undef OFFLOAD_DEFAULTED
+#endif
+
+
+/* Define to offload targets, separated by commas. */
+#ifndef USED_FOR_TARGET
+#undef OFFLOAD_TARGETS
+#endif
+
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef USED_FOR_TARGET
+#undef PACKAGE_BUGREPORT
+#endif
+
+
+/* Define to the full name of this package. */
+#ifndef USED_FOR_TARGET
+#undef PACKAGE_NAME
+#endif
+
+
+/* Define to the full name and version of this package. */
+#ifndef USED_FOR_TARGET
+#undef PACKAGE_STRING
+#endif
+
+
+/* Define to the one symbol short name of this package. */
+#ifndef USED_FOR_TARGET
+#undef PACKAGE_TARNAME
+#endif
+
+
+/* Define to the home page for this package. */
+#ifndef USED_FOR_TARGET
+#undef PACKAGE_URL
+#endif
+
+
+/* Define to the version of this package. */
+#ifndef USED_FOR_TARGET
+#undef PACKAGE_VERSION
+#endif
+
+
+/* Specify plugin linker */
+#ifndef USED_FOR_TARGET
+#undef PLUGIN_LD_SUFFIX
+#endif
+
+
+/* Define to .TOC. alignment forced by your linker. */
+#ifndef USED_FOR_TARGET
+#undef POWERPC64_TOC_POINTER_ALIGNMENT
+#endif
+
+
+/* Define to PREFIX/include if cpp should also search that directory. */
+#ifndef USED_FOR_TARGET
+#undef PREFIX_INCLUDE_DIR
+#endif
+
+
+/* The size of `dev_t', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_DEV_T
+#endif
+
+
+/* The size of `ino_t', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_INO_T
+#endif
+
+
+/* The size of `int', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_INT
+#endif
+
+
+/* The size of `long', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_LONG
+#endif
+
+
+/* The size of `long long', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_LONG_LONG
+#endif
+
+
+/* The size of `short', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_SHORT
+#endif
+
+
+/* The size of `void *', as computed by sizeof. */
+#ifndef USED_FOR_TARGET
+#undef SIZEOF_VOID_P
+#endif
+
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef USED_FOR_TARGET
+#undef STDC_HEADERS
+#endif
+
+
+/* Define if you can safely include both <string.h> and <strings.h>. */
+#ifndef USED_FOR_TARGET
+#undef STRING_WITH_STRINGS
+#endif
+
+
+/* Define if TFmode long double should be the default */
+#ifndef USED_FOR_TARGET
+#undef TARGET_DEFAULT_LONG_DOUBLE_128
+#endif
+
+
+/* Define if your target C library provides the `dl_iterate_phdr' function. */
+#undef TARGET_DL_ITERATE_PHDR
+
+/* GNU C Library major version number used on the target, or 0. */
+#ifndef USED_FOR_TARGET
+#undef TARGET_GLIBC_MAJOR
+#endif
+
+
+/* GNU C Library minor version number used on the target, or 0. */
+#ifndef USED_FOR_TARGET
+#undef TARGET_GLIBC_MINOR
+#endif
+
+
+/* Define if your target C Library properly handles PT_GNU_STACK */
+#ifndef USED_FOR_TARGET
+#undef TARGET_LIBC_GNUSTACK
+#endif
+
+
+/* Define if your target C Library provides the AT_HWCAP value in the TCB */
+#ifndef USED_FOR_TARGET
+#undef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
+#endif
+
+
+/* Define if your target C library provides stack protector support */
+#ifndef USED_FOR_TARGET
+#undef TARGET_LIBC_PROVIDES_SSP
+#endif
+
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#ifndef USED_FOR_TARGET
+#undef TIME_WITH_SYS_TIME
+#endif
+
+
+/* Define to the flag used to mark TLS sections if the default (`T') doesn't
+ work. */
+#ifndef USED_FOR_TARGET
+#undef TLS_SECTION_ASM_FLAG
+#endif
+
+
+/* Define if your assembler mis-optimizes .eh_frame data. */
+#ifndef USED_FOR_TARGET
+#undef USE_AS_TRADITIONAL_FORMAT
+#endif
+
+
+/* Define if you want to generate code by default that assumes that the Cygwin
+ DLL exports wrappers to support libstdc++ function replacement. */
+#ifndef USED_FOR_TARGET
+#undef USE_CYGWIN_LIBSTDCXX_WRAPPERS
+#endif
+
+
+/* Define 0/1 if your linker supports hidden thunks in linkonce sections. */
+#ifndef USED_FOR_TARGET
+#undef USE_HIDDEN_LINKONCE
+#endif
+
+
+/* Define to 1 if the 'long long' type is wider than 'long' but still
+ efficiently supported by the host hardware. */
+#ifndef USED_FOR_TARGET
+#undef USE_LONG_LONG_FOR_WIDEST_FAST_INT
+#endif
+
+
+/* Define if we should use leading underscore on 64 bit mingw targets */
+#ifndef USED_FOR_TARGET
+#undef USE_MINGW64_LEADING_UNDERSCORES
+#endif
+
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Define to be the last component of the Windows registry key under which to
+ look for installation paths. The full key used will be
+ HKEY_LOCAL_MACHINE/SOFTWARE/Free Software Foundation/{WIN32_REGISTRY_KEY}.
+ The default is the GCC version number. */
+#ifndef USED_FOR_TARGET
+#undef WIN32_REGISTRY_KEY
+#endif
+
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#ifndef USED_FOR_TARGET
+#undef _FILE_OFFSET_BITS
+#endif
+
+
+/* Define for large files, on AIX-style hosts. */
+#ifndef USED_FOR_TARGET
+#undef _LARGE_FILES
+#endif
+
+
+/* Define to 1 if on MINIX. */
+#ifndef USED_FOR_TARGET
+#undef _MINIX
+#endif
+
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#ifndef USED_FOR_TARGET
+#undef _POSIX_1_SOURCE
+#endif
+
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#ifndef USED_FOR_TARGET
+#undef _POSIX_SOURCE
+#endif
+
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#ifndef USED_FOR_TARGET
+#undef _UINT32_T
+#endif
+
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#ifndef USED_FOR_TARGET
+#undef _UINT64_T
+#endif
+
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+ <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+#ifndef USED_FOR_TARGET
+#undef _UINT8_T
+#endif
+
+
+/* Define to `char *' if <sys/types.h> does not define. */
+#ifndef USED_FOR_TARGET
+#undef caddr_t
+#endif
+
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to the type of a signed integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef int16_t
+#endif
+
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef int32_t
+#endif
+
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef int64_t
+#endif
+
+
+/* Define to the type of a signed integer type of width exactly 8 bits if such
+ a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef int8_t
+#endif
+
+
+/* Define to the widest signed integer type if <stdint.h> and <inttypes.h> do
+ not define. */
+#ifndef USED_FOR_TARGET
+#undef intmax_t
+#endif
+
+
+/* Define to the type of a signed integer type wide enough to hold a pointer,
+ if such a type exists, and if the system does not define it. */
+#ifndef USED_FOR_TARGET
+#undef intptr_t
+#endif
+
+
+/* Define to `int' if <sys/types.h> does not define. */
+#ifndef USED_FOR_TARGET
+#undef pid_t
+#endif
+
+
+/* Define to `long' if <sys/resource.h> doesn't define. */
+#ifndef USED_FOR_TARGET
+#undef rlim_t
+#endif
+
+
+/* Define to `int' if <sys/types.h> does not define. */
+#ifndef USED_FOR_TARGET
+#undef ssize_t
+#endif
+
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef uint16_t
+#endif
+
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef uint32_t
+#endif
+
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef uint64_t
+#endif
+
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#ifndef USED_FOR_TARGET
+#undef uint8_t
+#endif
+
+
+/* Define to the widest unsigned integer type if <stdint.h> and <inttypes.h>
+ do not define. */
+#ifndef USED_FOR_TARGET
+#undef uintmax_t
+#endif
+
+
+/* Define to the type of an unsigned integer type wide enough to hold a
+ pointer, if such a type exists, and if the system does not define it. */
+#ifndef USED_FOR_TARGET
+#undef uintptr_t
+#endif
+
+
+/* Define as `fork' if `vfork' does not work. */
+#ifndef USED_FOR_TARGET
+#undef vfork
+#endif
+
diff --git a/support/cpp/gcc/config/darwin-protos.h b/support/cpp/gcc/config/darwin-protos.h
new file mode 100644
index 000000000..15f3ee7b0
--- /dev/null
+++ b/support/cpp/gcc/config/darwin-protos.h
@@ -0,0 +1,132 @@
+/* Prototypes.
+ Copyright (C) 2001-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 CONFIG_DARWIN_PROTOS_H
+#define CONFIG_DARWIN_PROTOS_H
+
+extern void darwin_init_sections (void);
+extern int name_needs_quotes (const char *);
+
+extern void machopic_validate_stub_or_non_lazy_ptr (const char *);
+
+extern void machopic_output_function_base_name (FILE *);
+extern const char *machopic_indirection_name (rtx, bool);
+extern const char *machopic_mcount_stub_name (void);
+extern bool machopic_should_output_picbase_label (void);
+extern const char *machopic_get_function_picbase (void);
+
+#ifdef RTX_CODE
+
+extern rtx machopic_gen_offset (rtx);
+extern int machopic_operand_p (rtx);
+extern int machopic_symbol_defined_p (rtx sym_ref);
+extern enum machopic_addr_class machopic_classify_symbol (rtx);
+
+extern rtx machopic_indirect_data_reference (rtx, rtx);
+extern rtx machopic_indirect_call_target (rtx);
+extern rtx machopic_legitimize_pic_address (rtx, machine_mode, rtx);
+
+extern void machopic_asm_out_constructor (rtx, int);
+extern void machopic_asm_out_destructor (rtx, int);
+extern section *machopic_select_rtx_section (machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+
+extern void machopic_define_symbol (rtx);
+extern void darwin_encode_section_info (tree, rtx, int);
+extern void darwin_set_default_type_attributes (tree);
+
+#endif /* TREE_CODE */
+
+extern int machopic_reloc_rw_mask (void);
+extern section *machopic_select_section (tree, int, unsigned HOST_WIDE_INT);
+
+extern section *darwin_function_section (tree, enum node_frequency, bool, bool);
+extern section *darwin_tm_clone_table_section (void);
+extern void darwin_function_switched_text_sections (FILE *, tree, bool);
+
+extern void darwin_unique_section (tree decl, int reloc);
+extern void darwin_asm_named_section (const char *, unsigned int, tree);
+extern void darwin_non_lazy_pcrel (FILE *, rtx);
+
+extern void darwin_emit_unwind_label (FILE *, tree, int, int);
+extern void darwin_emit_except_table_label (FILE *);
+extern rtx darwin_make_eh_symbol_indirect (rtx, bool);
+extern bool darwin_should_restore_cfa_state (void);
+
+extern void darwin_pragma_ignore (struct cpp_reader *);
+extern void darwin_pragma_options (struct cpp_reader *);
+extern void darwin_pragma_unused (struct cpp_reader *);
+extern void darwin_pragma_ms_struct (struct cpp_reader *);
+
+extern void darwin_file_start (void);
+extern void darwin_file_end (void);
+
+extern void darwin_asm_lto_start (void);
+extern void darwin_asm_lto_end (void);
+
+extern void darwin_mark_decl_preserved (const char *);
+
+extern tree darwin_handle_kext_attribute (tree *, tree, tree, int, bool *);
+extern tree darwin_handle_weak_import_attribute (tree *node, tree name,
+ tree args, int flags,
+ bool * no_add_attrs);
+extern void machopic_output_stub (FILE *, const char *, const char *);
+extern void darwin_globalize_label (FILE *, const char *);
+extern void darwin_assemble_visibility (tree, int);
+
+extern void darwin_asm_output_dwarf_delta (FILE *, int, const char *,
+ const char *, HOST_WIDE_INT);
+extern void darwin_asm_output_dwarf_offset (FILE *, int, const char *,
+ HOST_WIDE_INT, section *);
+
+extern void darwin_asm_declare_object_name (FILE *, const char *, tree);
+extern void darwin_asm_declare_constant_name (FILE *, const char *,
+ const_tree, HOST_WIDE_INT);
+
+extern void darwin_output_aligned_bss (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT, unsigned int);
+
+extern void darwin_asm_output_aligned_decl_local (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT,
+ unsigned int);
+extern void darwin_asm_output_aligned_decl_common (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT,
+ unsigned int);
+
+extern bool darwin_binds_local_p (const_tree);
+extern void darwin_cpp_builtins (struct cpp_reader *);
+
+extern tree darwin_init_cfstring_builtins (unsigned);
+extern tree darwin_fold_builtin (tree, int, tree *, bool);
+extern bool darwin_cfstring_p (tree);
+extern tree darwin_build_constant_cfstring (tree);
+extern void darwin_enter_string_into_cfstring_table (tree);
+
+extern void darwin_asm_output_anchor (rtx symbol);
+extern bool darwin_use_anchors_for_symbol_p (const_rtx symbol);
+extern bool darwin_kextabi_p (void);
+extern void darwin_override_options (void);
+extern void darwin_patch_builtins (void);
+extern void darwin_rename_builtins (void);
+extern bool darwin_libc_has_function (enum function_class fn_class, tree);
+
+#endif /* CONFIG_DARWIN_PROTOS_H */
diff --git a/support/cpp/gcc/config/darwin.h b/support/cpp/gcc/config/darwin.h
new file mode 100644
index 000000000..3682bd2b2
--- /dev/null
+++ b/support/cpp/gcc/config/darwin.h
@@ -0,0 +1,1244 @@
+/* Target definitions for Darwin (Mac OS X) systems.
+ Copyright (C) 1989-2022 Free Software Foundation, Inc.
+ Contributed by Apple Computer 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/>. */
+
+#ifndef CONFIG_DARWIN_H
+#define CONFIG_DARWIN_H
+
+/* The definitions in this file are common to all processor types
+ running Darwin, which is the kernel for Mac OS X. Darwin is
+ basically a BSD user layer laid over a Mach kernel, then evolved
+ for many years (at NeXT) in parallel with other Unix systems. So
+ while the runtime is a somewhat idiosyncratic Mach-based thing,
+ other definitions look like they would for a BSD variant. */
+
+/* Although NeXT ran on many different architectures, as of Jan 2001
+ the only supported Darwin targets are PowerPC and x86. */
+
+/* One of Darwin's NeXT legacies is the Mach-O format, which is partly
+ like a.out and partly like COFF, with additional features like
+ multi-architecture binary support. */
+
+#define DARWIN_X86 0
+#define DARWIN_PPC 0
+
+#define OBJECT_FORMAT_MACHO 1
+
+/* Suppress g++ attempt to link in the math library automatically. */
+#define MATH_LIBRARY ""
+
+/* We have atexit. */
+
+#define HAVE_ATEXIT
+
+/* Define an empty body for the function do_global_dtors() in libgcc2.c. */
+
+#define DO_GLOBAL_DTORS_BODY
+
+/* Register static destructors to run from __cxa_atexit instead of putting
+ them into a .mod_term_funcs section. */
+
+#define TARGET_DTORS_FROM_CXA_ATEXIT true
+
+/* The string value for __SIZE_TYPE__. */
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
+
+/* Type used for ptrdiff_t, as a string used in a declaration. */
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+/* wchar_t is int. */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE "long long int"
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE "long long unsigned int"
+
+#define INT_LEAST8_TYPE "signed char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE "long long int"
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE "long long unsigned int"
+
+#define INT_FAST8_TYPE "signed char"
+#define INT_FAST16_TYPE "short int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE "long long int"
+#define UINT_FAST8_TYPE "unsigned char"
+#define UINT_FAST16_TYPE "short unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE "long long unsigned int"
+
+#define INTPTR_TYPE "long int"
+#define UINTPTR_TYPE "long unsigned int"
+
+#define SIG_ATOMIC_TYPE "int"
+
+/* Default to using the NeXT-style runtime, since that's what is
+ pre-installed on Darwin systems. */
+
+#define NEXT_OBJC_RUNTIME 100508
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+
+#undef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* True if pragma ms_struct is in effect. */
+extern GTY(()) int darwin_ms_struct;
+
+/* Darwin has a user convenience feature where some linker options are exposed
+ at the driver level (so one can type "-all_load" instead of "-Wl,-all_load"
+ or "-Xlinker -all_load"). We retain this, but now these options are all
+ marked as 'Driver' and we process them as early as possible so that they
+ get allocated to the right toolchain command. There are a couple of special
+ cases where these driver opts are used multiple times, or to control
+ operations on more than one command (e.g. dynamiclib). These are handled
+ specially and we then add %<xxxx specs for the commands that _don't_ need
+ them. NOTE: the order of 'shared' and 'dynamiclib' is significant, hence
+ they are placed out of alphabetical order at the start. Likewise, we keep
+ a couple of cases where a negative option originally appeared after the
+ positive alternate, potentially overriding it.
+ When we report an error with %e, it seems necessary to strip the option
+ before doing so, otherwise it survives to the cc1 command line (%e doesn't
+ appear to abort the program before this).
+ Right now there's no mechanism to split up the "variable portion" (%*) of
+ the matched spec string, so where we have some driver specs that take 2
+ or 3 arguments, these cannot be processed here, but are deferred until the
+ LINK_SPEC, where they are copied verbatim.
+ We have a "safe" version of the MacOS version string, that's been sanity-
+ checked and truncated to minor version. If the 'tiny' (3rd) portion of the
+ value is not significant, it's better to use this in version-compare(). */
+
+#undef SUBTARGET_DRIVER_SELF_SPECS
+#define SUBTARGET_DRIVER_SELF_SPECS \
+ "%{shared:%{!dynamiclib:-dynamiclib}} %<shared", \
+ "%{static:%{dynamic|dynamiclib:%econflicting code generation switches}}",\
+ "%{dynamiclib:-Xlinker -dylib \
+ %{allowable_client*:-Xlinker -allowable_client -Xlinker %*} \
+ %<allowable_client* \
+ %{bundle_loader*: %<bundle_loader* \
+ %e-bundle_loader not allowed with -dynamiclib} \
+ %{client_name*: %<client_name* \
+ %e-client_name not allowed with -dynamiclib} \
+ %{compatibility_version*:\
+ -Xlinker -dylib_compatibility_version -Xlinker %*} \
+ %<compatibility_version* \
+ %{current_version*:-Xlinker -dylib_current_version -Xlinker %*} \
+ %<current_version* \
+ %{install_name*:-Xlinker -dylib_install_name -Xlinker %* } \
+ %<install_name* \
+ %{keep_private_externs: %<keep_private_externs \
+ %e-keep_private_externs not allowed with -dynamiclib} \
+ %{private_bundle: %<private_bundle \
+ %e-private_bundle not allowed with -dynamiclib} \
+ }", \
+ "%{!dynamiclib: \
+ %{bundle_loader*:-Xlinker -bundle_loader -Xlinker %*} \
+ %<bundle_loader* \
+ %{client_name*:-Xlinker -client_name -Xlinker %*} \
+ %<client_name* \
+ %{compatibility_version*: %<compatibility_version* \
+ %e-compatibility_version only allowed with -dynamiclib} \
+ %{current_version*: %<current_version* \
+ %e-current_version only allowed with -dynamiclib} \
+ %{install_name*: %<install_name* \
+ %e-install_name only allowed with -dynamiclib} \
+ %{keep_private_externs:-Xlinker -keep_private_externs} \
+ %<keep_private_externs \
+ %{private_bundle:-Xlinker -private_bundle} \
+ %<private_bundle \
+ }", \
+ "%{all_load:-Xlinker -all_load} %<all_load", \
+ "%{arch_errors_fatal:-Xlinker -arch_errors_fatal} \
+ %<arch_errors_fatal", \
+ "%{bind_at_load:-Xlinker -bind_at_load} %<bind_at_load", \
+ "%{bundle:%{!dynamiclib:-Xlinker -bundle; \
+ :%e-bundle not allowed with -dynamiclib}}", \
+ "%{dead_strip:-Xlinker -dead_strip} %<dead_strip", \
+ "%{dylib_file*:-Xlinker -dylib_file -Xlinker %*} %<dylib_file*", \
+ "%{dylinker:-Xlinker -dylinker} %<dylinker", \
+ "%{dylinker_install_name*:-Xlinker -dylinker_install_name -Xlinker %*}\
+ %<dylinker_install_name*", \
+ "%{exported_symbols_list*:-Xlinker -exported_symbols_list -Xlinker %*}\
+ %<exported_symbols_list", \
+ "%{findirect-virtual-calls: -fapple-kext} %<findirect-virtual-calls", \
+ "%{fterminated-vtables: -fapple-kext} %<fterminated-vtables", \
+ "%{fapple-kext|mkernel:-static}", \
+ "%{filelist*:-Xlinker -filelist -Xlinker %*} %<filelist*", \
+ "%{flat_namespace:-Xlinker -flat_namespace} %<flat_namespace", \
+ "%{force_cpusubtype_ALL:-Xassembler -force_cpusubtype_ALL} ", \
+ "%{force_flat_namespace: \
+ %{!dynamiclib:-Xlinker -force_flat_namespace; \
+ :%e-force_flat_namespace not allowed with -dynamiclib}} \
+ %<force_flat_namespace", \
+ "%{framework*:-Xlinker -framework -Xlinker %*} %<framework*", \
+ "%{gfull:-g -fno-eliminate-unused-debug-symbols} %<gfull", \
+ "%{gused:-g -feliminate-unused-debug-symbols} %<gused", \
+ "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \
+ %<gsplit-dwarf", \
+ "%{headerpad_max_install_names:-Xlinker -headerpad_max_install_names}\
+ %<headerpad_max_install_names", \
+ "%{image_base*:-Xlinker -image_base -Xlinker %*} %<image_base*", \
+ "%{init*:-Xlinker -init -Xlinker %*} %<init*", \
+ "%{multi_module:-Xlinker -multi_module} %<multi_module", \
+ "%{multiply_defined*:-Xlinker -multiply_defined -Xlinker %*; \
+ :%{shared-libgcc: \
+ %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \
+ %:version-compare(< 10.5 asm_macosx_version_min= -multiply_defined) \
+ %:version-compare(< 10.5 asm_macosx_version_min= -Xlinker) \
+ %:version-compare(< 10.5 asm_macosx_version_min= suppress)}} \
+ %<multiply_defined*", \
+ "%{multiplydefinedunused*:\
+ -Xlinker -multiply_defined_unused -Xlinker %*} \
+ %<multiplydefinedunused* ", \
+ "%{no_dead_strip_inits_and_terms:\
+ -Xlinker -no_dead_strip_inits_and_terms} \
+ %<no_dead_strip_inits_and_terms", \
+ "%{nofixprebinding:-Xlinker -nofixprebinding} %<nofixprebinding", \
+ "%{nomultidefs:-Xlinker -nomultidefs} %<nomultidefs", \
+ "%{pagezero_size*:-Xlinker -pagezero_size -Xlinker %*} \
+ %<pagezero_size", \
+ "%{prebind:-Xlinker -prebind} %<prebind", \
+ "%{noprebind:-Xlinker -noprebind} %<noprebind", \
+ "%{prebind_all_twolevel_modules:\
+ -Xlinker -prebind_all_twolevel_modules} \
+ %<prebind_all_twolevel_modules", \
+ "%{preload:-Xlinker -preload} %<preload", \
+ "%{read_only_relocs*:-Xlinker -read_only_relocs -Xlinker %*} \
+ %<read_only_relocs*", \
+ "%{rpath*: -Xlinker -rpath -Xlinker %*}", \
+ "%{seg_addr_table_filename*: \
+ -Xlinker -seg_addr_table_filename -Xlinker %*} \
+ %<seg_addr_table_filename*", \
+ "%{seg_addr_table*:-Xlinker -seg_addr_table -Xlinker %*} \
+ %<seg_addr_table*", \
+ "%{seg1addr*:-Xlinker -image_base -Xlinker %*} %<seg1addr*", \
+ "%{seglinkedit:-Xlinker -seglinkedit} %<seglinkedit", \
+ "%{noseglinkedit:-Xlinker -noseglinkedit} %<noseglinkedit", \
+ "%{segs_read_only_addr*:-Xlinker -segs_read_only_addr -Xlinker %*} \
+ %<segs_read_only_addr*", \
+ "%{segs_read_write_addr*:-Xlinker -segs_read_write_addr -Xlinker %*} \
+ %<segs_read_write_addr*", \
+ "%{single_module:-Xlinker -single_module} %<single_module", \
+ "%{sub_library*:-Xlinker -sub_library -Xlinker %*} %<sub_library*", \
+ "%{sub_umbrella*:-Xlinker -sub_umbrella -Xlinker %*} %<sub_umbrella*",\
+ "%{twolevel_namespace:-Xlinker -twolevel_namespace} \
+ %<twolevel_namespace", \
+ "%{twolevel_namespace_hints:-Xlinker -twolevel_namespace_hints} \
+ %<twolevel_namespace_hints", \
+ "%{umbrella*:-Xlinker -umbrella -Xlinker %*} %<umbrella*", \
+ "%{undefined*:-Xlinker -undefined -Xlinker %*} %<undefined*", \
+ "%{unexported_symbols_list*:\
+ -Xlinker -unexported_symbols_list -Xlinker %*} \
+ %<unexported_symbols_list*", \
+ "%{weak_reference_mismatches*:\
+ -Xlinker -weak_reference_mismatches -Xlinker %*} \
+ %<weak_reference_mismatches*", \
+ "%{whyload:-Xlinker -whyload} %<whyload", \
+ "%{whatsloaded:-Xlinker -whatsloaded} %<whatsloaded", \
+ "%{w:-Xlinker -w}", \
+ "%<y*", \
+ "%<Mach "
+
+#if LD64_HAS_EXPORT_DYNAMIC
+#define DARWIN_RDYNAMIC "%{rdynamic:-export_dynamic}"
+#else
+#define DARWIN_RDYNAMIC "%{rdynamic:%nrdynamic is not supported}"
+#endif
+
+/* Code built with mdynamic-no-pic does not support PIE/PIC, so we disallow
+ these combinations; we also ensure that the no_pie option is passed to
+ ld64 on system versions that default to PIE when mdynamic-no-pic is given.
+ FIXME: we should check that the linker supports the -pie and -no_pie.
+ options. */
+#define DARWIN_PIE_SPEC \
+"%{pie|fpie|fPIE:\
+ %{mdynamic-no-pic: \
+ %n'-mdynamic-no-pic' overrides '-pie', '-fpie' or '-fPIE'; \
+ :%:version-compare(>= 10.5 mmacosx-version-min= -pie) }; \
+ mdynamic-no-pic:%:version-compare(>= 10.7 mmacosx-version-min= -no_pie) } "
+
+#define DARWIN_NOPIE_SPEC \
+"%{no-pie|fno-pie|fno-PIE: \
+ %:version-compare(>= 10.7 mmacosx-version-min= -no_pie) }"
+
+#define DARWIN_CC1_SPEC \
+ "%<dynamic %<dynamiclib %<force_cpusubtype_ALL "
+
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ darwin_override_options (); \
+ } while (0)
+
+#define SUBTARGET_C_COMMON_OVERRIDE_OPTIONS do { \
+ if (flag_mkernel || flag_apple_kext) \
+ { \
+ if (flag_use_cxa_atexit == 2) \
+ flag_use_cxa_atexit = 0; \
+ /* kexts should always be built without the coalesced sections \
+ because the kernel loader doesn't grok such sections. */ \
+ flag_weak = 0; \
+ /* No RTTI in kexts. */ \
+ flag_rtti = 0; \
+ } \
+ } while (0)
+
+/* Machine dependent cpp options. Don't add more options here, add
+ them to darwin_cpp_builtins in darwin-c.cc. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}" \
+ " %{pthread:-D_REENTRANT} "
+
+/* This is a fix for PR41260 by passing -no_compact_unwind on darwin10 and
+ later until the assembler, linker and libunwind are able to deal with the
+ output from GCC.
+
+ FIXME: we should check that the linker supports the option.
+*/
+
+#define DARWIN_NOCOMPACT_UNWIND \
+" %:version-compare(>= 10.6 mmacosx-version-min= -no_compact_unwind) "
+
+/* In Darwin linker specs we can put -lcrt0.o and ld will search the library
+ path for crt0.o or -lcrtx.a and it will search for libcrtx.a. As for
+ other ports, we can also put xxx.{o,a}%s and get the appropriate complete
+ startfile absolute directory. This latter point is important when we want
+ to override ld's rule of .dylib being found ahead of .a and the user wants
+ the convenience library to be linked. */
+
+/* The LINK_COMMAND spec is mostly a clone of the standard LINK_COMMAND_SPEC,
+ plus precomp, libtool, and fat build additions.
+
+ In general, random Darwin linker flags should go into LINK_SPEC
+ instead of LINK_COMMAND_SPEC. The command spec is better for
+ specifying the handling of options understood by generic Unix
+ linkers, and for positional arguments like libraries. */
+
+#define LINK_COMMAND_SPEC_A \
+ "%{!c:%{!E:%{!S:%{!M:%{!MM:%{!fsyntax-only:%{!fdump=*: \
+ %(linker)" \
+ LINK_PLUGIN_SPEC \
+ "%{flto*:%<fcompare-debug*} \
+ %{flto} %{fno-lto} %{flto=*} \
+ %l " LINK_COMPRESS_DEBUG_SPEC \
+ "%X %{s} %{t} %{Z} %{u*} \
+ %{e*} %{r} \
+ %{o*}%{!o:-o a.out} \
+ %{!r:%{!nostdlib:%{!nostartfiles:%S}}} \
+ %{L*} %(link_libgcc) %o \
+ %{!r:%{!nostdlib:%{!nodefaultlibs:\
+ %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} \
+ %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1): \
+ %{static|static-libgcc|static-libstdc++|static-libgfortran: \
+ libgomp.a%s; : -lgomp }} \
+ %{fgnu-tm: \
+ %{static|static-libgcc|static-libstdc++|static-libgfortran: \
+ libitm.a%s; : -litm }} \
+ %{%:sanitize(address): -lasan } \
+ %{%:sanitize(undefined): -lubsan } \
+ %(link_ssp) \
+ %:version-compare(>< 10.6 10.7 mmacosx-version-min= -ld10-uwfef) \
+ %(link_gcc_c_sequence) \
+ %{!nodefaultexport:%{dylib|dynamiclib|bundle: \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -U) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_get_address) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -exported_symbol) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_get_address) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -U) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_register_common) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -exported_symbol) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_register_common) \
+ }} \
+ }}}\
+ %{!r:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} %{F*} "\
+ DARWIN_PIE_SPEC \
+ DARWIN_NOPIE_SPEC \
+ DARWIN_RDYNAMIC \
+ DARWIN_NOCOMPACT_UNWIND \
+ "}}}}}}} %<pie %<no-pie %<rdynamic %<X %<rpath "
+
+/* Spec that controls whether the debug linker is run automatically for
+ a link step. This needs to be done if there is a source file on the
+ command line which will result in a temporary object (and debug is
+ enabled). */
+
+#define DSYMUTIL_SPEC \
+ "%{!c:%{!E:%{!S:%{!r:%{!M:%{!MM:%{!fsyntax-only:%{!fdump=*:\
+ %{g*:%{!gctf:%{!gbtf:%{!gstabs*:%{%: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
+
+/* Tell collect2 to run dsymutil for us as necessary. */
+#define COLLECT_RUN_DSYMUTIL 1
+
+/* We only want one instance of %G, since libSystem (Darwin's -lc) does not
+ depend on libgcc. */
+#undef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC \
+ "%G %{!nolibc:%L} "
+
+/* ld64 supports a sysroot, it just has a different name and there's no easy
+ way to check for it at config time. */
+#undef HAVE_LD_SYSROOT
+#define HAVE_LD_SYSROOT 1
+/* It seems the only (working) way to get a space after %R is to append a
+ dangling '/'. */
+#define SYSROOT_SPEC "%{!isysroot*:-syslibroot %R/ } "
+
+/* Do the same as clang, for now, and insert the sysroot for ld when an
+ isysroot is specified. */
+#define LINK_SYSROOT_SPEC "%{isysroot*:-syslibroot %*} "
+
+/* Suppress the addition of extra prefix paths when a sysroot is in use. */
+#define STANDARD_STARTFILE_PREFIX_1 ""
+#define STANDARD_STARTFILE_PREFIX_2 ""
+
+
+/* Please keep the random linker options in alphabetical order.
+ Note that options taking arguments may appear multiple times on a command
+ line with different arguments each time, so put a * after their names so
+ all of them get passed. */
+#define LINK_SPEC \
+ "%{static}%{!static:%{!dynamic:-dynamic}} \
+ %:remove-outfile(-ldl) \
+ %:remove-outfile(-lm) \
+ %:remove-outfile(-lpthread) \
+ %{fgnu-runtime: %{static|static-libgcc: \
+ %:replace-outfile(-lobjc libobjc-gnu.a%s); \
+ :%:replace-outfile(-lobjc -lobjc-gnu )}}\
+ %{static|static-libgcc|static-libgfortran:%:replace-outfile(-lgfortran libgfortran.a%s)}\
+ %{static|static-libgcc|static-libphobos:%:replace-outfile(-lgphobos libgphobos.a%s)}\
+ %{static|static-libgcc|static-libstdc++|static-libgfortran:%:replace-outfile(-lgomp libgomp.a%s)}\
+ %{static|static-libgcc|static-libstdc++:%:replace-outfile(-lstdc++ libstdc++.a%s)}\
+ %{force_cpusubtype_ALL:-arch %(darwin_arch)} \
+ %{!force_cpusubtype_ALL:-arch %(darwin_subarch)} "\
+ LINK_SYSROOT_SPEC \
+ "%{mmacosx-version-min=*:-macosx_version_min %*} \
+ %{sectalign*} %{sectcreate*} %{sectobjectsymbols*} %{sectorder*} \
+ %{segaddr*} %{segcreate*} %{segprot*} "
+
+/* Machine dependent libraries. */
+
+#define LIB_SPEC "%{!static:-lSystem}"
+
+/*
+ Note that by default, -lgcc_eh is not linked against.
+ This is because,in general, we need to unwind through system libraries that
+ are linked with the shared unwinder in libunwind (or libgcc_s for 10.4/5).
+
+ For -static-libgcc: < 10.6, use the unwinder in libgcc_eh (and find
+ the emultls impl. there too).
+
+ For -static-libgcc: >= 10.6, the unwinder *still* comes from libSystem and
+ we find the emutls impl from lemutls_w. In either case, the builtins etc.
+ are linked from -lgcc.
+
+ When we have specified shared-libgcc or any case that might require
+ exceptions, we pull the libgcc content (including emulated tls) from
+ -lgcc_s.1 in GCC and the unwinder from /usr/lib/libgcc_s.1 for < 10.6 and
+ libSystem for >= 10.6 respectively.
+ Otherwise, we just link the emutls/builtins from convenience libs.
+
+ If we need exceptions, prior to 10.3.9, then we have to link the static
+ eh lib, since there's no shared version on the system.
+
+ In all cases, libgcc_s.1 will be installed with the compiler, or any app
+ built using it, so we can link the builtins and emutls shared on all.
+
+ We have to work around that DYLD_XXXX are disabled in macOS 10.11+ which
+ means that any bootstrap trying to use a shared libgcc with a bumped SO-
+ name will fail. This means that we do not accept shared libgcc for these
+ versions.
+
+ For -static-libgcc: >= 10.6, the unwinder *still* comes from libSystem and
+ we find the emutls impl from lemutls_w. In either case, the builtins etc.
+ are linked from -lgcc.
+>
+ Otherwise, we just link the shared version of gcc_s.1.1 and pick up
+ exceptions:
+ * Prior to 10.3.9, then we have to link the static eh lib, since there
+ is no shared version on the system.
+ * from 10.3.9 to 10.5, from /usr/lib/libgcc_s.1.dylib
+ * from 10.6 onwards, from libSystem.dylib
+
+ In all cases, libgcc_s.1.1 will be installed with the compiler, or any app
+ built using it, so we can link the builtins and emutls shared on all.
+*/
+#undef REAL_LIBGCC_SPEC
+#define REAL_LIBGCC_SPEC \
+"%{static-libgcc|static: \
+ %:version-compare(!> 10.6 mmacosx-version-min= -lgcc_eh) \
+ %:version-compare(>= 10.6 mmacosx-version-min= -lemutls_w); \
+ shared-libgcc|fexceptions|fobjc-exceptions|fgnu-runtime: \
+ %:version-compare(!> 10.11 mmacosx-version-min= -lgcc_s.1.1) \
+ %:version-compare(>= 10.11 mmacosx-version-min= -lemutls_w) \
+ %:version-compare(!> 10.3.9 mmacosx-version-min= -lgcc_eh) \
+ %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5); \
+ : -lemutls_w \
+ } -lgcc "
+
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+"%{dynamiclib: %(darwin_dylib1) %{fgnu-tm: -lcrttms.o}} \
+ %{!dynamiclib:%{bundle:%(darwin_bundle1)} \
+ %{!bundle:%{pg:%{static:-lgcrt0.o} \
+ %{!static:%{object:-lgcrt0.o} \
+ %{!object:%{preload:-lgcrt0.o} \
+ %{!preload:-lgcrt1.o \
+ %:version-compare(>= 10.8 mmacosx-version-min= -no_new_main) \
+ %(darwin_crt2)}}}} \
+ %{!pg:%{static:-lcrt0.o} \
+ %{!static:%{object:-lcrt0.o} \
+ %{!object:%{preload:-lcrt0.o} \
+ %{!preload: %(darwin_crt1) \
+ %(darwin_crt2)}}}}}} \
+ %(darwin_crt3) %<dynamiclib "
+
+/* We want a destructor last in the list. */
+#define TM_DESTRUCTOR "%{fgnu-tm: -lcrttme.o}"
+#define ENDFILE_SPEC TM_DESTRUCTOR
+
+#define DARWIN_EXTRA_SPECS \
+ { "darwin_crt1", DARWIN_CRT1_SPEC }, \
+ { "darwin_crt2", DARWIN_CRT2_SPEC }, \
+ { "darwin_crt3", DARWIN_CRT3_SPEC }, \
+ { "darwin_dylib1", DARWIN_DYLIB1_SPEC }, \
+ { "darwin_bundle1", DARWIN_BUNDLE1_SPEC },
+
+#define DARWIN_CRT1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -lcrt1.o) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lcrt1.10.5.o) \
+ %:version-compare(>< 10.6 10.8 mmacosx-version-min= -lcrt1.10.6.o) \
+ %{fgnu-tm: -lcrttms.o}"
+
+#define DARWIN_CRT2_SPEC ""
+
+/* crt3.o provides __cxa_atexit on systems that don't have it (and a fix
+ up for faulty versions on 10.4). Since it's only used with C++, which
+ requires passing -shared-libgcc, key off that to avoid unnecessarily
+ adding a destructor to every program built for 10.4 or earlier. */
+
+#define DARWIN_CRT3_SPEC \
+"%{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"
+
+#define DARWIN_DYLIB1_SPEC \
+ "%:version-compare(!> 10.5 mmacosx-version-min= -ldylib1.o) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -ldylib1.10.5.o)"
+
+#define DARWIN_BUNDLE1_SPEC \
+"%{!static:%:version-compare(< 10.6 mmacosx-version-min= -lbundle1.o) \
+ %{fgnu-tm: -lcrttms.o}}"
+
+#ifdef HAVE_AS_MMACOSX_VERSION_MIN_OPTION
+/* Emit macosx version (but only major). */
+#define ASM_MMACOSX_VERSION_MIN_SPEC \
+"%{asm_macosx_version_min=*: -mmacosx-version-min=%* } \
+ %<asm_macosx_version_min=* "
+#else
+#define ASM_MMACOSX_VERSION_MIN_SPEC " %<asm_macosx_version_min=* "
+#endif
+
+#if HAVE_GNU_AS
+/* The options are added in gcc.cc for this case. */
+#define ASM_OPTIONS ""
+#else
+/* When we detect that we're cctools or llvm as, we need to insert the right
+ additional options. Actually, currently these are the same as GAS. */
+#define ASM_OPTIONS "%{v} %{w:-W} %{I*}"
+#endif
+
+/* Default Darwin ASM_SPEC, very simple. */
+#define ASM_SPEC \
+"%{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 ""
+
+#define ASM_FINAL_SPEC \
+ "%{gsplit-dwarf:%ngsplit-dwarf is not supported on this platform} \
+ %<gsplit-dwarf"
+
+/* We now require C++11 to bootstrap and newer tools than those based on
+ stabs, so require DWARF-2, even if stabs is supported by the assembler. */
+
+#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"
+#define DEBUG_ARANGES_SECTION "__DWARF,__debug_aranges,regular,debug"
+#define DEBUG_MACINFO_SECTION "__DWARF,__debug_macinfo,regular,debug"
+#define DEBUG_LINE_SECTION "__DWARF,__debug_line,regular,debug"
+#define DEBUG_LOC_SECTION "__DWARF,__debug_loc,regular,debug"
+#define DEBUG_LOCLISTS_SECTION "__DWARF,__debug_loclists,regular,debug"
+
+#define DEBUG_STR_SECTION "__DWARF,__debug_str,regular,debug"
+#define DEBUG_STR_OFFSETS_SECTION "__DWARF,__debug_str_offs,regular,debug"
+#define DEBUG_RANGES_SECTION "__DWARF,__debug_ranges,regular,debug"
+#define DEBUG_RNGLISTS_SECTION "__DWARF,__debug_rnglists,regular,debug"
+#define DEBUG_MACRO_SECTION "__DWARF,__debug_macro,regular,debug"
+
+#define DEBUG_LTO_INFO_SECTION "__GNU_DWARF_LTO,__debug_info,regular,debug"
+#define DEBUG_LTO_ABBREV_SECTION "__GNU_DWARF_LTO,__debug_abbrev,regular,debug"
+#define DEBUG_LTO_MACINFO_SECTION "__GNU_DWARF_LTO,__debug_macinfo,regular,debug"
+#define DEBUG_LTO_LINE_SECTION "__GNU_DWARF_LTO,__debug_line,regular,debug"
+#define DEBUG_LTO_STR_SECTION "__GNU_DWARF_LTO,__debug_str,regular,debug"
+#define DEBUG_LTO_MACRO_SECTION "__GNU_DWARF_LTO,__debug_macro,regular,debug"
+
+#define TARGET_WANT_DEBUG_PUB_SECTIONS true
+#define DEBUG_PUBNAMES_SECTION ((debug_generate_pub_sections == 2) \
+ ? "__DWARF,__debug_gnu_pubn,regular,debug" \
+ : "__DWARF,__debug_pubnames,regular,debug")
+
+#define DEBUG_PUBTYPES_SECTION ((debug_generate_pub_sections == 2) \
+ ? "__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)
+
+/* Mach-O supports 'weak imports', and 'weak definitions' in coalesced
+ sections. machopic_select_section ensures that weak variables go in
+ coalesced sections. Weak aliases (or any other kind of aliases) are
+ not supported. Weak symbols that aren't visible outside the .s file
+ are not supported. */
+#define ASM_WEAKEN_DECL(FILE, DECL, NAME, ALIAS) \
+ do { \
+ if (ALIAS) \
+ { \
+ warning (0, "alias definitions not supported in Mach-O; ignored"); \
+ break; \
+ } \
+ \
+ if (! DECL_EXTERNAL (DECL) && TREE_PUBLIC (DECL)) \
+ targetm.asm_out.globalize_label (FILE, NAME); \
+ if (DECL_EXTERNAL (DECL)) \
+ fputs ("\t.weak_reference ", FILE); \
+ else if (lookup_attribute ("weak_import", DECL_ATTRIBUTES (DECL))) \
+ break; \
+ else if (TREE_PUBLIC (DECL)) \
+ fputs ("\t.weak_definition ", FILE); \
+ else \
+ break; \
+ assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); \
+ } while (0)
+
+/* Darwin has the pthread routines in libSystem, which every program
+ links to, so there's no need for weak-ness for that. */
+#define GTHREAD_USE_WEAK 0
+
+/* On Darwin, we don't (at the time of writing) have linkonce sections
+ with names, so it's safe to make the class data not comdat. */
+#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT hook_bool_void_false
+
+/* For efficiency, on Darwin the RTTI information that is always
+ emitted in the standard C++ library should not be COMDAT. */
+#define TARGET_CXX_LIBRARY_RTTI_COMDAT hook_bool_void_false
+
+/* We make exception information linkonce. */
+#undef TARGET_USES_WEAK_UNWIND_INFO
+#define TARGET_USES_WEAK_UNWIND_INFO 1
+
+/* We need to use a nonlocal label for the start of an EH frame: the
+ Darwin linker requires that a coalesced section start with a label.
+ Unfortunately, it also requires that 'debug' sections don't contain
+ labels. */
+#undef FRAME_BEGIN_LABEL
+#define FRAME_BEGIN_LABEL (for_eh ? "EH_frame" : "Lframe")
+
+/* Emit a label for the FDE corresponding to DECL. EMPTY means
+ emit a label for an empty FDE. */
+#define TARGET_ASM_EMIT_UNWIND_LABEL darwin_emit_unwind_label
+
+/* Emit a label to separate the exception table. */
+#define TARGET_ASM_EMIT_EXCEPT_TABLE_LABEL darwin_emit_except_table_label
+
+/* Make an EH (personality or LDSA) symbol indirect as needed. */
+#define TARGET_ASM_MAKE_EH_SYMBOL_INDIRECT darwin_make_eh_symbol_indirect
+
+/* Some of Darwin's unwinders need current frame address state to be reset
+ after a DW_CFA_restore_state recovers the register values. */
+#undef TARGET_ASM_SHOULD_RESTORE_CFA_STATE
+#define TARGET_ASM_SHOULD_RESTORE_CFA_STATE darwin_should_restore_cfa_state
+
+/* Our profiling scheme doesn't LP labels and counter words. */
+
+#define NO_PROFILE_COUNTERS 1
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP ""
+
+#undef INVOKE__main
+
+#define TARGET_ASM_CONSTRUCTOR machopic_asm_out_constructor
+#define TARGET_ASM_DESTRUCTOR machopic_asm_out_destructor
+
+/* Always prefix with an underscore. */
+
+#define USER_LABEL_PREFIX "_"
+
+/* A dummy symbol that will be replaced with the function base name. */
+#define MACHOPIC_FUNCTION_BASE_NAME "<pic base>"
+
+/* Don't output a .file directive. That is only used by the assembler for
+ error reporting. */
+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE false
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END darwin_file_end
+
+/* Because Mach-O relocations have a counter from 1 to 255 for the
+ section number they apply to, it is necessary to output all
+ normal sections before the LTO sections, to make sure that the
+ sections that may have relocations always have a section number
+ smaller than 255. */
+#undef TARGET_ASM_LTO_START
+#define TARGET_ASM_LTO_START darwin_asm_lto_start
+#undef TARGET_ASM_LTO_END
+#define TARGET_ASM_LTO_END darwin_asm_lto_end
+
+#define ASM_OUTPUT_SKIP(FILE,SIZE) \
+ fprintf (FILE, "\t.space " HOST_WIDE_INT_PRINT_UNSIGNED"\n", SIZE)
+
+/* Give ObjC methods pretty symbol names. */
+
+#undef OBJC_GEN_METHOD_LABEL
+#define OBJC_GEN_METHOD_LABEL(BUF,IS_INST,CLASS_NAME,CAT_NAME,SEL_NAME,NUM) \
+ do { if (CAT_NAME) \
+ sprintf (BUF, "%c[%s(%s) %s]", (IS_INST) ? '-' : '+', \
+ (CLASS_NAME), (CAT_NAME), (SEL_NAME)); \
+ else \
+ sprintf (BUF, "%c[%s %s]", (IS_INST) ? '-' : '+', \
+ (CLASS_NAME), (SEL_NAME)); \
+ } while (0)
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ darwin_asm_declare_object_name ((FILE), (NAME), (DECL))
+
+/* The RTTI data (e.g., __ti4name) is common and public (and static),
+ but it does need to be referenced via indirect PIC data pointers.
+ The machopic_define_symbol calls are telling the machopic subsystem
+ that the name *is* defined in this module, so it doesn't need to
+ make them indirect. */
+
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do { \
+ const char *xname = NAME; \
+ if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
+ xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
+ if (! DECL_WEAK (DECL) \
+ && ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL))) \
+ machopic_define_symbol (DECL_RTL (DECL)); \
+ if ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL)) \
+ (* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false); \
+ ASM_OUTPUT_FUNCTION_LABEL (FILE, xname, DECL); \
+ } while (0)
+
+#undef TARGET_ASM_DECLARE_CONSTANT_NAME
+#define TARGET_ASM_DECLARE_CONSTANT_NAME darwin_asm_declare_constant_name
+
+/* Wrap new method names in quotes so the assembler doesn't gag.
+ Make Objective-C internal symbols local and in doing this, we need
+ to accommodate the name mangling done by c++ on file scope locals. */
+
+int darwin_label_is_anonymous_local_objc_name (const char *name);
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { \
+ const char *xname = (NAME); \
+ if (! strcmp (xname, MACHOPIC_FUNCTION_BASE_NAME)) \
+ machopic_output_function_base_name(FILE); \
+ else if (xname[0] == '&' || xname[0] == '*') \
+ { \
+ int len = strlen (xname); \
+ if (len > 6 && !strcmp ("$stub", xname + len - 5)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 7 && !strcmp ("$stub\"", xname + len - 6)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 14 && !strcmp ("$non_lazy_ptr", xname + len - 13)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 15 && !strcmp ("$non_lazy_ptr\"", xname + len - 14)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ if (xname[1] != '"' && name_needs_quotes (&xname[1])) \
+ fprintf (FILE, "\"%s\"", &xname[1]); \
+ else \
+ fputs (&xname[1], FILE); \
+ } \
+ else if (xname[0] == '+' || xname[0] == '-') \
+ fprintf (FILE, "\"%s\"", xname); \
+ else if (darwin_label_is_anonymous_local_objc_name (xname)) \
+ fprintf (FILE, "L%s", xname); \
+ else if (xname[0] != '"' && name_needs_quotes (xname)) \
+ asm_fprintf (FILE, "\"%U%s\"", xname); \
+ else \
+ asm_fprintf (FILE, "%U%s", xname); \
+ } while (0)
+
+/* Output before executable code. */
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable data. */
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP "\t.data"
+
+#undef ALIGN_ASM_OP
+#define ALIGN_ASM_OP ".align"
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t%s\t%d\n", ALIGN_ASM_OP, (LOG))
+
+/* The maximum alignment which the object file format can support in bits
+ which depends on the OS version and whether the object is a common
+ variable. */
+
+#undef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT ((1U << L2_MAX_OFILE_ALIGNMENT) * 8U)
+
+/* These are the three variants that emit referenced blank space. */
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ darwin_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
+
+#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
+ darwin_asm_output_aligned_decl_local \
+ ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
+
+#undef ASM_OUTPUT_ALIGNED_DECL_COMMON
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(FILE, DECL, NAME, SIZE, ALIGN) \
+ darwin_asm_output_aligned_decl_common \
+ ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
+
+/* The generic version, archs should over-ride where required. */
+#define MACHOPIC_NL_SYMBOL_PTR_SECTION ".non_lazy_symbol_pointer"
+
+/* Declare the section variables. */
+#ifndef USED_FOR_TARGET
+enum darwin_section_enum {
+#define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC) NAME,
+#include "darwin-sections.def"
+#undef DEF_SECTION
+ NUM_DARWIN_SECTIONS
+};
+extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
+#endif
+
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION machopic_select_section
+
+#undef TARGET_ASM_FUNCTION_SECTION
+#define TARGET_ASM_FUNCTION_SECTION darwin_function_section
+
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION darwin_unique_section
+#undef TARGET_ASM_FUNCTION_RODATA_SECTION
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
+
+#undef TARGET_ASM_TM_CLONE_TABLE_SECTION
+#define TARGET_ASM_TM_CLONE_TABLE_SECTION darwin_tm_clone_table_section
+
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK machopic_reloc_rw_mask
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl "
+#define TARGET_ASM_GLOBALIZE_LABEL darwin_globalize_label
+
+/* Emit an assembler directive to set visibility for a symbol. Used
+ to support visibility attribute and Darwin's private extern
+ feature. */
+#undef TARGET_ASM_ASSEMBLE_VISIBILITY
+#define TARGET_ASM_ASSEMBLE_VISIBILITY darwin_assemble_visibility
+
+/* Extra attributes for Darwin. */
+#define SUBTARGET_ATTRIBUTE_TABLE \
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, \
+ affects_type_identity, handler, exclude } */ \
+ { "apple_kext_compatibility", 0, 0, false, true, false, false, \
+ darwin_handle_kext_attribute, NULL }, \
+ { "weak_import", 0, 0, true, false, false, false, \
+ darwin_handle_weak_import_attribute, NULL }
+
+/* Make local constant labels linker-visible, so that if one follows a
+ weak_global constant, ld64 will be able to separate the atoms. */
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ do { \
+ if (strcmp ("LC", PREFIX) == 0) \
+ sprintf (LABEL, "*%s%ld", "lC", (long)(NUM)); \
+ else if (strcmp ("Lubsan_data", PREFIX) == 0) \
+ sprintf (LABEL, "*%s%ld", "lubsan_data", (long)(NUM));\
+ else if (strcmp ("Lubsan_type", PREFIX) == 0) \
+ sprintf (LABEL, "*%s%ld", "lubsan_type", (long)(NUM));\
+ else if (strcmp ("LASAN", PREFIX) == 0) \
+ sprintf (LABEL, "*%s%ld", "lASAN", (long)(NUM));\
+ else if (strcmp ("LTRAMP", PREFIX) == 0) \
+ sprintf (LABEL, "*%s%ld", "lTRAMP", (long)(NUM));\
+ else \
+ sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM)); \
+ } while (0)
+
+#undef TARGET_ASM_MARK_DECL_PRESERVED
+#define TARGET_ASM_MARK_DECL_PRESERVED darwin_mark_decl_preserved
+
+/* Any port using this header needs to define the first available
+ subtarget symbol bit: SYMBOL_FLAG_SUBT_DEP. */
+
+/* Is a variable. */
+#define MACHO_SYMBOL_FLAG_VARIABLE (SYMBOL_FLAG_SUBT_DEP)
+#define MACHO_SYMBOL_VARIABLE_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_VARIABLE) != 0)
+
+/* Set on a symbol that must be indirected, even when there is a
+ definition in the TU. The ABI mandates that common symbols are so
+ indirected, as are weak. If 'fix-and-continue' is operational then
+ data symbols might also be. */
+
+#define MACHO_SYMBOL_FLAG_MUST_INDIRECT ((SYMBOL_FLAG_SUBT_DEP) << 1)
+#define MACHO_SYMBOL_MUST_INDIRECT_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_MUST_INDIRECT) != 0)
+
+/* Set on a symbol with SYMBOL_FLAG_FUNCTION or MACHO_SYMBOL_FLAG_VARIABLE
+ to indicate that the function or variable is considered defined in this
+ translation unit. */
+
+#define MACHO_SYMBOL_FLAG_DEFINED ((SYMBOL_FLAG_SUBT_DEP) << 2)
+#define MACHO_SYMBOL_DEFINED_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_DEFINED) != 0)
+
+/* Set on a symbol that has specified non-default visibility. */
+
+#define MACHO_SYMBOL_FLAG_HIDDEN_VIS ((SYMBOL_FLAG_SUBT_DEP) << 3)
+#define MACHO_SYMBOL_HIDDEN_VIS_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_HIDDEN_VIS) != 0)
+
+/* Set on a symbol that should be made visible to the linker (overriding
+ 'L' symbol prefixes). */
+
+#define MACHO_SYMBOL_FLAG_LINKER_VIS ((SYMBOL_FLAG_SUBT_DEP) << 4)
+#define MACHO_SYMBOL_LINKER_VIS_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_LINKER_VIS) != 0)
+
+/* Set on a symbol that is a pic stub or symbol indirection (i.e. the
+ L_xxxxx${stub,non_lazy_ptr,lazy_ptr}. */
+
+#define MACHO_SYMBOL_FLAG_INDIRECTION ((SYMBOL_FLAG_SUBT_DEP) << 5)
+#define MACHO_SYMBOL_INDIRECTION_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_INDIRECTION) != 0)
+
+/* Set on a symbol to indicate when fix-and-continue style code
+ generation is being used and the symbol refers to a static symbol
+ that should be rebound from new instances of a translation unit to
+ the original instance of the data. */
+
+#define MACHO_SYMBOL_FLAG_STATIC ((SYMBOL_FLAG_SUBT_DEP) << 6)
+#define MACHO_SYMBOL_STATIC_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & MACHO_SYMBOL_FLAG_STATIC) != 0)
+
+/* Symbolic names for various things we might know about a symbol. */
+
+enum machopic_addr_class {
+ MACHOPIC_UNDEFINED,
+ MACHOPIC_DEFINED_DATA,
+ MACHOPIC_UNDEFINED_DATA,
+ MACHOPIC_DEFINED_FUNCTION,
+ MACHOPIC_UNDEFINED_FUNCTION
+};
+
+/* Macros defining the various PIC cases. */
+
+#undef MACHO_DYNAMIC_NO_PIC_P
+#define MACHO_DYNAMIC_NO_PIC_P (TARGET_MACHO_DYNAMIC_NO_PIC)
+#undef MACHOPIC_INDIRECT
+#define MACHOPIC_INDIRECT (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+#define MACHOPIC_JUST_INDIRECT (MACHO_DYNAMIC_NO_PIC_P)
+#undef MACHOPIC_PURE
+#define MACHOPIC_PURE (flag_pic && ! MACHO_DYNAMIC_NO_PIC_P)
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO darwin_encode_section_info
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING default_strip_name_encoding
+
+#define GEN_BINDER_NAME_FOR_STUB(BUF,STUB,STUB_LENGTH) \
+ do { \
+ const char *const stub_ = (STUB); \
+ char *buffer_ = (BUF); \
+ strcpy (buffer_, stub_); \
+ if (stub_[0] == '"') \
+ { \
+ strcpy (buffer_ + (STUB_LENGTH) - 1, "_binder\""); \
+ } \
+ else \
+ { \
+ strcpy (buffer_ + (STUB_LENGTH), "_binder"); \
+ } \
+ } while (0)
+
+#define GEN_SYMBOL_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
+ do { \
+ const char *const symbol_ = (SYMBOL); \
+ char *buffer_ = (BUF); \
+ if (name_needs_quotes (symbol_) && symbol_[0] != '"') \
+ { \
+ sprintf (buffer_, "\"%s\"", symbol_); \
+ } \
+ else \
+ { \
+ strcpy (buffer_, symbol_); \
+ } \
+ } while (0)
+
+/* Given a symbol name string, create the lazy pointer version
+ of the symbol name. */
+
+#define GEN_LAZY_PTR_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
+ do { \
+ const char *symbol_ = (SYMBOL); \
+ char *buffer_ = (BUF); \
+ if (symbol_[0] == '"') \
+ { \
+ strcpy (buffer_, "\"L"); \
+ strcpy (buffer_ + 2, symbol_ + 1); \
+ strcpy (buffer_ + (SYMBOL_LENGTH), "$lazy_ptr\""); \
+ } \
+ else if (name_needs_quotes (symbol_)) \
+ { \
+ strcpy (buffer_, "\"L"); \
+ strcpy (buffer_ + 2, symbol_); \
+ strcpy (buffer_ + (SYMBOL_LENGTH) + 2, "$lazy_ptr\""); \
+ } \
+ else \
+ { \
+ strcpy (buffer_, "L"); \
+ strcpy (buffer_ + 1, symbol_); \
+ strcpy (buffer_ + (SYMBOL_LENGTH) + 1, "$lazy_ptr"); \
+ } \
+ } while (0)
+
+#define EH_FRAME_SECTION_NAME "__TEXT"
+#define EH_FRAME_SECTION_ATTR ",coalesced,no_toc+strip_static_syms+live_support"
+
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
+ (((CODE) == 2 && (GLOBAL) == 1) \
+ ? (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4) : \
+ ((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
+
+#define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) \
+ darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2, 0)
+
+#define ASM_OUTPUT_DWARF_OFFSET(FILE,SIZE,LABEL,OFFSET,BASE) \
+ darwin_asm_output_dwarf_offset (FILE, SIZE, LABEL, OFFSET, BASE)
+
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(ASM_OUT_FILE, ENCODING, SIZE, ADDR, DONE) \
+ if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1)) { \
+ darwin_non_lazy_pcrel (ASM_OUT_FILE, ADDR); \
+ goto DONE; \
+ }
+
+/* Experimentally, putting jump tables in text is faster on SPEC.
+ Also this is needed for correctness for coalesced functions. */
+
+#ifndef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+#endif
+
+#define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
+
+#define TARGET_ASM_INIT_SECTIONS darwin_init_sections
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION darwin_asm_named_section
+
+#define DARWIN_REGISTER_TARGET_PRAGMAS() \
+ do { \
+ if (!flag_preprocess_only) \
+ cpp_register_pragma (parse_in, NULL, "mark", \
+ darwin_pragma_ignore, false); \
+ c_register_pragma (0, "options", darwin_pragma_options); \
+ c_register_pragma (0, "segment", darwin_pragma_ignore); \
+ c_register_pragma (0, "unused", darwin_pragma_unused); \
+ c_register_pragma (0, "ms_struct", darwin_pragma_ms_struct); \
+ } while (0)
+
+#undef ASM_APP_ON
+#define ASM_APP_ON ""
+#undef ASM_APP_OFF
+#define ASM_APP_OFF ""
+
+void darwin_register_frameworks (const char *, const char *, int);
+void darwin_register_objc_includes (const char *, const char *, int);
+#define TARGET_EXTRA_PRE_INCLUDES darwin_register_objc_includes
+#define TARGET_EXTRA_INCLUDES darwin_register_frameworks
+
+void add_framework_path (char *);
+#define TARGET_OPTF add_framework_path
+
+#define TARGET_POSIX_IO
+
+#define WINT_TYPE "int"
+
+/* Every program on darwin links against libSystem which contains the pthread
+ routines, so there's no need to explicitly call out when doing threaded
+ work. */
+
+#undef GOMP_SELF_SPECS
+#define GOMP_SELF_SPECS ""
+#undef GTM_SELF_SPECS
+#define GTM_SELF_SPECS ""
+
+/* Darwin disables section anchors by default.
+ They should be enabled per arch where support exists in that arch. */
+#define TARGET_ASM_OUTPUT_ANCHOR NULL
+#define DARWIN_SECTION_ANCHORS 0
+
+#define HAVE_ENABLE_EXECUTE_STACK
+
+/* For Apple KEXTs, we make the constructors return this to match gcc
+ 2.95. */
+#define TARGET_CXX_CDTOR_RETURNS_THIS (darwin_kextabi_p)
+#define TARGET_KEXTABI flag_apple_kext
+
+/* We have target-specific builtins. */
+#define SUBTARGET_FOLD_BUILTIN darwin_fold_builtin
+
+#define TARGET_N_FORMAT_TYPES 1
+#define TARGET_FORMAT_TYPES darwin_additional_format_types
+
+#ifndef USED_FOR_TARGET
+extern void darwin_driver_init (unsigned int *,struct cl_decoded_option **);
+#define GCC_DRIVER_HOST_INITIALIZATION \
+ darwin_driver_init (&decoded_options_count, &decoded_options)
+#endif
+
+/* The Apple assembler and linker do not support constructor priorities. */
+#undef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY 0
+
+#undef STACK_CHECK_STATIC_BUILTIN
+#define STACK_CHECK_STATIC_BUILTIN 1
+
+/* When building cross-compilers (and native crosses) we shall default to
+ providing an osx-version-min of this unless overridden by the User.
+ 10.5 is the only version that fully supports all our archs so that's the
+ fall-back default. */
+#ifndef DEF_MIN_OSX_VERSION
+#define DEF_MIN_OSX_VERSION "10.5"
+#endif
+
+/* Later versions of ld64 support coalescing weak code/data without requiring
+ that they be placed in specially identified sections. This is the earliest
+ _tested_ version known to support this so far. */
+#define MIN_LD64_NO_COAL_SECTS "236.3"
+
+/* From at least version 62.1, ld64 can build symbol indirection stubs as
+ needed, and there is no need for the compiler to emit them. */
+#define MIN_LD64_OMIT_STUBS "62.1"
+
+/* Emit start labels for init and term sections from this version. */
+#define MIN_LD64_INIT_TERM_START_LABELS "136.0"
+
+/* If we have no definition for the linker version, pick the minimum version
+ that will bootstrap the compiler. */
+#ifndef LD64_VERSION
+# ifndef DEF_LD64
+# define LD64_VERSION "85.2.1"
+# else
+# define LD64_VERSION DEF_LD64
+# endif
+#endif
+
+/* CTF and BTF support. */
+#undef CTF_INFO_SECTION_NAME
+#define CTF_INFO_SECTION_NAME "__CTF_BTF,__ctf,regular,debug"
+#undef BTF_INFO_SECTION_NAME
+#define BTF_INFO_SECTION_NAME "__CTF_BTF,__btf,regular,debug"
+
+#endif /* CONFIG_DARWIN_H */
diff --git a/support/cpp/gcc/config/dbxcoff.h b/support/cpp/gcc/config/dbxcoff.h
new file mode 100644
index 000000000..02b78c6bf
--- /dev/null
+++ b/support/cpp/gcc/config/dbxcoff.h
@@ -0,0 +1,56 @@
+/* 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/support/cpp/gcc/config/dbxelf.h b/support/cpp/gcc/config/dbxelf.h
new file mode 100644
index 000000000..4b90e95bc
--- /dev/null
+++ b/support/cpp/gcc/config/dbxelf.h
@@ -0,0 +1,68 @@
+/* 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/support/cpp/gcc/config/dragonfly-stdint.h b/support/cpp/gcc/config/dragonfly-stdint.h
new file mode 100644
index 000000000..7bd01f3da
--- /dev/null
+++ b/support/cpp/gcc/config/dragonfly-stdint.h
@@ -0,0 +1,56 @@
+/* Definitions for <stdint.h> types for DragonFly systems.
+ Copyright (C) 2014-2022 Free Software Foundation, Inc.
+ Contributed by John Marino <gnugcc@marino.st>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#define SIG_ATOMIC_TYPE "int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE INT8_TYPE
+#define INT_LEAST16_TYPE INT16_TYPE
+#define INT_LEAST32_TYPE INT32_TYPE
+#define INT_LEAST64_TYPE INT64_TYPE
+#define UINT_LEAST8_TYPE UINT8_TYPE
+#define UINT_LEAST16_TYPE UINT16_TYPE
+#define UINT_LEAST32_TYPE UINT32_TYPE
+#define UINT_LEAST64_TYPE UINT64_TYPE
+
+#define INT_FAST8_TYPE INT32_TYPE
+#define INT_FAST16_TYPE INT32_TYPE
+#define INT_FAST32_TYPE INT32_TYPE
+#define INT_FAST64_TYPE INT64_TYPE
+#define UINT_FAST8_TYPE UINT32_TYPE
+#define UINT_FAST16_TYPE UINT32_TYPE
+#define UINT_FAST32_TYPE UINT32_TYPE
+#define UINT_FAST64_TYPE UINT64_TYPE
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? INT64_TYPE : INT32_TYPE)
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? UINT64_TYPE : UINT32_TYPE)
diff --git a/support/cpp/gcc/config/dragonfly.h b/support/cpp/gcc/config/dragonfly.h
new file mode 100644
index 000000000..0235e6268
--- /dev/null
+++ b/support/cpp/gcc/config/dragonfly.h
@@ -0,0 +1,125 @@
+/* Base configuration file for all DragonFly targets.
+ Copyright (C) 2014-2022 Free Software Foundation, Inc.
+ Contributed by John Marino <gnugcc@marino.st>
+
+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/>. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define ("__DragonFly__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=DragonFly"); \
+ } \
+ while (0)
+
+#undef CPP_SPEC
+#define CPP_SPEC \
+ "%(cpp_cpu) %(cpp_arch) %{posix:-D_POSIX_SOURCE}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: \
+ %{pg:gcrt1.o%s} \
+ %{!pg: \
+ %{p:gcrt1.o%s} \
+ %{!p: \
+ %{profile: gcrt1.o%s} \
+ %{!profile: \
+ %{pie: Scrt1.o%s;:crt1.o%s}}}}} \
+ crti.o%s \
+ %{shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{pthread:-lpthread} -lc"
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "--eh-frame-hdr"
+#endif
+
+/* Provide a LINK_SPEC appropriate for DragonFly. Here we provide support
+ for the special GCC options -static and -shared, which allow us to
+ link things in one of these three modes by applying the appropriate
+ combinations of options at link-time.
+
+ When the -shared link option is used a final link is not being
+ done. */
+
+#define DFBSD_LINK_SPEC \
+ "%{p:%nconsider using '-pg' instead of '-p' with gprof(1)} \
+ %{v:-V} \
+ %{assert*} %{R*} %{rpath*} %{defsym*} \
+ %{shared:-Bshareable %{h*} %{soname*}} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ -dynamic-linker %(dfbsd_dynamic_linker) \
+ } \
+ %{static:-Bstatic} \
+ } \
+ %{!static:--hash-style=gnu} \
+ %{symbolic:-Bsymbolic}"
+
+#undef LINK_SPEC
+#define LINK_SPEC DFBSD_LINK_SPEC
+
+#define DFBSD_DYNAMIC_LINKER "/usr/libexec/ld-elf.so.2"
+
+
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+/************************[ Target stuff ]***********************************/
+
+/* All DragonFly Architectures support the ELF object file format. */
+#undef OBJECT_FORMAT_ELF
+#define OBJECT_FORMAT_ELF
+
+/* Follow DragonFly's standard headers (<machine/stdint.h>, etc...). */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WINT_TYPE
+#define WINT_TYPE "int"
+
+/* Code generation parameters. */
+
+/* Use periods rather than dollar signs in special g++ assembler names.
+ This ensures the configuration knows our system correctly so we can link
+ with libraries compiled with the native cc. */
+#undef NO_DOLLAR_IN_LABEL
+
+/* Used by libgcc2.c. We support file locking with fcntl / F_SETLKW.
+ This enables the test coverage code to use file locking when exiting a
+ program, which avoids race conditions if the program has forked. */
+#define TARGET_POSIX_IO
diff --git a/support/cpp/gcc/config/dummy/dummy-opts.h b/support/cpp/gcc/config/dummy/dummy-opts.h
new file mode 100644
index 000000000..8a4ad29d0
--- /dev/null
+++ b/support/cpp/gcc/config/dummy/dummy-opts.h
@@ -0,0 +1,131 @@
+/* Definitions for option handling for IA-32.
+ Copyright (C) 1988-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/>. */
+
+#ifndef DUMMY_OPTS_H
+#define DUMMY_OPTS_H
+
+/* Algorithm to expand string function with. */
+enum stringop_alg
+{
+#undef DEF_ALG
+#define DEF_ALG(alg, name) alg,
+
+// #include "stringop.def"
+last_alg
+
+#undef DEF_ALG
+};
+
+/* Available call abi. */
+enum calling_abi
+{
+ SYSV_ABI = 0,
+ MS_ABI = 1
+};
+
+enum fpmath_unit
+{
+ FPMATH_387 = 1,
+ FPMATH_SSE = 2
+};
+
+enum tls_dialect
+{
+ TLS_DIALECT_GNU,
+ TLS_DIALECT_GNU2,
+ TLS_DIALECT_SUN
+};
+
+enum cmodel {
+ CM_32, /* The traditional 32-bit ABI. */
+ CM_SMALL, /* Assumes all code and data fits in the low 31 bits. */
+ CM_KERNEL, /* Assumes all code and data fits in the high 31 bits. */
+ CM_MEDIUM, /* Assumes code fits in the low 31 bits; data unlimited. */
+ CM_LARGE, /* No assumptions. */
+ CM_SMALL_PIC, /* Assumes code+data+got/plt fits in a 31 bit region. */
+ CM_MEDIUM_PIC,/* Assumes code+got/plt fits in a 31 bit region. */
+ CM_LARGE_PIC /* No assumptions. */
+};
+
+enum pmode {
+ PMODE_SI, /* Pmode == SImode. */
+ PMODE_DI /* Pmode == DImode. */
+};
+
+enum ix86_align_data {
+ ix86_align_data_type_compat,
+ ix86_align_data_type_abi,
+ ix86_align_data_type_cacheline
+};
+
+enum asm_dialect {
+ ASM_ATT,
+ ASM_INTEL
+};
+
+enum ix86_veclibabi {
+ ix86_veclibabi_type_none,
+ ix86_veclibabi_type_svml,
+ ix86_veclibabi_type_acml
+};
+
+enum stack_protector_guard {
+ SSP_TLS, /* per-thread canary in TLS block */
+ SSP_GLOBAL /* global canary */
+};
+
+enum prefer_vector_width {
+ PVW_NONE,
+ PVW_AVX128,
+ PVW_AVX256,
+ PVW_AVX512
+};
+
+/* This is used to mitigate variant #2 of the speculative execution
+ vulnerabilities on x86 processors identified by CVE-2017-5715, aka
+ Spectre. They convert indirect branches and function returns to
+ call and return thunks to avoid speculative execution via indirect
+ call, jmp and ret. */
+enum indirect_branch {
+ indirect_branch_unset = 0,
+ indirect_branch_keep,
+ indirect_branch_thunk,
+ indirect_branch_thunk_inline,
+ indirect_branch_thunk_extern
+};
+
+enum instrument_return {
+ instrument_return_none = 0,
+ instrument_return_call,
+ instrument_return_nop5
+};
+
+enum harden_sls {
+ harden_sls_none = 0,
+ harden_sls_return = 1 << 0,
+ harden_sls_indirect_jmp = 1 << 1,
+ harden_sls_all = harden_sls_return | harden_sls_indirect_jmp
+};
+
+#endif
diff --git a/support/cpp/gcc/config/dummy/dummy-protos.h b/support/cpp/gcc/config/dummy/dummy-protos.h
new file mode 100644
index 000000000..3596ce81e
--- /dev/null
+++ b/support/cpp/gcc/config/dummy/dummy-protos.h
@@ -0,0 +1,412 @@
+/* Definitions of target machine for GCC for IA-32.
+ Copyright (C) 1988-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/>. */
+
+/* In i386-common.cc. */
+extern bool ix86_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set ATTRIBUTE_UNUSED,
+ const struct cl_decoded_option *decoded,
+ location_t loc);
+
+/* Functions in i386.cc */
+extern bool ix86_target_stack_probe (void);
+extern bool ix86_can_use_return_insn_p (void);
+extern bool ix86_function_ms_hook_prologue (const_tree fn);
+extern void ix86_setup_frame_addresses (void);
+extern bool ix86_rip_relative_addr_p (struct ix86_address *parts);
+
+extern HOST_WIDE_INT ix86_initial_elimination_offset (int, int);
+extern void ix86_expand_prologue (void);
+extern void ix86_maybe_emit_epilogue_vzeroupper (void);
+extern void ix86_expand_epilogue (int);
+extern void ix86_expand_split_stack_prologue (void);
+
+extern void ix86_output_addr_vec_elt (FILE *, int);
+extern void ix86_output_addr_diff_elt (FILE *, int, int);
+
+extern const char *ix86_output_ssemov (rtx_insn *, rtx *);
+
+extern enum calling_abi ix86_cfun_abi (void);
+extern enum calling_abi ix86_function_type_abi (const_tree);
+
+extern bool ix86_use_pseudo_pic_reg (void);
+
+extern void ix86_reset_previous_fndecl (void);
+
+extern bool ix86_using_red_zone (void);
+
+extern rtx ix86_gen_scratch_sse_rtx (machine_mode);
+
+extern unsigned int ix86_regmode_natural_size (machine_mode);
+extern bool ix86_check_builtin_isa_match (unsigned int fcode);
+#ifdef RTX_CODE
+extern int standard_80387_constant_p (rtx);
+extern const char *standard_80387_constant_opcode (rtx);
+extern rtx standard_80387_constant_rtx (int);
+extern int standard_sse_constant_p (rtx, machine_mode);
+extern const char *standard_sse_constant_opcode (rtx_insn *, rtx *);
+extern bool ix86_standard_x87sse_constant_load_p (const rtx_insn *, rtx);
+extern bool ix86_pre_reload_split (void);
+extern bool symbolic_reference_mentioned_p (rtx);
+extern bool extended_reg_mentioned_p (rtx);
+extern bool x86_extended_QIreg_mentioned_p (rtx_insn *);
+extern bool x86_extended_reg_mentioned_p (rtx);
+extern bool x86_maybe_negate_const_int (rtx *, machine_mode);
+extern machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
+
+extern int avx_vpermilp_parallel (rtx par, machine_mode mode);
+extern int avx_vperm2f128_parallel (rtx par, machine_mode mode);
+
+extern bool ix86_expand_strlen (rtx, rtx, rtx, rtx);
+extern bool ix86_expand_set_or_cpymem (rtx, rtx, rtx, rtx, rtx, rtx,
+ rtx, rtx, rtx, rtx, bool);
+extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, rtx, rtx, rtx, bool);
+
+extern bool constant_address_p (rtx);
+extern bool legitimate_pic_operand_p (rtx);
+extern bool legitimate_pic_address_disp_p (rtx);
+extern bool ix86_force_load_from_GOT_p (rtx, bool = false);
+extern void print_reg (rtx, int, FILE*);
+extern void ix86_print_operand (FILE *, rtx, int);
+
+extern void split_double_mode (machine_mode, rtx[], int, rtx[], rtx[]);
+
+extern const char *output_set_got (rtx, rtx);
+extern const char *output_387_binary_op (rtx_insn *, rtx*);
+extern const char *output_387_reg_move (rtx_insn *, rtx*);
+extern const char *output_fix_trunc (rtx_insn *, rtx*, bool);
+extern const char *output_fp_compare (rtx_insn *, rtx*, bool, bool);
+extern const char *output_adjust_stack_and_probe (rtx);
+extern const char *output_probe_stack_range (rtx, rtx);
+
+extern void ix86_output_patchable_area (unsigned int, bool);
+
+extern void ix86_expand_clear (rtx);
+extern void ix86_expand_move (machine_mode, rtx[]);
+extern void ix86_expand_vector_move (machine_mode, rtx[]);
+extern void ix86_expand_vector_move_misalign (machine_mode, rtx[]);
+extern rtx ix86_fixup_binary_operands (enum rtx_code,
+ machine_mode, rtx[]);
+extern void ix86_fixup_binary_operands_no_copy (enum rtx_code,
+ machine_mode, rtx[]);
+extern void ix86_expand_binary_operator (enum rtx_code,
+ machine_mode, rtx[]);
+extern void ix86_expand_vector_logical_operator (enum rtx_code,
+ machine_mode, rtx[]);
+extern bool ix86_binary_operator_ok (enum rtx_code, machine_mode, rtx[]);
+extern bool ix86_avoid_lea_for_add (rtx_insn *, rtx[]);
+extern bool ix86_use_lea_for_mov (rtx_insn *, rtx[]);
+extern bool ix86_avoid_lea_for_addr (rtx_insn *, rtx[]);
+extern void ix86_split_lea_for_addr (rtx_insn *, rtx[], machine_mode);
+extern bool ix86_lea_for_add_ok (rtx_insn *, rtx[]);
+extern int ix86_last_zero_store_uid;
+extern bool ix86_vec_interleave_v2df_operator_ok (rtx operands[3], bool high);
+extern bool ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn);
+extern bool ix86_agi_dependent (rtx_insn *set_insn, rtx_insn *use_insn);
+extern void ix86_expand_unary_operator (enum rtx_code, machine_mode,
+ rtx[]);
+extern rtx ix86_build_const_vector (machine_mode, bool, rtx);
+extern rtx ix86_build_signbit_mask (machine_mode, bool, bool);
+extern void ix86_split_convert_uns_si_sse (rtx[]);
+extern void ix86_expand_convert_uns_didf_sse (rtx, rtx);
+extern void ix86_expand_convert_uns_sixf_sse (rtx, rtx);
+extern void ix86_expand_convert_uns_sidf_sse (rtx, rtx);
+extern void ix86_expand_convert_uns_sisf_sse (rtx, rtx);
+extern void ix86_expand_convert_sign_didf_sse (rtx, rtx);
+extern void ix86_expand_vector_convert_uns_vsivsf (rtx, rtx);
+extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx, rtx *);
+extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code);
+extern void ix86_expand_fp_absneg_operator (enum rtx_code, machine_mode,
+ rtx[]);
+extern void ix86_split_fp_absneg_operator (enum rtx_code, machine_mode,
+ rtx[]);
+extern void ix86_expand_copysign (rtx []);
+extern void ix86_expand_xorsign (rtx []);
+extern bool ix86_unary_operator_ok (enum rtx_code, machine_mode, rtx[]);
+extern bool ix86_match_ccmode (rtx, machine_mode);
+extern void ix86_expand_branch (enum rtx_code, rtx, rtx, rtx);
+extern void ix86_expand_setcc (rtx, enum rtx_code, rtx, rtx);
+extern bool ix86_expand_int_movcc (rtx[]);
+extern bool ix86_expand_fp_movcc (rtx[]);
+extern bool ix86_expand_fp_vcond (rtx[]);
+extern bool ix86_expand_int_vcond (rtx[]);
+extern void ix86_expand_vec_perm (rtx[]);
+extern bool ix86_expand_mask_vec_cmp (rtx, enum rtx_code, rtx, rtx);
+extern bool ix86_expand_int_vec_cmp (rtx[]);
+extern bool ix86_expand_fp_vec_cmp (rtx[]);
+extern void ix86_expand_sse_movcc (rtx, rtx, rtx, rtx);
+extern void ix86_expand_sse_unpack (rtx, rtx, bool, bool);
+extern void ix86_expand_fp_spaceship (rtx, rtx, rtx);
+extern bool ix86_expand_int_addcc (rtx[]);
+extern rtx_insn *ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool);
+extern bool ix86_call_use_plt_p (rtx);
+extern void ix86_split_call_vzeroupper (rtx, rtx);
+extern void x86_initialize_trampoline (rtx, rtx, rtx);
+extern rtx ix86_zero_extend_to_Pmode (rtx);
+extern void ix86_split_long_move (rtx[]);
+extern void ix86_split_ashl (rtx *, rtx, machine_mode);
+extern void ix86_split_ashr (rtx *, rtx, machine_mode);
+extern void ix86_split_lshr (rtx *, rtx, machine_mode);
+extern void ix86_expand_v1ti_shift (enum rtx_code, rtx[]);
+extern void ix86_expand_v1ti_rotate (enum rtx_code, rtx[]);
+extern void ix86_expand_v1ti_ashiftrt (rtx[]);
+extern rtx ix86_find_base_term (rtx);
+extern bool ix86_check_movabs (rtx, int);
+extern bool ix86_check_no_addr_space (rtx);
+extern void ix86_split_idivmod (machine_mode, rtx[], bool);
+extern bool ix86_hardreg_mov_ok (rtx, rtx);
+
+extern rtx assign_386_stack_local (machine_mode, enum ix86_stack_slot);
+extern int ix86_attr_length_immediate_default (rtx_insn *, bool);
+extern int ix86_attr_length_address_default (rtx_insn *);
+extern int ix86_attr_length_vex_default (rtx_insn *, bool, bool);
+
+extern rtx ix86_libcall_value (machine_mode);
+extern bool ix86_function_arg_regno_p (int);
+extern void ix86_asm_output_function_label (FILE *, const char *, tree);
+extern void ix86_call_abi_override (const_tree);
+extern int ix86_reg_parm_stack_space (const_tree);
+
+extern bool ix86_libc_has_function (enum function_class fn_class);
+
+extern void x86_order_regs_for_local_alloc (void);
+extern void x86_function_profiler (FILE *, int);
+extern void x86_emit_floatuns (rtx [2]);
+extern void ix86_emit_fp_unordered_jump (rtx);
+
+extern void ix86_emit_i387_sinh (rtx, rtx);
+extern void ix86_emit_i387_cosh (rtx, rtx);
+extern void ix86_emit_i387_tanh (rtx, rtx);
+extern void ix86_emit_i387_asinh (rtx, rtx);
+extern void ix86_emit_i387_acosh (rtx, rtx);
+extern void ix86_emit_i387_atanh (rtx, rtx);
+extern void ix86_emit_i387_log1p (rtx, rtx);
+extern void ix86_emit_i387_round (rtx, rtx);
+extern void ix86_emit_swdivsf (rtx, rtx, rtx, machine_mode);
+extern void ix86_emit_swsqrtsf (rtx, rtx, machine_mode, bool);
+
+extern enum rtx_code ix86_reverse_condition (enum rtx_code, machine_mode);
+
+extern void ix86_expand_lround (rtx, rtx);
+extern void ix86_expand_lfloorceil (rtx, rtx, bool);
+extern void ix86_expand_rint (rtx, rtx);
+extern void ix86_expand_floorceil (rtx, rtx, bool);
+extern void ix86_expand_floorceildf_32 (rtx, rtx, bool);
+extern void ix86_expand_trunc (rtx, rtx);
+extern void ix86_expand_truncdf_32 (rtx, rtx);
+extern void ix86_expand_round (rtx, rtx);
+extern void ix86_expand_rounddf_32 (rtx, rtx);
+extern void ix86_expand_round_sse4 (rtx, rtx);
+
+extern void ix86_expand_vecop_qihi (enum rtx_code, rtx, rtx, rtx);
+extern rtx ix86_split_stack_guard (void);
+
+extern void ix86_move_vector_high_sse_to_mmx (rtx);
+extern void ix86_split_mmx_pack (rtx[], enum rtx_code);
+extern void ix86_split_mmx_punpck (rtx[], bool);
+extern void ix86_expand_avx_vzeroupper (void);
+extern void ix86_expand_atomic_fetch_op_loop (rtx, rtx, rtx, enum rtx_code,
+ bool, bool);
+extern void ix86_expand_cmpxchg_loop (rtx *, rtx, rtx, rtx, rtx, rtx,
+ bool, rtx_code_label *);
+
+#ifdef TREE_CODE
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+#endif /* TREE_CODE */
+
+#endif /* RTX_CODE */
+
+#ifdef TREE_CODE
+extern int ix86_data_alignment (tree, unsigned int, bool);
+extern unsigned int ix86_local_alignment (tree, machine_mode,
+ unsigned int, bool = false);
+extern unsigned int ix86_minimum_alignment (tree, machine_mode,
+ unsigned int);
+extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
+extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
+extern int x86_field_alignment (tree, int);
+extern tree ix86_valid_target_attribute_tree (tree, tree,
+ struct gcc_options *,
+ struct gcc_options *, bool);
+extern unsigned int ix86_get_callcvt (const_tree);
+
+#endif
+
+extern rtx ix86_tls_module_base (void);
+extern bool ix86_gpr_tls_address_pattern_p (rtx);
+extern bool ix86_tls_address_pattern_p (rtx);
+extern rtx ix86_rewrite_tls_address (rtx);
+
+extern void ix86_expand_vector_init (bool, rtx, rtx);
+extern void ix86_expand_vector_set (bool, rtx, rtx, int);
+extern void ix86_expand_vector_set_var (rtx, rtx, rtx);
+extern void ix86_expand_vector_extract (bool, rtx, rtx, int);
+extern void ix86_expand_reduc (rtx (*)(rtx, rtx, rtx), rtx, rtx);
+
+extern void ix86_expand_vec_extract_even_odd (rtx, rtx, rtx, unsigned);
+extern bool ix86_expand_pextr (rtx *);
+extern bool ix86_expand_pinsr (rtx *);
+extern void ix86_expand_mul_widen_evenodd (rtx, rtx, rtx, bool, bool);
+extern void ix86_expand_mul_widen_hilo (rtx, rtx, rtx, bool, bool);
+extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx);
+extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx);
+extern void ix86_expand_sse2_abs (rtx, rtx);
+extern bool ix86_expand_vector_init_duplicate (bool, machine_mode, rtx,
+ rtx);
+extern bool ix86_extract_perm_from_pool_constant (int*, rtx);
+
+/* In i386-c.cc */
+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);
+extern void i386_pe_record_external_function (tree, const char *);
+extern void i386_pe_maybe_record_exported_symbol (tree, const char *, int);
+extern void i386_pe_encode_section_info (tree, rtx, int);
+extern bool i386_pe_binds_local_p (const_tree);
+extern const char *i386_pe_strip_name_encoding_full (const char *);
+extern bool i386_pe_valid_dllimport_attribute_p (const_tree);
+extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
+extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
+extern void i386_pe_asm_output_aligned_decl_common (FILE *, tree,
+ const char *,
+ HOST_WIDE_INT,
+ HOST_WIDE_INT);
+extern void i386_pe_file_end (void);
+extern void i386_pe_asm_lto_start (void);
+extern void i386_pe_asm_lto_end (void);
+extern void i386_pe_start_function (FILE *, const char *, tree);
+extern void i386_pe_end_function (FILE *, const char *, tree);
+extern void i386_pe_end_cold_function (FILE *, const char *, tree);
+extern void i386_pe_assemble_visibility (tree, int);
+extern tree i386_pe_mangle_decl_assembler_name (tree, tree);
+extern tree i386_pe_mangle_assembler_name (const char *);
+extern void i386_pe_record_stub (const char *);
+
+extern void i386_pe_seh_init (FILE *);
+extern void i386_pe_seh_end_prologue (FILE *);
+extern void i386_pe_seh_cold_init (FILE *, const char *);
+extern void i386_pe_seh_unwind_emit (FILE *, rtx_insn *);
+extern void i386_pe_seh_emit_except_personality (rtx);
+extern void i386_pe_seh_init_sections (void);
+
+/* In winnt-cxx.cc and winnt-stubs.cc */
+extern void i386_pe_adjust_class_at_definition (tree);
+extern bool i386_pe_type_dllimport_p (tree);
+extern bool i386_pe_type_dllexport_p (tree);
+
+extern int i386_pe_reloc_rw_mask (void);
+
+extern char internal_label_prefix[16];
+extern int internal_label_prefix_len;
+
+extern bool ix86_epilogue_uses (int);
+
+struct ix86_address
+{
+ rtx base, index, disp;
+ HOST_WIDE_INT scale;
+ addr_space_t seg;
+};
+
+extern bool ix86_decompose_address (rtx, struct ix86_address *);
+extern int memory_address_length (rtx, bool);
+extern void x86_output_aligned_bss (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT, unsigned);
+extern void x86_elf_aligned_decl_common (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT, unsigned);
+
+#ifdef RTX_CODE
+extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
+ enum rtx_code *, enum rtx_code *);
+extern enum rtx_code ix86_fp_compare_code_to_integer (enum rtx_code);
+#endif
+extern int asm_preferred_eh_data_format (int, int);
+
+#ifdef HAVE_ATTR_cpu
+extern enum attr_cpu ix86_schedule;
+#endif
+
+extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
+extern const char * ix86_output_indirect_jmp (rtx call_op);
+extern const char * ix86_output_function_return (bool long_p);
+extern const char * ix86_output_indirect_function_return (rtx ret_op);
+extern void ix86_split_simple_return_pop_internal (rtx);
+extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
+ machine_mode mode);
+extern int ix86_min_insn_size (rtx_insn *);
+
+extern int ix86_issue_rate (void);
+extern int ix86_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn,
+ int cost, unsigned int);
+extern int ia32_multipass_dfa_lookahead (void);
+extern bool ix86_macro_fusion_p (void);
+extern bool ix86_macro_fusion_pair_p (rtx_insn *condgen, rtx_insn *condjmp);
+
+extern bool ix86_bd_has_dispatch (rtx_insn *insn, int action);
+extern void ix86_bd_do_dispatch (rtx_insn *insn, int mode);
+
+extern void ix86_core2i7_init_hooks (void);
+
+extern int ix86_atom_sched_reorder (FILE *, int, rtx_insn **, int *, int);
+
+extern poly_int64 ix86_push_rounding (poly_int64);
+
+#ifdef RTX_CODE
+/* Target data for multipass lookahead scheduling.
+ Currently used for Core 2/i7 tuning. */
+struct ix86_first_cycle_multipass_data_
+{
+ /* The length (in bytes) of ifetch block in this solution. */
+ int ifetch_block_len;
+ /* Number of instructions in ifetch block in this solution. */
+ int ifetch_block_n_insns;
+ /* Bitmap to remember changes to ready_try for backtracking. */
+ sbitmap ready_try_change;
+ /* Size of the bitmap. */
+ int ready_try_change_size;
+};
+# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T \
+ struct ix86_first_cycle_multipass_data_
+#endif /* RTX_CODE */
+
+const addr_space_t ADDR_SPACE_SEG_FS = 1;
+const addr_space_t ADDR_SPACE_SEG_GS = 2;
+
+namespace gcc { class context; }
+class rtl_opt_pass;
+
+extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
+extern rtl_opt_pass *make_pass_stv (gcc::context *);
+extern rtl_opt_pass *make_pass_insert_endbr_and_patchable_area
+ (gcc::context *);
+extern rtl_opt_pass *make_pass_remove_partial_avx_dependency
+ (gcc::context *);
+
+extern bool ix86_has_no_direct_extern_access;
+
+/* In i386-expand.cc. */
+bool ix86_check_builtin_isa_match (unsigned int, HOST_WIDE_INT*,
+ HOST_WIDE_INT*);
diff --git a/support/cpp/gcc/config/dummy/dummy.h b/support/cpp/gcc/config/dummy/dummy.h
new file mode 100644
index 000000000..4be466225
--- /dev/null
+++ b/support/cpp/gcc/config/dummy/dummy.h
@@ -0,0 +1,2600 @@
+/* Definitions of target machine for GCC for IA-32.
+ Copyright (C) 1988-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/>. */
+
+/* The purpose of this file is to define the characteristics of the i386,
+ independent of assembler syntax or operating system.
+
+ Three other files build on this one to describe a specific assembler syntax:
+ bsd386.h, att386.h, and sun386.h.
+
+ The actual tm.h file for a particular system should include
+ this file, and then the file for the appropriate assembler syntax.
+
+ Many macros that specify assembler syntax are omitted entirely from
+ this file because they really belong in the files for particular
+ assemblers. These include RP, IP, LPREFIX, PUT_OP_SIZE, USE_STAR,
+ ADDR_BEG, ADDR_END, PRINT_IREG, PRINT_SCALE, PRINT_B_I_S, and many
+ that start with ASM_ or end in ASM_OP. */
+
+/* Redefines for option macros. */
+
+#define TARGET_CMPXCHG16B TARGET_CX16
+#define TARGET_CMPXCHG16B_P(x) TARGET_CX16_P(x)
+
+#define TARGET_LP64 TARGET_ABI_64
+#define TARGET_LP64_P(x) TARGET_ABI_64_P(x)
+#define TARGET_X32 TARGET_ABI_X32
+#define TARGET_X32_P(x) TARGET_ABI_X32_P(x)
+#define TARGET_16BIT TARGET_CODE16
+#define TARGET_16BIT_P(x) TARGET_CODE16_P(x)
+
+#define TARGET_MMX_WITH_SSE (TARGET_64BIT && TARGET_SSE2)
+
+#include "config/vxworks-dummy.h"
+
+#include "config/dummy/dummy-opts.h"
+
+#define MAX_STRINGOP_ALGS 4
+
+/* Specify what algorithm to use for stringops on known size.
+ When size is unknown, the UNKNOWN_SIZE alg is used. When size is
+ known at compile time or estimated via feedback, the SIZE array
+ is walked in order until MAX is greater then the estimate (or -1
+ means infinity). Corresponding ALG is used then.
+ When NOALIGN is true the code guaranting the alignment of the memory
+ block is skipped.
+
+ For example initializer:
+ {{256, loop}, {-1, rep_prefix_4_byte}}
+ will use loop for blocks smaller or equal to 256 bytes, rep prefix will
+ be used otherwise. */
+struct stringop_algs
+{
+};
+
+/* Analog of COSTS_N_INSNS when optimizing for size. */
+#ifndef COSTS_N_BYTES
+#define COSTS_N_BYTES(N) ((N) * 2)
+#endif
+
+/* Define the specific costs for a given cpu. NB: hard_register is used
+ by TARGET_REGISTER_MOVE_COST and TARGET_MEMORY_MOVE_COST to compute
+ hard register move costs by register allocator. Relative costs of
+ pseudo register load and store versus pseudo register moves in RTL
+ expressions for TARGET_RTX_COSTS can be different from relative
+ costs of hard registers to get the most efficient operations with
+ pseudo registers. */
+
+struct processor_costs {
+ /* Costs used by register allocator. integer->integer register move
+ cost is 2. */
+ struct
+ {
+ const int movzbl_load; /* cost of loading using movzbl */
+ const int int_load[3]; /* cost of loading integer registers
+ in QImode, HImode and SImode relative
+ to reg-reg move (2). */
+ const int int_store[3]; /* cost of storing integer register
+ in QImode, HImode and SImode */
+ const int fp_move; /* cost of reg,reg fld/fst */
+ const int fp_load[3]; /* cost of loading FP register
+ in SFmode, DFmode and XFmode */
+ const int fp_store[3]; /* cost of storing FP register
+ in SFmode, DFmode and XFmode */
+ const int mmx_move; /* cost of moving MMX register. */
+ const int mmx_load[2]; /* cost of loading MMX register
+ in SImode and DImode */
+ const int mmx_store[2]; /* cost of storing MMX register
+ in SImode and DImode */
+ const int xmm_move; /* cost of moving XMM register. */
+ const int ymm_move; /* cost of moving XMM register. */
+ const int zmm_move; /* cost of moving XMM register. */
+ const int sse_load[5]; /* cost of loading SSE register
+ in 32bit, 64bit, 128bit, 256bit and 512bit */
+ const int sse_store[5]; /* cost of storing SSE register
+ in SImode, DImode and TImode. */
+ const int sse_to_integer; /* cost of moving SSE register to integer. */
+ const int integer_to_sse; /* cost of moving integer register to SSE. */
+ const int mask_to_integer; /* cost of moving mask register to integer. */
+ const int integer_to_mask; /* cost of moving integer register to mask. */
+ const int mask_load[3]; /* cost of loading mask registers
+ in QImode, HImode and SImode. */
+ const int mask_store[3]; /* cost of storing mask register
+ in QImode, HImode and SImode. */
+ const int mask_move; /* cost of moving mask register. */
+ } hard_register;
+
+ const int add; /* cost of an add instruction */
+ const int lea; /* cost of a lea instruction */
+ const int shift_var; /* variable shift costs */
+ const int shift_const; /* constant shift costs */
+ const int mult_init[5]; /* cost of starting a multiply
+ in QImode, HImode, SImode, DImode, TImode*/
+ const int mult_bit; /* cost of multiply per each bit set */
+ const int divide[5]; /* cost of a divide/mod
+ in QImode, HImode, SImode, DImode, TImode*/
+ int movsx; /* The cost of movsx operation. */
+ int movzx; /* The cost of movzx operation. */
+ const int large_insn; /* insns larger than this cost more */
+ const int move_ratio; /* The threshold of number of scalar
+ memory-to-memory move insns. */
+ const int clear_ratio; /* The threshold of number of scalar
+ memory clearing insns. */
+ const int int_load[3]; /* cost of loading integer registers
+ in QImode, HImode and SImode relative
+ to reg-reg move (2). */
+ const int int_store[3]; /* cost of storing integer register
+ in QImode, HImode and SImode */
+ const int sse_load[5]; /* cost of loading SSE register
+ in 32bit, 64bit, 128bit, 256bit and 512bit */
+ const int sse_store[5]; /* cost of storing SSE register
+ in 32bit, 64bit, 128bit, 256bit and 512bit */
+ const int sse_unaligned_load[5];/* cost of unaligned load. */
+ const int sse_unaligned_store[5];/* cost of unaligned store. */
+ const int xmm_move, ymm_move, /* cost of moving XMM and YMM register. */
+ zmm_move;
+ const int sse_to_integer; /* cost of moving SSE register to integer. */
+ const int gather_static, gather_per_elt; /* Cost of gather load is computed
+ as static + per_item * nelts. */
+ const int scatter_static, scatter_per_elt; /* Cost of gather store is
+ computed as static + per_item * nelts. */
+ const int l1_cache_size; /* size of l1 cache, in kilobytes. */
+ const int l2_cache_size; /* size of l2 cache, in kilobytes. */
+ const int prefetch_block; /* bytes moved to cache for prefetch. */
+ const int simultaneous_prefetches; /* number of parallel prefetch
+ operations. */
+ const int branch_cost; /* Default value for BRANCH_COST. */
+ const int fadd; /* cost of FADD and FSUB instructions. */
+ const int fmul; /* cost of FMUL instruction. */
+ const int fdiv; /* cost of FDIV instruction. */
+ const int fabs; /* cost of FABS instruction. */
+ const int fchs; /* cost of FCHS instruction. */
+ const int fsqrt; /* cost of FSQRT instruction. */
+ /* Specify what algorithm
+ to use for stringops on unknown size. */
+ const int sse_op; /* cost of cheap SSE instruction. */
+ const int addss; /* cost of ADDSS/SD SUBSS/SD instructions. */
+ const int mulss; /* cost of MULSS instructions. */
+ const int mulsd; /* cost of MULSD instructions. */
+ const int fmass; /* cost of FMASS instructions. */
+ const int fmasd; /* cost of FMASD instructions. */
+ const int divss; /* cost of DIVSS instructions. */
+ const int divsd; /* cost of DIVSD instructions. */
+ const int sqrtss; /* cost of SQRTSS instructions. */
+ const int sqrtsd; /* cost of SQRTSD instructions. */
+ const int reassoc_int, reassoc_fp, reassoc_vec_int, reassoc_vec_fp;
+ /* Specify reassociation width for integer,
+ fp, vector integer and vector fp
+ operations. Generally should correspond
+ to number of instructions executed in
+ parallel. See also
+ ix86_reassociation_width. */
+ struct stringop_algs *memcpy, *memset;
+ const int cond_taken_branch_cost; /* Cost of taken branch for vectorizer
+ cost model. */
+ const int cond_not_taken_branch_cost;/* Cost of not taken branch for
+ vectorizer cost model. */
+
+ /* The "0:0:8" label alignment specified for some processors generates
+ secondary 8-byte alignment only for those label/jump/loop targets
+ which have primary alignment. */
+ const char *const align_loop; /* Loop alignment. */
+ const char *const align_jump; /* Jump alignment. */
+ const char *const align_label; /* Label alignment. */
+ const char *const align_func; /* Function alignment. */
+};
+
+extern const struct processor_costs *ix86_cost;
+extern const struct processor_costs ix86_size_cost;
+
+#define ix86_cur_cost() \
+ (optimize_insn_for_size_p () ? &ix86_size_cost: ix86_cost)
+
+/* Macros used in the machine description to test the flags. */
+
+/* configure can arrange to change it. */
+
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT PROCESSOR_GENERIC
+#endif
+
+#ifndef TARGET_FPMATH_DEFAULT
+#define TARGET_FPMATH_DEFAULT \
+ (TARGET_64BIT && TARGET_SSE ? FPMATH_SSE : FPMATH_387)
+#endif
+
+#ifndef TARGET_FPMATH_DEFAULT_P
+#define TARGET_FPMATH_DEFAULT_P(x) \
+ (TARGET_64BIT_P(x) && TARGET_SSE_P(x) ? FPMATH_SSE : FPMATH_387)
+#endif
+
+/* If the i387 is disabled or -miamcu is used , then do not return
+ values in it. */
+#define TARGET_FLOAT_RETURNS_IN_80387 \
+ (TARGET_FLOAT_RETURNS && TARGET_80387 && !TARGET_IAMCU)
+#define TARGET_FLOAT_RETURNS_IN_80387_P(x) \
+ (TARGET_FLOAT_RETURNS_P(x) && TARGET_80387_P(x) && !TARGET_IAMCU_P(x))
+
+/* 64bit Sledgehammer mode. For libgcc2 we make sure this is a
+ compile-time constant. */
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __x86_64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#else
+#ifndef TARGET_BI_ARCH
+#undef TARGET_64BIT
+#undef TARGET_64BIT_P
+#if TARGET_64BIT_DEFAULT
+#define TARGET_64BIT 1
+#define TARGET_64BIT_P(x) 1
+#else
+#define TARGET_64BIT 0
+#define TARGET_64BIT_P(x) 0
+#endif
+#endif
+#endif
+
+#define HAS_LONG_COND_BRANCH 1
+#define HAS_LONG_UNCOND_BRANCH 1
+
+#define TARGET_CPU_P(CPU) (ix86_tune == PROCESSOR_ ## CPU)
+
+/* Feature tests against the various tunings. */
+enum ix86_tune_indices {
+#undef DEF_TUNE
+#define DEF_TUNE(tune, name, selector) tune,
+// #include "x86-tune.def"
+#undef DEF_TUNE
+X86_TUNE_LAST
+};
+
+/* Feature tests against the various architecture variations. */
+enum ix86_arch_indices {
+ X86_ARCH_CMOV,
+ X86_ARCH_CMPXCHG,
+ X86_ARCH_CMPXCHG8B,
+ X86_ARCH_XADD,
+ X86_ARCH_BSWAP,
+
+ X86_ARCH_LAST
+};
+
+extern unsigned char ix86_arch_features[X86_ARCH_LAST];
+
+#define TARGET_CMOV ix86_arch_features[X86_ARCH_CMOV]
+#define TARGET_CMPXCHG ix86_arch_features[X86_ARCH_CMPXCHG]
+#define TARGET_CMPXCHG8B ix86_arch_features[X86_ARCH_CMPXCHG8B]
+#define TARGET_XADD ix86_arch_features[X86_ARCH_XADD]
+#define TARGET_BSWAP ix86_arch_features[X86_ARCH_BSWAP]
+
+/* For sane SSE instruction set generation we need fcomi instruction.
+ It is safe to enable all CMOVE instructions. Also, RDRAND intrinsic
+ expands to a sequence that includes conditional move. */
+#define TARGET_CMOVE (TARGET_CMOV || TARGET_SSE || TARGET_RDRND)
+
+#define TARGET_FISTTP (TARGET_SSE3 && TARGET_80387)
+
+extern unsigned char ix86_prefetch_sse;
+#define TARGET_PREFETCH_SSE ix86_prefetch_sse
+
+#define ASSEMBLER_DIALECT (ix86_asm_dialect)
+
+#define TARGET_SSE_MATH ((ix86_fpmath & FPMATH_SSE) != 0)
+#define TARGET_MIX_SSE_I387 \
+ ((ix86_fpmath & (FPMATH_SSE | FPMATH_387)) == (FPMATH_SSE | FPMATH_387))
+
+#define TARGET_HARD_SF_REGS (TARGET_80387 || TARGET_MMX || TARGET_SSE)
+#define TARGET_HARD_DF_REGS (TARGET_80387 || TARGET_SSE)
+#define TARGET_HARD_XF_REGS (TARGET_80387)
+
+#define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU)
+#define TARGET_GNU2_TLS (ix86_tls_dialect == TLS_DIALECT_GNU2)
+#define TARGET_ANY_GNU_TLS (TARGET_GNU_TLS || TARGET_GNU2_TLS)
+#define TARGET_SUN_TLS 0
+
+#ifndef TARGET_64BIT_DEFAULT
+#define TARGET_64BIT_DEFAULT 0
+#endif
+#ifndef TARGET_TLS_DIRECT_SEG_REFS_DEFAULT
+#define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT 0
+#endif
+
+#define TARGET_SSP_GLOBAL_GUARD (ix86_stack_protector_guard == SSP_GLOBAL)
+#define TARGET_SSP_TLS_GUARD (ix86_stack_protector_guard == SSP_TLS)
+
+/* Fence to use after loop using storent. */
+
+extern GTY(()) tree x86_mfence;
+#define FENCE_FOLLOWING_MOVNT x86_mfence
+
+/* Once GDB has been enhanced to deal with functions without frame
+ pointers, we can change this to allow for elimination of
+ the frame pointer in leaf functions. */
+#define TARGET_DEFAULT 0
+
+/* Extra bits to force. */
+#define TARGET_SUBTARGET_DEFAULT 0
+#define TARGET_SUBTARGET_ISA_DEFAULT 0
+
+/* Extra bits to force on w/ 32-bit mode. */
+#define TARGET_SUBTARGET32_DEFAULT 0
+#define TARGET_SUBTARGET32_ISA_DEFAULT 0
+
+/* Extra bits to force on w/ 64-bit mode. */
+#define TARGET_SUBTARGET64_DEFAULT 0
+/* Enable MMX, SSE and SSE2 by default. */
+#define TARGET_SUBTARGET64_ISA_DEFAULT \
+ (OPTION_MASK_ISA_MMX | OPTION_MASK_ISA_SSE | OPTION_MASK_ISA_SSE2)
+
+/* Replace MACH-O, ifdefs by in-line tests, where possible.
+ (a) Macros defined in config/i386/darwin.h */
+#define TARGET_MACHO 0
+#define TARGET_MACHO_SYMBOL_STUBS 0
+#define MACHOPIC_ATT_STUB 0
+/* (b) Macros defined in config/darwin.h */
+#define MACHO_DYNAMIC_NO_PIC_P 0
+#define MACHOPIC_INDIRECT 0
+#define MACHOPIC_PURE 0
+
+/* For the RDOS */
+#define TARGET_RDOS 0
+
+/* For the Windows 64-bit ABI. */
+#define TARGET_64BIT_MS_ABI (TARGET_64BIT && ix86_cfun_abi () == MS_ABI)
+
+/* For the Windows 32-bit ABI. */
+#define TARGET_32BIT_MS_ABI (!TARGET_64BIT && ix86_cfun_abi () == MS_ABI)
+
+/* This is re-defined by cygming.h. */
+#define TARGET_SEH 0
+
+/* The default abi used by target. */
+#define DEFAULT_ABI SYSV_ABI
+
+/* The default TLS segment register used by target. */
+#define DEFAULT_TLS_SEG_REG \
+ (TARGET_64BIT ? ADDR_SPACE_SEG_FS : ADDR_SPACE_SEG_GS)
+
+/* Subtargets may reset this to 1 in order to enable 96-bit long double
+ with the rounding mode forced to 53 bits. */
+#define TARGET_96_ROUND_53_LONG_DOUBLE 0
+
+#ifndef SUBTARGET_DRIVER_SELF_SPECS
+# define SUBTARGET_DRIVER_SELF_SPECS ""
+#endif
+
+#define DRIVER_SELF_SPECS SUBTARGET_DRIVER_SELF_SPECS
+
+/* -march=native handling only makes sense with compiler running on
+ an x86 or x86_64 chip. If changing this condition, also change
+ the condition in driver-i386.cc. */
+#if defined(__i386__) || defined(__x86_64__)
+/* In driver-i386.cc. */
+extern const char *host_detect_local_cpu (int argc, const char **argv);
+#define EXTRA_SPEC_FUNCTIONS \
+ { "local_cpu_detect", host_detect_local_cpu },
+#define HAVE_LOCAL_CPU_DETECT
+#endif
+
+#if TARGET_64BIT_DEFAULT
+#define OPT_ARCH64 "!m32"
+#define OPT_ARCH32 "m32"
+#else
+#define OPT_ARCH64 "m64|mx32"
+#define OPT_ARCH32 "m64|mx32:;"
+#endif
+
+/* Specs for the compiler proper */
+
+#ifndef CC1_CPU_SPEC
+#define CC1_CPU_SPEC_1 ""
+
+#ifndef HAVE_LOCAL_CPU_DETECT
+#define CC1_CPU_SPEC CC1_CPU_SPEC_1
+#else
+#endif
+#endif
+
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() ix86_target_macros ()
+
+/* 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
+
+/* This macro defines names of additional specifications to put in the
+ specs that can be used in various specifications like CC1_SPEC. Its
+ definition is an initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ specification name, and a string constant that used by the GCC driver
+ program.
+
+ Do not define this macro if it does not need to do anything. */
+
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
+#endif
+
+/* Whether to allow x87 floating-point arithmetic on MODE (one of
+ SFmode, DFmode and XFmode) in the current excess precision
+ configuration. */
+#define X87_ENABLE_ARITH(MODE) \
+ (ix86_unsafe_math_optimizations \
+ || ix86_excess_precision == EXCESS_PRECISION_FAST \
+ || (MODE) == XFmode)
+
+/* Likewise, whether to allow direct conversions from integer mode
+ IMODE (HImode, SImode or DImode) to MODE. */
+#define X87_ENABLE_FLOAT(MODE, IMODE) \
+ (ix86_unsafe_math_optimizations \
+ || ix86_excess_precision == EXCESS_PRECISION_FAST \
+ || (MODE) == XFmode \
+ || ((MODE) == DFmode && (IMODE) == SImode) \
+ || (IMODE) == HImode)
+
+/* target machine storage layout */
+
+#define SHORT_TYPE_SIZE 16
+#define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
+#define POINTER_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
+#define LONG_LONG_TYPE_SIZE 64
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE \
+ (TARGET_LONG_DOUBLE_64 ? 64 : (TARGET_LONG_DOUBLE_128 ? 128 : 80))
+
+#define WIDEST_HARDWARE_FP_SIZE 80
+
+#if defined (TARGET_BI_ARCH) || TARGET_64BIT_DEFAULT
+#define MAX_BITS_PER_WORD 64
+#else
+#define MAX_BITS_PER_WORD 32
+#endif
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is true on the 80386. */
+
+#define BITS_BIG_ENDIAN 0
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* That is not true on the 80386. */
+#define BYTES_BIG_ENDIAN 0
+
+/* Define this if most significant word of a multiword number is the lowest
+ numbered. */
+/* Not true for 80386 */
+#define WORDS_BIG_ENDIAN 0
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
+
+#ifndef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD 4
+#endif
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY BITS_PER_WORD
+
+/* Boundary (in *bits*) on which stack pointer should be aligned. */
+#define STACK_BOUNDARY (TARGET_64BIT_MS_ABI ? 128 : BITS_PER_WORD)
+
+/* Stack boundary of the main function guaranteed by OS. */
+#define MAIN_STACK_BOUNDARY (TARGET_64BIT ? 128 : 32)
+
+/* Minimum stack boundary. */
+#define MIN_STACK_BOUNDARY BITS_PER_WORD
+
+/* Boundary (in *bits*) on which the stack pointer prefers to be
+ aligned; the compiler cannot rely on having this alignment. */
+#define PREFERRED_STACK_BOUNDARY ix86_preferred_stack_boundary
+
+/* It should be MIN_STACK_BOUNDARY. But we set it to 128 bits for
+ both 32bit and 64bit, to support codes that need 128 bit stack
+ alignment for SSE instructions, but can't realign the stack. */
+#define PREFERRED_STACK_BOUNDARY_DEFAULT \
+ (TARGET_IAMCU ? MIN_STACK_BOUNDARY : 128)
+
+/* 1 if -mstackrealign should be turned on by default. It will
+ generate an alternate prologue and epilogue that realigns the
+ runtime stack if nessary. This supports mixing codes that keep a
+ 4-byte aligned stack, as specified by i386 psABI, with codes that
+ need a 16-byte aligned stack, as required by SSE instructions. */
+#define STACK_REALIGN_DEFAULT 0
+
+/* Boundary (in *bits*) on which the incoming stack is aligned. */
+#define INCOMING_STACK_BOUNDARY ix86_incoming_stack_boundary
+
+/* According to Windows x64 software convention, the maximum stack allocatable
+ in the prologue is 4G - 8 bytes. Furthermore, there is a limited set of
+ instructions allowed to adjust the stack pointer in the epilog, forcing the
+ use of frame pointer for frames larger than 2 GB. This theorical limit
+ is reduced by 256, an over-estimated upper bound for the stack use by the
+ prologue.
+ We define only one threshold for both the prolog and the epilog. When the
+ frame size is larger than this threshold, we allocate the area to save SSE
+ regs, then save them, and then allocate the remaining. There is no SEH
+ unwind info for this later allocation. */
+#define SEH_MAX_FRAME_SIZE ((2U << 30) - 256)
+
+/* Target OS keeps a vector-aligned (128-bit, 16-byte) stack. This is
+ mandatory for the 64-bit ABI, and may or may not be true for other
+ operating systems. */
+#define TARGET_KEEPS_VECTOR_ALIGNED_STACK TARGET_64BIT
+
+/* Minimum allocation boundary for the code of a function. */
+#define FUNCTION_BOUNDARY 8
+
+/* C++ stores the virtual bit in the lowest bit of function pointers. */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_pfn
+
+/* Minimum size in bits of the largest boundary to which any
+ and all fundamental data types supported by the hardware
+ might need to be aligned. No data type wants to be aligned
+ rounder than this.
+
+ Pentium+ prefers DFmode values to be aligned to 64 bit boundary
+ and Pentium Pro XFmode values at 128 bit boundaries.
+
+ When increasing the maximum, also update
+ TARGET_ABSOLUTE_BIGGEST_ALIGNMENT. */
+
+#define BIGGEST_ALIGNMENT \
+ (TARGET_IAMCU ? 32 : (TARGET_AVX512F ? 512 : (TARGET_AVX ? 256 : 128)))
+
+/* Maximum stack alignment. */
+#define MAX_STACK_ALIGNMENT MAX_OFILE_ALIGNMENT
+
+/* Alignment value for attribute ((aligned)). It is a constant since
+ it is the part of the ABI. We shouldn't change it with -mavx. */
+#define ATTRIBUTE_ALIGNED_VALUE (TARGET_IAMCU ? 32 : 128)
+
+/* Decide whether a variable of mode MODE should be 128 bit aligned. */
+#define ALIGN_MODE_128(MODE) \
+ ((MODE) == XFmode || SSE_REG_MODE_P (MODE))
+
+/* The published ABIs say that doubles should be aligned on word
+ boundaries, so lower the alignment for structure fields unless
+ -malign-double is set. */
+
+/* ??? Blah -- this macro is used directly by libobjc. Since it
+ supports no vector modes, cut out the complexity and fall back
+ on BIGGEST_FIELD_ALIGNMENT. */
+#ifdef IN_TARGET_LIBS
+#ifdef __x86_64__
+#define BIGGEST_FIELD_ALIGNMENT 128
+#else
+#define BIGGEST_FIELD_ALIGNMENT 32
+#endif
+#else
+#define ADJUST_FIELD_ALIGN(FIELD, TYPE, COMPUTED) \
+ x86_field_alignment ((TYPE), (COMPUTED))
+#endif
+
+/* If defined, a C expression to compute the alignment for a static
+ variable. TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. Another is to
+ cause character arrays to be word-aligned so that `strcpy' calls
+ that copy constants to character arrays can be done inline. */
+
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ ix86_data_alignment ((TYPE), (ALIGN), true)
+
+/* Similar to DATA_ALIGNMENT, but for the cases where the ABI mandates
+ some alignment increase, instead of optimization only purposes. E.g.
+ AMD x86-64 psABI says that variables with array type larger than 15 bytes
+ must be aligned to 16 byte boundaries.
+
+ If this macro is not defined, then ALIGN is used. */
+
+#define DATA_ABI_ALIGNMENT(TYPE, ALIGN) \
+ ix86_data_alignment ((TYPE), (ALIGN), false)
+
+/* If defined, a C expression to compute the alignment for a local
+ variable. TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. */
+
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+ ix86_local_alignment ((TYPE), VOIDmode, (ALIGN))
+
+/* If defined, a C expression to compute the alignment for stack slot.
+ TYPE is the data type, MODE is the widest mode available, and ALIGN
+ is the alignment that the slot would ordinarily have. The value of
+ this macro is used instead of that alignment to align the slot.
+
+ If this macro is not defined, then ALIGN is used when TYPE is NULL,
+ Otherwise, LOCAL_ALIGNMENT will be used.
+
+ One use of this macro is to set alignment of stack slot to the
+ maximum alignment of all possible modes which the slot may have. */
+
+#define STACK_SLOT_ALIGNMENT(TYPE, MODE, ALIGN) \
+ ix86_local_alignment ((TYPE), (MODE), (ALIGN))
+
+/* If defined, a C expression to compute the alignment for a local
+ variable DECL.
+
+ If this macro is not defined, then
+ LOCAL_ALIGNMENT (TREE_TYPE (DECL), DECL_ALIGN (DECL)) will be used.
+
+ One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. */
+
+#define LOCAL_DECL_ALIGNMENT(DECL) \
+ ix86_local_alignment ((DECL), VOIDmode, DECL_ALIGN (DECL))
+
+/* If defined, a C expression to compute the minimum required alignment
+ for dynamic stack realignment purposes for EXP (a TYPE or DECL),
+ MODE, assuming normal alignment ALIGN.
+
+ If this macro is not defined, then (ALIGN) will be used. */
+
+#define MINIMUM_ALIGNMENT(EXP, MODE, ALIGN) \
+ ix86_minimum_alignment ((EXP), (MODE), (ALIGN))
+
+
+/* Set this nonzero if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT 0
+
+/* If bit field type is int, don't let it cross an int,
+ and give entire struct the alignment of an int. */
+/* Required on the 386 since it doesn't have bit-field insns. */
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* Standard register usage. */
+
+/* This processor has special stack-like registers. See reg-stack.cc
+ for details. */
+
+#define STACK_REGS
+
+#define IS_STACK_MODE(MODE) \
+ (X87_FLOAT_MODE_P (MODE) \
+ && (!(SSE_FLOAT_MODE_P (MODE) && TARGET_SSE_MATH) \
+ || TARGET_MIX_SSE_I387))
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers.
+
+ In the 80386 we give the 8 general purpose registers the numbers 0-7.
+ We number the floating point registers 8-15.
+ Note that registers 0-7 can be accessed as a short or int,
+ while only 0-3 may be used with byte `mov' instructions.
+
+ Reg 16 does not correspond to any hardware register, but instead
+ appears in the RTL as an argument pointer prior to reload, and is
+ eliminated during reloading in favor of either the stack or frame
+ pointer. */
+
+#define FIRST_PSEUDO_REGISTER FIRST_PSEUDO_REG
+
+/* Number of hardware registers that go into the DWARF-2 unwind info.
+ If not defined, equals FIRST_PSEUDO_REGISTER. */
+
+#define DWARF_FRAME_REGISTERS 17
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator.
+ On the 80386, the stack pointer is such, as is the arg pointer.
+
+ REX registers are disabled for 32bit targets in
+ TARGET_CONDITIONAL_REGISTER_USAGE. */
+
+#define FIXED_REGISTERS \
+/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/ \
+{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
+/*arg,flags,fpsr,frame*/ \
+ 1, 1, 1, 1, \
+/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/* mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/* r8, r9, r10, r11, r12, r13, r14, r15*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/*xmm16,xmm17,xmm18,xmm19,xmm20,xmm21,xmm22,xmm23*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+/* k0, k1, k2, k3, k4, k5, k6, k7*/ \
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+
+/* 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.
+ Aside from that, you can include as many other registers as you like.
+
+ Value is set to 1 if the register is call used unconditionally.
+ Bit one is set if the register is call used on TARGET_32BIT ABI.
+ Bit two is set if the register is call used on TARGET_64BIT ABI.
+ Bit three is set if the register is call used on TARGET_64BIT_MS_ABI.
+
+ Proper values are computed in TARGET_CONDITIONAL_REGISTER_USAGE. */
+
+#define CALL_USED_REGISTERS_MASK(IS_64BIT_MS_ABI) \
+ ((IS_64BIT_MS_ABI) ? (1 << 3) : TARGET_64BIT ? (1 << 2) : (1 << 1))
+
+#define CALL_USED_REGISTERS \
+/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7*/ \
+{ 1, 1, 1, 0, 4, 4, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+/*arg,flags,fpsr,frame*/ \
+ 1, 1, 1, 1, \
+/*xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7*/ \
+ 1, 1, 1, 1, 1, 1, 6, 6, \
+/* mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7*/ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+/* r8, r9, r10, r11, r12, r13, r14, r15*/ \
+ 1, 1, 1, 1, 2, 2, 2, 2, \
+/*xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15*/ \
+ 6, 6, 6, 6, 6, 6, 6, 6, \
+/*xmm16,xmm17,xmm18,xmm19,xmm20,xmm21,xmm22,xmm23*/ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+/*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* k0, k1, k2, k3, k4, k5, k6, k7*/ \
+ 1, 1, 1, 1, 1, 1, 1, 1 }
+
+/* Order in which to allocate registers. Each register must be
+ listed once, even those in FIXED_REGISTERS. List frame pointer
+ late and fixed registers last. Note that, in general, we prefer
+ registers listed in CALL_USED_REGISTERS, keeping the others
+ available for storage of persistent values.
+
+ The ADJUST_REG_ALLOC_ORDER actually overwrite the order,
+ so this is just empty initializer for array. */
+
+#define REG_ALLOC_ORDER \
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75 }
+
+/* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order
+ to be rearranged based on a particular function. When using sse math,
+ we want to allocate SSE before x87 registers and vice versa. */
+
+#define ADJUST_REG_ALLOC_ORDER x86_order_regs_for_local_alloc ()
+
+
+#define OVERRIDE_ABI_FORMAT(FNDECL) ix86_call_abi_override (FNDECL)
+
+#define HARD_REGNO_NREGS_HAS_PADDING(REGNO, MODE) \
+ (TARGET_128BIT_LONG_DOUBLE && !TARGET_64BIT \
+ && GENERAL_REGNO_P (REGNO) \
+ && ((MODE) == XFmode || (MODE) == XCmode))
+
+#define HARD_REGNO_NREGS_WITH_PADDING(REGNO, MODE) ((MODE) == XFmode ? 4 : 8)
+
+#define REGMODE_NATURAL_SIZE(MODE) ix86_regmode_natural_size (MODE)
+
+#define VALID_AVX256_REG_MODE(MODE) \
+ ((MODE) == V32QImode || (MODE) == V16HImode || (MODE) == V8SImode \
+ || (MODE) == V4DImode || (MODE) == V2TImode || (MODE) == V8SFmode \
+ || (MODE) == V4DFmode || (MODE) == V16HFmode)
+
+#define VALID_AVX256_REG_OR_OI_MODE(MODE) \
+ (VALID_AVX256_REG_MODE (MODE) || (MODE) == OImode)
+
+#define VALID_AVX512F_SCALAR_MODE(MODE) \
+ ((MODE) == DImode || (MODE) == DFmode || (MODE) == SImode \
+ || (MODE) == SFmode)
+
+#define VALID_AVX512FP16_SCALAR_MODE(MODE) \
+ ((MODE) == HImode || (MODE) == HFmode)
+
+#define VALID_AVX512F_REG_MODE(MODE) \
+ ((MODE) == V8DImode || (MODE) == V8DFmode || (MODE) == V64QImode \
+ || (MODE) == V16SImode || (MODE) == V16SFmode || (MODE) == V32HImode \
+ || (MODE) == V4TImode || (MODE) == V32HFmode)
+
+#define VALID_AVX512F_REG_OR_XI_MODE(MODE) \
+ (VALID_AVX512F_REG_MODE (MODE) || (MODE) == XImode)
+
+#define VALID_AVX512VL_128_REG_MODE(MODE) \
+ ((MODE) == V2DImode || (MODE) == V2DFmode || (MODE) == V16QImode \
+ || (MODE) == V4SImode || (MODE) == V4SFmode || (MODE) == V8HImode \
+ || (MODE) == TFmode || (MODE) == V1TImode || (MODE) == V8HFmode \
+ || (MODE) == TImode)
+
+#define VALID_AVX512FP16_REG_MODE(MODE) \
+ ((MODE) == V8HFmode || (MODE) == V16HFmode || (MODE) == V32HFmode \
+ || (MODE) == V2HFmode)
+
+#define VALID_SSE2_REG_MODE(MODE) \
+ ((MODE) == V16QImode || (MODE) == V8HImode || (MODE) == V2DFmode \
+ || (MODE) == V8HFmode || (MODE) == V4HFmode || (MODE) == V2HFmode \
+ || (MODE) == V4QImode || (MODE) == V2HImode || (MODE) == V1SImode \
+ || (MODE) == V2DImode || (MODE) == V2QImode || (MODE) == DFmode \
+ || (MODE) == HFmode)
+
+#define VALID_SSE_REG_MODE(MODE) \
+ ((MODE) == V1TImode || (MODE) == TImode \
+ || (MODE) == V4SFmode || (MODE) == V4SImode \
+ || (MODE) == SFmode || (MODE) == TFmode || (MODE) == TDmode)
+
+#define VALID_MMX_REG_MODE_3DNOW(MODE) \
+ ((MODE) == V2SFmode || (MODE) == SFmode)
+
+/* To match ia32 psABI, V4HFmode should be added here. */
+#define VALID_MMX_REG_MODE(MODE) \
+ ((MODE) == V1DImode || (MODE) == DImode \
+ || (MODE) == V2SImode || (MODE) == SImode \
+ || (MODE) == V4HImode || (MODE) == V8QImode \
+ || (MODE) == V4HFmode)
+
+#define VALID_MASK_REG_MODE(MODE) ((MODE) == HImode || (MODE) == QImode)
+
+#define VALID_MASK_AVX512BW_MODE(MODE) ((MODE) == SImode || (MODE) == DImode)
+
+#define VALID_FP_MODE_P(MODE) \
+ ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode \
+ || (MODE) == SCmode || (MODE) == DCmode || (MODE) == XCmode)
+
+#define VALID_INT_MODE_P(MODE) \
+ ((MODE) == QImode || (MODE) == HImode \
+ || (MODE) == SImode || (MODE) == DImode \
+ || (MODE) == CQImode || (MODE) == CHImode \
+ || (MODE) == CSImode || (MODE) == CDImode \
+ || (MODE) == SDmode || (MODE) == DDmode \
+ || (MODE) == HFmode || (MODE) == HCmode \
+ || (MODE) == V2HImode || (MODE) == V2HFmode \
+ || (MODE) == V1SImode || (MODE) == V4QImode || (MODE) == V2QImode \
+ || (TARGET_64BIT \
+ && ((MODE) == TImode || (MODE) == CTImode \
+ || (MODE) == TFmode || (MODE) == TCmode \
+ || (MODE) == V8QImode || (MODE) == V4HImode \
+ || (MODE) == V2SImode || (MODE) == TDmode)))
+
+/* Return true for modes passed in SSE registers. */
+#define SSE_REG_MODE_P(MODE) \
+ ((MODE) == V1TImode || (MODE) == TImode || (MODE) == V16QImode \
+ || (MODE) == TFmode || (MODE) == V8HImode || (MODE) == V2DFmode \
+ || (MODE) == V2DImode || (MODE) == V4SFmode || (MODE) == V4SImode \
+ || (MODE) == V32QImode || (MODE) == V16HImode || (MODE) == V8SImode \
+ || (MODE) == V4DImode || (MODE) == V8SFmode || (MODE) == V4DFmode \
+ || (MODE) == V2TImode || (MODE) == V8DImode || (MODE) == V64QImode \
+ || (MODE) == V16SImode || (MODE) == V32HImode || (MODE) == V8DFmode \
+ || (MODE) == V16SFmode || (MODE) == V32HFmode || (MODE) == V16HFmode \
+ || (MODE) == V8HFmode)
+
+#define X87_FLOAT_MODE_P(MODE) \
+ (TARGET_80387 && ((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode))
+
+#define SSE_FLOAT_MODE_P(MODE) \
+ ((TARGET_SSE && (MODE) == SFmode) || (TARGET_SSE2 && (MODE) == DFmode))
+
+#define SSE_FLOAT_MODE_SSEMATH_OR_HF_P(MODE) \
+ ((SSE_FLOAT_MODE_P (MODE) && TARGET_SSE_MATH) \
+ || (TARGET_AVX512FP16 && (MODE) == HFmode))
+
+#define FMA4_VEC_FLOAT_MODE_P(MODE) \
+ (TARGET_FMA4 && ((MODE) == V4SFmode || (MODE) == V2DFmode \
+ || (MODE) == V8SFmode || (MODE) == V4DFmode))
+
+#define VALID_BCST_MODE_P(MODE) \
+ ((MODE) == SFmode || (MODE) == DFmode \
+ || (MODE) == SImode || (MODE) == DImode \
+ || (MODE) == HFmode)
+
+/* It is possible to write patterns to move flags; but until someone
+ does it, */
+#define AVOID_CCMODE_COPIES
+
+/* Specify the modes required to caller save a given hard regno.
+ We do this on i386 to prevent flags from being saved at all.
+
+ Kill any attempts to combine saving of modes. */
+
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+ (CC_REGNO_P (REGNO) ? VOIDmode \
+ : (MODE) == VOIDmode && (NREGS) != 1 ? VOIDmode \
+ : (MODE) == VOIDmode ? choose_hard_reg_mode ((REGNO), (NREGS), NULL) \
+ : (MODE) == HImode && !((GENERAL_REGNO_P (REGNO) \
+ && TARGET_PARTIAL_REG_STALL) \
+ || MASK_REGNO_P (REGNO)) ? SImode \
+ : (MODE) == QImode && !(ANY_QI_REGNO_P (REGNO) \
+ || MASK_REGNO_P (REGNO)) ? SImode \
+ : (MODE))
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* on the 386 the pc register is %eip, and is not usable as a general
+ register. The ordinary mov instructions won't work */
+/* #define PC_REGNUM */
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM ARGP_REG
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM SP_REG
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM FRAME_REG
+#define HARD_FRAME_POINTER_REGNUM BP_REG
+
+#define FIRST_INT_REG AX_REG
+#define LAST_INT_REG SP_REG
+
+#define FIRST_QI_REG AX_REG
+#define LAST_QI_REG BX_REG
+
+/* First & last stack-like regs */
+#define FIRST_STACK_REG ST0_REG
+#define LAST_STACK_REG ST7_REG
+
+#define FIRST_SSE_REG XMM0_REG
+#define LAST_SSE_REG XMM7_REG
+
+#define FIRST_MMX_REG MM0_REG
+#define LAST_MMX_REG MM7_REG
+
+#define FIRST_REX_INT_REG R8_REG
+#define LAST_REX_INT_REG R15_REG
+
+#define FIRST_REX_SSE_REG XMM8_REG
+#define LAST_REX_SSE_REG XMM15_REG
+
+#define FIRST_EXT_REX_SSE_REG XMM16_REG
+#define LAST_EXT_REX_SSE_REG XMM31_REG
+
+#define FIRST_MASK_REG MASK0_REG
+#define LAST_MASK_REG MASK7_REG
+
+/* Override this in other tm.h files to cope with various OS lossage
+ requiring a frame pointer. */
+#ifndef SUBTARGET_FRAME_POINTER_REQUIRED
+#define SUBTARGET_FRAME_POINTER_REQUIRED 0
+#endif
+
+/* Define the shadow offset for asan. Other OS's can override in the
+ respective tm.h files. */
+#ifndef SUBTARGET_SHADOW_OFFSET
+#define SUBTARGET_SHADOW_OFFSET \
+ (TARGET_LP64 ? HOST_WIDE_INT_C (0x7fff8000) : HOST_WIDE_INT_1 << 29)
+#endif
+
+/* Make sure we can access arbitrary call frames. */
+#define SETUP_FRAME_ADDRESSES() ix86_setup_frame_addresses ()
+
+/* Register to hold the addressing base for position independent
+ code access to data items. We don't use PIC pointer for 64bit
+ mode. Define the regnum to dummy value to prevent gcc from
+ pessimizing code dealing with EBX.
+
+ To avoid clobbering a call-saved register unnecessarily, we renumber
+ the pic register when possible. The change is visible after the
+ prologue has been emitted. */
+
+#define REAL_PIC_OFFSET_TABLE_REGNUM (TARGET_64BIT ? R15_REG : BX_REG)
+
+#define PIC_OFFSET_TABLE_REGNUM \
+ (ix86_use_pseudo_pic_reg () \
+ ? (pic_offset_table_rtx \
+ ? INVALID_REGNUM \
+ : REAL_PIC_OFFSET_TABLE_REGNUM) \
+ : INVALID_REGNUM)
+
+#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
+
+/* This is overridden by <cygwin.h>. */
+#define MS_AGGREGATE_RETURN 0
+
+#define KEEP_AGGREGATE_RETURN_POINTER 0
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class. This is why CLOBBERED_REGS class
+ is listed early, even though in 64-bit mode it contains more
+ registers than just %eax, %ecx, %edx.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union.
+
+ The flags and fpsr registers are in no class. */
+
+enum reg_class
+{
+ NO_REGS,
+ AREG, DREG, CREG, BREG, SIREG, DIREG,
+ AD_REGS, /* %eax/%edx for DImode */
+ CLOBBERED_REGS, /* call-clobbered integer registers */
+ Q_REGS, /* %eax %ebx %ecx %edx */
+ NON_Q_REGS, /* %esi %edi %ebp %esp */
+ TLS_GOTBASE_REGS, /* %ebx %ecx %edx %esi %edi %ebp */
+ INDEX_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp */
+ LEGACY_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */
+ GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp
+ %r8 %r9 %r10 %r11 %r12 %r13 %r14 %r15 */
+ FP_TOP_REG, FP_SECOND_REG, /* %st(0) %st(1) */
+ FLOAT_REGS,
+ SSE_FIRST_REG,
+ NO_REX_SSE_REGS,
+ SSE_REGS,
+ ALL_SSE_REGS,
+ MMX_REGS,
+ FLOAT_SSE_REGS,
+ FLOAT_INT_REGS,
+ INT_SSE_REGS,
+ FLOAT_INT_SSE_REGS,
+ MASK_REGS,
+ ALL_MASK_REGS,
+ INT_MASK_REGS,
+ ALL_REGS,
+ LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
+
+#define INTEGER_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), GENERAL_REGS)
+#define FLOAT_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), FLOAT_REGS)
+#define SSE_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), ALL_SSE_REGS)
+#define INT_SSE_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), INT_SSE_REGS)
+#define MMX_CLASS_P(CLASS) \
+ ((CLASS) == MMX_REGS)
+#define MASK_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), ALL_MASK_REGS)
+#define MAYBE_INTEGER_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), GENERAL_REGS)
+#define MAYBE_FLOAT_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), FLOAT_REGS)
+#define MAYBE_SSE_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), ALL_SSE_REGS)
+#define MAYBE_MMX_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), MMX_REGS)
+#define MAYBE_MASK_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), ALL_MASK_REGS)
+
+#define Q_CLASS_P(CLASS) \
+ reg_class_subset_p ((CLASS), Q_REGS)
+
+#define MAYBE_NON_Q_CLASS_P(CLASS) \
+ reg_classes_intersect_p ((CLASS), NON_Q_REGS)
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+{ "NO_REGS", \
+ "AREG", "DREG", "CREG", "BREG", \
+ "SIREG", "DIREG", \
+ "AD_REGS", \
+ "CLOBBERED_REGS", \
+ "Q_REGS", "NON_Q_REGS", \
+ "TLS_GOTBASE_REGS", \
+ "INDEX_REGS", \
+ "LEGACY_REGS", \
+ "GENERAL_REGS", \
+ "FP_TOP_REG", "FP_SECOND_REG", \
+ "FLOAT_REGS", \
+ "SSE_FIRST_REG", \
+ "NO_REX_SSE_REGS", \
+ "SSE_REGS", \
+ "ALL_SSE_REGS", \
+ "MMX_REGS", \
+ "FLOAT_SSE_REGS", \
+ "FLOAT_INT_REGS", \
+ "INT_SSE_REGS", \
+ "FLOAT_INT_SSE_REGS", \
+ "MASK_REGS", \
+ "ALL_MASK_REGS", \
+ "INT_MASK_REGS", \
+ "ALL_REGS" }
+
+/* Define which registers fit in which classes. This is an initializer
+ for a vector of HARD_REG_SET of length N_REG_CLASSES.
+
+ Note that CLOBBERED_REGS are calculated by
+ TARGET_CONDITIONAL_REGISTER_USAGE. */
+
+#define REG_CLASS_CONTENTS \
+{ { 0x0, 0x0, 0x0 }, /* NO_REGS */ \
+ { 0x01, 0x0, 0x0 }, /* AREG */ \
+ { 0x02, 0x0, 0x0 }, /* DREG */ \
+ { 0x04, 0x0, 0x0 }, /* CREG */ \
+ { 0x08, 0x0, 0x0 }, /* BREG */ \
+ { 0x10, 0x0, 0x0 }, /* SIREG */ \
+ { 0x20, 0x0, 0x0 }, /* DIREG */ \
+ { 0x03, 0x0, 0x0 }, /* AD_REGS */ \
+ { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \
+ { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \
+ { 0x900f0, 0x0, 0x0 }, /* NON_Q_REGS */ \
+ { 0x7e, 0xff0, 0x0 }, /* TLS_GOTBASE_REGS */ \
+ { 0x7f, 0xff0, 0x0 }, /* INDEX_REGS */ \
+ { 0x900ff, 0x0, 0x0 }, /* LEGACY_REGS */ \
+ { 0x900ff, 0xff0, 0x0 }, /* GENERAL_REGS */ \
+ { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \
+ { 0x200, 0x0, 0x0 }, /* FP_SECOND_REG */ \
+ { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \
+ { 0x100000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \
+ { 0xff00000, 0x0, 0x0 }, /* NO_REX_SSE_REGS */ \
+ { 0xff00000, 0xff000, 0x0 }, /* SSE_REGS */ \
+ { 0xff00000, 0xfffff000, 0xf }, /* ALL_SSE_REGS */ \
+{ 0xf0000000, 0xf, 0x0 }, /* MMX_REGS */ \
+ { 0xff0ff00, 0xfffff000, 0xf }, /* FLOAT_SSE_REGS */ \
+ { 0x9ffff, 0xff0, 0x0 }, /* FLOAT_INT_REGS */ \
+ { 0xff900ff, 0xfffffff0, 0xf }, /* INT_SSE_REGS */ \
+ { 0xff9ffff, 0xfffffff0, 0xf }, /* FLOAT_INT_SSE_REGS */ \
+ { 0x0, 0x0, 0xfe0 }, /* MASK_REGS */ \
+ { 0x0, 0x0, 0xff0 }, /* ALL_MASK_REGS */ \
+ { 0x900ff, 0xff0, 0xff0 }, /* INT_MASK_REGS */ \
+{ 0xffffffff, 0xffffffff, 0xfff } /* ALL_REGS */ \
+}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) (regclass_map[(REGNO)])
+
+/* When this hook returns true for MODE, the compiler allows
+ registers explicitly used in the rtl to be used as spill registers
+ but prevents the compiler from extending the lifetime of these
+ registers. */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
+
+#define QI_REG_P(X) (REG_P (X) && QI_REGNO_P (REGNO (X)))
+#define QI_REGNO_P(N) IN_RANGE ((N), FIRST_QI_REG, LAST_QI_REG)
+
+#define LEGACY_INT_REG_P(X) (REG_P (X) && LEGACY_INT_REGNO_P (REGNO (X)))
+#define LEGACY_INT_REGNO_P(N) (IN_RANGE ((N), FIRST_INT_REG, LAST_INT_REG))
+
+#define REX_INT_REG_P(X) (REG_P (X) && REX_INT_REGNO_P (REGNO (X)))
+#define REX_INT_REGNO_P(N) \
+ IN_RANGE ((N), FIRST_REX_INT_REG, LAST_REX_INT_REG)
+
+#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
+#define GENERAL_REGNO_P(N) \
+ (LEGACY_INT_REGNO_P (N) || REX_INT_REGNO_P (N))
+
+#define ANY_QI_REG_P(X) (REG_P (X) && ANY_QI_REGNO_P (REGNO (X)))
+#define ANY_QI_REGNO_P(N) \
+ (TARGET_64BIT ? GENERAL_REGNO_P (N) : QI_REGNO_P (N))
+
+#define STACK_REG_P(X) (REG_P (X) && STACK_REGNO_P (REGNO (X)))
+#define STACK_REGNO_P(N) IN_RANGE ((N), FIRST_STACK_REG, LAST_STACK_REG)
+
+#define SSE_REG_P(X) (REG_P (X) && SSE_REGNO_P (REGNO (X)))
+#define SSE_REGNO_P(N) \
+ (LEGACY_SSE_REGNO_P (N) \
+ || REX_SSE_REGNO_P (N) \
+ || EXT_REX_SSE_REGNO_P (N))
+
+#define LEGACY_SSE_REGNO_P(N) \
+ IN_RANGE ((N), FIRST_SSE_REG, LAST_SSE_REG)
+
+#define REX_SSE_REGNO_P(N) \
+ IN_RANGE ((N), FIRST_REX_SSE_REG, LAST_REX_SSE_REG)
+
+#define EXT_REX_SSE_REG_P(X) (REG_P (X) && EXT_REX_SSE_REGNO_P (REGNO (X)))
+
+#define EXT_REX_SSE_REGNO_P(N) \
+ IN_RANGE ((N), FIRST_EXT_REX_SSE_REG, LAST_EXT_REX_SSE_REG)
+
+#define ANY_FP_REG_P(X) (REG_P (X) && ANY_FP_REGNO_P (REGNO (X)))
+#define ANY_FP_REGNO_P(N) (STACK_REGNO_P (N) || SSE_REGNO_P (N))
+
+#define MASK_REG_P(X) (REG_P (X) && MASK_REGNO_P (REGNO (X)))
+#define MASK_REGNO_P(N) IN_RANGE ((N), FIRST_MASK_REG, LAST_MASK_REG)
+#define MASK_PAIR_REGNO_P(N) ((((N) - FIRST_MASK_REG) & 1) == 0)
+
+#define MMX_REG_P(X) (REG_P (X) && MMX_REGNO_P (REGNO (X)))
+#define MMX_REGNO_P(N) IN_RANGE ((N), FIRST_MMX_REG, LAST_MMX_REG)
+
+#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
+#define CC_REGNO_P(X) ((X) == FLAGS_REG)
+
+#define MOD4_SSE_REG_P(X) (REG_P (X) && MOD4_SSE_REGNO_P (REGNO (X)))
+#define MOD4_SSE_REGNO_P(N) ((N) == XMM0_REG \
+ || (N) == XMM4_REG \
+ || (N) == XMM8_REG \
+ || (N) == XMM12_REG \
+ || (N) == XMM16_REG \
+ || (N) == XMM20_REG \
+ || (N) == XMM24_REG \
+ || (N) == XMM28_REG)
+
+/* First floating point reg */
+#define FIRST_FLOAT_REG FIRST_STACK_REG
+#define STACK_TOP_P(X) (REG_P (X) && REGNO (X) == FIRST_FLOAT_REG)
+
+#define GET_SSE_REGNO(N) \
+ ((N) < 8 ? FIRST_SSE_REG + (N) \
+ : (N) < 16 ? FIRST_REX_SSE_REG + (N) - 8 \
+ : FIRST_EXT_REX_SSE_REG + (N) - 16)
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS INDEX_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+#define STACK_GROWS_DOWNWARD 1
+
+/* Define this to nonzero if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+#define FRAME_GROWS_DOWNWARD 1
+
+#define PUSH_ROUNDING(BYTES) ix86_push_rounding (BYTES)
+
+/* If defined, the maximum amount of space required for outgoing arguments
+ will be computed and placed into the variable `crtl->outgoing_args_size'.
+ No space will be pushed onto the stack for each call; instead, the
+ function prologue should increase the stack frame size by this amount.
+
+ In 32bit mode enabling argument accumulation results in about 5% code size
+ growth because move instructions are less compact than push. In 64bit
+ mode the difference is less drastic but visible.
+
+ FIXME: Unlike earlier implementations, the size of unwind info seems to
+ actually grow with accumulation. Is that because accumulated args
+ unwind info became unnecesarily bloated?
+
+ With the 64-bit MS ABI, we can generate correct code with or without
+ accumulated args, but because of OUTGOING_REG_PARM_STACK_SPACE the code
+ generated without accumulated args is terrible.
+
+ If stack probes are required, the space used for large function
+ arguments on the stack must also be probed, so enable
+ -maccumulate-outgoing-args so this happens in the prologue.
+
+ We must use argument accumulation in interrupt function if stack
+ may be realigned to avoid DRAP. */
+
+#define ACCUMULATE_OUTGOING_ARGS \
+ ((TARGET_ACCUMULATE_OUTGOING_ARGS \
+ && optimize_function_for_speed_p (cfun)) \
+ || (cfun->machine->func_type != TYPE_NORMAL \
+ && crtl->stack_realign_needed) \
+ || TARGET_STACK_PROBE \
+ || TARGET_64BIT_MS_ABI \
+ || (TARGET_MACHO && crtl->profile))
+
+/* We want the stack and args grow in opposite directions, even if
+ targetm.calls.push_argument returns false. */
+#define PUSH_ARGS_REVERSED 1
+
+/* Offset of first parameter from the argument pointer register value. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Define this macro if functions should assume that stack space has been
+ allocated for arguments even when their values are passed in registers.
+
+ The value of this macro is the size, in bytes, of the area reserved for
+ arguments passed in registers for the function represented by FNDECL.
+
+ This space can be allocated by the caller, or be a part of the
+ machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
+ which. */
+#define REG_PARM_STACK_SPACE(FNDECL) ix86_reg_parm_stack_space (FNDECL)
+
+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) \
+ (TARGET_64BIT && ix86_function_type_abi (FNTYPE) == MS_ABI)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) ix86_libcall_value (MODE)
+
+/* Define the size of the result block used for communication between
+ untyped_call and untyped_return. The block contains a DImode value
+ followed by the block used by fnsave and frstor. */
+
+#define APPLY_RESULT_SIZE (8+108)
+
+/* 1 if N is a possible register number for function argument passing. */
+#define FUNCTION_ARG_REGNO_P(N) ix86_function_arg_regno_p (N)
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go. */
+
+typedef struct ix86_args {
+ int words; /* # words passed so far */
+ int nregs; /* # registers available for passing */
+ int regno; /* next available register number */
+ int fastcall; /* fastcall or thiscall calling convention
+ is used */
+ int sse_words; /* # sse words passed so far */
+ int sse_nregs; /* # sse registers available for passing */
+ int warn_avx512f; /* True when we want to warn
+ about AVX512F ABI. */
+ int warn_avx; /* True when we want to warn about AVX ABI. */
+ int warn_sse; /* True when we want to warn about SSE ABI. */
+ int warn_mmx; /* True when we want to warn about MMX ABI. */
+ int warn_empty; /* True when we want to warn about empty classes
+ passing ABI change. */
+ int sse_regno; /* next available sse register number */
+ int mmx_words; /* # mmx words passed so far */
+ int mmx_nregs; /* # mmx registers available for passing */
+ int mmx_regno; /* next available mmx register number */
+ int maybe_vaarg; /* true for calls to possibly vardic fncts. */
+ int caller; /* true if it is caller. */
+ int float_in_sse; /* Set to 1 or 2 for 32bit targets if
+ SFmode/DFmode arguments should be passed
+ in SSE registers. Otherwise 0. */
+ int stdarg; /* Set to 1 if function is stdarg. */
+ enum calling_abi call_abi; /* Set to SYSV_ABI for sysv abi. Otherwise
+ MS_ABI for ms abi. */
+ tree decl; /* Callee decl. */
+} CUMULATIVE_ARGS;
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
+ init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (FNDECL), \
+ (N_NAMED_ARGS) != -1)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ x86_function_profiler ((FILE), (LABELNO))
+
+#define MCOUNT_NAME "_mcount"
+
+#define MCOUNT_NAME_BEFORE_PROLOGUE "__fentry__"
+
+#define PROFILE_COUNT_REGISTER "edx"
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+/* Note on the 386 it might be more efficient not to define this since
+ we have to restore it ourselves from the frame pointer, in order to
+ use pop */
+
+#define EXIT_IGNORE_STACK 1
+
+/* Define this macro as a C expression that is nonzero for registers
+ used by the epilogue or the `return' pattern. */
+
+#define EPILOGUE_USES(REGNO) ix86_epilogue_uses (REGNO)
+
+/* Output assembler code for a block containing the constant parts
+ of a trampoline, leaving space for the variable parts. */
+
+/* On the 386, the trampoline contains two instructions:
+ mov #STATIC,ecx
+ jmp FUNCTION
+ The trampoline is generated entirely at runtime. The operand of JMP
+ is the address of FUNCTION relative to the instruction following the
+ JMP (which is 5 bytes long). */
+
+/* Length in units of the trampoline for entering a nested function. */
+
+#define TRAMPOLINE_SIZE (TARGET_64BIT ? 28 : 14)
+
+/* Definitions for register eliminations.
+
+ This is an array of structures. Each structure initializes one pair
+ of eliminable registers. The "from" register number is given first,
+ followed by "to". Eliminations of the same "from" register are listed
+ in order of preference.
+
+ There are two registers that can always be eliminated on the i386.
+ The frame pointer and the arg pointer can be replaced by either the
+ hard frame pointer or to the stack pointer, depending upon the
+ circumstances. The hard frame pointer is not used before reload and
+ so it is not eligible for elimination. */
+
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}} \
+
+/* Define the offset between two registers, one to be eliminated, and the other
+ its replacement, at the start of a routine. */
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ ((OFFSET) = ix86_initial_elimination_offset ((FROM), (TO)))
+
+/* Addressing modes, and classification of registers for them. */
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in reginfo.cc during register
+ allocation. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
+ ((REGNO) < STACK_POINTER_REGNUM \
+ || REX_INT_REGNO_P (REGNO) \
+ || (unsigned) reg_renumber[(REGNO)] < STACK_POINTER_REGNUM \
+ || REX_INT_REGNO_P ((unsigned) reg_renumber[(REGNO)]))
+
+#define REGNO_OK_FOR_BASE_P(REGNO) \
+ (GENERAL_REGNO_P (REGNO) \
+ || (REGNO) == ARG_POINTER_REGNUM \
+ || (REGNO) == FRAME_POINTER_REGNUM \
+ || GENERAL_REGNO_P ((unsigned) reg_renumber[(REGNO)]))
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+
+/* Non strict versions, pseudos are ok. */
+#define REG_OK_FOR_INDEX_NONSTRICT_P(X) \
+ (REGNO (X) < STACK_POINTER_REGNUM \
+ || REX_INT_REGNO_P (REGNO (X)) \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+
+#define REG_OK_FOR_BASE_NONSTRICT_P(X) \
+ (GENERAL_REGNO_P (REGNO (X)) \
+ || REGNO (X) == ARG_POINTER_REGNUM \
+ || REGNO (X) == FRAME_POINTER_REGNUM \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER)
+
+/* Strict versions, hard registers only */
+#define REG_OK_FOR_INDEX_STRICT_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
+#define REG_OK_FOR_BASE_STRICT_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+
+#ifndef REG_OK_STRICT
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P (X)
+#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_NONSTRICT_P (X)
+
+#else
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P (X)
+#define REG_OK_FOR_BASE_P(X) REG_OK_FOR_BASE_STRICT_P (X)
+#endif
+
+/* TARGET_LEGITIMATE_ADDRESS_P recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in TARGET_LEGITIMATE_ADDRESS_P,
+ except for CONSTANT_ADDRESS_P which is usually machine-independent.
+
+ See legitimize_pic_address in i386.cc for details as to what
+ constitutes a legitimate address when -fpic is used. */
+
+#define MAX_REGS_PER_ADDRESS 2
+
+#define CONSTANT_ADDRESS_P(X) constant_address_p (X)
+
+/* If defined, a C expression to determine the base term of address X.
+ This macro is used in only one place: `find_base_term' in alias.cc.
+
+ It is always safe for this macro to not be defined. It exists so
+ that alias analysis can understand machine-dependent addresses.
+
+ The typical use of this macro is to handle addresses containing
+ a label_ref or symbol_ref within an UNSPEC. */
+
+#define FIND_BASE_TERM(X) ix86_find_base_term (X)
+
+/* Nonzero if the constant value X is a legitimate general operand
+ when generating PIC code. It is given that flag_pic is on and
+ that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
+
+#define STRIP_UNARY(X) (UNARY_P (X) ? XEXP (X, 0) : X)
+
+#define SYMBOLIC_CONST(X) \
+ (GET_CODE (X) == SYMBOL_REF \
+ || GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
+
+/* Max number of args passed in registers. If this is more than 3, we will
+ have problems with ebx (register #4), since it is a caller save register and
+ is also used as the pic register in ELF. So for now, don't allow more than
+ 3 registers to be passed in registers. */
+
+/* Abi specific values for REGPARM_MAX and SSE_REGPARM_MAX */
+#define X86_64_REGPARM_MAX 6
+#define X86_64_MS_REGPARM_MAX 4
+
+#define X86_32_REGPARM_MAX 3
+
+#define REGPARM_MAX \
+ (TARGET_64BIT \
+ ? (TARGET_64BIT_MS_ABI \
+ ? X86_64_MS_REGPARM_MAX \
+ : X86_64_REGPARM_MAX) \
+ : X86_32_REGPARM_MAX)
+
+#define X86_64_SSE_REGPARM_MAX 8
+#define X86_64_MS_SSE_REGPARM_MAX 4
+
+#define X86_32_SSE_REGPARM_MAX (TARGET_SSE ? (TARGET_MACHO ? 4 : 3) : 0)
+
+#define SSE_REGPARM_MAX \
+ (TARGET_64BIT \
+ ? (TARGET_64BIT_MS_ABI \
+ ? X86_64_MS_SSE_REGPARM_MAX \
+ : X86_64_SSE_REGPARM_MAX) \
+ : X86_32_SSE_REGPARM_MAX)
+
+#define X86_32_MMX_REGPARM_MAX (TARGET_MMX ? (TARGET_MACHO ? 0 : 3) : 0)
+
+#define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : X86_32_MMX_REGPARM_MAX)
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE \
+ (!TARGET_LP64 || (flag_pic && ix86_cmodel != CM_LARGE_PIC) ? SImode : DImode)
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* The constant maximum number of bytes that a single instruction can
+ move quickly between memory and registers or between two memory
+ locations. */
+#define MAX_MOVE_MAX 64
+
+/* Max number of bytes we can move from memory to memory in one
+ reasonably fast instruction, as opposed to MOVE_MAX_PIECES which
+ is the number of bytes at a time which we can move efficiently.
+ MOVE_MAX_PIECES defaults to MOVE_MAX. */
+
+#define MOVE_MAX \
+ ((TARGET_AVX512F \
+ && (ix86_move_max == PVW_AVX512 \
+ || ix86_store_max == PVW_AVX512)) \
+ ? 64 \
+ : ((TARGET_AVX \
+ && (ix86_move_max >= PVW_AVX256 \
+ || ix86_store_max >= PVW_AVX256)) \
+ ? 32 \
+ : ((TARGET_SSE2 \
+ && TARGET_SSE_UNALIGNED_LOAD_OPTIMAL \
+ && TARGET_SSE_UNALIGNED_STORE_OPTIMAL) \
+ ? 16 : UNITS_PER_WORD)))
+
+/* STORE_MAX_PIECES is the number of bytes at a time that we can store
+ efficiently. Allow 16/32/64 bytes only if inter-unit move is enabled
+ since vec_duplicate enabled by inter-unit move is used to implement
+ store_by_pieces of 16/32/64 bytes. */
+#define STORE_MAX_PIECES \
+ (TARGET_INTER_UNIT_MOVES_TO_VEC \
+ ? ((TARGET_AVX512F && ix86_store_max == PVW_AVX512) \
+ ? 64 \
+ : ((TARGET_AVX \
+ && ix86_store_max >= PVW_AVX256) \
+ ? 32 \
+ : ((TARGET_SSE2 \
+ && TARGET_SSE_UNALIGNED_STORE_OPTIMAL) \
+ ? 16 : UNITS_PER_WORD))) \
+ : UNITS_PER_WORD)
+
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction pairs, we will do a cpymem or libcall instead.
+ Increasing the value will always make code faster, but eventually
+ incurs high cost in increased code size.
+
+ If you don't define this, a reasonable default is used. */
+
+#define MOVE_RATIO(speed) ((speed) ? ix86_cost->move_ratio : 3)
+
+/* If a clear memory operation would take CLEAR_RATIO or more simple
+ move-instruction sequences, we will do a clrmem or libcall instead. */
+
+#define CLEAR_RATIO(speed) ((speed) ? ix86_cost->clear_ratio : 2)
+
+/* Define if shifts truncate the shift count which implies one can
+ omit a sign-extension or zero-extension of a shift count.
+
+ On i386, shifts do truncate the count. But bit test instructions
+ take the modulo of the bit offset operand. */
+
+/* #define SHIFT_COUNT_TRUNCATED */
+
+/* A macro to update M and UNSIGNEDP when an object whose type is
+ TYPE and which has the specified mode and signedness is to be
+ stored in a register. This macro is only called when TYPE is a
+ scalar type.
+
+ On i386 it is sometimes useful to promote HImode and QImode
+ quantities to SImode. The choice depends on target type. */
+
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+do { \
+ if (((MODE) == HImode && TARGET_PROMOTE_HI_REGS) \
+ || ((MODE) == QImode && TARGET_PROMOTE_QI_REGS)) \
+ (MODE) = SImode; \
+} while (0)
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode)
+
+/* Supply a definition of STACK_SAVEAREA_MODE for emit_stack_save.
+ NONLOCAL needs space to save both shadow stack and stack pointers.
+
+ FIXME: We only need to save and restore stack pointer in ptr_mode.
+ But expand_builtin_setjmp_setup and expand_builtin_longjmp use Pmode
+ to save and restore stack pointer. See
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84150
+ */
+#define STACK_SAVEAREA_MODE(LEVEL) \
+ ((LEVEL) == SAVE_NONLOCAL ? (TARGET_64BIT ? TImode : DImode) : Pmode)
+
+/* Specify the machine_mode of the size increment
+ operand of an 'allocate_stack' named pattern. */
+#define STACK_SIZE_MODE Pmode
+
+/* A C expression whose value is zero if pointers that need to be extended
+ from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and
+ greater then zero if they are zero-extended and less then zero if the
+ ptr_extend instruction should be used. */
+
+#define POINTERS_EXTEND_UNSIGNED 1
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+
+/* A C expression for the cost of a branch instruction. A value of 1
+ is the default; other values are interpreted relative to that. */
+
+#define BRANCH_COST(speed_p, predictable_p) \
+ (!(speed_p) ? 2 : (predictable_p) ? 0 : ix86_branch_cost)
+
+/* An integer expression for the size in bits of the largest integer machine
+ mode that should actually be used. We allow pairs of registers. */
+#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_64BIT ? TImode : DImode)
+
+/* Define this macro as a C expression which is nonzero if accessing
+ less than a word of memory (i.e. a `char' or a `short') is no
+ faster than accessing a word of memory, i.e., if such access
+ require more than one instruction or if there is no difference in
+ cost between byte and (aligned) word loads.
+
+ When this macro is not defined, the compiler will access a field by
+ finding the smallest containing object; when it is defined, a
+ fullword load will be used if alignment permits. Unless bytes
+ accesses are faster than word accesses, using word accesses is
+ preferable since it may eliminate subsequent memory access if
+ subsequent accesses occur to other fields in the same word of the
+ structure, but to different bytes. */
+
+#define SLOW_BYTE_ACCESS 0
+
+/* Nonzero if access to memory by shorts is slow and undesirable. */
+#define SLOW_SHORT_ACCESS 0
+
+/* Define this macro if it is as good or better to call a constant
+ function address than to call an address kept in a register.
+
+ Desirable on the 386 because a CALL with a constant address is
+ faster than one with a register address. */
+
+#define NO_FUNCTION_CSE 1
+
+/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
+ return the mode to be used for the comparison.
+
+ For floating-point equality comparisons, CCFPEQmode should be used.
+ VOIDmode should be used in all other cases.
+
+ For integer comparisons against zero, reduce to CCNOmode or CCZmode if
+ possible, to allow for more combinations. */
+
+#define SELECT_CC_MODE(OP, X, Y) ix86_cc_mode ((OP), (X), (Y))
+
+/* Return nonzero if MODE implies a floating point inequality can be
+ reversed. */
+
+#define REVERSIBLE_CC_MODE(MODE) 1
+
+/* A C expression whose value is reversed condition code of the CODE for
+ comparison done in CC_MODE mode. */
+#define REVERSE_CONDITION(CODE, MODE) ix86_reverse_condition ((CODE), (MODE))
+
+
+/* Control the assembler format that we output, to the extent
+ this does not vary between assemblers. */
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+/* In order to refer to the first 8 regs as 32-bit regs, prefix an "e".
+ For non floating point regs, the following are the HImode names.
+
+ For float regs, the stack top is sometimes referred to as "%st(0)"
+ instead of just "%st". TARGET_PRINT_OPERAND handles this with the
+ "y" code. */
+
+#define HI_REGISTER_NAMES \
+{"ax","dx","cx","bx","si","di","bp","sp", \
+ "st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)", \
+ "argp", "flags", "fpsr", "frame", \
+ "xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7", \
+ "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", \
+ "xmm16", "xmm17", "xmm18", "xmm19", \
+ "xmm20", "xmm21", "xmm22", "xmm23", \
+ "xmm24", "xmm25", "xmm26", "xmm27", \
+ "xmm28", "xmm29", "xmm30", "xmm31", \
+ "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }
+
+#define REGISTER_NAMES HI_REGISTER_NAMES
+
+#define QI_REGISTER_NAMES \
+{"al", "dl", "cl", "bl", "sil", "dil", "bpl", "spl"}
+
+#define QI_HIGH_REGISTER_NAMES \
+{"ah", "dh", "ch", "bh"}
+
+/* Table of additional register names to use in user input. */
+
+#define ADDITIONAL_REGISTER_NAMES \
+{ \
+ { "eax", AX_REG }, { "edx", DX_REG }, { "ecx", CX_REG }, { "ebx", BX_REG }, \
+ { "esi", SI_REG }, { "edi", DI_REG }, { "ebp", BP_REG }, { "esp", SP_REG }, \
+ { "rax", AX_REG }, { "rdx", DX_REG }, { "rcx", CX_REG }, { "rbx", BX_REG }, \
+ { "rsi", SI_REG }, { "rdi", DI_REG }, { "rbp", BP_REG }, { "rsp", SP_REG }, \
+ { "al", AX_REG }, { "dl", DX_REG }, { "cl", CX_REG }, { "bl", BX_REG }, \
+ { "sil", SI_REG }, { "dil", DI_REG }, { "bpl", BP_REG }, { "spl", SP_REG }, \
+ { "ah", AX_REG }, { "dh", DX_REG }, { "ch", CX_REG }, { "bh", BX_REG }, \
+ { "ymm0", XMM0_REG }, { "ymm1", XMM1_REG }, { "ymm2", XMM2_REG }, { "ymm3", XMM3_REG }, \
+ { "ymm4", XMM4_REG }, { "ymm5", XMM5_REG }, { "ymm6", XMM6_REG }, { "ymm7", XMM7_REG }, \
+ { "ymm8", XMM8_REG }, { "ymm9", XMM9_REG }, { "ymm10", XMM10_REG }, { "ymm11", XMM11_REG }, \
+ { "ymm12", XMM12_REG }, { "ymm13", XMM13_REG }, { "ymm14", XMM14_REG }, { "ymm15", XMM15_REG }, \
+ { "ymm16", XMM16_REG }, { "ymm17", XMM17_REG }, { "ymm18", XMM18_REG }, { "ymm19", XMM19_REG }, \
+ { "ymm20", XMM20_REG }, { "ymm21", XMM21_REG }, { "ymm22", XMM22_REG }, { "ymm23", XMM23_REG }, \
+ { "ymm24", XMM24_REG }, { "ymm25", XMM25_REG }, { "ymm26", XMM26_REG }, { "ymm27", XMM27_REG }, \
+ { "ymm28", XMM28_REG }, { "ymm29", XMM29_REG }, { "ymm30", XMM30_REG }, { "ymm31", XMM31_REG }, \
+ { "zmm0", XMM0_REG }, { "zmm1", XMM1_REG }, { "zmm2", XMM2_REG }, { "zmm3", XMM3_REG }, \
+ { "zmm4", XMM4_REG }, { "zmm5", XMM5_REG }, { "zmm6", XMM6_REG }, { "zmm7", XMM7_REG }, \
+ { "zmm8", XMM8_REG }, { "zmm9", XMM9_REG }, { "zmm10", XMM10_REG }, { "zmm11", XMM11_REG }, \
+ { "zmm12", XMM12_REG }, { "zmm13", XMM13_REG }, { "zmm14", XMM14_REG }, { "zmm15", XMM15_REG }, \
+ { "zmm16", XMM16_REG }, { "zmm17", XMM17_REG }, { "zmm18", XMM18_REG }, { "zmm19", XMM19_REG }, \
+ { "zmm20", XMM20_REG }, { "zmm21", XMM21_REG }, { "zmm22", XMM22_REG }, { "zmm23", XMM23_REG }, \
+ { "zmm24", XMM24_REG }, { "zmm25", XMM25_REG }, { "zmm26", XMM26_REG }, { "zmm27", XMM27_REG }, \
+ { "zmm28", XMM28_REG }, { "zmm29", XMM29_REG }, { "zmm30", XMM30_REG }, { "zmm31", XMM31_REG } \
+}
+
+/* How to renumber registers for dbx and gdb. */
+
+#define DBX_REGISTER_NUMBER(N) \
+ (TARGET_64BIT ? dbx64_register_map[(N)] : dbx_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];
+
+/* Before the prologue, RA is at 0(%esp). */
+#define INCOMING_RETURN_ADDR_RTX \
+ gen_rtx_MEM (Pmode, stack_pointer_rtx)
+
+/* After the prologue, RA is at -4(AP) in the current frame. */
+#define RETURN_ADDR_RTX(COUNT, FRAME) \
+ ((COUNT) == 0 \
+ ? gen_rtx_MEM (Pmode, plus_constant (Pmode, arg_pointer_rtx, \
+ -UNITS_PER_WORD)) \
+ : gen_rtx_MEM (Pmode, plus_constant (Pmode, (FRAME), UNITS_PER_WORD)))
+
+/* PC is dbx register 8; let's use that column for RA. */
+#define DWARF_FRAME_RETURN_COLUMN (TARGET_64BIT ? 16 : 8)
+
+/* Before the prologue, there are return address and error code for
+ exception handler on the top of the frame. */
+#define INCOMING_FRAME_SP_OFFSET \
+ (cfun->machine->func_type == TYPE_EXCEPTION \
+ ? 2 * UNITS_PER_WORD : UNITS_PER_WORD)
+
+/* The value of INCOMING_FRAME_SP_OFFSET the assembler assumes in
+ .cfi_startproc. */
+#define DEFAULT_INCOMING_FRAME_SP_OFFSET UNITS_PER_WORD
+
+/* Describe how we implement __builtin_eh_return. */
+#define EH_RETURN_DATA_REGNO(N) ((N) <= DX_REG ? (N) : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, CX_REG)
+
+
+/* Select a format to encode pointers in exception handling data. CODE
+ is 0 for data, 1 for code labels, 2 for function pointers. GLOBAL is
+ true if the symbol may be affected by dynamic relocations.
+
+ ??? All x86 object file formats are capable of representing this.
+ After all, the relocation needed is the same as for the call insn.
+ Whether or not a particular assembler allows us to enter such, I
+ guess we'll have to see. */
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ asm_preferred_eh_data_format ((CODE), (GLOBAL))
+
+/* These are a couple of extensions to the formats accepted
+ by asm_fprintf:
+ %z prints out opcode suffix for word-mode instruction
+ %r prints out word-mode name for reg_names[arg] */
+#define ASM_FPRINTF_EXTENSIONS(FILE, ARGS, P) \
+ case 'z': \
+ fputc (TARGET_64BIT ? 'q' : 'l', (FILE)); \
+ break; \
+ \
+ case 'r': \
+ { \
+ unsigned int regno = va_arg ((ARGS), int); \
+ if (LEGACY_INT_REGNO_P (regno)) \
+ fputc (TARGET_64BIT ? 'r' : 'e', (FILE)); \
+ fputs (reg_names[regno], (FILE)); \
+ break; \
+ }
+
+/* This is how to output an insn to push a register on the stack. */
+
+#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) \
+ asm_fprintf ((FILE), "\tpush%z\t%%%r\n", (REGNO))
+
+/* This is how to output an insn to pop a register from the stack. */
+
+#define ASM_OUTPUT_REG_POP(FILE, REGNO) \
+ asm_fprintf ((FILE), "\tpop%z\t%%%r\n", (REGNO))
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ ix86_output_addr_vec_elt ((FILE), (VALUE))
+
+/* This is how to output an element of a case-vector that is relative. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
+ ix86_output_addr_diff_elt ((FILE), (VALUE), (REL))
+
+/* When we see %v, we will print the 'v' prefix if TARGET_AVX is true. */
+
+#define ASM_OUTPUT_AVX_PREFIX(STREAM, PTR) \
+{ \
+ if ((PTR)[0] == '%' && (PTR)[1] == 'v') \
+ (PTR) += TARGET_AVX ? 1 : 2; \
+}
+
+/* A C statement or statements which output an assembler instruction
+ opcode to the stdio stream STREAM. The macro-operand PTR is a
+ variable of type `char *' which points to the opcode name in
+ its "internal" form--the form that is written in the machine
+ description. */
+
+#define ASM_OUTPUT_OPCODE(STREAM, PTR) \
+ ASM_OUTPUT_AVX_PREFIX ((STREAM), (PTR))
+
+/* A C statement to output to the stdio stream FILE an assembler
+ command to pad the location counter to a multiple of 1<<LOG
+ bytes if it is within MAX_SKIP bytes. */
+
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+# define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ do { \
+ if ((LOG) != 0) { \
+ if ((MAX_SKIP) == 0 || (MAX_SKIP) >= (1 << (LOG)) - 1) \
+ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else \
+ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ } \
+ } while (0)
+#endif
+
+/* Write the extra assembler code needed to declare a function
+ properly. */
+
+#undef ASM_OUTPUT_FUNCTION_LABEL
+#define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \
+ ix86_asm_output_function_label ((FILE), (NAME), (DECL))
+
+/* A C statement (sans semicolon) to output a reference to SYMBOL_REF SYM.
+ If not defined, assemble_name will be used to output the name of the
+ symbol. This macro may be used to modify the way a symbol is referenced
+ depending on information encoded by TARGET_ENCODE_SECTION_INFO. */
+
+#ifndef ASM_OUTPUT_SYMBOL_REF
+#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \
+ do { \
+ const char *name \
+ = assemble_name_resolve (XSTR (x, 0)); \
+ /* In -masm=att wrap identifiers that start with $ \
+ into parens. */ \
+ if (ASSEMBLER_DIALECT == ASM_ATT \
+ && name[0] == '$' \
+ && user_label_prefix[0] == '\0') \
+ { \
+ fputc ('(', (FILE)); \
+ assemble_name_raw ((FILE), name); \
+ fputc (')', (FILE)); \
+ } \
+ else \
+ assemble_name_raw ((FILE), name); \
+ } while (0)
+#endif
+
+/* Under some conditions we need jump tables in the text section,
+ because the assembler cannot handle label differences between
+ sections. */
+
+#define JUMP_TABLES_IN_TEXT_SECTION \
+ (flag_pic && !(TARGET_64BIT || HAVE_AS_GOTOFF_IN_DATA))
+
+/* Switch to init or fini section via SECTION_OP, emit a call to FUNC,
+ and switch back. For x86 we do this only to save a few bytes that
+ would otherwise be unused in the text section. */
+#define CRT_MKSTR2(VAL) #VAL
+#define CRT_MKSTR(x) CRT_MKSTR2(x)
+
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n\t" \
+ "call " CRT_MKSTR(__USER_LABEL_PREFIX__) #FUNC "\n" \
+ TEXT_SECTION_ASM_OP);
+
+/* Default threshold for putting data in large sections
+ with x86-64 medium memory model */
+#define DEFAULT_LARGE_SECTION_THRESHOLD 65536
+
+/* Which processor to tune code generation for. These must be in sync
+ with processor_target_table in i386.cc. */
+
+enum processor_type
+{
+ PROCESSOR_GENERIC = 0,
+ PROCESSOR_I386, /* 80386 */
+ PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
+ PROCESSOR_PENTIUM,
+ PROCESSOR_LAKEMONT,
+ PROCESSOR_PENTIUMPRO,
+ PROCESSOR_PENTIUM4,
+ PROCESSOR_NOCONA,
+ PROCESSOR_CORE2,
+ PROCESSOR_NEHALEM,
+ PROCESSOR_SANDYBRIDGE,
+ PROCESSOR_HASWELL,
+ PROCESSOR_BONNELL,
+ PROCESSOR_SILVERMONT,
+ PROCESSOR_GOLDMONT,
+ PROCESSOR_GOLDMONT_PLUS,
+ PROCESSOR_TREMONT,
+ PROCESSOR_KNL,
+ PROCESSOR_KNM,
+ PROCESSOR_SKYLAKE,
+ PROCESSOR_SKYLAKE_AVX512,
+ PROCESSOR_CANNONLAKE,
+ PROCESSOR_ICELAKE_CLIENT,
+ PROCESSOR_ICELAKE_SERVER,
+ PROCESSOR_CASCADELAKE,
+ PROCESSOR_TIGERLAKE,
+ PROCESSOR_COOPERLAKE,
+ PROCESSOR_SAPPHIRERAPIDS,
+ PROCESSOR_ALDERLAKE,
+ PROCESSOR_ROCKETLAKE,
+ PROCESSOR_INTEL,
+ PROCESSOR_GEODE,
+ PROCESSOR_K6,
+ PROCESSOR_ATHLON,
+ PROCESSOR_K8,
+ PROCESSOR_AMDFAM10,
+ PROCESSOR_BDVER1,
+ PROCESSOR_BDVER2,
+ PROCESSOR_BDVER3,
+ PROCESSOR_BDVER4,
+ PROCESSOR_BTVER1,
+ PROCESSOR_BTVER2,
+ PROCESSOR_ZNVER1,
+ PROCESSOR_ZNVER2,
+ PROCESSOR_ZNVER3,
+ PROCESSOR_max
+};
+
+#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
+extern const char *const processor_names[];
+
+// sdcpp #include "wide-int-bitmask.h"
+
+enum pta_flag
+{
+#define DEF_PTA(NAME) _ ## NAME,
+// #include "i386-isa.def"
+#undef DEF_PTA
+ END_PTA
+};
+
+/* wide_int_bitmask can handle only 128 flags. */
+STATIC_ASSERT (END_PTA <= 128);
+
+#define WIDE_INT_BITMASK_FROM_NTH(N) (N < 64 ? wide_int_bitmask (0, 1ULL << N) \
+ : wide_int_bitmask (1ULL << (N - 64), 0))
+
+#define DEF_PTA(NAME) constexpr wide_int_bitmask PTA_ ## NAME \
+ = WIDE_INT_BITMASK_FROM_NTH ((pta_flag) _ ## NAME);
+// #include "i386-isa.def"
+#undef DEF_PTA
+
+#ifndef GENERATOR_FILE
+
+#include "insn-attr-common.h"
+
+// #include "common/config/i386/i386-cpuinfo.h"
+
+extern unsigned int const pta_size;
+extern unsigned int const num_arch_names;
+#endif
+
+#endif
+
+extern enum processor_type ix86_tune;
+extern enum processor_type ix86_arch;
+
+/* Size of the RED_ZONE area. */
+#define RED_ZONE_SIZE 128
+/* Reserved area of the red zone for temporaries. */
+#define RED_ZONE_RESERVE 8
+
+extern unsigned int ix86_preferred_stack_boundary;
+extern unsigned int ix86_incoming_stack_boundary;
+
+/* Smallest class containing REGNO. */
+extern enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER];
+
+enum ix86_fpcmp_strategy {
+ IX86_FPCMP_SAHF,
+ IX86_FPCMP_COMI,
+ IX86_FPCMP_ARITH
+};
+
+/* To properly truncate FP values into integers, we need to set i387 control
+ word. We can't emit proper mode switching code before reload, as spills
+ generated by reload may truncate values incorrectly, but we still can avoid
+ redundant computation of new control word by the mode switching pass.
+ The fldcw instructions are still emitted redundantly, but this is probably
+ not going to be noticeable problem, as most CPUs do have fast path for
+ the sequence.
+
+ The machinery is to emit simple truncation instructions and split them
+ before reload to instructions having USEs of two memory locations that
+ are filled by this code to old and new control word.
+
+ Post-reload pass may be later used to eliminate the redundant fildcw if
+ needed. */
+
+enum ix86_stack_slot
+{
+ SLOT_TEMP = 0,
+ SLOT_CW_STORED,
+ SLOT_CW_ROUNDEVEN,
+ SLOT_CW_TRUNC,
+ SLOT_CW_FLOOR,
+ SLOT_CW_CEIL,
+ SLOT_STV_TEMP,
+ SLOT_FLOATxFDI_387,
+ MAX_386_STACK_LOCALS
+};
+
+enum ix86_entity
+{
+ X86_DIRFLAG = 0,
+ AVX_U128,
+ I387_ROUNDEVEN,
+ I387_TRUNC,
+ I387_FLOOR,
+ I387_CEIL,
+ MAX_386_ENTITIES
+};
+
+enum x86_dirflag_state
+{
+ X86_DIRFLAG_RESET,
+ X86_DIRFLAG_ANY
+};
+
+enum avx_u128_state
+{
+ AVX_U128_CLEAN,
+ AVX_U128_DIRTY,
+ AVX_U128_ANY
+};
+
+/* Define this macro if the port needs extra instructions inserted
+ for mode switching in an optimizing compilation. */
+
+#define OPTIMIZE_MODE_SWITCHING(ENTITY) \
+ ix86_optimize_mode_switching[(ENTITY)]
+
+/* If you define `OPTIMIZE_MODE_SWITCHING', you have to define this as
+ initializer for an array of integers. Each initializer element N
+ refers to an entity that needs mode switching, and specifies the
+ number of different modes that might need to be set for this
+ entity. The position of the initializer in the initializer -
+ starting counting at zero - determines the integer that is used to
+ refer to the mode-switched entity in question. */
+
+#define NUM_MODES_FOR_MODE_SWITCHING \
+ { X86_DIRFLAG_ANY, AVX_U128_ANY, \
+ I387_CW_ANY, I387_CW_ANY, I387_CW_ANY, I387_CW_ANY }
+
+
+/* Avoid renaming of stack registers, as doing so in combination with
+ scheduling just increases amount of live registers at time and in
+ the turn amount of fxch instructions needed.
+
+ ??? Maybe Pentium chips benefits from renaming, someone can try....
+
+ Don't rename evex to non-evex sse registers. */
+
+#define HARD_REGNO_RENAME_OK(SRC, TARGET) \
+ (!STACK_REGNO_P (SRC) \
+ && EXT_REX_SSE_REGNO_P (SRC) == EXT_REX_SSE_REGNO_P (TARGET))
+
+
+#define FASTCALL_PREFIX '@'
+
+#ifndef USED_FOR_TARGET
+/* Structure describing stack frame layout.
+ Stack grows downward:
+
+ [arguments]
+ <- ARG_POINTER
+ saved pc
+
+ saved static chain if ix86_static_chain_on_stack
+
+ saved frame pointer if frame_pointer_needed
+ <- HARD_FRAME_POINTER
+ [saved regs]
+ <- reg_save_offset
+ [padding0]
+ <- stack_realign_offset
+ [saved SSE regs]
+ OR
+ [stub-saved registers for ms x64 --> sysv clobbers
+ <- Start of out-of-line, stub-saved/restored regs
+ (see libgcc/config/i386/(sav|res)ms64*.S)
+ [XMM6-15]
+ [RSI]
+ [RDI]
+ [?RBX] only if RBX is clobbered
+ [?RBP] only if RBP and RBX are clobbered
+ [?R12] only if R12 and all previous regs are clobbered
+ [?R13] only if R13 and all previous regs are clobbered
+ [?R14] only if R14 and all previous regs are clobbered
+ [?R15] only if R15 and all previous regs are clobbered
+ <- end of stub-saved/restored regs
+ [padding1]
+ ]
+ <- sse_reg_save_offset
+ [padding2]
+ | <- FRAME_POINTER
+ [va_arg registers] |
+ |
+ [frame] |
+ |
+ [padding2] | = to_allocate
+ <- STACK_POINTER
+ */
+struct GTY(()) ix86_frame
+{
+ int nsseregs;
+ int nregs;
+ int va_arg_size;
+ int red_zone_size;
+ int outgoing_arguments_size;
+
+ /* The offsets relative to ARG_POINTER. */
+ HOST_WIDE_INT frame_pointer_offset;
+ HOST_WIDE_INT hard_frame_pointer_offset;
+ HOST_WIDE_INT stack_pointer_offset;
+ HOST_WIDE_INT hfp_save_offset;
+ HOST_WIDE_INT reg_save_offset;
+ HOST_WIDE_INT stack_realign_allocate;
+ HOST_WIDE_INT stack_realign_offset;
+ HOST_WIDE_INT sse_reg_save_offset;
+
+ /* When save_regs_using_mov is set, emit prologue using
+ move instead of push instructions. */
+ bool save_regs_using_mov;
+
+ /* Assume without checking that:
+ EXPENSIVE_P = expensive_function_p (EXPENSIVE_COUNT). */
+ bool expensive_p;
+ int expensive_count;
+};
+
+/* Machine specific frame tracking during prologue/epilogue generation. All
+ values are positive, but since the x86 stack grows downward, are subtratced
+ from the CFA to produce a valid address. */
+
+struct GTY(()) machine_frame_state
+{
+ /* This pair tracks the currently active CFA as reg+offset. When reg
+ is drap_reg, we don't bother trying to record here the real CFA when
+ it might really be a DW_CFA_def_cfa_expression. */
+ rtx cfa_reg;
+ HOST_WIDE_INT cfa_offset;
+
+ /* The current offset (canonically from the CFA) of ESP and EBP.
+ When stack frame re-alignment is active, these may not be relative
+ to the CFA. However, in all cases they are relative to the offsets
+ of the saved registers stored in ix86_frame. */
+ HOST_WIDE_INT sp_offset;
+ HOST_WIDE_INT fp_offset;
+
+ /* The size of the red-zone that may be assumed for the purposes of
+ eliding register restore notes in the epilogue. This may be zero
+ if no red-zone is in effect, or may be reduced from the real
+ red-zone value by a maximum runtime stack re-alignment value. */
+ int red_zone_offset;
+
+ /* Indicate whether each of ESP, EBP or DRAP currently holds a valid
+ value within the frame. If false then the offset above should be
+ ignored. Note that DRAP, if valid, *always* points to the CFA and
+ thus has an offset of zero. */
+ BOOL_BITFIELD sp_valid : 1;
+ BOOL_BITFIELD fp_valid : 1;
+ BOOL_BITFIELD drap_valid : 1;
+
+ /* Indicate whether the local stack frame has been re-aligned. When
+ set, the SP/FP offsets above are relative to the aligned frame
+ and not the CFA. */
+ BOOL_BITFIELD realigned : 1;
+
+ /* Indicates whether the stack pointer has been re-aligned. When set,
+ SP/FP continue to be relative to the CFA, but the stack pointer
+ should only be used for offsets > sp_realigned_offset, while
+ the frame pointer should be used for offsets <= sp_realigned_fp_last.
+ The flags realigned and sp_realigned are mutually exclusive. */
+ BOOL_BITFIELD sp_realigned : 1;
+
+ /* If sp_realigned is set, this is the last valid offset from the CFA
+ that can be used for access with the frame pointer. */
+ HOST_WIDE_INT sp_realigned_fp_last;
+
+ /* If sp_realigned is set, this is the offset from the CFA that the stack
+ pointer was realigned, and may or may not be equal to sp_realigned_fp_last.
+ Access via the stack pointer is only valid for offsets that are greater than
+ this value. */
+ HOST_WIDE_INT sp_realigned_offset;
+};
+
+/* Private to winnt.cc. */
+struct seh_frame_state;
+
+enum function_type
+{
+ TYPE_UNKNOWN = 0,
+ TYPE_NORMAL,
+ /* The current function is an interrupt service routine with a
+ pointer argument as specified by the "interrupt" attribute. */
+ TYPE_INTERRUPT,
+ /* The current function is an interrupt service routine with a
+ pointer argument and an integer argument as specified by the
+ "interrupt" attribute. */
+ TYPE_EXCEPTION
+};
+
+enum queued_insn_type
+{
+ TYPE_NONE = 0,
+ TYPE_ENDBR,
+ TYPE_PATCHABLE_AREA
+};
+
+struct GTY(()) machine_function {
+ struct stack_local_entry *stack_locals;
+ int varargs_gpr_size;
+ int varargs_fpr_size;
+ int optimize_mode_switching[MAX_386_ENTITIES];
+
+ /* Cached initial frame layout for the current function. */
+ struct ix86_frame frame;
+
+ /* For -fsplit-stack support: A stack local which holds a pointer to
+ the stack arguments for a function with a variable number of
+ arguments. This is set at the start of the function and is used
+ to initialize the overflow_arg_area field of the va_list
+ structure. */
+ rtx split_stack_varargs_pointer;
+
+ /* This value is used for amd64 targets and specifies the current abi
+ to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */
+ ENUM_BITFIELD(calling_abi) call_abi : 8;
+
+ /* Nonzero if the function accesses a previous frame. */
+ BOOL_BITFIELD accesses_prev_frame : 1;
+
+ /* Set by ix86_compute_frame_layout and used by prologue/epilogue
+ expander to determine the style used. */
+ BOOL_BITFIELD use_fast_prologue_epilogue : 1;
+
+ /* Nonzero if the current function calls pc thunk and
+ must not use the red zone. */
+ BOOL_BITFIELD pc_thunk_call_expanded : 1;
+
+ /* If true, the current function needs the default PIC register, not
+ an alternate register (on x86) and must not use the red zone (on
+ x86_64), even if it's a leaf function. We don't want the
+ function to be regarded as non-leaf because TLS calls need not
+ affect register allocation. This flag is set when a TLS call
+ instruction is expanded within a function, and never reset, even
+ if all such instructions are optimized away. Use the
+ ix86_current_function_calls_tls_descriptor macro for a better
+ approximation. */
+ BOOL_BITFIELD tls_descriptor_call_expanded_p : 1;
+
+ /* If true, the current function has a STATIC_CHAIN is placed on the
+ stack below the return address. */
+ BOOL_BITFIELD static_chain_on_stack : 1;
+
+ /* If true, it is safe to not save/restore DRAP register. */
+ BOOL_BITFIELD no_drap_save_restore : 1;
+
+ /* Function type. */
+ ENUM_BITFIELD(function_type) func_type : 2;
+
+ /* How to generate indirec branch. */
+ ENUM_BITFIELD(indirect_branch) indirect_branch_type : 3;
+
+ /* If true, the current function has local indirect jumps, like
+ "indirect_jump" or "tablejump". */
+ BOOL_BITFIELD has_local_indirect_jump : 1;
+
+ /* How to generate function return. */
+ ENUM_BITFIELD(indirect_branch) function_return_type : 3;
+
+ /* If true, the current function is a function specified with
+ the "interrupt" or "no_caller_saved_registers" attribute. */
+ BOOL_BITFIELD no_caller_saved_registers : 1;
+
+ /* If true, there is register available for argument passing. This
+ is used only in ix86_function_ok_for_sibcall by 32-bit to determine
+ if there is scratch register available for indirect sibcall. In
+ 64-bit, rax, r10 and r11 are scratch registers which aren't used to
+ pass arguments and can be used for indirect sibcall. */
+ BOOL_BITFIELD arg_reg_available : 1;
+
+ /* If true, we're out-of-lining reg save/restore for regs clobbered
+ by 64-bit ms_abi functions calling a sysv_abi function. */
+ BOOL_BITFIELD call_ms2sysv : 1;
+
+ /* If true, the incoming 16-byte aligned stack has an offset (of 8) and
+ needs padding prior to out-of-line stub save/restore area. */
+ BOOL_BITFIELD call_ms2sysv_pad_in : 1;
+
+ /* This is the number of extra registers saved by stub (valid range is
+ 0-6). Each additional register is only saved/restored by the stubs
+ if all successive ones are. (Will always be zero when using a hard
+ frame pointer.) */
+ unsigned int call_ms2sysv_extra_regs:3;
+
+ /* Nonzero if the function places outgoing arguments on stack. */
+ BOOL_BITFIELD outgoing_args_on_stack : 1;
+
+ /* If true, ENDBR or patchable area is queued at function entrance. */
+ ENUM_BITFIELD(queued_insn_type) insn_queued_at_entrance : 2;
+
+ /* If true, the function label has been emitted. */
+ BOOL_BITFIELD function_label_emitted : 1;
+
+ /* True if the function needs a stack frame. */
+ BOOL_BITFIELD stack_frame_required : 1;
+
+ /* True if we should act silently, rather than raise an error for
+ invalid calls. */
+ BOOL_BITFIELD silent_p : 1;
+
+ /* True if red zone is used. */
+ BOOL_BITFIELD red_zone_used : 1;
+
+ /* The largest alignment, in bytes, of stack slot actually used. */
+ unsigned int max_used_stack_alignment;
+
+ /* During prologue/epilogue generation, the current frame state.
+ Otherwise, the frame state at the end of the prologue. */
+ struct machine_frame_state fs;
+
+ /* During SEH output, this is non-null. */
+ struct seh_frame_state * GTY((skip(""))) seh;
+};
+
+extern GTY(()) tree sysv_va_list_type_node;
+extern GTY(()) tree ms_va_list_type_node;
+#endif
+
+#define ix86_stack_locals (cfun->machine->stack_locals)
+#define ix86_varargs_gpr_size (cfun->machine->varargs_gpr_size)
+#define ix86_varargs_fpr_size (cfun->machine->varargs_fpr_size)
+#define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching)
+#define ix86_pc_thunk_call_expanded (cfun->machine->pc_thunk_call_expanded)
+#define ix86_tls_descriptor_calls_expanded_in_cfun \
+ (cfun->machine->tls_descriptor_call_expanded_p)
+/* Since tls_descriptor_call_expanded is not cleared, even if all TLS
+ calls are optimized away, we try to detect cases in which it was
+ optimized away. Since such instructions (use (reg REG_SP)), we can
+ verify whether there's any such instruction live by testing that
+ REG_SP is live. */
+#define ix86_current_function_calls_tls_descriptor \
+ (ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
+#define ix86_static_chain_on_stack (cfun->machine->static_chain_on_stack)
+#define ix86_red_zone_used (cfun->machine->red_zone_used)
+
+/* Control behavior of x86_file_start. */
+#define X86_FILE_START_VERSION_DIRECTIVE false
+#define X86_FILE_START_FLTUSED false
+
+/* Flag to mark data that is in the large address area. */
+#define SYMBOL_FLAG_FAR_ADDR (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_REF_FAR_ADDR_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0)
+
+/* Flags to mark dllimport/dllexport. Used by PE ports, but handy to
+ have defined always, to avoid ifdefing. */
+#define SYMBOL_FLAG_DLLIMPORT (SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_REF_DLLIMPORT_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLIMPORT) != 0)
+
+#define SYMBOL_FLAG_DLLEXPORT (SYMBOL_FLAG_MACH_DEP << 2)
+#define SYMBOL_REF_DLLEXPORT_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLEXPORT) != 0)
+
+#define SYMBOL_FLAG_STUBVAR (SYMBOL_FLAG_MACH_DEP << 4)
+#define SYMBOL_REF_STUBVAR_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_STUBVAR) != 0)
+
+extern void debug_ready_dispatch (void);
+extern void debug_dispatch_window (int);
+
+/* The value at zero is only defined for the BMI instructions
+ LZCNT and TZCNT, not the BSR/BSF insns in the original isa. */
+#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
+ ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_BMI ? 2 : 0)
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
+ ((VALUE) = GET_MODE_BITSIZE (MODE), TARGET_LZCNT ? 2 : 0)
+
+
+/* Flags returned by ix86_get_callcvt (). */
+#define IX86_CALLCVT_CDECL 0x1
+#define IX86_CALLCVT_STDCALL 0x2
+#define IX86_CALLCVT_FASTCALL 0x4
+#define IX86_CALLCVT_THISCALL 0x8
+#define IX86_CALLCVT_REGPARM 0x10
+#define IX86_CALLCVT_SSEREGPARM 0x20
+
+#define IX86_BASE_CALLCVT(FLAGS) \
+ ((FLAGS) & (IX86_CALLCVT_CDECL | IX86_CALLCVT_STDCALL \
+ | IX86_CALLCVT_FASTCALL | IX86_CALLCVT_THISCALL))
+
+#define RECIP_MASK_NONE 0x00
+#define RECIP_MASK_DIV 0x01
+#define RECIP_MASK_SQRT 0x02
+#define RECIP_MASK_VEC_DIV 0x04
+#define RECIP_MASK_VEC_SQRT 0x08
+#define RECIP_MASK_ALL (RECIP_MASK_DIV | RECIP_MASK_SQRT \
+ | RECIP_MASK_VEC_DIV | RECIP_MASK_VEC_SQRT)
+#define RECIP_MASK_DEFAULT (RECIP_MASK_VEC_DIV | RECIP_MASK_VEC_SQRT)
+
+#define TARGET_RECIP_DIV ((recip_mask & RECIP_MASK_DIV) != 0)
+#define TARGET_RECIP_SQRT ((recip_mask & RECIP_MASK_SQRT) != 0)
+#define TARGET_RECIP_VEC_DIV ((recip_mask & RECIP_MASK_VEC_DIV) != 0)
+#define TARGET_RECIP_VEC_SQRT ((recip_mask & RECIP_MASK_VEC_SQRT) != 0)
+
+/* Use 128-bit AVX instructions in the auto-vectorizer. */
+#define TARGET_PREFER_AVX128 (prefer_vector_width_type == PVW_AVX128)
+/* Use 256-bit AVX instructions in the auto-vectorizer. */
+#define TARGET_PREFER_AVX256 (TARGET_PREFER_AVX128 \
+ || prefer_vector_width_type == PVW_AVX256)
+
+#define TARGET_INDIRECT_BRANCH_REGISTER \
+ (ix86_indirect_branch_register \
+ || cfun->machine->indirect_branch_type != indirect_branch_keep)
+
+#define IX86_HLE_ACQUIRE (1 << 16)
+#define IX86_HLE_RELEASE (1 << 17)
+
+/* For switching between functions with different target attributes. */
+#define SWITCHABLE_TARGET 1
+
+#define TARGET_SUPPORTS_WIDE_INT 1
+
+#if !defined(GENERATOR_FILE) && !defined(IN_LIBGCC2)
+extern enum attr_cpu ix86_schedule;
+
+#define NUM_X86_64_MS_CLOBBERED_REGS 12
+#endif
+
+/* __builtin_eh_return can't handle stack realignment, so disable MMX/SSE
+ in 32-bit libgcc functions that call it. */
+#ifndef __x86_64__
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((target ("no-mmx,no-sse")))
+#endif
+
+/*
+Local variables:
+version-control: t
+End:
+*/
diff --git a/support/cpp/gcc/config/dummy/dummy.opt b/support/cpp/gcc/config/dummy/dummy.opt
new file mode 100644
index 000000000..e2e2117c1
--- /dev/null
+++ b/support/cpp/gcc/config/dummy/dummy.opt
@@ -0,0 +1,1144 @@
+; Options for the IA-32 and AMD64 ports of the compiler.
+
+; Copyright (C) 2005-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/>.
+
+HeaderInclude
+config/dummy/dummy-opts.h
+
+; Bit flags that specify the ISA we are compiling for.
+Variable
+HOST_WIDE_INT ix86_isa_flags = TARGET_64BIT_DEFAULT | TARGET_SUBTARGET_ISA_DEFAULT
+
+Variable
+HOST_WIDE_INT ix86_isa_flags2 = 0
+
+; A mask of ix86_isa_flags that includes bit X if X was set or cleared
+; on the command line.
+Variable
+HOST_WIDE_INT ix86_isa_flags_explicit
+
+Variable
+HOST_WIDE_INT ix86_isa_flags2_explicit
+
+; Additional target flags
+Variable
+int ix86_target_flags
+
+TargetVariable
+int recip_mask = RECIP_MASK_DEFAULT
+
+Variable
+int recip_mask_explicit
+
+TargetSave
+int x_recip_mask_explicit
+
+;; A copy of flag_excess_precision as a target variable that should
+;; force a different DECL_FUNCTION_SPECIFIC_TARGET upon
+;; flag_excess_precision changes.
+TargetVariable
+enum excess_precision ix86_excess_precision = EXCESS_PRECISION_DEFAULT
+
+;; Similarly for flag_unsafe_math_optimizations.
+TargetVariable
+bool ix86_unsafe_math_optimizations = false
+
+;; CPU schedule model
+TargetSave
+unsigned char schedule
+
+;; True if processor has SSE prefetch instruction.
+TargetSave
+unsigned char prefetch_sse
+
+;; branch cost
+TargetSave
+unsigned char branch_cost
+
+;; which flags were passed by the user
+TargetSave
+HOST_WIDE_INT x_ix86_isa_flags2_explicit
+
+;; which flags were passed by the user
+TargetSave
+HOST_WIDE_INT x_ix86_isa_flags_explicit
+
+;; -mcmodel= model
+TargetVariable
+enum cmodel ix86_cmodel = CM_32
+
+;; -mabi=
+TargetSave
+enum calling_abi x_ix86_abi
+
+;; -masm=
+TargetSave
+enum asm_dialect x_ix86_asm_dialect
+
+;; -mbranch-cost=
+TargetSave
+int x_ix86_branch_cost
+
+;; -mdump-tune-features=
+TargetSave
+int x_ix86_dump_tunes
+
+;; -mstackrealign=
+TargetSave
+int x_ix86_force_align_arg_pointer
+
+;; -mforce-drap=
+TargetSave
+int x_ix86_force_drap
+
+;; -mincoming-stack-boundary=
+TargetVariable
+int ix86_incoming_stack_boundary_arg
+
+;; -maddress-mode=
+TargetVariable
+enum pmode ix86_pmode = PMODE_SI
+
+;; -mpreferred-stack-boundary=
+TargetVariable
+int ix86_preferred_stack_boundary_arg
+
+;; -mrecip=
+TargetSave
+const char *x_ix86_recip_name
+
+;; -mregparm=
+TargetVariable
+int ix86_regparm
+
+;; -mlarge-data-threshold=
+TargetSave
+int x_ix86_section_threshold
+
+;; -msse2avx=
+TargetSave
+int x_ix86_sse2avx
+
+;; -mstack-protector-guard=
+TargetSave
+enum stack_protector_guard x_ix86_stack_protector_guard
+
+;; -mstringop-strategy=
+TargetSave
+enum stringop_alg x_ix86_stringop_alg
+
+;; -mtls-dialect=
+TargetSave
+enum tls_dialect x_ix86_tls_dialect
+
+;; -mmemcpy-strategy=
+TargetSave
+const char *x_ix86_tune_memcpy_strategy
+
+;; -mmemset-strategy=
+TargetSave
+const char *x_ix86_tune_memset_strategy
+
+;; -mno-default=
+TargetSave
+int x_ix86_tune_no_default
+
+;; -mveclibabi=
+TargetVariable
+enum ix86_veclibabi ix86_veclibabi_type = ix86_veclibabi_type_none
+
+;; x86 options
+m128bit-long-double
+Target RejectNegative Mask(128BIT_LONG_DOUBLE) Save
+sizeof(long double) is 16.
+
+m80387
+Target Mask(80387) Save
+Use hardware fp.
+
+m96bit-long-double
+Target RejectNegative InverseMask(128BIT_LONG_DOUBLE) Save
+sizeof(long double) is 12.
+
+mlong-double-80
+Target RejectNegative Negative(mlong-double-64) InverseMask(LONG_DOUBLE_64) Save
+Use 80-bit long double.
+
+mlong-double-64
+Target RejectNegative Negative(mlong-double-128) Mask(LONG_DOUBLE_64) InverseMask(LONG_DOUBLE_128) Save
+Use 64-bit long double.
+
+mlong-double-128
+Target RejectNegative Negative(mlong-double-80) Mask(LONG_DOUBLE_128) InverseMask(LONG_DOUBLE_64) Save
+Use 128-bit long double.
+
+maccumulate-outgoing-args
+Target Mask(ACCUMULATE_OUTGOING_ARGS) Save
+Reserve space for outgoing arguments in the function prologue.
+
+malign-double
+Target Mask(ALIGN_DOUBLE) Save
+Align some doubles on dword boundary.
+
+malign-functions=
+Target RejectNegative Joined UInteger
+Function starts are aligned to this power of 2.
+
+malign-jumps=
+Target RejectNegative Joined UInteger
+Jump targets are aligned to this power of 2.
+
+malign-loops=
+Target RejectNegative Joined UInteger
+Loop code aligned to this power of 2.
+
+malign-stringops
+Target RejectNegative InverseMask(NO_ALIGN_STRINGOPS, ALIGN_STRINGOPS) Save
+Align destination of the string operations.
+
+malign-data=
+Target RejectNegative Joined Var(ix86_align_data_type) Enum(ix86_align_data) Init(ix86_align_data_type_compat)
+Use the given data alignment.
+
+Enum
+Name(ix86_align_data) Type(enum ix86_align_data)
+Known data alignment choices (for use with the -malign-data= option):
+
+EnumValue
+Enum(ix86_align_data) String(compat) Value(ix86_align_data_type_compat)
+
+EnumValue
+Enum(ix86_align_data) String(abi) Value(ix86_align_data_type_abi)
+
+EnumValue
+Enum(ix86_align_data) String(cacheline) Value(ix86_align_data_type_cacheline)
+
+masm=
+Target RejectNegative Joined Enum(asm_dialect) Var(ix86_asm_dialect) Init(ASM_ATT)
+Use given assembler dialect.
+
+Enum
+Name(asm_dialect) Type(enum asm_dialect)
+Known assembler dialects (for use with the -masm= option):
+
+EnumValue
+Enum(asm_dialect) String(intel) Value(ASM_INTEL)
+
+EnumValue
+Enum(asm_dialect) String(att) Value(ASM_ATT)
+
+mbranch-cost=
+Target RejectNegative Joined UInteger Var(ix86_branch_cost) IntegerRange(0, 5)
+Branches are this expensive (arbitrary units).
+
+mlarge-data-threshold=
+Target RejectNegative Joined UInteger Var(ix86_section_threshold) Init(DEFAULT_LARGE_SECTION_THRESHOLD)
+-mlarge-data-threshold=<number> Data greater than given threshold will go into .ldata section in x86-64 medium model.
+
+mcmodel=
+Target RejectNegative Joined Enum(cmodel) Var(ix86_cmodel) Init(CM_32)
+Use given x86-64 code model.
+
+Enum
+Name(cmodel) Type(enum cmodel)
+Known code models (for use with the -mcmodel= option):
+
+EnumValue
+Enum(cmodel) String(small) Value(CM_SMALL)
+
+EnumValue
+Enum(cmodel) String(medium) Value(CM_MEDIUM)
+
+EnumValue
+Enum(cmodel) String(large) Value(CM_LARGE)
+
+EnumValue
+Enum(cmodel) String(32) Value(CM_32)
+
+EnumValue
+Enum(cmodel) String(kernel) Value(CM_KERNEL)
+
+maddress-mode=
+Target RejectNegative Joined Enum(pmode) Var(ix86_pmode) Init(PMODE_SI)
+Use given address mode.
+
+Enum
+Name(pmode) Type(enum pmode)
+Known address mode (for use with the -maddress-mode= option):
+
+EnumValue
+Enum(pmode) String(short) Value(PMODE_SI)
+
+EnumValue
+Enum(pmode) String(long) Value(PMODE_DI)
+
+mfancy-math-387
+Target RejectNegative InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save
+Generate sin, cos, sqrt for FPU.
+
+mforce-drap
+Target Var(ix86_force_drap)
+Always use Dynamic Realigned Argument Pointer (DRAP) to realign stack.
+
+mfp-ret-in-387
+Target Mask(FLOAT_RETURNS) Save
+Return values of functions in FPU registers.
+
+mfpmath=
+Target RejectNegative Joined Var(ix86_fpmath) Enum(fpmath_unit) Init(FPMATH_387) Save
+Generate floating point mathematics using given instruction set.
+
+Enum
+Name(fpmath_unit) Type(enum fpmath_unit)
+Valid arguments to -mfpmath=:
+
+EnumValue
+Enum(fpmath_unit) String(387) Value(FPMATH_387)
+
+EnumValue
+Enum(fpmath_unit) String(sse) Value(FPMATH_SSE)
+
+EnumValue
+Enum(fpmath_unit) String(387,sse) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(387+sse) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(sse,387) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(sse+387) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)})
+
+EnumValue
+Enum(fpmath_unit) String(both) Value({(enum fpmath_unit) (FPMATH_SSE | FPMATH_387)})
+
+mhard-float
+Target RejectNegative Mask(80387) Save
+Use hardware fp.
+
+mieee-fp
+Target Mask(IEEE_FP) Save
+Use IEEE math for fp comparisons.
+
+minline-all-stringops
+Target Mask(INLINE_ALL_STRINGOPS) Save
+Inline all known string operations.
+
+minline-stringops-dynamically
+Target Mask(INLINE_STRINGOPS_DYNAMICALLY) Save
+Inline memset/memcpy string operations, but perform inline version only for small blocks.
+
+mintel-syntax
+Target Undocumented Alias(masm=, intel, att) Warn(%<-mintel-syntax%> and %<-mno-intel-syntax%> are deprecated; use %<-masm=intel%> and %<-masm=att%> instead)
+
+mms-bitfields
+Target Mask(MS_BITFIELD_LAYOUT) Save
+Use native (MS) bitfield layout.
+
+mno-align-stringops
+Target RejectNegative Mask(NO_ALIGN_STRINGOPS) Undocumented Save
+
+mno-fancy-math-387
+Target RejectNegative Mask(NO_FANCY_MATH_387) Undocumented Save
+
+mno-push-args
+Target RejectNegative Mask(NO_PUSH_ARGS) Undocumented Save
+
+mno-red-zone
+Target RejectNegative Mask(NO_RED_ZONE) Undocumented Save
+
+momit-leaf-frame-pointer
+Target Mask(OMIT_LEAF_FRAME_POINTER) Save
+Omit the frame pointer in leaf functions.
+
+mrelax-cmpxchg-loop
+Target Mask(RELAX_CMPXCHG_LOOP) Save
+Relax cmpxchg loop for atomic_fetch_{or,xor,and,nand} by adding load and cmp before cmpxchg, execute pause and loop back to load and compare if load value is not expected.
+
+mpc32
+Target RejectNegative
+Set 80387 floating-point precision to 32-bit.
+
+mpc64
+Target RejectNegative
+Set 80387 floating-point precision to 64-bit.
+
+mpc80
+Target RejectNegative
+Set 80387 floating-point precision to 80-bit.
+
+mpreferred-stack-boundary=
+Target RejectNegative Joined UInteger Var(ix86_preferred_stack_boundary_arg)
+Attempt to keep stack aligned to this power of 2.
+
+mincoming-stack-boundary=
+Target RejectNegative Joined UInteger Var(ix86_incoming_stack_boundary_arg)
+Assume incoming stack aligned to this power of 2.
+
+mpush-args
+Target InverseMask(NO_PUSH_ARGS, PUSH_ARGS) Save
+Use push instructions to save outgoing arguments.
+
+mred-zone
+Target RejectNegative InverseMask(NO_RED_ZONE, RED_ZONE) Save
+Use red-zone in the x86-64 code.
+
+mregparm=
+Target RejectNegative Joined UInteger Var(ix86_regparm)
+Number of registers used to pass integer arguments.
+
+mrtd
+Target Mask(RTD) Save
+Alternate calling convention.
+
+msoft-float
+Target InverseMask(80387) Save
+Do not use hardware fp.
+
+msseregparm
+Target RejectNegative Mask(SSEREGPARM) Save
+Use SSE register passing conventions for SF and DF mode.
+
+mstackrealign
+Target Var(ix86_force_align_arg_pointer)
+Realign stack in prologue.
+
+mstack-arg-probe
+Target Mask(STACK_PROBE) Save
+Enable stack probing.
+
+mmemcpy-strategy=
+Target RejectNegative Joined Var(ix86_tune_memcpy_strategy)
+Specify memcpy expansion strategy when expected size is known.
+
+mmemset-strategy=
+Target RejectNegative Joined Var(ix86_tune_memset_strategy)
+Specify memset expansion strategy when expected size is known.
+
+Enum
+Name(stringop_alg) Type(enum stringop_alg)
+Valid arguments to -mstringop-strategy=:
+
+mtls-dialect=
+Target RejectNegative Joined Var(ix86_tls_dialect) Enum(tls_dialect) Init(TLS_DIALECT_GNU)
+Use given thread-local storage dialect.
+
+Enum
+Name(tls_dialect) Type(enum tls_dialect)
+Known TLS dialects (for use with the -mtls-dialect= option):
+
+EnumValue
+Enum(tls_dialect) String(gnu) Value(TLS_DIALECT_GNU)
+
+EnumValue
+Enum(tls_dialect) String(gnu2) Value(TLS_DIALECT_GNU2)
+
+mtls-direct-seg-refs
+Target Mask(TLS_DIRECT_SEG_REFS)
+Use direct references against %gs when accessing tls data.
+
+mno-default
+Target RejectNegative Var(ix86_tune_no_default)
+Clear all tune features.
+
+mdump-tune-features
+Target RejectNegative Var(ix86_dump_tunes)
+
+miamcu
+Target Mask(IAMCU)
+Generate code that conforms to Intel MCU psABI.
+
+mabi=
+Target RejectNegative Joined Var(ix86_abi) Enum(calling_abi) Init(SYSV_ABI)
+Generate code that conforms to the given ABI.
+
+Enum
+Name(calling_abi) Type(enum calling_abi)
+Known ABIs (for use with the -mabi= option):
+
+EnumValue
+Enum(calling_abi) String(sysv) Value(SYSV_ABI)
+
+EnumValue
+Enum(calling_abi) String(ms) Value(MS_ABI)
+
+mcall-ms2sysv-xlogues
+Target Mask(CALL_MS2SYSV_XLOGUES) Save
+Use libgcc stubs to save and restore registers clobbered by 64-bit Microsoft to System V ABI calls.
+
+mveclibabi=
+Target RejectNegative Joined Var(ix86_veclibabi_type) Enum(ix86_veclibabi) Init(ix86_veclibabi_type_none)
+Vector library ABI to use.
+
+Enum
+Name(ix86_veclibabi) Type(enum ix86_veclibabi)
+Known vectorization library ABIs (for use with the -mveclibabi= option):
+
+EnumValue
+Enum(ix86_veclibabi) String(svml) Value(ix86_veclibabi_type_svml)
+
+EnumValue
+Enum(ix86_veclibabi) String(acml) Value(ix86_veclibabi_type_acml)
+
+mvect8-ret-in-mem
+Target Mask(VECT8_RETURNS) Save
+Return 8-byte vectors in memory.
+
+mrecip
+Target Mask(RECIP) Save
+Generate reciprocals instead of divss and sqrtss.
+
+mrecip=
+Target RejectNegative Joined Var(ix86_recip_name)
+Control generation of reciprocal estimates.
+
+mcld
+Target Mask(CLD) Save
+Generate cld instruction in the function prologue.
+
+mvzeroupper
+Target Mask(VZEROUPPER) Save
+Generate vzeroupper instruction before a transfer of control flow out of
+the function.
+
+mstv
+Target Mask(STV) Save
+Disable Scalar to Vector optimization pass transforming 64-bit integer
+computations into a vector ones.
+
+mdispatch-scheduler
+Target RejectNegative Var(flag_dispatch_scheduler)
+Do dispatch scheduling if processor is bdver1, bdver2, bdver3, bdver4
+or znver1 and Haifa scheduling is selected.
+
+mprefer-avx128
+Target Alias(mprefer-vector-width=, 128, 256)
+Use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer.
+
+mprefer-vector-width=
+Target RejectNegative Joined Var(prefer_vector_width_type) Enum(prefer_vector_width) Init(PVW_NONE) Save
+Use given register vector width instructions instead of maximum register width in the auto-vectorizer.
+
+Enum
+Name(prefer_vector_width) Type(enum prefer_vector_width)
+Known preferred register vector length (to use with the -mprefer-vector-width= option):
+
+EnumValue
+Enum(prefer_vector_width) String(none) Value(PVW_NONE)
+
+EnumValue
+Enum(prefer_vector_width) String(128) Value(PVW_AVX128)
+
+EnumValue
+Enum(prefer_vector_width) String(256) Value(PVW_AVX256)
+
+EnumValue
+Enum(prefer_vector_width) String(512) Value(PVW_AVX512)
+
+mmove-max=
+Target RejectNegative Joined Var(ix86_move_max) Enum(prefer_vector_width) Init(PVW_NONE) Save
+Maximum number of bits that can be moved from memory to memory efficiently.
+
+mstore-max=
+Target RejectNegative Joined Var(ix86_store_max) Enum(prefer_vector_width) Init(PVW_NONE) Save
+Maximum number of bits that can be stored to memory efficiently.
+
+;; ISA support
+
+m32
+Target RejectNegative Negative(m64) InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
+Generate 32bit i386 code.
+
+m64
+Target RejectNegative Negative(mx32) Mask(ABI_64) Var(ix86_isa_flags) Save
+Generate 64bit x86-64 code.
+
+mx32
+Target RejectNegative Negative(m16) Mask(ABI_X32) Var(ix86_isa_flags) Save
+Generate 32bit x86-64 code.
+
+m16
+Target RejectNegative Negative(m32) Mask(CODE16) InverseMask(ISA_64BIT) Var(ix86_isa_flags) Save
+Generate 16bit i386 code.
+
+mmmx
+Target Mask(ISA_MMX) Var(ix86_isa_flags) Save
+Support MMX built-in functions.
+
+m3dnow
+Target Mask(ISA_3DNOW) Var(ix86_isa_flags) Save
+Support 3DNow! built-in functions.
+
+m3dnowa
+Target Mask(ISA_3DNOW_A) Var(ix86_isa_flags) Save
+Support Athlon 3Dnow! built-in functions.
+
+msse
+Target Mask(ISA_SSE) Var(ix86_isa_flags) Save
+Support MMX and SSE built-in functions and code generation.
+
+msse2
+Target Mask(ISA_SSE2) Var(ix86_isa_flags) Save
+Support MMX, SSE and SSE2 built-in functions and code generation.
+
+msse3
+Target Mask(ISA_SSE3) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2 and SSE3 built-in functions and code generation.
+
+mssse3
+Target Mask(ISA_SSSE3) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3 and SSSE3 built-in functions and code generation.
+
+msse4.1
+Target Mask(ISA_SSE4_1) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 built-in functions and code generation.
+
+msse4.2
+Target Mask(ISA_SSE4_2) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation.
+
+msse4
+Target RejectNegative Mask(ISA_SSE4_2) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1 and SSE4.2 built-in functions and code generation.
+
+mno-sse4
+Target RejectNegative InverseMask(ISA_SSE4_1) Var(ix86_isa_flags) Save
+Do not support SSE4.1 and SSE4.2 built-in functions and code generation.
+
+msse5
+Target Undocumented Alias(mavx) Warn(%<-msse5%> was removed)
+;; Deprecated
+
+mavx
+Target Mask(ISA_AVX) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX built-in functions and code generation.
+
+mavx2
+Target Mask(ISA_AVX2) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and AVX2 built-in functions and code generation.
+
+mavx512f
+Target Mask(ISA_AVX512F) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F built-in functions and code generation.
+
+mavx512pf
+Target Mask(ISA_AVX512PF) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512PF built-in functions and code generation.
+
+mavx512er
+Target Mask(ISA_AVX512ER) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512ER built-in functions and code generation.
+
+mavx512cd
+Target Mask(ISA_AVX512CD) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512CD built-in functions and code generation.
+
+mavx512dq
+Target Mask(ISA_AVX512DQ) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512DQ built-in functions and code generation.
+
+mavx512bw
+Target Mask(ISA_AVX512BW) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512BW built-in functions and code generation.
+
+mavx512vl
+Target Mask(ISA_AVX512VL) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512VL built-in functions and code generation.
+
+mavx512ifma
+Target Mask(ISA_AVX512IFMA) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512IFMA built-in functions and code generation.
+
+mavx512vbmi
+Target Mask(ISA_AVX512VBMI) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2 and AVX512F and AVX512VBMI built-in functions and code generation.
+
+mavx5124fmaps
+Target Mask(ISA2_AVX5124FMAPS) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX5124FMAPS built-in functions and code generation.
+
+mavx5124vnniw
+Target Mask(ISA2_AVX5124VNNIW) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX5124VNNIW built-in functions and code generation.
+
+mavx512vpopcntdq
+Target Mask(ISA_AVX512VPOPCNTDQ) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VPOPCNTDQ built-in functions and code generation.
+
+mavx512vbmi2
+Target Mask(ISA_AVX512VBMI2) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512VBMI2 built-in functions and code generation.
+
+mavx512vnni
+Target Mask(ISA_AVX512VNNI) Var(ix86_isa_flags) Save
+Support AVX512VNNI built-in functions and code generation.
+
+mavx512bitalg
+Target Mask(ISA_AVX512BITALG) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512BITALG built-in functions and code generation.
+
+mavx512vp2intersect
+Target Mask(ISA2_AVX512VP2INTERSECT) Var(ix86_isa_flags2) Save
+Support AVX512VP2INTERSECT built-in functions and code generation.
+
+mfma
+Target Mask(ISA_FMA) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX and FMA built-in functions and code generation.
+
+msse4a
+Target Mask(ISA_SSE4A) Var(ix86_isa_flags) Save
+Support MMX, SSE, SSE2, SSE3 and SSE4A built-in functions and code generation.
+
+mfma4
+Target Mask(ISA_FMA4) Var(ix86_isa_flags) Save
+Support FMA4 built-in functions and code generation.
+
+mxop
+Target Mask(ISA_XOP) Var(ix86_isa_flags) Save
+Support XOP built-in functions and code generation.
+
+mlwp
+Target Mask(ISA_LWP) Var(ix86_isa_flags) Save
+Support LWP built-in functions and code generation.
+
+mabm
+Target Mask(ISA_ABM) Var(ix86_isa_flags) Save
+Support code generation of Advanced Bit Manipulation (ABM) instructions.
+
+mpopcnt
+Target Mask(ISA_POPCNT) Var(ix86_isa_flags) Save
+Support code generation of popcnt instruction.
+
+mpconfig
+Target Mask(ISA2_PCONFIG) Var(ix86_isa_flags2) Save
+Support PCONFIG built-in functions and code generation.
+
+mwbnoinvd
+Target Mask(ISA2_WBNOINVD) Var(ix86_isa_flags2) Save
+Support WBNOINVD built-in functions and code generation.
+
+mptwrite
+Target Mask(ISA2_PTWRITE) Var(ix86_isa_flags2) Save
+Support PTWRITE built-in functions and code generation.
+
+muintr
+Target Mask(ISA2_UINTR) Var(ix86_isa_flags2) Save
+Support UINTR built-in functions and code generation.
+
+msgx
+Target Mask(ISA2_SGX) Var(ix86_isa_flags2) Save
+Support SGX built-in functions and code generation.
+
+mrdpid
+Target Mask(ISA2_RDPID) Var(ix86_isa_flags2) Save
+Support RDPID built-in functions and code generation.
+
+mgfni
+Target Mask(ISA_GFNI) Var(ix86_isa_flags) Save
+Support GFNI built-in functions and code generation.
+
+mvaes
+Target Mask(ISA2_VAES) Var(ix86_isa_flags2) Save
+Support VAES built-in functions and code generation.
+
+mvpclmulqdq
+Target Mask(ISA_VPCLMULQDQ) Var(ix86_isa_flags) Save
+Support VPCLMULQDQ built-in functions and code generation.
+
+mbmi
+Target Mask(ISA_BMI) Var(ix86_isa_flags) Save
+Support BMI built-in functions and code generation.
+
+mbmi2
+Target Mask(ISA_BMI2) Var(ix86_isa_flags) Save
+Support BMI2 built-in functions and code generation.
+
+mlzcnt
+Target Mask(ISA_LZCNT) Var(ix86_isa_flags) Save
+Support LZCNT built-in function and code generation.
+
+mhle
+Target Mask(ISA2_HLE) Var(ix86_isa_flags2) Save
+Support Hardware Lock Elision prefixes.
+
+mrdseed
+Target Mask(ISA_RDSEED) Var(ix86_isa_flags) Save
+Support RDSEED instruction.
+
+mprfchw
+Target Mask(ISA_PRFCHW) Var(ix86_isa_flags) Save
+Support PREFETCHW instruction.
+
+madx
+Target Mask(ISA_ADX) Var(ix86_isa_flags) Save
+Support flag-preserving add-carry instructions.
+
+mclflushopt
+Target Mask(ISA_CLFLUSHOPT) Var(ix86_isa_flags) Save
+Support CLFLUSHOPT instructions.
+
+mclwb
+Target Mask(ISA_CLWB) Var(ix86_isa_flags) Save
+Support CLWB instruction.
+
+mpcommit
+Target WarnRemoved
+
+mfxsr
+Target Mask(ISA_FXSR) Var(ix86_isa_flags) Save
+Support FXSAVE and FXRSTOR instructions.
+
+mxsave
+Target Mask(ISA_XSAVE) Var(ix86_isa_flags) Save
+Support XSAVE and XRSTOR instructions.
+
+mxsaveopt
+Target Mask(ISA_XSAVEOPT) Var(ix86_isa_flags) Save
+Support XSAVEOPT instruction.
+
+mxsavec
+Target Mask(ISA_XSAVEC) Var(ix86_isa_flags) Save
+Support XSAVEC instructions.
+
+mxsaves
+Target Mask(ISA_XSAVES) Var(ix86_isa_flags) Save
+Support XSAVES and XRSTORS instructions.
+
+mtbm
+Target Mask(ISA_TBM) Var(ix86_isa_flags) Save
+Support TBM built-in functions and code generation.
+
+mcx16
+Target Mask(ISA2_CX16) Var(ix86_isa_flags2) Save
+Support code generation of cmpxchg16b instruction.
+
+msahf
+Target Mask(ISA_SAHF) Var(ix86_isa_flags) Save
+Support code generation of sahf instruction in 64bit x86-64 code.
+
+mmovbe
+Target Mask(ISA2_MOVBE) Var(ix86_isa_flags2) Save
+Support code generation of movbe instruction.
+
+mcrc32
+Target Mask(ISA_CRC32) Var(ix86_isa_flags) Save
+Support code generation of crc32 instruction.
+
+maes
+Target Mask(ISA_AES) Var(ix86_isa_flags) Save
+Support AES built-in functions and code generation.
+
+msha
+Target Mask(ISA_SHA) Var(ix86_isa_flags) Save
+Support SHA1 and SHA256 built-in functions and code generation.
+
+mpclmul
+Target Mask(ISA_PCLMUL) Var(ix86_isa_flags) Save
+Support PCLMUL built-in functions and code generation.
+
+msse2avx
+Target Var(ix86_sse2avx)
+Encode SSE instructions with VEX prefix.
+
+mfsgsbase
+Target Mask(ISA_FSGSBASE) Var(ix86_isa_flags) Save
+Support FSGSBASE built-in functions and code generation.
+
+mrdrnd
+Target Mask(ISA_RDRND) Var(ix86_isa_flags) Save
+Support RDRND built-in functions and code generation.
+
+mf16c
+Target Mask(ISA_F16C) Var(ix86_isa_flags) Save
+Support F16C built-in functions and code generation.
+
+mprefetchwt1
+Target Mask(ISA_PREFETCHWT1) Var(ix86_isa_flags) Save
+Support PREFETCHWT1 built-in functions and code generation.
+
+mfentry
+Target Save Var(flag_fentry)
+Emit profiling counter call at function entry before prologue.
+
+mrecord-mcount
+Target Var(flag_record_mcount)
+Generate __mcount_loc section with all mcount or __fentry__ calls.
+
+mnop-mcount
+Target Var(flag_nop_mcount)
+Generate mcount/__fentry__ calls as nops. To activate they need to be
+patched in.
+
+mfentry-name=
+Target RejectNegative Joined Var(fentry_name)
+Set name of __fentry__ symbol called at function entry.
+
+mfentry-section=
+Target RejectNegative Joined Var(fentry_section)
+Set name of section to record mrecord-mcount calls.
+
+mskip-rax-setup
+Target Var(flag_skip_rax_setup)
+Skip setting up RAX register when passing variable arguments.
+
+m8bit-idiv
+Target Mask(USE_8BIT_IDIV) Save
+Expand 32bit/64bit integer divide into 8bit unsigned integer divide with run-time check.
+
+mavx256-split-unaligned-load
+Target Mask(AVX256_SPLIT_UNALIGNED_LOAD) Save
+Split 32-byte AVX unaligned load.
+
+mavx256-split-unaligned-store
+Target Mask(AVX256_SPLIT_UNALIGNED_STORE) Save
+Split 32-byte AVX unaligned store.
+
+mrtm
+Target Mask(ISA_RTM) Var(ix86_isa_flags) Save
+Support RTM built-in functions and code generation.
+
+mmpx
+Target WarnRemoved
+Removed in GCC 9. This switch has no effect.
+
+mmwaitx
+Target Mask(ISA2_MWAITX) Var(ix86_isa_flags2) Save
+Support MWAITX and MONITORX built-in functions and code generation.
+
+mclzero
+Target Mask(ISA2_CLZERO) Var(ix86_isa_flags2) Save
+Support CLZERO built-in functions and code generation.
+
+mpku
+Target Mask(ISA_PKU) Var(ix86_isa_flags) Save
+Support PKU built-in functions and code generation.
+
+mstack-protector-guard=
+Target RejectNegative Joined Enum(stack_protector_guard) Var(ix86_stack_protector_guard) Init(SSP_TLS)
+Use given stack-protector guard.
+
+Enum
+Name(stack_protector_guard) Type(enum stack_protector_guard)
+Known stack protector guard (for use with the -mstack-protector-guard= option):
+
+EnumValue
+Enum(stack_protector_guard) String(tls) Value(SSP_TLS)
+
+EnumValue
+Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL)
+
+mstack-protector-guard-reg=
+Target Save RejectNegative Joined Var(ix86_stack_protector_guard_reg_str)
+Use the given base register for addressing the stack-protector guard.
+
+TargetVariable
+addr_space_t ix86_stack_protector_guard_reg = ADDR_SPACE_GENERIC
+
+mstack-protector-guard-offset=
+Target Save RejectNegative Joined Integer Var(ix86_stack_protector_guard_offset_str)
+Use the given offset for addressing the stack-protector guard.
+
+TargetVariable
+HOST_WIDE_INT ix86_stack_protector_guard_offset = 0
+
+mstack-protector-guard-symbol=
+Target Save RejectNegative Joined Integer Var(ix86_stack_protector_guard_symbol_str)
+Use the given symbol for addressing the stack-protector guard.
+
+mmitigate-rop
+Target WarnRemoved
+
+mgeneral-regs-only
+Target RejectNegative Mask(GENERAL_REGS_ONLY) Var(ix86_target_flags) Save
+Generate code which uses only the general registers.
+
+mshstk
+Target Mask(ISA_SHSTK) Var(ix86_isa_flags) Save
+Enable shadow stack built-in functions from Control-flow Enforcement
+Technology (CET).
+
+mcet-switch
+Target Undocumented Var(flag_cet_switch) Init(0)
+Turn on CET instrumentation for switch statements that use a jump table and
+an indirect jump.
+
+mmanual-endbr
+Target Var(flag_manual_endbr) Init(0)
+Insert ENDBR instruction at function entry only via cf_check attribute
+for CET instrumentation.
+
+mforce-indirect-call
+Target Var(flag_force_indirect_call) Init(0)
+Make all function calls indirect.
+
+mindirect-branch=
+Target RejectNegative Joined Enum(indirect_branch) Var(ix86_indirect_branch) Init(indirect_branch_keep)
+Convert indirect call and jump to call and return thunks.
+
+mfunction-return=
+Target RejectNegative Joined Enum(indirect_branch) Var(ix86_function_return) Init(indirect_branch_keep)
+Convert function return to call and return thunk.
+
+Enum
+Name(indirect_branch) Type(enum indirect_branch)
+Known indirect branch choices (for use with the -mindirect-branch=/-mfunction-return= options):
+
+EnumValue
+Enum(indirect_branch) String(keep) Value(indirect_branch_keep)
+
+EnumValue
+Enum(indirect_branch) String(thunk) Value(indirect_branch_thunk)
+
+EnumValue
+Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
+
+EnumValue
+Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+
+mindirect-branch-cs-prefix
+Target Var(ix86_indirect_branch_cs_prefix) Init(0)
+Add CS prefix to call and jmp to indirect thunk with branch target in r8-r15 registers.
+
+mindirect-branch-register
+Target Var(ix86_indirect_branch_register) Init(0)
+Force indirect call and jump via register.
+
+mmovdiri
+Target Mask(ISA_MOVDIRI) Var(ix86_isa_flags) Save
+Support MOVDIRI built-in functions and code generation.
+
+mmovdir64b
+Target Mask(ISA2_MOVDIR64B) Var(ix86_isa_flags2) Save
+Support MOVDIR64B built-in functions and code generation.
+
+mwaitpkg
+Target Mask(ISA2_WAITPKG) Var(ix86_isa_flags2) Save
+Support WAITPKG built-in functions and code generation.
+
+mcldemote
+Target Mask(ISA2_CLDEMOTE) Var(ix86_isa_flags2) Save
+Support CLDEMOTE built-in functions and code generation.
+
+minstrument-return=
+Target RejectNegative Joined Enum(instrument_return) Var(ix86_instrument_return) Init(instrument_return_none)
+Instrument function exit in instrumented functions with __fentry__.
+
+Enum
+Name(instrument_return) Type(enum instrument_return)
+Known choices for return instrumentation with -minstrument-return=:
+
+EnumValue
+Enum(instrument_return) String(none) Value(instrument_return_none)
+
+EnumValue
+Enum(instrument_return) String(call) Value(instrument_return_call)
+
+EnumValue
+Enum(instrument_return) String(nop5) Value(instrument_return_nop5)
+
+mrecord-return
+Target Var(ix86_flag_record_return) Init(0)
+Generate a __return_loc section pointing to all return instrumentation code.
+
+mharden-sls=
+Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none)
+Generate code to mitigate against straight line speculation.
+
+Enum
+Name(harden_sls) Type(enum harden_sls)
+Known choices for mitigation against straight line speculation with -mharden-sls=:
+
+EnumValue
+Enum(harden_sls) String(none) Value(harden_sls_none)
+
+EnumValue
+Enum(harden_sls) String(return) Value(harden_sls_return)
+
+EnumValue
+Enum(harden_sls) String(indirect-jmp) Value(harden_sls_indirect_jmp)
+
+EnumValue
+Enum(harden_sls) String(all) Value(harden_sls_all)
+
+mavx512bf16
+Target Mask(ISA2_AVX512BF16) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and
+AVX512BF16 built-in functions and code generation.
+
+menqcmd
+Target Mask(ISA2_ENQCMD) Var(ix86_isa_flags2) Save
+Support ENQCMD built-in functions and code generation.
+
+mserialize
+Target Mask(ISA2_SERIALIZE) Var(ix86_isa_flags2) Save
+Support SERIALIZE built-in functions and code generation.
+
+mtsxldtrk
+Target Mask(ISA2_TSXLDTRK) Var(ix86_isa_flags2) Save
+Support TSXLDTRK built-in functions and code generation.
+
+mamx-tile
+Target Mask(ISA2_AMX_TILE) Var(ix86_isa_flags2) Save
+Support AMX-TILE built-in functions and code generation.
+
+mamx-int8
+Target Mask(ISA2_AMX_INT8) Var(ix86_isa_flags2) Save
+Support AMX-INT8 built-in functions and code generation.
+
+mamx-bf16
+Target Mask(ISA2_AMX_BF16) Var(ix86_isa_flags2) Save
+Support AMX-BF16 built-in functions and code generation.
+
+mhreset
+Target Mask(ISA2_HRESET) Var(ix86_isa_flags2) Save
+Support HRESET built-in functions and code generation.
+
+mkl
+Target Mask(ISA2_KL) Var(ix86_isa_flags2) Save
+Support KL built-in functions and code generation.
+
+mwidekl
+Target Mask(ISA2_WIDEKL) Var(ix86_isa_flags2) Save
+Support WIDEKL built-in functions and code generation.
+
+mavxvnni
+Target Mask(ISA2_AVXVNNI) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, and
+AVXVNNI built-in functions and code generation.
+
+mneeded
+Target Var(ix86_needed) Save
+Emit GNU_PROPERTY_X86_ISA_1_NEEDED GNU property.
+
+mmwait
+Target Mask(ISA2_MWAIT) Var(ix86_isa_flags2) Save
+Support MWAIT and MONITOR built-in functions and code generation.
+
+mavx512fp16
+Target Mask(ISA2_AVX512FP16) Var(ix86_isa_flags2) Save
+Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512FP16 built-in functions and code generation.
+
+mdirect-extern-access
+Target Var(ix86_direct_extern_access) Init(1)
+Do not use GOT to access external symbols.
+
+-param=x86-stlf-window-ninsns=
+Target Joined UInteger Var(x86_stlf_window_ninsns) Init(64) Param
+Instructions number above which STFL stall penalty can be compensated.
diff --git a/support/cpp/gcc/config/dummy/linux-common.h b/support/cpp/gcc/config/dummy/linux-common.h
new file mode 100644
index 000000000..efa7fb207
--- /dev/null
+++ b/support/cpp/gcc/config/dummy/linux-common.h
@@ -0,0 +1,71 @@
+/* Definitions for Intel 386 running Linux-based GNU systems with ELF format.
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ Contributed by Ilya Enkovich.
+
+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/>. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ GNU_USER_TARGET_OS_CPP_BUILTINS(); \
+ ANDROID_TARGET_OS_CPP_BUILTINS(); \
+ } \
+ while (0)
+
+#define EXTRA_TARGET_D_OS_VERSIONS() \
+ ANDROID_TARGET_D_OS_VERSIONS();
+
+#undef CC1_SPEC
+#define CC1_SPEC \
+ LINUX_OR_ANDROID_CC (GNU_USER_TARGET_CC1_SPEC, \
+ GNU_USER_TARGET_CC1_SPEC " " ANDROID_CC1_SPEC)
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_LINK_SPEC, \
+ GNU_USER_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_LIB_SPEC, \
+ GNU_USER_TARGET_NO_PTHREADS_LIB_SPEC " " ANDROID_LIB_SPEC)
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_STARTFILE_SPEC, \
+ ANDROID_STARTFILE_SPEC)
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ LINUX_OR_ANDROID_LD (GNU_USER_TARGET_MATHFILE_SPEC " " \
+ GNU_USER_TARGET_ENDFILE_SPEC, \
+ GNU_USER_TARGET_MATHFILE_SPEC " " \
+ ANDROID_ENDFILE_SPEC)
+
+#ifdef HAVE_LD_PUSHPOPSTATE_SUPPORT
+#define MPX_LD_AS_NEEDED_GUARD_PUSH "--push-state --no-as-needed"
+#define MPX_LD_AS_NEEDED_GUARD_POP "--pop-state"
+#else
+#define MPX_LD_AS_NEEDED_GUARD_PUSH ""
+#define MPX_LD_AS_NEEDED_GUARD_POP ""
+#endif
+
+extern void file_end_indicate_exec_stack_and_gnu_property (void);
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END file_end_indicate_exec_stack_and_gnu_property
diff --git a/support/cpp/gcc/config/dummy/unix.h b/support/cpp/gcc/config/dummy/unix.h
new file mode 100644
index 000000000..582d65b20
--- /dev/null
+++ b/support/cpp/gcc/config/dummy/unix.h
@@ -0,0 +1,80 @@
+/* Definitions for Unix assembler syntax for the Intel 80386.
+ Copyright (C) 1988-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 defines the aspects of assembler syntax
+ that are the same for all the i386 Unix systems
+ (though they may differ in non-Unix systems). */
+
+/* Define macro used to output shift-double opcodes when the shift
+ count is in %cl. Some assemblers require %cl as an argument;
+ some don't. This macro controls what to do: by default, don't
+ print %cl. */
+#define SHIFT_DOUBLE_OMITS_COUNT 1
+
+/* Define the syntax of pseudo-ops, labels and comments. */
+
+/* String containing the assembler's comment-starter.
+ Note the trailing space is necessary in case the character
+ that immediately follows the comment is '*'. If this happens
+ and the space is not there the assembler will interpret this
+ as the start of a C-like slash-star comment and complain when
+ there is no terminator. */
+
+#define ASM_COMMENT_START "/ "
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "/APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "/NO_APP\n"
+
+/* Output before read-only data. */
+
+#define TEXT_SECTION_ASM_OP "\t.text"
+
+/* Output before writable (initialized) data. */
+
+#define DATA_SECTION_ASM_OP "\t.data"
+
+/* Output before writable (uninitialized) data. */
+
+#define BSS_SECTION_ASM_OP "\t.bss"
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+/* By default, target has a 80387, uses IEEE compatible arithmetic,
+ and returns float values in the 387. */
+#undef TARGET_SUBTARGET_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
+
+/* By default, 64-bit mode uses 128-bit long double. */
+#undef TARGET_SUBTARGET64_DEFAULT
+#define TARGET_SUBTARGET64_DEFAULT \
+ MASK_128BIT_LONG_DOUBLE
diff --git a/support/cpp/gcc/config/elfos.h b/support/cpp/gcc/config/elfos.h
new file mode 100644
index 000000000..acb376283
--- /dev/null
+++ b/support/cpp/gcc/config/elfos.h
@@ -0,0 +1,490 @@
+/* elfos.h -- operating system specific defines to be used when
+ targeting GCC for some generic ELF system
+ Copyright (C) 1991-2022 Free Software Foundation, Inc.
+ Based on svr4.h contributed by Ron Guilmette (rfg@netcom.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/>. */
+
+#define TARGET_OBJFMT_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__ELF__"); \
+ } \
+ while (0)
+
+/* Define a symbol indicating that we are using elfos.h.
+ Some CPU specific configuration files use this. */
+#define USING_ELFOS_H
+
+/* The prefix to add to user-visible assembler symbols.
+
+ For ELF systems the convention is *not* to prepend a leading
+ underscore onto user-level symbol names. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
+/* The biggest alignment supported by ELF in bits. 32-bit ELF
+ supports section alignment up to (0x80000000 * 8), while
+ 64-bit ELF supports (0x8000000000000000 * 8). If this macro
+ is not defined, the default is the largest alignment supported
+ by 32-bit ELF and representable on a 32-bit host. Use this
+ macro to limit the alignment which can be specified using
+ the `__attribute__ ((aligned (N)))' construct. */
+#ifndef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT (((unsigned int) 1 << 28) * 8)
+#endif
+
+/* Use periods rather than dollar signs in special g++ assembler names. */
+
+#define NO_DOLLAR_IN_LABEL
+
+/* Writing `int' for a bit-field forces int alignment for the structure. */
+
+#ifndef PCC_BITFIELD_TYPE_MATTERS
+#define PCC_BITFIELD_TYPE_MATTERS 1
+#endif
+
+/* All ELF targets can support DWARF-2. */
+
+#define DWARF2_DEBUGGING_INFO 1
+
+/* All ELF targets can support CTF. */
+
+#define CTF_DEBUGGING_INFO 1
+
+/* All ELF targets can support BTF. */
+
+#define BTF_DEBUGGING_INFO 1
+
+/* The GNU tools operate better with dwarf2, and it is required by some
+ psABI's. Since we don't have any native tools to be compatible with,
+ default to dwarf2. */
+
+#ifndef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#endif
+
+/* All SVR4 targets use the ELF object file format. */
+#define OBJECT_FORMAT_ELF
+
+
+/* Output #ident as a .ident. */
+
+#undef TARGET_ASM_OUTPUT_IDENT
+#define TARGET_ASM_OUTPUT_IDENT default_asm_output_ident_directive
+
+#undef SET_ASM_OP
+#define SET_ASM_OP "\t.set\t"
+
+/* Most svr4 assemblers want a .file directive at the beginning of
+ their input file. */
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+
+/* This is how to allocate empty space in some section. The .zero
+ pseudo-op is used for this on most svr4 assemblers. */
+
+#define SKIP_ASM_OP "\t.zero\t"
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(FILE, SIZE) \
+ fprintf ((FILE), "%s" HOST_WIDE_INT_PRINT_UNSIGNED "\n",\
+ SKIP_ASM_OP, (SIZE))
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'.
+
+ For most svr4 systems, the convention is that any symbol which begins
+ with a period is not put into the linker symbol table by the assembler. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
+ do \
+ { \
+ char *__p; \
+ (LABEL)[0] = '*'; \
+ (LABEL)[1] = '.'; \
+ __p = stpcpy (&(LABEL)[2], PREFIX); \
+ sprint_ul (__p, (unsigned long) (NUM)); \
+ } \
+ while (0)
+
+/* Output the label which precedes a jumptable. Note that for all svr4
+ systems where we actually generate jumptables (which is to say every
+ svr4 target except i386, where we use casesi instead) we put the jump-
+ tables into the .rodata section and since other stuff could have been
+ put into the .rodata section prior to any given jumptable, we have to
+ make sure that the location counter for the .rodata section gets pro-
+ perly re-aligned prior to the actual beginning of the jump table. */
+
+#undef ALIGN_ASM_OP
+#define ALIGN_ASM_OP "\t.align\t"
+
+#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL
+#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE, PREFIX, NUM, TABLE) \
+ ASM_OUTPUT_ALIGN ((FILE), 2)
+#endif
+
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
+ do \
+ { \
+ ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE); \
+ (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); \
+ } \
+ while (0)
+
+/* The standard SVR4 assembler seems to require that certain builtin
+ library routines (e.g. .udiv) be explicitly declared as .globl
+ in each assembly file where they are referenced. */
+
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
+ (*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0))
+
+/* This says how to output assembler code to declare an
+ uninitialized external linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+#define COMMON_ASM_OP "\t.comm\t"
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ do \
+ { \
+ fprintf ((FILE), "%s", COMMON_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n", \
+ (SIZE), (ALIGN) / BITS_PER_UNIT); \
+ } \
+ while (0)
+
+/* This says how to output assembler code to declare an
+ uninitialized internal linkage data object. Under SVR4,
+ the linker seems to want the alignment of data objects
+ to depend on their types. We do exactly that here. */
+
+#define LOCAL_ASM_OP "\t.local\t"
+
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+ do \
+ { \
+ fprintf ((FILE), "%s", LOCAL_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "\n"); \
+ ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \
+ } \
+ while (0)
+
+/* This is the pseudo-op used to generate a contiguous sequence of byte
+ values from a double-quoted string WITHOUT HAVING A TERMINATING NUL
+ AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */
+
+#undef ASCII_DATA_ASM_OP
+#define ASCII_DATA_ASM_OP "\t.ascii\t"
+
+/* Support a read-only data section. */
+#define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rodata"
+
+/* On svr4, we *do* have support for the .init and .fini sections, and we
+ can put stuff in there to be executed before and after `main'. We let
+ crtstuff.c and other files know this by defining the following symbols.
+ The definitions say how to change sections to the .init and .fini
+ sections. This is the same for all known svr4 assemblers. */
+
+#define INIT_SECTION_ASM_OP "\t.section\t.init"
+#define FINI_SECTION_ASM_OP "\t.section\t.fini"
+
+/* Output assembly directive to move to the beginning of current section. */
+#ifdef HAVE_GAS_SUBSECTION_ORDERING
+# define ASM_SECTION_START_OP "\t.subsection\t-1"
+# define ASM_OUTPUT_SECTION_START(FILE) \
+ fprintf ((FILE), "%s\n", ASM_SECTION_START_OP)
+#endif
+
+#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+
+/* Switch into a generic section. */
+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
+
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION default_elf_select_rtx_section
+#undef TARGET_ASM_SELECT_SECTION
+#define TARGET_ASM_SELECT_SECTION default_elf_select_section
+#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
+#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS true
+
+/* Define the strings used for the special svr4 .type and .size directives.
+ These strings generally do not vary from one system running svr4 to
+ another, but if a given system (e.g. m88k running svr) needs to use
+ different pseudo-op names for these, they may be overridden in the
+ file which includes this one. */
+
+#define TYPE_ASM_OP "\t.type\t"
+#define SIZE_ASM_OP "\t.size\t"
+
+/* This is how we tell the assembler that a symbol is weak. */
+
+#define ASM_WEAKEN_LABEL(FILE, NAME) \
+ do \
+ { \
+ fputs ("\t.weak\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputc ('\n', (FILE)); \
+ } \
+ while (0)
+
+#define ASM_OUTPUT_SYMVER_DIRECTIVE(FILE, NAME, NAME2) \
+ do \
+ { \
+ fputs ("\t.symver\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputs (", ", (FILE)); \
+ assemble_name ((FILE), (NAME2)); \
+ fputc ('\n', (FILE)); \
+ } \
+ while (0)
+
+/* The following macro defines the format used to output the second
+ operand of the .type assembler directive. Different svr4 assemblers
+ expect various different forms for this operand. The one given here
+ is just a default. You may need to override it in your machine-
+ specific tm.h file (depending upon the particulars of your assembler). */
+
+#define TYPE_OPERAND_FMT "@%s"
+
+/* Write the extra assembler code needed to declare a function's result.
+ Most svr4 assemblers don't require any special declaration of the
+ result value, but there are exceptions. */
+
+#ifndef ASM_DECLARE_RESULT
+#define ASM_DECLARE_RESULT(FILE, RESULT)
+#endif
+
+/* These macros generate the special .type and .size directives which
+ are used to set the corresponding fields of the linker symbol table
+ entries in an ELF object file under SVR4. These macros also output
+ the starting labels for the relevant functions/objects. */
+
+/* Write the extra assembler code needed to declare a function properly.
+ Some svr4 assemblers need to also have something extra said about the
+ function's return value. We allow for that here. */
+
+#ifndef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_FUNCTION_LABEL (FILE, NAME, DECL); \
+ } \
+ while (0)
+#endif
+
+/* Write the extra assembler code needed to declare the name of a
+ cold function partition properly. Some svr4 assemblers need to also
+ have something extra said about the function's return value. We
+ allow for that here. */
+
+#ifndef ASM_DECLARE_COLD_FUNCTION_NAME
+#define ASM_DECLARE_COLD_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_FUNCTION_LABEL (FILE, NAME, DECL); \
+ } \
+ while (0)
+#endif
+
+/* Write the extra assembler code needed to declare an object properly. */
+
+#ifdef HAVE_GAS_GNU_UNIQUE_OBJECT
+#define USE_GNU_UNIQUE_OBJECT flag_gnu_unique
+#else
+#define USE_GNU_UNIQUE_OBJECT 0
+#endif
+
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ HOST_WIDE_INT size; \
+ \
+ /* For template static data member instantiations or \
+ inline fn local statics and their guard variables, use \
+ gnu_unique_object so that they will be combined even under \
+ RTLD_LOCAL. Don't use gnu_unique_object for typeinfo, \
+ vtables and other read-only artificial decls. */ \
+ if (USE_GNU_UNIQUE_OBJECT && DECL_ONE_ONLY (DECL) \
+ && (!DECL_ARTIFICIAL (DECL) || !TREE_READONLY (DECL))) \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "gnu_unique_object"); \
+ else \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = tree_to_uhwi (DECL_SIZE_UNIT (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } \
+ while (0)
+
+/* Output the size directive for a decl in rest_of_decl_compilation
+ in the case where we did not do so before the initializer.
+ Once we find the error_mark_node, we know that the value of
+ size_directive_output was set
+ by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
+
+#undef ASM_FINISH_DECLARE_OBJECT
+#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END)\
+ do \
+ { \
+ const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
+ \
+ if (!flag_inhibit_size_directive \
+ && DECL_SIZE (DECL) \
+ && ! AT_END && TOP_LEVEL \
+ && DECL_INITIAL (DECL) == error_mark_node \
+ && !size_directive_output) \
+ { \
+ size_directive_output = 1; \
+ size = tree_to_uhwi (DECL_SIZE_UNIT (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
+ } \
+ } \
+ while (0)
+
+/* This is how to declare the size of a function. */
+#ifndef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
+ } \
+ while (0)
+#endif
+
+/* This is how to declare the size of a cold function partition. */
+#ifndef ASM_DECLARE_COLD_FUNCTION_SIZE
+#define ASM_DECLARE_COLD_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
+ } \
+ while (0)
+#endif
+
+/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
+ ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
+ corresponds to a particular byte value [0..255]. For any
+ given byte value, if the value in the corresponding table
+ position is zero, the given character can be output directly.
+ If the table value is 1, the byte must be output as a \ooo
+ octal escape. If the tables value is anything else, then the
+ byte value should be output as a \ followed by the value
+ in the table. Note that we can use standard UN*X escape
+ sequences for many control characters, but we don't use
+ \a to represent BEL because some svr4 assemblers (e.g. on
+ the i386) don't know about that. Also, we don't use \v
+ since some versions of gas, such as 2.2 did not accept it. */
+
+#define ELF_ASCII_ESCAPES \
+"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
+\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\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\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\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\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\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\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
+
+/* Some svr4 assemblers have a limit on the number of characters which
+ can appear in the operand of a .string directive. If your assembler
+ has such a limitation, you should define STRING_LIMIT to reflect that
+ limit. Note that at least some svr4 assemblers have a limit on the
+ actual number of bytes in the double-quoted string, and that they
+ count each character in an escape sequence as one byte. Thus, an
+ escape sequence like \377 would count as four bytes.
+
+ If your target assembler doesn't support the .string directive, you
+ should define this to zero.
+*/
+
+#define ELF_STRING_LIMIT ((unsigned) 256)
+
+#define STRING_ASM_OP "\t.string\t"
+
+/* The routine used to output NUL terminated strings. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable, especially for targets like the i386
+ (where the only alternative is to output character sequences as
+ comma separated lists of numbers). */
+
+#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
+ default_elf_asm_output_limited_string ((FILE), (STR))
+
+/* The routine used to output sequences of byte values. We use a special
+ version of this for most svr4 targets because doing so makes the
+ generated assembly code more compact (and thus faster to assemble)
+ as well as more readable. Note that if we find subparts of the
+ character sequence which end with NUL (and which are shorter than
+ STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
+ default_elf_asm_output_ascii ((FILE), (STR), (LENGTH))
+
+/* Allow the use of the -frecord-gcc-switches switch via the
+ elf_record_gcc_switches function defined in varasm.cc. */
+#undef TARGET_ASM_RECORD_GCC_SWITCHES
+#define TARGET_ASM_RECORD_GCC_SWITCHES elf_record_gcc_switches
+
+/* A C statement (sans semicolon) to output to the stdio stream STREAM
+ any text necessary for declaring the name of an external symbol
+ named NAME which is referenced in this compilation but not defined.
+ It is needed to properly support non-default visibility. */
+
+#ifndef ASM_OUTPUT_EXTERNAL
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+ default_elf_asm_output_external (FILE, DECL, NAME)
+#endif
+
+#undef TARGET_LIBC_HAS_FUNCTION
+#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
+
+/* ELF support needed only by D front-end. */
+
+#define TARGET_D_MINFO_SECTION "minfo"
+#define TARGET_D_MINFO_START_NAME "__start_minfo"
+#define TARGET_D_MINFO_END_NAME "__stop_minfo"
diff --git a/support/cpp/gcc/config/flat.h b/support/cpp/gcc/config/flat.h
new file mode 100644
index 000000000..4c803735c
--- /dev/null
+++ b/support/cpp/gcc/config/flat.h
@@ -0,0 +1,22 @@
+/* Defines to be used for targets that support flat executables.
+ Copyright (C) 2006-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 macro applies on top of OBJECT_FORMAT_ELF and indicates that
+ we want to support both flat and ELF output. */
+#define OBJECT_FORMAT_FLAT
diff --git a/support/cpp/gcc/config/fuchsia.h b/support/cpp/gcc/config/fuchsia.h
new file mode 100644
index 000000000..0baf6f1f3
--- /dev/null
+++ b/support/cpp/gcc/config/fuchsia.h
@@ -0,0 +1,70 @@
+/* Base configuration file for all Fuchsia targets.
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+ Contributed by Google.
+
+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/>. */
+
+/* Common Fuchsia configuration. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared: crt1%O%s} crtbegin%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend%O%s"
+
+/* When neither pic nor pie has been specified, use PIE. */
+#undef CC1_SPEC
+#define CC1_SPEC "%{!fno-pic:%{!fno-PIC:%{!fpic:%{!fPIC:" \
+ "%{!fno-pie:%{!fno-PIE:%{!fpie:%{!fPIE: -fPIE}}}}}}}}"
+
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group" \
+ " -lmxio -lmagenta -lc -llaunchpad" \
+ "%{!static: -lgcc_s}" \
+ " --end-group"
+
+#undef LINK_SPEC
+#define LINK_SPEC "-z max-page-size=4096" \
+ " -z combreloc" \
+ " -z relro" \
+ " -z now" \
+ " -z text" \
+ "%{!hash-style: --hash-style=gnu}" \
+ "%{!no-eh-frame-hdr: --eh-frame-hdr}" \
+ "%{!no-build-id: --build-id}" \
+ "%{shared: -shared}" \
+ "%{!shared:%{!static:%{!dynamic-linker: -dynamic-linker=ld.so.1}}}"
+
+/* We are using MUSL as our libc. */
+#undef OPTION_MUSL
+#define OPTION_MUSL 1
+#undef OPTION_MUSL_P
+#define OPTION_MUSL_P(opts) 1
+
+#ifndef TARGET_SUB_OS_CPP_BUILTINS
+#define TARGET_SUB_OS_CPP_BUILTINS()
+#endif
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__fuchsia__"); \
+ TARGET_SUB_OS_CPP_BUILTINS(); \
+ } \
+ while (false)
+
diff --git a/support/cpp/gcc/config/fused-madd.opt b/support/cpp/gcc/config/fused-madd.opt
new file mode 100644
index 000000000..a6e416a44
--- /dev/null
+++ b/support/cpp/gcc/config/fused-madd.opt
@@ -0,0 +1,24 @@
+; -mfused-madd option (some targets only).
+;
+; Copyright (C) 2010-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/>.
+
+mfused-madd
+Target Undocumented Alias(ffp-contract=, fast, off) Warn(%<-mfused-madd%> is deprecated; use %<-ffp-contract=%> instead)
+
+; This comment is to ensure we retain the blank line above.
diff --git a/support/cpp/gcc/config/glibc-stdint.h b/support/cpp/gcc/config/glibc-stdint.h
new file mode 100644
index 000000000..a3652d011
--- /dev/null
+++ b/support/cpp/gcc/config/glibc-stdint.h
@@ -0,0 +1,64 @@
+/* Definitions for <stdint.h> types on systems using GNU libc or uClibc.
+ Copyright (C) 2008-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/>. */
+
+/* Systems using musl libc should use this header and make sure
+ OPTION_MUSL is defined correctly before using the TYPE macros. */
+#ifndef OPTION_MUSL
+#define OPTION_MUSL 0
+#endif
+#ifndef OPTION_MUSL_P
+#define OPTION_MUSL_P(opts) 0
+#endif
+
+#define SIG_ATOMIC_TYPE "int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE "signed char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_FAST8_TYPE "signed char"
+#define INT_FAST16_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long int" : "int")
+#define INT_FAST32_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long int" : "int")
+#define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_FAST8_TYPE "unsigned char"
+#define UINT_FAST16_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long unsigned int" : "unsigned int")
+#define UINT_FAST32_TYPE (LONG_TYPE_SIZE == 64 && !OPTION_MUSL ? "long unsigned int" : "unsigned int")
+#define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int")
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int")
diff --git a/support/cpp/gcc/config/gnu-user.h b/support/cpp/gcc/config/gnu-user.h
new file mode 100644
index 000000000..857c0e077
--- /dev/null
+++ b/support/cpp/gcc/config/gnu-user.h
@@ -0,0 +1,158 @@
+/* Definitions for systems using, at least optionally, a GNU
+ (glibc-based) userspace or other userspace with libc derived from
+ glibc (e.g. uClibc) or for which similar specs are appropriate.
+ Copyright (C) 1995-2022 Free Software Foundation, Inc.
+ Contributed by Eric Youngdale.
+ Modified for stabs-in-ELF by H.J. Lu (hjl@lucon.org).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#undef ASM_APP_ON
+#define ASM_APP_ON "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "#NO_APP\n"
+
+#if ENABLE_OFFLOADING == 1
+#define CRTOFFLOADBEGIN "%{fopenacc|fopenmp:crtoffloadbegin%O%s}"
+#define CRTOFFLOADEND "%{fopenacc|fopenmp:crtoffloadend%O%s}"
+#else
+#define CRTOFFLOADBEGIN ""
+#define CRTOFFLOADEND ""
+#endif
+
+#define GNU_USER_TARGET_CRTI "crti.o%s"
+#define GNU_USER_TARGET_CRTN "crtn.o%s"
+
+/* Provide a STARTFILE_SPEC appropriate for GNU userspace. Here we add
+ the GNU userspace magical crtbegin.o file (see crtstuff.c) which
+ provides part of the support for getting C++ file-scope static
+ object constructed before entering `main'. */
+
+#define GNU_USER_TARGET_STARTFILE_SPEC \
+ "%{shared:; \
+ pg|p|profile:%{static-pie:grcrt1.o%s;:gcrt1.o%s}; \
+ static:crt1.o%s; \
+ static-pie:rcrt1.o%s; \
+ " PIE_SPEC ":Scrt1.o%s; \
+ :crt1.o%s} " \
+ GNU_USER_TARGET_CRTI " \
+ %{static:crtbeginT.o%s; \
+ shared|static-pie|" PIE_SPEC ":crtbeginS.o%s; \
+ :crtbegin.o%s} \
+ %{fvtable-verify=none:%s; \
+ fvtable-verify=preinit:vtv_start_preinit.o%s; \
+ fvtable-verify=std:vtv_start.o%s} " \
+ CRTOFFLOADBEGIN
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC GNU_USER_TARGET_STARTFILE_SPEC
+
+/* Provide a ENDFILE_SPEC appropriate for GNU userspace. Here we tack on
+ the GNU userspace magical crtend.o file (see crtstuff.c) which
+ provides part of the support for getting C++ file-scope static
+ object constructed before entering `main', followed by a normal
+ GNU userspace "finalizer" file, `crtn.o'. */
+
+#define GNU_USER_TARGET_ENDFILE_SPEC \
+ "%{!static:%{fvtable-verify=none:%s; \
+ fvtable-verify=preinit:vtv_end_preinit.o%s; \
+ fvtable-verify=std:vtv_end.o%s}} \
+ %{static:crtend.o%s; \
+ shared|static-pie|" PIE_SPEC ":crtendS.o%s; \
+ :crtend.o%s} " \
+ GNU_USER_TARGET_CRTN " " \
+ CRTOFFLOADEND
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC GNU_USER_TARGET_ENDFILE_SPEC
+
+/* This is for -profile to use -lc_p instead of -lc. */
+#define GNU_USER_TARGET_CC1_SPEC "%{profile:-p}"
+#ifndef CC1_SPEC
+#define CC1_SPEC GNU_USER_TARGET_CC1_SPEC
+#endif
+
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+
+#define GNU_USER_TARGET_NO_PTHREADS_LIB_SPEC \
+ "%{shared:-lc} \
+ %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+
+#define GNU_USER_TARGET_LIB_SPEC \
+ "%{pthread:-lpthread} " \
+ GNU_USER_TARGET_NO_PTHREADS_LIB_SPEC
+
+#undef LIB_SPEC
+#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
+#endif
+
+#define GNU_USER_TARGET_LINK_GCC_C_SEQUENCE_SPEC \
+ "%{static|static-pie:--start-group} %G %{!nolibc:%L} \
+ %{static|static-pie:--end-group}%{!static:%{!static-pie:%G}}"
+
+#undef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC GNU_USER_TARGET_LINK_GCC_C_SEQUENCE_SPEC
+
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+#define TARGET_POSIX_IO
+
+#undef TARGET_LIBC_HAS_FUNCTION
+#define TARGET_LIBC_HAS_FUNCTION gnu_libc_has_function
+
+/* Link -lasan early on the command line. For -static-libasan, don't link
+ it for -shared link, the executable should be compiled with -static-libasan
+ in that case, and for executable link with --{,no-}whole-archive around
+ it to force everything into the executable. And similarly for -ltsan,
+ -lhwasan, and -llsan. */
+#if defined(HAVE_LD_STATIC_DYNAMIC)
+#undef LIBASAN_EARLY_SPEC
+#define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \
+ "%{static-libasan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -lasan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-libasan:-lasan}"
+#undef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC "%{static-libhwasan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -lhwasan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-libhwasan:-lhwasan}"
+#undef LIBTSAN_EARLY_SPEC
+#define LIBTSAN_EARLY_SPEC "%{!shared:libtsan_preinit%O%s} " \
+ "%{static-libtsan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -ltsan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-libtsan:-ltsan}"
+#undef LIBLSAN_EARLY_SPEC
+#define LIBLSAN_EARLY_SPEC "%{!shared:liblsan_preinit%O%s} " \
+ "%{static-liblsan:%{!shared:" \
+ LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \
+ LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}"
+#endif
+
+#undef TARGET_F951_OPTIONS
+#define TARGET_F951_OPTIONS "%{!nostdinc:\
+ %:fortran-preinclude-file(-fpre-include= math-vector-fortran.h finclude%s/)}"
diff --git a/support/cpp/gcc/config/gnu-user.opt b/support/cpp/gcc/config/gnu-user.opt
new file mode 100644
index 000000000..249089ecf
--- /dev/null
+++ b/support/cpp/gcc/config/gnu-user.opt
@@ -0,0 +1,38 @@
+; Options for systems using gnu-user.h.
+
+; 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/>.
+
+; See the GCC internals manual (options.texi) for a description of
+; this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+posix
+Driver
+
+profile
+Driver
+
+pthread
+Driver
+
+rdynamic
+Driver
+
+; This comment is to ensure we retain the blank line above.
diff --git a/support/cpp/gcc/config/gnu.h b/support/cpp/gcc/config/gnu.h
new file mode 100644
index 000000000..de2ead82b
--- /dev/null
+++ b/support/cpp/gcc/config/gnu.h
@@ -0,0 +1,39 @@
+/* Configuration common to all targets running the GNU system. */
+
+/*
+Copyright (C) 1994-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 of the License, 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. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#undef GNU_USER_TARGET_OS_CPP_BUILTINS
+#define GNU_USER_TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__gnu_hurd__"); \
+ builtin_define ("__GNU__"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__MACH__"); \
+ builtin_assert ("system=gnu"); \
+ builtin_assert ("system=mach"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } while (0)
+
+#define GNU_USER_TARGET_D_OS_VERSIONS() \
+ do { \
+ builtin_version ("Hurd"); \
+ builtin_version ("CRuntime_Glibc"); \
+ } while (0)
diff --git a/support/cpp/gcc/config/host-darwin.h b/support/cpp/gcc/config/host-darwin.h
new file mode 100644
index 000000000..fc2faf2fb
--- /dev/null
+++ b/support/cpp/gcc/config/host-darwin.h
@@ -0,0 +1,27 @@
+/* Darwin host-specific hook definitions.
+ Copyright (C) 2003-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/>. */
+
+extern void * darwin_gt_pch_get_address (size_t sz, int fd);
+extern int darwin_gt_pch_use_address (void *&addr, size_t sz, int fd,
+ size_t off);
+
+#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
+#define HOST_HOOKS_GT_PCH_GET_ADDRESS darwin_gt_pch_get_address
+#undef HOST_HOOKS_GT_PCH_USE_ADDRESS
+#define HOST_HOOKS_GT_PCH_USE_ADDRESS darwin_gt_pch_use_address
diff --git a/support/cpp/gcc/config/hpux-stdint.h b/support/cpp/gcc/config/hpux-stdint.h
new file mode 100644
index 000000000..b06813b47
--- /dev/null
+++ b/support/cpp/gcc/config/hpux-stdint.h
@@ -0,0 +1,34 @@
+
+/* These should be correct for ia64-hp-hpux11.23. */
+
+#define SIG_ATOMIC_TYPE "unsigned int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE "signed char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_FAST8_TYPE "int"
+#define INT_FAST16_TYPE "int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_FAST8_TYPE "unsigned int"
+#define UINT_FAST16_TYPE "unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INTPTR_TYPE "long int"
+#define UINTPTR_TYPE "long unsigned int"
diff --git a/support/cpp/gcc/config/i386/cpuid.h b/support/cpp/gcc/config/i386/cpuid.h
new file mode 100644
index 000000000..8b3dc2b1d
--- /dev/null
+++ b/support/cpp/gcc/config/i386/cpuid.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2007-2022 Free Software Foundation, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CPUID_H_INCLUDED
+#define _CPUID_H_INCLUDED
+
+/* %eax */
+#define bit_AVXVNNI (1 << 4)
+#define bit_AVX512BF16 (1 << 5)
+#define bit_HRESET (1 << 22)
+
+/* %ecx */
+#define bit_SSE3 (1 << 0)
+#define bit_PCLMUL (1 << 1)
+#define bit_LZCNT (1 << 5)
+#define bit_SSSE3 (1 << 9)
+#define bit_FMA (1 << 12)
+#define bit_CMPXCHG16B (1 << 13)
+#define bit_SSE4_1 (1 << 19)
+#define bit_SSE4_2 (1 << 20)
+#define bit_MOVBE (1 << 22)
+#define bit_POPCNT (1 << 23)
+#define bit_AES (1 << 25)
+#define bit_XSAVE (1 << 26)
+#define bit_OSXSAVE (1 << 27)
+#define bit_AVX (1 << 28)
+#define bit_F16C (1 << 29)
+#define bit_RDRND (1 << 30)
+
+/* %edx */
+#define bit_CMPXCHG8B (1 << 8)
+#define bit_CMOV (1 << 15)
+#define bit_MMX (1 << 23)
+#define bit_FXSAVE (1 << 24)
+#define bit_SSE (1 << 25)
+#define bit_SSE2 (1 << 26)
+
+/* Extended Features (%eax == 0x80000001) */
+/* %ecx */
+#define bit_LAHF_LM (1 << 0)
+#define bit_ABM (1 << 5)
+#define bit_SSE4a (1 << 6)
+#define bit_PRFCHW (1 << 8)
+#define bit_XOP (1 << 11)
+#define bit_LWP (1 << 15)
+#define bit_FMA4 (1 << 16)
+#define bit_TBM (1 << 21)
+#define bit_MWAITX (1 << 29)
+
+/* %edx */
+#define bit_MMXEXT (1 << 22)
+#define bit_LM (1 << 29)
+#define bit_3DNOWP (1 << 30)
+#define bit_3DNOW (1u << 31)
+
+/* %ebx */
+#define bit_CLZERO (1 << 0)
+#define bit_WBNOINVD (1 << 9)
+
+/* Extended Features (%eax == 7) */
+/* %ebx */
+#define bit_FSGSBASE (1 << 0)
+#define bit_SGX (1 << 2)
+#define bit_BMI (1 << 3)
+#define bit_HLE (1 << 4)
+#define bit_AVX2 (1 << 5)
+#define bit_BMI2 (1 << 8)
+#define bit_RTM (1 << 11)
+#define bit_AVX512F (1 << 16)
+#define bit_AVX512DQ (1 << 17)
+#define bit_RDSEED (1 << 18)
+#define bit_ADX (1 << 19)
+#define bit_AVX512IFMA (1 << 21)
+#define bit_CLFLUSHOPT (1 << 23)
+#define bit_CLWB (1 << 24)
+#define bit_AVX512PF (1 << 26)
+#define bit_AVX512ER (1 << 27)
+#define bit_AVX512CD (1 << 28)
+#define bit_SHA (1 << 29)
+#define bit_AVX512BW (1 << 30)
+#define bit_AVX512VL (1u << 31)
+
+/* %ecx */
+#define bit_PREFETCHWT1 (1 << 0)
+#define bit_AVX512VBMI (1 << 1)
+#define bit_PKU (1 << 3)
+#define bit_OSPKE (1 << 4)
+#define bit_WAITPKG (1 << 5)
+#define bit_AVX512VBMI2 (1 << 6)
+#define bit_SHSTK (1 << 7)
+#define bit_GFNI (1 << 8)
+#define bit_VAES (1 << 9)
+#define bit_AVX512VNNI (1 << 11)
+#define bit_VPCLMULQDQ (1 << 10)
+#define bit_AVX512BITALG (1 << 12)
+#define bit_AVX512VPOPCNTDQ (1 << 14)
+#define bit_RDPID (1 << 22)
+#define bit_MOVDIRI (1 << 27)
+#define bit_MOVDIR64B (1 << 28)
+#define bit_ENQCMD (1 << 29)
+#define bit_CLDEMOTE (1 << 25)
+#define bit_KL (1 << 23)
+
+/* %edx */
+#define bit_AVX5124VNNIW (1 << 2)
+#define bit_AVX5124FMAPS (1 << 3)
+#define bit_AVX512VP2INTERSECT (1 << 8)
+#define bit_AVX512FP16 (1 << 23)
+#define bit_IBT (1 << 20)
+#define bit_UINTR (1 << 5)
+#define bit_PCONFIG (1 << 18)
+#define bit_SERIALIZE (1 << 14)
+#define bit_TSXLDTRK (1 << 16)
+#define bit_AMX_BF16 (1 << 22)
+#define bit_AMX_TILE (1 << 24)
+#define bit_AMX_INT8 (1 << 25)
+
+/* Extended State Enumeration Sub-leaf (%eax == 0xd, %ecx == 1) */
+#define bit_XSAVEOPT (1 << 0)
+#define bit_XSAVEC (1 << 1)
+#define bit_XSAVES (1 << 3)
+
+/* PT sub leaf (%eax == 0x14, %ecx == 0) */
+/* %ebx */
+#define bit_PTWRITE (1 << 4)
+
+/* Keylocker leaf (%eax == 0x19) */
+/* %ebx */
+#define bit_AESKLE ( 1<<0 )
+#define bit_WIDEKL ( 1<<2 )
+
+
+/* Signatures for different CPU implementations as returned in uses
+ of cpuid with level 0. */
+#define signature_AMD_ebx 0x68747541
+#define signature_AMD_ecx 0x444d4163
+#define signature_AMD_edx 0x69746e65
+
+#define signature_CENTAUR_ebx 0x746e6543
+#define signature_CENTAUR_ecx 0x736c7561
+#define signature_CENTAUR_edx 0x48727561
+
+#define signature_CYRIX_ebx 0x69727943
+#define signature_CYRIX_ecx 0x64616574
+#define signature_CYRIX_edx 0x736e4978
+
+#define signature_INTEL_ebx 0x756e6547
+#define signature_INTEL_ecx 0x6c65746e
+#define signature_INTEL_edx 0x49656e69
+
+#define signature_TM1_ebx 0x6e617254
+#define signature_TM1_ecx 0x55504361
+#define signature_TM1_edx 0x74656d73
+
+#define signature_TM2_ebx 0x756e6547
+#define signature_TM2_ecx 0x3638784d
+#define signature_TM2_edx 0x54656e69
+
+#define signature_NSC_ebx 0x646f6547
+#define signature_NSC_ecx 0x43534e20
+#define signature_NSC_edx 0x79622065
+
+#define signature_NEXGEN_ebx 0x4778654e
+#define signature_NEXGEN_ecx 0x6e657669
+#define signature_NEXGEN_edx 0x72446e65
+
+#define signature_RISE_ebx 0x65736952
+#define signature_RISE_ecx 0x65736952
+#define signature_RISE_edx 0x65736952
+
+#define signature_SIS_ebx 0x20536953
+#define signature_SIS_ecx 0x20536953
+#define signature_SIS_edx 0x20536953
+
+#define signature_UMC_ebx 0x20434d55
+#define signature_UMC_ecx 0x20434d55
+#define signature_UMC_edx 0x20434d55
+
+#define signature_VIA_ebx 0x20414956
+#define signature_VIA_ecx 0x20414956
+#define signature_VIA_edx 0x20414956
+
+#define signature_VORTEX_ebx 0x74726f56
+#define signature_VORTEX_ecx 0x436f5320
+#define signature_VORTEX_edx 0x36387865
+
+#ifndef __x86_64__
+/* At least one cpu (Winchip 2) does not set %ebx and %ecx
+ for cpuid leaf 1. Forcibly zero the two registers before
+ calling cpuid as a precaution. */
+#define __cpuid(level, a, b, c, d) \
+ do { \
+ if (__builtin_constant_p (level) && (level) != 1) \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level)); \
+ else \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level), "1" (0), "2" (0)); \
+ } while (0)
+#else
+#define __cpuid(level, a, b, c, d) \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level))
+#endif
+
+#define __cpuid_count(level, count, a, b, c, d) \
+ __asm__ __volatile__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level), "2" (count))
+
+
+/* Return highest supported input value for cpuid instruction. ext can
+ be either 0x0 or 0x80000000 to return highest supported value for
+ basic or extended cpuid information. Function returns 0 if cpuid
+ is not supported or whatever cpuid returns in eax register. If sig
+ pointer is non-null, then first four bytes of the signature
+ (as found in ebx register) are returned in location pointed by sig. */
+
+static __inline unsigned int
+__get_cpuid_max (unsigned int __ext, unsigned int *__sig)
+{
+ unsigned int __eax, __ebx, __ecx, __edx;
+
+#ifndef __x86_64__
+ /* See if we can use cpuid. On AMD64 we always can. */
+#if __GNUC__ >= 3
+ __asm__ ("pushf{l|d}\n\t"
+ "pushf{l|d}\n\t"
+ "pop{l}\t%0\n\t"
+ "mov{l}\t{%0, %1|%1, %0}\n\t"
+ "xor{l}\t{%2, %0|%0, %2}\n\t"
+ "push{l}\t%0\n\t"
+ "popf{l|d}\n\t"
+ "pushf{l|d}\n\t"
+ "pop{l}\t%0\n\t"
+ "popf{l|d}\n\t"
+ : "=&r" (__eax), "=&r" (__ebx)
+ : "i" (0x00200000));
+#else
+/* Host GCCs older than 3.0 weren't supporting Intel asm syntax
+ nor alternatives in i386 code. */
+ __asm__ ("pushfl\n\t"
+ "pushfl\n\t"
+ "popl\t%0\n\t"
+ "movl\t%0, %1\n\t"
+ "xorl\t%2, %0\n\t"
+ "pushl\t%0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl\t%0\n\t"
+ "popfl\n\t"
+ : "=&r" (__eax), "=&r" (__ebx)
+ : "i" (0x00200000));
+#endif
+
+ if (!((__eax ^ __ebx) & 0x00200000))
+ return 0;
+#endif
+
+ /* Host supports cpuid. Return highest supported cpuid input value. */
+ __cpuid (__ext, __eax, __ebx, __ecx, __edx);
+
+ if (__sig)
+ *__sig = __ebx;
+
+ return __eax;
+}
+
+/* Return cpuid data for requested cpuid leaf, as found in returned
+ eax, ebx, ecx and edx registers. The function checks if cpuid is
+ supported and returns 1 for valid cpuid information or 0 for
+ unsupported cpuid leaf. All pointers are required to be non-null. */
+
+static __inline int
+__get_cpuid (unsigned int __leaf,
+ unsigned int *__eax, unsigned int *__ebx,
+ unsigned int *__ecx, unsigned int *__edx)
+{
+ unsigned int __ext = __leaf & 0x80000000;
+ unsigned int __maxlevel = __get_cpuid_max (__ext, 0);
+
+ if (__maxlevel == 0 || __maxlevel < __leaf)
+ return 0;
+
+ __cpuid (__leaf, *__eax, *__ebx, *__ecx, *__edx);
+ return 1;
+}
+
+/* Same as above, but sub-leaf can be specified. */
+
+static __inline int
+__get_cpuid_count (unsigned int __leaf, unsigned int __subleaf,
+ unsigned int *__eax, unsigned int *__ebx,
+ unsigned int *__ecx, unsigned int *__edx)
+{
+ unsigned int __ext = __leaf & 0x80000000;
+ unsigned int __maxlevel = __get_cpuid_max (__ext, 0);
+
+ if (__maxlevel == 0 || __maxlevel < __leaf)
+ return 0;
+
+ __cpuid_count (__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
+ return 1;
+}
+
+static __inline void
+__cpuidex (int __cpuid_info[4], int __leaf, int __subleaf)
+{
+ __cpuid_count (__leaf, __subleaf, __cpuid_info[0], __cpuid_info[1],
+ __cpuid_info[2], __cpuid_info[3]);
+}
+
+#endif /* _CPUID_H_INCLUDED */
diff --git a/support/cpp/gcc/config/initfini-array.h b/support/cpp/gcc/config/initfini-array.h
new file mode 100644
index 000000000..c9b20d57d
--- /dev/null
+++ b/support/cpp/gcc/config/initfini-array.h
@@ -0,0 +1,45 @@
+/* Definitions for ELF systems with .init_array/.fini_array section
+ support.
+ 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.
+
+ 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/>. */
+
+#if HAVE_INITFINI_ARRAY_SUPPORT
+
+#define USE_INITFINI_ARRAY
+
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+
+#undef INIT_ARRAY_SECTION_ASM_OP
+#define INIT_ARRAY_SECTION_ASM_OP
+
+#undef FINI_ARRAY_SECTION_ASM_OP
+#define FINI_ARRAY_SECTION_ASM_OP
+
+/* Use .init_array/.fini_array section for constructors and destructors. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR default_elf_init_array_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR default_elf_fini_array_asm_out_destructor
+
+#endif
diff --git a/support/cpp/gcc/config/kfreebsd-gnu.h b/support/cpp/gcc/config/kfreebsd-gnu.h
new file mode 100644
index 000000000..f74a627bc
--- /dev/null
+++ b/support/cpp/gcc/config/kfreebsd-gnu.h
@@ -0,0 +1,41 @@
+/* Definitions for kFreeBSD-based GNU systems with ELF format
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Robert Millan.
+
+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 GNU_USER_TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__FreeBSD_kernel__"); \
+ builtin_define ("__GLIBC__"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } \
+ while (0)
+
+#define GNU_USER_TARGET_D_OS_VERSIONS() \
+ do { \
+ builtin_version ("FreeBSD"); \
+ builtin_version ("CRuntime_Glibc"); \
+ } while (0)
+
+#define GNU_USER_DYNAMIC_LINKER GLIBC_DYNAMIC_LINKER
+#define GNU_USER_DYNAMIC_LINKER32 GLIBC_DYNAMIC_LINKER32
+#define GNU_USER_DYNAMIC_LINKER64 GLIBC_DYNAMIC_LINKER64
+#define GNU_USER_DYNAMIC_LINKERX32 GLIBC_DYNAMIC_LINKERX32
diff --git a/support/cpp/gcc/config/kopensolaris-gnu.h b/support/cpp/gcc/config/kopensolaris-gnu.h
new file mode 100644
index 000000000..8379f960b
--- /dev/null
+++ b/support/cpp/gcc/config/kopensolaris-gnu.h
@@ -0,0 +1,40 @@
+/* Definitions for kOpenSolaris-based GNU systems with ELF format
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Robert Millan.
+
+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/>. */
+
+#undef GNU_USER_TARGET_OS_CPP_BUILTINS
+#define GNU_USER_TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__OpenSolaris_kernel__"); \
+ builtin_define ("__GLIBC__"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } \
+ while (0)
+
+#define GNU_USER_TARGET_D_OS_VERSIONS() \
+ do { \
+ builtin_version ("Solaris"); \
+ builtin_version ("CRuntime_Glibc"); \
+ } while (0)
+
+#undef GNU_USER_DYNAMIC_LINKER
+#define GNU_USER_DYNAMIC_LINKER "/lib/ld.so.1"
diff --git a/support/cpp/gcc/config/linux-android.h b/support/cpp/gcc/config/linux-android.h
new file mode 100644
index 000000000..cf340660a
--- /dev/null
+++ b/support/cpp/gcc/config/linux-android.h
@@ -0,0 +1,65 @@
+/* Configuration file for Linux Android targets.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+ Contributed by Doug Kwan (dougkwan@google.com)
+ Rewritten by CodeSourcery, 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/>. */
+
+#define ANDROID_TARGET_OS_CPP_BUILTINS() \
+ do { \
+ if (TARGET_ANDROID) \
+ builtin_define ("__ANDROID__"); \
+ } while (0)
+
+#define ANDROID_TARGET_D_OS_VERSIONS() \
+ do { \
+ if (TARGET_ANDROID) \
+ builtin_version ("Android"); \
+ } while (0)
+
+#if ANDROID_DEFAULT
+# define NOANDROID "mno-android"
+#else
+# define NOANDROID "!mandroid"
+#endif
+
+#define LINUX_OR_ANDROID_CC(LINUX_SPEC, ANDROID_SPEC) \
+ "%{" NOANDROID "|tno-android-cc:" LINUX_SPEC ";:" ANDROID_SPEC "}"
+
+#define LINUX_OR_ANDROID_LD(LINUX_SPEC, ANDROID_SPEC) \
+ "%{" NOANDROID "|tno-android-ld:" LINUX_SPEC ";:" ANDROID_SPEC "}"
+
+#define ANDROID_LINK_SPEC \
+ "%{shared: -Bsymbolic}"
+
+#define ANDROID_CC1_SPEC \
+ "%{!mglibc:%{!muclibc:%{!mbionic: -mbionic}}} " \
+ "%{!fno-pic:%{!fno-PIC:%{!fpic:%{!fPIC: -fPIC}}}}"
+
+#define ANDROID_CC1PLUS_SPEC \
+ "%{!fexceptions:%{!fno-exceptions: -fno-exceptions}} " \
+ "%{!frtti:%{!fno-rtti: -fno-rtti}}"
+
+#define ANDROID_LIB_SPEC \
+ "%{!static: -ldl}"
+
+#define ANDROID_STARTFILE_SPEC \
+ "%{shared: crtbegin_so%O%s;:" \
+ " %{static: crtbegin_static%O%s;: crtbegin_dynamic%O%s}}"
+
+#define ANDROID_ENDFILE_SPEC \
+ "%{shared: crtend_so%O%s;: crtend_android%O%s}"
diff --git a/support/cpp/gcc/config/linux-android.opt b/support/cpp/gcc/config/linux-android.opt
new file mode 100644
index 000000000..9b07c4228
--- /dev/null
+++ b/support/cpp/gcc/config/linux-android.opt
@@ -0,0 +1,30 @@
+; Android specific options.
+
+; Copyright (C) 2008-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/>.
+
+mandroid
+Target Mask(ANDROID) Var(flag_android) Init(ANDROID_DEFAULT ? OPTION_MASK_ANDROID : 0)
+Generate code for the Android platform.
+
+tno-android-cc
+Driver
+
+tno-android-ld
+Driver
+
diff --git a/support/cpp/gcc/config/linux-protos.h b/support/cpp/gcc/config/linux-protos.h
new file mode 100644
index 000000000..c29c67e0c
--- /dev/null
+++ b/support/cpp/gcc/config/linux-protos.h
@@ -0,0 +1,22 @@
+/* Prototypes.
+ Copyright (C) 2013-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/>. */
+
+extern bool linux_has_ifunc_p (void);
+
+extern bool linux_libc_has_function (enum function_class fn_class, tree);
diff --git a/support/cpp/gcc/config/linux.h b/support/cpp/gcc/config/linux.h
new file mode 100644
index 000000000..74f70793d
--- /dev/null
+++ b/support/cpp/gcc/config/linux.h
@@ -0,0 +1,228 @@
+/* Definitions for systems using the Linux kernel, with or without
+ MMU, using ELF at the compiler level but possibly FLT for final
+ linked executables and shared libraries in some no-MMU cases, and
+ possibly with a choice of libc implementations.
+ Copyright (C) 1995-2022 Free Software Foundation, Inc.
+ Contributed by Eric Youngdale.
+ Modified for stabs-in-ELF by H.J. Lu (hjl@lucon.org).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* C libraries supported on Linux. */
+#ifdef SINGLE_LIBC
+#define OPTION_GLIBC_P(opts) (DEFAULT_LIBC == LIBC_GLIBC)
+#define OPTION_UCLIBC_P(opts) (DEFAULT_LIBC == LIBC_UCLIBC)
+#define OPTION_BIONIC_P(opts) (DEFAULT_LIBC == LIBC_BIONIC)
+#undef OPTION_MUSL_P
+#define OPTION_MUSL_P(opts) (DEFAULT_LIBC == LIBC_MUSL)
+#else
+#define OPTION_GLIBC_P(opts) ((opts)->x_linux_libc == LIBC_GLIBC)
+#define OPTION_UCLIBC_P(opts) ((opts)->x_linux_libc == LIBC_UCLIBC)
+#define OPTION_BIONIC_P(opts) ((opts)->x_linux_libc == LIBC_BIONIC)
+#undef OPTION_MUSL_P
+#define OPTION_MUSL_P(opts) ((opts)->x_linux_libc == LIBC_MUSL)
+#endif
+#define OPTION_GLIBC OPTION_GLIBC_P (&global_options)
+#define OPTION_UCLIBC OPTION_UCLIBC_P (&global_options)
+#define OPTION_BIONIC OPTION_BIONIC_P (&global_options)
+#undef OPTION_MUSL
+#define OPTION_MUSL OPTION_MUSL_P (&global_options)
+
+#define GNU_USER_TARGET_OS_CPP_BUILTINS() \
+ do { \
+ if (OPTION_GLIBC) \
+ builtin_define ("__gnu_linux__"); \
+ builtin_define_std ("linux"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } while (0)
+
+#define GNU_USER_TARGET_D_OS_VERSIONS() \
+ do { \
+ builtin_version ("linux"); \
+ if (OPTION_GLIBC) \
+ builtin_version ("CRuntime_Glibc"); \
+ else if (OPTION_UCLIBC) \
+ builtin_version ("CRuntime_UClibc"); \
+ else if (OPTION_BIONIC) \
+ builtin_version ("CRuntime_Bionic"); \
+ else if (OPTION_MUSL) \
+ builtin_version ("CRuntime_Musl"); \
+ } while (0)
+
+/* Determine which dynamic linker to use depending on whether GLIBC or
+ uClibc or Bionic or musl is the default C library and whether
+ -muclibc or -mglibc or -mbionic or -mmusl has been passed to change
+ the default. */
+
+#define CHOOSE_DYNAMIC_LINKER1(LIBC1, LIBC2, LIBC3, LIBC4, LD1, LD2, LD3, LD4) \
+ "%{" LIBC2 ":" LD2 ";:%{" LIBC3 ":" LD3 ";:%{" LIBC4 ":" LD4 ";:" LD1 "}}}"
+
+#if DEFAULT_LIBC == LIBC_GLIBC
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("mglibc", "muclibc", "mbionic", "mmusl", G, U, B, M)
+#elif DEFAULT_LIBC == LIBC_UCLIBC
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("muclibc", "mglibc", "mbionic", "mmusl", U, G, B, M)
+#elif DEFAULT_LIBC == LIBC_BIONIC
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("mbionic", "mglibc", "muclibc", "mmusl", B, G, U, M)
+#elif DEFAULT_LIBC == LIBC_MUSL
+#define CHOOSE_DYNAMIC_LINKER(G, U, B, M) \
+ CHOOSE_DYNAMIC_LINKER1 ("mmusl", "mglibc", "muclibc", "mbionic", M, G, U, B)
+#else
+#error "Unsupported DEFAULT_LIBC"
+#endif /* DEFAULT_LIBC */
+
+/* For most targets the following definitions suffice;
+ GLIBC_DYNAMIC_LINKER must be defined for each target using them, or
+ GLIBC_DYNAMIC_LINKER32 and GLIBC_DYNAMIC_LINKER64 for targets
+ supporting both 32-bit and 64-bit compilation. */
+#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKERX32 "/lib/ldx32-uClibc.so.0"
+#define BIONIC_DYNAMIC_LINKER "/system/bin/linker"
+#define BIONIC_DYNAMIC_LINKER32 "/system/bin/linker"
+#define BIONIC_DYNAMIC_LINKER64 "/system/bin/linker64"
+#define BIONIC_DYNAMIC_LINKERX32 "/system/bin/linkerx32"
+/* Should be redefined for each target that supports musl. */
+#define MUSL_DYNAMIC_LINKER "/dev/null"
+#define MUSL_DYNAMIC_LINKER32 "/dev/null"
+#define MUSL_DYNAMIC_LINKER64 "/dev/null"
+#define MUSL_DYNAMIC_LINKERX32 "/dev/null"
+
+#define GNU_USER_DYNAMIC_LINKER \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER, \
+ BIONIC_DYNAMIC_LINKER, MUSL_DYNAMIC_LINKER)
+#define GNU_USER_DYNAMIC_LINKER32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32, \
+ BIONIC_DYNAMIC_LINKER32, MUSL_DYNAMIC_LINKER32)
+#define GNU_USER_DYNAMIC_LINKER64 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, \
+ BIONIC_DYNAMIC_LINKER64, MUSL_DYNAMIC_LINKER64)
+#define GNU_USER_DYNAMIC_LINKERX32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERX32, UCLIBC_DYNAMIC_LINKERX32, \
+ BIONIC_DYNAMIC_LINKERX32, MUSL_DYNAMIC_LINKERX32)
+
+/* Whether we have Bionic libc runtime */
+#undef TARGET_HAS_BIONIC
+#define TARGET_HAS_BIONIC (OPTION_BIONIC)
+
+/* musl avoids problematic includes by rearranging the include directories.
+ * Unfortunately, this is mostly duplicated from cppdefault.cc */
+#if DEFAULT_LIBC == LIBC_MUSL
+#define INCLUDE_DEFAULTS_MUSL_GPP \
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1, \
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 }, \
+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1, \
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 1 }, \
+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, \
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
+
+#ifdef LOCAL_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_LOCAL \
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 }, \
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 },
+#else
+#define INCLUDE_DEFAULTS_MUSL_LOCAL
+#endif
+
+#ifdef PREFIX_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_PREFIX \
+ { PREFIX_INCLUDE_DIR, 0, 0, 1, 0, 0},
+#else
+#define INCLUDE_DEFAULTS_MUSL_PREFIX
+#endif
+
+#ifdef CROSS_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_CROSS \
+ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0, 0},
+#else
+#define INCLUDE_DEFAULTS_MUSL_CROSS
+#endif
+
+#ifdef TOOL_INCLUDE_DIR
+#define INCLUDE_DEFAULTS_MUSL_TOOL \
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0},
+#else
+#define INCLUDE_DEFAULTS_MUSL_TOOL
+#endif
+
+#ifdef NATIVE_SYSTEM_HEADER_DIR
+#define INCLUDE_DEFAULTS_MUSL_NATIVE \
+ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 2 }, \
+ { NATIVE_SYSTEM_HEADER_DIR, 0, 0, 0, 1, 0 },
+#else
+#define INCLUDE_DEFAULTS_MUSL_NATIVE
+#endif
+
+#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT)
+# undef INCLUDE_DEFAULTS_MUSL_LOCAL
+# define INCLUDE_DEFAULTS_MUSL_LOCAL
+# undef INCLUDE_DEFAULTS_MUSL_NATIVE
+# define INCLUDE_DEFAULTS_MUSL_NATIVE
+#else
+# undef INCLUDE_DEFAULTS_MUSL_CROSS
+# define INCLUDE_DEFAULTS_MUSL_CROSS
+#endif
+
+#undef INCLUDE_DEFAULTS
+#define INCLUDE_DEFAULTS \
+ { \
+ INCLUDE_DEFAULTS_MUSL_GPP \
+ INCLUDE_DEFAULTS_MUSL_LOCAL \
+ INCLUDE_DEFAULTS_MUSL_PREFIX \
+ INCLUDE_DEFAULTS_MUSL_CROSS \
+ INCLUDE_DEFAULTS_MUSL_TOOL \
+ INCLUDE_DEFAULTS_MUSL_NATIVE \
+ { GCC_INCLUDE_DIR, "GCC", 0, 1, 0, 0 }, \
+ { 0, 0, 0, 0, 0, 0 } \
+ }
+#endif
+
+#if (DEFAULT_LIBC == LIBC_UCLIBC) && defined (SINGLE_LIBC) /* uClinux */
+/* This is a *uclinux* target. We don't define below macros to normal linux
+ versions, because doing so would require *uclinux* targets to include
+ linux.cc, linux-protos.h, linux.opt, etc. We could, alternatively, add
+ these files to *uclinux* targets, but that would only pollute option list
+ (add -mglibc, etc.) without adding any useful support. */
+
+/* Define TARGET_LIBC_HAS_FUNCTION for *uclinux* targets to
+ no_c99_libc_has_function, because uclibc does not, normally, have
+ c99 runtime. If, in special cases, uclibc does have c99 runtime,
+ this should be defined to a new hook. Also please note that for targets
+ like *-linux-uclibc that similar check will also need to be added to
+ linux_libc_has_function. */
+# undef TARGET_LIBC_HAS_FUNCTION
+# define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
+
+#else /* !uClinux, i.e., normal Linux */
+
+/* Determine what functions are present at the runtime;
+ this includes full c99 runtime and sincos. */
+# undef TARGET_LIBC_HAS_FUNCTION
+# define TARGET_LIBC_HAS_FUNCTION linux_libc_has_function
+
+#endif
diff --git a/support/cpp/gcc/config/linux.opt b/support/cpp/gcc/config/linux.opt
new file mode 100644
index 000000000..52109e5bd
--- /dev/null
+++ b/support/cpp/gcc/config/linux.opt
@@ -0,0 +1,36 @@
+; Processor-independent options for GNU/Linux.
+;
+; Copyright (C) 2006-2022 Free Software Foundation, Inc.
+; Contributed by CodeSourcery.
+;
+; 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/>.
+
+mbionic
+Target RejectNegative Var(linux_libc,LIBC_BIONIC) Init(DEFAULT_LIBC) Negative(mglibc)
+Use Bionic C library.
+
+mglibc
+Target RejectNegative Var(linux_libc,LIBC_GLIBC) Negative(muclibc)
+Use GNU C library.
+
+muclibc
+Target RejectNegative Var(linux_libc,LIBC_UCLIBC) Negative(mmusl)
+Use uClibc C library.
+
+mmusl
+Target RejectNegative Var(linux_libc,LIBC_MUSL) Negative(mbionic)
+Use musl C library.
diff --git a/support/cpp/gcc/config/lynx.h b/support/cpp/gcc/config/lynx.h
new file mode 100644
index 000000000..ff5ee3d5f
--- /dev/null
+++ b/support/cpp/gcc/config/lynx.h
@@ -0,0 +1,163 @@
+/* Target independent definitions for LynxOS.
+ Copyright (C) 1993-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/>. */
+
+/* In this file we set up defaults that can be chosen by
+ <target>/lynx.h files. A target-specific lynx.h file can decide
+ either to define and override these definitions or to use them by
+ ensuring they are undefined at this point. If we were to #undef
+ them here we might accidentally disable some target-specific
+ defines. */
+
+#ifndef EXTRA_OS_LYNX_TARGET_SPECS
+# define EXTRA_OS_LYNX_TARGET_SPECS
+#endif
+
+#ifndef EXTRA_OS_LYNX_SPECS
+# define EXTRA_OS_LYNX_SPECS \
+ { "cpp_os_lynx", CPP_OS_LYNX_SPEC }, \
+ { "lib_os_lynx", LIB_OS_LYNX_SPEC }, \
+ { "link_os_lynx", LINK_OS_LYNX_SPEC }, \
+ { "startfile_os_lynx", STARTFILE_OS_LYNX_SPEC }, \
+ { "endfile_os_lynx", ENDFILE_OS_LYNX_SPEC }, \
+ EXTRA_OS_LYNX_TARGET_SPECS
+#endif
+
+#ifndef SUBTARGET_EXTRA_SPECS
+# define SUBTARGET_EXTRA_SPECS EXTRA_OS_LYNX_SPECS
+#endif
+
+#ifndef CPP_SPEC
+# define CPP_SPEC "%(cpp_cpu) %(cpp_os_lynx)"
+#endif
+
+#ifndef LIB_SPEC
+# define LIB_SPEC "%(lib_os_lynx)"
+#endif
+
+#ifndef LINK_SPEC
+# define LINK_SPEC "%(link_os_lynx)"
+#endif
+
+#ifndef STARTFILE_SPEC
+# define STARTFILE_SPEC "%(startfile_os_lynx)"
+#endif
+
+#ifndef ENDFILE_SPEC
+# define ENDFILE_SPEC "%(endfile_os_lynx)"
+#endif
+
+#ifndef CPP_OS_LYNX_SPEC
+# define CPP_OS_LYNX_SPEC \
+"%{mthreads: \
+ %{mlegacy-threads: \
+ %ecannot use mthreads and mlegacy-threads together}} \
+ %{mthreads: -D_MULTITHREADED} \
+ %{mlegacy-threads: -D_THREADS_POSIX4ad4} \
+ -Asystem=lynx -Asystem=unix -D__Lynx__ -D__unix__"
+#endif
+
+#ifndef LIB_OS_LYNX_SPEC
+# define LIB_OS_LYNX_SPEC \
+"%{mlegacy-threads:-lposix-pre1c} -lm -lc"
+#endif
+
+/* We link static executables for LynxOS by default unless -mshared is
+ used when linking an executable. Along the same line, we link to
+ shared libraries when linking a shared object by default unless
+ -static is used.
+
+ We have to pass in our -L options here otherwise the translated
+ startfile directories (%D) will take priority over this.
+ Furthermore since we have to pass in -L options here we have to
+ make sure that -L options provided by the user take priority over
+ everything we specify. */
+
+#ifndef LINK_OS_LYNX_SPEC
+# define LINK_OS_LYNX_SPEC \
+"%{shared} %{static} \
+ %{mshared: %{static: %ecannot use mshared and static together}} \
+ %{!mshared: %{!shared: %{!static: -static}}} \
+ %{L*} \
+ %{mthreads: \
+ %{mshared: -L/lib/thread/shlib -rpath /lib/thread/shlib} \
+ %{shared: \
+ %{!static: -L/lib/thread/shlib -rpath /lib/thread/shlib} \
+ %{!mshared: -L/lib/thread}} \
+ %{shared: %{static: -L/lib/thread}}} \
+ %{!mthreads: \
+ %{mshared: -L/lib/shlib -rpath /lib/shlib} \
+ %{shared: -L/lib/shlib -rpath /lib/shlib}} \
+ %{mlegacy-threads:-lposix-pre1c} -lm -lc"
+#endif
+
+#ifndef STARTFILE_OS_LYNX_SPEC
+# define STARTFILE_OS_LYNX_SPEC \
+"%{!shared: \
+ %{!mthreads: \
+ %{p:gcrt1.o%s} %{pg:gcrt1.o%s} \
+ %{!p:%{!pg:crt1.o%s}}} \
+ %{mthreads: \
+ %{p:thread/gcrt1.o%s} %{pg:thread/gcrt1.o%s} \
+ %{!p:%{!pg:thread/crt1.o%s }}}}\
+ %{mthreads: thread/crti.o%s} %{!mthreads: crti.o%s} \
+ %{!shared: crtbegin.o%s} \
+ %{shared: crtbeginS.o%s}"
+#endif
+
+#ifndef ENDFILE_OS_LYNX_SPEC
+# define ENDFILE_OS_LYNX_SPEC \
+"%{!shared: crtend.o%s} \
+ %{shared: crtendS.o%s} \
+ %{mthreads: thread/crtn.o%s} %{!mthreads: crtn.o%s}"
+#endif
+
+/* Define the actual types of some ANSI-mandated types. */
+
+#ifndef SIZE_TYPE
+# define SIZE_TYPE "unsigned int"
+#endif
+
+#ifndef PTRDIFF_TYPE
+# define PTRDIFF_TYPE "int"
+#endif
+
+#ifndef WCHAR_TYPE
+# define WCHAR_TYPE "long int"
+#endif
+
+#ifndef WCHAR_TYPE_SIZE
+# define WCHAR_TYPE_SIZE BITS_PER_WORD
+#endif
+
+/* Define ASM_OUTPUT_ALIGN to use the .balign directive rather that
+ the .align directive with GAS. */
+
+#ifndef ASM_OUTPUT_ALIGN
+# define ASM_OUTPUT_ALIGN(FILE, LOG) \
+ do \
+ { \
+ if ((LOG) != 0) \
+ fprintf ((FILE), "\t.balign %d\n", 1 << (LOG)); \
+ } \
+ while (0)
+#endif
+
+#ifndef TARGET_POSIX_IO
+# define TARGET_POSIX_IO
+#endif
diff --git a/support/cpp/gcc/config/netbsd-elf.h b/support/cpp/gcc/config/netbsd-elf.h
new file mode 100644
index 000000000..c2c35892a
--- /dev/null
+++ b/support/cpp/gcc/config/netbsd-elf.h
@@ -0,0 +1,107 @@
+/* Common configuration file for NetBSD ELF targets.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Contributed by Wasabi Systems, 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/>. */
+
+/* TARGET_OS_CPP_BUILTINS() common to all NetBSD ELF targets. */
+#define NETBSD_OS_CPP_BUILTINS_ELF() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_COMMON(); \
+ } \
+ while (0)
+
+/* Provide a STARTFILE_SPEC appropriate for NetBSD ELF. Here we
+ provide support for the special GCC option -static. On ELF
+ targets, we also add the crtbegin.o file, which provides part
+ of the support for getting C++ file-scope static objects
+ constructed before entering "main". */
+
+#define NETBSD_STARTFILE_SPEC \
+ "%{!shared: \
+ %{pg:gcrt0%O%s} \
+ %{!pg: \
+ %{p:gcrt0%O%s} \
+ %{!p:crt0%O%s}}} \
+ %:if-exists(crti%O%s) \
+ %{static:%:if-exists-else(crtbeginT%O%s crtbegin%O%s)} \
+ %{!static: \
+ %{!shared: \
+ %{!pie:crtbegin%O%s} \
+ %{pie:crtbeginS%O%s}} \
+ %{shared:crtbeginS%O%s}}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC NETBSD_STARTFILE_SPEC
+
+
+/* Provide an ENDFILE_SPEC appropriate for NetBSD ELF. Here we
+ add crtend.o, which provides part of the support for getting
+ C++ file-scope static objects deconstructed after exiting "main". */
+
+#define NETBSD_ENDFILE_SPEC \
+ "%{!shared: \
+ %{!pie:crtend%O%s} \
+ %{pie:crtendS%O%s}} \
+ %{shared:crtendS%O%s} \
+ %:if-exists(crtn%O%s)"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC NETBSD_ENDFILE_SPEC
+
+/* Provide a LINK_SPEC appropriate for NetBSD ELF. Here we provide
+ support for the special GCC options -assert, -R, -rpath, -shared,
+ -nostdlib, -static, -rdynamic, and -dynamic-linker.
+
+ Target-specific code can use this in conjunction with any other
+ target-specific LINK_SPEC options.
+
+ Target-specific code must provide the %(netbsd_entry_point) spec. */
+
+#define NETBSD_LINK_LD_ELF_SO_SPEC \
+ "%{!dynamic-linker:-dynamic-linker /usr/libexec/ld.elf_so}"
+
+#define NETBSD_LINK_SPEC_ELF \
+ "%{assert*} %{R*} %{rpath*} \
+ %{shared:-shared} \
+ %{symbolic:-Bsymbolic} \
+ %{!shared: \
+ -dc -dp \
+ %{!nostdlib: \
+ %{!r: \
+ %{!e*:-e %(netbsd_entry_point)}}} \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ -dynamic-linker /usr/libexec/ld.elf_so} \
+ %{static:-static}}"
+
+/* Provide the standard list of subtarget extra specs for NetBSD targets. */
+#define NETBSD_SUBTARGET_EXTRA_SPECS \
+ { "netbsd_link_ld_elf_so", NETBSD_LINK_LD_ELF_SO_SPEC }, \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT }, \
+ { "netbsd_endfile_spec", NETBSD_ENDFILE_SPEC },
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS NETBSD_SUBTARGET_EXTRA_SPECS
+
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
diff --git a/support/cpp/gcc/config/netbsd-protos.h b/support/cpp/gcc/config/netbsd-protos.h
new file mode 100644
index 000000000..af1ad07f1
--- /dev/null
+++ b/support/cpp/gcc/config/netbsd-protos.h
@@ -0,0 +1,20 @@
+/* Prototypes.
+ Copyright (C) 2017-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/>. */
+
+extern void netbsd_patch_builtins (void);
diff --git a/support/cpp/gcc/config/netbsd-stdint.h b/support/cpp/gcc/config/netbsd-stdint.h
new file mode 100644
index 000000000..099ae0bfc
--- /dev/null
+++ b/support/cpp/gcc/config/netbsd-stdint.h
@@ -0,0 +1,71 @@
+/* Definitions for <stdint.h> types for NetBSD systems.
+ Copyright (C) 2016-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/>. */
+
+#define SIG_ATOMIC_TYPE "int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE INT8_TYPE
+#define INT_LEAST16_TYPE INT16_TYPE
+#define INT_LEAST32_TYPE INT32_TYPE
+#define INT_LEAST64_TYPE INT64_TYPE
+#define UINT_LEAST8_TYPE UINT8_TYPE
+#define UINT_LEAST16_TYPE UINT16_TYPE
+#define UINT_LEAST32_TYPE UINT32_TYPE
+#define UINT_LEAST64_TYPE UINT64_TYPE
+
+#ifdef CHAR_FAST8
+#define INT_FAST8_TYPE (LONG_TYPE_SIZE == 64 ? "int" : "signed char")
+#else
+#define INT_FAST8_TYPE INT32_TYPE
+#endif
+#ifdef SHORT_FAST16
+#define INT_FAST16_TYPE (LONG_TYPE_SIZE == 64 ? "int" : "short int")
+#else
+#define INT_FAST16_TYPE INT32_TYPE
+#endif
+#define INT_FAST32_TYPE INT32_TYPE
+#define INT_FAST64_TYPE INT64_TYPE
+#ifdef CHAR_FAST8
+#define UINT_FAST8_TYPE "unsigned char"
+#else
+#define UINT_FAST8_TYPE UINT32_TYPE
+#endif
+#ifdef SHORT_FAST16
+#define UINT_FAST16_TYPE "short unsigned int"
+#else
+#define UINT_FAST16_TYPE UINT32_TYPE
+#endif
+#define UINT_FAST32_TYPE UINT32_TYPE
+#define UINT_FAST64_TYPE UINT64_TYPE
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? INT64_TYPE : INT32_TYPE)
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? UINT64_TYPE : UINT32_TYPE)
diff --git a/support/cpp/gcc/config/netbsd.h b/support/cpp/gcc/config/netbsd.h
new file mode 100644
index 000000000..9e46a0fff
--- /dev/null
+++ b/support/cpp/gcc/config/netbsd.h
@@ -0,0 +1,168 @@
+/* Base configuration file for all NetBSD targets.
+ 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/>. */
+
+/* TARGET_OS_CPP_BUILTINS() common to all NetBSD targets. */
+#define NETBSD_OS_CPP_BUILTINS_COMMON() \
+ do \
+ { \
+ builtin_define ("__NetBSD__"); \
+ builtin_define ("__unix__"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=NetBSD"); \
+ } \
+ while (0)
+
+/* CPP_SPEC parts common to all NetBSD targets. */
+#define NETBSD_CPP_SPEC \
+ "%{posix:-D_POSIX_SOURCE} \
+ %{pthread:-D_REENTRANT -D_PTHREADS}"
+
+/* NETBSD_NATIVE is defined when gcc is integrated into the NetBSD
+ source tree so it can be configured appropriately without using
+ the GNU configure/build mechanism. */
+
+#ifdef NETBSD_NATIVE
+
+/* Look for the include files in the system-defined places. */
+
+#undef GPLUSPLUS_INCLUDE_DIR
+#define GPLUSPLUS_INCLUDE_DIR "/usr/include/g++"
+
+#undef GCC_INCLUDE_DIR
+#define GCC_INCLUDE_DIR "/usr/include"
+
+#undef INCLUDE_DEFAULTS
+#define INCLUDE_DEFAULTS \
+ { \
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \
+ { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \
+ { 0, 0, 0, 0 } \
+ }
+
+/* Under NetBSD, the normal location of the compiler back ends is the
+ /usr/libexec directory. */
+
+#undef STANDARD_EXEC_PREFIX
+#define STANDARD_EXEC_PREFIX "/usr/libexec/"
+
+/* Under NetBSD, the normal location of the various *crt*.o files is the
+ /usr/lib directory. */
+
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/lib/"
+
+#endif /* NETBSD_NATIVE */
+
+
+/* Provide a LIB_SPEC appropriate for NetBSD. Here we:
+
+ 1. Select the appropriate set of libs, depending on whether we're
+ profiling.
+
+ 2. Include the pthread library if -pthread is specified (only
+ if threads are enabled).
+
+ 3. Include the posix library if -posix is specified.
+
+ FIXME: Could eliminate the duplication here if we were allowed to
+ use string concatenation. */
+
+#define NETBSD_LIB_SPEC \
+ "%{pthread: \
+ %{!p: \
+ %{!pg:-lpthread}} \
+ %{p:-lpthread_p} \
+ %{pg:-lpthread_p}} \
+ %{posix: \
+ %{!p: \
+ %{!pg:-lposix}} \
+ %{p:-lposix_p} \
+ %{pg:-lposix_p}} \
+ %{shared:-lc} \
+ %{!shared: \
+ %{!symbolic: \
+ %{!p: \
+ %{!pg:-lc}} \
+ %{p:-lc_p} \
+ %{pg:-lc_p}}}"
+
+#undef LIB_SPEC
+#define LIB_SPEC NETBSD_LIB_SPEC
+
+/* Provide a LIBGCC_SPEC appropriate for NetBSD. */
+
+#ifdef NETBSD_NATIVE
+#define NETBSD_LIBGCC_SPEC \
+ "%{!symbolic: \
+ %{!shared: \
+ %{!p: \
+ %{!pg: -lgcc}}} \
+ %{shared: -lgcc_pic} \
+ %{p: -lgcc_p} \
+ %{pg: -lgcc_p}}"
+#else
+#define NETBSD_LIBGCC_SPEC "-lgcc"
+#endif
+
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC NETBSD_LIBGCC_SPEC
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
+#endif
+
+#undef TARGET_LIBC_HAS_FUNCTION
+#define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function
+
+/* When building shared libraries, the initialization and finalization
+ functions for the library are .init and .fini respectively. */
+
+#define COLLECT_SHARED_INIT_FUNC(STREAM,FUNC) \
+ do { \
+ fprintf ((STREAM), "void __init() __asm__ (\".init\");"); \
+ fprintf ((STREAM), "void __init() {\n\t%s();\n}\n", (FUNC)); \
+ } while (0)
+
+#define COLLECT_SHARED_FINI_FUNC(STREAM,FUNC) \
+ do { \
+ fprintf ((STREAM), "void __fini() __asm__ (\".fini\");"); \
+ fprintf ((STREAM), "void __fini() {\n\t%s();\n}\n", (FUNC)); \
+ } while (0)
+
+#undef TARGET_POSIX_IO
+#define TARGET_POSIX_IO
+
+/* Define some types that are the same on all NetBSD platforms,
+ making them agree with <machine/ansi.h>. */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+#undef WINT_TYPE
+#define WINT_TYPE "int"
+
+#undef SUBTARGET_INIT_BUILTINS
+#define SUBTARGET_INIT_BUILTINS \
+ do { \
+ netbsd_patch_builtins (); \
+ } while(0)
diff --git a/support/cpp/gcc/config/newlib-stdint.h b/support/cpp/gcc/config/newlib-stdint.h
new file mode 100644
index 000000000..098f658e7
--- /dev/null
+++ b/support/cpp/gcc/config/newlib-stdint.h
@@ -0,0 +1,69 @@
+/* Definitions for <stdint.h> types on systems using newlib.
+ Copyright (C) 2008-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/>. */
+
+/* newlib uses 32-bit long in certain cases for all non-SPU
+ targets. */
+#ifndef STDINT_LONG32
+#define STDINT_LONG32 (LONG_TYPE_SIZE == 32)
+#endif
+
+#define SIG_ATOMIC_TYPE "int"
+
+/* The newlib logic actually checks for sizes greater than 32 rather
+ than equal to 64 for various 64-bit types. */
+
+#define INT8_TYPE (CHAR_TYPE_SIZE == 8 ? "signed char" : 0)
+#define INT16_TYPE (SHORT_TYPE_SIZE == 16 ? "short int" : INT_TYPE_SIZE == 16 ? "int" : CHAR_TYPE_SIZE == 16 ? "signed char" : 0)
+#define INT32_TYPE (STDINT_LONG32 ? "long int" : INT_TYPE_SIZE == 32 ? "int" : SHORT_TYPE_SIZE == 32 ? "short int" : CHAR_TYPE_SIZE == 32 ? "signed char" : 0)
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : LONG_LONG_TYPE_SIZE == 64 ? "long long int" : INT_TYPE_SIZE == 64 ? "int" : 0)
+#define UINT8_TYPE (CHAR_TYPE_SIZE == 8 ? "unsigned char" : 0)
+#define UINT16_TYPE (SHORT_TYPE_SIZE == 16 ? "short unsigned int" : INT_TYPE_SIZE == 16 ? "unsigned int" : CHAR_TYPE_SIZE == 16 ? "unsigned char" : 0)
+#define UINT32_TYPE (STDINT_LONG32 ? "long unsigned int" : INT_TYPE_SIZE == 32 ? "unsigned int" : SHORT_TYPE_SIZE == 32 ? "short unsigned int" : CHAR_TYPE_SIZE == 32 ? "unsigned char" : 0)
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : LONG_LONG_TYPE_SIZE == 64 ? "long long unsigned int" : INT_TYPE_SIZE == 64 ? "unsigned int" : 0)
+
+#define INT_LEAST8_TYPE (INT8_TYPE ? INT8_TYPE : INT16_TYPE ? INT16_TYPE : INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
+#define INT_LEAST16_TYPE (INT16_TYPE ? INT16_TYPE : INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
+#define INT_LEAST32_TYPE (INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
+#define INT_LEAST64_TYPE INT64_TYPE
+#define UINT_LEAST8_TYPE (UINT8_TYPE ? UINT8_TYPE : UINT16_TYPE ? UINT16_TYPE : UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
+#define UINT_LEAST16_TYPE (UINT16_TYPE ? UINT16_TYPE : UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
+#define UINT_LEAST32_TYPE (UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
+#define UINT_LEAST64_TYPE UINT64_TYPE
+
+#define INT_FAST8_TYPE (INT_TYPE_SIZE >= 8 ? "int" : INT_LEAST8_TYPE)
+#define INT_FAST16_TYPE (INT_TYPE_SIZE >= 16 ? "int" : INT_LEAST16_TYPE)
+#define INT_FAST32_TYPE (INT_TYPE_SIZE >= 32 ? "int" : INT_LEAST32_TYPE)
+#define INT_FAST64_TYPE (INT_TYPE_SIZE >= 64 ? "int" : INT_LEAST64_TYPE)
+#define UINT_FAST8_TYPE (INT_TYPE_SIZE >= 8 ? "unsigned int" : UINT_LEAST8_TYPE)
+#define UINT_FAST16_TYPE (INT_TYPE_SIZE >= 16 ? "unsigned int" : UINT_LEAST16_TYPE)
+#define UINT_FAST32_TYPE (INT_TYPE_SIZE >= 32 ? "unsigned int" : UINT_LEAST32_TYPE)
+#define UINT_FAST64_TYPE (INT_TYPE_SIZE >= 64 ? "unsigned int" : UINT_LEAST64_TYPE)
+
+/* Newlib uses the unsigned type corresponding to ptrdiff_t for
+ uintptr_t; this is the same as size_t for most newlib-using
+ targets. */
+#define INTPTR_TYPE PTRDIFF_TYPE
+#ifndef UINTPTR_TYPE
+#define UINTPTR_TYPE SIZE_TYPE
+#endif
diff --git a/support/cpp/gcc/config/openbsd-libpthread.h b/support/cpp/gcc/config/openbsd-libpthread.h
new file mode 100644
index 000000000..f2da0fecd
--- /dev/null
+++ b/support/cpp/gcc/config/openbsd-libpthread.h
@@ -0,0 +1,22 @@
+/* LIB_SPEC appropriate for OpenBSD. Include -lpthread if -pthread is
+ specified on the command line. */
+/* Copyright (C) 2004-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/>. */
+
+#define OBSD_LIB_SPEC "%{!shared:%{pthread:-lpthread} -lc}"
+
diff --git a/support/cpp/gcc/config/openbsd-stdint.h b/support/cpp/gcc/config/openbsd-stdint.h
new file mode 100644
index 000000000..a6da1da19
--- /dev/null
+++ b/support/cpp/gcc/config/openbsd-stdint.h
@@ -0,0 +1,34 @@
+#define SIG_ATOMIC_TYPE "int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE "long long int"
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE "long long unsigned int"
+
+#define INT_LEAST8_TYPE "signed char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE "long long int"
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE "long long unsigned int"
+
+#define INT_FAST8_TYPE "int"
+#define INT_FAST16_TYPE "int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE "long long int"
+#define UINT_FAST8_TYPE "unsigned int"
+#define UINT_FAST16_TYPE "unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE "long long unsigned int"
+
+#define INTMAX_TYPE "long long int"
+#define UINTMAX_TYPE "long long unsigned int"
+
+#define INTPTR_TYPE "long int"
+#define UINTPTR_TYPE "long unsigned int"
diff --git a/support/cpp/gcc/config/openbsd.h b/support/cpp/gcc/config/openbsd.h
new file mode 100644
index 000000000..54be22254
--- /dev/null
+++ b/support/cpp/gcc/config/openbsd.h
@@ -0,0 +1,289 @@
+/* Base configuration file for all OpenBSD targets.
+ 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.
+
+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/>. */
+
+/* Common OpenBSD configuration.
+ All OpenBSD architectures include this file, which is intended as
+ a repository for common defines.
+
+ Some defines are common to all architectures, a few of them are
+ triggered by OBSD_* guards, so that we won't override architecture
+ defaults by mistakes.
+
+ OBSD_HAS_CORRECT_SPECS:
+ another mechanism provides correct specs already.
+ OBSD_NO_DYNAMIC_LIBRARIES:
+ no implementation of dynamic libraries.
+ OBSD_OLD_GAS:
+ older flavor of gas which needs help for PIC.
+ OBSD_HAS_DECLARE_FUNCTION_NAME, OBSD_HAS_DECLARE_FUNCTION_SIZE,
+ OBSD_HAS_DECLARE_OBJECT:
+ PIC support, FUNCTION_NAME/FUNCTION_SIZE are independent, whereas
+ the corresponding logic for OBJECTS is necessarily coupled.
+
+ There are also a few `default' defines such as ASM_WEAKEN_LABEL,
+ intended as common ground for arch that don't provide
+ anything suitable. */
+
+/* OPENBSD_NATIVE is defined only when gcc is configured as part of
+ the OpenBSD source tree, specifically through Makefile.bsd-wrapper.
+
+ In such a case the include path can be trimmed as there is no
+ distinction between system includes and gcc includes. */
+
+/* This configuration method, namely Makefile.bsd-wrapper and
+ OPENBSD_NATIVE is NOT recommended for building cross-compilers. */
+
+#ifdef OPENBSD_NATIVE
+
+/* The compiler is configured with ONLY the gcc/g++ standard headers. */
+#undef INCLUDE_DEFAULTS
+#define INCLUDE_DEFAULTS \
+ { \
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \
+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1 }, \
+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1 }, \
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0 }, \
+ { 0, 0, 0, 0 } \
+ }
+
+/* Under OpenBSD, the normal location of the various *crt*.o files is the
+ /usr/lib directory. */
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
+
+#endif
+
+
+/* Controlling the compilation driver. */
+/* TARGET_OS_CPP_BUILTINS() common to all OpenBSD targets. */
+#define OPENBSD_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__OpenBSD__"); \
+ builtin_define ("__unix__"); \
+ builtin_define ("__ANSI_COMPAT"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=OpenBSD"); \
+ } \
+ while (0)
+
+/* TARGET_OS_CPP_BUILTINS() common to all OpenBSD ELF targets. */
+#define OPENBSD_OS_CPP_BUILTINS_ELF() \
+ do \
+ { \
+ OPENBSD_OS_CPP_BUILTINS(); \
+ builtin_define ("__ELF__"); \
+ } \
+while (0)
+
+/* TARGET_OS_CPP_BUILTINS() common to all LP64 OpenBSD targets. */
+#define OPENBSD_OS_CPP_BUILTINS_LP64() \
+ do \
+ { \
+ builtin_define ("_LP64"); \
+ builtin_define ("__LP64__"); \
+ } \
+ while (0)
+
+/* CPP_SPEC appropriate for OpenBSD. We deal with -posix and -pthread.
+ XXX the way threads are handled currently is not very satisfying,
+ since all code must be compiled with -pthread to work.
+ This two-stage defines makes it easy to pick that for targets that
+ have subspecs. */
+#ifdef CPP_CPU_SPEC
+#define OBSD_CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} %{pthread:-D_POSIX_THREADS}"
+#else
+#define OBSD_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_POSIX_THREADS}"
+#endif
+
+#undef LIB_SPEC
+#define LIB_SPEC OBSD_LIB_SPEC
+
+#ifndef OBSD_HAS_CORRECT_SPECS
+
+#undef CPP_SPEC
+#define CPP_SPEC OBSD_CPP_SPEC
+
+#ifdef OBSD_OLD_GAS
+/* ASM_SPEC appropriate for OpenBSD. For some architectures, OpenBSD
+ still uses a special flavor of gas that needs to be told when generating
+ pic code. */
+#undef ASM_SPEC
+#define ASM_SPEC "%{" FPIE1_OR_FPIC1_SPEC ":-k} %{" FPIE2_OR_FPIC2_SPEC ":-k -K}"
+#endif
+
+/* Since we use gas, stdin -> - is a good idea. */
+#define AS_NEEDS_DASH_FOR_PIPED_INPUT
+
+#undef LIB_SPEC
+#define LIB_SPEC OBSD_LIB_SPEC
+
+#if defined(HAVE_LD_EH_FRAME_HDR)
+#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
+#endif
+
+#undef LIB_SPEC
+#define LIB_SPEC OBSD_LIB_SPEC
+#endif
+
+#define TARGET_POSIX_IO
+
+/* All new versions of OpenBSD have C99 functions. We redefine this hook
+ so the version from elfos.h header won't be used. */
+#undef TARGET_LIBC_HAS_FUNCTION
+#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
+ This is more readable for a human being and confuses c++filt less. */
+
+/* Assembler format: output and generation of labels. */
+
+/* Define the strings used for the .type and .size directives.
+ These strings generally do not vary from one system running OpenBSD
+ to another, but if a given system needs to use different pseudo-op
+ names for these, they may be overridden in the arch specific file. */
+
+/* OpenBSD assembler is hacked to have .type & .size support even in a.out
+ format object files. Functions size are supported but not activated
+ yet (look for GRACE_PERIOD_EXPIRED in gas/config/obj-aout.c).
+ SET_ASM_OP is needed for attribute alias to work. */
+
+#undef TYPE_ASM_OP
+#undef SIZE_ASM_OP
+#undef SET_ASM_OP
+#undef GLOBAL_ASM_OP
+
+#define TYPE_ASM_OP "\t.type\t"
+#define SIZE_ASM_OP "\t.size\t"
+#define SET_ASM_OP "\t.set\t"
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+/* The following macro defines the format used to output the second
+ operand of the .type assembler directive. */
+#undef TYPE_OPERAND_FMT
+#define TYPE_OPERAND_FMT "@%s"
+
+/* Provision if extra assembler code is needed to declare a function's result
+ (taken from svr4, not needed yet actually). */
+#ifndef ASM_DECLARE_RESULT
+#define ASM_DECLARE_RESULT(FILE, RESULT)
+#endif
+
+/* These macros generate the special .type and .size directives which
+ are used to set the corresponding fields of the linker symbol table
+ entries under OpenBSD. These macros also have to output the starting
+ labels for the relevant functions/objects. */
+
+#ifndef OBSD_HAS_DECLARE_FUNCTION_NAME
+/* Extra assembler code needed to declare a function properly.
+ Some assemblers may also need to also have something extra said
+ about the function's return value. We allow for that here. */
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do { \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_FUNCTION_LABEL (FILE, NAME, DECL); \
+ } while (0)
+#endif
+
+#ifndef OBSD_HAS_DECLARE_FUNCTION_SIZE
+/* Declare the size of a function. */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
+ } while (0)
+#endif
+
+#ifndef OBSD_HAS_DECLARE_OBJECT
+/* Extra assembler code needed to declare an object properly. */
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
+ do { \
+ HOST_WIDE_INT size; \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive \
+ && (DECL) && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \
+ } \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ } while (0)
+
+/* Output the size directive for a decl in rest_of_decl_compilation
+ in the case where we did not do so before the initializer.
+ Once we find the error_mark_node, we know that the value of
+ size_directive_output was set by ASM_DECLARE_OBJECT_NAME
+ when it was run for the same decl. */
+#undef ASM_FINISH_DECLARE_OBJECT
+#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
+do { \
+ const char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
+ HOST_WIDE_INT size; \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
+ && ! AT_END && TOP_LEVEL \
+ && DECL_INITIAL (DECL) == error_mark_node \
+ && !size_directive_output) \
+ { \
+ size_directive_output = 1; \
+ size = int_size_in_bytes (TREE_TYPE (DECL)); \
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, name, size); \
+ } \
+ } while (0)
+#endif
+
+
+/* Those are `generic' ways to weaken/globalize a label. We shouldn't need
+ to override a processor specific definition. Hence, #ifndef ASM_*
+ In case overriding turns out to be needed, one can always #undef ASM_*
+ before including this file. */
+
+/* Tell the assembler that a symbol is weak. */
+/* Note: netbsd arm32 assembler needs a .globl here. An override may
+ be needed when/if we go for arm32 support. */
+#ifndef ASM_WEAKEN_LABEL
+#define ASM_WEAKEN_LABEL(FILE,NAME) \
+ do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); } while (0)
+#endif
+
+/* Storage layout. */
+
+
+#define HAVE_ENABLE_EXECUTE_STACK
diff --git a/support/cpp/gcc/config/phoenix.h b/support/cpp/gcc/config/phoenix.h
new file mode 100644
index 000000000..d9eef3573
--- /dev/null
+++ b/support/cpp/gcc/config/phoenix.h
@@ -0,0 +1,33 @@
+/* Base configuration file for all Phoenix-RTOS targets.
+ Copyright (C) 2016-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/>. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("phoenix"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=phoenix"); \
+ builtin_assert ("system=unix"); \
+ } while (0)
+
+#define STD_LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
+
+/* This will prevent selecting 'unsigned long int' instead of 'unsigned int' as 'uint32_t' in stdint-newlib.h. */
+#undef STDINT_LONG32
+#define STDINT_LONG32 0
diff --git a/support/cpp/gcc/config/rtems.h b/support/cpp/gcc/config/rtems.h
new file mode 100644
index 000000000..95bcdc41b
--- /dev/null
+++ b/support/cpp/gcc/config/rtems.h
@@ -0,0 +1,58 @@
+/* Configuration common to all targets running RTEMS.
+ Copyright (C) 2000-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/>. */
+
+#ifndef RTEMS_STARTFILE_SPEC
+#define RTEMS_STARTFILE_SPEC "crti%O%s crtbegin%O%s"
+#endif
+
+#ifndef RTEMS_ENDFILE_SPEC
+#define RTEMS_ENDFILE_SPEC "crtend%O%s crtn%O%s"
+#endif
+
+/*
+ * The crt0.o is a dummy start file to let the linker work as needed by
+ * autoconf scripts using this compiler.
+ */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!qrtems:crt0%O%s} " \
+"%{qrtems:" RTEMS_STARTFILE_SPEC "}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+"%{qrtems:" RTEMS_ENDFILE_SPEC " %{!qnolinkcmds:-T linkcmds%s}}"
+
+/*
+ * Some targets do not set up LIB_SPECS, override it, here.
+ */
+#define STD_LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!qrtems:" STD_LIB_SPEC "} " \
+"%{qrtems:--start-group -lrtemsbsp -lrtemscpu -latomic -lc -lgcc --end-group}"
+
+#define TARGET_POSIX_IO
+
+/* Prefer int for int32_t (see stdint-newlib.h). */
+#undef STDINT_LONG32
+#define STDINT_LONG32 (INT_TYPE_SIZE != 32 && LONG_TYPE_SIZE == 32)
diff --git a/support/cpp/gcc/config/sol2-protos.h b/support/cpp/gcc/config/sol2-protos.h
new file mode 100644
index 000000000..6307e137a
--- /dev/null
+++ b/support/cpp/gcc/config/sol2-protos.h
@@ -0,0 +1,33 @@
+/* Operating system specific prototypes to be used when targeting GCC for any
+ Solaris 2 system.
+ Copyright (C) 2004-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/>. */
+
+/* In sol2.cc. */
+extern void solaris_assemble_visibility (tree, int);
+extern void solaris_elf_asm_comdat_section (const char *, unsigned int, tree);
+extern void solaris_file_end (void);
+extern void solaris_insert_attributes (tree, tree *);
+extern void solaris_output_init_fini (FILE *, tree);
+extern void solaris_override_options (void);
+
+/* In sol2-c.cc. */
+extern void solaris_register_pragmas (void);
+
+/* In sol2-cxx.cc. */
+extern tree solaris_cxx_decl_mangling_context (const_tree);
diff --git a/support/cpp/gcc/config/sol2.h b/support/cpp/gcc/config/sol2.h
new file mode 100644
index 000000000..e22c70c45
--- /dev/null
+++ b/support/cpp/gcc/config/sol2.h
@@ -0,0 +1,521 @@
+/* Operating system specific defines to be used when targeting GCC for any
+ Solaris 2 system.
+ Copyright (C) 2002-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/>. */
+
+/* We are compiling for Solaris 2 now. */
+#define TARGET_SOLARIS 1
+
+/* wchar_t is called differently in <wchar.h> for 32 and 64-bit
+ compilations. This is called for by SCD 2.4.1, p. 6-83, Figure 6-65
+ (32-bit) and p. 6P-10, Figure 6.38 (64-bit). */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_64BIT ? "int" : "long int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Same for wint_t. See SCD 2.4.1, p. 6-83, Figure 6-66 (32-bit). There's
+ no corresponding 64-bit definition, but this is what Solaris 8
+ <iso/wchar_iso.h> uses. */
+
+#undef WINT_TYPE
+#define WINT_TYPE (TARGET_64BIT ? "int" : "long int")
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
+#define SIG_ATOMIC_TYPE "int"
+
+/* ??? This definition of int8_t follows the system header but does
+ not conform to C99. Likewise int_fast8_t, int_least8_t. */
+#define INT8_TYPE "char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE "char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_FAST8_TYPE "char"
+#define INT_FAST16_TYPE "int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_FAST8_TYPE "unsigned char"
+#define UINT_FAST16_TYPE "unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int")
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int")
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+%{pthreads|pthread:-D_REENTRANT -D_PTHREADS}"
+
+/* Names to predefine in the preprocessor for this target machine. */
+#define TARGET_SUB_OS_CPP_BUILTINS()
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("sun"); \
+ builtin_define ("__svr4__"); \
+ builtin_define ("__SVR4"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ /* For C++ we need to add some additional macro \
+ definitions required by the C++ standard \
+ library. */ \
+ if (c_dialect_cxx ()) \
+ { \
+ switch (cxx_dialect) \
+ { \
+ case cxx98: \
+ case cxx11: \
+ case cxx14: \
+ /* C++11 and C++14 are based on C99. \
+ libstdc++ makes use of C99 features \
+ even for C++98. */ \
+ builtin_define ("__STDC_VERSION__=199901L");\
+ break; \
+ \
+ default: \
+ /* C++17 is based on C11. */ \
+ builtin_define ("__STDC_VERSION__=201112L");\
+ break; \
+ } \
+ builtin_define ("_XOPEN_SOURCE=600"); \
+ builtin_define ("_LARGEFILE_SOURCE=1"); \
+ builtin_define ("_LARGEFILE64_SOURCE=1"); \
+ builtin_define ("_FILE_OFFSET_BITS=64"); \
+ builtin_define ("__EXTENSIONS__"); \
+ } \
+ TARGET_SUB_OS_CPP_BUILTINS(); \
+ } while (0)
+
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ solaris_override_options (); \
+ } while (0)
+
+#if DEFAULT_ARCH32_P
+#define MULTILIB_DEFAULTS { "m32" }
+#else
+#define MULTILIB_DEFAULTS { "m64" }
+#endif
+
+#if DEFAULT_ARCH32_P
+#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
+#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
+#else
+#define DEF_ARCH32_SPEC(__str) "%{m32:" __str "}"
+#define DEF_ARCH64_SPEC(__str) "%{!m32:" __str "}"
+#endif
+
+/* Solaris needs -fasynchronous-unwind-tables to generate unwind info. */
+#define ASAN_CC1_SPEC "%{%:sanitize(address):-fasynchronous-unwind-tables}"
+
+/* It's safe to pass -s always, even if -g is not used. Those options are
+ handled by both Sun as and GNU as. */
+#define ASM_SPEC_BASE \
+"%{v:-V} %{Qy:} %{!Qn:-Qy} %{Ym,*} -s %(asm_cpu)"
+
+#define ASM_PIC_SPEC " %{" FPIE_OR_FPIC_SPEC ":-K PIC}"
+
+#undef ASM_CPU_DEFAULT_SPEC
+#define ASM_CPU_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? "\
+%{m64:" ASM_CPU64_DEFAULT_SPEC "} \
+%{!m64:" ASM_CPU32_DEFAULT_SPEC "} \
+" : "\
+%{m32:" ASM_CPU32_DEFAULT_SPEC "} \
+%{!m32:" ASM_CPU64_DEFAULT_SPEC "} \
+")
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{!symbolic:\
+ %{pthreads|pthread:-lpthread} \
+ %{p|pg:-ldl} -lc}"
+
+#ifndef CROSS_DIRECTORY_STRUCTURE
+#undef MD_EXEC_PREFIX
+#define MD_EXEC_PREFIX "/usr/ccs/bin/"
+#endif
+
+/* Enable constructor priorities if the configured linker supports it. */
+#undef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY HAVE_INITFINI_ARRAY_SUPPORT
+
+/* Solaris libc and libm implement multiple behaviours for various
+ interfaces that have changed over the years in different versions of the
+ C standard. The behaviour is controlled by linking corresponding
+ values-*.o objects. Each of these objects contain alternate definitions
+ of one or more variables that the libraries use to select which
+ conflicting behaviour they should exhibit. There are two sets of these
+ objects, values-X*.o and values-xpg*.o.
+
+ The values-X[ac].o objects set the variable _lib_version. The Studio C
+ compilers use values-Xc.o with either -Xc or (since Studio 12.6)
+ -pedantic to select strictly conformant ISO C behaviour, otherwise
+ values-Xa.o. Since -pedantic is a diagnostic option only in GCC, we
+ need to specifiy the -std=c* options and -std=iso9899:199409. We
+ traditionally include -ansi, which affects C and C++, and also -std=c++*
+ for consistency.
+
+ The values-xpg[46].o objects define either or both __xpg[46] variables,
+ selecting XPG4 mode (__xpg4) and conforming C99/SUSv3 behavior (__xpg6).
+
+ Since GCC 5, gcc defaults to -std=gnu11 or higher, so we link
+ values-xpg6.o to get C99 semantics. Besides, most of the runtime
+ libraries always require C99 semantics.
+
+ Since only one instance of _lib_version and __xpg[46] takes effekt (the
+ first in ld.so.1's search path), we only link the values-*.o files into
+ executable programs. */
+#undef STARTFILE_ARCH_SPEC
+#define STARTFILE_ARCH_SPEC \
+ "%{!shared:%{!symbolic: \
+ %{ansi|std=c*|std=iso9899\\:199409:values-Xc.o%s; :values-Xa.o%s} \
+ %{std=c90|std=gnu90:values-xpg4.o%s; :values-xpg6.o%s}}}"
+
+#if defined(HAVE_LD_PIE) && defined(HAVE_SOLARIS_CRTS)
+#define STARTFILE_CRTBEGIN_SPEC "%{static:crtbegin.o%s; \
+ shared|" PIE_SPEC ":crtbeginS.o%s; \
+ :crtbegin.o%s}"
+#else
+#define STARTFILE_CRTBEGIN_SPEC "crtbegin.o%s"
+#endif
+
+#if ENABLE_VTABLE_VERIFY
+#if SUPPORTS_INIT_PRIORITY
+#define STARTFILE_VTV_SPEC \
+ "%{fvtable-verify=none:%s; \
+ fvtable-verify=preinit:vtv_start_preinit.o%s; \
+ fvtable-verify=std:vtv_start.o%s}"
+#define ENDFILE_VTV_SPEC \
+ "%{fvtable-verify=none:%s; \
+ fvtable-verify=preinit:vtv_end_preinit.o%s; \
+ fvtable-verify=std:vtv_end.o%s}"
+#else /* !SUPPORTS_INIT_PRIORITY */
+#define STARTFILE_VTV_SPEC \
+ "%{fvtable-verify=*: \
+ %e-fvtable-verify=%* is not supported in this configuration}"
+#define ENDFILE_VTV_SPEC ""
+#endif /* !SUPPORTS_INIT_PRIORITY */
+#else /* !ENABLE_VTABLE_VERIFY */
+#define STARTFILE_VTV_SPEC ""
+#define ENDFILE_VTV_SPEC ""
+#endif /* !ENABLE_VTABLE_VERIFY */
+
+/* Link -lasan early on the command line. For -static-libasan, don't link
+ it for -shared link, the executable should be compiled with -static-libasan
+ in that case, and for executable link with --{,no-}whole-archive around
+ it to force everything into the executable. */
+
+#ifndef USE_GNU_LD
+#define LD_WHOLE_ARCHIVE_OPTION "-z allextract"
+#define LD_NO_WHOLE_ARCHIVE_OPTION "-z defaultextract"
+#else
+#define LD_WHOLE_ARCHIVE_OPTION "--whole-archive"
+#define LD_NO_WHOLE_ARCHIVE_OPTION "--no-whole-archive"
+#endif
+
+/* Allow rejecting -fsanitize=address, e.g. for specific multilibs. */
+#ifndef ASAN_REJECT_SPEC
+#define ASAN_REJECT_SPEC ""
+#endif
+
+#define LIBASAN_EARLY_SPEC ASAN_REJECT_SPEC \
+ " %{!shared:libasan_preinit%O%s} \
+ %{static-libasan:%{!shared: -Bstatic "\
+ LD_WHOLE_ARCHIVE_OPTION " -lasan " LD_NO_WHOLE_ARCHIVE_OPTION \
+ "-Bdynamic}}%{!static-libasan:-lasan}"
+
+/* Error out on -fsanitize=thread|leak. */
+#define LIBTSAN_EARLY_SPEC "\
+ %e-fsanitize=thread is not supported in this configuration"
+#define LIBLSAN_EARLY_SPEC "\
+ %e-fsanitize=leak is not supported in this configuration"
+
+/* We don't use the standard svr4 STARTFILE_SPEC because it's wrong for us. */
+#undef STARTFILE_SPEC
+#ifdef HAVE_SOLARIS_CRTS
+/* Since Solaris 11.4, the OS delivers crt1.o, crti.o, and crtn.o, with a hook
+ for compiler-dependent stuff like profile handling. */
+#define STARTFILE_SPEC "%{!shared:%{!symbolic: \
+ crt1.o%s \
+ %{p:%e-p is not supported; \
+ pg:crtpg.o%s gmon.o%s; \
+ :crtp.o%s}}} \
+ crti.o%s %(startfile_arch) %(startfile_crtbegin) \
+ %(startfile_vtv)"
+#else
+#define STARTFILE_SPEC "%{!shared:%{!symbolic: \
+ %{p:mcrt1.o%s; \
+ pg:gcrt1.o%s gmon.o%s; \
+ :crt1.o%s}}} \
+ crti.o%s %(startfile_arch) %(startfile_crtbegin) \
+ %(startfile_vtv)"
+#endif
+
+#if defined(HAVE_LD_PIE) && defined(HAVE_SOLARIS_CRTS)
+#define ENDFILE_CRTEND_SPEC "%{static:crtend.o%s; \
+ shared|" PIE_SPEC ":crtendS.o%s; \
+ :crtend.o%s}"
+#else
+#define ENDFILE_CRTEND_SPEC "crtend.o%s"
+#endif
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ %(endfile_arch) %(endfile_vtv) %(endfile_crtend) crtn.o%s"
+
+#undef LINK_ARCH32_SPEC_BASE
+#define LINK_ARCH32_SPEC_BASE \
+ "%{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{!YP,*:%{p|pg:-Y P,%R/usr/lib/libp%R/lib:%R/usr/lib} \
+ %{!p:%{!pg:-Y P,%R/lib:%R/usr/lib}}}"
+
+#undef LINK_ARCH32_SPEC
+#define LINK_ARCH32_SPEC LINK_ARCH32_SPEC_BASE
+
+/* This should be the same as LINK_ARCH32_SPEC_BASE, except with
+ ARCH64_SUBDIR appended to the paths. */
+#undef LINK_ARCH64_SPEC_BASE
+#define LINK_ARCH64_SPEC_BASE \
+ "%{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{!YP,*:%{p|pg:-Y P,%R/usr/lib/libp/" ARCH64_SUBDIR ":%R/lib/" ARCH64_SUBDIR ":%R/usr/lib/" ARCH64_SUBDIR "} \
+ %{!p:%{!pg:-Y P,%R/lib/" ARCH64_SUBDIR ":%R/usr/lib/" ARCH64_SUBDIR "}}}"
+
+#undef LINK_ARCH64_SPEC
+#ifndef USE_GLD
+/* FIXME: Used to be SPARC-only. Not SPARC-specfic but for the model name! */
+#define LINK_ARCH64_SPEC \
+ "%{mcmodel=medlow:-M /usr/lib/ld/" ARCH64_SUBDIR "/map.below4G} " \
+ LINK_ARCH64_SPEC_BASE
+#else
+#define LINK_ARCH64_SPEC LINK_ARCH64_SPEC_BASE
+#endif
+
+#ifdef USE_GLD
+#if DEFAULT_ARCH32_P
+#define ARCH_DEFAULT_EMULATION ARCH32_EMULATION
+#else
+#define ARCH_DEFAULT_EMULATION ARCH64_EMULATION
+#endif
+#define TARGET_LD_EMULATION "%{m32:-m " ARCH32_EMULATION "}" \
+ "%{m64:-m " ARCH64_EMULATION "}" \
+ "%{!m32:%{!m64:-m " ARCH_DEFAULT_EMULATION "}} "
+#else
+#define TARGET_LD_EMULATION ""
+#endif
+
+#undef LINK_ARCH_SPEC
+#if DISABLE_MULTILIB
+#if DEFAULT_ARCH32_P
+#define LINK_ARCH_SPEC TARGET_LD_EMULATION " \
+%{m32:%(link_arch32)} \
+%{m64:%edoes not support multilib} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+#else
+#define LINK_ARCH_SPEC TARGET_LD_EMULATION " \
+%{m32:%edoes not support multilib} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}} \
+"
+#endif
+#else
+#define LINK_ARCH_SPEC TARGET_LD_EMULATION " \
+%{m32:%(link_arch32)} \
+%{m64:%(link_arch64)} \
+%{!m32:%{!m64:%(link_arch_default)}}"
+#endif
+
+#define LINK_ARCH_DEFAULT_SPEC \
+(DEFAULT_ARCH32_P ? LINK_ARCH32_SPEC : LINK_ARCH64_SPEC)
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "startfile_arch", STARTFILE_ARCH_SPEC }, \
+ { "startfile_crtbegin", STARTFILE_CRTBEGIN_SPEC }, \
+ { "startfile_vtv", STARTFILE_VTV_SPEC }, \
+ { "link_arch32", LINK_ARCH32_SPEC }, \
+ { "link_arch64", LINK_ARCH64_SPEC }, \
+ { "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
+ { "link_arch", LINK_ARCH_SPEC }, \
+ { "endfile_arch", ENDFILE_ARCH_SPEC }, \
+ { "endfile_crtend", ENDFILE_CRTEND_SPEC }, \
+ { "endfile_vtv", ENDFILE_VTV_SPEC }, \
+ SUBTARGET_CPU_EXTRA_SPECS
+
+#ifndef USE_GLD
+/* With Sun ld, -rdynamic is a no-op. */
+#define RDYNAMIC_SPEC ""
+#else
+/* GNU ld needs --export-dynamic to implement -rdynamic. */
+#define RDYNAMIC_SPEC "--export-dynamic"
+#endif
+
+#ifndef USE_GLD
+/* Prefer native form with Solaris ld. */
+#define SYSROOT_SPEC "-z sysroot=%R"
+#endif
+
+#if !defined(USE_GLD) && defined(ENABLE_SHARED_LIBGCC)
+/* With Sun ld, use mapfile to enforce direct binding to libgcc_s unwinder. */
+#define LINK_LIBGCC_MAPFILE_SPEC \
+ "%{shared|shared-libgcc:-M %slibgcc-unwind.map}"
+#else
+/* GNU ld doesn't support direct binding. */
+#define LINK_LIBGCC_MAPFILE_SPEC ""
+#endif
+
+/* Clear hardware capabilities, either explicitly or with OpenMP:
+ #pragma openmp declare simd creates clones for SSE2, AVX, and AVX2. */
+#ifdef HAVE_LD_CLEARCAP
+#define LINK_CLEARCAP_SPEC " %{mclear-hwcap|fopenmp*:-M %sclearcap.map}"
+#else
+#define LINK_CLEARCAP_SPEC ""
+#endif
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{h*} %{v:-V} \
+ %{!shared:%{!static:%{rdynamic: " RDYNAMIC_SPEC "}}} \
+ %{static:-dn -Bstatic} \
+ %{shared:-G -dy %{!mimpure-text:-z text}} " \
+ LINK_LIBGCC_MAPFILE_SPEC LINK_CLEARCAP_SPEC " \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
+ %(link_arch) \
+ %{Qy:} %{!Qn:-Qy}"
+
+/* Use --as-needed/-z ignore -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+#ifdef USE_GLD
+/* Solaris 11 build 135+ implements dl_iterate_phdr. GNU ld needs
+ --eh-frame-hdr to create the required .eh_frame_hdr sections. */
+#if defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR)
+#define LINK_EH_SPEC "%{!static|static-pie:--eh-frame-hdr} "
+#endif /* HAVE_LD_EH_FRAME && TARGET_DL_ITERATE_PHDR */
+#endif
+
+#if defined(HAVE_LD_PIE) && defined(HAVE_SOLARIS_CRTS)
+#ifdef USE_GLD
+/* Assert -z text by default to match Solaris ld. */
+#define LD_PIE_SPEC "-pie %{!mimpure-text:-z text}"
+#else
+/* Solaris ld needs -z type=pie instead of -pie. */
+#define LD_PIE_SPEC "-z type=pie %{mimpure-text:-z textoff}"
+#endif
+#else
+/* Error out if some part of PIE support is missing. */
+#define LINK_PIE_SPEC \
+ "%{no-pie:} %{pie:%e-pie is not supported in this configuration} "
+#endif
+
+/* collect2.cc can only parse GNU nm -n output. Solaris nm needs -png to
+ produce the same format. */
+#define NM_FLAGS "-png"
+
+#define STDC_0_IN_SYSTEM_HEADERS 1
+
+/* Support Solaris-specific format checking for cmn_err. */
+#define TARGET_N_FORMAT_TYPES 1
+#define TARGET_FORMAT_TYPES solaris_format_types
+
+/* #pragma init and #pragma fini are implemented on top of init and
+ fini attributes. */
+#define SOLARIS_ATTRIBUTE_TABLE \
+ { "init", 0, 0, true, false, false, false, NULL, NULL }, \
+ { "fini", 0, 0, true, false, false, false, NULL, NULL }
+
+/* Solaris-specific #pragmas are implemented on top of attributes. Hook in
+ the bits from config/sol2.cc. */
+#define SUBTARGET_INSERT_ATTRIBUTES solaris_insert_attributes
+#define SUBTARGET_ATTRIBUTE_TABLE SOLARIS_ATTRIBUTE_TABLE
+
+/* Allow macro expansion in #pragma pack. */
+#define HANDLE_PRAGMA_PACK_WITH_EXPANSION
+
+#define TARGET_CXX_DECL_MANGLING_CONTEXT solaris_cxx_decl_mangling_context
+
+/* Solaris/x86 as and gas support unquoted section names. */
+#ifndef SECTION_NAME_FORMAT
+#define SECTION_NAME_FORMAT "%s"
+#endif
+
+/* This is how to declare the size of a function. For Solaris, we output
+ any .init or .fini entries here. */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
+ solaris_output_init_fini (FILE, DECL); \
+ } \
+ while (0)
+
+#ifndef USE_GAS
+#undef TARGET_ASM_ASSEMBLE_VISIBILITY
+#define TARGET_ASM_ASSEMBLE_VISIBILITY solaris_assemble_visibility
+
+#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
+
+/* Static stack checking is supported by means of probes. */
+#define STACK_CHECK_STATIC_BUILTIN 1
+
+#define TARGET_POSIX_IO
+
+/* Solaris 10 has the float and long double forms of math functions.
+ We redefine this hook so the version from elfos.h header won't be used. */
+#undef TARGET_LIBC_HAS_FUNCTION
+#define TARGET_LIBC_HAS_FUNCTION default_libc_has_function
+
+extern GTY(()) tree solaris_pending_aligns;
+extern GTY(()) tree solaris_pending_inits;
+extern GTY(()) tree solaris_pending_finis;
diff --git a/support/cpp/gcc/config/t-glibc b/support/cpp/gcc/config/t-glibc
new file mode 100644
index 000000000..c8b7d4e52
--- /dev/null
+++ b/support/cpp/gcc/config/t-glibc
@@ -0,0 +1,25 @@
+# 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/>.
+
+glibc-c.o: config/glibc-c.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
+
+glibc-d.o: config/glibc-d.cc
+ $(COMPILE) $<
+ $(POSTCOMPILE)
diff --git a/support/cpp/gcc/config/tm-dwarf2.h b/support/cpp/gcc/config/tm-dwarf2.h
new file mode 100644
index 000000000..d08646ecc
--- /dev/null
+++ b/support/cpp/gcc/config/tm-dwarf2.h
@@ -0,0 +1,4 @@
+/* Enable Dwarf2 debugging and make it the default */
+#define DWARF2_DEBUGGING_INFO 1
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
diff --git a/support/cpp/gcc/config/usegas.h b/support/cpp/gcc/config/usegas.h
new file mode 100644
index 000000000..5ed73df00
--- /dev/null
+++ b/support/cpp/gcc/config/usegas.h
@@ -0,0 +1,20 @@
+/* Copyright (C) 2001-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/>. */
+
+/* Just set a single flag we can test for it inside other files. */
+#define USE_GAS 1
diff --git a/support/cpp/gcc/config/usegld.h b/support/cpp/gcc/config/usegld.h
new file mode 100644
index 000000000..066773270
--- /dev/null
+++ b/support/cpp/gcc/config/usegld.h
@@ -0,0 +1 @@
+#define USE_GLD 1
diff --git a/support/cpp/gcc/config/vx-common.h b/support/cpp/gcc/config/vx-common.h
new file mode 100644
index 000000000..aaae4f78b
--- /dev/null
+++ b/support/cpp/gcc/config/vx-common.h
@@ -0,0 +1,127 @@
+/* Target-independent configuration for VxWorks and VxWorks AE.
+ Copyright (C) 2005-2022 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+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/>. */
+
+/* ------------------------- Common SPEC strings ------------------------- */
+
+/* Most of these will probably be overridden by subsequent headers. We
+ undefine them here just in case, and define VXWORKS_ versions of each,
+ to be used in port-specific vxworks.h. */
+
+/* REAL_LIBGCC_SPEC needs to be used since the non-static option is not
+ handled in gcc.cc. */
+#undef REAL_LIBGCC_SPEC
+#define REAL_LIBGCC_SPEC VXWORKS_LIBGCC_SPEC
+#undef STARTFILE_SPEC
+#undef ENDFILE_SPEC
+
+/* Most of these macros are overridden in "config/vxworks.h" or
+ "config/vxworksae.h" and are here merely for documentation
+ purposes. */
+#define VXWORKS_ADDITIONAL_CPP_SPEC ""
+#define VXWORKS_LIB_SPEC ""
+#define VXWORKS_LINK_SPEC ""
+#define VXWORKS_LIBGCC_SPEC ""
+#define VXWORKS_STARTFILE_SPEC ""
+#define VXWORKS_ENDFILE_SPEC ""
+#define VXWORKS_CC1_SPEC ""
+
+/* ----------------------- Common type descriptions ----------------------- */
+
+/* Regardless of the target architecture, VxWorks uses a signed 32bit
+ integer for wchar_t starting with vx7 SR06xx. An unsigned short
+ otherwise. */
+#if TARGET_VXWORKS7
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_VXWORKS64 ? "int" : "long int")
+
+#else
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+
+#endif
+
+/* The VxWorks headers base wint_t on the definitions used for wchar_t.
+ Do the same here to make sure they remain in sync, in case WCHAR_TYPE
+ gets redefined for a specific CPU architecture. */
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE WCHAR_TYPE_SIZE
+#undef WINT_TYPE
+#define WINT_TYPE WCHAR_TYPE
+
+/* ---------------------- Debug and unwind info formats ------------------ */
+
+/* Dwarf2 unwind info is supported, unless overriden by a request for a target
+ specific format.
+
+ Taking care of this here allows using DWARF2_UNWIND_INFO in #if conditions
+ from the common config/vxworks.h files, included before the cpu
+ specializations. Unlike with conditions used in C expressions, where the
+ definitions which matter are those at the expression expansion point, use
+ in #if constructs requires an accurate definition of the operands at the
+ #if point. Since <cpu>/vxworks.h. is typically included after
+ config/vxworks.h, #if expressions in the latter can't rely on possible
+ redefinitions in the former. */
+#if !ARM_UNWIND_INFO
+#undef DWARF2_UNWIND_INFO
+#define DWARF2_UNWIND_INFO 1
+#endif
+
+/* VxWorks uses DWARF2 debugging info. */
+#define DWARF2_DEBUGGING_INFO 1
+#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 ---------------------- */
+
+#if !TARGET_VXWORKS7
+/* VxWorks, prior to version 7, could not have dots in constructor
+ labels, because it used a mutant variation of collect2 that
+ generates C code instead of assembly. Thus each constructor label
+ had to be a legitimate C symbol. */
+# undef NO_DOLLAR_IN_LABEL
+# define NO_DOT_IN_LABEL
+#endif
+
+/* Kernel mode doesn't have ctors/dtors, but RTP mode does. */
+#define TARGET_HAVE_CTORS_DTORS false
+#define VXWORKS_OVERRIDE_OPTIONS /* empty */
+
+/* No math library needed. */
+#define MATH_LIBRARY ""
+
+/* No profiling. */
+#define VXWORKS_FUNCTION_PROFILER(FILE, LABELNO) do \
+{ \
+ sorry ("profiler support for VxWorks"); \
+} while (0)
+
+/* We occasionally need to distinguish between the VxWorks variants. */
+#define VXWORKS_KIND_NORMAL 1
+#define VXWORKS_KIND_AE 2
diff --git a/support/cpp/gcc/config/vxworks-dummy.h b/support/cpp/gcc/config/vxworks-dummy.h
new file mode 100644
index 000000000..6d78d9be6
--- /dev/null
+++ b/support/cpp/gcc/config/vxworks-dummy.h
@@ -0,0 +1,48 @@
+/* Dummy definitions of VxWorks-related macros
+ Copyright (C) 2007-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/>. */
+
+/* True if we're targeting VxWorks, VxWorks7 and/or 64bit. */
+#ifndef TARGET_VXWORKS
+#define TARGET_VXWORKS 0
+#endif
+
+#ifndef TARGET_VXWORKS7
+#define TARGET_VXWORKS7 0
+#endif
+
+#ifndef TARGET_VXWORKS64
+#define TARGET_VXWORKS64 0
+#endif
+
+/* True if generating code for a VxWorks RTP. */
+#ifndef TARGET_VXWORKS_RTP
+#define TARGET_VXWORKS_RTP false
+#endif
+
+/* The symbol that points to an RTP's table of GOTs. */
+#define VXWORKS_GOTT_BASE (gcc_unreachable (), "")
+
+/* The symbol that holds the index of the current module's GOT in
+ VXWORKS_GOTT_BASE. */
+#define VXWORKS_GOTT_INDEX (gcc_unreachable (), "")
diff --git a/support/cpp/gcc/config/vxworks-stdint.h b/support/cpp/gcc/config/vxworks-stdint.h
new file mode 100644
index 000000000..f62fce8d8
--- /dev/null
+++ b/support/cpp/gcc/config/vxworks-stdint.h
@@ -0,0 +1,53 @@
+/* Definitions for <stdint.h> types on systems using VxWorks.
+ Copyright (C) 2017-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/>. */
+
+#define SIG_ATOMIC_TYPE "unsigned char"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+#define INT_LEAST8_TYPE "signed char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+#define INT_FAST8_TYPE "signed char"
+#define INT_FAST16_TYPE "int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_FAST8_TYPE "unsigned char"
+#define UINT_FAST16_TYPE "unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int")
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int")
diff --git a/support/cpp/gcc/config/vxworks.h b/support/cpp/gcc/config/vxworks.h
new file mode 100644
index 000000000..6a5f2f8f2
--- /dev/null
+++ b/support/cpp/gcc/config/vxworks.h
@@ -0,0 +1,381 @@
+/* Common VxWorks target definitions for GNU compiler.
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
+ Contributed by Wind River Systems.
+ Rewritten by CodeSourcery, LLC.
+
+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/>. */
+
+/* Assert that we are targeting VxWorks. */
+#undef TARGET_VXWORKS
+#define TARGET_VXWORKS 1
+
+/* In kernel mode, VxWorks provides all the libraries itself, as well as
+ the functionality of startup files, etc. In RTP mode, it behaves more
+ like a traditional Unix, with more external files. Most of our specs
+ must be aware of the difference. */
+
+/* Help locate system headers, assuming $sysroot set to $VSB_DIR on vx7 and
+ $WIND_BASE/target prior to that. Specs allow tailoring for RTP vs kernel,
+ and -idirafter allows putting system directories after GCC's own directories
+ for standard headers such as <stddef.h> or fixed include.
+
+ Regarding fixed includes, note the effect of sysroot_headers_suffix_spec:
+
+ For the case of VxWorks prior to 7 below, we have:
+
+ #define SYSROOT_HEADERS_SUFFIX_SPEC "%{mrtp:/usr/h;:/h}"
+
+ This results in
+
+ $build_sysroot/h ---> $prefix/include-fixed
+ $build_sysroot/usr/h ---> $prefix/include-fixed/mrtp for -mrtp
+
+ This is very different from what we'd get without a headers_suffix,
+ which would be:
+
+ $build_sysroot ---> $prefix/include-fixed/h
+ /usr/h
+
+ From (say) #include <assert.h>, we would find the fixed version
+ in the first case, not in the second. */
+
+/* Since we provide a default -isystem, expand -isystem on the command
+ line early. Then restrict the amount of references we add when compiling
+ self-tests, as these may be run in contexts where the VxWorks environment
+ isn't available. */
+
+#if TARGET_VXWORKS7
+
+/* We arrange not rely on fixed includes for vx7 and the headers spread over
+ common kernel/rtp directories in addition to specific ones for each mode.
+ Setup sysroot_headers_suffix_spec to deal with kernel/rtp distinction. */
+
+#undef SYSROOT_HEADERS_SUFFIX_SPEC
+#define SYSROOT_HEADERS_SUFFIX_SPEC "%{mrtp:/usr/h;:/krnl/h}"
+
+#undef VXWORKS_ADDITIONAL_CPP_SPEC
+#define VXWORKS_ADDITIONAL_CPP_SPEC \
+ "%{!nostdinc:%{!fself-test=*: \
+ %{isystem*} \
+ -idirafter %:getenv(VSB_DIR /h) \
+ -idirafter %:getenv(VSB_DIR /share/h) \
+ -idirafter =/system \
+ -idirafter =/public \
+ }}"
+
+#else /* TARGET_VXWORKS7 */
+
+/* Prior to vx7, rtp and kernel headers are fairly segregated and fixincludes
+ is needed on each set of headers to cope with expectations of not so old
+ libstdc++. A perfect use case for sysroot_headers_suffix. */
+
+#undef SYSROOT_HEADERS_SUFFIX_SPEC
+#define SYSROOT_HEADERS_SUFFIX_SPEC "%{mrtp:/usr/h;:/h}"
+
+#undef VXWORKS_ADDITIONAL_CPP_SPEC
+#define VXWORKS_ADDITIONAL_CPP_SPEC \
+ "%{!nostdinc:%{!fself-test=*: \
+ %{isystem*} \
+ -idirafter =/wrn/coreip \
+ }}"
+
+#endif
+
+/* Our ports rely on gnu-user.h, which #defines _POSIX_SOURCE for
+ C++ by default. VxWorks doesn't provide 100% of what this implies
+ (e.g. ::mkstemp), so, arrange to prevent that by falling back to
+ the default CPP spec for C++ as well. */
+#undef CPLUSPLUS_CPP_SPEC
+
+/* For VxWorks static rtps, the system provides libc_internal.a for a variety
+ of purposes. Care is needed to include it appropriately.
+
+ - In some configurations, libc_internal fills in possible references from
+ the static libc that we don't wouldn't satisfy ourselves, say, with
+ libgcc. An example is the __aeabi_memcpy family of functions on arm,
+ which have very specific ABI allowances.
+
+ - OTOH, in some configurations the library provides typical libgcc
+ services, for example register save/restore entry points on powerpc. We
+ want our libgcc to prevail for symbols it would provide, so place
+ -lc_internal after -lc -lgcc.
+
+ - libc_internal also contains __init/__fini functions for
+ USE_INITFINI_ARRAY support. However, the system expects these in
+ every shared lib as well, with slightly different names, and it is
+ simpler for us to provide our own versions through vxcrtstuff.
+
+ In addition, some versions of VxWorks rely on explicit extra libraries for
+ system calls and the set of base network libraries of common use varies
+ across architectures. The default settings defined here might be redefined
+ by target specific port configuration files. */
+
+#define VXWORKS_SYSCALL_LIBS_RTP
+
+#if TARGET_VXWORKS7
+#define VXWORKS_NET_LIBS_RTP "-l%:if-exists-then-else(%:getenv(VSB_DIR /usr/h/public/rtnetStackLib.h) rtnet net)"
+#else
+#define VXWORKS_NET_LIBS_RTP "-lnet -ldsi"
+#endif
+
+#define VXWORKS_BASE_LIBS_RTP "-lc -lgcc %{!shared:-lc_internal}"
+
+#define VXWORKS_EXTRA_LIBS_RTP
+
+#define VXWORKS_LIBS_RTP \
+ VXWORKS_SYSCALL_LIBS_RTP " " VXWORKS_NET_LIBS_RTP " " \
+ VXWORKS_BASE_LIBS_RTP " " VXWORKS_EXTRA_LIBS_RTP
+
+/* TLS configuration. VxWorks 7 now always has proper TLS support.
+ Earlier versions did not, not even for RTPS. */
+#define VXWORKS_HAVE_TLS TARGET_VXWORKS7
+
+/* On Vx6 and previous, the libraries to pick up depends on the architecture,
+ so cannot be defined for all archs at once. On Vx7, a VSB is always needed
+ and its structure is fixed and does not depend on the arch. We can thus
+ tell gcc where to look for when linking with RTP libraries. Use
+ STARTFILE_PREFIX_SPEC for this, instead of explicit -L options in LIB_SPEC,
+ so they survive -nodefaultlibs. */
+
+/* On Vx7 RTP, we need to drag the __tls__ symbol to trigger initialization of
+ tlsLib, responsible for TLS support by the OS. */
+
+#if TARGET_VXWORKS7
+
+/* For static links, /usr/lib/common has everything. For dynamic links,
+ /usr/lib/common/PIC has the static libs and objects that might be needed
+ in the closure (e.g. crt0.o), while the shared version of standard deps
+ (e.g. libc.so) are still in /usr/lib/common. */
+#undef STARTFILE_PREFIX_SPEC
+#define STARTFILE_PREFIX_SPEC \
+ "%{shared|non-static:/usr/lib/common/PIC} /usr/lib/common"
+
+#define TLS_SYM "-u __tls__"
+
+#else
+
+#define TLS_SYM ""
+
+#endif
+
+#undef VXWORKS_LIB_SPEC
+#define VXWORKS_LIB_SPEC \
+"%{mrtp:%{!shared:%{non-static:-u " USER_LABEL_PREFIX "_STI__6__rtld -ldl} \
+ " TLS_SYM " \
+ --start-group " VXWORKS_LIBS_RTP " --end-group}}"
+
+#if TARGET_VXWORKS7
+#define VXWORKS_EXTRA_LINK_SPEC ""
+#else
+/* Older VxWorks RTPs can only link with shared libs, and
+ need special switches --force-dynamic --export-dynamic. */
+#define VXWORKS_EXTRA_LINK_SPEC \
+"%{mrtp:%{!shared:%{non-static:--force-dynamic --export-dynamic}}}"
+#endif
+
+/* A default link_os expansion for RTPs, that cpu ports may override. */
+#undef VXWORKS_LINK_OS_SPEC
+#define VXWORKS_LINK_OS_SPEC "%(link_os)"
+
+/* The -B and -X switches are for DIAB based linking. */
+#undef VXWORKS_BASE_LINK_SPEC
+#define VXWORKS_BASE_LINK_SPEC \
+"%{!mrtp:-r} \
+ %{v:-V} \
+ %{shared:-shared} \
+ %{Bstatic:-Bstatic} \
+ %{Bdynamic:-Bdynamic} \
+ %{!Xbind-lazy:-z now} \
+ %{Xbind-now:%{Xbind-lazy: \
+ %e-Xbind-now and -Xbind-lazy are incompatible}} \
+ %{mrtp:-q %{!shared:%{!non-static:-static}} \
+ %{h*} %{R*} %{!T*: %(link_start)}" \
+ VXWORKS_LINK_OS_SPEC "}"
+
+#undef VXWORKS_LINK_SPEC
+#define VXWORKS_LINK_SPEC VXWORKS_BASE_LINK_SPEC " " VXWORKS_EXTRA_LINK_SPEC
+
+#undef VXWORKS_LIBGCC_SPEC
+#if defined(ENABLE_SHARED_LIBGCC)
+#define VXWORKS_LIBGCC_SPEC \
+"%{!mrtp:-lgcc -lgcc_eh} \
+ %{mrtp:%{!static-libgcc:%{shared|non-static:-lgcc_s;:-lgcc -lgcc_eh}} \
+ %{static-libgcc:-lgcc -lgcc_eh}}"
+#else
+#define VXWORKS_LIBGCC_SPEC "-lgcc"
+#endif
+
+/* Setup the crtstuff begin/end we might need for dwarf EH registration
+ and/or INITFINI_ARRAY support for shared libs. */
+
+#if (HAVE_INITFINI_ARRAY_SUPPORT && defined(ENABLE_SHARED_LIBGCC)) \
+ || (DWARF2_UNWIND_INFO && !defined(CONFIG_SJLJ_EXCEPTIONS))
+#define VX_CRTBEGIN_SPEC "%{!shared:vx_crtbegin.o%s;:vx_crtbeginS.o%s}"
+#define VX_CRTEND_SPEC "%{!shared:vx_crtend.o%s;:vx_crtendS.o%s}"
+#else
+#define VX_CRTBEGIN_SPEC ""
+#define VX_CRTEND_SPEC ""
+#endif
+
+#undef VXWORKS_STARTFILE_SPEC
+#define VXWORKS_STARTFILE_SPEC \
+ VX_CRTBEGIN_SPEC " %{mrtp:%{!shared:-l:crt0.o}}"
+
+#undef VXWORKS_ENDFILE_SPEC
+#define VXWORKS_ENDFILE_SPEC VX_CRTEND_SPEC
+
+#undef VXWORKS_CC1_SPEC
+#if TARGET_VXWORKS7
+#define VXWORKS_CC1_SPEC \
+ "%(cc1_cpu) %{!mrtp:%{!ftls-model=*:-ftls-model=local-exec}}"
+#else
+#define VXWORKS_CC1_SPEC ""
+#endif
+
+/* Do VxWorks-specific parts of TARGET_OPTION_OVERRIDE. */
+#undef VXWORKS_OVERRIDE_OPTIONS
+#define VXWORKS_OVERRIDE_OPTIONS vxworks_override_options ()
+extern void vxworks_override_options (void);
+
+/* Whether the VxWorks variant and mode supports constructors/destructors
+ placed in .ctors/.dtors section or if we should generate proxy functions
+ for them, with special names which munch knows how to collect. On most
+ versions of VxWorks, only the RTP loader supports .ctors/.dtors sections,
+ not the kernel module loader. */
+#define TARGET_VXWORKS_HAVE_CTORS_DTORS TARGET_VXWORKS_RTP
+
+/* Support for prioritized ctors/dtors is in sync with the support for sections
+ on the VxWorks front, and is assumed to be provided by whatever linker level
+ glue is required if we were configured with --enable-initfini-array. */
+#define SUPPORTS_INIT_PRIORITY \
+ (TARGET_VXWORKS_HAVE_CTORS_DTORS || HAVE_INITFINI_ARRAY_SUPPORT)
+
+#if !HAVE_INITFINI_ARRAY_SUPPORT
+/* VxWorks requires special handling of constructors and destructors.
+ All VxWorks configurations must use these functions. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR vxworks_asm_out_constructor
+#undef TARGET_ASM_DESTRUCTOR
+#define TARGET_ASM_DESTRUCTOR vxworks_asm_out_destructor
+extern void vxworks_asm_out_constructor (rtx symbol, int priority);
+extern void vxworks_asm_out_destructor (rtx symbol, int priority);
+#endif
+
+/* Override the vxworks-dummy.h definitions. TARGET_VXWORKS_RTP
+ is defined by vxworks.opt. */
+#undef VXWORKS_GOTT_BASE
+#define VXWORKS_GOTT_BASE "__GOTT_BASE__"
+#undef VXWORKS_GOTT_INDEX
+#define VXWORKS_GOTT_INDEX "__GOTT_INDEX__"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_VXWORKS64 ? "long int" : "int")
+
+#undef SIZE_TYPE
+#define SIZE_TYPE (TARGET_VXWORKS64 ? "long unsigned int" : "unsigned int")
+
+/* Assumptions on the target libc. VxWorks 7, post SR600, provides a C11
+ runtime without sincos support. */
+#undef TARGET_LIBC_HAS_FUNCTION
+#define TARGET_LIBC_HAS_FUNCTION \
+ (TARGET_VXWORKS7 ? default_libc_has_function : no_c99_libc_has_function)
+
+/* Both kernels and RTPs have the facilities required by this macro. */
+#define TARGET_POSIX_IO
+
+/* A VxWorks implementation of TARGET_OS_CPP_BUILTINS. */
+
+/* The VxWorks personality we rely on, controlling which sections of system
+ headers files we trigger. This might be redefined on targets where the
+ base VxWorks environment doesn't come with a GNU toolchain. */
+
+#define VXWORKS_PERSONALITY "gnu"
+
+#define VXWORKS_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__vxworks"); \
+ builtin_define ("__VXWORKS__"); \
+ builtin_assert ("system=unix"); \
+ if (TARGET_VXWORKS_RTP) \
+ builtin_define ("__RTP__"); \
+ else \
+ builtin_define ("_WRS_KERNEL"); \
+ builtin_define ("TOOL_FAMILY=" VXWORKS_PERSONALITY); \
+ builtin_define ("TOOL=" VXWORKS_PERSONALITY); \
+ if (TARGET_VXWORKS7) \
+ { \
+ builtin_define ("_VSB_CONFIG_FILE=<config/vsbConfig.h>"); \
+ \
+ /* _ALLOW_KEYWORD_MACROS is needed on VxWorks 7 to \
+ prevent compilation failures triggered by our \
+ definition of "inline" in ansidecl when "inline" \
+ is not a keyword. */ \
+ if (!flag_isoc99 && !c_dialect_cxx()) \
+ builtin_define ("_ALLOW_KEYWORD_MACROS"); \
+ } \
+ /* C++ support relies on C99 features from C++11, even C++98 \
+ for listdc++ in particular, with corresponding checks at \
+ configure time. Make sure C99 features are exposed by the \
+ system headers. */ \
+ if (c_dialect_cxx()) \
+ builtin_define("_C99"); \
+ } \
+ while (0)
+
+/* For specific CPU macro definitions expected by the system headers,
+ different versions of VxWorks expect different forms of macros,
+ such as "_VX_CPU=..." on Vx7 and some variants of Vx6, or "CPU=..."
+ on all Vx6 and earlier. Setup a common prefix macro here, that
+ arch specific ports can reuse. */
+
+#if TARGET_VXWORKS7
+#define VX_CPU_PREFIX "_VX_"
+#else
+#define VX_CPU_PREFIX ""
+#endif
+
+#define VXWORKS_KIND VXWORKS_KIND_NORMAL
+
+/* The diab linker does not handle .gnu_attribute sections. */
+#undef HAVE_AS_GNU_ATTRIBUTE
+
+/* We call vxworks's cacheTextUpdate instead of CLEAR_INSN_CACHE if
+ needed. We don't want to force a call on targets that don't define
+ cache-clearing insns nor CLEAR_INSN_CACHE. */
+#undef TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE
+#define TARGET_EMIT_CALL_BUILTIN___CLEAR_CACHE \
+ vxworks_emit_call_builtin___clear_cache
+extern void vxworks_emit_call_builtin___clear_cache (rtx begin, rtx end);
+
+/* Default dwarf control values, for non-gdb debuggers that come with
+ VxWorks. */
+
+#undef VXWORKS_DWARF_VERSION_DEFAULT
+#define VXWORKS_DWARF_VERSION_DEFAULT (TARGET_VXWORKS7 ? 4 : 2)
+
+#undef DWARF_GNAT_ENCODINGS_DEFAULT
+#define DWARF_GNAT_ENCODINGS_DEFAULT \
+ (TARGET_VXWORKS7 ? DWARF_GNAT_ENCODINGS_MINIMAL : DWARF_GNAT_ENCODINGS_ALL)
+
+/* The default configuration of incremental LTO linking (-flinker-output=rel)
+ warns if an object file included in the link does not contain LTO bytecode,
+ because in this case the output will not contain it either, thus preventing
+ further incremental LTO linking. We do not do repeated incremental linking
+ so silence the warning (instead of passing -flinker-output=nolto-rel). */
+#undef LTO_PLUGIN_SPEC
+#define LTO_PLUGIN_SPEC "%{!mrtp:-plugin-opt=-linker-output-auto-nolto-rel}"
diff --git a/support/cpp/gcc/config/vxworksae.h b/support/cpp/gcc/config/vxworksae.h
new file mode 100644
index 000000000..0cc45467a
--- /dev/null
+++ b/support/cpp/gcc/config/vxworksae.h
@@ -0,0 +1,96 @@
+/* Common VxWorks AE target definitions for GNU compiler.
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+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 header should be included after including vx-common.h. */
+
+/* Most of the definitions below this point are versions of the
+ vxworks.h definitions, without the -mrtp bits. */
+
+/* Resolve subdirectory of VxWorks AE target headers. */
+#define VXWORKSAE_TARGET_DIR(SUBDIR) "%:getenv(WIND_BASE /target" SUBDIR ")"
+
+/* Include target/vThreads/h or target/h (depending on the compilation
+ mode), and then target/val/h (in either mode). The macros defined
+ are in the user's namespace, but the VxWorks headers require
+ them. */
+#undef VXWORKS_ADDITIONAL_CPP_SPEC
+#define VXWORKS_ADDITIONAL_CPP_SPEC " \
+ %{!nostdinc:%{isystem*}} \
+ %{mvthreads:-DVTHREADS=1 \
+ %{!nostdinc:-isystem " VXWORKSAE_TARGET_DIR("/vThreads/h") "}} \
+ %{!mvthreads:-DAE653_BUILD=1 \
+ %{!nostdinc:-isystem " VXWORKSAE_TARGET_DIR("/h") "}} \
+ %{!nostdinc:-isystem " VXWORKSAE_TARGET_DIR("/val/h") "}"
+
+#undef VXWORKS_LIB_SPEC
+#define VXWORKS_LIB_SPEC ""
+
+#undef VXWORKS_LINK_SPEC
+#define VXWORKS_LINK_SPEC \
+ "-r %{v:-V}"
+
+#undef VXWORKS_LIBGCC_SPEC
+#define VXWORKS_LIBGCC_SPEC \
+ "-lgcc"
+
+/* The VxWorks AE ports features are restricted on purpose. No RTPs,
+ for example. */
+
+#undef TARGET_VXWORKS_HAVE_CTORS_DTORS
+#define TARGET_VXWORKS_HAVE_CTORS_DTORS 0
+
+#undef VXWORKS_STARTFILE_SPEC
+#define VXWORKS_STARTFILE_SPEC ""
+
+#define VXWORKS_KIND VXWORKS_KIND_AE
+
+/* Both kernels and RTPs have the facilities required by this macro. */
+#define TARGET_POSIX_IO
+
+/* The AE/653 system headers all predate the introduction of _VX_ prefixes
+ ahead of CPU families of macros. */
+#define VX_CPU_PREFIX ""
+
+/* A VxWorks 653 implementation of TARGET_OS_CPP_BUILTINS. */
+#define VXWORKS_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__vxworks"); \
+ builtin_define ("__VXWORKS__"); \
+ } \
+ while (0)
+
+/* Do VxWorks-specific parts of TARGET_OPTION_OVERRIDE. */
+
+/* None of the VxWorks AE/653/MILS ports to date has native TLS support. */
+#define VXWORKS_HAVE_TLS 0
+
+#undef VXWORKS_OVERRIDE_OPTIONS
+#define VXWORKS_OVERRIDE_OPTIONS vxworks_override_options ()
+extern void vxworks_override_options (void);
+
+/* Default dwarf control values, for non-gdb debuggers that come with
+ VxWorks. */
+
+#undef VXWORKS_DWARF_VERSION_DEFAULT
+#define VXWORKS_DWARF_VERSION_DEFAULT 2
+
+#undef DWARF_GNAT_ENCODINGS_DEFAULT
+#define DWARF_GNAT_ENCODINGS_DEFAULT DWARF_GNAT_ENCODINGS_ALL
diff --git a/support/cpp/gcc/configure b/support/cpp/gcc/configure
new file mode 100755
index 000000000..9fb70a94c
--- /dev/null
+++ b/support/cpp/gcc/configure
@@ -0,0 +1,33719 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1
+
+ test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+PACKAGE_URL=
+
+ac_unique_file="gcc.cc"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+LIBOBJS
+CET_HOST_FLAGS
+NO_PIE_FLAG
+NO_PIE_CFLAGS
+enable_default_pie
+PICFLAG
+enable_host_shared
+enable_plugin
+pluginlibs
+ISLINC
+ISLLIBS
+GMPINC
+GMPLIBS
+target_cpu_default
+d_target_objs
+fortran_target_objs
+cxx_target_objs
+c_target_objs
+use_gcc_stdint
+xm_defines
+xm_include_list
+xm_file_list
+tm_d_include_list
+tm_d_file_list
+tm_p_include_list
+tm_p_file_list
+tm_defines
+tm_include_list
+tm_file_list
+common_out_object_file
+common_out_file
+out_object_file
+out_file
+objc_boehm_gc
+md_file
+local_prefix
+lang_tree_files
+lang_specs_files
+lang_opt_files
+install
+out_host_hook_obj
+host_xm_defines
+host_xm_include_list
+host_xm_file_list
+host_exeext
+gcc_gxx_libcxx_include_dir_add_sysroot
+gcc_gxx_libcxx_include_dir
+gcc_gxx_include_dir_add_sysroot
+gcc_gxx_include_dir
+gcc_config_arguments
+float_h_file
+extra_programs
+extra_objs
+extra_headers_list
+user_headers_inc_next_post
+user_headers_inc_next_pre
+extra_gcc_objs
+TM_MULTILIB_EXCEPTIONS_CONFIG
+TM_MULTILIB_CONFIG
+TM_ENDIAN_CONFIG
+tmake_file
+xmake_file
+cpp_install_dir
+selftest_languages
+check_languages
+build_file_translate
+build_xm_defines
+build_xm_include_list
+build_xm_file_list
+build_install_headers_dir
+build_exeext
+all_selected_languages
+all_languages
+all_lang_makefrags
+all_lang_configurefrags
+all_gtfiles
+all_compilers
+srcdir
+subdirs
+dollar
+gcc_tooldir
+enable_lto
+DO_LINK_SERIALIZATION
+DO_LINK_MUTEX
+CSCOPE
+ETAGS
+CTAGS
+MAINT
+zlibinc
+zlibdir
+HOST_LIBS
+enable_default_ssp
+thin_archive_support
+ld_soname_option
+ld_version_script_option
+libgcc_visibility
+ORIGINAL_DSYMUTIL_FOR_TARGET
+gcc_cv_dsymutil
+gcc_cv_otool
+gcc_cv_readelf
+gcc_cv_objdump
+ORIGINAL_NM_FOR_TARGET
+gcc_cv_nm
+ORIGINAL_LD_GOLD_FOR_TARGET
+ORIGINAL_LD_BFD_FOR_TARGET
+ORIGINAL_LD_FOR_TARGET
+ORIGINAL_PLUGIN_LD_FOR_TARGET
+gcc_cv_ld
+ORIGINAL_AS_FOR_TARGET
+gcc_cv_as
+enable_fast_install
+objdir
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+STRIP
+OBJDUMP
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+LIBTOOL
+collect2
+STMP_FIXINC
+BUILD_LDFLAGS
+BUILD_CXXFLAGS
+BUILD_CFLAGS
+CXX_FOR_BUILD
+CC_FOR_BUILD
+inhibit_libc
+BUILD_SYSTEM_HEADER_DIR
+SYSTEM_HEADER_DIR
+ALL
+CROSS
+CATOBJEXT
+GENCAT
+INSTOBJEXT
+DATADIRNAME
+CATALOGS
+POSUB
+GMSGFMT
+XGETTEXT
+INCINTL
+LIBINTL_DEP
+LIBINTL
+USE_NLS
+get_gcc_base_ver
+HAVE_AUTO_BUILD
+extra_opt_files
+extra_modes_file
+NATIVE_SYSTEM_HEADER_DIR
+objext
+manext
+LIBICONV_DEP
+LTLIBICONV
+LIBICONV
+ZSTD_LDFLAGS
+ZSTD_CPPFLAGS
+ZSTD_LIB
+ZSTD_INCLUDE
+DL_LIB
+LDEXP_LIB
+NETLIBS
+EXTRA_GCC_LIBS
+GNAT_LIBEXC
+COLLECT2_LIBS
+CXXDEPMODE
+DEPDIR
+am__leading_dot
+doc_build_sys
+AR
+NM
+BISON
+FLEX
+GENERATED_MANPAGES
+BUILD_INFO
+MAKEINFO
+have_mktemp_command
+make_compare_target
+INSTALL_DATA
+INSTALL_PROGRAM
+INSTALL
+ranlib_flags
+RANLIB
+LN
+LN_S
+AWK
+SET_MAKE
+omp_device_property_deps
+omp_device_properties
+accel_dir_suffix
+real_target_noncanonical
+enable_as_accelerator
+gnat_install_lib
+REPORT_BUGS_TEXI
+REPORT_BUGS_TO
+PKGVERSION
+CONFIGURE_SPECS
+enable_gcov
+enable_shared
+enable_fixed_point
+enable_decimal_float
+with_float
+with_cpu
+enable_multiarch
+enable_multilib
+coverage_flags
+valgrind_command
+valgrind_path_defines
+valgrind_path
+TREECHECKING
+nocommon_flag
+noexception_flags
+warn_cxxflags
+warn_cflags
+c_strict_warn
+strict_warn
+c_loose_warn
+loose_warn
+aliasing_flags
+CPP
+EGREP
+GREP
+CXXCPP
+PICFLAG_FOR_TARGET
+GDCFLAGS
+ac_ct_CXX
+CXXFLAGS
+CXX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+GENINSRC
+CROSS_SYSTEM_HEADER_DIR
+TARGET_SYSTEM_ROOT_DEFINE
+TARGET_SYSTEM_ROOT
+SYSROOT_CFLAGS_FOR_TARGET
+target_subdir
+host_subdir
+build_subdir
+build_libsubdir
+target_noncanonical
+host_noncanonical
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files='option_includes
+language_hooks'
+ac_user_opts='
+enable_option_checking
+with_build_libsubdir
+with_local_prefix
+with_native_system_header_dir
+with_build_sysroot
+with_sysroot
+with_gxx_include_dir
+with_gxx_libcxx_include_dir
+with_cpp_install_dir
+enable_generated_files_in_srcdir
+with_gnu_ld
+with_ld
+with_demangler_in_ld
+with_dsymutil
+with_gnu_as
+with_as
+enable_largefile
+enable_build_format_warnings
+enable_werror_always
+enable_checking
+enable_coverage
+enable_gather_detailed_mem_stats
+enable_valgrind_annotations
+enable_multilib
+enable_multiarch
+with_stack_clash_protection_guard_size
+enable___cxa_atexit
+enable_decimal_float
+enable_fixed_point
+enable_threads
+enable_tls
+enable_vtable_verify
+enable_analyzer
+enable_objc_gc
+with_dwarf2
+enable_shared
+enable_gcov
+with_specs
+with_pkgversion
+with_bugurl
+with_documentation_root_url
+with_changes_root_url
+enable_languages
+with_multilib_list
+with_multilib_generator
+with_zstd
+with_zstd_include
+with_zstd_lib
+enable_rpath
+with_libiconv_prefix
+with_libiconv_type
+enable_sjlj_exceptions
+with_gcc_major_version_only
+enable_secureplt
+enable_mingw_wildcard
+enable_large_address_aware
+enable_leading_mingw64_underscores
+enable_cld
+enable_frame_pointer
+enable_win32_registry
+enable_static
+with_pic
+enable_fast_install
+enable_libtool_lock
+enable_ld
+enable_gold
+with_plugin_ld
+enable_gnu_indirect_function
+enable_initfini_array
+enable_comdat
+enable_newlib_nano_formatted_io
+enable_standard_branch_protection
+enable_fix_cortex_a53_835769
+enable_fix_cortex_a53_843419
+with_glibc_version
+enable_gnu_unique_object
+enable_linker_build_id
+enable_libssp
+enable_default_ssp
+with_long_double_128
+with_long_double_format
+with_gc
+with_system_zlib
+enable_maintainer_mode
+enable_link_mutex
+enable_link_serialization
+enable_version_specific_runtime_libs
+enable_host_shared
+enable_libquadmath_support
+with_linker_hash_style
+with_diagnostics_color
+with_diagnostics_urls
+enable_default_pie
+enable_cet
+enable_s390_excess_float_precision
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CXXCPP
+CPP
+GMPLIBS
+GMPINC
+ISLLIBS
+ISLINC'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-generated-files-in-srcdir
+ put copies of generated files in source dir intended
+ for creating source tarballs for users without
+ texinfo bison or flex
+ --disable-largefile omit support for large files
+ --disable-build-format-warnings
+ don't use -Wformat while building GCC
+ --enable-werror-always enable -Werror despite compiler version
+ --enable-checking[=LIST]
+ enable expensive run-time checks. With LIST, enable
+ only specific categories of checks. Categories are:
+ yes,no,all,none,release. Flags are:
+ assert,df,extra,fold,gc,gcac,gimple,misc,
+ rtlflag,rtl,runtime,tree,valgrind,types
+ --enable-coverage[=LEVEL]
+ enable compiler's code coverage collection. Use to
+ measure compiler performance and locate unused parts
+ of the compiler. With LEVEL, specify optimization.
+ Values are opt, noopt, default is noopt
+ --enable-gather-detailed-mem-stats
+ enable detailed memory allocation stats gathering
+ --enable-valgrind-annotations
+ enable valgrind runtime interaction
+ --enable-multilib enable library support for multiple ABIs
+ --enable-multiarch enable support for multiarch paths
+ --enable-__cxa_atexit enable __cxa_atexit for C++
+ --enable-decimal-float={no,yes,bid,dpd}
+ enable decimal float extension to C. Selecting 'bid'
+ or 'dpd' choses which decimal floating point format
+ to use
+ --enable-fixed-point enable fixed-point arithmetic extension to C
+ --enable-threads[=LIB] enable thread usage for target GCC, using LIB thread
+ package
+ --enable-tls enable or disable generation of tls code overriding
+ the assembler check for tls support
+ --enable-vtable-verify enable vtable verification feature
+ --disable-analyzer disable -fanalyzer static analyzer
+ --enable-objc-gc enable the use of Boehm's garbage collector with the
+ GNU Objective-C runtime
+ --disable-shared don't provide a shared libgcc
+ --disable-gcov don't provide libgcov and related host tools
+ --enable-languages=LIST specify which front-ends to build
+ --disable-rpath do not hardcode runtime library paths
+ --enable-sjlj-exceptions
+ arrange to use setjmp/longjmp exception handling
+ --enable-secureplt enable -msecure-plt by default for PowerPC
+ --enable-mingw-wildcard Set whether to expand wildcard on command-line.
+ Default to platform configuration
+ --enable-large-address-aware
+ Link mingw executables with --large-address-aware
+ --enable-leading-mingw64-underscores
+ enable leading underscores on 64 bit mingw targets
+ --enable-cld enable -mcld by default for 32bit x86
+ --enable-frame-pointer enable -fno-omit-frame-pointer by default for x86
+ --disable-win32-registry
+ disable lookup of installation paths in the Registry
+ on Windows hosts
+ --enable-win32-registry enable registry lookup (default)
+ --enable-win32-registry=KEY
+ use KEY instead of GCC version as the last portion
+ of the registry key
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --enable-ld[=ARG] build ld [ARG={default,yes,no}]
+ --enable-gold[=ARG] build gold [ARG={default,yes,no}]
+ --enable-gnu-indirect-function
+ enable the use of the @gnu_indirect_function to
+ glibc systems
+ --enable-initfini-array use .init_array/.fini_array sections
+ --enable-comdat enable COMDAT group support
+ --enable-newlib-nano-formatted-io
+ Use nano version formatted IO
+
+ --enable-standard-branch-protection
+ enable Branch Target Identification Mechanism and
+ Return Address Signing by default for AArch64
+ --disable-standard-branch-protection
+ disable Branch Target Identification Mechanism and
+ Return Address Signing by default for AArch64
+
+
+ --enable-fix-cortex-a53-835769
+ enable workaround for AArch64 Cortex-A53 erratum
+ 835769 by default
+ --disable-fix-cortex-a53-835769
+ disable workaround for AArch64 Cortex-A53 erratum
+ 835769 by default
+
+
+ --enable-fix-cortex-a53-843419
+ enable workaround for AArch64 Cortex-A53 erratum
+ 843419 by default
+ --disable-fix-cortex-a53-843419
+ disable workaround for AArch64 Cortex-A53 erratum
+ 843419 by default
+
+ --enable-gnu-unique-object
+ enable the use of the @gnu_unique_object ELF
+ extension on glibc systems
+ --enable-linker-build-id
+ compiler will always pass --build-id to linker
+ --enable-libssp enable linking against libssp
+ --enable-default-ssp enable Stack Smashing Protection as default
+ --enable-maintainer-mode
+ enable make rules and dependencies not useful (and
+ sometimes confusing) to the casual installer
+ --enable-link-mutex avoid linking multiple front-ends at once to avoid
+ thrashing on the build machine
+ --enable-link-serialization
+ avoid linking multiple GCC front-ends at once using
+ make dependencies to avoid thrashing on the build
+ machine
+ --enable-version-specific-runtime-libs
+ specify that runtime libraries should be installed
+ in a compiler-specific directory
+ --enable-host-shared build host code as shared libraries
+ --disable-libquadmath-support
+ disable libquadmath support for Fortran
+ --enable-default-pie enable Position Independent Executable as default
+ --enable-cet enable Intel CET in host libraries [default=auto]
+ --enable-s390-excess-float-precision
+ on s390 targets, evaluate float with double
+ precision when in standards-conforming mode
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-build-libsubdir=DIR Directory where to find libraries for build system
+ --with-local-prefix=DIR specifies directory to put local include
+ --with-native-system-header-dir=dir
+ use dir as the directory to look for standard
+ system header files in. Defaults to /usr/include.
+ --with-build-sysroot=sysroot
+ use sysroot as the system root during the build
+ --with-sysroot[=DIR] search for usr/lib, usr/include, et al, within DIR
+ --with-gxx-include-dir=DIR
+ specifies directory to put g++ header files
+ --with-gxx-libcxx-include-dir=DIR
+ specifies directory to find libc++ header files
+ --with-cpp-install-dir=DIR
+ install the user visible C preprocessor in DIR
+ (relative to PREFIX) as well as PREFIX/bin
+ --with-gnu-ld arrange to work with GNU ld
+ --with-ld arrange to use the specified ld (full pathname)
+ --with-demangler-in-ld try to use demangler in GNU ld
+ --with-dsymutil arrange to use the specified dsymutil (full
+ pathname)
+ --with-gnu-as arrange to work with GNU as
+ --with-as arrange to use the specified as (full pathname)
+ --with-stack-clash-protection-guard-size=size
+ Set the default stack clash protection guard size
+ for specific targets as a power of two in bytes.
+ --with-dwarf2 force the default debug format to be DWARF 2
+ --with-specs=SPECS add SPECS to driver command-line processing
+ --with-pkgversion=PKG Use PKG in the version string in place of "GCC"
+ --with-bugurl=URL Direct users to URL to report a bug
+ --with-documentation-root-url=URL
+ Root for documentation URLs
+ --with-changes-root-url=URL
+ Root for GCC changes URLs
+ --with-multilib-list select multilibs (AArch64, ARM, AVR, OR1K, RISC-V,
+ SH and x86-64 only)
+ --with-multilib-generator
+ Multi-libs configuration string (RISC-V only)
+ --with-zstd=PATH specify prefix directory for installed zstd library.
+ Equivalent to --with-zstd-include=PATH/include plus
+ --with-zstd-lib=PATH/lib
+ --with-zstd-include=PATH
+ specify directory for installed zstd include files
+ --with-zstd-lib=PATH specify directory for the installed zstd library
+ --with-gnu-ld assume the C compiler uses GNU ld default=no
+ --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib
+ --without-libiconv-prefix don't search for libiconv in includedir and libdir
+ --with-libiconv-type=TYPE type of library to search for (auto/static/shared)
+ --with-gcc-major-version-only
+ use only GCC major number in filesystem paths
+ --with-pic try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-plugin-ld=[ARG] specify the plugin linker
+ --with-glibc-version=M.N
+ assume GCC used with glibc version M.N or later
+ --with-long-double-128 use 128-bit long double by default
+ --with-long-double-format={ieee,ibm}
+ Specify whether PowerPC long double uses IEEE or IBM format
+
+ --with-gc={page,zone} this option is not supported anymore. It used to
+ choose the garbage collection mechanism to use with
+ the compiler
+ --with-system-zlib use installed libz
+ --with-linker-hash-style={sysv,gnu,both}
+ specify the linker hash style
+ --with-diagnostics-color={never,auto,auto-if-env,always}
+ specify the default of -fdiagnostics-color option
+ auto-if-env stands for -fdiagnostics-color=auto if
+ GCC_COLOR environment variable is present and
+ -fdiagnostics-color=never otherwise
+ --with-diagnostics-urls={never,auto,auto-if-env,always}
+ specify the default of -fdiagnostics-urls option
+ auto-if-env stands for -fdiagnostics-urls=auto if
+ GCC_URLS or TERM_URLS environment variable is
+ present and -fdiagnostics-urls=never otherwise
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ CXXCPP C++ preprocessor
+ CPP C preprocessor
+ GMPLIBS How to link GMP
+ GMPINC How to find GMP include files
+ ISLLIBS How to link isl
+ ISLINC How to find isl include files
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_cxx_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_mongrel
+
+# ac_fn_cxx_try_run LINENO
+# ------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_cxx_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_run
+
+# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_cxx_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_cxx_compute_int LINENO EXPR VAR INCLUDES
+# ----------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_cxx_compute_int ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_hi=$ac_mid; break
+else
+ as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_lo=$ac_mid; break
+else
+ as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_hi=$ac_mid
+else
+ as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+ else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (($2) < 0)
+ {
+ long int i = longval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%ld", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%lu", i);
+ }
+ /* Do not output a trailing newline, as this causes \r\n confusion
+ on some platforms. */
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+ ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+ fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_compute_int
+
+# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES
+# ---------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_cxx_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_type
+
+# ac_fn_c_find_intX_t LINENO BITS VAR
+# -----------------------------------
+# Finds a signed integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_intX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
+$as_echo_n "checking for int$2_t... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
+ for ac_type in int$2_t 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ enum { N = $2 / 2 - 1 };
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ enum { N = $2 / 2 - 1 };
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+ < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ case $ac_type in #(
+ int$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if eval test \"x\$"$3"\" = x"no"; then :
+
+else
+ break
+fi
+ done
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_intX_t
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+$as_echo_n "checking for uint$2_t... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
+ for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ case $ac_type in #(
+ uint$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if eval test \"x\$"$3"\" = x"no"; then :
+
+else
+ break
+fi
+ done
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_uintX_t
+
+# ac_fn_cxx_check_header_preproc LINENO HEADER VAR
+# ------------------------------------------------
+# Tests whether HEADER is present, setting the cache variable VAR accordingly.
+ac_fn_cxx_check_header_preproc ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_preproc
+
+# ac_fn_cxx_check_func LINENO FUNC VAR
+# ------------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_cxx_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_func
+
+# ac_fn_cxx_check_decl LINENO SYMBOL VAR INCLUDES
+# -----------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_cxx_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_decl
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_preproc LINENO HEADER VAR
+# ----------------------------------------------
+# Tests whether HEADER is present, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_preproc ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_preproc
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+ac_config_headers="$ac_config_headers auto-host.h:config.in"
+
+
+gcc_version=`cat $srcdir/BASE-VER`
+
+# Determine the host, build, and target systems
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+# Determine the noncanonical host name, for Ada.
+ case ${build_alias} in
+ "") build_noncanonical=${build} ;;
+ *) build_noncanonical=${build_alias} ;;
+esac
+
+ case ${host_alias} in
+ "") host_noncanonical=${build_noncanonical} ;;
+ *) host_noncanonical=${host_alias} ;;
+esac
+
+
+
+
+# Determine the noncanonical target name, for directory use.
+ case ${target_alias} in
+ "") target_noncanonical=${host_noncanonical} ;;
+ *) target_noncanonical=${target_alias} ;;
+esac
+
+
+
+
+# Used for constructing correct paths for offload compilers.
+real_target_noncanonical=${target_noncanonical}
+accel_dir_suffix=
+
+# Determine the target- and build-specific subdirectories
+
+# post-stage1 host modules use a different CC_FOR_BUILD so, in order to
+# have matching libraries, they should use host libraries: Makefile.tpl
+# arranges to pass --with-build-libsubdir=$(HOST_SUBDIR).
+# However, they still use the build modules, because the corresponding
+# host modules (e.g. bison) are only built for the host when bootstrap
+# finishes. So:
+# - build_subdir is where we find build modules, and never changes.
+# - build_libsubdir is where we find build libraries, and can be overridden.
+
+# Prefix 'build-' so this never conflicts with target_subdir.
+build_subdir="build-${build_noncanonical}"
+
+# Check whether --with-build-libsubdir was given.
+if test "${with_build_libsubdir+set}" = set; then :
+ withval=$with_build_libsubdir; build_libsubdir="$withval"
+else
+ build_libsubdir="$build_subdir"
+fi
+
+# --srcdir=. covers the toplevel, while "test -d" covers the subdirectories
+if ( test $srcdir = . && test -d gcc ) \
+ || test -d $srcdir/../host-${host_noncanonical}; then
+ host_subdir="host-${host_noncanonical}"
+else
+ host_subdir=.
+fi
+# No prefix.
+target_subdir=${target_noncanonical}
+
+
+# Set program_transform_name
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+
+# Check for bogus environment variables.
+# Test if LIBRARY_PATH contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# LIBRARY_PATH contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking LIBRARY_PATH variable" >&5
+$as_echo_n "checking LIBRARY_PATH variable... " >&6; }
+case ${LIBRARY_PATH} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ library_path_setting="contains current directory"
+ ;;
+ *)
+ library_path_setting="ok"
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $library_path_setting" >&5
+$as_echo "$library_path_setting" >&6; }
+if test "$library_path_setting" != "ok"; then
+as_fn_error $? "
+*** LIBRARY_PATH shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again." "$LINENO" 5
+fi
+
+# Test if GCC_EXEC_PREFIX contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# GCC_EXEC_PREFIX contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking GCC_EXEC_PREFIX variable" >&5
+$as_echo_n "checking GCC_EXEC_PREFIX variable... " >&6; }
+case ${GCC_EXEC_PREFIX} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ gcc_exec_prefix_setting="contains current directory"
+ ;;
+ *)
+ gcc_exec_prefix_setting="ok"
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_exec_prefix_setting" >&5
+$as_echo "$gcc_exec_prefix_setting" >&6; }
+if test "$gcc_exec_prefix_setting" != "ok"; then
+as_fn_error $? "
+*** GCC_EXEC_PREFIX shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again." "$LINENO" 5
+fi
+
+# -----------
+# Directories
+# -----------
+
+# Specify the local prefix
+local_prefix=
+
+# Check whether --with-local-prefix was given.
+if test "${with_local_prefix+set}" = set; then :
+ withval=$with_local_prefix; case "${withval}" in
+yes) as_fn_error $? "bad value ${withval} given for local include directory prefix" "$LINENO" 5 ;;
+no) ;;
+*) local_prefix=$with_local_prefix ;;
+esac
+fi
+
+
+# Default local prefix if it is empty
+if test x$local_prefix = x; then
+ local_prefix=/usr/local
+fi
+
+
+# Check whether --with-native-system-header-dir was given.
+if test "${with_native_system_header_dir+set}" = set; then :
+ withval=$with_native_system_header_dir;
+ case ${with_native_system_header_dir} in
+ yes|no) as_fn_error $? "bad value ${withval} given for --with-native-system-header-dir" "$LINENO" 5 ;;
+ /* | [A-Za-z]:[\\/]*) ;;
+ *) as_fn_error $? "--with-native-system-header-dir argument ${withval} must be an absolute directory" "$LINENO" 5 ;;
+ esac
+ configured_native_system_header_dir="${withval}"
+
+else
+ configured_native_system_header_dir=
+fi
+
+
+
+# Check whether --with-build-sysroot was given.
+if test "${with_build_sysroot+set}" = set; then :
+ withval=$with_build_sysroot; if test x"$withval" != x ; then
+ SYSROOT_CFLAGS_FOR_TARGET="--sysroot=$withval"
+ fi
+else
+ SYSROOT_CFLAGS_FOR_TARGET=
+fi
+
+
+
+if test "x$prefix" = xNONE; then
+ test_prefix=/usr/local
+else
+ test_prefix=$prefix
+fi
+if test "x$exec_prefix" = xNONE; then
+ test_exec_prefix=$test_prefix
+else
+ test_exec_prefix=$exec_prefix
+fi
+
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+ withval=$with_sysroot;
+ case ${with_sysroot} in
+ /) ;;
+ */) with_sysroot=`echo $with_sysroot | sed 's,/$,,'` ;;
+ esac
+ case ${with_sysroot} in
+ yes) TARGET_SYSTEM_ROOT='${exec_prefix}/${target_noncanonical}/sys-root' ;;
+ *) TARGET_SYSTEM_ROOT=$with_sysroot ;;
+ esac
+
+ TARGET_SYSTEM_ROOT_DEFINE='-DTARGET_SYSTEM_ROOT=\"$(TARGET_SYSTEM_ROOT)\"'
+ CROSS_SYSTEM_HEADER_DIR='$(TARGET_SYSTEM_ROOT)$${sysroot_headers_suffix}$(NATIVE_SYSTEM_HEADER_DIR)'
+
+ case ${TARGET_SYSTEM_ROOT} in
+ "${test_prefix}"|"${test_prefix}/"*|\
+ "${test_exec_prefix}"|"${test_exec_prefix}/"*|\
+ '${prefix}'|'${prefix}/'*|\
+ '${exec_prefix}'|'${exec_prefix}/'*)
+ t="$TARGET_SYSTEM_ROOT_DEFINE -DTARGET_SYSTEM_ROOT_RELOCATABLE"
+ TARGET_SYSTEM_ROOT_DEFINE="$t"
+ ;;
+ esac
+
+else
+
+ TARGET_SYSTEM_ROOT=
+ TARGET_SYSTEM_ROOT_DEFINE=
+ CROSS_SYSTEM_HEADER_DIR='$(gcc_tooldir)/sys-include'
+
+fi
+
+
+
+
+
+# Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
+# passed in by the toplevel make and thus we'd get different behavior
+# depending on where we built the sources.
+gcc_gxx_include_dir=
+# Specify the g++ header file directory
+
+# Check whether --with-gxx-include-dir was given.
+if test "${with_gxx_include_dir+set}" = set; then :
+ withval=$with_gxx_include_dir; case "${withval}" in
+yes) as_fn_error $? "bad value ${withval} given for g++ include directory" "$LINENO" 5 ;;
+no) ;;
+*) gcc_gxx_include_dir=$with_gxx_include_dir ;;
+esac
+fi
+
+
+# If both --with-sysroot and --with-gxx-include-dir are passed, we interpolate
+# the former in the latter and, upon success, compute gcc_gxx_include_dir as
+# relative to the sysroot.
+gcc_gxx_include_dir_add_sysroot=0
+
+# This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_include_dir} = x; then
+ if test x${enable_version_specific_runtime_libs} = xyes; then
+ gcc_gxx_include_dir='${libsubdir}/include/c++'
+ else
+ libstdcxx_incdir='include/c++/$(version)'
+ if test x$host != x$target; then
+ libstdcxx_incdir="$target_alias/$libstdcxx_incdir"
+ fi
+ gcc_gxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libstdcxx_incdir"
+ fi
+elif test "${with_sysroot+set}" = set; then
+ gcc_gxx_without_sysroot=`expr "${gcc_gxx_include_dir}" : "${with_sysroot}"'\(.*\)'`
+ if test "${gcc_gxx_without_sysroot}"; then
+ gcc_gxx_include_dir="${gcc_gxx_without_sysroot}"
+ gcc_gxx_include_dir_add_sysroot=1
+ fi
+fi
+
+# Configuration for an alternate set of C++ headers.
+gcc_gxx_libcxx_include_dir=
+# Specify the alternate g++ header file directory
+
+# Check whether --with-gxx-libcxx-include-dir was given.
+if test "${with_gxx_libcxx_include_dir+set}" = set; then :
+ withval=$with_gxx_libcxx_include_dir; case "${withval}" in
+yes) as_fn_error $? "bad value ${withval} given for libc++ include directory" "$LINENO" 5 ;;
+no) ;;
+*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac
+fi
+
+
+# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
+# check to see if the latter starts with the former and, upon success, compute
+# gcc_gxx_libcxx_include_dir as relative to the sysroot.
+gcc_gxx_libcxx_include_dir_add_sysroot=0
+
+if test x${gcc_gxx_libcxx_include_dir} != x; then
+
+$as_echo "#define ENABLE_STDLIB_OPTION 1" >>confdefs.h
+
+else
+ $as_echo "#define ENABLE_STDLIB_OPTION 0" >>confdefs.h
+
+fi
+# ??? This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_libcxx_include_dir} = x; then
+ if test x${enable_version_specific_runtime_libs} = xyes; then
+ gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'
+ else
+ libcxx_incdir='libc++_include/c++/$(version)/v1'
+ if test x$host != x$target; then
+ libcxx_incdir="$target_alias/$libcxx_incdir"
+ fi
+ gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir"
+ fi
+elif test "${with_sysroot+set}" = set; then
+ gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" : "${with_sysroot}"'\(.*\)'`
+ if test "${gcc_gxx_libcxx_without_sysroot}"; then
+ gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"
+ gcc_gxx_libcxx_include_dir_add_sysroot=1
+ fi
+fi
+
+
+# Check whether --with-cpp_install_dir was given.
+if test "${with_cpp_install_dir+set}" = set; then :
+ withval=$with_cpp_install_dir; if test x$withval = xyes; then
+ as_fn_error $? "option --with-cpp-install-dir requires an argument" "$LINENO" 5
+elif test x$withval != xno; then
+ cpp_install_dir=$withval
+fi
+fi
+
+
+# We would like to our source tree to be readonly. However when releases or
+# pre-releases are generated, the flex/bison generated files as well as the
+# various formats of manuals need to be included along with the rest of the
+# sources. Therefore we have --enable-generated-files-in-srcdir to do
+# just that.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to place generated files in the source directory" >&5
+$as_echo_n "checking whether to place generated files in the source directory... " >&6; }
+ # Check whether --enable-generated-files-in-srcdir was given.
+if test "${enable_generated_files_in_srcdir+set}" = set; then :
+ enableval=$enable_generated_files_in_srcdir; generated_files_in_srcdir=$enableval
+else
+ generated_files_in_srcdir=no
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $generated_files_in_srcdir" >&5
+$as_echo "$generated_files_in_srcdir" >&6; }
+
+if test "$generated_files_in_srcdir" = "yes"; then
+ GENINSRC=''
+else
+ GENINSRC='#'
+fi
+
+
+# -------------------
+# Find default linker
+# -------------------
+
+# With GNU ld
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; gnu_ld_flag="$with_gnu_ld"
+else
+ gnu_ld_flag=no
+fi
+
+
+case $target in
+ *darwin*)
+ ld64_flag=yes # Darwin can only use a ld64-compatible linker.
+ dsymutil_flag=yes # Darwin uses dsymutil to link debug.
+ ;;
+ *)
+ ld64_flag=no
+ dsymutil_flag=no
+ ;;
+esac
+
+# With pre-defined ld
+
+# Check whether --with-ld was given.
+if test "${with_ld+set}" = set; then :
+ withval=$with_ld; DEFAULT_LINKER="$with_ld"
+fi
+
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_LINKER"; then
+ as_fn_error $? "cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER" "$LINENO" 5
+ elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gnu_ld_flag=yes
+ elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep ld64- > /dev/null; then
+ ld64_flag=yes
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_LINKER "$DEFAULT_LINKER"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a default linker was specified" >&5
+$as_echo_n "checking whether a default linker was specified... " >&6; }
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test x"$gnu_ld_flag" = x"no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($DEFAULT_LINKER)" >&5
+$as_echo "yes ($DEFAULT_LINKER)" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($DEFAULT_LINKER - GNU ld)" >&5
+$as_echo "yes ($DEFAULT_LINKER - GNU ld)" >&6; }
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+# With demangler in GNU ld
+
+# Check whether --with-demangler-in-ld was given.
+if test "${with_demangler_in_ld+set}" = set; then :
+ withval=$with_demangler_in_ld; demangler_in_ld="$with_demangler_in_ld"
+else
+ demangler_in_ld=yes
+fi
+
+
+# Allow the user to specify a dsymutil executable (used on Darwin only, so far)
+
+# Check whether --with-dsymutil was given.
+if test "${with_dsymutil+set}" = set; then :
+ withval=$with_dsymutil; DEFAULT_DSYMUTIL="$with_dsymutil"
+fi
+
+
+dsymutil_vers=
+if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then
+ if test ! -x "$DEFAULT_DSYMUTIL"; then
+ as_fn_error $? "cannot execute: $DEFAULT_DSYMUTIL: check --with-dsymutil or env. var. DEFAULT_DSYMUTIL" "$LINENO" 5
+ else
+ if dsymutil_vers=`$DEFAULT_DSYMUTIL -v /dev/null 2>&1`; then
+ dsymutil_flag=yes
+ fi
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_DSYMUTIL "$DEFAULT_DSYMUTIL"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a default dsymutil was specified" >&5
+$as_echo_n "checking whether a default dsymutil was specified... " >&6; }
+if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($DEFAULT_DSYMUTIL)" >&5
+$as_echo "yes ($DEFAULT_DSYMUTIL)" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+# ----------------------
+# Find default assembler
+# ----------------------
+
+# With GNU as
+
+# Check whether --with-gnu-as was given.
+if test "${with_gnu_as+set}" = set; then :
+ withval=$with_gnu_as; gas_flag="$with_gnu_as"
+else
+ gas_flag=no
+fi
+
+
+
+# Check whether --with-as was given.
+if test "${with_as+set}" = set; then :
+ withval=$with_as; DEFAULT_ASSEMBLER="$with_as"
+fi
+
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_ASSEMBLER"; then
+ as_fn_error $? "cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER" "$LINENO" 5
+ elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gas_flag=yes
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_ASSEMBLER "$DEFAULT_ASSEMBLER"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a default assembler was specified" >&5
+$as_echo_n "checking whether a default assembler was specified... " >&6; }
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test x"$gas_flag" = x"no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($DEFAULT_ASSEMBLER)" >&5
+$as_echo "yes ($DEFAULT_ASSEMBLER)" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($DEFAULT_ASSEMBLER - GNU as)" >&5
+$as_echo "yes ($DEFAULT_ASSEMBLER - GNU as)" >&6; }
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+# ---------------
+# Find C compiler
+# ---------------
+
+# If a non-executable a.out is present (e.g. created by GNU as above even if
+# invoked with -v only), the IRIX 6 native ld just overwrites the existing
+# file, even when creating an executable, so an execution test fails.
+# Remove possible default executable files to avoid this.
+#
+# FIXME: This really belongs into AC_PROG_CC and can be removed once
+# Autoconf includes it.
+rm -f a.out a.exe b.out
+
+# Find the native compiler
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+# ACX_PROG_GNAT([-I"$srcdir"/ada/libgnat])
+# ACX_PROG_GDC([-I"$srcdir"/d])
+
+# Do configure tests with the C++ compiler, since that's what we build with.
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+# Remove the -O2: for historical reasons, unless bootstrapping we prefer
+# optimizations to be activated explicitly by the toplevel.
+case "$CC" in
+ */prev-gcc/xgcc*) ;;
+ *) CFLAGS=`echo "$CFLAGS " | sed -e "s/-Ofast[ ]//" -e "s/-O[gs][ ]//" -e "s/-O[0-9]*[ ]//" `
+ CXXFLAGS=`echo "$CXXFLAGS " | sed -e "s/-Ofast[ ]//" -e "s/-O[gs][ ]//" -e "s/-O[0-9]*[ ]//" ` ;;
+esac
+
+
+
+
+# Determine PICFLAG for target gnatlib.
+
+
+
+
+case "${target}" in
+ # PIC is the default on some targets or must not be used.
+ *-*-darwin*)
+ # For darwin, common symbols are not allowed in MH_DYLIB files
+ case "${CFLAGS}" in
+ # If we are using a compiler supporting mdynamic-no-pic
+ # and the option has been tested as safe to add, then cancel
+ # it here, since the code generated is incompatible with shared
+ # libs.
+ *-mdynamic-no-pic*) PICFLAG_FOR_TARGET='-fno-common -mno-dynamic-no-pic' ;;
+ *) PICFLAG_FOR_TARGET=-fno-common ;;
+ esac
+ ;;
+ alpha*-dec-osf5*)
+ # PIC is the default.
+ ;;
+ hppa*64*-*-hpux*)
+ # PIC is the default for 64-bit PA HP-UX.
+ ;;
+ i[34567]86-*-cygwin* | x86_64-*-cygwin*)
+ ;;
+ i[34567]86-*-mingw* | x86_64-*-mingw*)
+ ;;
+ i[34567]86-*-interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ i[34567]86-*-nto-qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ PICFLAG_FOR_TARGET='-fPIC -shared'
+ ;;
+ i[34567]86-pc-msdosdjgpp*)
+ # DJGPP does not support shared libraries at all.
+ ;;
+ ia64*-*-hpux*)
+ # On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ PICFLAG_FOR_TARGET=-fPIC
+ ;;
+ loongarch*-*-*)
+ PICFLAG_FOR_TARGET=-fpic
+ ;;
+ mips-sgi-irix6*)
+ # PIC is the default.
+ ;;
+ rs6000-ibm-aix* | powerpc-ibm-aix*)
+ # All AIX code is PIC.
+ ;;
+
+ # Some targets support both -fPIC and -fpic, but prefer the latter.
+ # FIXME: Why?
+ i[34567]86-*-* | x86_64-*-*)
+ PICFLAG_FOR_TARGET=-fpic
+ ;;
+ # FIXME: Override -fPIC default in libgcc only?
+ sh-*-linux* | sh[2346lbe]*-*-linux*)
+ PICFLAG_FOR_TARGET=-fpic
+ ;;
+ # FIXME: Simplify to sh*-*-netbsd*?
+ sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
+ sh64-*-netbsd* | sh64l*-*-netbsd*)
+ PICFLAG_FOR_TARGET=-fpic
+ ;;
+ # Default to -fPIC unless specified otherwise.
+ *)
+ PICFLAG_FOR_TARGET=-fPIC
+ ;;
+esac
+
+# If the user explicitly uses -fpic/-fPIC, keep that.
+case "${CFLAGS_FOR_TARGET}" in
+ *-fpic*)
+ PICFLAG_FOR_TARGET=-fpic
+ ;;
+ *-fPIC*)
+ PICFLAG_FOR_TARGET=-fPIC
+ ;;
+esac
+
+
+
+# -------------------------
+# Check C compiler features
+# -------------------------
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+ if ${ac_cv_prog_CXXCPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+ ac_fn_cxx_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+ MINIX=yes
+else
+ MINIX=
+fi
+
+
+ if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_safe_to_define___extensions__=yes
+else
+ ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+ test $ac_cv_safe_to_define___extensions__ = yes &&
+ $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+ $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if ${ac_cv_c_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_c_inline=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+case $ac_cv_c_inline in
+ inline | yes) ;;
+ *)
+ case $ac_cv_c_inline in
+ no) ac_val=;;
+ *) ac_val=$ac_cv_c_inline;;
+ esac
+ cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+ ;;
+esac
+
+
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ if ac_fn_cxx_try_compile "$LINENO"; then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ fi
+
+
+fi
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of ino_t" >&5
+$as_echo_n "checking size of ino_t... " >&6; }
+if ${ac_cv_sizeof_ino_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (ino_t))" "ac_cv_sizeof_ino_t" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_ino_t" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (ino_t)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_ino_t=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_ino_t" >&5
+$as_echo "$ac_cv_sizeof_ino_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INO_T $ac_cv_sizeof_ino_t
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of dev_t" >&5
+$as_echo_n "checking size of dev_t... " >&6; }
+if ${ac_cv_sizeof_dev_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (dev_t))" "ac_cv_sizeof_dev_t" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_dev_t" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (dev_t)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_dev_t=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_dev_t" >&5
+$as_echo "$ac_cv_sizeof_dev_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_DEV_T $ac_cv_sizeof_dev_t
+_ACEOF
+
+
+
+# Select the right stat being able to handle 64bit inodes, if needed.
+if test "$enable_largefile" != no; then
+ case "$host, $build" in
+ *-*-aix*,*|*,*-*-aix*)
+ if test "$ac_cv_sizeof_ino_t" == "4" -a "$ac_cv_sizeof_dev_t" == 4; then
+
+$as_echo "#define HOST_STAT_FOR_64BIT_INODES stat64x" >>confdefs.h
+
+ fi;;
+ esac
+fi
+
+
+# sizeof(char) is 1 by definition.
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+$as_echo_n "checking size of void *... " >&6; }
+if ${ac_cv_sizeof_void_p+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_void_p" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (void *)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_void_p=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+$as_echo "$ac_cv_sizeof_void_p" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5
+$as_echo_n "checking size of short... " >&6; }
+if ${ac_cv_sizeof_short+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_short" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (short)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_short=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5
+$as_echo "$ac_cv_sizeof_short" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5
+$as_echo_n "checking size of int... " >&6; }
+if ${ac_cv_sizeof_int+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_int" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (int)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_int=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5
+$as_echo "$ac_cv_sizeof_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5
+$as_echo_n "checking size of long... " >&6; }
+if ${ac_cv_sizeof_long+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_long" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_long=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5
+$as_echo "$ac_cv_sizeof_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+ac_fn_cxx_check_type "$LINENO" "long long" "ac_cv_type_long_long" "$ac_includes_default"
+if test "x$ac_cv_type_long_long" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LONG_LONG 1
+_ACEOF
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5
+$as_echo_n "checking size of long long... " >&6; }
+if ${ac_cv_sizeof_long_long+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_cxx_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$ac_includes_default"; then :
+
+else
+ if test "$ac_cv_type_long_long" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_long_long=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5
+$as_echo "$ac_cv_sizeof_long_long" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
+fi
+
+ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
+case $ac_cv_c_int8_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int8_t $ac_cv_c_int8_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t"
+case $ac_cv_c_int16_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int16_t $ac_cv_c_int16_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t"
+case $ac_cv_c_int32_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int32_t $ac_cv_c_int32_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
+case $ac_cv_c_int64_t in #(
+ no|yes) ;; #(
+ *)
+
+cat >>confdefs.h <<_ACEOF
+#define int64_t $ac_cv_c_int64_t
+_ACEOF
+;;
+esac
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unsigned long long int" >&5
+$as_echo_n "checking for unsigned long long int... " >&6; }
+if ${ac_cv_type_unsigned_long_long_int+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_type_unsigned_long_long_int=yes
+ if test "x${ac_cv_prog_cc_c99-no}" = xno; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ /* For now, do not test the preprocessor; as of 2007 there are too many
+ implementations with broken preprocessors. Perhaps this can
+ be revisited in 2012. In the meantime, code should not expect
+ #if to work with literals wider than 32 bits. */
+ /* Test literals. */
+ long long int ll = 9223372036854775807ll;
+ long long int nll = -9223372036854775807LL;
+ unsigned long long int ull = 18446744073709551615ULL;
+ /* Test constant expressions. */
+ typedef int a[((-9223372036854775807LL < 0 && 0 < 9223372036854775807ll)
+ ? 1 : -1)];
+ typedef int b[(18446744073709551615ULL <= (unsigned long long int) -1
+ ? 1 : -1)];
+ int i = 63;
+int
+main ()
+{
+/* Test availability of runtime routines for shift and division. */
+ long long int llmax = 9223372036854775807ll;
+ unsigned long long int ullmax = 18446744073709551615ull;
+ return ((ll << 63) | (ll >> 63) | (ll < i) | (ll > i)
+ | (llmax / ll) | (llmax % ll)
+ | (ull << 63) | (ull >> 63) | (ull << i) | (ull >> i)
+ | (ullmax / ull) | (ullmax % ull));
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+else
+ ac_cv_type_unsigned_long_long_int=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_unsigned_long_long_int" >&5
+$as_echo "$ac_cv_type_unsigned_long_long_int" >&6; }
+ if test $ac_cv_type_unsigned_long_long_int = yes; then
+
+$as_echo "#define HAVE_UNSIGNED_LONG_LONG_INT 1" >>confdefs.h
+
+ fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long long int" >&5
+$as_echo_n "checking for long long int... " >&6; }
+if ${ac_cv_type_long_long_int+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_type_long_long_int=yes
+ if test "x${ac_cv_prog_cc_c99-no}" = xno; then
+ ac_cv_type_long_long_int=$ac_cv_type_unsigned_long_long_int
+ if test $ac_cv_type_long_long_int = yes; then
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ #ifndef LLONG_MAX
+ # define HALF \
+ (1LL << (sizeof (long long int) * CHAR_BIT - 2))
+ # define LLONG_MAX (HALF - 1 + HALF)
+ #endif
+int
+main ()
+{
+long long int n = 1;
+ int i;
+ for (i = 0; ; i++)
+ {
+ long long int m = n << i;
+ if (m >> i != n)
+ return 1;
+ if (LLONG_MAX / 2 < m)
+ break;
+ }
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+
+else
+ ac_cv_type_long_long_int=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_long_int" >&5
+$as_echo "$ac_cv_type_long_long_int" >&6; }
+ if test $ac_cv_type_long_long_int = yes; then
+
+$as_echo "#define HAVE_LONG_LONG_INT 1" >>confdefs.h
+
+ fi
+
+
+
+ ac_fn_cxx_check_type "$LINENO" "intmax_t" "ac_cv_type_intmax_t" "$ac_includes_default"
+if test "x$ac_cv_type_intmax_t" = xyes; then :
+
+$as_echo "#define HAVE_INTMAX_T 1" >>confdefs.h
+
+else
+ test $ac_cv_type_long_long_int = yes \
+ && ac_type='long long int' \
+ || ac_type='long int'
+
+cat >>confdefs.h <<_ACEOF
+#define intmax_t $ac_type
+_ACEOF
+
+fi
+
+
+
+ ac_fn_cxx_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_intptr_t" = xyes; then :
+
+$as_echo "#define HAVE_INTPTR_T 1" >>confdefs.h
+
+else
+ for ac_type in 'int' 'long int' 'long long int'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define intptr_t $ac_type
+_ACEOF
+
+ ac_type=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test -z "$ac_type" && break
+ done
+fi
+
+
+ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
+case $ac_cv_c_uint8_t in #(
+ no|yes) ;; #(
+ *)
+
+$as_echo "#define _UINT8_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint8_t $ac_cv_c_uint8_t
+_ACEOF
+;;
+ esac
+
+ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
+case $ac_cv_c_uint16_t in #(
+ no|yes) ;; #(
+ *)
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint16_t $ac_cv_c_uint16_t
+_ACEOF
+;;
+ esac
+
+ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
+case $ac_cv_c_uint32_t in #(
+ no|yes) ;; #(
+ *)
+
+$as_echo "#define _UINT32_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+ esac
+
+ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
+case $ac_cv_c_uint64_t in #(
+ no|yes) ;; #(
+ *)
+
+$as_echo "#define _UINT64_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint64_t $ac_cv_c_uint64_t
+_ACEOF
+;;
+ esac
+
+
+
+ ac_fn_cxx_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintmax_t" = xyes; then :
+
+$as_echo "#define HAVE_UINTMAX_T 1" >>confdefs.h
+
+else
+ test $ac_cv_type_unsigned_long_long_int = yes \
+ && ac_type='unsigned long long int' \
+ || ac_type='unsigned long int'
+
+cat >>confdefs.h <<_ACEOF
+#define uintmax_t $ac_type
+_ACEOF
+
+fi
+
+
+
+ ac_fn_cxx_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintptr_t" = xyes; then :
+
+$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
+
+else
+ for ac_type in 'unsigned int' 'unsigned long int' \
+ 'unsigned long long int'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define uintptr_t $ac_type
+_ACEOF
+
+ ac_type=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test -z "$ac_type" && break
+ done
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test x"$ac_cv_c_uint64_t" = x"no" -o x"$ac_cv_c_int64_t" = x"no"; then
+ as_fn_error $? "uint64_t or int64_t not found" "$LINENO" 5
+fi
+
+# check what underlying integer type int64_t uses
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for int64_t underlying type" >&5
+$as_echo_n "checking for int64_t underlying type... " >&6; }
+if ${ac_cv_int64_t_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+template <typename T> struct X { };
+template <>
+struct X<long> { typedef long t; };
+
+int
+main ()
+{
+X<int64_t>::t x;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_int64_t_type=long
+else
+ ac_cv_int64_t_type="long long"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_int64_t_type" >&5
+$as_echo "$ac_cv_int64_t_type" >&6; }
+if test "$ac_cv_int64_t_type" = "long"; then
+
+$as_echo "#define INT64_T_IS_LONG 1" >>confdefs.h
+
+else
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+template <typename T> struct X { };
+template <>
+struct X<long long> { typedef long long t; };
+
+int
+main ()
+{
+X<int64_t>::t x;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ as_fn_error $? "error verifying int64_t uses long long" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for std::swap in <utility>" >&5
+$as_echo_n "checking for std::swap in <utility>... " >&6; }
+if ${ac_cv_std_swap_in_utility+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <utility>
+
+int
+main ()
+{
+int a, b; std::swap(a,b);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_std_swap_in_utility=yes
+else
+ ac_cv_std_swap_in_utility=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_std_swap_in_utility" >&5
+$as_echo "$ac_cv_std_swap_in_utility" >&6; }
+if test $ac_cv_std_swap_in_utility = yes; then
+
+$as_echo "#define HAVE_SWAP_IN_UTILITY 1" >>confdefs.h
+
+fi
+
+# Check whether compiler is affected by placement new aliasing bug (PR 29286).
+# If the host compiler is affected by the bug, and we build with optimization
+# enabled (which happens e.g. when cross-compiling), the pool allocator may
+# get miscompiled. Use -fno-strict-aliasing to work around this problem.
+# Since there is no reliable feature check for the presence of this bug,
+# we simply use a GCC version number check. (This should never trigger for
+# stages 2 or 3 of a native bootstrap.)
+aliasing_flags=
+if test "$GCC" = yes; then
+ saved_CXXFLAGS="$CXXFLAGS"
+
+ # The following test compilation will succeed if and only if $CXX accepts
+ # -fno-strict-aliasing *and* is older than GCC 4.3.
+ CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX is affected by placement new aliasing bug" >&5
+$as_echo_n "checking whether $CXX is affected by placement new aliasing bug... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+#error compiler not affected by placement new aliasing bug
+#endif
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }; aliasing_flags='-fno-strict-aliasing'
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ CXXFLAGS="$saved_CXXFLAGS"
+fi
+
+
+
+
+# ---------------------
+# Warnings and checking
+# ---------------------
+
+# Check $CC warning features (if it's GCC).
+# We want to use -pedantic, but we don't want warnings about
+# * 'long long'
+# * variadic macros
+# * overlong strings
+# * C++11 narrowing conversions in { }
+# So, we only use -pedantic if we can disable those warnings.
+
+# In stage 1, disable -Wformat warnings from old GCCs about new % codes
+# Check whether --enable-build-format-warnings was given.
+if test "${enable_build_format_warnings+set}" = set; then :
+ enableval=$enable_build_format_warnings;
+else
+ enable_build_format_warnings=yes
+fi
+
+if test $enable_build_format_warnings = no; then :
+ wf_opt=-Wno-format
+else
+ wf_opt=
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+loose_warn=
+save_CXXFLAGS="$CXXFLAGS"
+for real_option in -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual $wf_opt; do
+ # Do the check with the no- prefix removed since gcc silently
+ # accepts any -Wno-* option on purpose
+ case $real_option in
+ -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+ *) option=$real_option ;;
+ esac
+ as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports $option" >&5
+$as_echo_n "checking whether $CXX supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ CXXFLAGS="$option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$as_acx_Woption=yes"
+else
+ eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+ loose_warn="$loose_warn${loose_warn:+ }$real_option"
+fi
+ done
+CXXFLAGS="$save_CXXFLAGS"
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+c_loose_warn=
+save_CFLAGS="$CFLAGS"
+for real_option in -Wstrict-prototypes -Wmissing-prototypes ; do
+ # Do the check with the no- prefix removed since gcc silently
+ # accepts any -Wno-* option on purpose
+ case $real_option in
+ -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+ *) option=$real_option ;;
+ esac
+ as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ CFLAGS="$option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_acx_Woption=yes"
+else
+ eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+ c_loose_warn="$c_loose_warn${c_loose_warn:+ }$real_option"
+fi
+ done
+CFLAGS="$save_CFLAGS"
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+strict_warn=
+save_CXXFLAGS="$CXXFLAGS"
+for real_option in -Wmissing-format-attribute -Woverloaded-virtual; do
+ # Do the check with the no- prefix removed since gcc silently
+ # accepts any -Wno-* option on purpose
+ case $real_option in
+ -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+ *) option=$real_option ;;
+ esac
+ as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports $option" >&5
+$as_echo_n "checking whether $CXX supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ CXXFLAGS="$option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$as_acx_Woption=yes"
+else
+ eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+ strict_warn="$strict_warn${strict_warn:+ }$real_option"
+fi
+ done
+CXXFLAGS="$save_CXXFLAGS"
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+c_strict_warn=
+save_CFLAGS="$CFLAGS"
+for real_option in -Wold-style-definition -Wc++-compat; do
+ # Do the check with the no- prefix removed since gcc silently
+ # accepts any -Wno-* option on purpose
+ case $real_option in
+ -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+ *) option=$real_option ;;
+ esac
+ as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ CFLAGS="$option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_acx_Woption=yes"
+else
+ eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+ c_strict_warn="$c_strict_warn${c_strict_warn:+ }$real_option"
+fi
+ done
+CFLAGS="$save_CFLAGS"
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+# Do the check with the no- prefix removed from the warning options
+# since gcc silently accepts any -Wno-* option on purpose
+if test "$GXX" = yes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports -pedantic -Wlong-long -Wvariadic-macros -Woverlength-strings" >&5
+$as_echo_n "checking whether $CXX supports -pedantic -Wlong-long -Wvariadic-macros -Woverlength-strings... " >&6; }
+if ${acx_cv_prog_cc_pedantic__Wlong_long__Wvariadic_macros__Woverlength_strings+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="-pedantic -Wlong-long -Wvariadic-macros -Woverlength-strings"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ acx_cv_prog_cc_pedantic__Wlong_long__Wvariadic_macros__Woverlength_strings=yes
+else
+ acx_cv_prog_cc_pedantic__Wlong_long__Wvariadic_macros__Woverlength_strings=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CXXFLAGS="$save_CXXFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_prog_cc_pedantic__Wlong_long__Wvariadic_macros__Woverlength_strings" >&5
+$as_echo "$acx_cv_prog_cc_pedantic__Wlong_long__Wvariadic_macros__Woverlength_strings" >&6; }
+if test $acx_cv_prog_cc_pedantic__Wlong_long__Wvariadic_macros__Woverlength_strings = yes; then :
+ strict_warn="$strict_warn${strict_warn:+ }-pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings"
+fi
+
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+# Check whether --enable-werror-always was given.
+if test "${enable_werror_always+set}" = set; then :
+ enableval=$enable_werror_always;
+else
+ enable_werror_always=no
+fi
+
+if test $enable_werror_always = yes; then :
+ strict_warn="$strict_warn${strict_warn:+ }-Werror"
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+# The above macros do nothing if the compiler is not GCC. However, the
+# Makefile has more goo to add other flags, so these variables are used
+# to enable warnings only for GCC.
+warn_cflags=
+warn_cxxflags=
+if test "x$GCC" = "xyes"; then
+ warn_cflags='$(GCC_WARN_CFLAGS)'
+ warn_cxxflags='$(GCC_WARN_CXXFLAGS)'
+fi
+
+
+
+# Disable exceptions and RTTI if building with g++
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+noexception_flags=
+save_CFLAGS="$CFLAGS"
+for real_option in -fno-exceptions -fno-rtti -fasynchronous-unwind-tables; do
+ # Do the check with the no- prefix removed since gcc silently
+ # accepts any -Wno-* option on purpose
+ case $real_option in
+ -Wno-*) option=-W`expr x$real_option : 'x-Wno-\(.*\)'` ;;
+ *) option=$real_option ;;
+ esac
+ as_acx_Woption=`$as_echo "acx_cv_prog_cc_warning_$option" | $as_tr_sh`
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports $option" >&5
+$as_echo_n "checking whether $CC supports $option... " >&6; }
+if eval \${$as_acx_Woption+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ CFLAGS="$option"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_acx_Woption=yes"
+else
+ eval "$as_acx_Woption=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+eval ac_res=\$$as_acx_Woption
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if test `eval 'as_val=${'$as_acx_Woption'};$as_echo "$as_val"'` = yes; then :
+ noexception_flags="$noexception_flags${noexception_flags:+ }$real_option"
+fi
+ done
+CFLAGS="$save_CFLAGS"
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+# Enable expensive internal checks
+is_release=
+if test x"`cat $srcdir/DEV-PHASE`" != xexperimental; then
+ is_release=yes
+fi
+
+# Check whether --enable-checking was given.
+if test "${enable_checking+set}" = set; then :
+ enableval=$enable_checking; ac_checking_flags="${enableval}"
+else
+
+# Determine the default checks.
+if test x$is_release = x ; then
+ ac_checking_flags=yes,extra
+else
+ ac_checking_flags=release
+fi
+fi
+
+IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
+for check in release $ac_checking_flags
+do
+ case $check in
+ # these set all the flags to specific states
+ yes) ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking= ;
+ ac_fold_checking= ; ac_gc_checking=1 ; ac_extra_checking= ;
+ ac_gc_always_collect= ; ac_gimple_checking=1 ; ac_rtl_checking= ;
+ ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
+ ac_tree_checking=1 ; ac_valgrind_checking= ;
+ ac_types_checking=1 ;;
+ no|none) ac_assert_checking= ; ac_checking= ; ac_df_checking= ;
+ ac_fold_checking= ; ac_gc_checking= ; ac_extra_checking= ;
+ ac_gc_always_collect= ; ac_gimple_checking= ; ac_rtl_checking= ;
+ ac_rtlflag_checking= ; ac_runtime_checking= ;
+ ac_tree_checking= ; ac_valgrind_checking= ;
+ ac_types_checking= ;;
+ all) ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking=1 ;
+ ac_fold_checking=1 ; ac_gc_checking=1 ; ac_extra_checking=1 ;
+ ac_gc_always_collect=1 ; ac_gimple_checking=1 ; ac_rtl_checking=1 ;
+ ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
+ ac_tree_checking=1 ; ac_valgrind_checking= ;
+ ac_types_checking=1 ;;
+ release) ac_assert_checking=1 ; ac_checking= ; ac_df_checking= ;
+ ac_fold_checking= ; ac_gc_checking= ; ac_extra_checking= ;
+ ac_gc_always_collect= ; ac_gimple_checking= ; ac_rtl_checking= ;
+ ac_rtlflag_checking= ; ac_runtime_checking=1 ;
+ ac_tree_checking= ; ac_valgrind_checking= ;
+ ac_types_checking= ;;
+ # these enable particular checks
+ assert) ac_assert_checking=1 ;;
+ df) ac_df_checking=1 ;;
+ extra) ac_extra_checking=1 ;;
+ fold) ac_fold_checking=1 ;;
+ gc) ac_gc_checking=1 ;;
+ gcac) ac_gc_always_collect=1 ;;
+ gimple) ac_gimple_checking=1 ;;
+ misc) ac_checking=1 ;;
+ rtl) ac_rtl_checking=1 ;;
+ rtlflag) ac_rtlflag_checking=1 ;;
+ runtime) ac_runtime_checking=1 ;;
+ tree) ac_tree_checking=1 ;;
+ types) ac_types_checking=1 ;;
+ valgrind) ac_valgrind_checking=1 ;;
+ *) as_fn_error $? "unknown check category $check" "$LINENO" 5 ;;
+ esac
+done
+IFS="$ac_save_IFS"
+
+nocommon_flag=""
+if test x$ac_checking != x ; then
+
+$as_echo "#define CHECKING_P 1" >>confdefs.h
+
+ nocommon_flag=-fno-common
+else
+ $as_echo "#define CHECKING_P 0" >>confdefs.h
+
+fi
+
+if test x$ac_extra_checking != x ; then
+
+$as_echo "#define ENABLE_EXTRA_CHECKING 1" >>confdefs.h
+
+else
+ $as_echo "#define ENABLE_EXTRA_CHECKING 0" >>confdefs.h
+
+fi
+if test x$ac_df_checking != x ; then
+
+$as_echo "#define ENABLE_DF_CHECKING 1" >>confdefs.h
+
+fi
+if test x$ac_assert_checking != x ; then
+
+$as_echo "#define ENABLE_ASSERT_CHECKING 1" >>confdefs.h
+
+fi
+if test x$ac_gimple_checking != x ; then
+
+$as_echo "#define ENABLE_GIMPLE_CHECKING 1" >>confdefs.h
+
+fi
+
+if test x$ac_runtime_checking != x ; then
+
+$as_echo "#define ENABLE_RUNTIME_CHECKING 1" >>confdefs.h
+
+fi
+if test x$ac_tree_checking != x ; then
+
+$as_echo "#define ENABLE_TREE_CHECKING 1" >>confdefs.h
+
+ TREECHECKING=yes
+fi
+if test x$ac_types_checking != x ; then
+
+$as_echo "#define ENABLE_TYPES_CHECKING 1" >>confdefs.h
+
+fi
+
+if test x$ac_rtl_checking != x ; then
+
+$as_echo "#define ENABLE_RTL_CHECKING 1" >>confdefs.h
+
+fi
+if test x$ac_rtlflag_checking != x ; then
+
+$as_echo "#define ENABLE_RTL_FLAG_CHECKING 1" >>confdefs.h
+
+fi
+if test x$ac_gc_checking != x ; then
+
+$as_echo "#define ENABLE_GC_CHECKING 1" >>confdefs.h
+
+fi
+if test x$ac_gc_always_collect != x ; then
+
+$as_echo "#define ENABLE_GC_ALWAYS_COLLECT 1" >>confdefs.h
+
+fi
+if test x$ac_fold_checking != x ; then
+
+$as_echo "#define ENABLE_FOLD_CHECKING 1" >>confdefs.h
+
+fi
+valgrind_path_defines=
+valgrind_command=
+
+ac_fn_cxx_check_header_mongrel "$LINENO" "valgrind.h" "ac_cv_header_valgrind_h" "$ac_includes_default"
+if test "x$ac_cv_header_valgrind_h" = xyes; then :
+ have_valgrind_h=yes
+else
+ have_valgrind_h=no
+fi
+
+
+
+# It is certainly possible that there's valgrind but no valgrind.h.
+# GCC relies on making annotations so we must have both.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <valgrind/memcheck.h>" >&5
+$as_echo_n "checking for VALGRIND_DISCARD in <valgrind/memcheck.h>... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <valgrind/memcheck.h>
+#ifndef VALGRIND_DISCARD
+#error VALGRIND_DISCARD not defined
+#endif
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ gcc_cv_header_valgrind_memcheck_h=yes
+else
+ gcc_cv_header_valgrind_memcheck_h=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_valgrind_memcheck_h" >&5
+$as_echo "$gcc_cv_header_valgrind_memcheck_h" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for VALGRIND_DISCARD in <memcheck.h>" >&5
+$as_echo_n "checking for VALGRIND_DISCARD in <memcheck.h>... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <memcheck.h>
+#ifndef VALGRIND_DISCARD
+#error VALGRIND_DISCARD not defined
+#endif
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ gcc_cv_header_memcheck_h=yes
+else
+ gcc_cv_header_memcheck_h=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_memcheck_h" >&5
+$as_echo "$gcc_cv_header_memcheck_h" >&6; }
+if test $gcc_cv_header_valgrind_memcheck_h = yes; then
+
+$as_echo "#define HAVE_VALGRIND_MEMCHECK_H 1" >>confdefs.h
+
+fi
+if test $gcc_cv_header_memcheck_h = yes; then
+
+$as_echo "#define HAVE_MEMCHECK_H 1" >>confdefs.h
+
+fi
+
+if test x$ac_valgrind_checking != x ; then
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Find out how to test for executable files. Don't use a zero-byte file,
+# as systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+ ac_executable_p="test -x"
+else
+ ac_executable_p="test -f"
+fi
+rm -f conf$$.file
+
+# Extract the first word of "valgrind", so it can be a program name with args.
+set dummy valgrind; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_valgrind_path+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case "$valgrind_path" in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_valgrind_path="$valgrind_path" # Let the user override the test with a path.
+ ;;
+ *)
+ ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$ac_save_IFS"
+ test -z "$ac_dir" && ac_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
+ if $ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1; then
+ ac_cv_path_valgrind_path="$ac_dir/$ac_word$ac_exec_ext"
+ break 2
+ fi
+ fi
+ done
+ done
+ IFS="$ac_save_IFS"
+ ;;
+esac
+fi
+valgrind_path="$ac_cv_path_valgrind_path"
+if test -n "$valgrind_path"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $valgrind_path" >&5
+$as_echo "$valgrind_path" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$valgrind_path" = "x" \
+ || (test $have_valgrind_h = no \
+ && test $gcc_cv_header_memcheck_h = no \
+ && test $gcc_cv_header_valgrind_memcheck_h = no); then
+ as_fn_error $? "*** Can't find both valgrind and valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5
+ fi
+ valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"'
+ valgrind_command="$valgrind_path -q"
+
+$as_echo "#define ENABLE_VALGRIND_CHECKING 1" >>confdefs.h
+
+fi
+
+
+
+# Enable code coverage collection
+# Check whether --enable-coverage was given.
+if test "${enable_coverage+set}" = set; then :
+ enableval=$enable_coverage; case "${enableval}" in
+ yes|noopt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0 -fkeep-static-functions"
+ ;;
+ opt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2 -fkeep-static-functions"
+ ;;
+ no)
+ # a.k.a. --disable-coverage
+ coverage_flags=""
+ ;;
+ *)
+ as_fn_error $? "unknown coverage setting $enableval" "$LINENO" 5
+ ;;
+esac
+else
+ coverage_flags=""
+fi
+
+
+
+# Check whether --enable-gather-detailed-mem-stats was given.
+if test "${enable_gather_detailed_mem_stats+set}" = set; then :
+ enableval=$enable_gather_detailed_mem_stats;
+else
+ enable_gather_detailed_mem_stats=no
+fi
+
+gather_stats=`if test $enable_gather_detailed_mem_stats != no; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define GATHER_STATISTICS $gather_stats
+_ACEOF
+
+
+# Check whether --enable-valgrind-annotations was given.
+if test "${enable_valgrind_annotations+set}" = set; then :
+ enableval=$enable_valgrind_annotations;
+else
+ enable_valgrind_annotations=no
+fi
+
+if test x$enable_valgrind_annotations != xno \
+ || test x$ac_valgrind_checking != x; then
+ if (test $have_valgrind_h = no \
+ && test $gcc_cv_header_memcheck_h = no \
+ && test $gcc_cv_header_valgrind_memcheck_h = no); then
+ as_fn_error $? "*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h" "$LINENO" 5
+ fi
+
+$as_echo "#define ENABLE_VALGRIND_ANNOTATIONS 1" >>confdefs.h
+
+fi
+
+# -------------------------------
+# Miscenalleous configure options
+# -------------------------------
+
+# Determine whether or not multilibs are enabled.
+# Check whether --enable-multilib was given.
+if test "${enable_multilib+set}" = set; then :
+ enableval=$enable_multilib;
+else
+ enable_multilib=yes
+fi
+
+
+
+# Determine whether or not multiarch is enabled.
+# Check whether --enable-multiarch was given.
+if test "${enable_multiarch+set}" = set; then :
+ enableval=$enable_multiarch; case "${enableval}" in
+yes|no|auto) enable_multiarch=$enableval;;
+*) as_fn_error $? "bad value ${enableval} given for --enable-multiarch option" "$LINENO" 5 ;;
+esac
+else
+ enable_multiarch=auto
+fi
+
+if test x${enable_multiarch} = xauto; then
+ if test x${with_native_system_header_dir} != x; then
+ ma_msg_suffix=", disabled auto check (configured with --native-system-header-dir)"
+ enable_multiarch=no
+ fi
+ if test x$host != x$target && test "x$with_sysroot" = x; then
+ ma_msg_suffix=", disabled auto check (cross build configured without --with-sysroot)"
+ enable_multiarch=no
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for multiarch configuration" >&5
+$as_echo_n "checking for multiarch configuration... " >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_multiarch$ma_msg_suffix" >&5
+$as_echo "$enable_multiarch$ma_msg_suffix" >&6; }
+
+# needed for setting the multiarch name for soft-float/hard-float ABIs
+
+
+
+# default stack clash protection guard size as power of twos in bytes.
+# Please keep these in sync with params.def.
+stk_clash_min=12
+stk_clash_max=30
+
+# Keep the default value when the option is not used to 0, this allows us to
+# distinguish between the cases where the user specifially set a value via
+# configure and when the normal default value is used.
+
+# Check whether --with-stack-clash-protection-guard-size was given.
+if test "${with_stack_clash_protection_guard_size+set}" = set; then :
+ withval=$with_stack_clash_protection_guard_size; DEFAULT_STK_CLASH_GUARD_SIZE="$with_stack_clash_protection_guard_size"
+else
+ DEFAULT_STK_CLASH_GUARD_SIZE=0
+fi
+
+if test $DEFAULT_STK_CLASH_GUARD_SIZE -ne 0 \
+ && (test $DEFAULT_STK_CLASH_GUARD_SIZE -lt $stk_clash_min \
+ || test $DEFAULT_STK_CLASH_GUARD_SIZE -gt $stk_clash_max); then
+ as_fn_error $? "Invalid value $DEFAULT_STK_CLASH_GUARD_SIZE for --with-stack-clash-protection-guard-size. Must be between $stk_clash_min and $stk_clash_max." "$LINENO" 5
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_STK_CLASH_GUARD_SIZE $DEFAULT_STK_CLASH_GUARD_SIZE
+_ACEOF
+
+
+# Enable __cxa_atexit for C++.
+# Check whether --enable-__cxa_atexit was given.
+if test "${enable___cxa_atexit+set}" = set; then :
+ enableval=$enable___cxa_atexit;
+fi
+
+
+# Enable C extension for decimal float if target supports it.
+
+# Check whether --enable-decimal-float was given.
+if test "${enable_decimal_float+set}" = set; then :
+ enableval=$enable_decimal_float;
+ case $enable_decimal_float in
+ yes | no | bid | dpd) default_decimal_float=$enable_decimal_float ;;
+ *) as_fn_error $? "'$enable_decimal_float' is an invalid value for --enable-decimal-float.
+Valid choices are 'yes', 'bid', 'dpd', and 'no'." "$LINENO" 5 ;;
+ esac
+
+else
+
+ case $target in
+ powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
+ i?86*-*-elfiamcu | i?86*-*-gnu* | x86_64*-*-gnu* | \
+ i?86*-*-mingw* | x86_64*-*-mingw* | \
+ i?86*-*-cygwin* | x86_64*-*-cygwin*)
+ enable_decimal_float=yes
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: decimal float is not supported for this target, ignored" >&5
+$as_echo "$as_me: WARNING: decimal float is not supported for this target, ignored" >&2;}
+ enable_decimal_float=no
+ ;;
+ esac
+
+fi
+
+
+# x86's use BID format instead of DPD
+case x$enable_decimal_float in
+ xyes)
+ case $target in
+ i?86*-*-* | x86_64*-*-*)
+ enable_decimal_float=bid
+ ;;
+ *)
+ enable_decimal_float=dpd
+ ;;
+ esac
+ default_decimal_float=$enable_decimal_float
+ ;;
+ xno)
+ # ENABLE_DECIMAL_FLOAT is set to 0. But we have to have proper
+ # dependency on libdecnumber.
+ default_decimal_float=dpd
+ ;;
+esac
+
+
+
+
+dfp=`if test $enable_decimal_float != no; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_DECIMAL_FLOAT $dfp
+_ACEOF
+
+
+# Use default_decimal_float for dependency.
+enable_decimal_float=$default_decimal_float
+
+bid=`if test $enable_decimal_float = bid; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_DECIMAL_BID_FORMAT $bid
+_ACEOF
+
+
+# Enable C extension for fixed-point arithmetic.
+# Check whether --enable-fixed-point was given.
+if test "${enable_fixed_point+set}" = set; then :
+ enableval=$enable_fixed_point;
+else
+
+ case $target in
+ arm*)
+ enable_fixed_point=yes
+ ;;
+
+ mips*-*-*)
+ enable_fixed_point=yes
+ ;;
+ loongarch*-*-*)
+ enable_fixed_point=yes
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fixed-point is not supported for this target, ignored" >&5
+$as_echo "$as_me: WARNING: fixed-point is not supported for this target, ignored" >&2;}
+ enable_fixed_point=no
+ ;;
+ esac
+
+fi
+
+
+
+fixedpoint=`if test $enable_fixed_point = yes; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_FIXED_POINT $fixedpoint
+_ACEOF
+
+
+# Enable threads
+# Pass with no value to take the default
+# Pass with a value to specify a thread package
+# Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then :
+ enableval=$enable_threads;
+else
+ enable_threads=''
+fi
+
+
+# Check whether --enable-tls was given.
+if test "${enable_tls+set}" = set; then :
+ enableval=$enable_tls;
+ case $enable_tls in
+ yes | no) ;;
+ *) as_fn_error $? "'$enable_tls' is an invalid value for --enable-tls.
+Valid choices are 'yes' and 'no'." "$LINENO" 5 ;;
+ esac
+
+else
+ enable_tls=''
+fi
+
+
+# Check whether --enable-vtable-verify was given.
+if test "${enable_vtable_verify+set}" = set; then :
+ enableval=$enable_vtable_verify;
+else
+ enable_vtable_verify=no
+fi
+
+vtable_verify=`if test x$enable_vtable_verify = xyes; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_VTABLE_VERIFY $vtable_verify
+_ACEOF
+
+
+# Check whether --enable-analyzer was given.
+if test "${enable_analyzer+set}" = set; then :
+ enableval=$enable_analyzer; if test x$enable_analyzer = xno; then
+ analyzer=0
+else
+ analyzer=1
+fi
+else
+ analyzer=1
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define ENABLE_ANALYZER $analyzer
+_ACEOF
+
+
+# Check whether --enable-objc-gc was given.
+if test "${enable_objc_gc+set}" = set; then :
+ enableval=$enable_objc_gc; if test x$enable_objc_gc = xno; then
+ objc_boehm_gc=''
+else
+ objc_boehm_gc=1
+fi
+else
+ objc_boehm_gc=''
+fi
+
+
+
+# Check whether --with-dwarf2 was given.
+if test "${with_dwarf2+set}" = set; then :
+ withval=$with_dwarf2; dwarf2="$with_dwarf2"
+else
+ dwarf2=no
+fi
+
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared;
+ case $enable_shared in
+ yes | no) ;;
+ *)
+ enable_shared=no
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "Xgcc" || test "X$pkg" = "Xlibgcc"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+ esac
+
+else
+ enable_shared=yes
+fi
+
+
+
+# Check whether --enable-gcov was given.
+if test "${enable_gcov+set}" = set; then :
+ enableval=$enable_gcov;
+else
+ case $target in
+ bpf-*-*)
+ enable_gcov=no
+ ;;
+ *)
+ enable_gcov=yes
+ ;;
+ esac
+fi
+
+
+
+
+
+# Check whether --with-specs was given.
+if test "${with_specs+set}" = set; then :
+ withval=$with_specs; CONFIGURE_SPECS=$withval
+else
+ CONFIGURE_SPECS=
+
+fi
+
+
+
+
+
+# Check whether --with-pkgversion was given.
+if test "${with_pkgversion+set}" = set; then :
+ withval=$with_pkgversion; case "$withval" in
+ yes) as_fn_error $? "package version not specified" "$LINENO" 5 ;;
+ no) PKGVERSION= ;;
+ *) PKGVERSION="($withval) " ;;
+ esac
+else
+ PKGVERSION="(GCC) "
+
+fi
+
+
+
+
+
+# Check whether --with-bugurl was given.
+if test "${with_bugurl+set}" = set; then :
+ withval=$with_bugurl; case "$withval" in
+ yes) as_fn_error $? "bug URL not specified" "$LINENO" 5 ;;
+ no) BUGURL=
+ ;;
+ *) BUGURL="$withval"
+ ;;
+ esac
+else
+ BUGURL="http://sourceforge.net/tracker/?atid=100599&group_id=599&func=browse"
+
+fi
+
+ case ${BUGURL} in
+ "")
+ REPORT_BUGS_TO=
+ REPORT_BUGS_TEXI=
+ ;;
+ *)
+ REPORT_BUGS_TO="<$BUGURL>"
+ REPORT_BUGS_TEXI=@uref{`echo "$BUGURL" | sed 's/@/@@/g'`}
+ ;;
+ esac;
+
+
+
+
+# Allow overriding the default URL for documentation
+
+# Check whether --with-documentation-root-url was given.
+if test "${with_documentation_root_url+set}" = set; then :
+ withval=$with_documentation_root_url; case "$withval" in
+ yes) as_fn_error $? "documentation root URL not specified" "$LINENO" 5 ;;
+ no) as_fn_error $? "documentation root URL not specified" "$LINENO" 5 ;;
+ */) DOCUMENTATION_ROOT_URL="$withval" ;;
+ *) as_fn_error $? "documentation root URL does not end with /" "$LINENO" 5 ;;
+ esac
+else
+ DOCUMENTATION_ROOT_URL="https://gcc.gnu.org/onlinedocs/"
+
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define DOCUMENTATION_ROOT_URL "$DOCUMENTATION_ROOT_URL"
+_ACEOF
+
+
+# Allow overriding the default URL for GCC changes
+
+# Check whether --with-changes-root-url was given.
+if test "${with_changes_root_url+set}" = set; then :
+ withval=$with_changes_root_url; case "$withval" in
+ yes) as_fn_error $? "changes root URL not specified" "$LINENO" 5 ;;
+ no) as_fn_error $? "changes root URL not specified" "$LINENO" 5 ;;
+ */) CHANGES_ROOT_URL="$withval" ;;
+ *) as_fn_error $? "changes root URL does not end with /" "$LINENO" 5 ;;
+ esac
+else
+ CHANGES_ROOT_URL="https://gcc.gnu.org/"
+
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define CHANGES_ROOT_URL "$CHANGES_ROOT_URL"
+_ACEOF
+
+
+# Sanity check enable_languages in case someone does not run the toplevel
+# configure # script.
+# Check whether --enable-languages was given.
+if test "${enable_languages+set}" = set; then :
+ enableval=$enable_languages; case ,${enable_languages}, in
+ ,,|,yes,)
+ # go safe -- we cannot be much sure without the toplevel
+ # configure's
+ # analysis of which target libs are present and usable
+ enable_languages=c
+ ;;
+ *,all,*)
+ as_fn_error $? "only the toplevel supports --enable-languages=all" "$LINENO" 5
+ ;;
+ *,c,*)
+ ;;
+ *)
+ enable_languages=c,${enable_languages}
+ ;;
+esac
+else
+ enable_languages=c
+fi
+
+
+# If top-level libada has been disabled, then wire in install-gnatlib
+# invocation with `make install', so that one can build and install
+# the library manually with `make -C gcc all gnatlib gnattools install'.
+if test x"$enable_libada" = xno; then
+ gnat_install_lib=gnat-install-lib
+else
+ gnat_install_lib=
+fi
+
+
+if test x"$enable_as_accelerator_for" != x; then
+
+$as_echo "#define ACCEL_COMPILER 1" >>confdefs.h
+
+ enable_as_accelerator=yes
+ case "${target}" in
+ *-intelmicemul-*)
+ # In this case we expect offload compiler to be built as native, so we
+ # need to rename the driver to avoid clashes with host's drivers.
+ program_transform_name="s&^&${target}-&" ;;
+ esac
+ sedscript="s#${target_noncanonical}#${enable_as_accelerator_for}-accel-${target_noncanonical}#"
+ program_transform_name=`echo $program_transform_name | sed $sedscript`
+ accel_dir_suffix=/accel/${target_noncanonical}
+ real_target_noncanonical=${enable_as_accelerator_for}
+fi
+
+
+
+
+for tgt in `echo $enable_offload_targets | sed 's/,/ /g'`; do
+ tgt=`echo $tgt | sed 's/=.*//'`
+
+ enable_offloading=1
+ case "$tgt" in
+ *-intelmic-* | *-intelmicemul-*)
+ omp_device_property=omp-device-properties-i386
+ omp_device_property_tmake_file="${omp_device_property_tmake_file} \$(srcdir)/config/i386/t-omp-device"
+ ;;
+ amdgcn*)
+ omp_device_property=omp-device-properties-gcn
+ omp_device_property_tmake_file="${omp_device_property_tmake_file} \$(srcdir)/config/gcn/t-omp-device"
+ ;;
+ nvptx*)
+ omp_device_property=omp-device-properties-nvptx
+ omp_device_property_tmake_file="${omp_device_property_tmake_file} \$(srcdir)/config/nvptx/t-omp-device"
+ ;;
+ *)
+ as_fn_error $? "unknown offload target specified" "$LINENO" 5
+ ;;
+ esac
+ omp_device_properties="${omp_device_properties} ${tgt}=${omp_device_property}"
+ omp_device_property_deps="${omp_device_property_deps} ${omp_device_property}"
+
+ if test x"$offload_targets" = x; then
+ offload_targets=$tgt
+ else
+ offload_targets="$offload_targets,$tgt"
+ fi
+done
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define OFFLOAD_TARGETS "$offload_targets"
+_ACEOF
+
+if test x"$enable_offloading" != x; then
+
+$as_echo "#define ENABLE_OFFLOADING 1" >>confdefs.h
+
+else
+
+$as_echo "#define ENABLE_OFFLOADING 0" >>confdefs.h
+
+fi
+
+if test "x$enable_offload_defaulted" = xyes; then
+
+$as_echo "#define OFFLOAD_DEFAULTED 1" >>confdefs.h
+
+fi
+
+
+# Check whether --with-multilib-list was given.
+if test "${with_multilib_list+set}" = set; then :
+ withval=$with_multilib_list; :
+else
+ with_multilib_list=default
+fi
+
+
+
+# Check whether --with-multilib-generator was given.
+if test "${with_multilib_generator+set}" = set; then :
+ withval=$with_multilib_generator; :
+else
+ with_multilib_generator=default
+fi
+
+
+# -------------------------
+# Checks for other programs
+# -------------------------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+# Find some useful tools
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+# We need awk to create options.cc and options.h.
+# Bail out if it's missing.
+case ${AWK} in
+ "") as_fn_error $? "can't build without awk, bailing out" "$LINENO" 5 ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+if ${gcc_cv_prog_LN_S+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f conftestdata_t
+echo >conftestdata_f
+if ln -s conftestdata_f conftestdata_t 2>/dev/null
+then
+ gcc_cv_prog_LN_S="ln -s"
+else
+ if ln conftestdata_f conftestdata_t 2>/dev/null
+ then
+ gcc_cv_prog_LN_S=ln
+ else
+ if cp -p conftestdata_f conftestdata_t 2>/dev/null
+ then
+ gcc_cv_prog_LN_S="cp -p"
+ else
+ gcc_cv_prog_LN_S=cp
+ fi
+ fi
+fi
+rm -f conftestdata_f conftestdata_t
+
+fi
+LN_S="$gcc_cv_prog_LN_S"
+if test "$gcc_cv_prog_LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ if test "$gcc_cv_prog_LN_S" = "ln"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using ln" >&5
+$as_echo "no, using ln" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, and neither does ln, so using $gcc_cv_prog_LN_S" >&5
+$as_echo "no, and neither does ln, so using $gcc_cv_prog_LN_S" >&6; }
+ fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln works" >&5
+$as_echo_n "checking whether ln works... " >&6; }
+if ${acx_cv_prog_LN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f conftestdata_t
+echo >conftestdata_f
+if ln conftestdata_f conftestdata_t 2>/dev/null
+then
+ acx_cv_prog_LN=ln
+else
+ acx_cv_prog_LN=no
+fi
+rm -f conftestdata_f conftestdata_t
+
+fi
+if test $acx_cv_prog_LN = no; then
+ LN="$LN_S"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN" >&5
+$as_echo "no, using $LN" >&6; }
+else
+ LN="$acx_cv_prog_LN"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+ranlib_flags=""
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD compatible install" >&5
+$as_echo_n "checking for a BSD compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# See if cmp has --ignore-initial.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cmp's capabilities" >&5
+$as_echo_n "checking for cmp's capabilities... " >&6; }
+if ${gcc_cv_prog_cmp_skip+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ echo abfoo >t1
+ echo cdfoo >t2
+ gcc_cv_prog_cmp_skip=slowcompare
+ if cmp --ignore-initial=2 t1 t2 > /dev/null 2>&1; then
+ if cmp --ignore-initial=1 t1 t2 > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_prog_cmp_skip=gnucompare
+ fi
+ fi
+ if test $gcc_cv_prog_cmp_skip = slowcompare ; then
+ if cmp t1 t2 2 2 > /dev/null 2>&1; then
+ if cmp t1 t2 1 1 > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_prog_cmp_skip=fastcompare
+ fi
+ fi
+ fi
+ rm t1 t2
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_prog_cmp_skip" >&5
+$as_echo "$gcc_cv_prog_cmp_skip" >&6; }
+make_compare_target=$gcc_cv_prog_cmp_skip
+
+
+
+# See if we have the mktemp command.
+# Extract the first word of "mktemp", so it can be a program name with args.
+set dummy mktemp; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_have_mktemp_command+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$have_mktemp_command"; then
+ ac_cv_prog_have_mktemp_command="$have_mktemp_command" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_have_mktemp_command="yes"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_have_mktemp_command" && ac_cv_prog_have_mktemp_command="no"
+fi
+fi
+have_mktemp_command=$ac_cv_prog_have_mktemp_command
+if test -n "$have_mktemp_command"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_mktemp_command" >&5
+$as_echo "$have_mktemp_command" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# See if makeinfo has been installed and is modern enough
+# that we can use it.
+
+ # Extract the first word of "makeinfo", so it can be a program name with args.
+set dummy makeinfo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MAKEINFO+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MAKEINFO"; then
+ ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_MAKEINFO="makeinfo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+MAKEINFO=$ac_cv_prog_MAKEINFO
+if test -n "$MAKEINFO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5
+$as_echo "$MAKEINFO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -n "$MAKEINFO"; then
+ # Found it, now check the version.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for modern makeinfo" >&5
+$as_echo_n "checking for modern makeinfo... " >&6; }
+if ${gcc_cv_prog_makeinfo_modern+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_prog_version=`eval $MAKEINFO --version 2>&1 |
+ sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'`
+
+ case $ac_prog_version in
+ '') gcc_cv_prog_makeinfo_modern=no;;
+ 4.[7-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*) gcc_cv_prog_makeinfo_modern=yes;;
+ *) gcc_cv_prog_makeinfo_modern=no;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_prog_makeinfo_modern" >&5
+$as_echo "$gcc_cv_prog_makeinfo_modern" >&6; }
+ else
+ gcc_cv_prog_makeinfo_modern=no
+ fi
+ if test $gcc_cv_prog_makeinfo_modern = no; then
+ MAKEINFO="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing makeinfo"
+ fi
+
+if test $gcc_cv_prog_makeinfo_modern = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+*** Makeinfo is missing or too old.
+*** Info documentation will not be built." >&5
+$as_echo "$as_me: WARNING:
+*** Makeinfo is missing or too old.
+*** Info documentation will not be built." >&2;}
+ BUILD_INFO=
+else
+ BUILD_INFO=info
+fi
+
+
+# Is pod2man recent enough to regenerate manpages?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for recent Pod::Man" >&5
+$as_echo_n "checking for recent Pod::Man... " >&6; }
+if (perl -e 'use 1.10 Pod::Man') >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ GENERATED_MANPAGES=generated-manpages
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ GENERATED_MANPAGES=
+fi
+
+
+MISSING="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing"
+
+# How about lex?
+for ac_prog in flex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_FLEX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$FLEX"; then
+ ac_cv_prog_FLEX="$FLEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FLEX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+FLEX=$ac_cv_prog_FLEX
+if test -n "$FLEX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5
+$as_echo "$FLEX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$FLEX" && break
+done
+test -n "$FLEX" || FLEX="$MISSING flex"
+
+
+# Bison?
+for ac_prog in bison
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_BISON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$BISON"; then
+ ac_cv_prog_BISON="$BISON" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_BISON="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+BISON=$ac_cv_prog_BISON
+if test -n "$BISON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BISON" >&5
+$as_echo "$BISON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$BISON" && break
+done
+test -n "$BISON" || BISON="$MISSING bison"
+
+
+# Binutils are not build modules, unlike bison/flex/makeinfo. So we
+# check for build == host before using them.
+
+# NM
+if test x${build} = x${host} && test -f $srcdir/../binutils/nm.c \
+ && test -d ../binutils ; then
+ NM='${objdir}/../binutils/nm-new'
+else
+ # Extract the first word of "nm", so it can be a program name with args.
+set dummy nm; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NM+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NM"; then
+ ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_NM="nm"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_NM" && ac_cv_prog_NM="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing nm"
+fi
+fi
+NM=$ac_cv_prog_NM
+if test -n "$NM"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5
+$as_echo "$NM" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+# AR
+if test x${build} = x${host} && test -f $srcdir/../binutils/ar.c \
+ && test -d ../binutils ; then
+ AR='${objdir}/../binutils/ar'
+else
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing ar"
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+
+# The jit documentation looks better if built with sphinx, but can be
+# built with texinfo if sphinx is not available.
+# Set "doc_build_sys" to "sphinx" or "texinfo" accordingly.
+# Extract the first word of "sphinx-build", so it can be a program name with args.
+set dummy sphinx-build; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_doc_build_sys+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$doc_build_sys"; then
+ ac_cv_prog_doc_build_sys="$doc_build_sys" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_doc_build_sys="sphinx"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_doc_build_sys" && ac_cv_prog_doc_build_sys="texinfo"
+fi
+fi
+doc_build_sys=$ac_cv_prog_doc_build_sys
+if test -n "$doc_build_sys"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doc_build_sys" >&5
+$as_echo "$doc_build_sys" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# --------------------
+# Checks for C headers
+# --------------------
+
+# Need to reject headers which give warnings, so that the -Werror bootstrap
+# works later. *sigh* This needs to come before all header checks.
+
+ac_c_preproc_warn_flag=yes
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5
+$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; }
+if ${ac_cv_header_time+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+
+int
+main ()
+{
+if ((struct tm *) 0)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_header_time=yes
+else
+ ac_cv_header_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5
+$as_echo "$ac_cv_header_time" >&6; }
+if test $ac_cv_header_time = yes; then
+
+$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether string.h and strings.h may both be included" >&5
+$as_echo_n "checking whether string.h and strings.h may both be included... " >&6; }
+if ${gcc_cv_header_string+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+#include <strings.h>
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_header_string=yes
+else
+ gcc_cv_header_string=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_string" >&5
+$as_echo "$gcc_cv_header_string" >&6; }
+if test $gcc_cv_header_string = yes; then
+
+$as_echo "#define STRING_WITH_STRINGS 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5
+$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; }
+if ${ac_cv_header_sys_wait_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+int
+main ()
+{
+ int s;
+ wait (&s);
+ s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_header_sys_wait_h=yes
+else
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5
+$as_echo "$ac_cv_header_sys_wait_h" >&6; }
+if test $ac_cv_header_sys_wait_h = yes; then
+
+$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether termios.h defines TIOCGWINSZ" >&5
+$as_echo_n "checking whether termios.h defines TIOCGWINSZ... " >&6; }
+if ${ac_cv_sys_tiocgwinsz_in_termios_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <termios.h>
+#ifdef TIOCGWINSZ
+ yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then :
+ ac_cv_sys_tiocgwinsz_in_termios_h=yes
+else
+ ac_cv_sys_tiocgwinsz_in_termios_h=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_tiocgwinsz_in_termios_h" >&5
+$as_echo "$ac_cv_sys_tiocgwinsz_in_termios_h" >&6; }
+
+if test $ac_cv_sys_tiocgwinsz_in_termios_h != yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/ioctl.h defines TIOCGWINSZ" >&5
+$as_echo_n "checking whether sys/ioctl.h defines TIOCGWINSZ... " >&6; }
+if ${ac_cv_sys_tiocgwinsz_in_sys_ioctl_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#ifdef TIOCGWINSZ
+ yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then :
+ ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=yes
+else
+ ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&5
+$as_echo "$ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&6; }
+
+ if test $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h = yes; then
+
+$as_echo "#define GWINSZ_IN_SYS_IOCTL 1" >>confdefs.h
+
+ fi
+fi
+
+for ac_header in limits.h stddef.h string.h strings.h stdlib.h time.h iconv.h \
+ fcntl.h ftw.h unistd.h sys/file.h sys/time.h sys/mman.h \
+ sys/resource.h sys/param.h sys/times.h sys/stat.h sys/locking.h \
+ direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+# Check for thread headers.
+ac_fn_cxx_check_header_preproc "$LINENO" "thread.h" "ac_cv_header_thread_h"
+if test "x$ac_cv_header_thread_h" = xyes; then :
+ have_thread_h=yes
+else
+ have_thread_h=
+fi
+
+ac_fn_cxx_check_header_preproc "$LINENO" "pthread.h" "ac_cv_header_pthread_h"
+if test "x$ac_cv_header_pthread_h" = xyes; then :
+ have_pthread_h=yes
+else
+ have_pthread_h=
+fi
+
+
+# These tests can't be done till we know if we have limits.h.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CHAR_BIT" >&5
+$as_echo_n "checking for CHAR_BIT... " >&6; }
+if ${gcc_cv_decl_char_bit+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef CHAR_BIT
+found
+#endif
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "found" >/dev/null 2>&1; then :
+ gcc_cv_decl_char_bit=yes
+else
+ gcc_cv_decl_char_bit=no
+fi
+rm -f conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_decl_char_bit" >&5
+$as_echo "$gcc_cv_decl_char_bit" >&6; }
+if test $gcc_cv_decl_char_bit = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking number of bits in a byte" >&5
+$as_echo_n "checking number of bits in a byte... " >&6; }
+if ${gcc_cv_c_nbby+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ i=8
+ gcc_cv_c_nbby=
+ while test $i -lt 65; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+switch(0) {
+ case (unsigned char)((unsigned long)1 << $i) == ((unsigned long)1 << $i):
+ case (unsigned char)((unsigned long)1<<($i-1)) == ((unsigned long)1<<($i-1)):
+ ; }
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_c_nbby=$i; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ i=`expr $i + 1`
+ done
+ test -z "$gcc_cv_c_nbby" && gcc_cv_c_nbby=failed
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_c_nbby" >&5
+$as_echo "$gcc_cv_c_nbby" >&6; }
+if test $gcc_cv_c_nbby = failed; then
+ as_fn_error $? "cannot determine number of bits in a byte" "$LINENO" 5
+else
+
+cat >>confdefs.h <<_ACEOF
+#define CHAR_BIT $gcc_cv_c_nbby
+_ACEOF
+
+fi
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+# ----------------------
+# Checks for C++ headers
+# ----------------------
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+ if ${ac_cv_prog_CXXCPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" >&5
+$as_echo "$as_me: WARNING: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" >&2;}; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+for ac_header in unordered_map
+do :
+ ac_fn_cxx_check_header_preproc "$LINENO" "unordered_map" "ac_cv_header_unordered_map"
+if test "x$ac_cv_header_unordered_map" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_UNORDERED_MAP 1
+_ACEOF
+
+fi
+done
+
+for ac_header in tr1/unordered_map
+do :
+ ac_fn_cxx_check_header_preproc "$LINENO" "tr1/unordered_map" "ac_cv_header_tr1_unordered_map"
+if test "x$ac_cv_header_tr1_unordered_map" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_TR1_UNORDERED_MAP 1
+_ACEOF
+
+fi
+done
+
+for ac_header in ext/hash_map
+do :
+ ac_fn_cxx_check_header_preproc "$LINENO" "ext/hash_map" "ac_cv_header_ext_hash_map"
+if test "x$ac_cv_header_ext_hash_map" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EXT_HASH_MAP 1
+_ACEOF
+
+fi
+done
+
+
+# --------
+# Dependency checking.
+# --------
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depdir"
+
+
+ac_config_commands="$ac_config_commands gccdepdir"
+
+
+depcc="$CXX" am_compiler_list=
+
+am_depcomp=$ac_aux_dir/depcomp
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CXX_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ for depmode in $am_compiler_list; do
+ if test $depmode = none; then break; fi
+
+ $as_echo "$as_me:$LINENO: trying $depmode" >&5
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "include sub/conftest.Po" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this.
+ depcmd="depmode=$depmode \
+ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c"
+ echo "| $depcmd" | sed -e 's/ */ /g' >&5
+ if env $depcmd > conftest.err 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po >>conftest.err 2>&1 &&
+ grep sub/conftest.${OBJEXT-o} sub/conftest.Po >>conftest.err 2>&1 &&
+ ${MAKE-make} -s -f confmf >>conftest.err 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ $as_echo "$as_me:$LINENO: success" >&5
+ break
+ fi
+ fi
+ $as_echo "$as_me:$LINENO: failure, diagnostics are:" >&5
+ sed -e 's/^/| /' < conftest.err >&5
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+if test x${am_cv_CXX_dependencies_compiler_type-none} = xnone
+then as_fn_error $? "no usable dependency style found" "$LINENO" 5
+else CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+fi
+
+
+# --------
+# UNSORTED
+# --------
+
+
+# These libraries may be used by collect2.
+# We may need a special search path to get them linked.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for collect2 libraries" >&5
+$as_echo_n "checking for collect2 libraries... " >&6; }
+if ${gcc_cv_collect2_libs+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ save_LIBS="$LIBS"
+for libs in '' -lld -lmld \
+ '-L/usr/lib/cmplrs/cc2.11 -lmld' \
+ '-L/usr/lib/cmplrs/cc3.11 -lmld'
+do
+ LIBS="$libs"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldopen ();
+int
+main ()
+{
+return ldopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ gcc_cv_collect2_libs="$libs"; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+done
+LIBS="$save_LIBS"
+test -z "$gcc_cv_collect2_libs" && gcc_cv_collect2_libs='none required'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_collect2_libs" >&5
+$as_echo "$gcc_cv_collect2_libs" >&6; }
+case $gcc_cv_collect2_libs in
+ "none required") ;;
+ *) COLLECT2_LIBS=$gcc_cv_collect2_libs ;;
+esac
+
+
+# When building Ada code on Alpha, we need exc_resume which is usually in
+# -lexc. So test for it.
+save_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing exc_resume" >&5
+$as_echo_n "checking for library containing exc_resume... " >&6; }
+if ${ac_cv_search_exc_resume+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char exc_resume ();
+int
+main ()
+{
+return exc_resume ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' exc; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_exc_resume=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_exc_resume+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_exc_resume+:} false; then :
+
+else
+ ac_cv_search_exc_resume=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_exc_resume" >&5
+$as_echo "$ac_cv_search_exc_resume" >&6; }
+ac_res=$ac_cv_search_exc_resume
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+GNAT_LIBEXC="$LIBS"
+LIBS="$save_LIBS"
+
+
+# To support -mcpu=native on Solaris/SPARC, we need libkstat.
+save_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing kstat_open" >&5
+$as_echo_n "checking for library containing kstat_open... " >&6; }
+if ${ac_cv_search_kstat_open+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char kstat_open ();
+int
+main ()
+{
+return kstat_open ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' kstat; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_kstat_open=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_kstat_open+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_kstat_open+:} false; then :
+
+else
+ ac_cv_search_kstat_open=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_kstat_open" >&5
+$as_echo "$ac_cv_search_kstat_open" >&6; }
+ac_res=$ac_cv_search_kstat_open
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+EXTRA_GCC_LIBS="$LIBS"
+LIBS="$save_LIBS"
+
+
+# Solaris needs libsocket and libnsl for socket functions before 11.4.
+# C++ needs those for libcody.
+save_LIBS="$LIBS"
+LIBS=
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+$as_echo_n "checking for library containing gethostbyname... " >&6; }
+if ${ac_cv_search_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_gethostbyname+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_gethostbyname+:} false; then :
+
+else
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+$as_echo "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if ${ac_cv_search_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_socket+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_socket+:} false; then :
+
+else
+ ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
+$as_echo_n "checking for socket in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_lib_socket_socket=yes
+else
+ ac_cv_lib_socket_socket=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
+$as_echo "$ac_cv_lib_socket_socket" >&6; }
+if test "x$ac_cv_lib_socket_socket" = xyes; then :
+ LIBS="-lsocket -lnsl $LIBS"
+fi
+
+fi
+
+
+NETLIBS="$LIBS"
+LIBS="$save_LIBS"
+
+
+# Some systems put ldexp and frexp in libm instead of libc; assume
+# they're both in the same place. jcf-dump needs them.
+save_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ldexp" >&5
+$as_echo_n "checking for library containing ldexp... " >&6; }
+if ${ac_cv_search_ldexp+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ldexp ();
+int
+main ()
+{
+return ldexp ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' m; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_ldexp=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ldexp+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ldexp+:} false; then :
+
+else
+ ac_cv_search_ldexp=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ldexp" >&5
+$as_echo "$ac_cv_search_ldexp" >&6; }
+ac_res=$ac_cv_search_ldexp
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+LDEXP_LIB="$LIBS"
+LIBS="$save_LIBS"
+
+
+# Some systems need dlopen
+save_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_dlopen+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+ ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+DL_LIB="$LIBS"
+LIBS="$save_LIBS"
+
+
+# Use <inttypes.h> only if it exists,
+# doesn't clash with <sys/types.h>, declares intmax_t and defines
+# PRId64
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inttypes.h" >&5
+$as_echo_n "checking for inttypes.h... " >&6; }
+if ${gcc_cv_header_inttypes_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define __STDC_FORMAT_MACROS
+#include <sys/types.h>
+#include <inttypes.h>
+int
+main ()
+{
+intmax_t i = -1;
+#ifndef PRId64
+choke me
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_header_inttypes_h=yes
+else
+ gcc_cv_header_inttypes_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_inttypes_h" >&5
+$as_echo "$gcc_cv_header_inttypes_h" >&6; }
+if test $gcc_cv_header_inttypes_h = yes; then
+
+$as_echo "#define HAVE_INTTYPES_H 1" >>confdefs.h
+
+fi
+
+# Look for the ZSTD package.
+ZSTD_INCLUDE=
+ZSTD_LIB=
+
+
+ZSTD_CPPFLAGS=
+ZSTD_LDFLAGS=
+
+
+
+# Check whether --with-zstd was given.
+if test "${with_zstd+set}" = set; then :
+ withval=$with_zstd;
+fi
+
+
+# Check whether --with-zstd-include was given.
+if test "${with_zstd_include+set}" = set; then :
+ withval=$with_zstd_include;
+fi
+
+
+# Check whether --with-zstd-lib was given.
+if test "${with_zstd_lib+set}" = set; then :
+ withval=$with_zstd_lib;
+fi
+
+case "x$with_zstd" in
+ x) ;;
+ xno)
+ ZSTD_INCLUDE=
+ ZSTD_LIB=
+ ;;
+ *) ZSTD_INCLUDE=$with_zstd/include
+ ZSTD_LIB=$with_zstd/lib
+ ;;
+esac
+
+if test "x$with_zstd" != xno; then
+if test "x$with_zstd_include" != x; then
+ ZSTD_INCLUDE=$with_zstd_include
+fi
+if test "x$with_zstd_lib" != x; then
+ ZSTD_LIB=$with_zstd_lib
+fi
+if test "x$ZSTD_INCLUDE" != x \
+ && test "x$ZSTD_INCLUDE" != xno; then
+ ZSTD_CPPFLAGS=-I$ZSTD_INCLUDE
+fi
+if test "x$ZSTD_LIB" != x \
+ && test "x$ZSTD_LIB" != xno; then
+ ZSTD_LDFLAGS=-L$ZSTD_LIB
+fi
+
+CXXFLAGS="$CXXFLAGS $ZSTD_CPPFLAGS"
+LDFLAGS="$LDFLAGS $ZSTD_LDFLAGS"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zstd.h" >&5
+$as_echo_n "checking for zstd.h... " >&6; }
+if ${gcc_cv_header_zstd_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # We require version 1.3.0 or later. This is the first version that has
+# ZSTD_getFrameContentSize.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <zstd.h>
+#if ZSTD_VERSION_NUMBER < 10300
+#error "need zstd 1.3.0 or better"
+#endif
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_header_zstd_h=yes
+else
+ gcc_cv_header_zstd_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_zstd_h" >&5
+$as_echo "$gcc_cv_header_zstd_h" >&6; }
+if test $gcc_cv_header_zstd_h = yes; then
+
+$as_echo "#define HAVE_ZSTD_H 1" >>confdefs.h
+
+elif test "x$with_zstd" != x; then
+ as_fn_error $? "Unable to find zstd.h. See config.log for details." "$LINENO" 5
+fi
+
+# LTO can use zstd compression algorithm
+save_LIBS="$LIBS"
+LIBS=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ZSTD_compress" >&5
+$as_echo_n "checking for library containing ZSTD_compress... " >&6; }
+if ${ac_cv_search_ZSTD_compress+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ZSTD_compress ();
+int
+main ()
+{
+return ZSTD_compress ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' zstd; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_ZSTD_compress=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_ZSTD_compress+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_ZSTD_compress+:} false; then :
+
+else
+ ac_cv_search_ZSTD_compress=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ZSTD_compress" >&5
+$as_echo "$ac_cv_search_ZSTD_compress" >&6; }
+ac_res=$ac_cv_search_ZSTD_compress
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+ZSTD_LIB="$LIBS"
+LIBS="$save_LIBS"
+
+fi
+
+
+
+for ac_func in times clock kill getrlimit setrlimit atoq \
+ popen sysconf strsignal getrusage nl_langinfo \
+ gettimeofday mbstowcs wcswidth mmap posix_fallocate setlocale \
+ clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked madvise mallinfo mallinfo2 fstatat
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+if test x$ac_cv_func_mbstowcs = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mbstowcs works" >&5
+$as_echo_n "checking whether mbstowcs works... " >&6; }
+if ${gcc_cv_func_mbstowcs_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ gcc_cv_func_mbstowcs_works=yes
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+int main()
+{
+ mbstowcs(0, "", 0);
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ gcc_cv_func_mbstowcs_works=yes
+else
+ gcc_cv_func_mbstowcs_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mbstowcs_works" >&5
+$as_echo "$gcc_cv_func_mbstowcs_works" >&6; }
+ if test x$gcc_cv_func_mbstowcs_works = xyes; then
+
+$as_echo "#define HAVE_WORKING_MBSTOWCS 1" >>confdefs.h
+
+ fi
+fi
+
+ac_fn_cxx_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+ac_fn_cxx_check_type "$LINENO" "caddr_t" "ac_cv_type_caddr_t" "$ac_includes_default"
+if test "x$ac_cv_type_caddr_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define caddr_t char *
+_ACEOF
+
+fi
+
+ac_fn_cxx_check_type "$LINENO" "sighander_t" "ac_cv_type_sighander_t" "signal.h
+"
+if test "x$ac_cv_type_sighander_t" = xyes; then :
+
+$as_echo "#define HAVE_SIGHANDLER_T 1" >>confdefs.h
+
+fi
+
+
+
+ac_fn_cxx_check_header_preproc "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h"
+if test "x$ac_cv_header_sys_mman_h" = xyes; then :
+ gcc_header_sys_mman_h=yes
+else
+ gcc_header_sys_mman_h=no
+fi
+
+ac_fn_cxx_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = xyes; then :
+ gcc_func_mmap=yes
+else
+ gcc_func_mmap=no
+fi
+
+if test "$gcc_header_sys_mman_h" != yes \
+ || test "$gcc_func_mmap" != yes; then
+ gcc_cv_func_mmap_file=no
+ gcc_cv_func_mmap_dev_zero=no
+ gcc_cv_func_mmap_anon=no
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether read-only mmap of a plain file works" >&5
+$as_echo_n "checking whether read-only mmap of a plain file works... " >&6; }
+if ${gcc_cv_func_mmap_file+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Add a system to this blacklist if
+ # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+ # memory area containing the same data that you'd get if you applied
+ # read() to the same fd. The only system known to have a problem here
+ # is VMS, where text files have record structure.
+ case "$host_os" in
+ *vms* | ultrix*)
+ gcc_cv_func_mmap_file=no ;;
+ *)
+ gcc_cv_func_mmap_file=yes;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_file" >&5
+$as_echo "$gcc_cv_func_mmap_file" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap from /dev/zero works" >&5
+$as_echo_n "checking whether mmap from /dev/zero works... " >&6; }
+if ${gcc_cv_func_mmap_dev_zero+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Add a system to this blacklist if it has mmap() but /dev/zero
+ # does not exist, or if mmapping /dev/zero does not give anonymous
+ # zeroed pages with both the following properties:
+ # 1. If you map N consecutive pages in with one call, and then
+ # unmap any subset of those pages, the pages that were not
+ # explicitly unmapped remain accessible.
+ # 2. If you map two adjacent blocks of memory and then unmap them
+ # both at once, they must both go away.
+ # Systems known to be in this category are Windows (all variants),
+ # VMS, and Darwin.
+ case "$host_os" in
+ *vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+ gcc_cv_func_mmap_dev_zero=no ;;
+ *)
+ gcc_cv_func_mmap_dev_zero=yes;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_dev_zero" >&5
+$as_echo "$gcc_cv_func_mmap_dev_zero" >&6; }
+
+ # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAP_ANON(YMOUS)" >&5
+$as_echo_n "checking for MAP_ANON(YMOUS)... " >&6; }
+if ${gcc_cv_decl_map_anon+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+int
+main ()
+{
+int n = MAP_ANONYMOUS;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_decl_map_anon=yes
+else
+ gcc_cv_decl_map_anon=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_decl_map_anon" >&5
+$as_echo "$gcc_cv_decl_map_anon" >&6; }
+
+ if test $gcc_cv_decl_map_anon = no; then
+ gcc_cv_func_mmap_anon=no
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap with MAP_ANON(YMOUS) works" >&5
+$as_echo_n "checking whether mmap with MAP_ANON(YMOUS) works... " >&6; }
+if ${gcc_cv_func_mmap_anon+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Add a system to this blacklist if it has mmap() and MAP_ANON or
+ # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+ # doesn't give anonymous zeroed pages with the same properties listed
+ # above for use of /dev/zero.
+ # Systems known to be in this category are Windows, VMS, and SCO Unix.
+ case "$host_os" in
+ *vms* | cygwin* | pe | mingw* | sco* | udk* )
+ gcc_cv_func_mmap_anon=no ;;
+ *)
+ gcc_cv_func_mmap_anon=yes;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_anon" >&5
+$as_echo "$gcc_cv_func_mmap_anon" >&6; }
+ fi
+fi
+
+if test $gcc_cv_func_mmap_file = yes; then
+
+$as_echo "#define HAVE_MMAP_FILE 1" >>confdefs.h
+
+fi
+if test $gcc_cv_func_mmap_dev_zero = yes; then
+
+$as_echo "#define HAVE_MMAP_DEV_ZERO 1" >>confdefs.h
+
+fi
+if test $gcc_cv_func_mmap_anon = yes; then
+
+$as_echo "#define HAVE_MMAP_ANON 1" >>confdefs.h
+
+fi
+
+
+case "${host}" in
+*-*-*vms*)
+ # Under VMS, vfork works very differently than on Unix. The standard test
+ # won't work, and it isn't easily adaptable. It makes more sense to
+ # just force it.
+ ac_cv_func_vfork_works=yes
+ ;;
+esac
+ac_fn_cxx_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+for ac_header in vfork.h
+do :
+ ac_fn_cxx_check_header_preproc "$LINENO" "vfork.h" "ac_cv_header_vfork_h"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+done
+
+for ac_func in fork vfork
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_fork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* By Ruediger Kuhlmann. */
+ return fork () < 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ ac_cv_func_fork_works=yes
+else
+ ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+ ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+ case $host in
+ *-*-amigaos* | *-*-msdosdjgpp*)
+ # Override, as these systems have only a dummy fork() stub
+ ac_cv_func_fork_works=no
+ ;;
+ *)
+ ac_cv_func_fork_works=yes
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_vfork_works=cross
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Thanks to Paul Eggert for this test. */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent. The compiler
+ is told about this with #include <vfork.h>, but some compilers
+ (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
+ static variable whose address is put into a register that is
+ clobbered by the vfork. */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+
+int
+main ()
+{
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test (0);
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems. This
+ test uses lots of local variables, at least as many local
+ variables as main has allocated so far including compiler
+ temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
+ 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
+ reuse the register of parent for one of the local variables,
+ since it will think that parent can't possibly be used any more
+ in this routine. Assigning to the local variable will thus
+ munge parent in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+ from child file descriptors. If the child closes a descriptor
+ before it execs or exits, this munges the parent's descriptor
+ as well. Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ return (
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ ac_cv_func_vfork_works=yes
+else
+ ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+ ac_cv_func_vfork_works=$ac_cv_func_vfork
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+
+
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by GCC" >&5
+$as_echo_n "checking for ld used by GCC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | [A-Za-z]:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${acl_cv_path_LD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${acl_cv_prog_gnu_ld+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ acl_cv_prog_gnu_ld=yes
+else
+ acl_cv_prog_gnu_ld=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_prog_gnu_ld" >&5
+$as_echo "$acl_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$acl_cv_prog_gnu_ld
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared library run path origin" >&5
+$as_echo_n "checking for shared library run path origin... " >&6; }
+if ${acl_cv_rpath+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acl_cv_rpath" >&5
+$as_echo "$acl_cv_rpath" >&6; }
+ wl="$acl_cv_wl"
+ libext="$acl_cv_libext"
+ shlibext="$acl_cv_shlibext"
+ hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ hardcode_direct="$acl_cv_hardcode_direct"
+ hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ # Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then :
+ enableval=$enable_rpath; :
+else
+ enable_rpath=yes
+fi
+
+
+
+
+
+
+
+
+ use_additional=yes
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+
+# Check whether --with-libiconv-prefix was given.
+if test "${with_libiconv_prefix+set}" = set; then :
+ withval=$with_libiconv_prefix;
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/lib"
+ fi
+ fi
+
+fi
+
+
+# Check whether --with-libiconv-type was given.
+if test "${with_libiconv_type+set}" = set; then :
+ withval=$with_libiconv_type; with_libiconv_type=$withval
+else
+ with_libiconv_type=auto
+fi
+
+ lib_type=`eval echo \$with_libiconv_type`
+
+ LIBICONV=
+ LTLIBICONV=
+ INCICONV=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='iconv '
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value"
+ else
+ :
+ fi
+ else
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ if test $use_additional = yes; then
+ if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext" && test x$lib_type != xstatic; then
+ found_dir="$additional_libdir"
+ found_so="$additional_libdir/lib$name.$shlibext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ elif test x$lib_type != xshared; then
+ if test -f "$additional_libdir/lib$name.$libext"; then
+ found_dir="$additional_libdir"
+ found_a="$additional_libdir/lib$name.$libext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext" && test x$lib_type != xstatic; then
+ found_dir="$dir"
+ found_so="$dir/lib$name.$shlibext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ elif test x$lib_type != xshared; then
+ if test -f "$dir/lib$name.$libext"; then
+ found_dir="$dir"
+ found_a="$dir/lib$name.$libext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ if test "$hardcode_direct" = yes; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir"
+ fi
+ if test "$hardcode_minus_L" != no; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name"
+ fi
+ fi
+ additional_includedir=
+ case "$found_dir" in
+ */lib | */lib/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INCICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ if test -n "$found_la"; then
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ if test "X$additional_libdir" != "X/usr/lib"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/lib"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIBICONV; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$dep"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ if test "x$lib_type" = "xauto" || test "x$lib_type" = "xshared"; then
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name"
+ else
+ LIBICONV="${LIBICONV}${LIBICONV:+ }-l:lib$name.$libext"
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l:lib$name.$libext"
+ fi
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$hardcode_libdir_separator"; then
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ else
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIBICONV="${LIBICONV}${LIBICONV:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ for found_dir in $ltrpathdirs; do
+ LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir"
+ done
+ fi
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5
+$as_echo_n "checking for iconv... " >&6; }
+if ${am_cv_func_iconv+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ am_save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $INCICONV"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ am_cv_func_iconv=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CPPFLAGS="$am_save_CPPFLAGS"
+
+ if test "$am_cv_func_iconv" != yes && test -d ../libiconv; then
+ for _libs in .libs _libs; do
+ am_save_CPPFLAGS="$CPPFLAGS"
+ am_save_LIBS="$LIBS"
+ CPPFLAGS="$CPPFLAGS -I../libiconv/include"
+ LIBS="$LIBS ../libiconv/lib/$_libs/libiconv.a"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ INCICONV="-I../libiconv/include"
+ LIBICONV='${top_builddir}'/../libiconv/lib/$_libs/libiconv.a
+ LTLIBICONV='${top_builddir}'/../libiconv/lib/libiconv.la
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBS="$am_save_LIBS"
+ if test "$am_cv_func_iconv" = "yes"; then
+ break
+ fi
+ done
+ fi
+
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_CPPFLAGS="$CPPFLAGS"
+ am_save_LIBS="$LIBS"
+ CPPFLAGS="$CPPFLAGS $INCICONV"
+ LIBS="$LIBS $LIBICONV"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBS="$am_save_LIBS"
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5
+$as_echo "$am_cv_func_iconv" >&6; }
+ if test "$am_cv_func_iconv" = yes; then
+
+$as_echo "#define HAVE_ICONV 1" >>confdefs.h
+
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+
+ for element in $INCICONV; do
+ haveit=
+ for x in $CPPFLAGS; do
+
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ eval x=\"$x\"
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element"
+ fi
+ done
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5
+$as_echo_n "checking how to link with libiconv... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5
+$as_echo "$LIBICONV" >&6; }
+ else
+ LIBICONV=
+ LTLIBICONV=
+ fi
+
+
+
+ if test "$am_cv_func_iconv" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5
+$as_echo_n "checking for iconv declaration... " >&6; }
+ if ${am_cv_proto_iconv+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ am_cv_proto_iconv_arg1=""
+else
+ am_cv_proto_iconv_arg1="const"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"
+fi
+
+ am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_t:-
+ }$am_cv_proto_iconv" >&5
+$as_echo "${ac_t:-
+ }$am_cv_proto_iconv" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $am_cv_proto_iconv_arg1
+_ACEOF
+
+ fi
+
+
+# Until we have in-tree GNU iconv:
+LIBICONV_DEP=
+if test -f "$LTLIBICONV"; then
+ LIBICONV_DEP=$LTLIBICONV
+fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5
+$as_echo_n "checking for LC_MESSAGES... " >&6; }
+if ${am_cv_val_LC_MESSAGES+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <locale.h>
+int
+main ()
+{
+return LC_MESSAGES
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ am_cv_val_LC_MESSAGES=yes
+else
+ am_cv_val_LC_MESSAGES=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5
+$as_echo "$am_cv_val_LC_MESSAGES" >&6; }
+ if test $am_cv_val_LC_MESSAGES = yes; then
+
+$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h
+
+ fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_langinfo and CODESET" >&5
+$as_echo_n "checking for nl_langinfo and CODESET... " >&6; }
+if ${am_cv_langinfo_codeset+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <langinfo.h>
+int
+main ()
+{
+char* cs = nl_langinfo(CODESET);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ am_cv_langinfo_codeset=yes
+else
+ am_cv_langinfo_codeset=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_langinfo_codeset" >&5
+$as_echo "$am_cv_langinfo_codeset" >&6; }
+ if test $am_cv_langinfo_codeset = yes; then
+
+$as_echo "#define HAVE_LANGINFO_CODESET 1" >>confdefs.h
+
+ fi
+
+
+# We will need to find libiberty.h and ansidecl.h
+saved_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include $GMPINC -I${top_srcdir}/../../sdbinutils/include"
+saved_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include $GMPINC -I${srcdir}/../../sdbinutils/include"
+
+# gcc_AC_CHECK_DECLS doesn't support overloaded functions, so use the
+# normal autoconf function for these. But force definition of
+# HAVE_DECL_BASENAME like gcc_AC_CHECK_DECLS does, to suppress the bizarre
+# basename handling in libiberty.h.
+as_ac_Symbol=`$as_echo "ac_cv_have_decl_basename(const char*)" | $as_tr_sh`
+ac_fn_cxx_check_decl "$LINENO" "basename(const char*)" "$as_ac_Symbol" "
+#undef HAVE_DECL_BASENAME
+#define HAVE_DECL_BASENAME 1
+#include \"ansidecl.h\"
+#include \"system.h\"
+"
+if eval test \"x\$"$as_ac_Symbol"\" = x"yes"; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_BASENAME $ac_have_decl
+_ACEOF
+as_ac_Symbol=`$as_echo "ac_cv_have_decl_strstr(const char*,const char*)" | $as_tr_sh`
+ac_fn_cxx_check_decl "$LINENO" "strstr(const char*,const char*)" "$as_ac_Symbol" "
+#undef HAVE_DECL_BASENAME
+#define HAVE_DECL_BASENAME 1
+#include \"ansidecl.h\"
+#include \"system.h\"
+"
+if eval test \"x\$"$as_ac_Symbol"\" = x"yes"; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRSTR $ac_have_decl
+_ACEOF
+
+
+for ac_func in getenv atol atoll asprintf sbrk abort atof getcwd getwd \
+ madvise stpcpy strnlen strsignal strverscmp \
+ strtol strtoul strtoll strtoull setenv unsetenv \
+ errno snprintf vsnprintf vasprintf malloc realloc calloc \
+ free getopt clock getpagesize ffs clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if eval \${gcc_cv_have_decl_$ac_func+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+#include "ansidecl.h"
+#include "system.h"
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in getrlimit setrlimit getrusage
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if eval \${gcc_cv_have_decl_$ac_func+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in mallinfo mallinfo2
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if eval \${gcc_cv_have_decl_$ac_func+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+int
+main ()
+{
+rlim_t l = 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+
+$as_echo "#define rlim_t long" >>confdefs.h
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+# On AIX 5.2, <ldfcn.h> conflicts with <fcntl.h>, as both define incompatible
+# FREAD and FWRITE macros. Fortunately, for GCC's single usage of ldgetname
+# in collect2.cc, <fcntl.h> isn't visible, but the configure test below needs
+# to undef these macros to get the correct value for HAVE_DECL_LDGETNAME.
+for ac_func in ldgetname
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if eval \${gcc_cv_have_decl_$ac_func+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_LDFCN_H
+#undef FREAD
+#undef FWRITE
+#include <ldfcn.h>
+#endif
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in times
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if eval \${gcc_cv_have_decl_$ac_func+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+for ac_func in sigaltstack
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if eval \${gcc_cv_have_decl_$ac_func+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+#include "ansidecl.h"
+#include "system.h"
+#include <signal.h>
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+# More time-related stuff.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct tms" >&5
+$as_echo_n "checking for struct tms... " >&6; }
+if ${ac_cv_struct_tms+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
+
+int
+main ()
+{
+struct tms tms;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_struct_tms=yes
+else
+ ac_cv_struct_tms=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tms" >&5
+$as_echo "$ac_cv_struct_tms" >&6; }
+if test $ac_cv_struct_tms = yes; then
+
+$as_echo "#define HAVE_STRUCT_TMS 1" >>confdefs.h
+
+fi
+
+# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE.
+# revisit after autoconf 2.50.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_t" >&5
+$as_echo_n "checking for clock_t... " >&6; }
+if ${gcc_cv_type_clock_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include "ansidecl.h"
+#include "system.h"
+
+int
+main ()
+{
+clock_t x;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_type_clock_t=yes
+else
+ gcc_cv_type_clock_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_type_clock_t" >&5
+$as_echo "$gcc_cv_type_clock_t" >&6; }
+if test $gcc_cv_type_clock_t = yes; then
+
+$as_echo "#define HAVE_CLOCK_T 1" >>confdefs.h
+
+fi
+
+# Check if F_SETLKW is supported by fcntl.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for F_SETLKW" >&5
+$as_echo_n "checking for F_SETLKW... " >&6; }
+if ${ac_cv_f_setlkw+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <fcntl.h>
+int
+main ()
+{
+
+struct flock fl;
+fl.l_whence = 0;
+fl.l_start = 0;
+fl.l_len = 0;
+fl.l_pid = 0;
+return fcntl (1, F_SETLKW, &fl);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_f_setlkw=yes
+else
+ ac_cv_f_setlkw=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f_setlkw" >&5
+$as_echo "$ac_cv_f_setlkw" >&6; }
+if test $ac_cv_f_setlkw = yes; then
+
+$as_echo "#define HOST_HAS_F_SETLKW 1" >>confdefs.h
+
+fi
+
+# Check if O_CLOEXEC is defined by fcntl
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for O_CLOEXEC" >&5
+$as_echo_n "checking for O_CLOEXEC... " >&6; }
+if ${ac_cv_o_cloexec+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <fcntl.h>
+int
+main ()
+{
+
+return open ("/dev/null", O_RDONLY | O_CLOEXEC);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_o_cloexec=yes
+else
+ ac_cv_o_cloexec=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_o_cloexec" >&5
+$as_echo "$ac_cv_o_cloexec" >&6; }
+if test $ac_cv_o_cloexec = yes; then
+
+$as_echo "#define HOST_HAS_O_CLOEXEC 1" >>confdefs.h
+
+fi
+
+# C++ Modules would like some networking features to provide the mapping
+# server. You can still use modules without them though.
+# The following network-related checks could probably do with some
+# Windows and other non-linux defenses and checking.
+
+# Local socket connectivity wants AF_UNIX networking
+# Check for AF_UNIX networking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AF_UNIX" >&5
+$as_echo_n "checking for AF_UNIX... " >&6; }
+if ${ac_cv_af_unix+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+int
+main ()
+{
+
+sockaddr_un un;
+un.sun_family = AF_UNSPEC;
+int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&un, sizeof (un));
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_af_unix=yes
+else
+ ac_cv_af_unix=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_af_unix" >&5
+$as_echo "$ac_cv_af_unix" >&6; }
+if test $ac_cv_af_unix = yes; then
+
+$as_echo "#define HAVE_AF_UNIX 1" >>confdefs.h
+
+fi
+
+# Remote socket connectivity wants AF_INET6 networking
+# Check for AF_INET6 networking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for AF_INET6" >&5
+$as_echo_n "checking for AF_INET6... " >&6; }
+if ${ac_cv_af_inet6+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+int
+main ()
+{
+
+sockaddr_in6 in6;
+in6.sin6_family = AF_UNSPEC;
+struct addrinfo *addrs = 0;
+struct addrinfo hints;
+hints.ai_flags = 0;
+hints.ai_family = AF_INET6;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_protocol = 0;
+hints.ai_canonname = 0;
+hints.ai_addr = 0;
+hints.ai_next = 0;
+int e = getaddrinfo ("localhost", 0, &hints, &addrs);
+const char *str = gai_strerror (e);
+freeaddrinfo (addrs);
+int fd = socket (AF_INET6, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&in6, sizeof (in6));
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_af_inet6=yes
+else
+ ac_cv_af_inet6=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_af_inet6" >&5
+$as_echo "$ac_cv_af_inet6" >&6; }
+if test $ac_cv_af_inet6 = yes; then
+
+$as_echo "#define HAVE_AF_INET6 1" >>confdefs.h
+
+fi
+
+# Check if _LK_LOCK is supported by _locking
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LK_LOCK" >&5
+$as_echo_n "checking for _LK_LOCK... " >&6; }
+if ${ac_cv_lk_lock+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <io.h>
+#include <sys/locking.h>
+int
+main ()
+{
+
+ int fd;
+ return _locking (fd, _LK_LOCK, 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_lk_lock=yes
+else
+ ac_cv_lk_lock=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lk_lock" >&5
+$as_echo "$ac_cv_lk_lock" >&6; }
+if test $ac_cv_lk_lock = yes; then
+
+$as_echo "#define HOST_HAS_LK_LOCK 1" >>confdefs.h
+
+fi
+
+# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
+CFLAGS="$saved_CFLAGS"
+CXXFLAGS="$saved_CXXFLAGS"
+
+# mkdir takes a single argument on some systems.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if mkdir takes one argument" >&5
+$as_echo_n "checking if mkdir takes one argument... " >&6; }
+if ${gcc_cv_mkdir_takes_one_arg+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif
+int
+main ()
+{
+mkdir ("foo", 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_mkdir_takes_one_arg=no
+else
+ gcc_cv_mkdir_takes_one_arg=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_mkdir_takes_one_arg" >&5
+$as_echo "$gcc_cv_mkdir_takes_one_arg" >&6; }
+if test $gcc_cv_mkdir_takes_one_arg = yes ; then
+
+$as_echo "#define MKDIR_TAKES_ONE_ARG 1" >>confdefs.h
+
+fi
+
+
+# File extensions
+manext='.1'
+objext='.o'
+
+
+
+# With Setjmp/Longjmp based exception handling.
+# 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
+ ;;
+ *)
+ force_sjlj_exceptions=no
+ ;;
+esac
+fi
+
+if test $force_sjlj_exceptions = yes; then
+ sjlj=`if test $enableval = yes; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define CONFIG_SJLJ_EXCEPTIONS $sjlj
+_ACEOF
+
+fi
+
+# --------------------------------------------------------
+# Build, host, and target specific configuration fragments
+# --------------------------------------------------------
+
+# Collect build-machine-specific information.
+. ${srcdir}/config.build || exit 1
+
+# Collect host-machine-specific information.
+. ${srcdir}/config.host || exit 1
+
+target_gtfiles=
+
+# Collect target-machine-specific information.
+. ${srcdir}/config.gcc || exit 1
+
+extra_objs="${host_extra_objs} ${extra_objs}"
+extra_gcc_objs="${host_extra_gcc_objs} ${extra_gcc_objs}"
+
+# Default the target-machine variables that were not explicitly set.
+if test x"$tm_file" = x
+then tm_file=$cpu_type/$cpu_type.h; fi
+
+if test x"$extra_headers" = x
+then extra_headers=; fi
+
+if test x$md_file = x
+then md_file=$cpu_type/$cpu_type.md; fi
+
+if test x$out_file = x
+then out_file=$cpu_type/$cpu_type.cc; fi
+
+if test x"$tmake_file" = x
+then tmake_file=$cpu_type/t-$cpu_type
+fi
+
+# Support --enable-initfini-array.
+if test x$enable_initfini_array != xno; then
+ tm_file="${tm_file} initfini-array.h"
+fi
+
+if test x"$dwarf2" = xyes
+then tm_file="$tm_file tm-dwarf2.h"
+fi
+
+# Say what files are being used for the output code and MD file.
+echo "Using \`$srcdir/config/$out_file' for machine-specific logic."
+echo "Using \`$srcdir/config/$md_file' as machine description file."
+
+# If any of the xm_file variables contain nonexistent files, warn
+# about them and drop them.
+
+bx=
+for x in $build_xm_file; do
+ if test -f $srcdir/config/$x
+ then bx="$bx $x"
+ else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $srcdir/config/$x does not exist." >&5
+$as_echo "$as_me: WARNING: $srcdir/config/$x does not exist." >&2;}
+ fi
+done
+build_xm_file="$bx"
+
+hx=
+for x in $host_xm_file; do
+ if test -f $srcdir/config/$x
+ then hx="$hx $x"
+ else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $srcdir/config/$x does not exist." >&5
+$as_echo "$as_me: WARNING: $srcdir/config/$x does not exist." >&2;}
+ fi
+done
+host_xm_file="$hx"
+
+tx=
+for x in $xm_file; do
+ if test -f $srcdir/config/$x
+ then tx="$tx $x"
+ else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $srcdir/config/$x does not exist." >&5
+$as_echo "$as_me: WARNING: $srcdir/config/$x does not exist." >&2;}
+ fi
+done
+xm_file="$tx"
+
+count=a
+for f in $tm_file; do
+ count=${count}x
+done
+if test $count = ax; then
+ echo "Using \`$srcdir/config/$tm_file' as target machine macro file."
+else
+ echo "Using the following target machine macro files:"
+ for f in $tm_file; do
+ echo " $srcdir/config/$f"
+ done
+fi
+
+if test x$use_long_long_for_widest_fast_int = xyes; then
+
+$as_echo "#define USE_LONG_LONG_FOR_WIDEST_FAST_INT 1" >>confdefs.h
+
+fi
+
+gnu_ld_bool=`if test x"$gnu_ld" = x"yes"; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GNU_LD $gnu_ld_bool
+_ACEOF
+
+
+gnu_as_bool=`if test x"$gas" = x"yes"; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GNU_AS $gnu_as_bool
+_ACEOF
+
+
+count=a
+for f in $host_xm_file; do
+ count=${count}x
+done
+if test $count = a; then
+ :
+elif test $count = ax; then
+ echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file."
+else
+ echo "Using the following host machine macro files:"
+ for f in $host_xm_file; do
+ echo " $srcdir/config/$f"
+ done
+fi
+echo "Using ${out_host_hook_obj} for host machine hooks."
+
+if test "$host_xm_file" != "$build_xm_file"; then
+ count=a
+ for f in $build_xm_file; do
+ count=${count}x
+ done
+ if test $count = a; then
+ :
+ elif test $count = ax; then
+ echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file."
+ else
+ echo "Using the following build machine macro files:"
+ for f in $build_xm_file; do
+ echo " $srcdir/config/$f"
+ done
+ fi
+fi
+
+if test -n "$configured_native_system_header_dir"; then
+ native_system_header_dir=$configured_native_system_header_dir
+fi
+NATIVE_SYSTEM_HEADER_DIR="$native_system_header_dir"
+
+
+case ${host} in
+ powerpc*-*-darwin*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mcontext_t fields have underscores" >&5
+$as_echo_n "checking whether mcontext_t fields have underscores... " >&6; }
+if ${gcc_cv_mcontext_underscores+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/cdefs.h>
+#include <sys/signal.h>
+#include <ucontext.h>
+int main() { mcontext_t m; if (m->ss.srr0) return 0; return 0; }
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_mcontext_underscores=no
+else
+ gcc_cv_mcontext_underscores=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_mcontext_underscores" >&5
+$as_echo "$gcc_cv_mcontext_underscores" >&6; }
+ if test $gcc_cv_mcontext_underscores = yes; then
+
+$as_echo "#define HAS_MCONTEXT_T_UNDERSCORES /**/" >>confdefs.h
+
+ fi
+ ;;
+esac
+
+# ---------
+# Threading
+# ---------
+
+# Check if a valid thread package
+case ${enable_threads} in
+ "" | no)
+ # No threads
+ target_thread_file='single'
+ ;;
+ yes)
+ # default
+ target_thread_file='single'
+ ;;
+ aix | dce | lynx | mipssde | posix | rtems | \
+ single | tpf | vxworks | win32)
+ target_thread_file=${enable_threads}
+ ;;
+ *)
+ echo "${enable_threads} is an unknown thread package" 1>&2
+ exit 1
+ ;;
+esac
+
+if test x${thread_file} = x; then
+ # No thread file set by target-specific clauses in config.gcc,
+ # so use file chosen by default logic above
+ thread_file=${target_thread_file}
+fi
+
+# --------
+# UNSORTED
+# --------
+
+use_cxa_atexit=no
+if test x$enable___cxa_atexit = xyes || \
+ test x$enable___cxa_atexit = x -a x$default_use_cxa_atexit = xyes; then
+ if test x$host = x$target; then
+ case $host in
+ # mingw32 doesn't have __cxa_atexit but uses atexit registration
+ # keyed to flag_use_cxa_atexit
+ *-*-mingw32*)
+ use_cxa_atexit=yes
+ ;;
+ powerpc-ibm-aix*)
+ use_cxa_atexit=yes
+ ;;
+ *)
+ ac_fn_cxx_check_func "$LINENO" "__cxa_atexit" "ac_cv_func___cxa_atexit"
+if test "x$ac_cv_func___cxa_atexit" = xyes; then :
+ use_cxa_atexit=yes
+else
+ echo "__cxa_atexit can't be enabled on this target"
+fi
+
+ ;;
+ esac
+ else
+ # We can't check for __cxa_atexit when building a cross, so assume
+ # it is available
+ use_cxa_atexit=yes
+ fi
+ if test x$use_cxa_atexit = xyes; then
+
+$as_echo "#define DEFAULT_USE_CXA_ATEXIT 2" >>confdefs.h
+
+ fi
+fi
+
+# Look for a file containing extra machine modes.
+if test -n "$extra_modes" && test -f $srcdir/config/$extra_modes; then
+ extra_modes_file='$(srcdir)'/config/${extra_modes}
+
+
+cat >>confdefs.h <<_ACEOF
+#define EXTRA_MODES_FILE "config/$extra_modes"
+_ACEOF
+
+fi
+
+# Convert extra_options into a form suitable for Makefile use.
+extra_opt_files=
+all_opt_files=
+for f in $extra_options; do
+ extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+ all_opt_files="$all_opt_files $srcdir/config/$f"
+done
+
+
+# auto-host.h is the file containing items generated by autoconf and is
+# the first file included by config.h.
+# If host=build, it is correct to have bconfig include auto-host.h
+# as well. If host!=build, we are in error and need to do more
+# work to find out the build config parameters.
+if test x$host = x$build
+then
+ build_auto=auto-host.h
+ HAVE_AUTO_BUILD='# '
+else
+ # We create a subdir, then run autoconf in the subdir.
+ # To prevent recursion we set host and build for the new
+ # invocation of configure to the build for this invocation
+ # of configure.
+ tempdir=build.$$
+ rm -rf $tempdir
+ mkdir $tempdir
+ cd $tempdir
+ case ${srcdir} in
+ /* | A-Za-z:\\/* ) realsrcdir=${srcdir};;
+ *) realsrcdir=../${srcdir};;
+ esac
+ # Clearing GMPINC is necessary to prevent host headers being
+ # used by the build compiler. Defining GENERATOR_FILE stops
+ # system.h from including gmp.h.
+ CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \
+ CXX="${CXX_FOR_BUILD}" CXXFLAGS="${CXXFLAGS_FOR_BUILD}" \
+ LD="${LD_FOR_BUILD}" LDFLAGS="${LDFLAGS_FOR_BUILD}" \
+ GMPINC="" CPPFLAGS="${CPPFLAGS_FOR_BUILD} -DGENERATOR_FILE" \
+ ${realsrcdir}/configure \
+ --enable-languages=${enable_languages-all} \
+ ${enable_obsolete+--enable-obsolete="$enable_obsolete"} \
+ ${enable_option_checking+--enable-option-checking="$enable_option_checking"} \
+ --target=$target_alias --host=$build_alias \
+ --build=$build_alias || exit # retaining $tempdir
+
+ # We just finished tests for the build machine, so rename
+ # the file auto-build.h in the gcc directory.
+ mv auto-host.h ../auto-build.h
+ cd ..
+ rm -rf $tempdir
+ build_auto=auto-build.h
+ HAVE_AUTO_BUILD=
+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.
+# put this back in temporarily.
+xm_file="auto-host.h ansidecl.h ${xm_file}"
+
+# --------
+# UNSORTED
+# --------
+
+# Compile in configure arguments.
+if test -f configargs.h ; then
+ # Being re-configured.
+ gcc_config_arguments=`grep configuration_arguments configargs.h | sed -e 's/.*"\([^"]*\)".*/\1/'`
+ gcc_reconf_arguments=`echo "$gcc_config_arguments" | sed -e 's/^.*\( : (reconfigured) .*$\)/\1/'`
+ if [ "$gcc_reconf_arguments" != " : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" ]; then
+ gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS"
+ fi
+else
+ gcc_config_arguments="$TOPLEVEL_CONFIGURE_ARGUMENTS"
+fi
+
+# Double all backslashes and backslash all quotes to turn
+# gcc_config_arguments into a C string.
+sed -e 's/\\/\\\\/g; s/"/\\"/g' <<EOF >conftest.out
+$gcc_config_arguments
+EOF
+gcc_config_arguments_str=`cat conftest.out`
+rm -f conftest.out
+
+cat > configargs.h <<EOF
+/* Generated automatically. */
+static const char configuration_arguments[] = "$gcc_config_arguments_str";
+static const char thread_model[] = "$thread_file";
+
+static const struct {
+ const char *name, *value;
+} configure_default_options[] = $configure_default_options;
+EOF
+
+gcc_BASEVER=`cat $srcdir/BASE-VER`
+gcc_DEVPHASE=`cat $srcdir/DEV-PHASE`
+gcc_DATESTAMP=`cat $srcdir/DATESTAMP`
+if test -f $srcdir/REVISION ; then
+ gcc_REVISION=`cat $srcdir/REVISION`
+else
+ gcc_REVISION=""
+fi
+cat > plugin-version.h <<EOF
+#include "configargs.h"
+
+#define GCCPLUGIN_VERSION_MAJOR `echo $gcc_BASEVER | sed -e 's/^\([0-9]*\).*$/\1/'`
+#define GCCPLUGIN_VERSION_MINOR `echo $gcc_BASEVER | sed -e 's/^[0-9]*\.\([0-9]*\).*$/\1/'`
+#define GCCPLUGIN_VERSION_PATCHLEVEL `echo $gcc_BASEVER | sed -e 's/^[0-9]*\.[0-9]*\.\([0-9]*\)$/\1/'`
+#define GCCPLUGIN_VERSION (GCCPLUGIN_VERSION_MAJOR*1000 + GCCPLUGIN_VERSION_MINOR)
+
+static char basever[] = "$gcc_BASEVER";
+static char datestamp[] = "$gcc_DATESTAMP";
+static char devphase[] = "$gcc_DEVPHASE";
+static char revision[] = "$gcc_REVISION";
+
+/* FIXME plugins: We should make the version information more precise.
+ One way to do is to add a checksum. */
+
+static struct plugin_gcc_version gcc_version = {basever, datestamp,
+ devphase, revision,
+ configuration_arguments};
+EOF
+
+# Determine what GCC version number to use in filesystem paths.
+
+ get_gcc_base_ver="cat"
+
+# Check whether --with-gcc-major-version-only was given.
+if test "${with_gcc_major_version_only+set}" = set; then :
+ withval=$with_gcc_major_version_only; if test x$with_gcc_major_version_only = xyes ; then
+ get_gcc_base_ver="sed -e 's/^\([0-9]*\).*/\1/'"
+ fi
+
+fi
+
+
+
+
+# Internationalization
+# If we haven't got the data from the intl directory,
+# assume NLS is disabled.
+USE_NLS=no
+LIBINTL=
+LIBINTL_DEP=
+INCINTL=
+XGETTEXT=
+GMSGFMT=
+POSUB=
+
+if test -f ../intl/config.intl; then
+ . ../intl/config.intl
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether NLS is requested" >&5
+$as_echo_n "checking whether NLS is requested... " >&6; }
+if test x"$USE_NLS" != xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define ENABLE_NLS 1" >>confdefs.h
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5
+$as_echo_n "checking for catalogs to be installed... " >&6; }
+ # Look for .po and .gmo files in the source directory.
+ CATALOGS=
+ XLINGUAS=
+ for cat in $srcdir/po/*.gmo $srcdir/po/*.po; do
+ # If there aren't any .gmo files the shell will give us the
+ # literal string "../path/to/srcdir/po/*.gmo" which has to be
+ # weeded out.
+ case "$cat" in *\**)
+ continue;;
+ esac
+ # The quadruple backslash is collapsed to a double backslash
+ # by the backticks, then collapsed again by the double quotes,
+ # leaving us with one backslash in the sed expression (right
+ # before the dot that mustn't act as a wildcard).
+ cat=`echo $cat | sed -e "s!$srcdir/po/!!" -e "s!\\\\.po!.gmo!"`
+ lang=`echo $cat | sed -e "s!\\\\.gmo!!"`
+ # The user is allowed to set LINGUAS to a list of languages to
+ # install catalogs for. If it's empty that means "all of them."
+ if test "x$LINGUAS" = x; then
+ CATALOGS="$CATALOGS $cat"
+ XLINGUAS="$XLINGUAS $lang"
+ else
+ case "$LINGUAS" in *$lang*)
+ CATALOGS="$CATALOGS $cat"
+ XLINGUAS="$XLINGUAS $lang"
+ ;;
+ esac
+ fi
+ done
+ LINGUAS="$XLINGUAS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5
+$as_echo "$LINGUAS" >&6; }
+
+
+ DATADIRNAME=share
+
+ INSTOBJEXT=.mo
+
+ GENCAT=gencat
+
+ CATOBJEXT=.gmo
+
+fi
+
+# If LIBINTL contains LIBICONV, then clear LIBICONV so we don't get
+# -liconv on the link line twice.
+case "$LIBINTL" in *$LIBICONV*)
+ LIBICONV= ;;
+esac
+
+# Check whether --enable-secureplt was given.
+if test "${enable_secureplt+set}" = set; then :
+ enableval=$enable_secureplt;
+fi
+
+
+# Check whether --enable-mingw-wildcard was given.
+if test "${enable_mingw_wildcard+set}" = set; then :
+ enableval=$enable_mingw_wildcard;
+else
+ enable_mingw_wildcard=platform
+fi
+
+if test x"$enable_mingw_wildcard" != xplatform ; then :
+
+cat >>confdefs.h <<_ACEOF
+#define MINGW_DOWILDCARD $(test x"$enable_mingw_wildcard" = xno; echo $?)
+_ACEOF
+
+fi
+
+# Check whether --enable-large-address-aware was given.
+if test "${enable_large_address_aware+set}" = set; then :
+ enableval=$enable_large_address_aware;
+fi
+
+if test x"$enable_large_address_aware" = xyes; then :
+
+$as_echo "#define MINGW_DEFAULT_LARGE_ADDR_AWARE 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-leading-mingw64-underscores was given.
+if test "${enable_leading_mingw64_underscores+set}" = set; then :
+ enableval=$enable_leading_mingw64_underscores;
+fi
+
+if test x"$enable_leading_mingw64_underscores" = xyes ; then :
+
+$as_echo "#define USE_MINGW64_LEADING_UNDERSCORES 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-cld was given.
+if test "${enable_cld+set}" = set; then :
+ enableval=$enable_cld;
+else
+ enable_cld=no
+fi
+
+
+# Check whether --enable-frame-pointer was given.
+if test "${enable_frame_pointer+set}" = set; then :
+ enableval=$enable_frame_pointer;
+else
+
+case $target_os in
+linux* | gnu* | darwin[8912]* | cygwin* | mingw*)
+ # Enable -fomit-frame-pointer by default for these systems with DWARF2.
+ enable_frame_pointer=no
+ ;;
+*)
+ enable_frame_pointer=yes
+ ;;
+esac
+
+fi
+
+
+case $target in
+i[34567]86-*-* | x86_64-*-*)
+ if test "x$enable_cld" = xyes; then
+ tm_defines="${tm_defines} USE_IX86_CLD=1"
+ fi
+ if test "x$enable_frame_pointer" = xyes; then
+ tm_defines="${tm_defines} USE_IX86_FRAME_POINTER=1"
+ fi
+ ;;
+esac
+
+# Windows32 Registry support for specifying GCC installation paths.
+# Check whether --enable-win32-registry was given.
+if test "${enable_win32_registry+set}" = set; then :
+ enableval=$enable_win32_registry;
+fi
+
+
+case $host_os in
+ win32 | pe | cygwin* | mingw32*)
+ if test "x$enable_win32_registry" != xno; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RegOpenKeyExA" >&5
+$as_echo_n "checking for library containing RegOpenKeyExA... " >&6; }
+if ${ac_cv_search_RegOpenKeyExA+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char RegOpenKeyExA ();
+int
+main ()
+{
+return RegOpenKeyExA ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' advapi32; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_cxx_try_link "$LINENO"; then :
+ ac_cv_search_RegOpenKeyExA=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_RegOpenKeyExA+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_RegOpenKeyExA+:} false; then :
+
+else
+ ac_cv_search_RegOpenKeyExA=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_RegOpenKeyExA" >&5
+$as_echo "$ac_cv_search_RegOpenKeyExA" >&6; }
+ac_res=$ac_cv_search_RegOpenKeyExA
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+else
+ enable_win32_registry=no
+fi
+
+ fi
+
+ if test "x$enable_win32_registry" != xno; then
+
+$as_echo "#define ENABLE_WIN32_REGISTRY 1" >>confdefs.h
+
+
+ if test "x$enable_win32_registry" != xyes \
+ && test "x$enable_win32_registry" != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define WIN32_REGISTRY_KEY "$enable_win32_registry"
+_ACEOF
+
+ fi
+ fi
+ ;;
+esac
+
+# Get an absolute path to the GCC top-level source directory
+holddir=`${PWDCMD-pwd}`
+cd $srcdir
+topdir=`${PWDCMD-pwd}`
+cd $holddir
+
+# Conditionalize the makefile for this host machine.
+xmake_file=
+for f in ${host_xmake_file}
+do
+ if test -f ${srcdir}/config/$f
+ then
+ xmake_file="${xmake_file} \$(srcdir)/config/$f"
+ fi
+done
+
+# Conditionalize the makefile for this target machine.
+tmake_file_=
+for f in ${tmake_file}
+do
+ if test -f ${srcdir}/config/$f
+ then
+ tmake_file_="${tmake_file_} \$(srcdir)/config/$f"
+ fi
+done
+tmake_file="${tmake_file_}${omp_device_property_tmake_file}"
+
+out_object_file=`basename $out_file .cc`.o
+common_out_file=default-common.cc
+common_out_object_file=`basename $common_out_file .cc`.o
+
+tm_file_list="options.h"
+tm_include_list="options.h insn-constants.h"
+for f in $tm_file; do
+ case $f in
+ ./* )
+ f=`echo $f | sed 's/^..//'`
+ tm_file_list="${tm_file_list} $f"
+ tm_include_list="${tm_include_list} $f"
+ ;;
+ defaults.h )
+ tm_file_list="${tm_file_list} \$(srcdir)/$f"
+ tm_include_list="${tm_include_list} $f"
+ ;;
+ * )
+ tm_file_list="${tm_file_list} \$(srcdir)/config/$f"
+ tm_include_list="${tm_include_list} config/$f"
+ ;;
+ esac
+done
+
+tm_p_file_list=
+tm_p_include_list=
+for f in $tm_p_file; do
+ case $f in
+ tm-preds.h )
+ tm_p_file_list="${tm_p_file_list} $f"
+ tm_p_include_list="${tm_p_include_list} $f"
+ ;;
+ * )
+ tm_p_file_list="${tm_p_file_list} \$(srcdir)/config/$f"
+ tm_p_include_list="${tm_p_include_list} config/$f"
+ esac
+done
+
+tm_d_file_list=
+tm_d_include_list="options.h insn-constants.h"
+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"
+ ;;
+ esac
+done
+
+xm_file_list=
+xm_include_list=
+for f in $xm_file; do
+ case $f in
+ ansidecl.h )
+ xm_file_list="${xm_file_list} \$(srcdir)/../include/$f"
+ xm_include_list="${xm_include_list} $f"
+ ;;
+ auto-host.h )
+ xm_file_list="${xm_file_list} $f"
+ xm_include_list="${xm_include_list} $f"
+ ;;
+ * )
+ xm_file_list="${xm_file_list} \$(srcdir)/config/$f"
+ xm_include_list="${xm_include_list} config/$f"
+ ;;
+ esac
+done
+
+host_xm_file_list=
+host_xm_include_list=
+for f in $host_xm_file; do
+ case $f in
+ ansidecl.h )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/../include/$f"
+ host_xm_include_list="${host_xm_include_list} $f"
+ ;;
+ auto-host.h )
+ host_xm_file_list="${host_xm_file_list} $f"
+ host_xm_include_list="${host_xm_include_list} $f"
+ ;;
+ * )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f"
+ host_xm_include_list="${host_xm_include_list} config/$f"
+ ;;
+ esac
+done
+
+build_xm_file_list=
+for f in $build_xm_file; do
+ case $f in
+ ansidecl.h )
+ build_xm_file_list="${build_xm_file_list} \$(srcdir)/../include/$f"
+ build_xm_include_list="${build_xm_include_list} $f"
+ ;;
+ auto-build.h | auto-host.h )
+ build_xm_file_list="${build_xm_file_list} $f"
+ build_xm_include_list="${build_xm_include_list} $f"
+ ;;
+ * )
+ build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f"
+ build_xm_include_list="${build_xm_include_list} config/$f"
+ ;;
+ esac
+done
+
+# Define macro CROSS_DIRECTORY_STRUCTURE in compilation if this is a
+# cross-compiler which does not use the native headers and libraries.
+# Also use all.cross instead of all.internal and adjust SYSTEM_HEADER_DIR.
+CROSS=
+ALL=all.internal
+SYSTEM_HEADER_DIR='$(NATIVE_SYSTEM_HEADER_DIR)'
+BUILD_SYSTEM_HEADER_DIR=$SYSTEM_HEADER_DIR
+
+if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x ||
+ test x$build != x$host || test "x$with_build_sysroot" != x; then
+ if test "x$with_build_sysroot" != x; then
+ BUILD_SYSTEM_HEADER_DIR=$with_build_sysroot'$${sysroot_headers_suffix}$(NATIVE_SYSTEM_HEADER_DIR)'
+ else
+ BUILD_SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ fi
+
+ if test x$host != x$target
+ then
+ CROSS="-DCROSS_DIRECTORY_STRUCTURE"
+ ALL=all.cross
+ SYSTEM_HEADER_DIR=$BUILD_SYSTEM_HEADER_DIR
+ elif test "x$TARGET_SYSTEM_ROOT" != x; then
+ SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ fi
+
+ if test "x$with_build_sysroot" != "x"; then
+ target_header_dir="${with_build_sysroot}${native_system_header_dir}"
+ elif test "x$with_sysroot" = x; then
+ target_header_dir="${test_exec_prefix}/${target_noncanonical}/sys-include"
+ elif test "x$with_sysroot" = xyes; then
+ target_header_dir="${test_exec_prefix}/${target_noncanonical}/sys-root${native_system_header_dir}"
+ else
+ target_header_dir="${with_sysroot}${native_system_header_dir}"
+ fi
+else
+ target_header_dir=${native_system_header_dir}
+fi
+
+# If this is a cross-compiler that does not
+# have its own set of headers then define
+# inhibit_libc
+
+# If this is using newlib, without having the headers available now,
+# then define inhibit_libc in LIBGCC2_CFLAGS.
+# This prevents libgcc2 from containing any code which requires libc
+# support.
+: ${inhibit_libc=false}
+if { { test x$host != x$target && test "x$with_sysroot" = x ; } ||
+ test x$with_newlib = xyes ; } &&
+ { test "x$with_headers" = xno || test ! -f "$target_header_dir/stdio.h"; } ; then
+ inhibit_libc=true
+fi
+
+
+# When building gcc with a cross-compiler, we need to adjust things so
+# that the generator programs are still built with the native compiler.
+# Also, we cannot run fixincludes.
+
+# These are the normal (build=host) settings:
+CC_FOR_BUILD='$(CC)'
+CXX_FOR_BUILD='$(CXX)'
+BUILD_CFLAGS='$(ALL_CFLAGS)'
+BUILD_CXXFLAGS='$(ALL_CXXFLAGS)'
+BUILD_LDFLAGS='$(LDFLAGS)'
+STMP_FIXINC=stmp-fixinc
+
+# And these apply if build != host, or we are generating coverage data
+if test x$build != x$host || test "x$coverage_flags" != x
+then
+ BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CFLAGS_FOR_BUILD)'
+ BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CXXFLAGS_FOR_BUILD)'
+ BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)'
+fi
+
+# Expand extra_headers to include complete path.
+# This substitutes for lots of t-* files.
+extra_headers_list=
+# Prepend $(srcdir)/config/${cpu_type}/ to every entry in extra_headers.
+for file in ${extra_headers} ; do
+ extra_headers_list="${extra_headers_list} \$(srcdir)/config/${cpu_type}/${file}"
+done
+
+# If use_gcc_tgmath is set, append ginclude/tgmath.h.
+if test x"$use_gcc_tgmath" = xyes
+then extra_headers_list="${extra_headers_list} \$(srcdir)/ginclude/tgmath.h"
+fi
+
+# Define collect2 in Makefile.
+case $host_can_use_collect2 in
+ no) collect2= ;;
+ *) collect2='collect2$(exeext)' ;;
+esac
+
+
+# Add a definition of USE_COLLECT2 if system wants one.
+case $use_collect2 in
+ no) use_collect2= ;;
+ "") ;;
+ *)
+ host_xm_defines="${host_xm_defines} USE_COLLECT2"
+ xm_defines="${xm_defines} USE_COLLECT2"
+ case $host_can_use_collect2 in
+ no)
+ as_fn_error $? "collect2 is required but cannot be built on this system" "$LINENO" 5
+ ;;
+ esac
+ ;;
+esac
+
+
+cat >>confdefs.h <<_ACEOF
+#define LTOPLUGINSONAME "${host_lto_plugin_soname}"
+_ACEOF
+
+
+# ---------------------------
+# Assembler & linker features
+# ---------------------------
+
+# During stage 2, ld is actually gcc/collect-ld, which is a small script to
+# discern between when to use prev-ld/ld-new and when to use ld/ld-new.
+# However when ld-new is first executed from the build tree, libtool will
+# relink it as .libs/lt-ld-new, so that it can give it an RPATH that refers
+# to the build tree. While doing this we need to use the previous-stage
+# linker, or we have an infinite loop. The presence of a shell script as
+# ld/ld-new, and the fact that the script *uses ld itself*, is what confuses
+# the gcc/collect-ld script. So we need to know how libtool works, or
+# exec-tool will fail.
+
+
+case `pwd` in
+ *\ * | *\ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.2.7a'
+macro_revision='1.3134'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain="$ac_aux_dir/ltmain.sh"
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`print -r -- -n 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO ""
+}
+
+case "$ECHO" in
+ printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+ print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+ *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if ${ac_cv_path_FGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+ then ac_cv_path_FGREP="$GREP -F"
+ else
+ if test -z "$FGREP"; then
+ ac_path_FGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in fgrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+ # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'FGREP' >> "conftest.nl"
+ "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_FGREP="$ac_path_FGREP"
+ ac_path_FGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_FGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_FGREP"; then
+ as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_FGREP=$FGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if ${lt_cv_path_NM+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in dumpbin "link -dump"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DUMPBIN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DUMPBIN"; then
+ ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$DUMPBIN" && break
+ done
+fi
+if test -z "$DUMPBIN"; then
+ ac_ct_DUMPBIN=$DUMPBIN
+ for ac_prog in dumpbin "link -dump"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DUMPBIN"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_DUMPBIN" && break
+done
+
+ if test "x$ac_ct_DUMPBIN" = x; then
+ DUMPBIN=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DUMPBIN=$ac_ct_DUMPBIN
+ fi
+fi
+
+ case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+
+ if test "$DUMPBIN" != ":"; then
+ NM="$DUMPBIN"
+ fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if ${lt_cv_nm_interface+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+ cat conftest.out >&5
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if ${lt_cv_sys_max_cmd_len+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8 ; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+
+fi
+
+if test -n $lt_cv_sys_max_cmd_len ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5
+$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; }
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5
+$as_echo "$xsi_shell" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5
+$as_echo_n "checking whether the shell understands \"+=\"... " >&6; }
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5
+$as_echo "$lt_shell_append" >&6; }
+
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if ${lt_cv_ld_reload_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if ${lt_cv_deplibs_check_method+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+ if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[3-9]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[ABCDEGRST]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function
+ # and D for any global variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK '"\
+" {last_section=section; section=\$ 3};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+ (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+const struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_save_LIBS="$LIBS"
+ lt_save_CFLAGS="$CFLAGS"
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS="$lt_save_LIBS"
+ CFLAGS="$lt_save_CFLAGS"
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+ enableval=$enable_libtool_lock;
+fi
+
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if ${lt_cv_cc_needs_belf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_cc_needs_belf=yes
+else
+ lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+sparc*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*) LD="${LD-ld} -m elf64_sparc" ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks="$enable_libtool_lock"
+
+
+ case $host_os in
+ rhapsody* | darwin*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DSYMUTIL"; then
+ ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+ ac_ct_DSYMUTIL=$DSYMUTIL
+ # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DSYMUTIL"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_DSYMUTIL" = x; then
+ DSYMUTIL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DSYMUTIL=$ac_ct_DSYMUTIL
+ fi
+else
+ DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NMEDIT"; then
+ ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+ ac_ct_NMEDIT=$NMEDIT
+ # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_NMEDIT"; then
+ ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_NMEDIT="nmedit"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_NMEDIT" = x; then
+ NMEDIT=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ NMEDIT=$ac_ct_NMEDIT
+ fi
+else
+ NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LIPO+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$LIPO"; then
+ ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+ ac_ct_LIPO=$LIPO
+ # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_LIPO"; then
+ ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_LIPO="lipo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_LIPO" = x; then
+ LIPO=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LIPO=$ac_ct_LIPO
+ fi
+else
+ LIPO="$ac_cv_prog_LIPO"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OTOOL"; then
+ ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+ ac_ct_OTOOL=$OTOOL
+ # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OTOOL"; then
+ ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL="otool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL" = x; then
+ OTOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL=$ac_ct_OTOOL
+ fi
+else
+ OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OTOOL64"; then
+ ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+ ac_ct_OTOOL64=$OTOOL64
+ # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OTOOL64"; then
+ ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL64="otool64"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL64" = x; then
+ OTOOL64=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL64=$ac_ct_OTOOL64
+ fi
+else
+ OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if ${lt_cv_apple_cc_single_mod+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_apple_cc_single_mod=no
+ if test -z "${LT_MULTI_MODULE}"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_ld_exported_symbols_list=yes
+else
+ lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+ echo "$AR cru libconftest.a conftest.o" >&5
+ $AR cru libconftest.a conftest.o 2>&5
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+ # Allow for Darwin 4-7 (macOS 10.0-10.3) although these are not expect to
+ # build without first building modern cctools / linker.
+ case $host_cpu-$host_os in
+ *-rhapsody* | *-darwin1.[012])
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+ *-darwin1.*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ *-darwin*)
+ # darwin 5.x (macOS 10.1) onwards we only need to adjust when the
+ # deployment target is forced to an earlier version.
+ case ${MACOSX_DEPLOYMENT_TARGET-UNSET},$host in
+ UNSET,*-darwin[89]*|UNSET,*-darwin[12][0123456789]*)
+ ;;
+ 10.[012][,.]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+
+
+for ac_header in dlfcn.h
+do :
+ ac_fn_c_check_header_preproc "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+done
+
+
+
+
+
+# Set options
+
+
+
+ enable_dlopen=no
+
+
+ enable_win32_dll=no
+
+
+ # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+ # Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+ withval=$with_pic; pic_mode="$withval"
+else
+ pic_mode=default
+fi
+
+
+test -z "$pic_mode" && pic_mode=default
+
+
+
+
+
+
+
+ # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if ${lt_cv_objdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/${ac_tool_prefix}file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/file; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac
+fi
+
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC="$CC"
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test "$GCC" = yes; then
+ case $cc_basename in
+ nvcc*)
+ lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+ *)
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+
+
+
+
+
+ lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+ if test "$GCC" = yes; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ lt_prog_compiler_static=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ lt_prog_compiler_wl='-Xlinker '
+ lt_prog_compiler_pic='-Xcompiler -fPIC'
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ # old Intel for x86_64 which still supported -KPIC.
+ ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='--shared'
+ lt_prog_compiler_static='--static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-qpic'
+ lt_prog_compiler_static='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ F* | *Sun*Fortran*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl=''
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ rdos*)
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5
+$as_echo "$lt_prog_compiler_pic" >&6; }
+
+
+
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works" = xyes; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_static_works=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works" = xyes; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ always_export_symbols=no
+ archive_cmds=
+ archive_expsym_cmds=
+ compiler_needs_object=no
+ enable_shared_with_static_runtimes=no
+ export_dynamic_flag_spec=
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ hardcode_automatic=no
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld=
+ hardcode_libdir_separator=
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ inherit_rpath=no
+ link_all_deplibs=unknown
+ module_cmds=
+ module_expsym_cmds=
+ old_archive_from_new_cmds=
+ old_archive_from_expsyms_cmds=
+ thread_safe_flag_spec=
+ whole_archive_flag_spec=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test "$with_gnu_ld" = yes; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+ *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test "$lt_use_gnu_ld_interface" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ export_dynamic_flag_spec='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ export_dynamic_flag_spec='${wl}--export-all-symbols'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ haiku*)
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ link_all_deplibs=yes
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu | uclinuxfdpiceabi)
+ tmp_diet=no
+ if test "$host_os" = linux-dietlibc; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test "$tmp_diet" = no
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ whole_archive_flag_spec=
+ tmp_sharedflag='--shared' ;;
+ xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ compiler_needs_object=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ compiler_needs_object=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test "x$supports_anon_versioning" = xyes; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_flag_spec_ld='-rpath $libdir'
+ archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test "$ld_shlibs" = no; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ # Also, AIX nm treats weak defined symbols like other global
+ # defined symbols, whereas GNU nm marks them as "W".
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ file_list_spec='${wl}-f,'
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ export_dynamic_flag_spec='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' ${wl}-bernotok'
+ allow_undefined_flag=' ${wl}-berok'
+ if test "$with_gnu_ld" = yes; then
+ # We only use this code for GNU lds that support --whole-archive.
+ whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ fi
+ archive_cmds_need_lc=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ fix_srcfile_path='`cygpath -w "$srcfile"`'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ if test "$lt_cv_ld_force_load" = "yes"; then
+ whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+ else
+ whole_archive_flag_spec=''
+ fi
+ link_all_deplibs=yes
+ allow_undefined_flag="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=func_echo_all
+ archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+
+ else
+ ld_shlibs=no
+ fi
+
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_flag_spec_ld='+b $libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='${wl}-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler__b=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -b"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler__b=yes
+ fi
+ else
+ lt_cv_prog_compiler__b=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test x"$lt_cv_prog_compiler__b" = xyes; then
+ archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo(void) {}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ inherit_rpath=yes
+ link_all_deplibs=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ hardcode_direct_absolute=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec='${wl}-E'
+ else
+ case $host_os in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z defs'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='${wl}'
+ archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'. GCC discards it without `$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test "$GCC" = yes; then
+ whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ else
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag='${wl}-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='${wl}-z,text'
+ allow_undefined_flag='${wl}-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='${wl}-R,$libdir'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+
+ if test x$host_vendor = xsni; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ export_dynamic_flag_spec='${wl}-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test "$ld_shlibs" = no && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+ lt_cv_archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+ archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;;
+ *) lt_sed_strip_eq="s,=/,/,g" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary.
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+ else
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+ lt_foo="";
+ lt_count=0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo="/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[lt_foo]++; }
+ if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's,/\([A-Za-z]:\),\1,g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[23].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[3-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+
+# uclinux* changes (here and below) have been submitted to the libtool
+# project, but have not yet been accepted: they are GCC-local changes
+# for the time being. (See
+# https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+ lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+fi
+
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+ test -n "$runpath_var" ||
+ test "X$hardcode_automatic" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$hardcode_direct" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no &&
+ test "$hardcode_minus_L" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test "$hardcode_action" = relink ||
+ test "$inherit_rpath" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ *)
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+ lt_cv_dlopen="shl_load"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_shl_load=yes
+else
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
+else
+ ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes; then :
+ lt_cv_dlopen="dlopen"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_svld_dlopen=yes
+else
+ ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+ lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_dld_link=yes
+else
+ ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line 19336 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self_static+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line 19442 "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+void fnord () __attribute__((visibility("default")));
+#endif
+
+void fnord () { int i=42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ # Report which library types will actually be built
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+CC="$lt_save_CC"
+
+ if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+ if ${ac_cv_prog_CXXCPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+else
+ _lt_caught_CXX_error=yes
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+compiler_needs_object_CXX=no
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_direct_absolute_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+inherit_rpath_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+reload_flag_CXX=$reload_flag
+reload_cmds_CXX=$reload_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+ # save warnings/boilerplate of simple test code
+ ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ compiler=$CC
+ compiler_CXX=$CC
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+ else
+ lt_prog_compiler_no_builtin_flag_CXX=
+ fi
+
+ if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+ ld_shlibs_CXX=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix[4-9]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_direct_absolute_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ file_list_spec_CXX='${wl}-f,'
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ export_dynamic_flag_spec_CXX='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ if test "$with_gnu_ld" = yes; then
+ # We only use this code for GNU lds that support --whole-archive.
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ fi
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-all-symbols'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ if test "$lt_cv_ld_force_load" = "yes"; then
+ whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+ else
+ whole_archive_flag_spec_CXX=''
+ fi
+ link_all_deplibs_CXX=yes
+ allow_undefined_flag_CXX="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=func_echo_all
+ archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+ archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+ archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+ fi
+
+ else
+ ld_shlibs_CXX=no
+ fi
+
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ freebsd2.*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+
+ gnu*)
+ ;;
+
+ haiku*)
+ archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ link_all_deplibs_CXX=yes
+ ;;
+
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_direct_absolute_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ inherit_rpath_CXX=yes
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [1-5].* | *pgcpp\ [1-5].*)
+ prelink_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+ old_archive_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+ $RANLIB $oldlib'
+ archive_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 and above use weak symbols
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ esac
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+ ;;
+ xl* | mpixl* | bgxl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ compiler_needs_object_CXX=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ ld_shlibs_CXX=yes
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ hardcode_direct_absolute_CXX=yes
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=func_echo_all
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ ;;
+ *)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
+ $RM $lib.exp'
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ ;;
+ esac
+
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ case $host in
+ osf3*)
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ esac
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ archive_cmds_need_lc_CXX=yes
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag_CXX='${wl}-z,text'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_CXX='${wl}-z,text'
+ allow_undefined_flag_CXX='${wl}-z,nodefs'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir'
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~
+ '"$old_archive_cmds_CXX"
+ reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~
+ '"$reload_cmds_CXX"
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+ test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+ GCC_CXX="$GXX"
+ LD_CXX="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ # Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+
+if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix[3-9]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ predep_objects_CXX=
+ postdep_objects_CXX=
+ postdeps_CXX=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ postdeps_CXX='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ postdeps_CXX='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+ compiler_lib_search_dirs_CXX=
+if test -n "${compiler_lib_search_path_CXX}"; then
+ compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ lt_prog_compiler_static_CXX=
+ ;;
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic_CXX='-fPIC -shared'
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[4-9]*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64 which still supported -KPIC.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fpic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ xlc* | xlC* | bgxl[cC]* | mpixl[cC]*)
+ # IBM XL 8.0, 9.0 on PPC and BlueGene
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-qpic'
+ lt_prog_compiler_static_CXX='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic_CXX='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5
+$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_static_works_CXX=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works_CXX=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works_CXX=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then
+ :
+else
+ lt_prog_compiler_static_CXX=
+fi
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix[4-9]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ # Also, AIX nm treats weak defined symbols like other global defined
+ # symbols, whereas GNU nm marks them as "W".
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+ exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+with_gnu_ld_CXX=$with_gnu_ld
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ pic_flag=$lt_prog_compiler_pic_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ lt_cv_archive_cmds_need_lc_CXX=no
+ else
+ lt_cv_archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
+ archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[23].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[3-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+
+# uclinux* changes (here and below) have been submitted to the libtool
+# project, but have not yet been accepted: they are GCC-local changes
+# for the time being. (See
+# https://lists.gnu.org/archive/html/libtool-patches/2018-05/msg00000.html)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu* | uclinuxfdpiceabi)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+ lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+fi
+
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" ||
+ test -n "$runpath_var_CXX" ||
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
+$as_echo "$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink ||
+ test "$inherit_rpath_CXX" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Only expand once:
+
+
+
+
+
+# Identify the assembler which will work hand-in-glove with the newly
+# built GCC, so that we can examine its features. This is the assembler
+# which will be driven by the driver program.
+#
+# If build != host, and we aren't building gas in-tree, we identify a
+# build->target assembler and hope that it will have the same features
+# as the host->target assembler we'll be using.
+gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gas
+
+if ${gcc_cv_as+:} false; then :
+
+else
+
+if test -x "$DEFAULT_ASSEMBLER"; then
+ gcc_cv_as="$DEFAULT_ASSEMBLER"
+elif test -f $gcc_cv_as_gas_srcdir/configure.ac \
+ && test -f ../gas/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_as=../gas/as-new$build_exeext
+elif test -x as$build_exeext; then
+ # Build using assembler in the current directory.
+ gcc_cv_as=./as$build_exeext
+elif ( set dummy $AS_FOR_TARGET; test -x $2 ); then
+ gcc_cv_as="$AS_FOR_TARGET"
+else
+ # Extract the first word of "$AS_FOR_TARGET", so it can be a program name with args.
+set dummy $AS_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_as+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_as in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_as="$gcc_cv_as" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_as="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_as=$ac_cv_path_gcc_cv_as
+if test -n "$gcc_cv_as"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as" >&5
+$as_echo "$gcc_cv_as" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+ORIGINAL_AS_FOR_TARGET=$gcc_cv_as
+
+case "$ORIGINAL_AS_FOR_TARGET" in
+ ./as | ./as$build_exeext) ;;
+ *) ac_config_files="$ac_config_files as:exec-tool.in"
+ ;;
+esac
+
+default_ld=
+# Check whether --enable-ld was given.
+if test "${enable_ld+set}" = set; then :
+ enableval=$enable_ld; case "${enableval}" in
+ no)
+ default_ld=ld.gold
+ ;;
+ esac
+fi
+
+
+install_gold_as_default=no
+# Check whether --enable-gold was given.
+if test "${enable_gold+set}" = set; then :
+ enableval=$enable_gold; case "${enableval}" in
+ default)
+ install_gold_as_default=yes
+ ;;
+ yes)
+ if test x${default_ld} != x; then
+ install_gold_as_default=yes
+ fi
+ ;;
+ no)
+ ;;
+ *)
+ as_fn_error $? "invalid --enable-gold argument" "$LINENO" 5
+ ;;
+ esac
+fi
+
+
+# Identify the linker which will work hand-in-glove with the newly
+# built GCC, so that we can examine its features. This is the linker
+# which will be driven by the driver program.
+#
+# If build != host, and we aren't building gas in-tree, we identify a
+# build->target linker and hope that it will have the same features
+# as the host->target linker we'll be using.
+gcc_cv_gld_major_version=
+gcc_cv_gld_minor_version=
+gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld
+gcc_cv_ld_gold_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gold
+gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd
+
+if ${gcc_cv_ld+:} false; then :
+
+else
+
+if test -x "$DEFAULT_LINKER"; then
+ gcc_cv_ld="$DEFAULT_LINKER"
+elif test $install_gold_as_default = yes \
+ && test -f $gcc_cv_ld_gold_srcdir/configure.ac \
+ && test -f ../gold/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_ld=../gold/ld-new$build_exeext
+elif test -f $gcc_cv_ld_gld_srcdir/configure.ac \
+ && test -f ../ld/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_ld=../ld/ld-new$build_exeext
+elif test -x collect-ld$build_exeext; then
+ # Build using linker in the current directory.
+ gcc_cv_ld=./collect-ld$build_exeext
+elif ( set dummy $LD_FOR_TARGET; test -x $2 ); then
+ gcc_cv_ld="$LD_FOR_TARGET"
+else
+ # Extract the first word of "$LD_FOR_TARGET", so it can be a program name with args.
+set dummy $LD_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_ld+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_ld in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_ld="$gcc_cv_ld" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_ld="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_ld=$ac_cv_path_gcc_cv_ld
+if test -n "$gcc_cv_ld"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld" >&5
+$as_echo "$gcc_cv_ld" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+ORIGINAL_PLUGIN_LD_FOR_TARGET=$gcc_cv_ld
+PLUGIN_LD_SUFFIX=`basename $gcc_cv_ld | sed -e "s,$target_alias-,,"`
+# if the PLUGIN_LD is set ld-new, just have it as ld
+# as that is the installed named.
+if test x$PLUGIN_LD_SUFFIX = xld-new \
+ || test x$PLUGIN_LD_SUFFIX = xcollect-ld ; then
+ PLUGIN_LD_SUFFIX=ld
+fi
+
+# Check whether --with-plugin-ld was given.
+if test "${with_plugin_ld+set}" = set; then :
+ withval=$with_plugin_ld; if test x"$withval" != x; then
+ ORIGINAL_PLUGIN_LD_FOR_TARGET="$withval"
+ PLUGIN_LD_SUFFIX="$withval"
+ fi
+fi
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define PLUGIN_LD_SUFFIX "$PLUGIN_LD_SUFFIX"
+_ACEOF
+
+
+# Check to see if we are using gold instead of ld
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using gold" >&5
+$as_echo_n "checking whether we are using gold... " >&6; }
+ld_is_gold=no
+if test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --version 2>/dev/null | sed 1q \
+ | grep "GNU gold" > /dev/null; then
+ ld_is_gold=yes
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_is_gold" >&5
+$as_echo "$ld_is_gold" >&6; }
+
+# Check to see if we are using mold instead of ld
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using mold" >&5
+$as_echo_n "checking whether we are using mold... " >&6; }
+ld_is_mold=no
+if test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --version 2>/dev/null | sed 1q \
+ | grep "mold" > /dev/null; then
+ ld_is_mold=yes
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_is_mold" >&5
+$as_echo "$ld_is_mold" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gold linker with split stack support as non default" >&5
+$as_echo_n "checking gold linker with split stack support as non default... " >&6; }
+# Check to see if default ld is not gold, but gold is
+# available and has support for split stack. If gcc was configured
+# with gold then no checking is done.
+#
+if test x$ld_is_gold = xno && which ${gcc_cv_ld}.gold >/dev/null 2>&1; then
+
+# For platforms other than powerpc64*, enable as appropriate.
+
+ gold_non_default=no
+ ld_gold=`which ${gcc_cv_ld}.gold`
+# Make sure this gold has minimal split stack support
+ if $ld_gold --help 2>/dev/null | grep split-stack-adjust-size >/dev/null 2>&1; then
+ ld_vers=`$ld_gold --version | sed 1q`
+ gold_vers=`echo $ld_vers | sed -n \
+ -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
+ case $target in
+# check that the gold version contains the complete split stack support
+# on powerpc64 big and little endian
+ powerpc64*-*-*)
+ case "$gold_vers" in
+ 2.25.[1-9]*|2.2[6-9][.0-9]*|2.[3-9][.0-9]*|[3-9].[.0-9]*) gold_non_default=yes
+ ;;
+ *) gold_non_default=no
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ if test $gold_non_default = yes; then
+
+$as_echo "#define HAVE_GOLD_NON_DEFAULT_SPLIT_STACK 1" >>confdefs.h
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_non_default" >&5
+$as_echo "$gold_non_default" >&6; }
+
+ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld
+
+case "$ORIGINAL_LD_FOR_TARGET" in
+ ./collect-ld | ./collect-ld$build_exeext) ;;
+ *) ac_config_files="$ac_config_files collect-ld:exec-tool.in"
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what linker to use" >&5
+$as_echo_n "checking what linker to use... " >&6; }
+if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext \
+ || test "$gcc_cv_ld" = ../gold/ld-new$build_exeext; then
+ # Single tree build which includes ld. We want to prefer it
+ # over whatever linker top-level may have detected, since
+ # we'll use what we're building after installation anyway.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: newly built ld" >&5
+$as_echo "newly built ld" >&6; }
+ in_tree_ld=yes
+ in_tree_ld_is_elf=no
+ if (grep 'EMUL = .*elf' ../ld/Makefile \
+ || grep 'EMUL = .*linux' ../ld/Makefile \
+ || grep 'EMUL = .*lynx' ../ld/Makefile) > /dev/null; then
+ in_tree_ld_is_elf=yes
+ elif test "$ld_is_gold" = yes; then
+ in_tree_ld_is_elf=yes
+ fi
+ for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.ac $gcc_cv_ld_gld_srcdir/Makefile.in
+ do
+ gcc_cv_gld_version=`sed -n -e 's/^[ ]*VERSION=[^0-9A-Za-z_]*\([0-9]*\.[0-9]*.*\)/VERSION=\1/p' < $f`
+ if test x$gcc_cv_gld_version != x; then
+ break
+ fi
+ done
+ case $gcc_cv_gld_version in
+ VERSION=[0-9]*) ;;
+ *) as_fn_error $? "cannot find version of in-tree linker" "$LINENO" 5 ;;
+ esac
+ gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"`
+ gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"`
+ ORIGINAL_LD_BFD_FOR_TARGET=../ld/ld-new$build_exeext
+ ORIGINAL_LD_GOLD_FOR_TARGET=../gold/ld-new$build_exeext
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld" >&5
+$as_echo "$gcc_cv_ld" >&6; }
+ in_tree_ld=no
+ gcc_cvs_ld_program=false # `dirname $gcc_cv_ld`/`basename $gcc_cv_ld $host_exeext`
+ ORIGINAL_LD_BFD_FOR_TARGET=${gcc_cvs_ld_program}.bfd$host_exeext
+ ORIGINAL_LD_GOLD_FOR_TARGET=${gcc_cvs_ld_program}.gold$host_exeext
+fi
+
+
+
+
+# Figure out what nm we will be using.
+gcc_cv_binutils_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/binutils
+if ${gcc_cv_nm+:} false; then :
+
+else
+
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_nm=../binutils/nm-new$build_exeext
+elif test -x nm$build_exeext; then
+ gcc_cv_nm=./nm$build_exeext
+elif ( set dummy $NM_FOR_TARGET; test -x $2 ); then
+ gcc_cv_nm="$NM_FOR_TARGET"
+else
+ # Extract the first word of "$NM_FOR_TARGET", so it can be a program name with args.
+set dummy $NM_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_nm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_nm in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_nm="$gcc_cv_nm" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_nm="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_nm=$ac_cv_path_gcc_cv_nm
+if test -n "$gcc_cv_nm"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_nm" >&5
+$as_echo "$gcc_cv_nm" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what nm to use" >&5
+$as_echo_n "checking what nm to use... " >&6; }
+if test "$gcc_cv_nm" = ../binutils/nm-new$build_exeext; then
+ # Single tree build which includes binutils.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: newly built nm" >&5
+$as_echo "newly built nm" >&6; }
+ in_tree_nm=yes
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_nm" >&5
+$as_echo "$gcc_cv_nm" >&6; }
+ in_tree_nm=no
+fi
+
+ORIGINAL_NM_FOR_TARGET=$gcc_cv_nm
+
+case "$ORIGINAL_NM_FOR_TARGET" in
+ ./nm | ./nm$build_exeext) ;;
+ *) ac_config_files="$ac_config_files nm:exec-tool.in"
+ ;;
+esac
+
+
+# Figure out what objdump we will be using.
+if ${gcc_cv_objdump+:} false; then :
+
+else
+
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_objdump=../binutils/objdump$build_exeext
+elif test -x objdump$build_exeext; then
+ gcc_cv_objdump=./objdump$build_exeext
+elif ( set dummy $OBJDUMP_FOR_TARGET; test -x $2 ); then
+ gcc_cv_objdump="$OBJDUMP_FOR_TARGET"
+else
+ # Extract the first word of "$OBJDUMP_FOR_TARGET", so it can be a program name with args.
+set dummy $OBJDUMP_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_objdump+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_objdump in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_objdump="$gcc_cv_objdump" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_objdump="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_objdump=$ac_cv_path_gcc_cv_objdump
+if test -n "$gcc_cv_objdump"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_objdump" >&5
+$as_echo "$gcc_cv_objdump" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what objdump to use" >&5
+$as_echo_n "checking what objdump to use... " >&6; }
+if test "$gcc_cv_objdump" = ../binutils/objdump$build_exeext; then
+ # Single tree build which includes binutils.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: newly built objdump" >&5
+$as_echo "newly built objdump" >&6; }
+elif test x$gcc_cv_objdump = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_objdump" >&5
+$as_echo "$gcc_cv_objdump" >&6; }
+fi
+
+# Figure out what readelf we will be using.
+if ${gcc_cv_readelf+:} false; then :
+
+else
+
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_readelf=../binutils/readelf$build_exeext
+elif test -x readelf$build_exeext; then
+ gcc_cv_readelf=./readelf$build_exeext
+elif ( set dummy $READELF_FOR_TARGET; test -x $2 ); then
+ gcc_cv_readelf="$READELF_FOR_TARGET"
+else
+ # Extract the first word of "$READELF_FOR_TARGET", so it can be a program name with args.
+set dummy $READELF_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_readelf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_readelf in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_readelf="$gcc_cv_readelf" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_readelf="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_readelf=$ac_cv_path_gcc_cv_readelf
+if test -n "$gcc_cv_readelf"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_readelf" >&5
+$as_echo "$gcc_cv_readelf" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what readelf to use" >&5
+$as_echo_n "checking what readelf to use... " >&6; }
+if test "$gcc_cv_readelf" = ../binutils/readelf$build_exeext; then
+ # Single tree build which includes binutils.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: newly built readelf" >&5
+$as_echo "newly built readelf" >&6; }
+elif test x$gcc_cv_readelf = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_readelf" >&5
+$as_echo "$gcc_cv_readelf" >&6; }
+fi
+
+# Figure out what otool we will be using.
+if ${gcc_cv_otool+:} false; then :
+
+else
+
+if test -x otool$build_exeext; then
+ gcc_cv_otool=./otool$build_exeext
+elif ( set dummy $OTOOL_FOR_TARGET; test -x $2 ); then
+ gcc_cv_otool="$OTOOL_FOR_TARGET"
+else
+ # Extract the first word of "$OTOOL_FOR_TARGET", so it can be a program name with args.
+set dummy $OTOOL_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_otool+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_otool in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_otool="$gcc_cv_otool" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_otool="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_otool=$ac_cv_path_gcc_cv_otool
+if test -n "$gcc_cv_otool"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_otool" >&5
+$as_echo "$gcc_cv_otool" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what otool to use" >&5
+$as_echo_n "checking what otool to use... " >&6; }
+if test x$gcc_cv_otool = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_otool" >&5
+$as_echo "$gcc_cv_otool" >&6; }
+fi
+
+# Figure out the dsymutil we will use.
+if ${gcc_cv_dsymutil+:} false; then :
+
+else
+
+if test -x "$DEFAULT_DSYMUTIL"; then
+ gcc_cv_dsymutil="$DEFAULT_DSYMUTIL"
+elif test -x dsymutil$build_exeext; then
+ gcc_cv_dsymutil=./dsymutil$build_exeext
+elif ( set dummy $DSYMUTIL_FOR_TARGET; test -x $2 ); then
+ gcc_cv_dsymutil=$DSYMUTIL_FOR_TARGET
+elif ( set dummy $DSYMUTIL; test -x $2 ); then
+ gcc_cv_dsymutil=$DSYMUTIL
+else
+ # Extract the first word of "$DSYMUTIL_FOR_TARGET", so it can be a program name with args.
+set dummy $DSYMUTIL_FOR_TARGET; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_gcc_cv_dsymutil+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $gcc_cv_dsymutil in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_gcc_cv_dsymutil="$gcc_cv_dsymutil" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_gcc_cv_dsymutil="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+gcc_cv_dsymutil=$ac_cv_path_gcc_cv_dsymutil
+if test -n "$gcc_cv_dsymutil"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_dsymutil" >&5
+$as_echo "$gcc_cv_dsymutil" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+fi
+
+ORIGINAL_DSYMUTIL_FOR_TARGET=$gcc_cv_dsymutil
+
+case "$ORIGINAL_DSYMUTIL_FOR_TARGET" in
+ ./dsymutil | ./dsymutil$build_exeext) ;;
+ *) ac_config_files="$ac_config_files dsymutil:exec-tool.in"
+ ;;
+esac
+
+# Figure out what assembler alignment features are present.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler flags" >&5
+$as_echo_n "checking assembler flags... " >&6; }
+if ${gcc_cv_as_flags+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case "$target" in
+ i[34567]86-*-linux*)
+ gcc_cv_as_flags=--32
+ ;;
+ x86_64-*-linux-gnux32)
+ gcc_cv_as_flags=--x32
+ ;;
+ x86_64-*-linux*)
+ gcc_cv_as_flags=--64
+ ;;
+ powerpc*-*-darwin*)
+ gcc_cv_as_flags="-arch ppc"
+ ;;
+ *)
+ gcc_cv_as_flags=" "
+ ;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_flags" >&5
+$as_echo "$gcc_cv_as_flags" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .balign and .p2align" >&5
+$as_echo_n "checking assembler for .balign and .p2align... " >&6; }
+if ${gcc_cv_as_balign_and_p2align+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_balign_and_p2align=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.balign 4
+.p2align 2' > 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_balign_and_p2align=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_balign_and_p2align" >&5
+$as_echo "$gcc_cv_as_balign_and_p2align" >&6; }
+if test $gcc_cv_as_balign_and_p2align = yes; then
+
+$as_echo "#define HAVE_GAS_BALIGN_AND_P2ALIGN 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .p2align with maximum skip" >&5
+$as_echo_n "checking assembler for .p2align with maximum skip... " >&6; }
+if ${gcc_cv_as_max_skip_p2align+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_max_skip_p2align=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.p2align 4,,7' > 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_max_skip_p2align=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_max_skip_p2align" >&5
+$as_echo "$gcc_cv_as_max_skip_p2align" >&6; }
+if test $gcc_cv_as_max_skip_p2align = yes; then
+
+$as_echo "#define HAVE_GAS_MAX_SKIP_P2ALIGN 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .literal16" >&5
+$as_echo_n "checking assembler for .literal16... " >&6; }
+if ${gcc_cv_as_literal16+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_literal16=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.literal16' > 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_literal16=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_literal16" >&5
+$as_echo "$gcc_cv_as_literal16" >&6; }
+if test $gcc_cv_as_literal16 = yes; then
+
+$as_echo "#define HAVE_GAS_LITERAL16 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for working .subsection -1" >&5
+$as_echo_n "checking assembler for working .subsection -1... " >&6; }
+if ${gcc_cv_as_subsection_m1+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_subsection_m1=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'conftest_label1: .word 0
+.subsection -1
+conftest_label2: .word 0
+.previous' > 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
+ if test x$gcc_cv_nm != x; then
+ $gcc_cv_nm conftest.o | grep conftest_label1 > conftest.nm1
+ $gcc_cv_nm conftest.o | grep conftest_label2 | sed -e 's/label2/label1/' > conftest.nm2
+ if cmp conftest.nm1 conftest.nm2 > /dev/null 2>&1
+ then :
+ else gcc_cv_as_subsection_m1=yes
+ fi
+ rm -f conftest.nm1 conftest.nm2
+ fi
+ 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_subsection_m1" >&5
+$as_echo "$gcc_cv_as_subsection_m1" >&6; }
+if test $gcc_cv_as_subsection_m1 = yes; then
+
+$as_echo "#define HAVE_GAS_SUBSECTION_ORDERING 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .weak" >&5
+$as_echo_n "checking assembler for .weak... " >&6; }
+if ${gcc_cv_as_weak+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_weak=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .weak foobar' > 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_weak=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_weak" >&5
+$as_echo "$gcc_cv_as_weak" >&6; }
+if test $gcc_cv_as_weak = yes; then
+
+$as_echo "#define HAVE_GAS_WEAK 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .weakref" >&5
+$as_echo_n "checking assembler for .weakref... " >&6; }
+if ${gcc_cv_as_weakref+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_weakref=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .weakref foobar, barfnot' > 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_weakref=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_weakref" >&5
+$as_echo "$gcc_cv_as_weakref" >&6; }
+if test $gcc_cv_as_weakref = yes; then
+
+$as_echo "#define HAVE_GAS_WEAKREF 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .nsubspa comdat" >&5
+$as_echo_n "checking assembler for .nsubspa comdat... " >&6; }
+if ${gcc_cv_as_nsubspa_comdat+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_nsubspa_comdat=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .SPACE $TEXT$
+ .NSUBSPA $CODE$,COMDAT' > 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_nsubspa_comdat=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_nsubspa_comdat" >&5
+$as_echo "$gcc_cv_as_nsubspa_comdat" >&6; }
+if test $gcc_cv_as_nsubspa_comdat = yes; then
+
+$as_echo "#define HAVE_GAS_NSUBSPA_COMDAT 1" >>confdefs.h
+
+fi
+
+
+# .hidden needs to be supported in both the assembler and the linker,
+# because GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN.
+# This is irritatingly difficult to feature test for; we have to check the
+# date string after the version number. If we've got an in-tree
+# ld, we don't know its patchlevel version, so we set the baseline at 2.13
+# to be safe.
+# The gcc_GAS_CHECK_FEATURE call just sets a cache variable.
+case "${target}" in
+ *-*-aix*)
+ conftest_s=' .globl foobar,hidden'
+ ;;
+ *)
+ conftest_s=' .hidden foobar
+foobar:'
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .hidden" >&5
+$as_echo_n "checking assembler for .hidden... " >&6; }
+if ${gcc_cv_as_hidden+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_hidden=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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_hidden=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_hidden" >&5
+$as_echo "$gcc_cv_as_hidden" >&6; }
+
+
+case "${target}" in
+ *-*-darwin*)
+ # Darwin as has some visibility support, though with a different syntax.
+ gcc_cv_as_hidden=yes
+ ;;
+esac
+
+# gnu_indirect_function type is an extension proposed at
+# http://groups.google/com/group/generic-abi/files. It allows dynamic runtime
+# selection of function implementation
+# Check whether --enable-gnu-indirect-function was given.
+if test "${enable_gnu_indirect_function+set}" = set; then :
+ enableval=$enable_gnu_indirect_function; case $enable_gnu_indirect_function in
+ yes | no) ;;
+ *) as_fn_error $? "'$enable_gnu_indirect_function' is an invalid value for --enable-gnu-indirect-function.
+Valid choices are 'yes' and 'no'." "$LINENO" 5 ;;
+ esac
+else
+ enable_gnu_indirect_function="$default_gnu_indirect_function"
+fi
+
+
+case "${target}" in
+ riscv*-*-linux*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker ifunc IRELATIVE support" >&5
+$as_echo_n "checking linker ifunc IRELATIVE support... " >&6; }
+ cat > conftest.s <<EOF
+ .text
+ .type foo_resolver, @function
+foo_resolver:
+ ret
+ .size foo_resolver, .-foo_resolver
+
+ .globl foo
+ .type foo, %gnu_indirect_function
+ .set foo, foo_resolver
+
+ .globl bar
+ .type bar, @function
+bar:
+ call foo
+ ret
+ .size bar, .-bar
+EOF
+ if test x$gcc_cv_as != x \
+ && test x$gcc_cv_ld != x \
+ && test x$gcc_cv_readelf != x \
+ && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_readelf --relocs --wide conftest \
+ | grep R_RISCV_IRELATIVE > /dev/null 2>&1; then
+ enable_gnu_indirect_function=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gnu_indirect_function" >&5
+$as_echo "$enable_gnu_indirect_function" >&6; }
+ ;;
+esac
+
+gif=`if test x$enable_gnu_indirect_function = xyes; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GNU_INDIRECT_FUNCTION $gif
+_ACEOF
+
+
+
+if test $in_tree_ld != yes ; then
+ ld_ver=`$gcc_cv_ld --version 2>/dev/null | sed 1q`
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ if test x"$ld_is_gold" = xyes; then
+ # GNU gold --version looks like this:
+ #
+ # GNU gold (GNU Binutils 2.21.51.20110225) 1.11
+ #
+ # We extract the binutils version which is more familiar and specific
+ # than the gold version.
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
+ else
+ # GNU ld --version looks like this:
+ #
+ # GNU ld (GNU Binutils) 2.21.51.20110225
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
+ fi
+ ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)\(-*\)\([01][0-9]\)\2\([0-3][0-9]\).*$,\1\3\4,p'`
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ ld_vers_patch=`expr "$ld_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
+ else
+ case "${target}" in
+ *-*-solaris2*)
+ # Solaris 2 ld -V output looks like this for a regular version:
+ #
+ # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1699
+ #
+ # but test versions add stuff at the end:
+ #
+ # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
+ #
+ # ld and ld.so.1 are guaranteed to be updated in lockstep, so ld version
+ # numbers can be used in ld.so.1 feature checks even if a different
+ # linker is configured.
+ ld_ver=`$gcc_cv_ld -V 2>&1`
+ if echo "$ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^.*: 5\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\1,p'`
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ fi
+ ;;
+ esac
+ fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for .hidden support" >&5
+$as_echo_n "checking linker for .hidden support... " >&6; }
+if ${gcc_cv_ld_hidden+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test $in_tree_ld = yes ; then
+ gcc_cv_ld_hidden=no
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 13 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_hidden=yes
+ fi
+else
+ gcc_cv_ld_hidden=yes
+ if test x"$ld_is_gold" = xyes; then
+ :
+ elif test x"$ld_is_mold" = xyes; then
+ :
+ elif echo "$ld_ver" | grep GNU > /dev/null; then
+ if test 0"$ld_date" -lt 20020404; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2002-04-04, fail
+ gcc_cv_ld_hidden=no
+ elif test -z "$ld_vers"; then
+ # If there was no date string nor ld version number, something is wrong
+ gcc_cv_ld_hidden=no
+ else
+ test -z "$ld_vers_patch" && ld_vers_patch=0
+ if test "$ld_vers_major" -lt 2; then
+ gcc_cv_ld_hidden=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 12; then
+ gcc_cv_ld_hidden="no"
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -eq 12 -a "$ld_vers_patch" -eq 0; then
+ gcc_cv_ld_hidden=no
+ fi
+ fi
+ fi
+ else
+ case "${target}" in
+ *-*-aix[789]*)
+ gcc_cv_ld_hidden=yes
+ ;;
+ *-*-darwin*)
+ # Darwin ld has some visibility support.
+ gcc_cv_ld_hidden=yes
+ ;;
+ hppa64*-*-hpux* | ia64*-*-hpux*)
+ gcc_cv_ld_hidden=yes
+ ;;
+ *-*-solaris2*)
+ # Support for .hidden in Sun ld appeared in Solaris 9 FCS, but
+ # .symbolic was only added in Solaris 9 12/02.
+ gcc_cv_ld_hidden=yes
+ ;;
+ *)
+ gcc_cv_ld_hidden=no
+ ;;
+ esac
+ fi
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_hidden" >&5
+$as_echo "$gcc_cv_ld_hidden" >&6; }
+libgcc_visibility=no
+
+
+if test $gcc_cv_as_hidden = yes && test $gcc_cv_ld_hidden = yes; then
+ libgcc_visibility=yes
+
+$as_echo "#define HAVE_GAS_HIDDEN 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker read-only and read-write section mixing" >&5
+$as_echo_n "checking linker read-only and read-write section mixing... " >&6; }
+gcc_cv_ld_ro_rw_mix=unknown
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ echo '.section myfoosect, "a"' > conftest1.s
+ echo '.section myfoosect, "aw"' > conftest2.s
+ echo '.byte 1' >> conftest2.s
+ echo '.section myfoosect, "a"' > conftest3.s
+ echo '.byte 0' >> conftest3.s
+ if $gcc_cv_as -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest3.o conftest3.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -shared -o conftest1.so conftest1.o \
+ conftest2.o conftest3.o > /dev/null 2>&1; then
+ gcc_cv_ld_ro_rw_mix=`$gcc_cv_objdump -h conftest1.so \
+ | sed -e '/myfoosect/!d' -e N`
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep CONTENTS > /dev/null; then
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep READONLY > /dev/null; then
+ gcc_cv_ld_ro_rw_mix=read-only
+ else
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+ fi
+ fi
+ rm -f conftest.* conftest[123].*
+fi
+if test x$gcc_cv_ld_ro_rw_mix = xread-write; then
+
+$as_echo "#define HAVE_LD_RO_RW_SECTION_MIXING 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_ro_rw_mix" >&5
+$as_echo "$gcc_cv_ld_ro_rw_mix" >&6; }
+
+# Check whether --enable-initfini-array was given.
+if test "${enable_initfini_array+set}" = set; then :
+ enableval=$enable_initfini_array;
+else
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .preinit_array/.init_array/.fini_array support" >&5
+$as_echo_n "checking for .preinit_array/.init_array/.fini_array support... " >&6; }
+if ${gcc_cv_initfini_array+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x${build}" = "x${target}" && test "x${build}" = "x${host}"; then
+ case "${target}" in
+ ia64-*)
+ if test "$cross_compiling" = yes; then :
+ gcc_cv_initfini_array=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifndef __ELF__
+#error Not an ELF OS
+#endif
+/* We turn on .preinit_array/.init_array/.fini_array support for ia64
+ if it can be used. */
+static int x = -1;
+int main (void) { return x; }
+int foo (void) { x = 0; }
+int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;
+
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ gcc_cv_initfini_array=yes
+else
+ gcc_cv_initfini_array=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+;;
+ *)
+ gcc_cv_initfini_array=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 \
+ -a "$gcc_cv_gld_minor_version" -ge 22 \
+ -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_initfini_array=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ case $target:$gas in
+ *:yes)
+ sh_flags='"a"'
+ sh_type='%progbits'
+ ;;
+ i?86-*-solaris2*:no | x86_64-*-solaris2*:no)
+ sh_flags='"a"'
+ sh_type='@progbits'
+ ;;
+ sparc*-*-solaris2*:no)
+ sh_flags='#alloc'
+ sh_type='#progbits'
+ sh_quote='"'
+ ;;
+ esac
+ case "$target:$gnu_ld" in
+ *:yes)
+ cat > conftest.s <<EOF
+.section .dtors,$sh_flags,$sh_type
+.balign 4
+.byte 'A', 'A', 'A', 'A'
+.section .ctors,$sh_flags,$sh_type
+.balign 4
+.byte 'B', 'B', 'B', 'B'
+.section .fini_array.65530,$sh_flags,$sh_type
+.balign 4
+.byte 'C', 'C', 'C', 'C'
+.section .init_array.65530,$sh_flags,$sh_type
+.balign 4
+.byte 'D', 'D', 'D', 'D'
+.section .dtors.64528,$sh_flags,$sh_type
+.balign 4
+.byte 'E', 'E', 'E', 'E'
+.section .ctors.64528,$sh_flags,$sh_type
+.balign 4
+.byte 'F', 'F', 'F', 'F'
+.section .fini_array.01005,$sh_flags,$sh_type
+.balign 4
+.byte 'G', 'G', 'G', 'G'
+.section .init_array.01005,$sh_flags,$sh_type
+.balign 4
+.byte 'H', 'H', 'H', 'H'
+.text
+.globl _start
+_start:
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHFFFFDDDDBBBB > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGEEEECCCCAAAA > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ *-*-solaris2*:no)
+ # When Solaris ld added constructor priority support, it was
+ # decided to only handle .init_array.N/.fini_array.N since
+ # there was no need for backwards compatibility with
+ # .ctors.N/.dtors.N. .ctors/.dtors remain as separate
+ # sections with correct execution order resp. to
+ # .init_array/.fini_array, while gld merges them into
+ # .init_array/.fini_array.
+ cat > conftest.s <<EOF
+.section $sh_quote.fini_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'
+.section $sh_quote.init_array.65530$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D'
+.section $sh_quote.fini_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'
+.section $sh_quote.init_array.01005$sh_quote,$sh_flags,$sh_type
+.align 4
+.byte 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H'
+.text
+.globl _start
+_start:
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .init_array conftest \
+ | grep HHHHHHHHDDDDDDDD > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .fini_array conftest \
+ | grep GGGGGGGGCCCCCCCC > /dev/null 2>&1; then
+ gcc_cv_initfini_array=yes
+ fi
+ ;;
+ esac
+ rm -f conftest conftest.*
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifndef __ELF__
+# error Not an ELF OS
+#endif
+#include <stdlib.h>
+#if defined __GLIBC_PREREQ
+# if __GLIBC_PREREQ (2, 4)
+# else
+# error GLIBC 2.4 required
+# endif
+#else
+# if defined __sun__ && defined __svr4__
+ /* Solaris ld.so.1 supports .init_array/.fini_array since Solaris 8. */
+# else
+# error The C library not known to support .init_array/.fini_array
+# endif
+#endif
+
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ gcc_cv_initfini_array=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext;;
+ esac
+ else
+ case "${target}" in
+ aarch64*-linux-gnu*)
+ # AArch64 postdates glibc support for .init_array/.fini_array,
+ # so we don't need the preprocessor test above.
+ gcc_cv_initfini_array=yes
+ ;;
+
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking cross compile... guessing" >&5
+$as_echo_n "checking cross compile... guessing... " >&6; }
+ gcc_cv_initfini_array=no
+ ;;
+ esac
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_initfini_array" >&5
+$as_echo "$gcc_cv_initfini_array" >&6; }
+ enable_initfini_array=$gcc_cv_initfini_array
+
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_INITFINI_ARRAY_SUPPORT `if test $enable_initfini_array = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+
+# Check if we have .[us]leb128, and support symbol arithmetic with it.
+# Older versions of GAS and some non-GNU assemblers, have a bugs handling
+# these directives, even when they appear to accept them.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .sleb128 and .uleb128" >&5
+$as_echo_n "checking assembler for .sleb128 and .uleb128... " >&6; }
+if ${gcc_cv_as_leb128+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_leb128=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .data
+ .uleb128 L2 - L1
+L1:
+ .uleb128 1280
+ .sleb128 -1010
+L2:
+ .uleb128 0x8000000000000000
+' > 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
+
+if test "x$gcc_cv_objdump" != x; then
+ if $gcc_cv_objdump -s conftest.o 2>/dev/null \
+ | grep '04800a8e 78808080 80808080 808001' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+elif test "x$gcc_cv_otool" != x; then
+ if $gcc_cv_otool -d conftest.o 2>/dev/null \
+ | grep '04 80 0a 8e 78 80 80 80 80 80 80 80 80 80 01' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+else
+ # play safe, assume the assembler is broken.
+ :
+fi
+
+ 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_leb128" >&5
+$as_echo "$gcc_cv_as_leb128" >&6; }
+if test $gcc_cv_as_leb128 = yes; then
+
+$as_echo "#define HAVE_AS_LEB128 1" >>confdefs.h
+
+fi
+if test $gcc_cv_as_leb128 != yes; then
+
+$as_echo "#define HAVE_AS_LEB128 0" >>confdefs.h
+
+fi
+
+# Determine if an .eh_frame section is read-only.
+gcc_fn_eh_frame_ro () {
+ $gcc_cv_as $1 -o conftest.o conftest.s > /dev/null 2>&1 && \
+ $gcc_cv_objdump -h conftest.o 2>/dev/null | \
+ sed -e '/.eh_frame/!d' -e N | grep READONLY > /dev/null
+}
+
+# Check if we have assembler support for unwind directives.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for cfi directives" >&5
+$as_echo_n "checking assembler for cfi directives... " >&6; }
+if ${gcc_cv_as_cfi_directive+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_cfi_directive=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .cfi_startproc
+ .cfi_offset 0, 0
+ .cfi_same_value 1
+ .cfi_def_cfa 1, 2
+ .cfi_escape 1, 2, 3, 4, 5
+ .cfi_endproc' > 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
+ case "$target" in
+ *-*-solaris*)
+ # If the linker used on Solaris (like Sun ld) isn't capable of merging
+ # read-only and read-write sections, we need to make sure that the
+ # assembler used emits read-write .eh_frame sections.
+ if test "x$gcc_cv_ld_ro_rw_mix" = xread-write; then
+ gcc_cv_as_cfi_directive=yes
+ elif test "x$gcc_cv_objdump" = x; then
+ # No objdump, err on the side of caution.
+ gcc_cv_as_cfi_directive=no
+ else
+ if test x$gas = xyes; then
+ as_32_opt="--32"
+ as_64_opt="--64"
+ else
+ as_32_opt="-m32"
+ as_64_opt="-m64"
+ fi
+ case "$target" in
+ sparc*-*-solaris2.*)
+ # On Solaris/SPARC, .eh_frame sections should always be read-write.
+ if gcc_fn_eh_frame_ro $as_32_opt \
+ || gcc_fn_eh_frame_ro $as_64_opt; then
+ gcc_cv_as_cfi_directive=no
+ else
+ gcc_cv_as_cfi_directive=yes
+ fi
+ ;;
+ i?86-*-solaris2.* | x86_64-*-solaris2.*)
+ # On Solaris/x86, make sure that GCC and assembler agree on using
+ # read-only .eh_frame sections for 64-bit.
+ if gcc_fn_eh_frame_ro $as_32_opt; then
+ gcc_cv_as_cfi_directive=no
+ elif gcc_fn_eh_frame_ro $as_64_opt; then
+ gcc_cv_as_cfi_directive=yes
+ else
+ gcc_cv_as_cfi_directive=no
+ fi
+ ;;
+ esac
+ fi
+ ;;
+ *-*-*)
+ gcc_cv_as_cfi_directive=yes
+ ;;
+esac
+ 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_cfi_directive" >&5
+$as_echo "$gcc_cv_as_cfi_directive" >&6; }
+
+
+if test $gcc_cv_as_cfi_directive = yes && test x$gcc_cv_objdump != x; then
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for working cfi advance" >&5
+$as_echo_n "checking assembler for working cfi advance... " >&6; }
+if ${gcc_cv_as_cfi_advance_working+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_cfi_advance_working=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .cfi_startproc
+ .cfi_adjust_cfa_offset 64
+ .skip 75040, 0
+ .cfi_adjust_cfa_offset 128
+ .cfi_endproc' > 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
+
+if $gcc_cv_objdump -Wf conftest.o 2>/dev/null \
+ | grep 'DW_CFA_advance_loc[24]:[ ][ ]*75040[ ]' >/dev/null; then
+ gcc_cv_as_cfi_advance_working=yes
+fi
+
+ 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_cfi_advance_working" >&5
+$as_echo "$gcc_cv_as_cfi_advance_working" >&6; }
+
+
+else
+ # no objdump, err on the side of caution
+ gcc_cv_as_cfi_advance_working=no
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_CFI_DIRECTIVE `if test $gcc_cv_as_cfi_directive = yes \
+ && test $gcc_cv_as_cfi_advance_working = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for cfi personality directive" >&5
+$as_echo_n "checking assembler for cfi personality directive... " >&6; }
+if ${gcc_cv_as_cfi_personality_directive+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_cfi_personality_directive=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .cfi_startproc
+ .cfi_personality 0, symbol
+ .cfi_endproc' > 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_cfi_personality_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_cfi_personality_directive" >&5
+$as_echo "$gcc_cv_as_cfi_personality_directive" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_CFI_PERSONALITY_DIRECTIVE `if test $gcc_cv_as_cfi_personality_directive = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for cfi sections directive" >&5
+$as_echo_n "checking assembler for cfi sections directive... " >&6; }
+if ${gcc_cv_as_cfi_sections_directive+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_cfi_sections_directive=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .cfi_sections .debug_frame, .eh_frame
+ .cfi_startproc
+ .cfi_endproc' > 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
+ case $target_os in
+ win32 | pe | cygwin* | mingw32*)
+ # Need to check that we generated the correct relocation for the
+ # .debug_frame section. This was fixed for binutils 2.21.
+ gcc_cv_as_cfi_sections_directive=no
+ if test "x$gcc_cv_objdump" != x; then
+ if $gcc_cv_objdump -j .debug_frame -r conftest.o 2>/dev/null | \
+ grep secrel > /dev/null; then
+ gcc_cv_as_cfi_sections_directive=yes
+ fi
+ fi
+ ;;
+ *)
+ gcc_cv_as_cfi_sections_directive=yes
+ ;;
+esac
+ 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_cfi_sections_directive" >&5
+$as_echo "$gcc_cv_as_cfi_sections_directive" >&6; }
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_CFI_SECTIONS_DIRECTIVE `if test $gcc_cv_as_cfi_sections_directive = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+# GAS versions up to and including 2.11.0 may mis-optimize
+# .eh_frame data.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for eh_frame optimization" >&5
+$as_echo_n "checking assembler for eh_frame optimization... " >&6; }
+if ${gcc_cv_as_eh_frame+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_eh_frame=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+.LFB1:
+ .4byte 0
+.L1:
+ .4byte 0
+.LFE1:
+ .section .eh_frame,"aw",@progbits
+__FRAME_BEGIN__:
+ .4byte .LECIE1-.LSCIE1
+.LSCIE1:
+ .4byte 0x0
+ .byte 0x1
+ .ascii "z\0"
+ .byte 0x1
+ .byte 0x78
+ .byte 0x1a
+ .byte 0x0
+ .byte 0x4
+ .4byte 1
+ .p2align 1
+.LECIE1:
+.LSFDE1:
+ .4byte .LEFDE1-.LASFDE1
+.LASFDE1:
+ .4byte .LASFDE1-__FRAME_BEGIN__
+ .4byte .LFB1
+ .4byte .LFE1-.LFB1
+ .byte 0x4
+ .4byte .LFE1-.LFB1
+ .byte 0x4
+ .4byte .L1-.LFB1
+.LEFDE1:' > 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
+ cat > conftest.lit <<EOF
+ 0000 10000000 00000000 017a0001 781a0004 .........z..x...
+ 0010 01000000 12000000 18000000 00000000 ................
+ 0020 08000000 04080000 0044 .........D
+EOF
+cat > conftest.big <<EOF
+ 0000 00000010 00000000 017a0001 781a0004 .........z..x...
+ 0010 00000001 00000012 00000018 00000000 ................
+ 0020 00000008 04000000 0844 .........D
+EOF
+ # If the assembler didn't choke, and we can objdump,
+ # and we got the correct data, then succeed.
+ # The text in the here-document typically retains its unix-style line
+ # endings, while the output of objdump will use host line endings.
+ # Therefore, use diff -b for the comparisons.
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -s -j .eh_frame conftest.o 2>/dev/null \
+ | tail -3 > conftest.got \
+ && { diff -b conftest.lit conftest.got > /dev/null 2>&1 \
+ || diff -b conftest.big conftest.got > /dev/null 2>&1; }
+ then
+ gcc_cv_as_eh_frame=yes
+ elif { ac_try='$gcc_cv_as -o conftest.o --traditional-format /dev/null'
+ { { 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_eh_frame=buggy
+ else
+ # Uh oh, what do we do now?
+ gcc_cv_as_eh_frame=no
+ fi
+ 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_eh_frame" >&5
+$as_echo "$gcc_cv_as_eh_frame" >&6; }
+
+
+
+if test $gcc_cv_as_eh_frame = buggy; then
+
+$as_echo "#define USE_AS_TRADITIONAL_FORMAT 1" >>confdefs.h
+
+fi
+
+# Test if the assembler supports the section flag 'e' or #exclude for
+# specifying an excluded section.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section exclude flag" >&5
+$as_echo_n "checking assembler for section exclude flag... " >&6; }
+if ${gcc_cv_as_section_exclude_e+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_section_exclude_e=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section foo1,"e"
+ .byte 0,0,0,0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_section_exclude_e=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_section_exclude_e" >&5
+$as_echo "$gcc_cv_as_section_exclude_e" >&6; }
+
+
+if test $gcc_cv_as_section_exclude_e = no; then
+ case "${target}" in
+ # Solaris as uses #exclude instead.
+ *-*-solaris2*)
+ case "${target}" in
+ sparc*-*-solaris2*)
+ conftest_s='.section "foo1", #exclude'
+ ;;
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ conftest_s='.section foo1, #exclude'
+ ;;
+ esac
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section exclude flag" >&5
+$as_echo_n "checking assembler for section exclude flag... " >&6; }
+if ${gcc_cv_as_section_exclude_hash+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_section_exclude_hash=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s
+ .byte 0,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_section_exclude_hash=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_section_exclude_hash" >&5
+$as_echo "$gcc_cv_as_section_exclude_hash" >&6; }
+
+
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SECTION_EXCLUDE `if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'R' flag" >&5
+$as_echo_n "checking assembler for section 'R' flag... " >&6; }
+if ${gcc_cv_as_shf_gnu_retain+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_gnu_retain=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"awR",%progbits
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_shf_gnu_retain=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_shf_gnu_retain" >&5
+$as_echo "$gcc_cv_as_shf_gnu_retain" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_GNU_RETAIN `if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+# Test if the assembler supports the section flag 'o' for specifying
+# section with link-order.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'o', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_section_link_order=no
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'o' flag" >&5
+$as_echo_n "checking assembler for section 'o' flag... " >&6; }
+if ${gcc_cv_as_section_link_order+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_section_link_order=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .foo,"a"
+.byte 0
+.section __patchable_function_entries,"awo",%progbits,.foo
+.byte 0' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_section_link_order=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_section_link_order" >&5
+$as_echo "$gcc_cv_as_section_link_order" >&6; }
+
+
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SECTION_LINK_ORDER `if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
+$as_echo_n "checking assembler for section merging support... " >&6; }
+if ${gcc_cv_as_shf_merge+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_merge=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .rodata.str, "aMS", @progbits, 1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_shf_merge=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_shf_merge" >&5
+$as_echo "$gcc_cv_as_shf_merge" >&6; }
+
+
+if test $gcc_cv_as_shf_merge = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
+$as_echo_n "checking assembler for section merging support... " >&6; }
+if ${gcc_cv_as_shf_merge+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_shf_merge=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .rodata.str, "aMS", %progbits, 1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_shf_merge=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_shf_merge" >&5
+$as_echo "$gcc_cv_as_shf_merge" >&6; }
+
+
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SHF_MERGE `if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+gcc_cv_ld_aligned_shf_merge=yes
+case "$target" in
+ # SHF_MERGE support is broken in Solaris ld up to Solaris 11.3/SPARC for
+ # alignment > 1.
+ sparc*-*-solaris2.11*)
+ if test x"$gnu_ld" = xno \
+ && test "$ld_vers_major" -lt 2 && test "$ld_vers_minor" -lt 3159; then
+ gcc_cv_ld_aligned_shf_merge=no
+ fi
+ ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_ALIGNED_SHF_MERGE `if test $gcc_cv_ld_aligned_shf_merge = yes; then echo 1; else echo 0; fi`
+_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 :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_comdat_group=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .text,"axG",@progbits,.foo,comdat' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_comdat_group=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_comdat_group" >&5
+$as_echo "$gcc_cv_as_comdat_group" >&6; }
+
+
+if test $gcc_cv_as_comdat_group = yes; then
+ gcc_cv_as_comdat_group_percent=no
+ gcc_cv_as_comdat_group_group=no
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for COMDAT group support (GNU as, %type)" >&5
+$as_echo_n "checking assembler for COMDAT group support (GNU as, %type)... " >&6; }
+if ${gcc_cv_as_comdat_group_percent+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_comdat_group_percent=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .text,"axG",%progbits,.foo,comdat' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_comdat_group_percent=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_comdat_group_percent" >&5
+$as_echo "$gcc_cv_as_comdat_group_percent" >&6; }
+
+
+ if test $gcc_cv_as_comdat_group_percent = yes; then
+ gcc_cv_as_comdat_group_group=no
+ else
+ case "${target}" in
+ # Sun as uses a completely different syntax.
+ *-*-solaris2*)
+ case "${target}" in
+ sparc*-*-solaris2*)
+ conftest_s='
+ .group foo,".text%foo",#comdat
+ .section ".text%foo", #alloc,#execinstr,#progbits
+ .globl foo
+ foo:
+ '
+ ;;
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ conftest_s='
+ .group foo,.text%foo,#comdat
+ .section .text%foo, "ax", @progbits
+ .globl foo
+ foo:
+ '
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for COMDAT group support (Sun as, .group)" >&5
+$as_echo_n "checking assembler for COMDAT group support (Sun as, .group)... " >&6; }
+if ${gcc_cv_as_comdat_group_group+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_comdat_group_group=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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_comdat_group_group=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_comdat_group_group" >&5
+$as_echo "$gcc_cv_as_comdat_group_group" >&6; }
+
+
+ ;;
+ esac
+ if test -z "${gcc_cv_as_comdat_group_group+set}"; then
+ gcc_cv_as_comdat_group_group=no
+ fi
+ fi
+fi
+if test x"$ld_is_gold" = xyes; then
+ comdat_group=yes
+elif test x"$ld_is_mold" = xyes; then
+ comdat_group=yes
+elif test $in_tree_ld = yes ; then
+ comdat_group=no
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ comdat_group=yes
+ fi
+elif echo "$ld_ver" | grep GNU > /dev/null; then
+ comdat_group=yes
+ if test 0"$ld_date" -lt 20050308; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2005-03-08, fail
+ comdat_group=no
+ elif test "$ld_vers_major" -lt 2; then
+ comdat_group=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 16; then
+ comdat_group=no
+ fi
+ fi
+else
+ case "${target}" in
+ *-*-solaris2.1[1-9]*)
+ comdat_group=no
+ # Sun ld has COMDAT group support since Solaris 9, but it doesn't
+ # interoperate with GNU as until Solaris 11 build 130, i.e. ld
+ # version 1.688.
+ #
+ # If using Sun as for COMDAT group as emitted by GCC, one needs at
+ # least ld version 1.2267.
+ if test "$ld_vers_major" -gt 1; then
+ comdat_group=yes
+ elif test "x$gas_flag" = xyes && test "$ld_vers_minor" -ge 1688; then
+ comdat_group=yes
+ elif test "$ld_vers_minor" -ge 2267; then
+ comdat_group=yes
+ fi
+ ;;
+ *)
+ # Assume linkers other than GNU ld don't support COMDAT group.
+ comdat_group=no
+ ;;
+ esac
+fi
+# Allow overriding the automatic COMDAT group tests above.
+# Check whether --enable-comdat was given.
+if test "${enable_comdat+set}" = set; then :
+ enableval=$enable_comdat; comdat_group="$enable_comdat"
+fi
+
+if test $comdat_group = no; then
+ gcc_cv_as_comdat_group=no
+ gcc_cv_as_comdat_group_percent=no
+ gcc_cv_as_comdat_group_group=no
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_COMDAT_GROUP `if test $gcc_cv_as_comdat_group = yes \
+ || test $gcc_cv_as_comdat_group_percent = yes \
+ || test $gcc_cv_as_comdat_group_group = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+# Restrict this test to Solaris/x86: other targets define this statically.
+case "${target}" in
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for hidden thunks in linkonce sections" >&5
+$as_echo_n "checking support for hidden thunks in linkonce sections... " >&6; }
+ if test $in_tree_ld = yes || echo "$ld_ver" | grep GNU > /dev/null; then
+ hidden_linkonce=yes
+ else
+ case "${target}" in
+ # Full support for hidden thunks in linkonce sections only appeared in
+ # Solaris 11/OpenSolaris.
+ *-*-solaris2.1[1-9]*)
+ hidden_linkonce=yes
+ ;;
+ *)
+ hidden_linkonce=no
+ ;;
+ esac
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hidden_linkonce" >&5
+$as_echo "$hidden_linkonce" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define USE_HIDDEN_LINKONCE `if test $hidden_linkonce = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for line table is_stmt support" >&5
+$as_echo_n "checking assembler for line table is_stmt support... " >&6; }
+if ${gcc_cv_as_is_stmt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_is_stmt=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .file 1 "conf.c"
+ .loc 1 1 0 is_stmt 1' > 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_is_stmt=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_is_stmt" >&5
+$as_echo "$gcc_cv_as_is_stmt" >&6; }
+if test $gcc_cv_as_is_stmt = yes; then
+
+$as_echo "#define HAVE_GAS_LOC_STMT 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for line table discriminator support" >&5
+$as_echo_n "checking assembler for line table discriminator support... " >&6; }
+if ${gcc_cv_as_discriminator+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_discriminator=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ .file 1 "conf.c"
+ .loc 1 1 0 discriminator 1' > 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_discriminator=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_discriminator" >&5
+$as_echo "$gcc_cv_as_discriminator" >&6; }
+if test $gcc_cv_as_discriminator = yes; then
+
+$as_echo "#define HAVE_GAS_DISCRIMINATOR 1" >>confdefs.h
+
+fi
+
+
+# Catch the newlib flag of the same name so we can gate GCC features on it.
+# Check whether --enable-newlib-nano-formatted-io was given.
+if test "${enable_newlib_nano_formatted_io+set}" = set; then :
+ enableval=$enable_newlib_nano_formatted_io; case "${enableval}" in
+ yes|no)
+ ;;
+ *)
+ as_fn_error $? "unknown newlib-nano-formatted-io setting $enableval" "$LINENO" 5
+ ;;
+esac
+fi
+
+
+# Thread-local storage - the check is heavily parameterized.
+conftest_s=
+tls_as_opt=
+case "$target" in
+ alpha*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ ldq $27,__tls_get_addr($29) !literal!1
+ lda $16,foo($29) !tlsgd!1
+ jsr $26,($27),__tls_get_addr !lituse_tlsgd!1
+ ldq $27,__tls_get_addr($29) !literal!2
+ lda $16,foo($29) !tlsldm!2
+ jsr $26,($27),__tls_get_addr !lituse_tlsldm!2
+ ldq $1,foo($29) !gotdtprel
+ ldah $2,foo($29) !dtprelhi
+ lda $3,foo($2) !dtprello
+ lda $4,foo($29) !dtprel
+ ldq $1,foo($29) !gottprel
+ ldah $2,foo($29) !tprelhi
+ lda $3,foo($2) !tprello
+ lda $4,foo($29) !tprel'
+ tls_as_opt=--fatal-warnings
+ ;;
+ arc*-*-*)
+ conftest_s='
+ add_s r0,r0, @foo@tpoff'
+ ;;
+ cris-*-*|crisv32-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+x: .long 25
+ .text
+ move.d x:IE,$r10
+ nop'
+ tls_as_opt=--fatal-warnings
+ ;;
+ frv*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+x: .long 25
+ .text
+ call #gettlsoff(x)'
+ ;;
+ hppa*-*-linux*)
+ conftest_s='
+t1: .reg %r20
+t2: .reg %r21
+gp: .reg %r19
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .align 4
+ addil LT%foo-$tls_gdidx$,gp
+ ldo RT%foo-$tls_gdidx$(%r1),%arg0
+ b __tls_get_addr
+ nop
+ addil LT%foo-$tls_ldidx$,gp
+ b __tls_get_addr
+ ldo RT%foo-$tls_ldidx$(%r1),%arg0
+ addil LR%foo-$tls_dtpoff$,%ret0
+ ldo RR%foo-$tls_dtpoff$(%r1),%t1
+ mfctl %cr27,%t1
+ addil LT%foo-$tls_ieoff$,gp
+ ldw RT%foo-$tls_ieoff$(%r1),%t2
+ add %t1,%t2,%t3
+ mfctl %cr27,%t1
+ addil LR%foo-$tls_leoff$,%t1
+ ldo RR%foo-$tls_leoff$(%r1),%t2'
+ tls_as_opt=--fatal-warnings
+ ;;
+ arm*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+.word foo(gottpoff)
+.word foo(tpoff)
+.word foo(tlsgd)
+.word foo(tlsldm)
+.word foo(tlsldo)'
+ ;;
+ i[34567]86-*-* | x86_64-*-*)
+ case "$target" in
+ i[34567]86-*-solaris2.* | x86_64-*-solaris2.*)
+ on_solaris=yes
+ ;;
+ *)
+ on_solaris=no
+ ;;
+ esac
+ if test x$on_solaris = xyes && test x$gas_flag = xno; then
+ conftest_s='
+ .section .tdata,"awt",@progbits'
+ tls_section_flag=t
+
+$as_echo "#define TLS_SECTION_ASM_FLAG 't'" >>confdefs.h
+
+ else
+ conftest_s='
+ .section ".tdata","awT",@progbits'
+ tls_section_flag=T
+ tls_as_opt="--fatal-warnings"
+ fi
+ case "$target" in
+ i[34567]86-*-*)
+ if test x$on_solaris = xyes; then
+ case $gas_flag in
+ yes) tls_as_opt="$tls_as_opt --32" ;;
+ esac
+ fi
+ conftest_s="$conftest_s
+foo: .long 25
+ .text
+ movl %gs:0, %eax
+ leal foo@tlsgd(,%ebx,1), %eax
+ leal foo@tlsldm(%ebx), %eax
+ leal foo@dtpoff(%eax), %edx
+ movl foo@gottpoff(%ebx), %eax
+ subl foo@gottpoff(%ebx), %eax
+ addl foo@gotntpoff(%ebx), %eax
+ movl foo@indntpoff, %eax
+ movl \$foo@tpoff, %eax
+ subl \$foo@tpoff, %eax
+ leal foo@ntpoff(%ecx), %eax"
+ ;;
+ x86_64-*-*)
+ if test x$on_solaris = xyes; then
+ case $gas_flag in
+ yes) tls_as_opt="$tls_as_opt --64" ;;
+ no) tls_as_opt="$tls_as_opt -xarch=amd64" ;;
+ esac
+ fi
+ conftest_s="$conftest_s
+foo: .long 25
+ .text
+ movq %fs:0, %rax
+ leaq foo@tlsgd(%rip), %rdi
+ leaq foo@tlsld(%rip), %rdi
+ leaq foo@dtpoff(%rax), %rdx
+ movq foo@gottpoff(%rip), %rax
+ movq \$foo@tpoff, %rax"
+ ;;
+ esac
+ ;;
+ ia64-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: data8 25
+ .text
+ addl r16 = @ltoff(@dtpmod(foo#)), gp
+ addl r17 = @ltoff(@dtprel(foo#)), gp
+ addl r18 = @ltoff(@tprel(foo#)), gp
+ addl r19 = @dtprel(foo#), gp
+ adds r21 = @dtprel(foo#), r13
+ movl r23 = @dtprel(foo#)
+ addl r20 = @tprel(foo#), gp
+ adds r22 = @tprel(foo#), r13
+ movl r24 = @tprel(foo#)'
+ tls_as_opt=--fatal-warnings
+ ;;
+ loongarch*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x: .word 2
+ .text
+ la.tls.gd $a0,x
+ bl __tls_get_addr'
+ tls_first_major=0
+ tls_first_minor=0
+ tls_as_opt='--fatal-warnings'
+ ;;
+ microblaze*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ addik r5,r20,x@TLSGD
+ addik r5,r20,x@TLSLDM'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ mips*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ addiu $4, $28, %tlsgd(x)
+ addiu $4, $28, %tlsldm(x)
+ lui $4, %dtprel_hi(x)
+ addiu $4, $4, %dtprel_lo(x)
+ lw $4, %gottprel(x)($28)
+ lui $4, %tprel_hi(x)
+ addiu $4, $4, %tprel_lo(x)'
+ tls_as_opt='-32 --fatal-warnings'
+ ;;
+ m68k-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+foo:
+ move.l x@TLSGD(%a5),%a0
+ move.l x@TLSLDM(%a5),%a0
+ move.l x@TLSLDO(%a5),%a0
+ move.l x@TLSIE(%a5),%a0
+ move.l x@TLSLE(%a5),%a0'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ nios2-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits'
+ tls_as_opt="--fatal-warnings"
+ ;;
+ aarch64*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+ adrp x0, :tlsgd:x
+ add x0, x0, #:tlsgd_lo12:x
+ bl __tls_get_addr
+ nop'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ or1k*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ l.movhi r3, tpoffha(foo)
+ l.add r3, r3, r10
+ l.lwz r4, tpofflo(foo)(r3)'
+ tls_as_opt=--fatal-warnings
+ ;;
+ powerpc-ibm-aix*)
+ conftest_s='
+ .extern __get_tpointer
+ .toc
+LC..1:
+ .tc a[TC],a[TL]@le
+ .csect .text[PR]
+.tlstest:
+ lwz 9,LC..1(2)
+ bla __get_tpointer
+ lwzx 3,9,3
+ .globl a
+ .csect a[TL],4
+a:
+ .space 4'
+ ;;
+ powerpc64*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+ .align 3
+ld0: .space 8
+ld1: .space 8
+x1: .space 8
+x2: .space 8
+x3: .space 8
+ .text
+ addi 3,2,ld0@got@tlsgd
+ bl .__tls_get_addr
+ nop
+ addi 3,2,ld1@toc
+ bl .__tls_get_addr
+ nop
+ addi 3,2,x1@got@tlsld
+ bl .__tls_get_addr
+ nop
+ addi 9,3,x1@dtprel
+ bl .__tls_get_addr
+ nop
+ addis 9,3,x2@dtprel@ha
+ addi 9,9,x2@dtprel@l
+ bl .__tls_get_addr
+ nop
+ ld 9,x3@got@dtprel(2)
+ add 9,9,3
+ bl .__tls_get_addr
+ nop'
+ tls_as_opt="-a64 --fatal-warnings"
+ ;;
+ powerpc*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+ .align 2
+ld0: .space 4
+ld1: .space 4
+x1: .space 4
+x2: .space 4
+x3: .space 4
+ .text
+ addi 3,31,ld0@got@tlsgd
+ bl __tls_get_addr
+ addi 3,31,x1@got@tlsld
+ bl __tls_get_addr
+ addi 9,3,x1@dtprel
+ addis 9,3,x2@dtprel@ha
+ addi 9,9,x2@dtprel@l
+ lwz 9,x3@got@tprel(31)
+ add 9,9,x@tls
+ addi 9,2,x1@tprel
+ addis 9,2,x2@tprel@ha
+ addi 9,9,x2@tprel@l'
+ tls_as_opt="-a32 --fatal-warnings"
+ ;;
+ riscv*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x: .word 2
+ .text
+ la.tls.gd a0,x
+ call __tls_get_addr'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ s390-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@NTPOFF
+ .long foo@GOTNTPOFF
+ .long foo@INDNTPOFF
+ l %r1,foo@GOTNTPOFF(%r12)
+ l %r1,0(%r1):tls_load:foo
+ bas %r14,0(%r1,%r13):tls_gdcall:foo
+ bas %r14,0(%r1,%r13):tls_ldcall:foo'
+ tls_as_opt="-m31 --fatal-warnings"
+ ;;
+ s390x-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .quad foo@TLSGD
+ .quad foo@TLSLDM
+ .quad foo@DTPOFF
+ .quad foo@NTPOFF
+ .quad foo@GOTNTPOFF
+ lg %r1,foo@GOTNTPOFF(%r12)
+ larl %r1,foo@INDNTPOFF
+ brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo
+ brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo'
+ tls_as_opt="-m64 -Aesame --fatal-warnings"
+ ;;
+ sh-*-* | sh[123456789lbe]*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@GOTTPOFF
+ .long foo@TPOFF'
+ tls_as_opt=--fatal-warnings
+ ;;
+ sparc*-*-*)
+ case "$target" in
+ sparc*-sun-solaris2.*)
+ on_solaris=yes
+ ;;
+ *)
+ on_solaris=no
+ ;;
+ esac
+ if test x$on_solaris = xyes && test x$gas_flag = xno; then
+ conftest_s='
+ .section ".tdata",#alloc,#write,#tls'
+ else
+ conftest_s='
+ .section ".tdata","awT",@progbits'
+ tls_as_opt="-32 --fatal-warnings"
+ fi
+ conftest_s="$conftest_s
+foo: .long 25
+ .text
+ sethi %tgd_hi22(foo), %o0
+ add %o0, %tgd_lo10(foo), %o1
+ add %l7, %o1, %o0, %tgd_add(foo)
+ call __tls_get_addr, %tgd_call(foo)
+ sethi %tldm_hi22(foo), %l1
+ add %l1, %tldm_lo10(foo), %l2
+ add %l7, %l2, %o0, %tldm_add(foo)
+ call __tls_get_addr, %tldm_call(foo)
+ sethi %tldo_hix22(foo), %l3
+ xor %l3, %tldo_lox10(foo), %l4
+ add %o0, %l4, %l5, %tldo_add(foo)
+ sethi %tie_hi22(foo), %o3
+ add %o3, %tie_lo10(foo), %o3
+ ld [%l7 + %o3], %o2, %tie_ld(foo)
+ add %g7, %o2, %o4, %tie_add(foo)
+ sethi %tle_hix22(foo), %l1
+ xor %l1, %tle_lox10(foo), %o5
+ ld [%g7 + %o5], %o1"
+ ;;
+ tilepro*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ addli r0, zero, tls_gd(foo)
+ auli r0, zero, tls_gd_ha16(foo)
+ addli r0, r0, tls_gd_lo16(foo)
+ jal __tls_get_addr
+ addli r0, zero, tls_ie(foo)
+ auli r0, r0, tls_ie_ha16(foo)
+ addli r0, r0, tls_ie_lo16(foo)'
+ tls_as_opt="--fatal-warnings"
+ ;;
+ tilegx*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ shl16insli r0, zero, hw0_last_tls_gd(foo)
+ shl16insli r0, zero, hw1_last_tls_gd(foo)
+ shl16insli r0, r0, hw0_tls_gd(foo)
+ jal __tls_get_addr
+ shl16insli r0, zero, hw1_last_tls_ie(foo)
+ shl16insli r0, r0, hw0_tls_ie(foo)'
+ tls_as_opt="--fatal-warnings"
+ ;;
+ xtensa*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ movi a8, foo@TLSFUNC
+ movi a10, foo@TLSARG
+ callx8.tls a8, foo@TLSCALL'
+ ;;
+esac
+set_have_as_tls=no
+if test "x$enable_tls" = xno ; then
+ : # TLS explicitly disabled.
+elif test "x$enable_tls" = xyes ; then
+ set_have_as_tls=yes # TLS explicitly enabled.
+elif test -z "$conftest_s"; then
+ : # If we don't have a check, assume no support.
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for thread-local storage support" >&5
+$as_echo_n "checking assembler for thread-local storage support... " >&6; }
+if ${gcc_cv_as_tls+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_tls=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $tls_as_opt -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_tls=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_tls" >&5
+$as_echo "$gcc_cv_as_tls" >&6; }
+if test $gcc_cv_as_tls = yes; then
+ set_have_as_tls=yes
+fi
+
+fi
+if test $set_have_as_tls = yes ; then
+
+$as_echo "#define HAVE_AS_TLS 1" >>confdefs.h
+
+fi
+
+# Target-specific assembler checks.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -Bstatic/-Bdynamic option" >&5
+$as_echo_n "checking linker -Bstatic/-Bdynamic option... " >&6; }
+gcc_cv_ld_static_dynamic=no
+gcc_cv_ld_static_option='-Bstatic'
+gcc_cv_ld_dynamic_option='-Bdynamic'
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_static_dynamic=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -Bstatic/-Bdynamic option
+ if $gcc_cv_ld --help 2>&1 | grep -- -Bstatic > /dev/null \
+ && $gcc_cv_ld --help 2>&1 | grep -- -Bdynamic > /dev/null; then
+ gcc_cv_ld_static_dynamic=yes
+ else
+ case "$target" in
+ # AIX ld uses -b flags
+ *-*-aix4.[23]* | *-*-aix[5-9]*)
+ gcc_cv_ld_static_dynamic=yes
+ gcc_cv_ld_static_option="-bstatic"
+ gcc_cv_ld_dynamic_option="-bdynamic"
+ ;;
+ # HP-UX ld uses -a flags to select between shared and archive.
+ *-*-hpux*)
+ if test x"$gnu_ld" = xno; then
+ gcc_cv_ld_static_dynamic=yes
+ gcc_cv_ld_static_option="-aarchive_shared"
+ gcc_cv_ld_dynamic_option="-adefault"
+ fi
+ ;;
+ # Solaris 2 ld always supports -Bstatic/-Bdynamic.
+ *-*-solaris2*)
+ gcc_cv_ld_static_dynamic=yes
+ ;;
+ esac
+ fi
+fi
+if test x"$gcc_cv_ld_static_dynamic" = xyes; then
+
+$as_echo "#define HAVE_LD_STATIC_DYNAMIC 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD_STATIC_OPTION "$gcc_cv_ld_static_option"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD_DYNAMIC_OPTION "$gcc_cv_ld_dynamic_option"
+_ACEOF
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_static_dynamic" >&5
+$as_echo "$gcc_cv_ld_static_dynamic" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --version-script option" >&5
+$as_echo_n "checking linker --version-script option... " >&6; }
+gcc_cv_ld_version_script=no
+ld_version_script_option=''
+if test $in_tree_ld = yes || test x"$gnu_ld" = xyes; then
+ gcc_cv_ld_version_script=yes
+ ld_version_script_option='--version-script'
+elif test x$gcc_cv_ld != x; then
+ case "$target" in
+ # Solaris 2 ld always supports -M. It also supports a subset of
+ # --version-script since Solaris 11.4, but requires
+ # -z gnu-version-script-compat to activate.
+ *-*-solaris2*)
+ gcc_cv_ld_version_script=yes
+ ld_version_script_option='-M'
+ ;;
+ esac
+fi
+# Don't AC_DEFINE result, only used in jit/Make-lang.in so far.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_version_script" >&5
+$as_echo "$gcc_cv_ld_version_script" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker soname option" >&5
+$as_echo_n "checking linker soname option... " >&6; }
+gcc_cv_ld_soname=no
+if test $in_tree_ld = yes || test x"$gnu_ld" = xyes; then
+ gcc_cv_ld_soname=yes
+ ld_soname_option='-soname'
+elif test x$gcc_cv_ld != x; then
+ case "$target" in
+ *-*-darwin*)
+ gcc_cv_ld_soname=yes
+ ld_soname_option='-install_name'
+ ;;
+ # Solaris 2 ld always supports -h. It also supports --soname for GNU
+ # ld compatiblity since some Solaris 10 update.
+ *-*-solaris2*)
+ gcc_cv_ld_soname=yes
+ ld_soname_option='-h'
+ ;;
+ esac
+fi
+# Don't AC_DEFINE result, only used in jit/Make-lang.in so far.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_soname" >&5
+$as_echo "$gcc_cv_ld_soname" >&6; }
+
+
+if test x"$demangler_in_ld" = xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --demangle support" >&5
+$as_echo_n "checking linker --demangle support... " >&6; }
+ gcc_cv_ld_demangle=no
+ if test $in_tree_ld = yes; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then \
+ gcc_cv_ld_demangle=yes
+ fi
+ elif test x$gcc_cv_ld != x -a x"$gnu_ld" = xyes; then
+ # Check if the GNU linker supports --demangle option
+ if $gcc_cv_ld --help 2>&1 | grep no-demangle > /dev/null; then
+ gcc_cv_ld_demangle=yes
+ fi
+ fi
+ if test x"$gcc_cv_ld_demangle" = xyes; then
+
+$as_echo "#define HAVE_LD_DEMANGLE 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_demangle" >&5
+$as_echo "$gcc_cv_ld_demangle" >&6; }
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker plugin support" >&5
+$as_echo_n "checking linker plugin support... " >&6; }
+gcc_cv_lto_plugin=0
+if test -f liblto_plugin.la; then
+ save_ld_ver="$ld_ver"
+ save_ld_vers_major="$ld_vers_major"
+ save_ld_vers_minor="$ld_vers_minor"
+ save_ld_is_gold="$ld_is_gold"
+
+ ld_is_gold=no
+
+ if test $in_tree_ld = yes -a x"$ORIGINAL_PLUGIN_LD_FOR_TARGET" = x"$gcc_cv_ld"; then
+ ld_ver="GNU ld"
+ # FIXME: ld_is_gold?
+ ld_vers_major="$gcc_cv_gld_major_version"
+ ld_vers_minor="$gcc_cv_gld_minor_version"
+ else
+ # Determine plugin linker version.
+ # FIXME: Partial duplicate from above, generalize.
+ ld_ver=`$ORIGINAL_PLUGIN_LD_FOR_TARGET --version 2>/dev/null | sed 1q`
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ if echo "$ld_ver" | grep "GNU gold" > /dev/null; then
+ ld_is_gold=yes
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
+ else
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
+ fi
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ fi
+ fi
+
+ # Determine plugin support.
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ # Require GNU ld or gold 2.21+ for plugin support by default.
+ if test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -ge 21; then
+ gcc_cv_lto_plugin=2
+ elif test "$ld_is_mold" = yes; then
+ gcc_cv_lto_plugin=2
+ # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
+ elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -eq 20; then
+ gcc_cv_lto_plugin=1
+ fi
+ fi
+
+ ld_ver="$save_ld_ver"
+ ld_vers_major="$save_ld_vers_major"
+ ld_vers_minor="$save_ld_vers_minor"
+ ld_is_gold="$save_ld_is_gold"
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LTO_PLUGIN $gcc_cv_lto_plugin
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_lto_plugin" >&5
+$as_echo "$gcc_cv_lto_plugin" >&6; }
+
+# Target OS-specific assembler checks.
+
+case "$target_os" in
+ darwin*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -mmacosx-version-min option" >&5
+$as_echo_n "checking assembler for -mmacosx-version-min option... " >&6; }
+if ${gcc_cv_as_mmacosx_version_min+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mmacosx_version_min=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mmacosx-version-min=10.1 -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_mmacosx_version_min=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_mmacosx_version_min" >&5
+$as_echo "$gcc_cv_as_mmacosx_version_min" >&6; }
+if test $gcc_cv_as_mmacosx_version_min = yes; then
+
+$as_echo "#define HAVE_AS_MMACOSX_VERSION_MIN_OPTION 1" >>confdefs.h
+
+fi
+
+ ;;
+esac
+
+# Target CPU-specific assembler checks.
+
+case "$target" in
+ aarch64*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -mabi option" >&5
+$as_echo_n "checking assembler for -mabi option... " >&6; }
+if ${gcc_cv_as_aarch64_mabi+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_aarch64_mabi=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mabi=lp64 -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_aarch64_mabi=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_aarch64_mabi" >&5
+$as_echo "$gcc_cv_as_aarch64_mabi" >&6; }
+
+
+ if test x$gcc_cv_as_aarch64_mabi = xyes; then
+
+$as_echo "#define HAVE_AS_MABI_OPTION 1" >>confdefs.h
+
+ else
+ if test x$with_abi = xilp32; then
+ as_fn_error $? "Assembler does not support -mabi=ilp32.\
+ Upgrade the Assembler." "$LINENO" 5
+ fi
+ if test x"$with_multilib_list" = xdefault; then
+ TM_MULTILIB_CONFIG=lp64
+ else
+ aarch64_multilibs=`echo $with_multilib_list | sed -e 's/,/ /g'`
+ for aarch64_multilib in ${aarch64_multilibs}; do
+ case ${aarch64_multilib} in
+ ilp32)
+ as_fn_error $? "Assembler does not support -mabi=ilp32.\
+ Upgrade the Assembler." "$LINENO" 5
+ ;;
+ *)
+ ;;
+ esac
+ done
+ fi
+ fi
+ # Check if we have binutils support for relocations types needed by -fpic
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -fpic relocs" >&5
+$as_echo_n "checking assembler for -fpic relocs... " >&6; }
+if ${gcc_cv_as_aarch64_picreloc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_aarch64_picreloc=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '
+ .text
+ ldr x0, [x2, #:gotpage_lo15:globalsym]
+ ' > 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_aarch64_picreloc=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_aarch64_picreloc" >&5
+$as_echo "$gcc_cv_as_aarch64_picreloc" >&6; }
+if test $gcc_cv_as_aarch64_picreloc = yes; then
+
+$as_echo "#define HAVE_AS_SMALL_PIC_RELOCS 1" >>confdefs.h
+
+fi
+
+ # Enable Branch Target Identification Mechanism and Return Address
+ # Signing by default.
+ # Check whether --enable-standard-branch-protection was given.
+if test "${enable_standard_branch_protection+set}" = set; then :
+ enableval=$enable_standard_branch_protection;
+ case $enableval in
+ yes)
+ tm_defines="${tm_defines} TARGET_ENABLE_BTI=1 TARGET_ENABLE_PAC_RET=1"
+ ;;
+ no)
+ ;;
+ *)
+ as_fn_error $? "'$enableval' is an invalid value for --enable-standard-branch-protection.\
+ Valid choices are 'yes' and 'no'." "$LINENO" 5
+ ;;
+ esac
+
+fi
+
+ # Enable default workaround for AArch64 Cortex-A53 erratum 835769.
+ # Check whether --enable-fix-cortex-a53-835769 was given.
+if test "${enable_fix_cortex_a53_835769+set}" = set; then :
+ enableval=$enable_fix_cortex_a53_835769;
+ case $enableval in
+ yes)
+ tm_defines="${tm_defines} TARGET_FIX_ERR_A53_835769_DEFAULT=1"
+ ;;
+ no)
+ ;;
+ *)
+ as_fn_error $? "'$enableval' is an invalid value for --enable-fix-cortex-a53-835769.\
+ Valid choices are 'yes' and 'no'." "$LINENO" 5
+ ;;
+
+ esac
+
+fi
+
+ # Enable default workaround for AArch64 Cortex-A53 erratum 843419.
+ # Check whether --enable-fix-cortex-a53-843419 was given.
+if test "${enable_fix_cortex_a53_843419+set}" = set; then :
+ enableval=$enable_fix_cortex_a53_843419;
+ case $enableval in
+ yes)
+ tm_defines="${tm_defines} TARGET_FIX_ERR_A53_843419_DEFAULT=1"
+ ;;
+ no)
+ ;;
+ *)
+ as_fn_error $? "'$enableval' is an invalid value for --enable-fix-cortex-a53-843419.\
+ Valid choices are 'yes' and 'no'." "$LINENO" 5
+ ;;
+
+ esac
+
+fi
+
+ ;;
+
+ # All TARGET_ABI_OSF targets.
+ alpha*-*-linux* | alpha*-*-*bsd*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for explicit relocation support" >&5
+$as_echo_n "checking assembler for explicit relocation support... " >&6; }
+if ${gcc_cv_as_alpha_explicit_relocs+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_alpha_explicit_relocs=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .set nomacro
+ .text
+ extbl $3, $2, $3 !lituse_bytoff!1
+ ldq $2, a($29) !literal!1
+ ldq $4, b($29) !literal!2
+ ldq_u $3, 0($2) !lituse_base!1
+ ldq $27, f($29) !literal!5
+ jsr $26, ($27), f !lituse_jsr!5
+ ldah $29, 0($26) !gpdisp!3
+ lda $0, c($29) !gprel
+ ldah $1, d($29) !gprelhigh
+ lda $1, d($1) !gprellow
+ lda $29, 0($29) !gpdisp!3' > 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_alpha_explicit_relocs=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_alpha_explicit_relocs" >&5
+$as_echo "$gcc_cv_as_alpha_explicit_relocs" >&6; }
+if test $gcc_cv_as_alpha_explicit_relocs = yes; then
+
+$as_echo "#define HAVE_AS_EXPLICIT_RELOCS 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for jsrdirect relocation support" >&5
+$as_echo_n "checking assembler for jsrdirect relocation support... " >&6; }
+if ${gcc_cv_as_alpha_jsrdirect_relocs+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_alpha_jsrdirect_relocs=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .set nomacro
+ .text
+ ldq $27, a($29) !literal!1
+ jsr $26, ($27), a !lituse_jsrdirect!1' > 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_alpha_jsrdirect_relocs=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_alpha_jsrdirect_relocs" >&5
+$as_echo "$gcc_cv_as_alpha_jsrdirect_relocs" >&6; }
+if test $gcc_cv_as_alpha_jsrdirect_relocs = yes; then
+
+$as_echo "#define HAVE_AS_JSRDIRECT_RELOCS 1" >>confdefs.h
+
+fi
+
+ ;;
+
+ avr-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --mlink-relax option" >&5
+$as_echo_n "checking assembler for --mlink-relax option... " >&6; }
+if ${gcc_cv_as_avr_mlink_relax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_avr_mlink_relax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --mlink-relax -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_avr_mlink_relax=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_avr_mlink_relax" >&5
+$as_echo "$gcc_cv_as_avr_mlink_relax" >&6; }
+if test $gcc_cv_as_avr_mlink_relax = yes; then
+
+$as_echo "#define HAVE_AS_AVR_MLINK_RELAX_OPTION 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -mrmw option" >&5
+$as_echo_n "checking assembler for -mrmw option... " >&6; }
+if ${gcc_cv_as_avr_mrmw+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_avr_mrmw=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mrmw -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_avr_mrmw=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_avr_mrmw" >&5
+$as_echo "$gcc_cv_as_avr_mrmw" >&6; }
+if test $gcc_cv_as_avr_mrmw = yes; then
+
+$as_echo "#define HAVE_AS_AVR_MRMW_OPTION 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for __gcc_isr pseudo instruction" >&5
+$as_echo_n "checking assembler for __gcc_isr pseudo instruction... " >&6; }
+if ${gcc_cv_as_avr_mgccisr+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_avr_mgccisr=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ __gcc_isr 1
+ __gcc_isr 2
+ __gcc_isr 0,r24
+ ' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mgcc-isr -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_avr_mgccisr=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_avr_mgccisr" >&5
+$as_echo "$gcc_cv_as_avr_mgccisr" >&6; }
+if test $gcc_cv_as_avr_mgccisr = yes; then
+
+$as_echo "#define HAVE_AS_AVR_MGCCISR_OPTION 1" >>confdefs.h
+
+fi
+
+
+ # Check how default linker description file implements .rodata for
+ # avrxmega3 (PR21472). avr-gcc assumes .rodata is *not* loaded to
+ # RAM so avr-gcc skips __do_copy_data for .rodata objects.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking binutils for avrxmega3 .rodata support" >&5
+$as_echo_n "checking binutils for avrxmega3 .rodata support... " >&6; }
+ cat > conftest.s <<EOF
+ .section .rodata,"a",@progbits
+ .global xxvaryy
+ ;; avr-nm should print "... R xxvaryy", not "... D xxvaryy".
+ xxvaryy:
+ .word 1
+EOF
+ rm -f conftest.nm
+ { ac_try='$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ { ac_try='$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ { ac_try='$gcc_cv_nm conftest.elf > conftest.nm'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+ if test -s conftest.nm
+ then
+ if grep ' R xxvaryy' conftest.nm > /dev/null; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no: avrxmega3 .rodata located in RAM" >&5
+$as_echo "no: avrxmega3 .rodata located in RAM" >&6; }
+ echo "$as_me: nm output was" >&5
+ cat conftest.nm >&5
+ avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)" >&5
+$as_echo "$as_me: WARNING: support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)" >&2;}
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: test failed" >&5
+$as_echo "test failed" >&6; }
+ echo "$as_me: failed program was" >&5
+ cat conftest.s >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: see \`config.log' for details" >&5
+$as_echo "$as_me: WARNING: see \`config.log' for details" >&2;}
+ fi
+ rm -f conftest.s conftest.o conftest.elf conftest.nm
+ ;;
+
+ cris-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -no-mul-bug-abort option" >&5
+$as_echo_n "checking assembler for -no-mul-bug-abort option... " >&6; }
+if ${gcc_cv_as_cris_no_mul_bug+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_cris_no_mul_bug=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -no-mul-bug-abort -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_cris_no_mul_bug=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_cris_no_mul_bug" >&5
+$as_echo "$gcc_cv_as_cris_no_mul_bug" >&6; }
+if test $gcc_cv_as_cris_no_mul_bug = yes; then
+
+$as_echo "#define HAVE_AS_NO_MUL_BUG_ABORT_OPTION 1" >>confdefs.h
+
+fi
+
+ ;;
+
+ sparc*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -relax option" >&5
+$as_echo_n "checking assembler for -relax option... " >&6; }
+if ${gcc_cv_as_sparc_relax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_relax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -relax -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_sparc_relax=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_sparc_relax" >&5
+$as_echo "$gcc_cv_as_sparc_relax" >&6; }
+if test $gcc_cv_as_sparc_relax = yes; then
+
+$as_echo "#define HAVE_AS_RELAX_OPTION 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for GOTDATA_OP relocs" >&5
+$as_echo_n "checking assembler for GOTDATA_OP relocs... " >&6; }
+if ${gcc_cv_as_sparc_gotdata_op+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_gotdata_op=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+.align 4
+foo:
+ nop
+bar:
+ sethi %gdop_hix22(foo), %g1
+ xor %g1, %gdop_lox10(foo), %g1
+ ld [%l7 + %g1], %g2, %gdop(foo)' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -K PIC -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
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o -G > /dev/null 2>&1; then
+ if test x$gcc_cv_objdump != x; then
+ if $gcc_cv_objdump -s -j .text conftest 2> /dev/null \
+ | grep ' 03000004 82186004 c405c001'> /dev/null 2>&1; then
+ gcc_cv_as_sparc_gotdata_op=no
+ else
+ gcc_cv_as_sparc_gotdata_op=yes
+ fi
+ fi
+ fi
+ rm -f conftest
+ 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_sparc_gotdata_op" >&5
+$as_echo "$gcc_cv_as_sparc_gotdata_op" >&6; }
+if test $gcc_cv_as_sparc_gotdata_op = yes; then
+
+$as_echo "#define HAVE_AS_SPARC_GOTDATA_OP 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for unaligned pcrel relocs" >&5
+$as_echo_n "checking assembler for unaligned pcrel relocs... " >&6; }
+if ${gcc_cv_as_sparc_ua_pcrel+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_ua_pcrel=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+foo:
+ nop
+.data
+.align 4
+.byte 0
+.uaword %r_disp32(foo)' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -K PIC -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
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o -G > /dev/null 2>&1; then
+ gcc_cv_as_sparc_ua_pcrel=yes
+ fi
+ rm -f conftest
+ 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_sparc_ua_pcrel" >&5
+$as_echo "$gcc_cv_as_sparc_ua_pcrel" >&6; }
+if test $gcc_cv_as_sparc_ua_pcrel = yes; then
+
+$as_echo "#define HAVE_AS_SPARC_UA_PCREL 1" >>confdefs.h
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for unaligned pcrel relocs against hidden symbols" >&5
+$as_echo_n "checking assembler for unaligned pcrel relocs against hidden symbols... " >&6; }
+if ${gcc_cv_as_sparc_ua_pcrel_hidden+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_ua_pcrel_hidden=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.data
+.align 4
+.byte 0x31
+.uaword %r_disp32(foo)
+.byte 0x32, 0x33, 0x34
+.global foo
+.hidden foo
+foo:
+.skip 4' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -K PIC -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
+ if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+ && $gcc_cv_ld -o conftest conftest.o -G > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .data conftest 2> /dev/null \
+ | grep ' 31000000 07323334' > /dev/null 2>&1; then
+ if $gcc_cv_objdump -R conftest 2> /dev/null \
+ | grep 'DISP32' > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_as_sparc_ua_pcrel_hidden=yes
+ fi
+ fi
+ rm -f conftest
+ 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_sparc_ua_pcrel_hidden" >&5
+$as_echo "$gcc_cv_as_sparc_ua_pcrel_hidden" >&6; }
+if test $gcc_cv_as_sparc_ua_pcrel_hidden = yes; then
+
+$as_echo "#define HAVE_AS_SPARC_UA_PCREL_HIDDEN 1" >>confdefs.h
+
+fi
+
+
+fi
+ # unaligned pcrel relocs
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for offsetable %lo()" >&5
+$as_echo_n "checking assembler for offsetable %lo()... " >&6; }
+if ${gcc_cv_as_sparc_offsetable_lo10+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_offsetable_lo10=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ or %g1, %lo(ab) + 12, %g1
+ or %g1, %lo(ab + 12), %g1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=v9 -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
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -s -j .text conftest.o 2> /dev/null \
+ | grep ' 82106000 82106000' > /dev/null 2>&1; then
+ gcc_cv_as_sparc_offsetable_lo10=yes
+ fi
+ 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_sparc_offsetable_lo10" >&5
+$as_echo "$gcc_cv_as_sparc_offsetable_lo10" >&6; }
+if test $gcc_cv_as_sparc_offsetable_lo10 = yes; then
+
+$as_echo "#define HAVE_AS_OFFSETABLE_LO10 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for FMAF, HPC, and VIS 3.0 instructions" >&5
+$as_echo_n "checking assembler for FMAF, HPC, and VIS 3.0 instructions... " >&6; }
+if ${gcc_cv_as_sparc_fmaf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_fmaf=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ fmaddd %f0, %f2, %f4, %f6
+ addxccc %g1, %g2, %g3
+ fsrl32 %f2, %f4, %f8
+ fnaddd %f10, %f12, %f14' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=v9d -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_sparc_fmaf=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_sparc_fmaf" >&5
+$as_echo "$gcc_cv_as_sparc_fmaf" >&6; }
+if test $gcc_cv_as_sparc_fmaf = yes; then
+
+$as_echo "#define HAVE_AS_FMAF_HPC_VIS3 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for SPARC4 instructions" >&5
+$as_echo_n "checking assembler for SPARC4 instructions... " >&6; }
+if ${gcc_cv_as_sparc_sparc4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_sparc4=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ cxbe %g2, %g3, 1f
+1: cwbneg %g2, %g3, 1f
+1: sha1
+ md5
+ aes_kexpand0 %f4, %f6, %f8
+ des_round %f38, %f40, %f42, %f44
+ camellia_f %f54, %f56, %f58, %f60
+ kasumi_fi_xor %f46, %f48, %f50, %f52' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=sparc4 -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_sparc_sparc4=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_sparc_sparc4" >&5
+$as_echo "$gcc_cv_as_sparc_sparc4" >&6; }
+if test $gcc_cv_as_sparc_sparc4 = yes; then
+
+$as_echo "#define HAVE_AS_SPARC4 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for SPARC5 and VIS 4.0 instructions" >&5
+$as_echo_n "checking assembler for SPARC5 and VIS 4.0 instructions... " >&6; }
+if ${gcc_cv_as_sparc_sparc5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_sparc5=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ subxc %g1, %g2, %g3
+ fpadd8 %f0, %f2, %f4' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=sparc5 -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_sparc_sparc5=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_sparc_sparc5" >&5
+$as_echo "$gcc_cv_as_sparc_sparc5" >&6; }
+if test $gcc_cv_as_sparc_sparc5 = yes; then
+
+$as_echo "#define HAVE_AS_SPARC5_VIS4 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for SPARC6 instructions" >&5
+$as_echo_n "checking assembler for SPARC6 instructions... " >&6; }
+if ${gcc_cv_as_sparc_sparc6+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_sparc6=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ rd %entropy, %g1
+ fpsll64x %f0, %f2, %f4' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=sparc6 -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_sparc_sparc6=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_sparc_sparc6" >&5
+$as_echo "$gcc_cv_as_sparc_sparc6" >&6; }
+if test $gcc_cv_as_sparc_sparc6 = yes; then
+
+$as_echo "#define HAVE_AS_SPARC6 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for LEON instructions" >&5
+$as_echo_n "checking assembler for LEON instructions... " >&6; }
+if ${gcc_cv_as_sparc_leon+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_leon=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ smac %g2, %g3, %g1
+ umac %g2, %g3, %g1
+ casa [%g2] 0xb, %g3, %g1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -Aleon -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_sparc_leon=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_sparc_leon" >&5
+$as_echo "$gcc_cv_as_sparc_leon" >&6; }
+if test $gcc_cv_as_sparc_leon = yes; then
+
+$as_echo "#define HAVE_AS_LEON 1" >>confdefs.h
+
+fi
+
+ ;;
+
+ i[34567]86-*-* | x86_64-*-*)
+ case $target_os in
+ cygwin*)
+ # Full C++ conformance when using a shared libstdc++-v3 requires some
+ # support from the Cygwin DLL, which in more recent versions exports
+ # wrappers to aid in interposing and redirecting operators new, delete,
+ # etc., as per n2800 #17.6.4.6 [replacement.functions]. Check if we
+ # are configuring for a version of Cygwin that exports the wrappers.
+ if test x$host = x$target && test x$host_cpu = xi686; then
+ ac_fn_cxx_check_func "$LINENO" "__wrap__Znaj" "ac_cv_func___wrap__Znaj"
+if test "x$ac_cv_func___wrap__Znaj" = xyes; then :
+ gcc_ac_cygwin_dll_wrappers=yes
+else
+ gcc_ac_cygwin_dll_wrappers=no
+fi
+
+ else
+ # Can't check presence of libc functions during cross-compile, so
+ # we just have to assume we're building for an up-to-date target.
+ gcc_ac_cygwin_dll_wrappers=yes
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define USE_CYGWIN_LIBSTDCXX_WRAPPERS `if test $gcc_ac_cygwin_dll_wrappers = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+ esac
+ case $target_os in
+ cygwin* | pe | mingw32*)
+ # Recent binutils allows the three-operand form of ".comm" on PE. This
+ # definition is used unconditionally to initialise the default state of
+ # the target option variable that governs usage of the feature.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .comm with alignment" >&5
+$as_echo_n "checking assembler for .comm with alignment... " >&6; }
+if ${gcc_cv_as_comm_has_align+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_comm_has_align=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.comm foo,1,32' > 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_comm_has_align=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_comm_has_align" >&5
+$as_echo "$gcc_cv_as_comm_has_align" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_ALIGNED_COMM `if test $gcc_cv_as_comm_has_align = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+ # Used for DWARF 2 in PE
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .secrel32 relocs" >&5
+$as_echo_n "checking assembler for .secrel32 relocs... " >&6; }
+if ${gcc_cv_as_ix86_pe_secrel32+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_pe_secrel32=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+foo: nop
+.data
+ .secrel32 foo' > 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
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_as_ix86_pe_secrel32=yes
+ fi
+ rm -f conftest
+ 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_ix86_pe_secrel32" >&5
+$as_echo "$gcc_cv_as_ix86_pe_secrel32" >&6; }
+if test $gcc_cv_as_ix86_pe_secrel32 = yes; then
+
+$as_echo "#define HAVE_GAS_PE_SECREL32_RELOC 1" >>confdefs.h
+
+fi
+
+ # Test if the assembler supports the extended form of the .section
+ # directive that specifies section alignment. LTO support uses this,
+ # but normally only after installation, so we warn but don't fail the
+ # configure if LTO is enabled but the assembler does not support it.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .section with alignment" >&5
+$as_echo_n "checking assembler for .section with alignment... " >&6; }
+if ${gcc_cv_as_section_has_align+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_section_has_align=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section lto_test,"dr0"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -fatal-warnings -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_section_has_align=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_section_has_align" >&5
+$as_echo "$gcc_cv_as_section_has_align" >&6; }
+
+
+ if test x$gcc_cv_as_section_has_align != xyes; then
+ case ",$enable_languages," in
+ *,lto,*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: LTO for $target requires binutils >= 2.20.1, but version found appears insufficient; LTO will not work until binutils is upgraded." >&5
+$as_echo "$as_me: WARNING: LTO for $target requires binutils >= 2.20.1, but version found appears insufficient; LTO will not work until binutils is upgraded." >&2;}
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ case $target_os in
+ darwin2* | darwin19*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for llvm assembler x86-pad-for-align option" >&5
+$as_echo_n "checking assembler for llvm assembler x86-pad-for-align option... " >&6; }
+if ${gcc_cv_as_mllvm_x86_pad_for_align+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mllvm_x86_pad_for_align=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mllvm -x86-pad-for-align=false -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_mllvm_x86_pad_for_align=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_mllvm_x86_pad_for_align" >&5
+$as_echo "$gcc_cv_as_mllvm_x86_pad_for_align" >&6; }
+if test $gcc_cv_as_mllvm_x86_pad_for_align = yes; then
+
+$as_echo "#define HAVE_AS_MLLVM_X86_PAD_FOR_ALIGN 1" >>confdefs.h
+
+fi
+
+ ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -xbrace_comment" >&5
+$as_echo_n "checking assembler for -xbrace_comment... " >&6; }
+if ${gcc_cv_as_ix86_xbrace_comment+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_xbrace_comment=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xbrace_comment=no -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_ix86_xbrace_comment=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_ix86_xbrace_comment" >&5
+$as_echo "$gcc_cv_as_ix86_xbrace_comment" >&6; }
+if test $gcc_cv_as_ix86_xbrace_comment = yes; then
+
+$as_echo "#define HAVE_AS_XBRACE_COMMENT_OPTION 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for filds and fists mnemonics" >&5
+$as_echo_n "checking assembler for filds and fists mnemonics... " >&6; }
+if ${gcc_cv_as_ix86_filds+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_filds=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'filds (%ebp); fists (%ebp)' > 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_ix86_filds=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_ix86_filds" >&5
+$as_echo "$gcc_cv_as_ix86_filds" >&6; }
+if test $gcc_cv_as_ix86_filds = yes; then
+
+$as_echo "#define HAVE_AS_IX86_FILDS 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for fildq and fistpq mnemonics" >&5
+$as_echo_n "checking assembler for fildq and fistpq mnemonics... " >&6; }
+if ${gcc_cv_as_ix86_fildq+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_fildq=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'fildq (%ebp); fistpq (%ebp)' > 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_ix86_fildq=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_ix86_fildq" >&5
+$as_echo "$gcc_cv_as_ix86_fildq" >&6; }
+if test $gcc_cv_as_ix86_fildq = yes; then
+
+$as_echo "#define HAVE_AS_IX86_FILDQ 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for cmov syntax" >&5
+$as_echo_n "checking assembler for cmov syntax... " >&6; }
+if ${gcc_cv_as_ix86_cmov_sun_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_cmov_sun_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'cmovl.l %edx, %eax' > 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_ix86_cmov_sun_syntax=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_ix86_cmov_sun_syntax" >&5
+$as_echo "$gcc_cv_as_ix86_cmov_sun_syntax" >&6; }
+if test $gcc_cv_as_ix86_cmov_sun_syntax = yes; then
+
+$as_echo "#define HAVE_AS_IX86_CMOV_SUN_SYNTAX 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for ffreep mnemonic" >&5
+$as_echo_n "checking assembler for ffreep mnemonic... " >&6; }
+if ${gcc_cv_as_ix86_ffreep+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_ffreep=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'ffreep %st(1)' > 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_ix86_ffreep=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_ix86_ffreep" >&5
+$as_echo "$gcc_cv_as_ix86_ffreep" >&6; }
+if test $gcc_cv_as_ix86_ffreep = yes; then
+
+$as_echo "#define HAVE_AS_IX86_FFREEP 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .quad directive" >&5
+$as_echo_n "checking assembler for .quad directive... " >&6; }
+if ${gcc_cv_as_ix86_quad+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_quad=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.quad 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_ix86_quad=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_ix86_quad" >&5
+$as_echo "$gcc_cv_as_ix86_quad" >&6; }
+if test $gcc_cv_as_ix86_quad = yes; then
+
+$as_echo "#define HAVE_AS_IX86_QUAD 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for sahf mnemonic" >&5
+$as_echo_n "checking assembler for sahf mnemonic... " >&6; }
+if ${gcc_cv_as_ix86_sahf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_sahf=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.code64
+ sahf' > 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_ix86_sahf=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_ix86_sahf" >&5
+$as_echo "$gcc_cv_as_ix86_sahf" >&6; }
+if test $gcc_cv_as_ix86_sahf = yes; then
+
+$as_echo "#define HAVE_AS_IX86_SAHF 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for interunit movq mnemonic" >&5
+$as_echo_n "checking assembler for interunit movq mnemonic... " >&6; }
+if ${gcc_cv_as_ix86_interunit_movq+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_interunit_movq=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.code64
+ movq %mm0, %rax
+ movq %rax, %xmm0' > 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_ix86_interunit_movq=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_ix86_interunit_movq" >&5
+$as_echo "$gcc_cv_as_ix86_interunit_movq" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_IX86_INTERUNIT_MOVQ `if test $gcc_cv_as_ix86_interunit_movq = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for hle prefixes" >&5
+$as_echo_n "checking assembler for hle prefixes... " >&6; }
+if ${gcc_cv_as_ix86_hle+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_hle=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'lock xacquire cmpxchg %esi, (%ecx)' > 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_ix86_hle=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_ix86_hle" >&5
+$as_echo "$gcc_cv_as_ix86_hle" >&6; }
+if test $gcc_cv_as_ix86_hle = yes; then
+
+$as_echo "#define HAVE_AS_IX86_HLE 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for swap suffix" >&5
+$as_echo_n "checking assembler for swap suffix... " >&6; }
+if ${gcc_cv_as_ix86_swap+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_swap=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'movl.s %esp, %ebp' > 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_ix86_swap=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_ix86_swap" >&5
+$as_echo "$gcc_cv_as_ix86_swap" >&6; }
+if test $gcc_cv_as_ix86_swap = yes; then
+
+$as_echo "#define HAVE_AS_IX86_SWAP 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for different section symbol subtraction" >&5
+$as_echo_n "checking assembler for different section symbol subtraction... " >&6; }
+if ${gcc_cv_as_ix86_diff_sect_delta+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_diff_sect_delta=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .rodata
+.L1:
+ .long .L2-.L1
+ .long .L3-.L1
+ .text
+.L3: nop
+.L2: nop' > 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_ix86_diff_sect_delta=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_ix86_diff_sect_delta" >&5
+$as_echo "$gcc_cv_as_ix86_diff_sect_delta" >&6; }
+if test $gcc_cv_as_ix86_diff_sect_delta = yes; then
+
+$as_echo "#define HAVE_AS_IX86_DIFF_SECT_DELTA 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for rep and lock prefix" >&5
+$as_echo_n "checking assembler for rep and lock prefix... " >&6; }
+if ${gcc_cv_as_ix86_rep_lock_prefix+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_rep_lock_prefix=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'rep movsl
+ rep ret
+ rep nop
+ rep bsf %ecx, %eax
+ rep bsr %ecx, %eax
+ lock addl %edi, (%eax,%esi)
+ lock orl $0, (%esp)' > 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_ix86_rep_lock_prefix=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_ix86_rep_lock_prefix" >&5
+$as_echo "$gcc_cv_as_ix86_rep_lock_prefix" >&6; }
+if test $gcc_cv_as_ix86_rep_lock_prefix = yes; then
+
+$as_echo "#define HAVE_AS_IX86_REP_LOCK_PREFIX 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for ud2 mnemonic" >&5
+$as_echo_n "checking assembler for ud2 mnemonic... " >&6; }
+if ${gcc_cv_as_ix86_ud2+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_ud2=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'ud2' > 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_ix86_ud2=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_ix86_ud2" >&5
+$as_echo "$gcc_cv_as_ix86_ud2" >&6; }
+if test $gcc_cv_as_ix86_ud2 = yes; then
+
+$as_echo "#define HAVE_AS_IX86_UD2 1" >>confdefs.h
+
+fi
+
+
+ # Enforce 32-bit output with gas and gld.
+ if test x$gas = xyes; then
+ as_ix86_gas_32_opt="--32"
+ fi
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ if $gcc_cv_ld -V 2>/dev/null | grep elf_i386_sol2 > /dev/null; then
+ ld_ix86_gld_32_opt="-melf_i386_sol2"
+ else
+ ld_ix86_gld_32_opt="-melf_i386"
+ fi
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for R_386_TLS_GD_PLT reloc" >&5
+$as_echo_n "checking assembler for R_386_TLS_GD_PLT reloc... " >&6; }
+if ${gcc_cv_as_ix86_tlsgdplt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_tlsgdplt=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'call tls_gd@tlsgdplt' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_32_opt -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
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o -G > /dev/null 2>&1; then
+ gcc_cv_as_ix86_tlsgdplt=yes
+ fi
+ rm -f conftest
+ 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_ix86_tlsgdplt" >&5
+$as_echo "$gcc_cv_as_ix86_tlsgdplt" >&6; }
+if test $gcc_cv_as_ix86_tlsgdplt = yes; then
+
+$as_echo "#define HAVE_AS_IX86_TLSGDPLT 1" >>confdefs.h
+
+fi
+
+
+ conftest_s='
+ .section .tdata,"aw'$tls_section_flag'",@progbits
+tls_ld:
+ .section .text,"ax",@progbits
+ call tls_ld@tlsldmplt'
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for R_386_TLS_LDM_PLT reloc" >&5
+$as_echo_n "checking assembler for R_386_TLS_LDM_PLT reloc... " >&6; }
+if ${gcc_cv_as_ix86_tlsldmplt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_tlsldmplt=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_32_opt -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
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o -G > /dev/null 2>&1; then
+ gcc_cv_as_ix86_tlsldmplt=yes
+ fi
+ rm -f conftest
+ 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_ix86_tlsldmplt" >&5
+$as_echo "$gcc_cv_as_ix86_tlsldmplt" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_IX86_TLSLDMPLT `if test $gcc_cv_as_ix86_tlsldmplt = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+ conftest_s='
+ .section .text,"ax",@progbits
+ .globl _start
+ .type _start, @function
+_start:
+ leal value@tlsldm(%ebx), %eax
+ call ___tls_get_addr@plt
+
+ .section .tdata,"aw'$tls_section_flag'",@progbits
+ .type value, @object
+value:'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for R_386_TLS_LDM reloc" >&5
+$as_echo_n "checking assembler for R_386_TLS_LDM reloc... " >&6; }
+if ${gcc_cv_as_ix86_tlsldm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_tlsldm=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_32_opt -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
+ if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then
+ if $gcc_cv_objdump -d conftest 2>/dev/null | grep nop > /dev/null \
+ || dis conftest 2>/dev/null | grep nop > /dev/null; then
+ gcc_cv_as_ix86_tlsldm=yes
+ fi
+ fi
+ rm -f conftest
+ 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_ix86_tlsldm" >&5
+$as_echo "$gcc_cv_as_ix86_tlsldm" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_IX86_TLSLDM `if test $gcc_cv_as_ix86_tlsldm = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+ conftest_s='
+ .data
+bar:
+ .byte 1
+ .text
+ .global _start
+_start:
+ cmpl $0, bar@GOT
+ jmp *_start@GOT'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for R_386_GOT32X reloc" >&5
+$as_echo_n "checking assembler for R_386_GOT32X reloc... " >&6; }
+if ${gcc_cv_as_ix86_got32x+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_got32x=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_32_opt -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
+ if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+ && test x$gcc_cv_readelf != x \
+ && $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+ | grep R_386_GOT32X > /dev/null 2>&1 \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o > /dev/null 2>&1; then
+ if $gcc_cv_objdump -dw conftest 2>&1 \
+ | grep 0xffffff > /dev/null 2>&1; then
+ gcc_cv_as_ix86_got32x=no
+ else
+ gcc_cv_as_ix86_got32x=yes
+ fi
+ fi
+ rm -f conftest
+ 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_ix86_got32x" >&5
+$as_echo "$gcc_cv_as_ix86_got32x" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_IX86_GOT32X `if test x"$gcc_cv_as_ix86_got32x" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for GOTOFF in data" >&5
+$as_echo_n "checking assembler for GOTOFF in data... " >&6; }
+if ${gcc_cv_as_ix86_gotoff_in_data+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_gotoff_in_data=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+.L0:
+ nop
+ .data
+ .long .L0@GOTOFF' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_32_opt -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_ix86_gotoff_in_data=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_ix86_gotoff_in_data" >&5
+$as_echo "$gcc_cv_as_ix86_gotoff_in_data" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_GOTOFF_IN_DATA `if test $gcc_cv_as_ix86_gotoff_in_data = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
+ conftest_s='
+ .section .text,"ax",@progbits
+ .globl _start
+ .type _start, @function
+_start:
+ leal ld@tlsldm(%ecx), %eax
+ call *___tls_get_addr@GOT(%ecx)
+ leal gd@tlsgd(%ecx), %eax
+ call *___tls_get_addr@GOT(%ecx)
+
+ .section .tdata,"aw'$tls_section_flag'",@progbits
+ .type ld, @object
+ld:
+ .byte 0
+ .globl gd
+ .type gd, @object
+gd:
+ .byte 0'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for calling ___tls_get_addr via GOT" >&5
+$as_echo_n "checking assembler for calling ___tls_get_addr via GOT... " >&6; }
+if ${gcc_cv_as_ix86_tls_get_addr_via_got+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ix86_tls_get_addr_via_got=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags $as_ix86_gas_32_opt -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
+ if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_as_ix86_tls_get_addr_via_got=yes
+ fi
+ rm -f conftest
+ 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_ix86_tls_get_addr_via_got" >&5
+$as_echo "$gcc_cv_as_ix86_tls_get_addr_via_got" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_IX86_TLS_GET_ADDR_GOT `if test x"$gcc_cv_as_ix86_tls_get_addr_via_got" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+ ;;
+
+ ia64*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for ltoffx and ldxmov relocs" >&5
+$as_echo_n "checking assembler for ltoffx and ldxmov relocs... " >&6; }
+if ${gcc_cv_as_ia64_ltoffx_ldxmov_relocs+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_ia64_ltoffx_ldxmov_relocs=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .text
+ addl r15 = @ltoffx(x#), gp
+ ;;
+ ld8.mov r16 = [r15], x#
+' > 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_ia64_ltoffx_ldxmov_relocs=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_ia64_ltoffx_ldxmov_relocs" >&5
+$as_echo "$gcc_cv_as_ia64_ltoffx_ldxmov_relocs" >&6; }
+if test $gcc_cv_as_ia64_ltoffx_ldxmov_relocs = yes; then
+
+$as_echo "#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 1" >>confdefs.h
+
+fi
+
+
+ ;;
+
+ powerpc*-*-*)
+
+ case $target in
+ *-*-darwin*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .machine directive support" >&5
+$as_echo_n "checking assembler for .machine directive support... " >&6; }
+if ${gcc_cv_as_machine_directive+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_machine_directive=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .machine ppc7400' > 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_machine_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_machine_directive" >&5
+$as_echo "$gcc_cv_as_machine_directive" >&6; }
+
+
+ if test x$gcc_cv_as_machine_directive != xyes; then
+ echo "*** This target requires an assembler supporting \".machine\"" >&2
+ echo you can get it from: https://gcc.gnu.org/pub/gcc/infrastructure/cctools-528.5.dmg >&2
+ test x$build = x$target && exit 1
+ fi
+ ;;
+ esac
+
+ case $target in
+ *-*-aix*) conftest_s=' .machine "pwr5"
+ .csect .text[PR]
+ mfcr 3,128';;
+ *-*-darwin*) conftest_s=' .text
+ mfcr r3,128';;
+ *) conftest_s=' .machine power4
+ .text
+ mfcr 3,128';;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for mfcr field support" >&5
+$as_echo_n "checking assembler for mfcr field support... " >&6; }
+if ${gcc_cv_as_powerpc_mfcrf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_mfcrf=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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_powerpc_mfcrf=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_powerpc_mfcrf" >&5
+$as_echo "$gcc_cv_as_powerpc_mfcrf" >&6; }
+if test $gcc_cv_as_powerpc_mfcrf = yes; then
+
+$as_echo "#define HAVE_AS_MFCRF 1" >>confdefs.h
+
+fi
+
+
+ case $target in
+ *-*-aix*) conftest_s=' .csect .text[PR]
+LCF..0:
+ addis 11,30,_GLOBAL_OFFSET_TABLE_-LCF..0@ha';;
+ *-*-darwin*)
+ conftest_s=' .text
+LCF0:
+ addis r11,r30,_GLOBAL_OFFSET_TABLE_-LCF0@ha';;
+ *) conftest_s=' .text
+.LCF0:
+ addis 11,30,_GLOBAL_OFFSET_TABLE_-.LCF0@ha';;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for rel16 relocs" >&5
+$as_echo_n "checking assembler for rel16 relocs... " >&6; }
+if ${gcc_cv_as_powerpc_rel16+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_rel16=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a32 -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_powerpc_rel16=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_powerpc_rel16" >&5
+$as_echo "$gcc_cv_as_powerpc_rel16" >&6; }
+if test $gcc_cv_as_powerpc_rel16 = yes; then
+
+$as_echo "#define HAVE_AS_REL16 1" >>confdefs.h
+
+fi
+
+
+ case $target in
+ *-*-aix*) conftest_s=' .machine "pwr7"
+ .csect .text[PR]
+ lxvd2x 1,2,3';;
+ *) conftest_s=' .machine power7
+ .text
+ lxvd2x 1,2,3';;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for vector-scalar support" >&5
+$as_echo_n "checking assembler for vector-scalar support... " >&6; }
+if ${gcc_cv_as_powerpc_vsx+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_vsx=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a32 -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_powerpc_vsx=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_powerpc_vsx" >&5
+$as_echo "$gcc_cv_as_powerpc_vsx" >&6; }
+if test $gcc_cv_as_powerpc_vsx = yes; then
+
+$as_echo "#define HAVE_AS_VSX 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
+$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
+if ${gcc_cv_as_powerpc_gnu_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_gnu_attribute=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.gnu_attribute 4,1' > 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_powerpc_gnu_attribute=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_powerpc_gnu_attribute" >&5
+$as_echo "$gcc_cv_as_powerpc_gnu_attribute" >&6; }
+if test $gcc_cv_as_powerpc_gnu_attribute = yes; then
+
+$as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for prologue entry point marker support" >&5
+$as_echo_n "checking assembler for prologue entry point marker support... " >&6; }
+if ${gcc_cv_as_powerpc_entry_markers+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_entry_markers=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .reloc .,R_PPC64_ENTRY; nop' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a64 --fatal-warnings -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_powerpc_entry_markers=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_powerpc_entry_markers" >&5
+$as_echo "$gcc_cv_as_powerpc_entry_markers" >&6; }
+if test $gcc_cv_as_powerpc_entry_markers = yes; then
+
+$as_echo "#define HAVE_AS_ENTRY_MARKERS 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for plt sequence marker support" >&5
+$as_echo_n "checking assembler for plt sequence marker support... " >&6; }
+if ${gcc_cv_as_powerpc_pltseq_markers+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_powerpc_pltseq_markers=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .reloc .,R_PPC_PLTSEQ; nop' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a32 --fatal-warnings -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_powerpc_pltseq_markers=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_powerpc_pltseq_markers" >&5
+$as_echo "$gcc_cv_as_powerpc_pltseq_markers" >&6; }
+if test $gcc_cv_as_powerpc_pltseq_markers = yes; then
+
+$as_echo "#define HAVE_AS_PLTSEQ 1" >>confdefs.h
+
+fi
+
+
+ case $target in
+ *-*-aix*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for AIX .ref support" >&5
+$as_echo_n "checking assembler for AIX .ref support... " >&6; }
+if ${gcc_cv_as_aix_ref+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_aix_ref=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .csect stuff[rw]
+ stuff:
+ .long 1
+ .extern sym
+ .ref sym
+ ' > 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_ref=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_ref" >&5
+$as_echo "$gcc_cv_as_aix_ref" >&6; }
+if test $gcc_cv_as_aix_ref = yes; then
+
+$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
+ ;;
+
+ mips*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for explicit relocation support" >&5
+$as_echo_n "checking assembler for explicit relocation support... " >&6; }
+if ${gcc_cv_as_mips_explicit_relocs+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_explicit_relocs=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' lw $4,%gp_rel(foo)($4)' > 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_mips_explicit_relocs=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_mips_explicit_relocs" >&5
+$as_echo "$gcc_cv_as_mips_explicit_relocs" >&6; }
+if test $gcc_cv_as_mips_explicit_relocs = yes; then
+ if test x$target_cpu_default = x
+ then target_cpu_default=MASK_EXPLICIT_RELOCS
+ else target_cpu_default="($target_cpu_default)|MASK_EXPLICIT_RELOCS"
+ fi
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -mno-shared support" >&5
+$as_echo_n "checking assembler for -mno-shared support... " >&6; }
+if ${gcc_cv_as_mips_no_shared+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_no_shared=no
+ if test x$gcc_cv_as != x; then
+ $as_echo 'nop' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mno-shared -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_mips_no_shared=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_mips_no_shared" >&5
+$as_echo "$gcc_cv_as_mips_no_shared" >&6; }
+if test $gcc_cv_as_mips_no_shared = yes; then
+
+$as_echo "#define HAVE_AS_NO_SHARED 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
+$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
+if ${gcc_cv_as_mips_gnu_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_gnu_attribute=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.gnu_attribute 4,1' > 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_mips_gnu_attribute=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_mips_gnu_attribute" >&5
+$as_echo "$gcc_cv_as_mips_gnu_attribute" >&6; }
+if test $gcc_cv_as_mips_gnu_attribute = yes; then
+
+$as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .module support" >&5
+$as_echo_n "checking assembler for .module support... " >&6; }
+if ${gcc_cv_as_mips_dot_module+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_dot_module=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.module mips2
+ .module fp=xx' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -32 -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_mips_dot_module=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_mips_dot_module" >&5
+$as_echo "$gcc_cv_as_mips_dot_module" >&6; }
+if test $gcc_cv_as_mips_dot_module = yes; then
+
+$as_echo "#define HAVE_AS_DOT_MODULE 1" >>confdefs.h
+
+fi
+
+ if test x$gcc_cv_as_mips_dot_module = xno \
+ && test x$with_fp_32 != x; then
+ as_fn_error $? "Requesting --with-fp-32= requires assembler support for .module." "$LINENO" 5
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .micromips support" >&5
+$as_echo_n "checking assembler for .micromips support... " >&6; }
+if ${gcc_cv_as_micromips_support+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_micromips_support=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.set micromips' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -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_micromips_support=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_micromips_support" >&5
+$as_echo "$gcc_cv_as_micromips_support" >&6; }
+if test $gcc_cv_as_micromips_support = yes; then
+
+$as_echo "#define HAVE_GAS_MICROMIPS 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .dtprelword support" >&5
+$as_echo_n "checking assembler for .dtprelword support... " >&6; }
+if ${gcc_cv_as_mips_dtprelword+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_dtprelword=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ .dtprelword x+0x8000' > 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_mips_dtprelword=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_mips_dtprelword" >&5
+$as_echo "$gcc_cv_as_mips_dtprelword" >&6; }
+if test $gcc_cv_as_mips_dtprelword = yes; then
+
+$as_echo "#define HAVE_AS_DTPRELWORD 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for DSPR1 mult with four accumulators support" >&5
+$as_echo_n "checking assembler for DSPR1 mult with four accumulators support... " >&6; }
+if ${gcc_cv_as_mips_dspr1_mult+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_dspr1_mult=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .set mips32r2
+ .set nodspr2
+ .set dsp
+ madd $ac3,$4,$5
+ maddu $ac3,$4,$5
+ msub $ac3,$4,$5
+ msubu $ac3,$4,$5
+ mult $ac3,$4,$5
+ multu $ac3,$4,$5' > 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_mips_dspr1_mult=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_mips_dspr1_mult" >&5
+$as_echo "$gcc_cv_as_mips_dspr1_mult" >&6; }
+if test $gcc_cv_as_mips_dspr1_mult = yes; then
+
+$as_echo "#define HAVE_AS_DSPR1_MULT 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker for explicit JALR relocation" >&5
+$as_echo_n "checking assembler and linker for explicit JALR relocation... " >&6; }
+ gcc_cv_as_ld_jalr_reloc=no
+ if test $gcc_cv_as_mips_explicit_relocs = yes; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 20 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_as_ld_jalr_reloc=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x; then
+ echo ' .ent x' > conftest.s
+ echo 'x: lw $2,%got_disp(y)($3)' >> conftest.s
+ echo ' lw $25,%call16(y)($28)' >> conftest.s
+ echo ' .reloc 1f,R_MIPS_JALR,y' >> conftest.s
+ echo '1: jalr $25' >> conftest.s
+ echo ' .reloc 1f,R_MIPS_JALR,x' >> conftest.s
+ echo '1: jalr $25' >> conftest.s
+ echo ' .end x' >> conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s >/dev/null 2>&5 \
+ && $gcc_cv_ld -shared -o conftest.so conftest.o >/dev/null 2>&5; then
+ if $gcc_cv_objdump -d conftest.so | grep jalr >/dev/null 2>&1 \
+ && $gcc_cv_objdump -d conftest.so | grep "bal.*<x>" >/dev/null 2>&1; then
+ gcc_cv_as_ld_jalr_reloc=yes
+ fi
+ fi
+ rm -f conftest.*
+ fi
+ fi
+ if test $gcc_cv_as_ld_jalr_reloc = yes; then
+ if test x$target_cpu_default = x; then
+ target_cpu_default=MASK_RELAX_PIC_CALLS
+ else
+ target_cpu_default="($target_cpu_default)|MASK_RELAX_PIC_CALLS"
+ fi
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_ld_jalr_reloc" >&5
+$as_echo "$gcc_cv_as_ld_jalr_reloc" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for .eh_frame personality relaxation" >&5
+$as_echo_n "checking linker for .eh_frame personality relaxation... " >&6; }
+if ${gcc_cv_ld_mips_personality_relaxation+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_mips_personality_relaxation=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 \
+ -a "$gcc_cv_gld_minor_version" -ge 21 \
+ -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_mips_personality_relaxation=yes
+ fi
+ elif test x$gcc_cv_as != x \
+ -a x$gcc_cv_ld != x \
+ -a x$gcc_cv_readelf != x ; then
+ cat > conftest.s <<EOF
+ .cfi_startproc
+ .cfi_personality 0x80,indirect_ptr
+ .ent test
+test:
+ nop
+ .end test
+ .cfi_endproc
+
+ .section .data,"aw",@progbits
+indirect_ptr:
+ .dc.a personality
+EOF
+ if $gcc_cv_as -KPIC -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o -shared > /dev/null 2>&1; then
+ if $gcc_cv_readelf -d conftest 2>&1 \
+ | grep TEXTREL > /dev/null 2>&1; then
+ :
+ elif $gcc_cv_readelf --relocs conftest 2>&1 \
+ | grep 'R_MIPS_REL32 *$' > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_ld_mips_personality_relaxation=yes
+ fi
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_mips_personality_relaxation" >&5
+$as_echo "$gcc_cv_ld_mips_personality_relaxation" >&6; }
+ if test x$gcc_cv_ld_mips_personality_relaxation = xyes; then
+
+$as_echo "#define HAVE_LD_PERSONALITY_RELAXATION 1" >>confdefs.h
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -mnan= support" >&5
+$as_echo_n "checking assembler for -mnan= support... " >&6; }
+if ${gcc_cv_as_mips_nan+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_mips_nan=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mnan=2008 -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_mips_nan=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_mips_nan" >&5
+$as_echo "$gcc_cv_as_mips_nan" >&6; }
+if test $gcc_cv_as_mips_nan = yes; then
+
+$as_echo "#define HAVE_AS_NAN 1" >>confdefs.h
+
+fi
+
+ if test x$gcc_cv_as_mips_nan = xno \
+ && test x$with_nan != x; then
+ as_fn_error $? "Requesting --with-nan= requires assembler support for -mnan=" "$LINENO" 5
+ fi
+ ;;
+ msp430-*-*)
+ # Earlier GAS versions generically support .gnu_attribute, but the
+ # msp430 assembler will not do anything with it.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
+$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
+if ${gcc_cv_as_msp430_gnu_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_msp430_gnu_attribute=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.gnu_attribute 4,1' > 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_msp430_gnu_attribute=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_msp430_gnu_attribute" >&5
+$as_echo "$gcc_cv_as_msp430_gnu_attribute" >&6; }
+if test $gcc_cv_as_msp430_gnu_attribute = yes; then
+
+$as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .mspabi_attribute support" >&5
+$as_echo_n "checking assembler for .mspabi_attribute support... " >&6; }
+if ${gcc_cv_as_msp430_mspabi_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_msp430_mspabi_attribute=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.mspabi_attribute 4,2' > 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_msp430_mspabi_attribute=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_msp430_mspabi_attribute" >&5
+$as_echo "$gcc_cv_as_msp430_mspabi_attribute" >&6; }
+if test $gcc_cv_as_msp430_mspabi_attribute = yes; then
+
+$as_echo "#define HAVE_AS_MSPABI_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+ if test x$enable_newlib_nano_formatted_io = xyes; then
+
+$as_echo "#define HAVE_NEWLIB_NANO_FORMATTED_IO 1" >>confdefs.h
+
+ fi
+ ;;
+ nios2-*-*)
+ # Versions 2.33 and earlier lacked support for the %gotoff relocation
+ # syntax that is documented in the ABI specification.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for support for %gotoff relocations in constant data" >&5
+$as_echo_n "checking assembler for support for %gotoff relocations in constant data... " >&6; }
+if ${gcc_cv_as_nios2_gotoff_relocation+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_nios2_gotoff_relocation=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .extern foo
+ .data
+ .long %gotoff(foo)' > 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_nios2_gotoff_relocation=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_nios2_gotoff_relocation" >&5
+$as_echo "$gcc_cv_as_nios2_gotoff_relocation" >&6; }
+if test $gcc_cv_as_nios2_gotoff_relocation = yes; then
+
+$as_echo "#define HAVE_AS_NIOS2_GOTOFF_RELOCATION 1" >>confdefs.h
+
+fi
+
+ ;;
+ riscv*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .attribute support" >&5
+$as_echo_n "checking assembler for .attribute support... " >&6; }
+if ${gcc_cv_as_riscv_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_riscv_attribute=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.attribute stack_align,4' > 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_riscv_attribute=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_riscv_attribute" >&5
+$as_echo "$gcc_cv_as_riscv_attribute" >&6; }
+if test $gcc_cv_as_riscv_attribute = yes; then
+
+$as_echo "#define HAVE_AS_RISCV_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -misa-spec= support" >&5
+$as_echo_n "checking assembler for -misa-spec= support... " >&6; }
+if ${gcc_cv_as_riscv_isa_spec+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_riscv_isa_spec=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -misa-spec=2.2 -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_riscv_isa_spec=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_riscv_isa_spec" >&5
+$as_echo "$gcc_cv_as_riscv_isa_spec" >&6; }
+if test $gcc_cv_as_riscv_isa_spec = yes; then
+
+$as_echo "#define HAVE_AS_MISA_SPEC 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zifencei support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zifencei support... " >&6; }
+if ${gcc_cv_as_riscv_march_zifencei+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_riscv_march_zifencei=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zifencei2p0 -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_riscv_march_zifencei=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_riscv_march_zifencei" >&5
+$as_echo "$gcc_cv_as_riscv_march_zifencei" >&6; }
+if test $gcc_cv_as_riscv_march_zifencei = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZIFENCEI 1" >>confdefs.h
+
+fi
+
+ ;;
+ loongarch*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .dtprelword support" >&5
+$as_echo_n "checking assembler for .dtprelword support... " >&6; }
+if ${gcc_cv_as_loongarch_dtprelword+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_loongarch_dtprelword=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags 2,18,0 -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
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ .dtprelword x+0x8000
+ 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_loongarch_dtprelword" >&5
+$as_echo "$gcc_cv_as_loongarch_dtprelword" >&6; }
+
+if test $gcc_cv_as_loongarch_dtprelword != yes; then
+
+$as_echo "#define HAVE_AS_DTPRELWORD 1" >>confdefs.h
+
+fi
+ ;;
+ s390*-*-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
+$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
+if ${gcc_cv_as_s390_gnu_attribute+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_s390_gnu_attribute=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.gnu_attribute 8,1' > 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_s390_gnu_attribute=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_s390_gnu_attribute" >&5
+$as_echo "$gcc_cv_as_s390_gnu_attribute" >&6; }
+if test $gcc_cv_as_s390_gnu_attribute = yes; then
+
+$as_echo "#define HAVE_AS_GNU_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .machine and .machinemode support" >&5
+$as_echo_n "checking assembler for .machine and .machinemode support... " >&6; }
+if ${gcc_cv_as_s390_machine_machinemode+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_s390_machine_machinemode=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .machinemode push
+ .machinemode pop
+ .machine push
+ .machine pop' > 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_s390_machine_machinemode=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_s390_machine_machinemode" >&5
+$as_echo "$gcc_cv_as_s390_machine_machinemode" >&6; }
+if test $gcc_cv_as_s390_machine_machinemode = yes; then
+
+$as_echo "#define HAVE_AS_MACHINE_MACHINEMODE 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for architecture modifiers support" >&5
+$as_echo_n "checking assembler for architecture modifiers support... " >&6; }
+if ${gcc_cv_as_s390_architecture_modifiers+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_s390_architecture_modifiers=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .machine z13+vx ' > 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_s390_architecture_modifiers=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_s390_architecture_modifiers" >&5
+$as_echo "$gcc_cv_as_s390_architecture_modifiers" >&6; }
+if test $gcc_cv_as_s390_architecture_modifiers = yes; then
+
+$as_echo "#define HAVE_AS_ARCHITECTURE_MODIFIERS 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for vector load/store alignment hints" >&5
+$as_echo_n "checking assembler for vector load/store alignment hints... " >&6; }
+if ${gcc_cv_as_s390_vector_loadstore_alignment_hints+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_s390_vector_loadstore_alignment_hints=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' vl %v24,0(%r15),3 ' > 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_s390_vector_loadstore_alignment_hints=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_s390_vector_loadstore_alignment_hints" >&5
+$as_echo "$gcc_cv_as_s390_vector_loadstore_alignment_hints" >&6; }
+if test $gcc_cv_as_s390_vector_loadstore_alignment_hints = yes; then
+
+$as_echo "#define HAVE_AS_VECTOR_LOADSTORE_ALIGNMENT_HINTS 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for vector load/store alignment hints on z13" >&5
+$as_echo_n "checking assembler for vector load/store alignment hints on z13... " >&6; }
+if ${gcc_cv_as_s390_vector_loadstore_alignment_hints_on_z13+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_s390_vector_loadstore_alignment_hints_on_z13=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' vl %v24,0(%r15),3 ' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -mzarch -march=z13 -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_s390_vector_loadstore_alignment_hints_on_z13=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_s390_vector_loadstore_alignment_hints_on_z13" >&5
+$as_echo "$gcc_cv_as_s390_vector_loadstore_alignment_hints_on_z13" >&6; }
+if test $gcc_cv_as_s390_vector_loadstore_alignment_hints_on_z13 = yes; then
+
+$as_echo "#define HAVE_AS_VECTOR_LOADSTORE_ALIGNMENT_HINTS_ON_Z13 1" >>confdefs.h
+
+fi
+
+
+ ;;
+esac
+
+# Mips, LoongArch and HP-UX need the GNU assembler.
+# Linux on IA64 might be able to use the Intel assembler.
+
+case "$target" in
+ mips*-*-* | loongarch*-*-* | *-*-hpux* )
+ if test x$gas_flag = xyes \
+ || test x"$host" != x"$build" \
+ || test ! -x "$gcc_cv_as" \
+ || "$gcc_cv_as" -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ :
+ else
+ echo "*** This configuration requires the GNU assembler" >&2
+ exit 1
+ fi
+ ;;
+esac
+
+# This tests if the assembler supports two registers for global_load functions
+# (like in LLVM versions <12) or one register (like in LLVM 12).
+case "$target" in
+ amdgcn-* | gcn-*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler fix for global_load functions" >&5
+$as_echo_n "checking assembler fix for global_load functions... " >&6; }
+ gcc_cv_as_gcn_global_load_fixed=yes
+ if test x$gcc_cv_as != x; then
+ cat > conftest.s <<EOF
+ global_store_dwordx2 v[1:2], v[4:5], s[14:15]
+EOF
+ if $gcc_cv_as -triple=amdgcn--amdhsa -filetype=obj -mcpu=gfx900 -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_gcn_global_load_fixed=no
+ fi
+ rm -f conftest.s conftest.o conftest
+ fi
+ global_load_fixed=`if test x$gcc_cv_as_gcn_global_load_fixed = xyes; then echo 1; else echo 0; fi`
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GCN_ASM_GLOBAL_LOAD_FIXED $global_load_fixed
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_gcn_global_load_fixed" >&5
+$as_echo "$gcc_cv_as_gcn_global_load_fixed" >&6; }
+ ;;
+esac
+
+case "$target" in
+ amdgcn-* | gcn-*)
+ # Test the LLVM assembler syntax dialect; they have made a number of
+ # changes between LLVM 12 & 13 without any backward compatibility.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v2/3 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v2/3 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v3_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_asm_v3_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack -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_gcn_asm_v3_syntax=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_gcn_asm_v3_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v3_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V3_SYNTAX 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler amdgcn_target v4 syntax" >&5
+$as_echo_n "checking assembler for assembler amdgcn_target v4 syntax... " >&6; }
+if ${gcc_cv_as_gcn_asm_v4_syntax+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_asm_v4_syntax=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack -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_gcn_asm_v4_syntax=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_gcn_asm_v4_syntax" >&5
+$as_echo "$gcc_cv_as_gcn_asm_v4_syntax" >&6; }
+if test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+
+$as_echo "#define HAVE_GCN_ASM_V4_SYNTAX 1" >>confdefs.h
+
+fi
+
+
+ # Some attribute names changed in the move to v4 ...
+ if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+ sramopt="+sram-ecc"
+ sramattr="+sram-ecc"
+ xnackattr="+xnack"
+ elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+ sramopt="+sramecc"
+ sramattr=":sramecc+"
+ xnackattr=":xnack+"
+ else
+ as_fn_error $? "Unrecognised assembler version" "$LINENO" 5
+ fi
+
+ # Test whether the LLVM assembler accepts -mattr=+xnack without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # LLVM 12+ throws a warning for GPUs without support.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for fiji... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_fiji+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_fiji=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_fiji=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_gcn_xnack_ecc_fiji" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_fiji" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_fiji = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_FIJI 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx900... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx900+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx900=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx900=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_gcn_xnack_ecc_gfx900" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx900" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx900 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX900 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx906... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx906+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx906=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx906=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_gcn_xnack_ecc_gfx906" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx906" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx906 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX906 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=+xnack for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=+xnack for gfx908... " >&6; }
+if ${gcc_cv_as_gcn_xnack_ecc_gfx908+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_xnack_ecc_gfx908=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_xnack_ecc_gfx908=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_gcn_xnack_ecc_gfx908" >&5
+$as_echo "$gcc_cv_as_gcn_xnack_ecc_gfx908" >&6; }
+if test $gcc_cv_as_gcn_xnack_ecc_gfx908 = yes; then
+
+$as_echo "#define HAVE_GCN_XNACK_GFX908 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+
+ # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+ # for GPUs without support.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for fiji" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for fiji... " >&6; }
+if ${gcc_cv_as_gcn_sram_ecc_fiji+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_sram_ecc_fiji=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_fiji=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_gcn_sram_ecc_fiji" >&5
+$as_echo "$gcc_cv_as_gcn_sram_ecc_fiji" >&6; }
+if test $gcc_cv_as_gcn_sram_ecc_fiji = yes; then
+
+$as_echo "#define HAVE_GCN_SRAM_ECC_FIJI 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx900" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx900... " >&6; }
+if ${gcc_cv_as_gcn_sram_ecc_gfx900+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_sram_ecc_gfx900=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx900=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_gcn_sram_ecc_gfx900" >&5
+$as_echo "$gcc_cv_as_gcn_sram_ecc_gfx900" >&6; }
+if test $gcc_cv_as_gcn_sram_ecc_gfx900 = yes; then
+
+$as_echo "#define HAVE_GCN_SRAM_ECC_GFX900 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx906" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx906... " >&6; }
+if ${gcc_cv_as_gcn_sram_ecc_gfx906+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_sram_ecc_gfx906=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx906=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_gcn_sram_ecc_gfx906" >&5
+$as_echo "$gcc_cv_as_gcn_sram_ecc_gfx906" >&6; }
+if test $gcc_cv_as_gcn_sram_ecc_gfx906 = yes; then
+
+$as_echo "#define HAVE_GCN_SRAM_ECC_GFX906 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler accepts -mattr=$sramopt for gfx908" >&5
+$as_echo_n "checking assembler for assembler accepts -mattr=$sramopt for gfx908... " >&6; }
+if ${gcc_cv_as_gcn_sram_ecc_gfx908+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gcn_sram_ecc_gfx908=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err -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
+ grep "." conftest.err >&5 \
+ || gcc_cv_as_gcn_sram_ecc_gfx908=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_gcn_sram_ecc_gfx908" >&5
+$as_echo "$gcc_cv_as_gcn_sram_ecc_gfx908" >&6; }
+if test $gcc_cv_as_gcn_sram_ecc_gfx908 = yes; then
+
+$as_echo "#define HAVE_GCN_SRAM_ECC_GFX908 1" >>confdefs.h
+
+fi
+
+ rm -f conftest.err
+ ;;
+ arm*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembler for arm accepts context-specific architecture extensions" >&5
+$as_echo_n "checking assembler for assembler for arm accepts context-specific architecture extensions... " >&6; }
+if ${gcc_cv_as_arm_option_extensions+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_arm_option_extensions=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.text
+ .thumb
+ .syntax unified
+ vmov.f32 s0, s1' > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=armv8.1-m.main+mve -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_arm_option_extensions=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_arm_option_extensions" >&5
+$as_echo "$gcc_cv_as_arm_option_extensions" >&6; }
+if test $gcc_cv_as_arm_option_extensions = yes; then
+
+$as_echo "#define HAVE_GAS_ARM_EXTENDED_ARCH 1" >>confdefs.h
+
+fi
+
+esac
+
+# ??? Not all targets support dwarf2 debug_line, even within a version
+# of gas. Moreover, we need to emit a valid instruction to trigger any
+# info to the output file. So, as supported targets are added to gas 2.11,
+# add some instruction here to (also) show we expect this might work.
+# ??? Once 2.11 is released, probably need to add first known working
+# version to the per-target configury.
+case "$cpu_type" in
+ aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | loongarch | m32c \
+ | m68k | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \
+ | tilegx | tilepro | visium | xstormy16 | xtensa)
+ insn="nop"
+ ;;
+ ia64 | s390)
+ insn="nop 0"
+ ;;
+ mmix)
+ insn="swym 0"
+ ;;
+esac
+if test x"$insn" != x; then
+ conftest_s="\
+ .file 1 \"conftest.s\"
+ .loc 1 3 0
+ $insn"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for dwarf2 debug_line support" >&5
+$as_echo_n "checking assembler for dwarf2 debug_line support... " >&6; }
+if ${gcc_cv_as_dwarf2_debug_line+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_dwarf2_debug_line=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -h conftest.o 2> /dev/null \
+ | grep debug_line > /dev/null 2>&1; then
+ gcc_cv_as_dwarf2_debug_line=yes
+ elif test x$gcc_cv_otool != x \
+ && $gcc_cv_otool -l conftest.o 2> /dev/null \
+ | grep debug_line > /dev/null 2>&1; then
+ gcc_cv_as_dwarf2_debug_line=yes
+ fi
+ 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_dwarf2_debug_line" >&5
+$as_echo "$gcc_cv_as_dwarf2_debug_line" >&6; }
+
+
+
+# The .debug_line file table must be in the exact order that
+# we specified the files, since these indices are also used
+# by DW_AT_decl_file. Approximate this test by testing if
+# the assembler bitches if the same index is assigned twice.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for buggy dwarf2 .file directive" >&5
+$as_echo_n "checking assembler for buggy dwarf2 .file directive... " >&6; }
+if ${gcc_cv_as_dwarf2_file_buggy+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_dwarf2_file_buggy=no
+ if test x$gcc_cv_as != x; then
+ $as_echo ' .file 1 "foo.s"
+ .file 1 "bar.s"' > 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_dwarf2_file_buggy=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_dwarf2_file_buggy" >&5
+$as_echo "$gcc_cv_as_dwarf2_file_buggy" >&6; }
+
+
+
+ if test $gcc_cv_as_dwarf2_debug_line = yes \
+ && test $gcc_cv_as_dwarf2_file_buggy = no; then
+
+$as_echo "#define HAVE_AS_DWARF2_DEBUG_LINE 1" >>confdefs.h
+
+
+ if test $gcc_cv_as_leb128 = yes; then
+ conftest_s="\
+ .file 1 \"conftest.s\"
+ .loc 1 3 0 view .LVU1
+ $insn
+ .data
+ .uleb128 .LVU1
+ .uleb128 .LVU1
+"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for dwarf2 debug_view support" >&5
+$as_echo_n "checking assembler for dwarf2 debug_view support... " >&6; }
+if ${gcc_cv_as_dwarf2_debug_view+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_dwarf2_debug_view=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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_dwarf2_debug_view=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_dwarf2_debug_view" >&5
+$as_echo "$gcc_cv_as_dwarf2_debug_view" >&6; }
+if test $gcc_cv_as_dwarf2_debug_view = yes; then
+
+$as_echo "#define HAVE_AS_DWARF2_DEBUG_VIEW 1" >>confdefs.h
+
+fi
+
+ fi
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf2 option" >&5
+$as_echo_n "checking assembler for --gdwarf2 option... " >&6; }
+if ${gcc_cv_as_gdwarf2_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gdwarf2_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 --gdwarf2 -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_gdwarf2_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_gdwarf2_flag" >&5
+$as_echo "$gcc_cv_as_gdwarf2_flag" >&6; }
+if test $gcc_cv_as_gdwarf2_flag = yes; then
+
+$as_echo "#define HAVE_AS_GDWARF2_DEBUG_FLAG 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf-5 option" >&5
+$as_echo_n "checking assembler for --gdwarf-5 option... " >&6; }
+if ${gcc_cv_as_gdwarf_5_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gdwarf_5_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 --gdwarf-5 -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
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -Wi conftest.o 2>&1 \
+ | grep DW_TAG_compile_unit > /dev/null 2>&1; then
+ gcc_cv_as_gdwarf_5_flag=yes;
+ fi
+ 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_gdwarf_5_flag" >&5
+$as_echo "$gcc_cv_as_gdwarf_5_flag" >&6; }
+if test $gcc_cv_as_gdwarf_5_flag = yes; then
+
+$as_echo "#define HAVE_AS_GDWARF_5_DEBUG_FLAG 1" >>confdefs.h
+
+fi
+
+
+ case $target_os in
+ win32 | pe | cygwin* | mingw32*)
+ section_flags=\"dr\"
+ function_type=".def foo; .scl 2; .type 32; .endef"
+ function_size="";;
+ *)
+ section_flags=\"\",%progbits
+ function_type=".type foo, %function"
+ function_size=".size foo, .-foo";;
+ esac
+ dwarf4_debug_info_size=0x46
+ dwarf4_high_pc_form=7
+ dwarf4_debug_aranges_size=0x2c
+ dwarf4_line_sz=9
+ for dwarf4_addr_size in 8 4; do
+ conftest_s="\
+ .file \"a.c\"
+ .text
+.Ltext0:
+ .p2align 4
+ .globl foo
+ $function_type
+foo:
+.LFB0:
+.LM1:
+ $insn
+.LM2:
+.LFE0:
+ $function_size
+.Letext0:
+ .section .debug_info,$section_flags
+.Ldebug_info0:
+ .4byte $dwarf4_debug_info_size
+ .2byte 0x4
+ .4byte .Ldebug_abbrev0
+ .byte 0x$dwarf4_addr_size
+ .byte 0x1
+ .ascii \"GNU C17\\0\"
+ .byte 0xc
+ .ascii \"a.c\\0\"
+ .ascii \"/\\0\"
+ .${dwarf4_addr_size}byte .Ltext0
+ .${dwarf4_addr_size}byte .Letext0-.Ltext0
+ .4byte .Ldebug_line0
+ .byte 0x2
+ .ascii \"foo\\0\"
+ .byte 0x1
+ .byte 0x2
+ .byte 0x1
+ .${dwarf4_addr_size}byte .LFB0
+ .${dwarf4_addr_size}byte .LFE0-.LFB0
+ .byte 0x1
+ .byte 0x9c
+ .byte 0
+ .section .debug_abbrev,$section_flags
+.Ldebug_abbrev0:
+ .byte 0x1
+ .byte 0x11
+ .byte 0x1
+ .byte 0x25
+ .byte 0x8
+ .byte 0x13
+ .byte 0xb
+ .byte 0x3
+ .byte 0x8
+ .byte 0x1b
+ .byte 0x8
+ .byte 0x11
+ .byte 0x1
+ .byte 0x12
+ .byte 0x$dwarf4_high_pc_form
+ .byte 0x10
+ .byte 0x17
+ .byte 0
+ .byte 0
+ .byte 0x2
+ .byte 0x2e
+ .byte 0
+ .byte 0x3f
+ .byte 0x19
+ .byte 0x3
+ .byte 0x8
+ .byte 0x3a
+ .byte 0xb
+ .byte 0x3b
+ .byte 0xb
+ .byte 0x39
+ .byte 0xb
+ .byte 0x11
+ .byte 0x1
+ .byte 0x12
+ .byte 0x$dwarf4_high_pc_form
+ .byte 0x40
+ .byte 0x18
+ .byte 0
+ .byte 0
+ .byte 0
+ .section .debug_aranges,$section_flags
+ .4byte $dwarf4_debug_aranges_size
+ .2byte 0x2
+ .4byte .Ldebug_info0
+ .byte 0x8
+ .byte 0
+ .2byte 0
+ .2byte 0
+ .${dwarf4_addr_size}byte .Ltext0
+ .${dwarf4_addr_size}byte .Letext0-.Ltext0
+ .${dwarf4_addr_size}byte 0
+ .${dwarf4_addr_size}byte 0
+ .section .debug_line,$section_flags
+.Ldebug_line0:
+ .4byte .LELT0-.LSLT0
+.LSLT0:
+ .2byte 0x4
+ .4byte .LELTP0-.LASLTP0
+.LASLTP0:
+ .byte 0x1
+ .byte 0x1
+ .byte 0x1
+ .byte 0xf6
+ .byte 0xf2
+ .byte 0xd
+ .byte 0
+ .byte 0x1
+ .byte 0x1
+ .byte 0x1
+ .byte 0x1
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0x1
+ .byte 0
+ .byte 0
+ .byte 0x1
+ .byte 0
+ .ascii \"a.c\\0\"
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0
+.LELTP0:
+ .byte 0
+ .byte 0x$dwarf4_line_sz
+ .byte 0x2
+ .${dwarf4_addr_size}byte .LM1
+ .byte 0x18
+ .byte 0x5
+ .byte 0x1
+ .byte 0
+ .byte 0x$dwarf4_line_sz
+ .byte 0x2
+ .${dwarf4_addr_size}byte .LM2
+ .byte 0x1
+ .byte 0x5
+ .byte 0x1
+ .byte 0
+ .byte 0x$dwarf4_line_sz
+ .byte 0x2
+ .${dwarf4_addr_size}byte .Letext0
+ .byte 0
+ .byte 0x1
+ .byte 0x1
+.LELT0:
+ .section .debug_str,$section_flags
+ .ident \"GCC\"
+"
+ dwarf4_success=no
+ if test $dwarf4_addr_size = 4; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembly of compiler generated 32-bit .debug_line" >&5
+$as_echo_n "checking assembler for assembly of compiler generated 32-bit .debug_line... " >&6; }
+if ${gcc_cv_as_debug_line_32_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_debug_line_32_flag=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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_debug_line_32_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_debug_line_32_flag" >&5
+$as_echo "$gcc_cv_as_debug_line_32_flag" >&6; }
+if test $gcc_cv_as_debug_line_32_flag = yes; then
+ dwarf4_success=yes
+fi
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for assembly of compiler generated 64-bit .debug_line" >&5
+$as_echo_n "checking assembler for assembly of compiler generated 64-bit .debug_line... " >&6; }
+if ${gcc_cv_as_debug_line_64_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_debug_line_64_flag=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > 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_debug_line_64_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_debug_line_64_flag" >&5
+$as_echo "$gcc_cv_as_debug_line_64_flag" >&6; }
+if test $gcc_cv_as_debug_line_64_flag = yes; then
+ dwarf4_success=yes
+fi
+
+ fi
+ if test $dwarf4_success = yes; then
+ dwarf4_success=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf-4 not refusing compiler generated .debug_line" >&5
+$as_echo_n "checking assembler for --gdwarf-4 not refusing compiler generated .debug_line... " >&6; }
+if ${gcc_cv_as_dwarf_4_debug_line_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_dwarf_4_debug_line_flag=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --gdwarf-4 -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_dwarf_4_debug_line_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_dwarf_4_debug_line_flag" >&5
+$as_echo "$gcc_cv_as_dwarf_4_debug_line_flag" >&6; }
+if test $gcc_cv_as_dwarf_4_debug_line_flag = yes; then
+ dwarf4_success=yes
+fi
+
+ break
+ fi
+ dwarf4_debug_info_size=0x36
+ dwarf4_high_pc_form=6
+ dwarf4_debug_aranges_size=0x1c
+ dwarf4_line_sz=5
+ done
+
+ if test $dwarf4_success = yes; then
+ conftest_s="\
+ .file \"foo.c\"
+ .text
+bar:
+#APP
+# 82 \"xxx.h\" 1
+ $insn
+# 0 \"\" 2
+#NO_APP
+ $insn
+foo:
+ .file 1 \"foo.c\"
+ $insn
+ .file 2 \"foo.h\"
+ ret
+"
+ dwarf4_success=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for --gdwarf-4 with the APP marker" >&5
+$as_echo_n "checking assembler for --gdwarf-4 with the APP marker... " >&6; }
+if ${gcc_cv_as_dwarf_4_app_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_dwarf_4_app_flag=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --gdwarf-4 -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_dwarf_4_app_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_dwarf_4_app_flag" >&5
+$as_echo "$gcc_cv_as_dwarf_4_app_flag" >&6; }
+if test $gcc_cv_as_dwarf_4_app_flag = yes; then
+ dwarf4_success=yes
+fi
+
+ fi
+
+ if test $dwarf4_success = yes; then
+ conftest_s="\
+ .text
+ .globl foo
+ $function_type
+foo:
+ $insn
+ $function_size
+ .file 1 \"foo.c\"
+"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for working --gdwarf-4/--gdwarf-5 for all sources" >&5
+$as_echo_n "checking assembler for working --gdwarf-4/--gdwarf-5 for all sources... " >&6; }
+if ${gcc_cv_as_working_gdwarf_n_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_working_gdwarf_n_flag=no
+ if test x$gcc_cv_as != x; then
+ $as_echo "$conftest_s" > conftest.s
+ if { ac_try='$gcc_cv_as $gcc_cv_as_flags --gdwarf-4 -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
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -W conftest.o 2>&1 \
+ | grep conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_working_gdwarf_n_flag=no
+ else
+ gcc_cv_as_working_gdwarf_n_flag=yes
+ fi
+ 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_working_gdwarf_n_flag" >&5
+$as_echo "$gcc_cv_as_working_gdwarf_n_flag" >&6; }
+
+
+ if test $gcc_cv_as_working_gdwarf_n_flag = yes; then
+
+$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 :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_debug_prefix_map_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 --debug-prefix-map /a=/b -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_debug_prefix_map_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_debug_prefix_map_flag" >&5
+$as_echo "$gcc_cv_as_debug_prefix_map_flag" >&6; }
+if test $gcc_cv_as_debug_prefix_map_flag = yes; then
+
+$as_echo "#define HAVE_AS_DEBUG_PREFIX_MAP 1" >>confdefs.h
+
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for compressed debug sections" >&5
+$as_echo_n "checking assembler for compressed debug sections... " >&6; }
+if ${gcc_cv_as_compress_debug+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_compress_debug=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '' > 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
+ # gas compiled without zlib cannot compress debug sections and warns
+ # about it, but still exits successfully. So check for this, too.
+ if $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s 2>&1 | grep -i warning > /dev/null
+ then
+ gcc_cv_as_compress_debug=0
+ # Since binutils 2.26, gas supports --compress-debug-sections=type,
+ # defaulting to the ELF gABI format.
+ elif $gcc_cv_as --compress-debug-sections=zlib-gnu -o conftest.o conftest.s > /dev/null 2>&1
+ then
+ gcc_cv_as_compress_debug=2
+ gcc_cv_as_compress_debug_option="--compress-debug-sections"
+ gcc_cv_as_no_compress_debug_option="--nocompress-debug-sections"
+ # Before binutils 2.26, gas only supported --compress-debug-options and
+ # emitted the traditional GNU format.
+ elif $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s > /dev/null 2>&1
+ then
+ gcc_cv_as_compress_debug=1
+ gcc_cv_as_compress_debug_option="--compress-debug-sections"
+ gcc_cv_as_no_compress_debug_option="--nocompress-debug-sections"
+ else
+ gcc_cv_as_compress_debug=0
+ fi
+ 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_compress_debug" >&5
+$as_echo "$gcc_cv_as_compress_debug" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_AS_COMPRESS_DEBUG $gcc_cv_as_compress_debug
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define AS_COMPRESS_DEBUG_OPTION "$gcc_cv_as_compress_debug_option"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define AS_NO_COMPRESS_DEBUG_OPTION "$gcc_cv_as_no_compress_debug_option"
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .lcomm with alignment" >&5
+$as_echo_n "checking assembler for .lcomm with alignment... " >&6; }
+if ${gcc_cv_as_lcomm_with_alignment+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_lcomm_with_alignment=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.lcomm bar,4,16' > 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_lcomm_with_alignment=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_lcomm_with_alignment" >&5
+$as_echo "$gcc_cv_as_lcomm_with_alignment" >&6; }
+if test $gcc_cv_as_lcomm_with_alignment = yes; then
+
+$as_echo "#define HAVE_GAS_LCOMM_WITH_ALIGNMENT 1" >>confdefs.h
+
+fi
+
+
+if test x$with_sysroot = x && test x$host = x$target \
+ && test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" \
+ && test "$prefix" != "NONE"; then
+
+cat >>confdefs.h <<_ACEOF
+#define PREFIX_INCLUDE_DIR "$prefix/include"
+_ACEOF
+
+fi
+
+# Determine the version of glibc, if any, used on the target.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for target glibc version" >&5
+$as_echo_n "checking for target glibc version... " >&6; }
+
+# Check whether --with-glibc-version was given.
+if test "${with_glibc_version+set}" = set; then :
+ withval=$with_glibc_version;
+if echo "$with_glibc_version" | grep '^[0-9][0-9]*\.[0-9][0-9]*$'; then
+ glibc_version_major=`echo "$with_glibc_version" | sed -e 's/\..*//'`
+ glibc_version_minor=`echo "$with_glibc_version" | sed -e 's/.*\.//'`
+else
+ as_fn_error $? "option --with-glibc-version requires a version number M.N" "$LINENO" 5
+fi
+else
+
+glibc_version_major=0
+glibc_version_minor=0
+if test -f $target_header_dir/features.h \
+ && glibc_version_major_define=`$EGREP '^[ ]*#[ ]*define[ ]+__GLIBC__[ ]+[0-9]' $target_header_dir/features.h` \
+ && glibc_version_minor_define=`$EGREP '^[ ]*#[ ]*define[ ]+__GLIBC_MINOR__[ ]+[0-9]' $target_header_dir/features.h`; then
+ glibc_version_major=`echo "$glibc_version_major_define" | sed -e 's/.*__GLIBC__[ ]*//'`
+ glibc_version_minor=`echo "$glibc_version_minor_define" | sed -e 's/.*__GLIBC_MINOR__[ ]*//'`
+fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibc_version_major.$glibc_version_minor" >&5
+$as_echo "$glibc_version_major.$glibc_version_minor" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define TARGET_GLIBC_MAJOR $glibc_version_major
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define TARGET_GLIBC_MINOR $glibc_version_minor
+_ACEOF
+
+
+# Check whether --enable-gnu-unique-object was given.
+if test "${enable_gnu_unique_object+set}" = set; then :
+ enableval=$enable_gnu_unique_object; case $enable_gnu_unique_object in
+ yes | no) ;;
+ *) as_fn_error $? "'$enable_gnu_unique_object' is an invalid value for --enable-gnu-unique-object.
+Valid choices are 'yes' and 'no'." "$LINENO" 5 ;;
+ esac
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for gnu_unique_object" >&5
+$as_echo_n "checking assembler for gnu_unique_object... " >&6; }
+if ${gcc_cv_as_gnu_unique_object+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_gnu_unique_object=no
+ if test x$gcc_cv_as != x; then
+ $as_echo '.type foo, '$target_type_format_char'gnu_unique_object' > 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_gnu_unique_object=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_gnu_unique_object" >&5
+$as_echo "$gcc_cv_as_gnu_unique_object" >&6; }
+if test $gcc_cv_as_gnu_unique_object = yes; then
+ # We need to unquote above to to use the definition from config.gcc.
+# Also check for ld.so support, i.e. glibc 2.11 or higher.
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 11 ); then :
+ enable_gnu_unique_object=yes
+fi
+
+fi
+
+fi
+
+if test x$enable_gnu_unique_object = xyes; then
+
+$as_echo "#define HAVE_GAS_GNU_UNIQUE_OBJECT 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for tolerance to line number 0" >&5
+$as_echo_n "checking assembler for tolerance to line number 0... " >&6; }
+if ${gcc_cv_as_line_zero+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_line_zero=no
+ if test "x$gcc_cv_as" != x; then
+ { echo '# 1 "test.s" 1'; echo '# 0 "" 2'; } > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5 2>conftest.out'
+ { { 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; }; } &&
+ test "x`cat conftest.out`" = x
+ then
+ gcc_cv_as_line_zero=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ echo "configure: error output was" >&5
+ cat conftest.out >&5
+ fi
+ rm -f conftest.o conftest.s conftest.out
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_line_zero" >&5
+$as_echo "$gcc_cv_as_line_zero" >&6; }
+if test "x$gcc_cv_as_line_zero" = xyes; then
+
+$as_echo "#define HAVE_AS_LINE_ZERO 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking support for thin archives" >&5
+$as_echo_n "checking support for thin archives... " >&6; }
+thin_archive_support=no
+echo 'int main (void) { return 0; }' > conftest.c
+if ($AR --version | sed 1q | grep "GNU ar" \
+ && $CC $CFLAGS -c conftest.c \
+ && $AR rcT conftest.a conftest.o \
+ && $CC $CFLAGS $LDFLAGS -o conftest conftest.a) >/dev/null 2>&1; then
+ thin_archive_support=yes
+fi
+rm -f conftest.c conftest.o conftest.a conftest
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $thin_archive_support" >&5
+$as_echo "$thin_archive_support" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker PT_GNU_EH_FRAME support" >&5
+$as_echo_n "checking linker PT_GNU_EH_FRAME support... " >&6; }
+gcc_cv_ld_eh_frame_hdr=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_frame_hdr=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ # Check if linker supports --eh-frame-hdr option
+ if $gcc_cv_ld --help 2>&1 | grep eh-frame-hdr > /dev/null; then
+ gcc_cv_ld_eh_frame_hdr=yes
+ fi
+ else
+ case "$target" in
+ *-*-solaris2*)
+ # Sun ld has various bugs in .eh_frame_hdr support before version 1.2251.
+ if test "$ld_vers_major" -gt 1 || test "$ld_vers_minor" -ge 2251; then
+ gcc_cv_ld_eh_frame_hdr=yes
+ fi
+ ;;
+ esac
+ fi
+fi
+
+if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then
+
+$as_echo "#define HAVE_LD_EH_FRAME_HDR 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_eh_frame_hdr" >&5
+$as_echo "$gcc_cv_ld_eh_frame_hdr" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker CIEv3 in .eh_frame support" >&5
+$as_echo_n "checking linker CIEv3 in .eh_frame support... " >&6; }
+gcc_cv_ld_eh_frame_ciev3=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_frame_ciev3=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ gcc_cv_ld_eh_frame_ciev3=yes
+ if test 0"$ld_date" -lt 20040513; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2004-05-13, fail
+ gcc_cv_ld_eh_frame_ciev3=no
+ elif test "$ld_vers_major" -lt 2; then
+ gcc_cv_ld_eh_frame_ciev3=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 16; then
+ gcc_cv_ld_eh_frame_ciev3=no
+ fi
+ fi
+ else
+ case "$target" in
+ *-*-solaris2*)
+ # Sun ld added support for CIE v3 in .eh_frame in Solaris 11.1.
+ if test "$ld_vers_major" -gt 1 || test "$ld_vers_minor" -ge 2324; then
+ gcc_cv_ld_eh_frame_ciev3=yes
+ fi
+ ;;
+ esac
+ fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_EH_FRAME_CIEV3 `if test x"$gcc_cv_ld_eh_frame_ciev3" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_eh_frame_ciev3" >&5
+$as_echo "$gcc_cv_ld_eh_frame_ciev3" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker position independent executable support" >&5
+$as_echo_n "checking linker position independent executable support... " >&6; }
+gcc_cv_ld_pie=no
+if test $in_tree_ld = yes ; then
+ case "$target" in
+ # Full PIE support on Solaris was only introduced in gld 2.26.
+ *-*-solaris2*) gcc_gld_pie_min_version=26 ;;
+ *) gcc_gld_pie_min_version=15 ;;
+ esac
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge "$gcc_gld_pie_min_version" -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_pie=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -pie option
+ if $gcc_cv_ld --help 2>&1 | grep -- -pie > /dev/null; then
+ gcc_cv_ld_pie=yes
+ case "$target" in
+ *-*-solaris2*)
+ if echo "$ld_ver" | grep GNU > /dev/null \
+ && test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 26; then
+ gcc_cv_ld_pie=no
+ fi
+ ;;
+ esac
+ else
+ case "$target" in
+ *-*-solaris2.1[1-9]*)
+ # Solaris 11.3 added PIE support.
+ if $gcc_cv_ld -z help 2>&1 | grep -- type.*pie > /dev/null; then
+ gcc_cv_ld_pie=yes
+ fi
+ ;;
+ esac
+ fi
+fi
+if test x"$gcc_cv_ld_pie" = xyes; then
+
+$as_echo "#define HAVE_LD_PIE 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie" >&5
+$as_echo "$gcc_cv_ld_pie" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker PIE support with copy reloc" >&5
+$as_echo_n "checking linker PIE support with copy reloc... " >&6; }
+gcc_cv_ld_pie_copyreloc=no
+if test $gcc_cv_ld_pie = yes ; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_pie_copyreloc=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ # Check if linker supports -pie option with copy reloc
+ case "$target" in
+ i?86-*-linux* | x86_64-*-linux*)
+ cat > conftest1.s <<EOF
+ .globl a_glob
+ .data
+ .type a_glob, @object
+ .size a_glob, 4
+a_glob:
+ .long 2
+EOF
+ cat > conftest2.s <<EOF
+ .text
+ .globl main
+ .type main, @function
+main:
+ movl %eax, a_glob(%rip)
+ .size main, .-main
+ .globl ptr
+ .section .data.rel,"aw",@progbits
+ .type ptr, @object
+ptr:
+ .quad a_glob
+EOF
+ if $gcc_cv_as --64 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \
+ && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
+ gcc_cv_ld_pie_copyreloc=yes
+ fi
+ rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
+ ;;
+ esac
+ fi
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_PIE_COPYRELOC `if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie_copyreloc" >&5
+$as_echo "$gcc_cv_ld_pie_copyreloc" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker EH-compatible garbage collection of sections" >&5
+$as_echo_n "checking linker EH-compatible garbage collection of sections... " >&6; }
+gcc_cv_ld_eh_gc_sections=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 17 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_gc_sections=yes
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ cat > conftest.s <<EOF
+ .section .text
+.globl _start
+ .type _start, @function
+_start:
+ .long foo
+ .size _start, .-_start
+ .section .text.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .long 0
+ .size foo, .-foo
+ .section .gcc_except_table.foo,"a",@progbits
+.L0:
+ .long 0
+ .section .eh_frame,"a",@progbits
+ .long .L0
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+ | grep "gc-sections option ignored" > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=no
+ elif $gcc_cv_objdump -h conftest 2> /dev/null \
+ | grep gcc_except_table > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=yes
+ # If no COMDAT groups, the compiler will emit .gnu.linkonce.t. sections.
+ if test x$gcc_cv_as_comdat_group != xyes; then
+ gcc_cv_ld_eh_gc_sections=no
+ cat > conftest.s <<EOF
+ .section .text
+.globl _start
+ .type _start, @function
+_start:
+ .long foo
+ .size _start, .-_start
+ .section .gnu.linkonce.t.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .long 0
+ .size foo, .-foo
+ .section .gcc_except_table.foo,"a",@progbits
+.L0:
+ .long 0
+ .section .eh_frame,"a",@progbits
+ .long .L0
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+ | grep "gc-sections option ignored" > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=no
+ elif $gcc_cv_objdump -h conftest 2> /dev/null \
+ | grep gcc_except_table > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=yes
+ fi
+ fi
+ fi
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest
+fi
+case "$target" in
+ hppa*-*-linux*)
+ # ??? This apparently exposes a binutils bug with PC-relative relocations.
+ gcc_cv_ld_eh_gc_sections=no
+ ;;
+esac
+if test x$gcc_cv_ld_eh_gc_sections = xyes; then
+
+$as_echo "#define HAVE_LD_EH_GC_SECTIONS 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_eh_gc_sections" >&5
+$as_echo "$gcc_cv_ld_eh_gc_sections" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker EH garbage collection of sections bug" >&5
+$as_echo_n "checking linker EH garbage collection of sections bug... " >&6; }
+gcc_cv_ld_eh_gc_sections_bug=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -lt 19 -o "$gcc_cv_gld_major_version" -lt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_gc_sections_bug=yes
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x -a x$gcc_cv_as_comdat_group = xyes; then
+ gcc_cv_ld_eh_gc_sections_bug=yes
+ cat > conftest.s <<EOF
+ .section .text
+.globl _start
+ .type _start, @function
+_start:
+ .long foo
+ .size _start, .-_start
+ .section .text.startup.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .long 0
+ .size foo, .-foo
+ .section .gcc_except_table.foo,"a",@progbits
+.L0:
+ .long 0
+ .section .eh_frame,"a",@progbits
+ .long .L0
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+ | grep "gc-sections option ignored" > /dev/null; then
+ :
+ elif $gcc_cv_objdump -h conftest 2> /dev/null \
+ | grep gcc_except_table > /dev/null; then
+ gcc_cv_ld_eh_gc_sections_bug=no
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest
+fi
+if test x$gcc_cv_ld_eh_gc_sections_bug = xyes; then
+
+$as_echo "#define HAVE_LD_EH_GC_SECTIONS_BUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_eh_gc_sections_bug" >&5
+$as_echo "$gcc_cv_ld_eh_gc_sections_bug" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for compressed debug sections" >&5
+$as_echo_n "checking linker for compressed debug sections... " >&6; }
+# gold/gld support compressed debug sections since binutils 2.19/2.21
+# In binutils 2.26, gld gained support for the ELF gABI format.
+if test $in_tree_ld = yes ; then
+ gcc_cv_ld_compress_debug=0
+ if test $ld_is_mold = yes; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 19 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes && test $ld_is_gold = yes; then
+ gcc_cv_ld_compress_debug=2
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes && test $ld_is_gold = no; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_compress_debug=1
+ fi
+elif echo "$ld_ver" | grep GNU > /dev/null; then
+ if test $ld_is_mold = yes; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$ld_vers_major" -lt 2 \
+ || test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 21; then
+ gcc_cv_ld_compress_debug=0
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 26; then
+ gcc_cv_ld_compress_debug=1
+ else
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ fi
+ if test $ld_is_gold = yes; then
+ gcc_cv_ld_compress_debug=2
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ fi
+else
+ case "${target}" in
+ *-*-solaris2*)
+ # Introduced in Solaris 11.2.
+ if $gcc_cv_ld --help 2>&1 | grep -- '-z compress-sections' > /dev/null; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="-z compress-sections"
+ else
+ gcc_cv_ld_compress_debug=0
+ fi
+ ;;
+ *)
+ # Assume linkers other than GNU ld don't support compessed debug
+ # sections.
+ gcc_cv_ld_compress_debug=0
+ ;;
+ esac
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_LD_COMPRESS_DEBUG $gcc_cv_ld_compress_debug
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD_COMPRESS_DEBUG_OPTION "$gcc_cv_ld_compress_debug_option"
+_ACEOF
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_compress_debug" >&5
+$as_echo "$gcc_cv_ld_compress_debug" >&6; }
+
+if test x"$ld64_flag" = x"yes"; then
+
+ # Set defaults for possibly untestable items.
+ gcc_cv_ld64_export_dynamic=0
+ gcc_cv_ld64_platform_version=0
+
+ if test "$build" = "$host"; then
+ darwin_try_test=1
+ else
+ darwin_try_test=0
+ fi
+
+ # On Darwin, because of FAT library support, it is often possible to execute
+ # exes from compatible archs even when the host differs from the build system.
+ case "$build","$host" in
+ x86_64-*-darwin*,i?86-*-darwin* | powerpc64*-*-darwin*,powerpc*-*-darwin*)
+ darwin_try_test=1;;
+ *) ;;
+ esac
+
+ # If the configurer specified a minimum ld64 version to be supported, then use
+ # that to determine feature support.
+ if test x"${gcc_cv_ld64_version}" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking ld64 specified version" >&5
+$as_echo_n "checking ld64 specified version... " >&6; }
+ gcc_cv_ld64_major=`echo "$gcc_cv_ld64_version" | sed -e 's/\..*//'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld64_major" >&5
+$as_echo "$gcc_cv_ld64_major" >&6; }
+ if test "$gcc_cv_ld64_major" -ge 236; then
+ gcc_cv_ld64_export_dynamic=1
+ fi
+ if test "$gcc_cv_ld64_major" -ge 512; then
+ gcc_cv_ld64_platform_version=1
+ fi
+ elif test -x "$gcc_cv_ld" -a "$darwin_try_test" -eq 1; then
+ # If the version was not specified, try to find it.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker version" >&5
+$as_echo_n "checking linker version... " >&6; }
+ if test x"${gcc_cv_ld64_version}" = x; then
+ gcc_cv_ld64_version=`$gcc_cv_ld -v 2>&1 | grep ld64 | sed s/.*ld64-// | awk '{print $1}'`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld64_version" >&5
+$as_echo "$gcc_cv_ld64_version" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for -export_dynamic support" >&5
+$as_echo_n "checking linker for -export_dynamic support... " >&6; }
+ gcc_cv_ld64_export_dynamic=1
+ if $gcc_cv_ld -export_dynamic < /dev/null 2>&1 | grep 'unknown option' > /dev/null; then
+ gcc_cv_ld64_export_dynamic=0
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld64_export_dynamic" >&5
+$as_echo "$gcc_cv_ld64_export_dynamic" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker for -platform_version support" >&5
+$as_echo_n "checking linker for -platform_version support... " >&6; }
+ gcc_cv_ld64_platform_version=1
+ if $gcc_cv_ld -platform_version macos 10.5 0.0 < /dev/null 2>&1 | grep 'unknown option' > /dev/null; then
+ gcc_cv_ld64_platform_version=0
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld64_platform_version" >&5
+$as_echo "$gcc_cv_ld64_platform_version" >&6; }
+ fi
+
+ if test x"${gcc_cv_ld64_version}" != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define LD64_VERSION "${gcc_cv_ld64_version}"
+_ACEOF
+
+ fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD64_HAS_EXPORT_DYNAMIC $gcc_cv_ld64_export_dynamic
+_ACEOF
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD64_HAS_PLATFORM_VERSION $gcc_cv_ld64_platform_version
+_ACEOF
+
+fi
+
+if test x"$dsymutil_flag" = x"yes"; then
+
+ # If the user specified a dsymutil path, then we will already have the
+ # version string, otherwise, pick it up.
+ if test x"$gcc_cv_dsymutil" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: dsymutil is a required tool for this system, but not found" >&5
+$as_echo "$as_me: WARNING: dsymutil is a required tool for this system, but not found" >&2;}
+ dsymutil_vers="tool unspecified"
+ elif test x"$dsymutil_vers" = x; then
+ dsymutil_vers=`$gcc_cv_dsymutil -v /dev/null 2>&1`
+ fi
+
+ dsymutil_temp=`echo $dsymutil_vers | sed 1q`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dsymutil version \"$dsymutil_temp\"" >&5
+$as_echo_n "checking dsymutil version \"$dsymutil_temp\"... " >&6; }
+ if echo $dsymutil_temp | grep dwarfutils- > /dev/null; then
+ dsymutil_kind=DWARFUTILS
+ dsymutil_vers=`echo $dsymutil_temp | sed 's/.*dwarfutils-\([0-9\.]*\).*/\1/'`
+ elif echo $dsymutil_temp | grep clang- > /dev/null; then
+ dsymutil_kind=CLANG
+ dsymutil_vers=`echo $dsymutil_temp | sed 's/.*clang-\([0-9\.]*\).*/\1/'`
+ elif echo $dsymutil_temp | grep 'LLVM version ' > /dev/null; then
+ dsymutil_kind=LLVM
+ dsymutil_vers=`echo $dsymutil_temp | sed 's/.*LLVM\ version\ \([0-9\.]*\).*/\1/'`
+ else
+ dsymutil_kind=UNKNOWN
+ dsymutil_vers="0.0"
+ fi
+ dsymutil_major=`expr "$dsymutil_vers" : '\([0-9]*\)'`
+ dsymutil_minor=`expr "$dsymutil_vers" : '[0-9]*\.\([0-9]*\)'`
+ dsymutil_tiny=`expr "$dsymutil_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
+ if test x"${dsymutil_minor}" = x; then
+ dsymutil_minor=0
+ fi
+ if test x"${dsymutil_tiny}" = x; then
+ dsymutil_tiny=0
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define DSYMUTIL_VERSION $dsymutil_kind,${dsymutil_major},${dsymutil_minor},${dsymutil_tiny}
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dsymutil_vers : $dsymutil_kind ${dsymutil_major} ${dsymutil_minor} ${dsymutil_tiny} " >&5
+$as_echo "$dsymutil_vers : $dsymutil_kind ${dsymutil_major} ${dsymutil_minor} ${dsymutil_tiny} " >&6; }
+fi
+
+case $target_os in
+ win32 | pe | cygwin* | mingw32*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking broken PE linker dwarf5 support" >&5
+$as_echo_n "checking broken PE linker dwarf5 support... " >&6; }
+ gcc_cv_ld_broken_pe_dwarf5=yes
+ if test $in_tree_ld = yes ; then
+ if grep -q '\.debug_loclists.*BLOCK.*__section_alignment__.*NOLOAD.*:' \
+ $gcc_cv_ld_gld_srcdir/scripttempl/pe*.sc \
+ && grep -q '\.debug_rnglists.*BLOCK.*__section_alignment__.*NOLOAD.*:' \
+ $gcc_cv_ld_gld_srcdir/scripttempl/pe*.sc; then
+ gcc_cv_ld_broken_pe_dwarf5=no
+ fi
+ else
+ if $gcc_cv_ld --verbose 2>&1 | grep -q '\.debug_loclists.*BLOCK.*__section_alignment__.*NOLOAD.*:' \
+ && $gcc_cv_ld --verbose 2>&1 | grep -q '\.debug_rnglists.*BLOCK.*__section_alignment__.*NOLOAD.*:'; then
+ gcc_cv_ld_broken_pe_dwarf5=no
+ fi
+ fi
+ if test x$gcc_cv_ld_broken_pe_dwarf5 = xyes; then
+
+$as_echo "#define HAVE_LD_BROKEN_PE_DWARF5 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_broken_pe_dwarf5" >&5
+$as_echo "$gcc_cv_ld_broken_pe_dwarf5" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking PE linker --disable-dynamicbase support" >&5
+$as_echo_n "checking PE linker --disable-dynamicbase support... " >&6; }
+ gcc_cv_ld_disable_dynamicbase=no
+ if test $in_tree_ld = yes; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 36 -o "$gcc_cv_gld_major_version" -gt 2; then \
+ gcc_cv_ld_disable_dynamicbase=yes
+ fi
+ else
+ if $gcc_cv_ld --help 2>&1 | grep -q 'disable\-]dynamicbase' > /dev/null; then
+ gcc_cv_ld_disable_dynamicbase=yes
+ fi
+ fi
+ if test x"$gcc_cv_ld_disable_dynamicbase" = xyes; then
+
+$as_echo "#define HAVE_LD_PE_DISABLE_DYNAMICBASE 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_disable_dynamicbase" >&5
+$as_echo "$gcc_cv_ld_disable_dynamicbase" >&6; }
+ ;;
+esac
+
+# --------
+# UNSORTED
+# --------
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --as-needed support" >&5
+$as_echo_n "checking linker --as-needed support... " >&6; }
+if ${gcc_cv_ld_as_needed+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_as_needed=no
+gcc_cv_ld_as_needed_option='--as-needed'
+gcc_cv_ld_no_as_needed_option='--no-as-needed'
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_as_needed=yes
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 28; then
+ gcc_cv_ld_as_needed_option='--push-state --as-needed'
+ gcc_cv_ld_no_as_needed_option='--pop-state'
+ fi
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports --as-needed and --no-as-needed options
+ if $gcc_cv_ld --help 2>&1 | grep as-needed > /dev/null; then
+ gcc_cv_ld_as_needed=yes
+ if $gcc_cv_ld --help 2>&1 | grep push-state > /dev/null \
+ && $gcc_cv_ld --help 2>&1 | grep pop-state > /dev/null \
+ && echo "$ld_ver" | grep GNU > /dev/null \
+ && test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -ge 28; then
+ # Use these options only when both ld.bfd and ld.gold support
+ # --push-state/--pop-state, which unfortunately wasn't added
+ # at the same time.
+ gcc_cv_ld_as_needed_option='--push-state --as-needed'
+ gcc_cv_ld_no_as_needed_option='--pop-state'
+ fi
+ fi
+ case "$target:$gnu_ld" in
+ *-*-solaris2*:no)
+ # Solaris 2 ld always supports -z ignore/-z record. Prefer the native
+ # forms.
+ gcc_cv_ld_as_needed=yes
+ gcc_cv_ld_as_needed_option="-z ignore"
+ gcc_cv_ld_no_as_needed_option="-z record"
+ ;;
+ esac
+fi
+# --as-needed/-z ignore can only be used if libgcc_s.so.1 uses
+# dl_iterate_phdr, i.e. since Solaris 11.
+case "$target" in
+ *-*-solaris2.1[1-9]*)
+ case "$target" in
+ i?86-*-* | x86_64-*-*)
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ # Doesn't work with gld on Solaris/x86 due to PR ld/12320.
+ gcc_cv_ld_as_needed=no
+ fi
+ ;;
+ esac
+ ;;
+ *-*-solaris2*)
+ gcc_cv_ld_as_needed=no
+ ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_as_needed" >&5
+$as_echo "$gcc_cv_ld_as_needed" >&6; }
+if test x"$gcc_cv_ld_as_needed" = xyes; then
+
+$as_echo "#define HAVE_LD_AS_NEEDED 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD_AS_NEEDED_OPTION "$gcc_cv_ld_as_needed_option"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define LD_NO_AS_NEEDED_OPTION "$gcc_cv_ld_no_as_needed_option"
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker mapfile support for clearing hardware capabilities" >&5
+$as_echo_n "checking linker mapfile support for clearing hardware capabilities... " >&6; }
+saved_LDFLAGS="$LDFLAGS"
+for clearcap_map in sol2-clearcapv2.map sol2-clearcap.map; do
+ LDFLAGS="$saved_LDFLAGS -Wl,-M,${srcdir}/config/$clearcap_map"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) {return 0;}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ gcc_cv_ld_clearcap=yes; break
+else
+ gcc_cv_ld_clearcap=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+done
+LDFLAGS="$saved_LDFLAGS"
+if test "x$gcc_cv_ld_clearcap" = xyes; then
+
+$as_echo "#define HAVE_LD_CLEARCAP 1" >>confdefs.h
+
+ ac_config_links="$ac_config_links clearcap.map:${srcdir}/config/$clearcap_map"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_clearcap" >&5
+$as_echo "$gcc_cv_ld_clearcap" >&6; }
+
+case "$target" in
+ powerpc*-*-*)
+ case "$target" in
+ *le-*-linux*)
+ emul_name="-melf32lppc"
+ ;;
+ *)
+ emul_name="-melf32ppc"
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker .gnu.attributes long double support" >&5
+$as_echo_n "checking linker .gnu.attributes long double support... " >&6; }
+if ${gcc_cv_ld_ppc_attr+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_ppc_attr=no
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_ppc_attr=yes
+ elif test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 \
+ -a "$gcc_cv_gld_minor_version" -ge 28 \
+ -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_ppc_attr=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ # check that merging the long double .gnu_attribute doesn't warn
+ cat > conftest1.s <<EOF
+ .gnu_attribute 4,1
+EOF
+ cat > conftest2.s <<EOF
+ .gnu_attribute 4,9
+EOF
+ if $gcc_cv_as -a32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -a32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name -r -o conftest.o conftest1.o conftest2.o > /dev/null 2> conftest.err \
+ && test ! -s conftest.err; then
+ gcc_cv_ld_ppc_attr=yes
+ fi
+ rm -f conftest.err conftest.o conftest1.o conftest2.o conftest1.s conftest2.s
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_ppc_attr" >&5
+$as_echo "$gcc_cv_ld_ppc_attr" >&6; }
+ if test x$gcc_cv_ld_ppc_attr = xyes; then
+
+$as_echo "#define HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
+case "$target:$tm_file" in
+ powerpc64*-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
+ case "$target" in
+ *le-*-linux*)
+ emul_name="-melf64lppc"
+ ;;
+ *-*-linux*)
+ emul_name="-melf64ppc"
+ ;;
+ *le-*-freebsd*)
+ emul_name="-melf64lppc_fbsd"
+ ;;
+ *-*-freebsd*)
+ emul_name="-melf64ppc_fbsd"
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker support for omitting dot symbols" >&5
+$as_echo_n "checking linker support for omitting dot symbols... " >&6; }
+if ${gcc_cv_ld_no_dot_syms+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_no_dot_syms=no
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_no_dot_syms=yes
+ elif test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_no_dot_syms=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ cat > conftest1.s <<EOF
+ .text
+ bl .foo
+EOF
+ cat > conftest2.s <<EOF
+ .section ".opd","aw"
+ .align 3
+ .globl foo
+ .type foo,@function
+foo:
+ .quad .LEfoo,.TOC.@tocbase,0
+ .text
+.LEfoo:
+ blr
+ .size foo,.-.LEfoo
+EOF
+ if $gcc_cv_as -a64 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -a64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name -o conftest conftest1.o conftest2.o > /dev/null 2>&1; then
+ gcc_cv_ld_no_dot_syms=yes
+ fi
+ rm -f conftest conftest1.o conftest2.o conftest1.s conftest2.s
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_no_dot_syms" >&5
+$as_echo "$gcc_cv_ld_no_dot_syms" >&6; }
+ if test x"$gcc_cv_ld_no_dot_syms" = xyes; then
+
+$as_echo "#define HAVE_LD_NO_DOT_SYMS 1" >>confdefs.h
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker large toc support" >&5
+$as_echo_n "checking linker large toc support... " >&6; }
+if ${gcc_cv_ld_large_toc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_large_toc=no
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_large_toc=yes
+ elif test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_large_toc=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ cat > conftest.s <<EOF
+ .section ".tbss","awT",@nobits
+ .align 3
+ie0: .space 8
+ .global _start
+ .text
+_start:
+ addis 9,13,ie0@got@tprel@ha
+ ld 9,ie0@got@tprel@l(9)
+EOF
+ if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name --no-toc-sort -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_ld_large_toc=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_large_toc" >&5
+$as_echo "$gcc_cv_ld_large_toc" >&6; }
+ if test x"$gcc_cv_ld_large_toc" = xyes; then
+
+$as_echo "#define HAVE_LD_LARGE_TOC 1" >>confdefs.h
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker toc pointer alignment" >&5
+$as_echo_n "checking linker toc pointer alignment... " >&6; }
+if ${gcc_cv_ld_toc_align+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_nm != x; then
+ cat > conftest.s <<EOF
+ .global _start
+ .text
+_start:
+ addis 9,2,x@got@ha
+ .section .data.rel.ro,"aw",@progbits
+ .p2align 16
+ .space 32768
+x: .quad .TOC.
+EOF
+ if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name -z norelro -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_ld_toc_align=`$gcc_cv_nm conftest | ${AWK} '/\.TOC\./ { match ($0, "0[[:xdigit:]]*", a); print strtonum ("0x" substr(a[0], length(a[0])-3)) }'`
+ fi
+ rm -f conftest conftest.o conftest.s
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_toc_align" >&5
+$as_echo "$gcc_cv_ld_toc_align" >&6; }
+ if test -n "$gcc_cv_ld_toc_align" && test $gcc_cv_ld_toc_align -gt 8; then
+
+cat >>confdefs.h <<_ACEOF
+#define POWERPC64_TOC_POINTER_ALIGNMENT $gcc_cv_ld_toc_align
+_ACEOF
+
+ fi
+ ;;
+esac
+
+case "$target" in
+ *-*-aix*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker large toc support" >&5
+$as_echo_n "checking linker large toc support... " >&6; }
+if ${gcc_cv_ld_large_toc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_large_toc=no
+ if test x$gcc_cv_as != x ; then
+ cat > conftest.s <<EOF
+ .toc
+LC..1:
+ .tc a[TC],a[RW]
+ .extern a[RW]
+ .csect .text[PR]
+.largetoctest:
+ addis 9,LC..1@u(2)
+ ld 3,LC..1@l(9)
+EOF
+ if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_ld_large_toc=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_large_toc" >&5
+$as_echo "$gcc_cv_ld_large_toc" >&6; }
+ if test x"$gcc_cv_ld_large_toc" = xyes; then
+
+$as_echo "#define HAVE_LD_LARGE_TOC 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --build-id support" >&5
+$as_echo_n "checking linker --build-id support... " >&6; }
+if ${gcc_cv_ld_buildid+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_buildid=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a \
+ "$gcc_cv_gld_minor_version" -ge 18 -o \
+ "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_buildid=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --help 2>&1 | grep build-id > /dev/null; then
+ gcc_cv_ld_buildid=yes
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_buildid" >&5
+$as_echo "$gcc_cv_ld_buildid" >&6; }
+if test x"$gcc_cv_ld_buildid" = xyes; then
+
+$as_echo "#define HAVE_LD_BUILDID 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-linker-build-id was given.
+if test "${enable_linker_build_id+set}" = set; then :
+ enableval=$enable_linker_build_id;
+else
+ enable_linker_build_id=no
+fi
+
+
+if test x"$enable_linker_build_id" = xyes; then
+ if test x"$gcc_cv_ld_buildid" = xyes; then
+
+$as_echo "#define ENABLE_LD_BUILDID 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --build-id is not supported by your linker; --enable-linker-build-id ignored" >&5
+$as_echo "$as_me: WARNING: --build-id is not supported by your linker; --enable-linker-build-id ignored" >&2;}
+ fi
+fi
+
+# In binutils 2.21, GNU ld gained support for new emulations fully
+# supporting the Solaris 2 ABI. Detect their presence in the linker used.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker *_sol2 emulation support" >&5
+$as_echo_n "checking linker *_sol2 emulation support... " >&6; }
+if ${gcc_cv_ld_sol2_emulation+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_sol2_emulation=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a \
+ "$gcc_cv_gld_minor_version" -ge 21 -o \
+ "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_sol2_emulation=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld -V 2>/dev/null | sed -e '1,/Supported emulations/d;q' | \
+ grep _sol2 > /dev/null; then
+ gcc_cv_ld_sol2_emulation=yes
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_sol2_emulation" >&5
+$as_echo "$gcc_cv_ld_sol2_emulation" >&6; }
+if test x"$gcc_cv_ld_sol2_emulation" = xyes; then
+
+$as_echo "#define HAVE_LD_SOL2_EMULATION 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --sysroot support" >&5
+$as_echo_n "checking linker --sysroot support... " >&6; }
+if ${gcc_cv_ld_sysroot+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_ld_sysroot=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 ; then
+ gcc_cv_ld_sysroot=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --help 2>&1 | grep sysroot > /dev/null; then
+ gcc_cv_ld_sysroot=yes
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_sysroot" >&5
+$as_echo "$gcc_cv_ld_sysroot" >&6; }
+if test x"$gcc_cv_ld_sysroot" = xyes; then
+
+$as_echo "#define HAVE_LD_SYSROOT 1" >>confdefs.h
+
+fi
+
+case $target in
+*-*-solaris2*)
+ # Check for system-provided CRTs on Solaris 11.x and Solaris 12.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking system-provided CRTs on Solaris" >&5
+$as_echo_n "checking system-provided CRTs on Solaris... " >&6; }
+if ${gcc_cv_solaris_crts+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_solaris_crts=no
+ if test x$host != x$target; then
+ if test "x$with_sysroot" = xyes; then
+ target_sysroot="${test_exec_prefix}/${target_noncanonical}/sys-root"
+ else
+ target_sysroot="${with_sysroot}"
+ fi
+ fi
+ target_libdir="$target_sysroot/usr/lib"
+ # At the time they were added, gcrt1.o became a symlink for backwards
+ # compatibility on x86, while crt1.o was added on sparc, so check for that.
+ case $target in
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ if test -h "$target_libdir/gcrt1.o"; then gcc_cv_solaris_crts=yes; fi
+ ;;
+ sparc*-*-solaris2*)
+ if test -f "$target_libdir/crt1.o"; then gcc_cv_solaris_crts=yes; fi
+ ;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_solaris_crts" >&5
+$as_echo "$gcc_cv_solaris_crts" >&6; }
+ ;;
+esac
+if test x$gcc_cv_solaris_crts = xyes; then
+
+$as_echo "#define HAVE_SOLARIS_CRTS 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-libssp was given.
+if test "${enable_libssp+set}" = set; then :
+ enableval=$enable_libssp; case "${enableval}" in
+ yes|no)
+ ;;
+ *)
+ as_fn_error $? "unknown libssp setting $enableval" "$LINENO" 5
+ ;;
+esac
+fi
+
+
+# Test for stack protector support in target C library.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking __stack_chk_fail in target C library" >&5
+$as_echo_n "checking __stack_chk_fail in target C library... " >&6; }
+if ${gcc_cv_libc_provides_ssp+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_libc_provides_ssp=no
+ if test "x$enable_libssp" = "xno"; then
+ gcc_cv_libc_provides_ssp=yes
+ elif test "x$enable_libssp" = "xyes"; then
+ gcc_cv_libc_provides_ssp=no
+ else
+ case "$target" in
+ *-*-musl*)
+ # All versions of musl provide stack protector
+ gcc_cv_libc_provides_ssp=yes;;
+ *-*-linux* | *-*-kfreebsd*-gnu)
+ # glibc 2.4 and later provides __stack_chk_fail and
+ # either __stack_chk_guard, or TLS access to stack guard canary.
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 4 ); then :
+ gcc_cv_libc_provides_ssp=yes
+else
+
+ if test -f $target_header_dir/features.h \
+ && $EGREP '^[ ]*#[ ]*define[ ]+__GNU_LIBRARY__[ ]+([1-9][0-9]|[6-9])' \
+ $target_header_dir/features.h > /dev/null; then
+ if $EGREP '^[ ]*#[ ]*define[ ]+__UCLIBC__[ ]+1' \
+ $target_header_dir/features.h > /dev/null && \
+ test -f $target_header_dir/bits/uClibc_config.h && \
+ $EGREP '^[ ]*#[ ]*define[ ]+__UCLIBC_HAS_SSP__[ ]+1' \
+ $target_header_dir/bits/uClibc_config.h > /dev/null; then
+ gcc_cv_libc_provides_ssp=yes
+ fi
+ # all versions of Bionic support stack protector
+ elif test -f $target_header_dir/sys/cdefs.h \
+ && $EGREP '^[ ]*#[ ]*define[ ]+__BIONIC__[ ]+1' \
+ $target_header_dir/sys/cdefs.h > /dev/null; then
+ gcc_cv_libc_provides_ssp=yes
+ fi
+fi
+ ;;
+ *-*-gnu*)
+ # Avoid complicated tests (see
+ # <http://gcc.gnu.org/ml/gcc/2008-10/msg00130.html>) and for now
+ # simply assert that glibc does provide this, which is true for all
+ # realistically usable GNU/Hurd configurations.
+ # All supported versions of musl provide it as well
+ gcc_cv_libc_provides_ssp=yes;;
+ *-*-darwin* | *-*-freebsd* | *-*-netbsd*)
+ ac_fn_cxx_check_func "$LINENO" "__stack_chk_fail" "ac_cv_func___stack_chk_fail"
+if test "x$ac_cv_func___stack_chk_fail" = xyes; then :
+ gcc_cv_libc_provides_ssp=yes
+else
+ echo "no __stack_chk_fail on this target"
+fi
+
+ ;;
+ *) gcc_cv_libc_provides_ssp=no ;;
+ esac
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_libc_provides_ssp" >&5
+$as_echo "$gcc_cv_libc_provides_ssp" >&6; }
+
+if test x$gcc_cv_libc_provides_ssp = xyes; then
+
+$as_echo "#define TARGET_LIBC_PROVIDES_SSP 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-default-ssp was given.
+# Check whether --enable-default-ssp was given.
+if test "${enable_default_ssp+set}" = set; then :
+ enableval=$enable_default_ssp;
+if test x$gcc_cv_libc_provides_ssp = xyes; then
+ case "$target" in
+ ia64*-*-*) enable_default_ssp=no ;;
+ *) enable_default_ssp=$enableval ;;
+ esac
+else
+ enable_default_ssp=no
+fi
+else
+ enable_default_ssp=no
+fi
+
+if test x$enable_default_ssp = xyes ; then
+
+$as_echo "#define ENABLE_DEFAULT_SSP 1" >>confdefs.h
+
+fi
+
+
+# Test for <sys/sdt.h> on the target.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking sys/sdt.h in the target C library" >&5
+$as_echo_n "checking sys/sdt.h in the target C library... " >&6; }
+have_sys_sdt_h=no
+if test -f $target_header_dir/sys/sdt.h; then
+ have_sys_sdt_h=yes
+
+$as_echo "#define HAVE_SYS_SDT_H 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_sys_sdt_h" >&5
+$as_echo "$have_sys_sdt_h" >&6; }
+
+# Check if TFmode long double should be used by default or not.
+# Some glibc targets used DFmode long double, but with glibc 2.4
+# and later they can use TFmode.
+case "$target" in
+ powerpc*-*-linux* | \
+ sparc*-*-linux* | \
+ s390*-*-linux* | \
+ alpha*-*-linux*)
+
+# Check whether --with-long-double-128 was given.
+if test "${with_long_double_128+set}" = set; then :
+ withval=$with_long_double_128; gcc_cv_target_ldbl128="$with_long_double_128"
+else
+
+ case "$target" in
+ s390*-*-linux-musl*)
+ gcc_cv_target_ldbl128=yes
+ ;;
+ powerpc*-*-linux-musl*)
+ gcc_cv_target_ldbl128=no
+ ;;
+ *)
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 4 ); then :
+ gcc_cv_target_ldbl128=yes
+else
+
+ gcc_cv_target_ldbl128=no
+ grep '^[ ]*#[ ]*define[ ][ ]*__LONG_DOUBLE_MATH_OPTIONAL' \
+ $target_header_dir/bits/wordsize.h > /dev/null 2>&1 \
+ && gcc_cv_target_ldbl128=yes
+
+fi
+
+ ;;
+ esac
+
+fi
+
+ ;;
+esac
+if test x$gcc_cv_target_ldbl128 = xyes; then
+
+$as_echo "#define TARGET_DEFAULT_LONG_DOUBLE_128 1" >>confdefs.h
+
+fi
+
+# Check if TFmode long double target should use the IBM extended double or IEEE
+# 128-bit floating point formats if long doubles are 128-bits long. The long
+# double type can only be switched on powerpc64 bit Linux systems where VSX is
+# supported. Other PowerPC systems do not build the IEEE 128-bit emulator in
+# libgcc.
+
+# Check whether --with-long-double-format was given.
+if test "${with_long_double_format+set}" = set; then :
+ withval=$with_long_double_format;
+case "$target:$with_long_double_format" in
+ powerpc64le-*-linux*:ieee | powerpc64le-*-linux*:ibm)
+ :
+ ;;
+ powerpc64-*-linux*:ieee | powerpc64-*-linux*:ibm)
+ # IEEE 128-bit emulation is only built on 64-bit VSX Linux systems
+ case "$with_cpu" in
+ power7 | power8 | power9 | power1*)
+ :
+ ;;
+ *)
+ as_fn_error $? "Configuration option --with-long-double-format is only \
+supported if the default cpu is power7 or newer" "$LINENO" 5
+ with_long_double_format=""
+ ;;
+ esac
+ ;;
+ powerpc64*-*-linux*:*)
+ as_fn_error $? "--with-long-double-format argument should be ibm or ieee" "$LINENO" 5
+ with_long_double_format=""
+ ;;
+ *)
+ as_fn_error $? "Configure option --with-long-double-format is only supported \
+on 64-bit PowerPC VSX Linux systems" "$LINENO" 5
+ with_long_double_format=""
+ ;;
+esac
+fi
+
+
+# Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP
+# values in the TCB. Currently, only GLIBC 2.23 and later support this.
+gcc_cv_libc_provides_hwcap_in_tcb=no
+case "$target" in
+ powerpc*-*-linux*)
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 23 ); then :
+ gcc_cv_libc_provides_hwcap_in_tcb=yes
+fi
+ ;;
+esac
+if test x$gcc_cv_libc_provides_hwcap_in_tcb = xyes; then
+
+$as_echo "#define TARGET_LIBC_PROVIDES_HWCAP_IN_TCB 1" >>confdefs.h
+
+fi
+
+# Check if the target LIBC handles PT_GNU_STACK.
+gcc_cv_libc_gnustack=unknown
+case "$target" in
+ mips*-*-linux-musl*)
+ gcc_cv_libc_gnustack=yes
+ ;;
+ mips*-*-linux*)
+
+if test $glibc_version_major -gt 2 \
+ || ( test $glibc_version_major -eq 2 && test $glibc_version_minor -ge 31 ); then :
+ gcc_cv_libc_gnustack=yes
+fi
+ ;;
+esac
+if test x$gcc_cv_libc_gnustack = xyes; then
+
+$as_echo "#define TARGET_LIBC_GNUSTACK 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dl_iterate_phdr in target C library" >&5
+$as_echo_n "checking dl_iterate_phdr in target C library... " >&6; }
+gcc_cv_target_dl_iterate_phdr=unknown
+case "$target" in
+ *-*-solaris2*)
+ # <link.h> needs both a dl_iterate_phdr declaration and support for
+ # compilation with largefile support.
+ if grep dl_iterate_phdr $target_header_dir/link.h > /dev/null 2>&1 \
+ && grep 'large file capable' $target_header_dir/link.h > /dev/null 2>&1; then
+ gcc_cv_target_dl_iterate_phdr=yes
+ else
+ gcc_cv_target_dl_iterate_phdr=no
+ fi
+ ;;
+ *-*-dragonfly* | *-*-freebsd*)
+ if grep dl_iterate_phdr $target_header_dir/sys/link_elf.h > /dev/null 2>&1; then
+ gcc_cv_target_dl_iterate_phdr=yes
+ else
+ gcc_cv_target_dl_iterate_phdr=no
+ fi
+ ;;
+ *-linux-musl*)
+ gcc_cv_target_dl_iterate_phdr=yes
+ ;;
+esac
+
+if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
+
+$as_echo "#define TARGET_DL_ITERATE_PHDR 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_target_dl_iterate_phdr" >&5
+$as_echo "$gcc_cv_target_dl_iterate_phdr" >&6; }
+
+# We no longer support different GC mechanisms. Emit an error if
+# the user configures with --with-gc.
+
+# Check whether --with-gc was given.
+if test "${with_gc+set}" = set; then :
+ withval=$with_gc; as_fn_error $? "Configure option --with-gc is only supported up to GCC 4.7.x" "$LINENO" 5
+fi
+
+
+# Libraries to use on the host. This will normally be set by the top
+# level Makefile. Here we simply capture the value for our Makefile.
+if test -z "${HOST_LIBS+set}"; then
+ HOST_LIBS=
+fi
+
+
+# Use the system's zlib library.
+
+ # Use the system's zlib library.
+ zlibdir="-L\$(top_builddir)/../zlib"
+ zlibinc="-I\$(top_srcdir)/../zlib"
+
+# Check whether --with-system-zlib was given.
+if test "${with_system_zlib+set}" = set; then :
+ withval=$with_system_zlib; if test x$with_system_zlib = xyes ; then
+ zlibdir=
+ zlibinc=
+ fi
+
+fi
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+ enableval=$enable_maintainer_mode; maintainer_mode=$enableval
+else
+ maintainer_mode=no
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $maintainer_mode" >&5
+$as_echo "$maintainer_mode" >&6; }
+
+if test "$maintainer_mode" = "yes"; then
+ MAINT=''
+else
+ MAINT='#'
+fi
+
+if test -z "$CTAGS"; then
+ CTAGS=ctags
+fi
+
+if test -z "$ETAGS"; then
+ ETAGS=etags
+fi
+
+if test -z "$CSCOPE"; then
+ CSCOPE=cscope
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to avoid linking multiple front-ends at once" >&5
+$as_echo_n "checking whether to avoid linking multiple front-ends at once... " >&6; }
+ # Check whether --enable-link-mutex was given.
+if test "${enable_link_mutex+set}" = set; then :
+ enableval=$enable_link_mutex; do_link_mutex=$enableval
+else
+ do_link_mutex=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $do_link_mutex" >&5
+$as_echo "$do_link_mutex" >&6; }
+
+if test "$do_link_mutex" = "yes"; then
+ DO_LINK_MUTEX=true
+else
+ DO_LINK_MUTEX=false
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to serialize linking of multiple front-ends" >&5
+$as_echo_n "checking whether to serialize linking of multiple front-ends... " >&6; }
+ # Check whether --enable-link-serialization was given.
+if test "${enable_link_serialization+set}" = set; then :
+ enableval=$enable_link_serialization; do_link_serialization=$enableval
+else
+ do_link_serialization=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $do_link_serialization" >&5
+$as_echo "$do_link_serialization" >&6; }
+
+case "$do_link_serialization" in
+ yes)
+ DO_LINK_SERIALIZATION=1;;
+ [1-9] | [1-9][0-9] | [1-9][0-9][0-9])
+ DO_LINK_SERIALIZATION=$do_link_serialization;;
+ no)
+ DO_LINK_SERIALIZATION=;;
+ *)
+ as_fn_error $? "bad value ${do_link_serialization} given for --enable-link-serialization" "$LINENO" 5 ;;
+esac
+
+
+# --------------
+# Language hooks
+# --------------
+
+# Make empty files to contain the specs and options for each language.
+# Then add #include lines to for a compiler that has specs and/or options.
+
+subdirs=
+lang_opt_files=
+lang_specs_files=
+lang_tree_files=
+# These (without "all_") are set in each config-lang.in.
+# `language' must be a single word so is spelled singularly.
+all_languages=
+all_compilers=
+all_outputs='Makefile'
+# List of language configure and makefile fragments.
+all_lang_configurefrags=
+all_lang_makefrags=
+# Additional files for gengtype
+all_gtfiles="$target_gtfiles"
+
+# These are the languages that are set in --enable-languages,
+# and are available in the GCC tree.
+all_selected_languages=
+
+# Add the language fragments.
+# Languages are added via two mechanisms. Some information must be
+# recorded in makefile variables, these are defined in config-lang.in.
+# We accumulate them and plug them into the main Makefile.
+# The other mechanism is a set of hooks for each of the main targets
+# like `clean', `install', etc.
+
+language_hooks="Make-hooks"
+
+for lang in ${srcdir}/*/config-lang.in
+do
+ test "$lang" = "${srcdir}/*/config-lang.in" && continue
+
+ lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
+ if test "x$lang_alias" = x
+ then
+ echo "$lang doesn't set \$language." 1>&2
+ exit 1
+ fi
+ subdir="`echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ subdirs="$subdirs $subdir"
+
+ # $gcc_subdir is where the gcc integration files are to be found
+ # for a language, both for internal compiler purposes (compiler
+ # sources implementing front-end to GCC tree converters), and for
+ # build infrastructure purposes (Make-lang.in, etc.)
+ #
+ # This will be <subdir> (relative to $srcdir) if a line like
+ # gcc_subdir="<subdir>" or gcc_subdir=<subdir>
+ # is found in <langdir>/config-lang.in, and will remain <langdir>
+ # otherwise.
+ #
+ # Except for the language alias (fetched above), the regular
+ # "config-lang.in" contents are always retrieved from $gcc_subdir,
+ # so a <langdir>/config-lang.in setting gcc_subdir typically sets
+ # only this and the language alias.
+
+ gcc_subdir=`sed -n -e 's,^gcc_subdir=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^gcc_subdir=\([^ ]*\).*$,\1,p' $lang`
+ if [ "$gcc_subdir" = "" ]; then
+ gcc_subdir="$subdir"
+ fi
+
+ case ",$enable_languages," in
+ *,$lang_alias,*)
+ all_selected_languages="$all_selected_languages $lang_alias"
+ if test -f $srcdir/$gcc_subdir/lang-specs.h; then
+ lang_specs_files="$lang_specs_files $srcdir/$gcc_subdir/lang-specs.h"
+ fi
+ ;;
+ esac
+
+ language=
+ boot_language=
+ compilers=
+ outputs=
+ gtfiles=
+ subdir_requires=
+ . ${srcdir}/$gcc_subdir/config-lang.in
+ if test "x$language" = x
+ then
+ echo "${srcdir}/$gcc_subdir/config-lang.in doesn't set \$language." 1>&2
+ exit 1
+ fi
+
+ ok=:
+ case ",$enable_languages," in
+ *,$lang_alias,*) ;;
+ *)
+ for i in $subdir_requires; do
+ test -f "${srcdir}/$i/config-lang.in" && continue
+ ok=false
+ break
+ done
+ ;;
+ esac
+ $ok || continue
+
+ all_lang_configurefrags="$all_lang_configurefrags \$(srcdir)/$gcc_subdir/config-lang.in"
+ if test "x$language" = xc && test -n "$all_lang_makefrags"; then
+ # Put c/Make-lang.in fragment first to match serialization languages order.
+ all_lang_makefrags="\$(srcdir)/$gcc_subdir/Make-lang.in $all_lang_makefrags"
+ else
+ all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
+ fi
+ if test -f $srcdir/$gcc_subdir/lang.opt; then
+ lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+ all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
+ fi
+ if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
+ lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
+ fi
+ all_languages="$all_languages $language"
+ all_compilers="$all_compilers $compilers"
+ all_outputs="$all_outputs $outputs"
+ all_gtfiles="$all_gtfiles [$subdir] $gtfiles"
+ case ",$enable_languages," in
+ *,lto,*)
+
+$as_echo "#define ENABLE_LTO 1" >>confdefs.h
+
+ enable_lto=yes
+
+ ;;
+ *) ;;
+ esac
+done
+
+check_languages=
+for language in $all_selected_languages
+do
+ check_languages="$check_languages check-$language"
+done
+
+selftest_languages=
+for language in $all_selected_languages
+do
+ selftest_languages="$selftest_languages selftest-$language"
+done
+
+# We link each language in with a set of hooks, reached indirectly via
+# lang.${target}. Only do so for selected languages.
+
+rm -f Make-hooks
+touch Make-hooks
+target_list="all.cross start.encap rest.encap tags \
+ install-common install-man install-info install-dvi install-pdf \
+ install-html dvi pdf html uninstall info man srcextra srcman srcinfo \
+ mostlyclean clean distclean maintainer-clean install-plugin"
+
+for t in $target_list
+do
+ x=
+ for lang in $all_selected_languages
+ do
+ x="$x $lang.$t"
+ done
+ echo "lang.$t: $x" >> Make-hooks
+done
+
+echo "ifeq (\$(DO_LINK_SERIALIZATION),)" >> Make-hooks
+echo "SERIAL_LIST =" >> Make-hooks
+echo else >> Make-hooks
+lang_cnt=0
+lang_list=
+prev=c
+serialization_languages=c
+for lang in $all_selected_languages
+do
+ test $lang = c && continue
+ if test $lang = lto; then
+ serialization_languages="$serialization_languages lto1 lto2"
+ else
+ serialization_languages="$serialization_languages $lang"
+ fi
+done
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ lang_cnt=`expr $lang_cnt + 1`
+ lang_list=" $prev$lang_list"
+ prev=${lang}
+done
+echo "SERIAL_LIST = \$(wordlist \$(DO_LINK_SERIALIZATION),$lang_cnt,$lang_list)" >> Make-hooks
+echo endif >> Make-hooks
+echo "SERIAL_COUNT = `expr $lang_cnt + 1`" >> Make-hooks
+echo "INDEX.c = 0" >> Make-hooks
+lang_idx=1
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ echo "$lang.prev = \$(if \$(word $lang_cnt,\$(SERIAL_LIST)),\$(\$(word $lang_cnt,\$(SERIAL_LIST)).serial))" >> Make-hooks
+ echo "INDEX.$lang = $lang_idx" >> Make-hooks
+ lang_cnt=`expr $lang_cnt - 1`
+ lang_idx=`expr $lang_idx + 1`
+done
+
+# --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+
+
+# --------
+# UNSORTED
+# --------
+
+# Create .gdbinit.
+
+echo "dir ." > .gdbinit
+echo "dir ${srcdir}" >> .gdbinit
+if test x$gdb_needs_out_file_path = xyes
+then
+ echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit
+fi
+if test "x$subdirs" != x; then
+ for s in $subdirs
+ do
+ echo "dir ${srcdir}/$s" >> .gdbinit
+ done
+fi
+echo "source ${srcdir}/gdbinit.in" >> .gdbinit
+echo "python import sys; sys.path.append('${srcdir}'); import gdbhooks" >> .gdbinit
+
+# Put a breakpoint on __asan_report_error to help with debugging buffer
+# overflow.
+case "$CFLAGS" in
+*-fsanitize=address*)
+ echo "source ${srcdir}/gdbasan.in" >> .gdbinit
+ ;;
+esac
+
+gcc_tooldir='$(libsubdir)/$(libsubdir_to_prefix)$(target_noncanonical)'
+
+
+
+# Find a directory in which to install a shared libgcc.
+
+# Check whether --enable-version-specific-runtime-libs was given.
+if test "${enable_version_specific_runtime_libs+set}" = set; then :
+ enableval=$enable_version_specific_runtime_libs;
+fi
+
+
+# Substitute configuration variables
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Echo link setup.
+if test x${build} = x${host} ; then
+ if test x${host} = x${target} ; then
+ echo "Links are now set up to build a native compiler for ${target}." 1>&2
+ else
+ echo "Links are now set up to build a cross-compiler" 1>&2
+ echo " from ${host} to ${target}." 1>&2
+ fi
+else
+ if test x${host} = x${target} ; then
+ echo "Links are now set up to build (on ${build}) a native compiler" 1>&2
+ echo " for ${target}." 1>&2
+ else
+ echo "Links are now set up to build (on ${build}) a cross-compiler" 1>&2
+ echo " from ${host} to ${target}." 1>&2
+ fi
+fi
+
+
+
+
+
+
+if test "x${ISLLIBS}" != "x" ; then
+
+$as_echo "#define HAVE_isl 1" >>confdefs.h
+
+fi
+
+# SDCC GCC_ENABLE_PLUGINS
+
+
+if test x"$enable_plugin" = x"yes"; then
+
+$as_echo "#define ENABLE_PLUGIN 1" >>confdefs.h
+
+fi
+
+
+# Enable --enable-host-shared
+# Check whether --enable-host-shared was given.
+if test "${enable_host_shared+set}" = set; then :
+ enableval=$enable_host_shared; PICFLAG=-fPIC
+else
+ PICFLAG=
+fi
+
+
+
+
+
+# Check whether --enable-libquadmath-support was given.
+if test "${enable_libquadmath_support+set}" = set; then :
+ enableval=$enable_libquadmath_support; ENABLE_LIBQUADMATH_SUPPORT=$enableval
+else
+ ENABLE_LIBQUADMATH_SUPPORT=yes
+fi
+
+if test "${ENABLE_LIBQUADMATH_SUPPORT}" != "no" ; then
+
+$as_echo "#define ENABLE_LIBQUADMATH_SUPPORT 1" >>confdefs.h
+
+fi
+
+
+# Specify what hash style to use by default.
+
+# Check whether --with-linker-hash-style was given.
+if test "${with_linker_hash_style+set}" = set; then :
+ withval=$with_linker_hash_style; case x"$withval" in
+ xsysv)
+ LINKER_HASH_STYLE=sysv
+ ;;
+ xgnu)
+ LINKER_HASH_STYLE=gnu
+ ;;
+ xboth)
+ LINKER_HASH_STYLE=both
+ ;;
+ *)
+ as_fn_error $? "$withval is an invalid option to --with-linker-hash-style" "$LINENO" 5
+ ;;
+ esac
+else
+ LINKER_HASH_STYLE=''
+fi
+
+if test x"${LINKER_HASH_STYLE}" != x; then
+
+cat >>confdefs.h <<_ACEOF
+#define LINKER_HASH_STYLE "$LINKER_HASH_STYLE"
+_ACEOF
+
+fi
+
+# Specify what should be the default of -fdiagnostics-color option.
+
+# Check whether --with-diagnostics-color was given.
+if test "${with_diagnostics_color+set}" = set; then :
+ withval=$with_diagnostics_color; case x"$withval" in
+ xnever)
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_NO
+ ;;
+ xauto)
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_AUTO
+ ;;
+ xauto-if-env)
+ DIAGNOSTICS_COLOR_DEFAULT=-1
+ ;;
+ xalways)
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_YES
+ ;;
+ *)
+ as_fn_error $? "$withval is an invalid option to --with-diagnostics-color" "$LINENO" 5
+ ;;
+ esac
+else
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_AUTO
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define DIAGNOSTICS_COLOR_DEFAULT $DIAGNOSTICS_COLOR_DEFAULT
+_ACEOF
+
+
+# Specify what should be the default of -fdiagnostics-urls option.
+
+# Check whether --with-diagnostics-urls was given.
+if test "${with_diagnostics_urls+set}" = set; then :
+ withval=$with_diagnostics_urls; case x"$withval" in
+ xnever)
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_NO
+ ;;
+ xauto)
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_AUTO
+ ;;
+ xauto-if-env)
+ DIAGNOSTICS_URLS_DEFAULT=-1
+ ;;
+ xalways)
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_YES
+ ;;
+ *)
+ as_fn_error $? "$withval is an invalid option to --with-diagnostics-urls" "$LINENO" 5
+ ;;
+ esac
+else
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_AUTO
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define DIAGNOSTICS_URLS_DEFAULT $DIAGNOSTICS_URLS_DEFAULT
+_ACEOF
+
+
+# Generate gcc-driver-name.h containing GCC_DRIVER_NAME for the benefit
+# of jit/jit-playback.cc.
+gcc_driver_version=`eval "${get_gcc_base_ver} $srcdir/BASE-VER"`
+echo "gcc_driver_version: ${gcc_driver_version}"
+cat > gcc-driver-name.h <<EOF
+#define GCC_DRIVER_NAME "${target_noncanonical}-gcc-${gcc_driver_version}${exeext}"
+EOF
+
+# Check whether --enable-default-pie was given.
+# Check whether --enable-default-pie was given.
+if test "${enable_default_pie+set}" = set; then :
+ enableval=$enable_default_pie; enable_default_pie=$enableval
+else
+ enable_default_pie=no
+fi
+
+if test x$enable_default_pie = xyes ; then
+
+$as_echo "#define ENABLE_DEFAULT_PIE 1" >>confdefs.h
+
+fi
+
+
+# Check if -fno-PIE works.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -fno-PIE option" >&5
+$as_echo_n "checking for -fno-PIE option... " >&6; }
+if ${gcc_cv_c_no_fpie+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ saved_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS -fno-PIE"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) {return 0;}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_c_no_fpie=yes
+else
+ gcc_cv_c_no_fpie=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXXFLAGS="$saved_CXXFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_c_no_fpie" >&5
+$as_echo "$gcc_cv_c_no_fpie" >&6; }
+if test "$gcc_cv_c_no_fpie" = "yes"; then
+ NO_PIE_CFLAGS="-fno-PIE"
+fi
+
+
+# Check if -no-pie works.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for -no-pie option" >&5
+$as_echo_n "checking for -no-pie option... " >&6; }
+if ${gcc_cv_no_pie+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ saved_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -no-pie"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) {return 0;}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ gcc_cv_no_pie=yes
+else
+ gcc_cv_no_pie=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$saved_LDFLAGS"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_no_pie" >&5
+$as_echo "$gcc_cv_no_pie" >&6; }
+if test "$gcc_cv_no_pie" = "yes"; then
+ NO_PIE_FLAG="-no-pie"
+fi
+
+
+# Enable Intel CET on Intel CET enabled host if jit is enabled.
+ # Check whether --enable-cet was given.
+if test "${enable_cet+set}" = set; then :
+ enableval=$enable_cet;
+ case "$enableval" in
+ yes|no|auto) ;;
+ *) as_fn_error $? "Unknown argument to enable/disable cet" "$LINENO" 5 ;;
+ esac
+
+else
+ enable_cet=auto
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for CET support" >&5
+$as_echo_n "checking for CET support... " >&6; }
+
+case "$host" in
+ i[34567]86-*-linux* | x86_64-*-linux*)
+ may_have_cet=yes
+ cet_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fcf-protection"
+ case "$enable_cet" in
+ auto)
+ # Check if target supports multi-byte NOPs
+ # and if compiler and assembler support CET.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+#if !defined(__SSE2__)
+#error target does not support multi-byte NOPs
+#else
+asm ("setssbsy");
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ enable_cet=yes
+else
+ enable_cet=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ yes)
+ # Check if compiler and assembler support CET.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+asm ("setssbsy");
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ support_cet=yes
+else
+ support_cet=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $support_cet = "no"; then
+ if test x$enable_bootstrap != xno \
+ && test -z "${with_build_subdir}" \
+ && (test ! -f ../stage_current \
+ || test `cat ../stage_current` != "stage1"); then
+ # Require CET support only for the final GCC build.
+ as_fn_error $? "compiler and assembler with CET support are required for --enable-cet" "$LINENO" 5
+ else
+ # Don't enable CET without CET support for non-bootstrap
+ # build, in stage1 nor for build support.
+ enable_cet=no
+ fi
+ fi
+ ;;
+ esac
+ CFLAGS="$cet_save_CFLAGS"
+ ;;
+ *)
+ may_have_cet=no
+ enable_cet=no
+ ;;
+esac
+
+cet_save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fcf-protection=none"
+cet_save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$LDFLAGS -Wl,-z,ibt,-z,shstk"
+if test x$may_have_cet = xyes; then
+ # Check whether -fcf-protection=none -Wl,-z,ibt,-z,shstk work.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ may_have_cet=yes
+else
+ may_have_cet=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+
+if test x$may_have_cet = xyes; then
+ if test x$cross_compiling = xno; then
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+ asm ("endbr32");
+ return 0;
+}
+
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ have_multi_byte_nop=yes
+else
+ have_multi_byte_nop=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ have_cet=no
+ if test x$have_multi_byte_nop = xyes; then
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run test program while cross compiling
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+static void
+foo (void)
+{
+}
+
+static void
+__attribute__ ((noinline, noclone))
+xxx (void (*f) (void))
+{
+ f ();
+}
+
+static void
+__attribute__ ((noinline, noclone))
+bar (void)
+{
+ xxx (foo);
+}
+
+int
+main ()
+{
+ bar ();
+ return 0;
+}
+
+_ACEOF
+if ac_fn_cxx_try_run "$LINENO"; then :
+ have_cet=no
+else
+ have_cet=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+ if test x$enable_cet = xno -a x$have_cet = xyes; then
+ as_fn_error $? "Intel CET must be enabled on Intel CET enabled host" "$LINENO" 5
+ fi
+ fi
+else
+ # Enable CET in cross compiler if possible so that it will run on both
+ # CET and non-CET hosts.
+ have_cet=yes
+fi
+if test x$enable_cet = xyes; then
+ CET_HOST_FLAGS="-fcf-protection"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+CFLAGS="$cet_save_CFLAGS"
+LDFLAGS="$cet_save_LDFLAGS"
+
+case x$enable_languages in
+*jit*)
+ ;;
+*)
+ CET_HOST_FLAGS=
+ ;;
+esac
+
+
+# Check linker supports '-z bndplt'
+ld_bndplt_support=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker -z bndplt option" >&5
+$as_echo_n "checking linker -z bndplt option... " >&6; }
+if test x"$ld_is_gold" = xno; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
+ ld_bndplt_support=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -a bndplt option
+ if $gcc_cv_ld --help 2>&1 | grep -- '-z bndplt' > /dev/null; then
+ ld_bndplt_support=yes
+ fi
+ fi
+fi
+if test x"$ld_bndplt_support" = xyes; then
+
+$as_echo "#define HAVE_LD_BNDPLT_SUPPORT 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_bndplt_support" >&5
+$as_echo "$ld_bndplt_support" >&6; }
+
+# Check linker supports '--push-state'/'--pop-state'
+ld_pushpopstate_support=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker --push-state/--pop-state options" >&5
+$as_echo_n "checking linker --push-state/--pop-state options... " >&6; }
+if test x"$ld_is_gold" = xno; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
+ ld_pushpopstate_support=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ # Check if linker supports --push-state/--pop-state options
+ if $gcc_cv_ld --help 2>&1 | grep -- '--push-state' > /dev/null; then
+ ld_pushpopstate_support=yes
+ fi
+ fi
+fi
+if test x"$ld_pushpopstate_support" = xyes; then
+
+$as_echo "#define HAVE_LD_PUSHPOPSTATE_SUPPORT 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_pushpopstate_support" >&5
+$as_echo "$ld_pushpopstate_support" >&6; }
+
+# On s390, float_t has historically been statically defined as double for no
+# good reason. To comply with the C standard in the light of this definition,
+# gcc has evaluated float expressions in double precision when in
+# standards-compatible mode or when given -fexcess-precision=standard. To enable
+# a smooth transition towards the new model used by most architectures, where
+# gcc describes its behavior via the macro __FLT_EVAL_METHOD__ and glibc derives
+# float_t from that, this behavior can be configured with
+# --enable-s390-excess-float-precision. When given as enabled, that flag selects
+# the old model. When omitted, native builds and cross compiles that have target
+# libc headers will detect whether libc clamps float_t to double and in that
+# case maintain the old model. Otherwise, they will default to the new model.
+# Check whether --enable-s390-excess-float-precision was given.
+if test "${enable_s390_excess_float_precision+set}" = set; then :
+ enableval=$enable_s390_excess_float_precision;
+else
+ enable_s390_excess_float_precision=auto
+fi
+
+
+case $target in
+ s390*-linux*)
+ if test x"$enable_s390_excess_float_precision" = xauto; then
+ # Can we autodetect the behavior of the target libc?
+ if test "$target" = "$host" -a "$host" = "$build"; then
+ enable_s390_excess_float_precision=autodetect
+ elif test "x$with_headers" != xno; then
+ # cross build. are target headers available?
+ # carefully coerce the build-system compiler to use target headers
+ saved_CXXFLAGS="$CXXFLAGS"
+ fixed_XGCC_FLAGS_FOR_TARGET=`echo "$XGCC_FLAGS_FOR_TARGET" | sed 's/-B/-idirafter/g'`
+ CROSS_TEST_CXXFLAGS="-nostdinc $fixed_XGCC_FLAGS_FOR_TARGET"
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <math.h>
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ enable_s390_excess_float_precision=autodetect
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXXFLAGS="$saved_CXXFLAGS"
+ fi
+
+ if test x"$enable_s390_excess_float_precision" = xautodetect; then
+ saved_CXXFLAGS="$CXXFLAGS"
+ if ! test "$target" = "$host" -a "$host" = "$build"; then
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ unset CROSS_TEST_CXXFLAGS
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glibc clamping float_t to double" >&5
+$as_echo_n "checking for glibc clamping float_t to double... " >&6; }
+if ${gcc_cv_float_t_clamped_to_double+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define __FLT_EVAL_METHOD__ 0
+#include <math.h>
+int dummy[sizeof(float_t) == sizeof(double) ? 1 : -1];
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gcc_cv_float_t_clamped_to_double=yes
+else
+ gcc_cv_float_t_clamped_to_double=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_float_t_clamped_to_double" >&5
+$as_echo "$gcc_cv_float_t_clamped_to_double" >&6; }
+ CXXFLAGS="$saved_CXXFLAGS"
+ enable_s390_excess_float_precision="$gcc_cv_float_t_clamped_to_double"
+ else
+ # no way to detect behavior of target libc, default to new model
+ enable_s390_excess_float_precision=no
+ fi
+ fi
+
+
+ if test x"$enable_s390_excess_float_precision" = xyes; then
+
+$as_echo "#define ENABLE_S390_EXCESS_FLOAT_PRECISION 1" >>confdefs.h
+
+ fi
+ ;;
+esac
+
+# Configure the subdirectories
+# AC_CONFIG_SUBDIRS($subdirs)
+
+# Create the Makefile
+# and configure language subdirectories
+ac_config_files="$ac_config_files $all_outputs"
+
+
+ac_config_commands="$ac_config_commands default"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_links="$ac_config_links"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration links:
+$config_links
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR
+subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR
+subdirs='$subdirs'
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "auto-host.h") CONFIG_HEADERS="$CONFIG_HEADERS auto-host.h:config.in" ;;
+ "depdir") CONFIG_COMMANDS="$CONFIG_COMMANDS depdir" ;;
+ "gccdepdir") CONFIG_COMMANDS="$CONFIG_COMMANDS gccdepdir" ;;
+ "as") CONFIG_FILES="$CONFIG_FILES as:exec-tool.in" ;;
+ "collect-ld") CONFIG_FILES="$CONFIG_FILES collect-ld:exec-tool.in" ;;
+ "nm") CONFIG_FILES="$CONFIG_FILES nm:exec-tool.in" ;;
+ "dsymutil") CONFIG_FILES="$CONFIG_FILES dsymutil:exec-tool.in" ;;
+ "clearcap.map") CONFIG_LINKS="$CONFIG_LINKS clearcap.map:${srcdir}/config/$clearcap_map" ;;
+ "$all_outputs") CONFIG_FILES="$CONFIG_FILES $all_outputs" ;;
+ "default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_LINKS+set}" = set || CONFIG_LINKS=$config_links
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+if $AWK 'BEGIN { getline <"/dev/null" }' </dev/null 2>/dev/null; then
+ ac_cs_awk_getline=:
+ ac_cs_awk_pipe_init=
+ ac_cs_awk_read_file='
+ while ((getline aline < (F[key])) > 0)
+ print(aline)
+ close(F[key])'
+ ac_cs_awk_pipe_fini=
+else
+ ac_cs_awk_getline=false
+ ac_cs_awk_pipe_init="print \"cat <<'|#_!!_#|' &&\""
+ ac_cs_awk_read_file='
+ print "|#_!!_#|"
+ print "cat " F[key] " &&"
+ '$ac_cs_awk_pipe_init
+ # The final `:' finishes the AND list.
+ ac_cs_awk_pipe_fini='END { print "|#_!!_#|"; print ":" }'
+fi
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+# Create commands to substitute file output variables.
+{
+ echo "cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1" &&
+ echo 'cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&' &&
+ echo "$ac_subst_files" | sed 's/.*/F["&"]="$&"/' &&
+ echo "_ACAWK" &&
+ echo "_ACEOF"
+} >conf$$files.sh &&
+. ./conf$$files.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+rm -f conf$$files.sh
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+ \$ac_cs_awk_pipe_init
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+ if (nfields == 3 && !substed) {
+ key = field[2]
+ if (F[key] != "" && line ~ /^[ ]*@.*@[ ]*$/) {
+ \$ac_cs_awk_read_file
+ next
+ }
+ }
+ print line
+}
+\$ac_cs_awk_pipe_fini
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :L $CONFIG_LINKS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" |
+if $ac_cs_awk_getline; then
+ $AWK -f "$ac_tmp/subs.awk"
+else
+ $AWK -f "$ac_tmp/subs.awk" | $SHELL
+fi \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+ :L)
+ #
+ # CONFIG_LINK
+ #
+
+ if test "$ac_source" = "$ac_file" && test "$srcdir" = '.'; then
+ :
+ else
+ # Prefer the file from the source tree if names are identical.
+ if test "$ac_source" = "$ac_file" || test ! -r "$ac_source"; then
+ ac_source=$srcdir/$ac_source
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: linking $ac_source to $ac_file" >&5
+$as_echo "$as_me: linking $ac_source to $ac_file" >&6;}
+
+ if test ! -r "$ac_source"; then
+ as_fn_error $? "$ac_source: file not found" "$LINENO" 5
+ fi
+ rm -f "$ac_file"
+
+ # Try a relative symlink, then a hard link, then a copy.
+ case $ac_source in
+ [\\/$]* | ?:[\\/]* ) ac_rel_source=$ac_source ;;
+ *) ac_rel_source=$ac_top_build_prefix$ac_source ;;
+ esac
+ ln -s "$ac_rel_source" "$ac_file" 2>/dev/null ||
+ ln "$ac_source" "$ac_file" 2>/dev/null ||
+ cp -p "$ac_source" "$ac_file" ||
+ as_fn_error $? "cannot link or copy $ac_source to $ac_file" "$LINENO" 5
+ fi
+ ;;
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depdir":C) $SHELL $ac_aux_dir/mkinstalldirs $DEPDIR ;;
+ "gccdepdir":C)
+ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
+ for lang in $subdirs c-family common analyzer rtl-ssa
+ do
+ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
+ done ;;
+ "as":F) chmod +x as ;;
+ "collect-ld":F) chmod +x collect-ld ;;
+ "nm":F) chmod +x nm ;;
+ "dsymutil":F) chmod +x dsymutil ;;
+ "default":C)
+case ${CONFIG_HEADERS} in
+ *auto-host.h:config.in*)
+ echo > cstamp-h ;;
+esac
+# Make sure all the subdirs exist.
+for d in $subdirs doc build common c-family
+do
+ test -d $d || mkdir $d
+done
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
diff --git a/support/cpp/gcc/configure.ac b/support/cpp/gcc/configure.ac
new file mode 100644
index 000000000..7bb178000
--- /dev/null
+++ b/support/cpp/gcc/configure.ac
@@ -0,0 +1,7821 @@
+# configure.ac for GCC
+# Process this file with autoconf to generate a configuration script.
+
+# Copyright (C) 1997-2022 Free Software Foundation, Inc.
+
+#This file is part of GCC.
+#was: gcc/configure.ac
+
+#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/>.
+
+# --------------------------------
+# Initialization and sanity checks
+# --------------------------------
+
+AC_INIT
+AC_CONFIG_SRCDIR(gcc.cc)
+AC_CONFIG_HEADER(auto-host.h:config.in)
+
+gcc_version=`cat $srcdir/BASE-VER`
+
+# Determine the host, build, and target systems
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+# Determine the noncanonical host name, for Ada.
+ACX_NONCANONICAL_HOST
+
+# Determine the noncanonical target name, for directory use.
+ACX_NONCANONICAL_TARGET
+
+# Used for constructing correct paths for offload compilers.
+real_target_noncanonical=${target_noncanonical}
+accel_dir_suffix=
+
+# Determine the target- and build-specific subdirectories
+GCC_TOPLEV_SUBDIRS
+
+# Set program_transform_name
+AC_ARG_PROGRAM
+
+# Check for bogus environment variables.
+# Test if LIBRARY_PATH contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# LIBRARY_PATH contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+AC_MSG_CHECKING(LIBRARY_PATH variable)
+changequote(,)dnl
+case ${LIBRARY_PATH} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ library_path_setting="contains current directory"
+ ;;
+ *)
+ library_path_setting="ok"
+ ;;
+esac
+changequote([,])dnl
+AC_MSG_RESULT($library_path_setting)
+if test "$library_path_setting" != "ok"; then
+AC_MSG_ERROR([
+*** LIBRARY_PATH shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again.])
+fi
+
+# Test if GCC_EXEC_PREFIX contains the notation for the current directory
+# since this would lead to problems installing/building glibc.
+# GCC_EXEC_PREFIX contains the current directory if one of the following
+# is true:
+# - one of the terminals (":" and ";") is the first or last sign
+# - two terminals occur directly after each other
+# - the path contains an element with a dot in it
+AC_MSG_CHECKING(GCC_EXEC_PREFIX variable)
+changequote(,)dnl
+case ${GCC_EXEC_PREFIX} in
+ [:\;]* | *[:\;] | *[:\;][:\;]* | *[:\;]. | .[:\;]*| . | *[:\;].[:\;]* )
+ gcc_exec_prefix_setting="contains current directory"
+ ;;
+ *)
+ gcc_exec_prefix_setting="ok"
+ ;;
+esac
+changequote([,])dnl
+AC_MSG_RESULT($gcc_exec_prefix_setting)
+if test "$gcc_exec_prefix_setting" != "ok"; then
+AC_MSG_ERROR([
+*** GCC_EXEC_PREFIX shouldn't contain the current directory when
+*** building gcc. Please change the environment variable
+*** and run configure again.])
+fi
+
+# -----------
+# Directories
+# -----------
+
+# Specify the local prefix
+local_prefix=
+AC_ARG_WITH(local-prefix,
+[AS_HELP_STRING([--with-local-prefix=DIR],
+ [specifies directory to put local include])],
+[case "${withval}" in
+yes) AC_MSG_ERROR(bad value ${withval} given for local include directory prefix) ;;
+no) ;;
+*) local_prefix=$with_local_prefix ;;
+esac])
+
+# Default local prefix if it is empty
+if test x$local_prefix = x; then
+ local_prefix=/usr/local
+fi
+
+AC_ARG_WITH([native-system-header-dir],
+ [ --with-native-system-header-dir=dir
+ use dir as the directory to look for standard
+ system header files in. Defaults to /usr/include.],
+[
+ case ${with_native_system_header_dir} in
+ yes|no) AC_MSG_ERROR([bad value ${withval} given for --with-native-system-header-dir]) ;;
+ /* | [[A-Za-z]]:[[\\/]]*) ;;
+ *) AC_MSG_ERROR([--with-native-system-header-dir argument ${withval} must be an absolute directory]) ;;
+ esac
+ configured_native_system_header_dir="${withval}"
+], [configured_native_system_header_dir=])
+
+AC_ARG_WITH(build-sysroot,
+ [AS_HELP_STRING([--with-build-sysroot=sysroot],
+ [use sysroot as the system root during the build])],
+ [if test x"$withval" != x ; then
+ SYSROOT_CFLAGS_FOR_TARGET="--sysroot=$withval"
+ fi],
+ [SYSROOT_CFLAGS_FOR_TARGET=])
+AC_SUBST(SYSROOT_CFLAGS_FOR_TARGET)
+
+if test "x$prefix" = xNONE; then
+ test_prefix=/usr/local
+else
+ test_prefix=$prefix
+fi
+if test "x$exec_prefix" = xNONE; then
+ test_exec_prefix=$test_prefix
+else
+ test_exec_prefix=$exec_prefix
+fi
+
+AC_ARG_WITH(sysroot,
+[AS_HELP_STRING([[--with-sysroot[=DIR]]],
+ [search for usr/lib, usr/include, et al, within DIR])],
+[
+ case ${with_sysroot} in
+ /) ;;
+ */) with_sysroot=`echo $with_sysroot | sed 's,/$,,'` ;;
+ esac
+ case ${with_sysroot} in
+ yes) TARGET_SYSTEM_ROOT='${exec_prefix}/${target_noncanonical}/sys-root' ;;
+ *) TARGET_SYSTEM_ROOT=$with_sysroot ;;
+ esac
+
+ TARGET_SYSTEM_ROOT_DEFINE='-DTARGET_SYSTEM_ROOT=\"$(TARGET_SYSTEM_ROOT)\"'
+ CROSS_SYSTEM_HEADER_DIR='$(TARGET_SYSTEM_ROOT)$${sysroot_headers_suffix}$(NATIVE_SYSTEM_HEADER_DIR)'
+
+ case ${TARGET_SYSTEM_ROOT} in
+ "${test_prefix}"|"${test_prefix}/"*|\
+ "${test_exec_prefix}"|"${test_exec_prefix}/"*|\
+ '${prefix}'|'${prefix}/'*|\
+ '${exec_prefix}'|'${exec_prefix}/'*)
+ t="$TARGET_SYSTEM_ROOT_DEFINE -DTARGET_SYSTEM_ROOT_RELOCATABLE"
+ TARGET_SYSTEM_ROOT_DEFINE="$t"
+ ;;
+ esac
+], [
+ TARGET_SYSTEM_ROOT=
+ TARGET_SYSTEM_ROOT_DEFINE=
+ CROSS_SYSTEM_HEADER_DIR='$(gcc_tooldir)/sys-include'
+])
+AC_SUBST(TARGET_SYSTEM_ROOT)
+AC_SUBST(TARGET_SYSTEM_ROOT_DEFINE)
+AC_SUBST(CROSS_SYSTEM_HEADER_DIR)
+
+# Don't set gcc_gxx_include_dir to gxx_include_dir since that's only
+# passed in by the toplevel make and thus we'd get different behavior
+# depending on where we built the sources.
+gcc_gxx_include_dir=
+# Specify the g++ header file directory
+AC_ARG_WITH(gxx-include-dir,
+[AS_HELP_STRING([--with-gxx-include-dir=DIR],
+ [specifies directory to put g++ header files])],
+[case "${withval}" in
+yes) AC_MSG_ERROR(bad value ${withval} given for g++ include directory) ;;
+no) ;;
+*) gcc_gxx_include_dir=$with_gxx_include_dir ;;
+esac])
+
+# If both --with-sysroot and --with-gxx-include-dir are passed, we interpolate
+# the former in the latter and, upon success, compute gcc_gxx_include_dir as
+# relative to the sysroot.
+gcc_gxx_include_dir_add_sysroot=0
+
+# This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_include_dir} = x; then
+ if test x${enable_version_specific_runtime_libs} = xyes; then
+ gcc_gxx_include_dir='${libsubdir}/include/c++'
+ else
+ libstdcxx_incdir='include/c++/$(version)'
+ if test x$host != x$target; then
+ libstdcxx_incdir="$target_alias/$libstdcxx_incdir"
+ fi
+ gcc_gxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libstdcxx_incdir"
+ fi
+elif test "${with_sysroot+set}" = set; then
+ gcc_gxx_without_sysroot=`expr "${gcc_gxx_include_dir}" : "${with_sysroot}"'\(.*\)'`
+ if test "${gcc_gxx_without_sysroot}"; then
+ gcc_gxx_include_dir="${gcc_gxx_without_sysroot}"
+ gcc_gxx_include_dir_add_sysroot=1
+ fi
+fi
+
+# Configuration for an alternate set of C++ headers.
+gcc_gxx_libcxx_include_dir=
+# Specify the alternate g++ header file directory
+AC_ARG_WITH(gxx-libcxx-include-dir,
+[AS_HELP_STRING([--with-gxx-libcxx-include-dir=DIR],
+ [specifies directory to find libc++ header files])],
+[case "${withval}" in
+yes) AC_MSG_ERROR(bad value ${withval} given for libc++ include directory) ;;
+no) ;;
+*) gcc_gxx_libcxx_include_dir=$with_gxx_libcxx_include_dir ;;
+esac])
+
+# If both --with-sysroot and --with-gxx-libcxx-include-dir are passed, we
+# check to see if the latter starts with the former and, upon success, compute
+# gcc_gxx_libcxx_include_dir as relative to the sysroot.
+gcc_gxx_libcxx_include_dir_add_sysroot=0
+
+if test x${gcc_gxx_libcxx_include_dir} != x; then
+ AC_DEFINE(ENABLE_STDLIB_OPTION, 1,
+ [Define if the -stdlib= option should be enabled.])
+else
+ AC_DEFINE(ENABLE_STDLIB_OPTION, 0)
+fi
+# ??? This logic must match libstdc++-v3/acinclude.m4:GLIBCXX_EXPORT_INSTALL_INFO.
+if test x${gcc_gxx_libcxx_include_dir} = x; then
+ if test x${enable_version_specific_runtime_libs} = xyes; then
+ gcc_gxx_libcxx_include_dir='${libsubdir}/libc++_include/c++/v1'
+ else
+ libcxx_incdir='libc++_include/c++/$(version)/v1'
+ if test x$host != x$target; then
+ libcxx_incdir="$target_alias/$libcxx_incdir"
+ fi
+ gcc_gxx_libcxx_include_dir="\$(libsubdir)/\$(libsubdir_to_prefix)$libcxx_incdir"
+ fi
+elif test "${with_sysroot+set}" = set; then
+ gcc_gxx_libcxx_without_sysroot=`expr "${gcc_gxx_libcxx_include_dir}" : "${with_sysroot}"'\(.*\)'`
+ if test "${gcc_gxx_libcxx_without_sysroot}"; then
+ gcc_gxx_libcxx_include_dir="${gcc_gxx_libcxx_without_sysroot}"
+ gcc_gxx_libcxx_include_dir_add_sysroot=1
+ fi
+fi
+
+AC_ARG_WITH(cpp_install_dir,
+[AC_HELP_STRING([--with-cpp-install-dir=DIR],
+ [install the user visible C preprocessor in DIR
+ (relative to PREFIX) as well as PREFIX/bin])],
+[if test x$withval = xyes; then
+ AC_MSG_ERROR([option --with-cpp-install-dir requires an argument])
+elif test x$withval != xno; then
+ cpp_install_dir=$withval
+fi])
+
+# We would like to our source tree to be readonly. However when releases or
+# pre-releases are generated, the flex/bison generated files as well as the
+# various formats of manuals need to be included along with the rest of the
+# sources. Therefore we have --enable-generated-files-in-srcdir to do
+# just that.
+
+AC_MSG_CHECKING([whether to place generated files in the source directory])
+ dnl generated-files-in-srcdir is disabled by default
+ AC_ARG_ENABLE(generated-files-in-srcdir,
+ [AS_HELP_STRING([--enable-generated-files-in-srcdir],
+ [put copies of generated files in source dir
+ intended for creating source tarballs for users
+ without texinfo bison or flex])],
+ generated_files_in_srcdir=$enableval,
+ generated_files_in_srcdir=no)
+
+AC_MSG_RESULT($generated_files_in_srcdir)
+
+if test "$generated_files_in_srcdir" = "yes"; then
+ GENINSRC=''
+else
+ GENINSRC='#'
+fi
+AC_SUBST(GENINSRC)
+
+# -------------------
+# Find default linker
+# -------------------
+
+# With GNU ld
+AC_ARG_WITH(gnu-ld,
+[AS_HELP_STRING([--with-gnu-ld], [arrange to work with GNU ld])],
+gnu_ld_flag="$with_gnu_ld",
+gnu_ld_flag=no)
+
+case $target in
+ *darwin*)
+ ld64_flag=yes # Darwin can only use a ld64-compatible linker.
+ dsymutil_flag=yes # Darwin uses dsymutil to link debug.
+ ;;
+ *)
+ ld64_flag=no
+ dsymutil_flag=no
+ ;;
+esac
+
+# With pre-defined ld
+AC_ARG_WITH(ld,
+[AS_HELP_STRING([--with-ld], [arrange to use the specified ld (full pathname)])],
+DEFAULT_LINKER="$with_ld")
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_LINKER"; then
+ AC_MSG_ERROR([cannot execute: $DEFAULT_LINKER: check --with-ld or env. var. DEFAULT_LINKER])
+ elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gnu_ld_flag=yes
+ elif $DEFAULT_LINKER -v < /dev/null 2>&1 | grep ld64- > /dev/null; then
+ ld64_flag=yes
+ fi
+ AC_DEFINE_UNQUOTED(DEFAULT_LINKER,"$DEFAULT_LINKER",
+ [Define to enable the use of a default linker.])
+fi
+
+AC_MSG_CHECKING([whether a default linker was specified])
+if test x"${DEFAULT_LINKER+set}" = x"set"; then
+ if test x"$gnu_ld_flag" = x"no"; then
+ AC_MSG_RESULT([yes ($DEFAULT_LINKER)])
+ else
+ AC_MSG_RESULT([yes ($DEFAULT_LINKER - GNU ld)])
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+
+# With demangler in GNU ld
+AC_ARG_WITH(demangler-in-ld,
+[AS_HELP_STRING([--with-demangler-in-ld], [try to use demangler in GNU ld])],
+demangler_in_ld="$with_demangler_in_ld",
+demangler_in_ld=yes)
+
+# Allow the user to specify a dsymutil executable (used on Darwin only, so far)
+AC_ARG_WITH(dsymutil,
+[AS_HELP_STRING([--with-dsymutil], [arrange to use the specified dsymutil (full pathname)])],
+DEFAULT_DSYMUTIL="$with_dsymutil")
+
+dsymutil_vers=
+if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then
+ if test ! -x "$DEFAULT_DSYMUTIL"; then
+ AC_MSG_ERROR([cannot execute: $DEFAULT_DSYMUTIL: check --with-dsymutil or env. var. DEFAULT_DSYMUTIL])
+ else
+ if dsymutil_vers=`$DEFAULT_DSYMUTIL -v /dev/null 2>&1`; then
+ dsymutil_flag=yes
+ fi
+ fi
+ AC_DEFINE_UNQUOTED(DEFAULT_DSYMUTIL,"$DEFAULT_DSYMUTIL",
+ [Define to enable the use of a default debug linker.])
+fi
+
+AC_MSG_CHECKING([whether a default dsymutil was specified])
+if test x"${DEFAULT_DSYMUTIL+set}" = x"set"; then
+ AC_MSG_RESULT([yes ($DEFAULT_DSYMUTIL)])
+else
+ AC_MSG_RESULT(no)
+fi
+
+# ----------------------
+# Find default assembler
+# ----------------------
+
+# With GNU as
+AC_ARG_WITH(gnu-as,
+[AS_HELP_STRING([--with-gnu-as], [arrange to work with GNU as])],
+gas_flag="$with_gnu_as",
+gas_flag=no)
+
+AC_ARG_WITH(as,
+[AS_HELP_STRING([--with-as], [arrange to use the specified as (full pathname)])],
+DEFAULT_ASSEMBLER="$with_as")
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test ! -x "$DEFAULT_ASSEMBLER"; then
+ AC_MSG_ERROR([cannot execute: $DEFAULT_ASSEMBLER: check --with-as or env. var. DEFAULT_ASSEMBLER])
+ elif $DEFAULT_ASSEMBLER -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ gas_flag=yes
+ fi
+ AC_DEFINE_UNQUOTED(DEFAULT_ASSEMBLER,"$DEFAULT_ASSEMBLER",
+ [Define to enable the use of a default assembler.])
+fi
+
+AC_MSG_CHECKING([whether a default assembler was specified])
+if test x"${DEFAULT_ASSEMBLER+set}" = x"set"; then
+ if test x"$gas_flag" = x"no"; then
+ AC_MSG_RESULT([yes ($DEFAULT_ASSEMBLER)])
+ else
+ AC_MSG_RESULT([yes ($DEFAULT_ASSEMBLER - GNU as)])
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
+
+# ---------------
+# Find C compiler
+# ---------------
+
+# If a non-executable a.out is present (e.g. created by GNU as above even if
+# invoked with -v only), the IRIX 6 native ld just overwrites the existing
+# file, even when creating an executable, so an execution test fails.
+# Remove possible default executable files to avoid this.
+#
+# FIXME: This really belongs into AC_PROG_CC and can be removed once
+# Autoconf includes it.
+rm -f a.out a.exe b.out
+
+# Find the native compiler
+AC_PROG_CC
+AC_PROG_CXX
+# ACX_PROG_GNAT([-I"$srcdir"/ada/libgnat])
+# ACX_PROG_GDC([-I"$srcdir"/d])
+
+# Do configure tests with the C++ compiler, since that's what we build with.
+AC_LANG(C++)
+
+# Remove the -O2: for historical reasons, unless bootstrapping we prefer
+# optimizations to be activated explicitly by the toplevel.
+case "$CC" in
+ */prev-gcc/xgcc*) ;;
+ *) CFLAGS=`echo "$CFLAGS " | sed -e "s/-Ofast[[ ]]//" -e "s/-O[[gs]][[ ]]//" -e "s/-O[[0-9]]*[[ ]]//" `
+ CXXFLAGS=`echo "$CXXFLAGS " | sed -e "s/-Ofast[[ ]]//" -e "s/-O[[gs]][[ ]]//" -e "s/-O[[0-9]]*[[ ]]//" ` ;;
+esac
+AC_SUBST(CFLAGS)
+AC_SUBST(CXXFLAGS)
+AC_SUBST(GDCFLAGS)
+
+# Determine PICFLAG for target gnatlib.
+GCC_PICFLAG_FOR_TARGET
+AC_SUBST(PICFLAG_FOR_TARGET)
+
+# -------------------------
+# Check C compiler features
+# -------------------------
+
+AC_USE_SYSTEM_EXTENSIONS
+
+AC_PROG_CPP
+AC_C_INLINE
+
+AC_SYS_LARGEFILE
+AC_CHECK_SIZEOF(ino_t)
+AC_CHECK_SIZEOF(dev_t)
+
+# Select the right stat being able to handle 64bit inodes, if needed.
+if test "$enable_largefile" != no; then
+ case "$host, $build" in
+ *-*-aix*,*|*,*-*-aix*)
+ if test "$ac_cv_sizeof_ino_t" == "4" -a "$ac_cv_sizeof_dev_t" == 4; then
+ AC_DEFINE(HOST_STAT_FOR_64BIT_INODES, stat64x,
+ [Define which stat syscall is able to handle 64bit indodes.])
+ fi;;
+ esac
+fi
+
+
+# sizeof(char) is 1 by definition.
+AC_CHECK_SIZEOF(void *)
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_TYPES([long long], [AC_CHECK_SIZEOF(long long)])
+GCC_STDINT_TYPES
+if test x"$ac_cv_c_uint64_t" = x"no" -o x"$ac_cv_c_int64_t" = x"no"; then
+ AC_MSG_ERROR([uint64_t or int64_t not found])
+fi
+
+# check what underlying integer type int64_t uses
+AC_CACHE_CHECK(for int64_t underlying type, ac_cv_int64_t_type, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+template <typename T> struct X { };
+template <>
+struct X<long> { typedef long t; };
+]], [[X<int64_t>::t x;]])],[ac_cv_int64_t_type=long],[ac_cv_int64_t_type="long long"])])
+if test "$ac_cv_int64_t_type" = "long"; then
+ AC_DEFINE(INT64_T_IS_LONG, 1,
+ [Define if int64_t uses long as underlying type.])
+else
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+template <typename T> struct X { };
+template <>
+struct X<long long> { typedef long long t; };
+]], [[X<int64_t>::t x;]])],[],[AC_MSG_ERROR([error verifying int64_t uses long long])])
+fi
+
+AC_CACHE_CHECK(for std::swap in <utility>, ac_cv_std_swap_in_utility, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <utility>
+]], [[int a, b; std::swap(a,b);]])],[ac_cv_std_swap_in_utility=yes],[ac_cv_std_swap_in_utility=no])])
+if test $ac_cv_std_swap_in_utility = yes; then
+ AC_DEFINE(HAVE_SWAP_IN_UTILITY, 1,
+ [Define if <utility> defines std::swap.])
+fi
+
+# Check whether compiler is affected by placement new aliasing bug (PR 29286).
+# If the host compiler is affected by the bug, and we build with optimization
+# enabled (which happens e.g. when cross-compiling), the pool allocator may
+# get miscompiled. Use -fno-strict-aliasing to work around this problem.
+# Since there is no reliable feature check for the presence of this bug,
+# we simply use a GCC version number check. (This should never trigger for
+# stages 2 or 3 of a native bootstrap.)
+aliasing_flags=
+if test "$GCC" = yes; then
+ saved_CXXFLAGS="$CXXFLAGS"
+
+ # The following test compilation will succeed if and only if $CXX accepts
+ # -fno-strict-aliasing *and* is older than GCC 4.3.
+ CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
+ AC_MSG_CHECKING([whether $CXX is affected by placement new aliasing bug])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
+#error compiler not affected by placement new aliasing bug
+#endif
+])],
+ [AC_MSG_RESULT([yes]); aliasing_flags='-fno-strict-aliasing'],
+ [AC_MSG_RESULT([no])])
+
+ CXXFLAGS="$saved_CXXFLAGS"
+fi
+AC_SUBST(aliasing_flags)
+
+
+
+# ---------------------
+# Warnings and checking
+# ---------------------
+
+# Check $CC warning features (if it's GCC).
+# We want to use -pedantic, but we don't want warnings about
+# * 'long long'
+# * variadic macros
+# * overlong strings
+# * C++11 narrowing conversions in { }
+# So, we only use -pedantic if we can disable those warnings.
+
+# In stage 1, disable -Wformat warnings from old GCCs about new % codes
+AC_ARG_ENABLE(build-format-warnings,
+ AS_HELP_STRING([--disable-build-format-warnings],[don't use -Wformat while building GCC]),
+ [],[enable_build_format_warnings=yes])
+AS_IF([test $enable_build_format_warnings = no],
+ [wf_opt=-Wno-format],[wf_opt=])
+ACX_PROG_CXX_WARNING_OPTS(
+ m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings ],
+ [-Wcast-qual $wf_opt])),
+ [loose_warn])
+ACX_PROG_CC_WARNING_OPTS(
+ m4_quote(m4_do([-Wstrict-prototypes -Wmissing-prototypes ],
+ [])), [c_loose_warn])
+ACX_PROG_CXX_WARNING_OPTS(
+ m4_quote(m4_do([-Wmissing-format-attribute ],
+ [-Woverloaded-virtual])), [strict_warn])
+ACX_PROG_CC_WARNING_OPTS(
+ m4_quote(m4_do([-Wold-style-definition -Wc++-compat])), [c_strict_warn])
+ACX_PROG_CXX_WARNING_ALMOST_PEDANTIC(
+ m4_quote(m4_do([-Wno-long-long -Wno-variadic-macros ],
+ [-Wno-overlength-strings])), [strict_warn])
+ACX_PROG_CXX_WARNINGS_ARE_ERRORS([manual], [strict_warn])
+
+# The above macros do nothing if the compiler is not GCC. However, the
+# Makefile has more goo to add other flags, so these variables are used
+# to enable warnings only for GCC.
+warn_cflags=
+warn_cxxflags=
+if test "x$GCC" = "xyes"; then
+ warn_cflags='$(GCC_WARN_CFLAGS)'
+ warn_cxxflags='$(GCC_WARN_CXXFLAGS)'
+fi
+AC_SUBST(warn_cflags)
+AC_SUBST(warn_cxxflags)
+
+# Disable exceptions and RTTI if building with g++
+ACX_PROG_CC_WARNING_OPTS(
+ m4_quote(m4_do([-fno-exceptions -fno-rtti -fasynchronous-unwind-tables])),
+ [noexception_flags])
+
+# Enable expensive internal checks
+is_release=
+if test x"`cat $srcdir/DEV-PHASE`" != xexperimental; then
+ is_release=yes
+fi
+
+AC_ARG_ENABLE(checking,
+[AS_HELP_STRING([[--enable-checking[=LIST]]],
+ [enable expensive run-time checks. With LIST,
+ enable only specific categories of checks.
+ Categories are: yes,no,all,none,release.
+ Flags are: assert,df,extra,fold,gc,gcac,gimple,misc,
+ rtlflag,rtl,runtime,tree,valgrind,types])],
+[ac_checking_flags="${enableval}"],[
+# Determine the default checks.
+if test x$is_release = x ; then
+ ac_checking_flags=yes,extra
+else
+ ac_checking_flags=release
+fi])
+IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="$IFS,"
+for check in release $ac_checking_flags
+do
+ case $check in
+ # these set all the flags to specific states
+ yes) ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking= ;
+ ac_fold_checking= ; ac_gc_checking=1 ; ac_extra_checking= ;
+ ac_gc_always_collect= ; ac_gimple_checking=1 ; ac_rtl_checking= ;
+ ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
+ ac_tree_checking=1 ; ac_valgrind_checking= ;
+ ac_types_checking=1 ;;
+ no|none) ac_assert_checking= ; ac_checking= ; ac_df_checking= ;
+ ac_fold_checking= ; ac_gc_checking= ; ac_extra_checking= ;
+ ac_gc_always_collect= ; ac_gimple_checking= ; ac_rtl_checking= ;
+ ac_rtlflag_checking= ; ac_runtime_checking= ;
+ ac_tree_checking= ; ac_valgrind_checking= ;
+ ac_types_checking= ;;
+ all) ac_assert_checking=1 ; ac_checking=1 ; ac_df_checking=1 ;
+ ac_fold_checking=1 ; ac_gc_checking=1 ; ac_extra_checking=1 ;
+ ac_gc_always_collect=1 ; ac_gimple_checking=1 ; ac_rtl_checking=1 ;
+ ac_rtlflag_checking=1 ; ac_runtime_checking=1 ;
+ ac_tree_checking=1 ; ac_valgrind_checking= ;
+ ac_types_checking=1 ;;
+ release) ac_assert_checking=1 ; ac_checking= ; ac_df_checking= ;
+ ac_fold_checking= ; ac_gc_checking= ; ac_extra_checking= ;
+ ac_gc_always_collect= ; ac_gimple_checking= ; ac_rtl_checking= ;
+ ac_rtlflag_checking= ; ac_runtime_checking=1 ;
+ ac_tree_checking= ; ac_valgrind_checking= ;
+ ac_types_checking= ;;
+ # these enable particular checks
+ assert) ac_assert_checking=1 ;;
+ df) ac_df_checking=1 ;;
+ extra) ac_extra_checking=1 ;;
+ fold) ac_fold_checking=1 ;;
+ gc) ac_gc_checking=1 ;;
+ gcac) ac_gc_always_collect=1 ;;
+ gimple) ac_gimple_checking=1 ;;
+ misc) ac_checking=1 ;;
+ rtl) ac_rtl_checking=1 ;;
+ rtlflag) ac_rtlflag_checking=1 ;;
+ runtime) ac_runtime_checking=1 ;;
+ tree) ac_tree_checking=1 ;;
+ types) ac_types_checking=1 ;;
+ valgrind) ac_valgrind_checking=1 ;;
+ *) AC_MSG_ERROR(unknown check category $check) ;;
+ esac
+done
+IFS="$ac_save_IFS"
+
+nocommon_flag=""
+if test x$ac_checking != x ; then
+ AC_DEFINE(CHECKING_P, 1,
+[Define to 0/1 if you want more run-time sanity checks. This one gets a grab
+bag of miscellaneous but relatively cheap checks.])
+ nocommon_flag=-fno-common
+else
+ AC_DEFINE(CHECKING_P, 0)
+fi
+AC_SUBST(nocommon_flag)
+if test x$ac_extra_checking != x ; then
+ AC_DEFINE(ENABLE_EXTRA_CHECKING, 1,
+[Define to 0/1 if you want extra run-time checking that might affect code
+generation.])
+else
+ AC_DEFINE(ENABLE_EXTRA_CHECKING, 0)
+fi
+if test x$ac_df_checking != x ; then
+ AC_DEFINE(ENABLE_DF_CHECKING, 1,
+[Define if you want more run-time sanity checks for dataflow.])
+fi
+if test x$ac_assert_checking != x ; then
+ AC_DEFINE(ENABLE_ASSERT_CHECKING, 1,
+[Define if you want assertions enabled. This is a cheap check.])
+fi
+if test x$ac_gimple_checking != x ; then
+ AC_DEFINE(ENABLE_GIMPLE_CHECKING, 1,
+[Define if you want operations on GIMPLE (the basic data structure of
+the high-level optimizers) to be checked for dynamic type safety at
+runtime. This is moderately expensive.])
+fi
+GCC_TARGET_TEMPLATE(ENABLE_RUNTIME_CHECKING)
+if test x$ac_runtime_checking != x ; then
+ AC_DEFINE(ENABLE_RUNTIME_CHECKING, 1,
+[Define if you want runtime assertions enabled. This is a cheap check.])
+fi
+if test x$ac_tree_checking != x ; then
+ AC_DEFINE(ENABLE_TREE_CHECKING, 1,
+[Define if you want all operations on trees (the basic data
+ structure of the front ends) to be checked for dynamic type safety
+ at runtime. This is moderately expensive.
+ ])
+ TREECHECKING=yes
+fi
+if test x$ac_types_checking != x ; then
+ AC_DEFINE(ENABLE_TYPES_CHECKING, 1,
+[Define if you want all gimple types to be verified after gimplifiation.
+ This is cheap.
+ ])
+fi
+AC_SUBST(TREECHECKING)
+if test x$ac_rtl_checking != x ; then
+ AC_DEFINE(ENABLE_RTL_CHECKING, 1,
+[Define if you want all operations on RTL (the basic data structure
+ of the optimizer and back end) to be checked for dynamic type safety
+ at runtime. This is quite expensive.])
+fi
+if test x$ac_rtlflag_checking != x ; then
+ AC_DEFINE(ENABLE_RTL_FLAG_CHECKING, 1,
+[Define if you want RTL flag accesses to be checked against the RTL
+ codes that are supported for each access macro. This is relatively
+ cheap.])
+fi
+if test x$ac_gc_checking != x ; then
+ AC_DEFINE(ENABLE_GC_CHECKING, 1,
+[Define if you want the garbage collector to do object poisoning and
+ other memory allocation checks. This is quite expensive.])
+fi
+if test x$ac_gc_always_collect != x ; then
+ AC_DEFINE(ENABLE_GC_ALWAYS_COLLECT, 1,
+[Define if you want the garbage collector to operate in maximally
+ paranoid mode, validating the entire heap and collecting garbage at
+ every opportunity. This is extremely expensive.])
+fi
+if test x$ac_fold_checking != x ; then
+ AC_DEFINE(ENABLE_FOLD_CHECKING, 1,
+[Define if you want fold checked that it never destructs its argument.
+ This is quite expensive.])
+fi
+valgrind_path_defines=
+valgrind_command=
+
+dnl # This check AC_REQUIREs various stuff, so it *must not* be inside
+dnl # an if statement. This was the source of very frustrating bugs
+dnl # in converting to autoconf 2.5x!
+AC_CHECK_HEADER(valgrind.h, have_valgrind_h=yes, have_valgrind_h=no)
+
+# It is certainly possible that there's valgrind but no valgrind.h.
+# GCC relies on making annotations so we must have both.
+AC_MSG_CHECKING(for VALGRIND_DISCARD in <valgrind/memcheck.h>)
+AC_PREPROC_IFELSE([AC_LANG_SOURCE(
+ [[#include <valgrind/memcheck.h>
+#ifndef VALGRIND_DISCARD
+#error VALGRIND_DISCARD not defined
+#endif]])],
+ [gcc_cv_header_valgrind_memcheck_h=yes],
+ [gcc_cv_header_valgrind_memcheck_h=no])
+AC_MSG_RESULT($gcc_cv_header_valgrind_memcheck_h)
+AC_MSG_CHECKING(for VALGRIND_DISCARD in <memcheck.h>)
+AC_PREPROC_IFELSE([AC_LANG_SOURCE(
+ [[#include <memcheck.h>
+#ifndef VALGRIND_DISCARD
+#error VALGRIND_DISCARD not defined
+#endif]])],
+ [gcc_cv_header_memcheck_h=yes],
+ [gcc_cv_header_memcheck_h=no])
+AC_MSG_RESULT($gcc_cv_header_memcheck_h)
+if test $gcc_cv_header_valgrind_memcheck_h = yes; then
+ AC_DEFINE(HAVE_VALGRIND_MEMCHECK_H, 1,
+ [Define if valgrind's valgrind/memcheck.h header is installed.])
+fi
+if test $gcc_cv_header_memcheck_h = yes; then
+ AC_DEFINE(HAVE_MEMCHECK_H, 1,
+ [Define if valgrind's memcheck.h header is installed.])
+fi
+
+if test x$ac_valgrind_checking != x ; then
+ AM_PATH_PROG_WITH_TEST(valgrind_path, valgrind,
+ [$ac_dir/$ac_word --version | grep valgrind- >/dev/null 2>&1])
+ if test "x$valgrind_path" = "x" \
+ || (test $have_valgrind_h = no \
+ && test $gcc_cv_header_memcheck_h = no \
+ && test $gcc_cv_header_valgrind_memcheck_h = no); then
+ AC_MSG_ERROR([*** Can't find both valgrind and valgrind/memcheck.h, memcheck.h or valgrind.h])
+ fi
+ valgrind_path_defines=-DVALGRIND_PATH='\"'$valgrind_path'\"'
+ valgrind_command="$valgrind_path -q"
+ AC_DEFINE(ENABLE_VALGRIND_CHECKING, 1,
+[Define if you want to run subprograms and generated programs
+ through valgrind (a memory checker). This is extremely expensive.])
+fi
+AC_SUBST(valgrind_path_defines)
+AC_SUBST(valgrind_command)
+
+# Enable code coverage collection
+AC_ARG_ENABLE(coverage,
+[AS_HELP_STRING([[--enable-coverage[=LEVEL]]],
+ [enable compiler's code coverage collection.
+ Use to measure compiler performance and locate
+ unused parts of the compiler. With LEVEL, specify
+ optimization. Values are opt, noopt,
+ default is noopt])],
+[case "${enableval}" in
+ yes|noopt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O0 -fkeep-static-functions"
+ ;;
+ opt)
+ coverage_flags="-fprofile-arcs -ftest-coverage -frandom-seed=\$@ -O2 -fkeep-static-functions"
+ ;;
+ no)
+ # a.k.a. --disable-coverage
+ coverage_flags=""
+ ;;
+ *)
+ AC_MSG_ERROR(unknown coverage setting $enableval)
+ ;;
+esac],
+[coverage_flags=""])
+AC_SUBST(coverage_flags)
+
+AC_ARG_ENABLE(gather-detailed-mem-stats,
+[AS_HELP_STRING([--enable-gather-detailed-mem-stats],
+ [enable detailed memory allocation stats gathering])], [],
+[enable_gather_detailed_mem_stats=no])
+gather_stats=`if test $enable_gather_detailed_mem_stats != no; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(GATHER_STATISTICS, $gather_stats,
+[Define to enable detailed memory allocation stats gathering.])
+
+AC_ARG_ENABLE(valgrind-annotations,
+[AS_HELP_STRING([--enable-valgrind-annotations],
+ [enable valgrind runtime interaction])], [],
+[enable_valgrind_annotations=no])
+if test x$enable_valgrind_annotations != xno \
+ || test x$ac_valgrind_checking != x; then
+ if (test $have_valgrind_h = no \
+ && test $gcc_cv_header_memcheck_h = no \
+ && test $gcc_cv_header_valgrind_memcheck_h = no); then
+ AC_MSG_ERROR([*** Can't find valgrind/memcheck.h, memcheck.h or valgrind.h])
+ fi
+ AC_DEFINE(ENABLE_VALGRIND_ANNOTATIONS, 1,
+[Define to get calls to the valgrind runtime enabled.])
+fi
+
+# -------------------------------
+# Miscenalleous configure options
+# -------------------------------
+
+# Determine whether or not multilibs are enabled.
+AC_ARG_ENABLE(multilib,
+[AS_HELP_STRING([--enable-multilib],
+ [enable library support for multiple ABIs])],
+[], [enable_multilib=yes])
+AC_SUBST(enable_multilib)
+
+# Determine whether or not multiarch is enabled.
+AC_ARG_ENABLE(multiarch,
+[AS_HELP_STRING([--enable-multiarch],
+ [enable support for multiarch paths])],
+[case "${enableval}" in
+yes|no|auto) enable_multiarch=$enableval;;
+*) AC_MSG_ERROR(bad value ${enableval} given for --enable-multiarch option) ;;
+esac], [enable_multiarch=auto])
+if test x${enable_multiarch} = xauto; then
+ if test x${with_native_system_header_dir} != x; then
+ ma_msg_suffix=", disabled auto check (configured with --native-system-header-dir)"
+ enable_multiarch=no
+ fi
+ if test x$host != x$target && test "x$with_sysroot" = x; then
+ ma_msg_suffix=", disabled auto check (cross build configured without --with-sysroot)"
+ enable_multiarch=no
+ fi
+fi
+AC_MSG_CHECKING(for multiarch configuration)
+AC_SUBST(enable_multiarch)
+AC_MSG_RESULT($enable_multiarch$ma_msg_suffix)
+
+# needed for setting the multiarch name for soft-float/hard-float ABIs
+AC_SUBST(with_cpu)
+AC_SUBST(with_float)
+
+# default stack clash protection guard size as power of twos in bytes.
+# Please keep these in sync with params.def.
+stk_clash_min=12
+stk_clash_max=30
+
+# Keep the default value when the option is not used to 0, this allows us to
+# distinguish between the cases where the user specifially set a value via
+# configure and when the normal default value is used.
+AC_ARG_WITH(stack-clash-protection-guard-size,
+[AS_HELP_STRING([--with-stack-clash-protection-guard-size=size],
+[Set the default stack clash protection guard size for specific targets as a power of two in bytes.])],
+[DEFAULT_STK_CLASH_GUARD_SIZE="$with_stack_clash_protection_guard_size"], [DEFAULT_STK_CLASH_GUARD_SIZE=0])
+if test $DEFAULT_STK_CLASH_GUARD_SIZE -ne 0 \
+ && (test $DEFAULT_STK_CLASH_GUARD_SIZE -lt $stk_clash_min \
+ || test $DEFAULT_STK_CLASH_GUARD_SIZE -gt $stk_clash_max); then
+ AC_MSG_ERROR(m4_normalize([
+ Invalid value $DEFAULT_STK_CLASH_GUARD_SIZE for --with-stack-clash-protection-guard-size. \
+ Must be between $stk_clash_min and $stk_clash_max.]))
+fi
+
+AC_DEFINE_UNQUOTED(DEFAULT_STK_CLASH_GUARD_SIZE, $DEFAULT_STK_CLASH_GUARD_SIZE,
+ [Define to larger than zero set the default stack clash protector size.])
+
+# Enable __cxa_atexit for C++.
+AC_ARG_ENABLE(__cxa_atexit,
+[AS_HELP_STRING([--enable-__cxa_atexit], [enable __cxa_atexit for C++])],
+[], [])
+
+# Enable C extension for decimal float if target supports it.
+GCC_AC_ENABLE_DECIMAL_FLOAT([$target])
+
+dfp=`if test $enable_decimal_float != no; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(ENABLE_DECIMAL_FLOAT, $dfp,
+[Define to 1 to enable decimal float extension to C.])
+
+# Use default_decimal_float for dependency.
+enable_decimal_float=$default_decimal_float
+
+bid=`if test $enable_decimal_float = bid; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(ENABLE_DECIMAL_BID_FORMAT, $bid,
+[Define to 1 to specify that we are using the BID decimal floating
+point format instead of DPD])
+
+# Enable C extension for fixed-point arithmetic.
+AC_ARG_ENABLE(fixed-point,
+[AS_HELP_STRING([--enable-fixed-point],
+ [enable fixed-point arithmetic extension to C])],
+[],
+[
+ case $target in
+ arm*)
+ enable_fixed_point=yes
+ ;;
+
+ mips*-*-*)
+ enable_fixed_point=yes
+ ;;
+ loongarch*-*-*)
+ enable_fixed_point=yes
+ ;;
+ *)
+ AC_MSG_WARN([fixed-point is not supported for this target, ignored])
+ enable_fixed_point=no
+ ;;
+ esac
+])
+AC_SUBST(enable_fixed_point)
+
+fixedpoint=`if test $enable_fixed_point = yes; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(ENABLE_FIXED_POINT, $fixedpoint,
+[Define to 1 to enable fixed-point arithmetic extension to C.])
+
+# Enable threads
+# Pass with no value to take the default
+# Pass with a value to specify a thread package
+AC_ARG_ENABLE(threads,
+[AS_HELP_STRING([[--enable-threads[=LIB]]],
+ [enable thread usage for target GCC,
+ using LIB thread package])],,
+[enable_threads=''])
+
+AC_ARG_ENABLE(tls,
+[AS_HELP_STRING([--enable-tls],
+ [enable or disable generation of tls code
+ overriding the assembler check for tls support])],
+[
+ case $enable_tls in
+ yes | no) ;;
+ *) AC_MSG_ERROR(['$enable_tls' is an invalid value for --enable-tls.
+Valid choices are 'yes' and 'no'.]) ;;
+ esac
+], [enable_tls=''])
+
+AC_ARG_ENABLE(vtable-verify,
+[AS_HELP_STRING([--enable-vtable-verify],
+ [enable vtable verification feature])],,
+[enable_vtable_verify=no])
+vtable_verify=`if test x$enable_vtable_verify = xyes; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(ENABLE_VTABLE_VERIFY, $vtable_verify,
+[Define 0/1 if vtable verification feature is enabled.])
+
+AC_ARG_ENABLE(analyzer,
+[AS_HELP_STRING([--disable-analyzer],
+ [disable -fanalyzer static analyzer])],
+if test x$enable_analyzer = xno; then
+ analyzer=0
+else
+ analyzer=1
+fi,
+analyzer=1)
+AC_DEFINE_UNQUOTED(ENABLE_ANALYZER, $analyzer,
+[Define 0/1 if static analyzer feature is enabled.])
+
+AC_ARG_ENABLE(objc-gc,
+[AS_HELP_STRING([--enable-objc-gc],
+ [enable the use of Boehm's garbage collector with
+ the GNU Objective-C runtime])],
+if test x$enable_objc_gc = xno; then
+ objc_boehm_gc=''
+else
+ objc_boehm_gc=1
+fi,
+objc_boehm_gc='')
+
+AC_ARG_WITH(dwarf2,
+[AS_HELP_STRING([--with-dwarf2], [force the default debug format to be DWARF 2])],
+dwarf2="$with_dwarf2",
+dwarf2=no)
+
+AC_ARG_ENABLE(shared,
+[AS_HELP_STRING([--disable-shared], [don't provide a shared libgcc])],
+[
+ case $enable_shared in
+ yes | no) ;;
+ *)
+ enable_shared=no
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+ for pkg in $enableval; do
+ if test "X$pkg" = "Xgcc" || test "X$pkg" = "Xlibgcc"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+ esac
+], [enable_shared=yes])
+AC_SUBST(enable_shared)
+
+AC_ARG_ENABLE(gcov,
+[ --disable-gcov don't provide libgcov and related host tools],
+[], [case $target in
+ bpf-*-*)
+ enable_gcov=no
+ ;;
+ *)
+ enable_gcov=yes
+ ;;
+ esac])
+
+AC_SUBST(enable_gcov)
+
+AC_ARG_WITH(specs,
+ [AS_HELP_STRING([--with-specs=SPECS],
+ [add SPECS to driver command-line processing])],
+ [CONFIGURE_SPECS=$withval],
+ [CONFIGURE_SPECS=]
+)
+AC_SUBST(CONFIGURE_SPECS)
+
+ACX_PKGVERSION([GCC])
+ACX_BUGURL([http://sourceforge.net/tracker/?atid=100599&group_id=599&func=browse])
+
+# Allow overriding the default URL for documentation
+AC_ARG_WITH(documentation-root-url,
+ AS_HELP_STRING([--with-documentation-root-url=URL],
+ [Root for documentation URLs]),
+ [case "$withval" in
+ yes) AC_MSG_ERROR([documentation root URL not specified]) ;;
+ no) AC_MSG_ERROR([documentation root URL not specified]) ;;
+ */) DOCUMENTATION_ROOT_URL="$withval" ;;
+ *) AC_MSG_ERROR([documentation root URL does not end with /]) ;;
+ esac],
+ DOCUMENTATION_ROOT_URL="https://gcc.gnu.org/onlinedocs/"
+)
+AC_DEFINE_UNQUOTED(DOCUMENTATION_ROOT_URL,"$DOCUMENTATION_ROOT_URL",
+ [Define to the root for documentation URLs.])
+
+# Allow overriding the default URL for GCC changes
+AC_ARG_WITH(changes-root-url,
+ AS_HELP_STRING([--with-changes-root-url=URL],
+ [Root for GCC changes URLs]),
+ [case "$withval" in
+ yes) AC_MSG_ERROR([changes root URL not specified]) ;;
+ no) AC_MSG_ERROR([changes root URL not specified]) ;;
+ */) CHANGES_ROOT_URL="$withval" ;;
+ *) AC_MSG_ERROR([changes root URL does not end with /]) ;;
+ esac],
+ CHANGES_ROOT_URL="https://gcc.gnu.org/"
+)
+AC_DEFINE_UNQUOTED(CHANGES_ROOT_URL,"$CHANGES_ROOT_URL",
+ [Define to the root for URLs about GCC changes.])
+
+# Sanity check enable_languages in case someone does not run the toplevel
+# configure # script.
+AC_ARG_ENABLE(languages,
+[AS_HELP_STRING([--enable-languages=LIST], [specify which front-ends to build])],
+[case ,${enable_languages}, in
+ ,,|,yes,)
+ # go safe -- we cannot be much sure without the toplevel
+ # configure's
+ # analysis of which target libs are present and usable
+ enable_languages=c
+ ;;
+ *,all,*)
+ AC_MSG_ERROR([only the toplevel supports --enable-languages=all])
+ ;;
+ *,c,*)
+ ;;
+ *)
+ enable_languages=c,${enable_languages}
+ ;;
+esac],
+[enable_languages=c])
+
+# If top-level libada has been disabled, then wire in install-gnatlib
+# invocation with `make install', so that one can build and install
+# the library manually with `make -C gcc all gnatlib gnattools install'.
+if test x"$enable_libada" = xno; then
+ gnat_install_lib=gnat-install-lib
+else
+ gnat_install_lib=
+fi
+AC_SUBST(gnat_install_lib)
+
+if test x"$enable_as_accelerator_for" != x; then
+ AC_DEFINE(ACCEL_COMPILER, 1,
+ [Define if this compiler should be built as the offload target compiler.])
+ enable_as_accelerator=yes
+ case "${target}" in
+ *-intelmicemul-*)
+ # In this case we expect offload compiler to be built as native, so we
+ # need to rename the driver to avoid clashes with host's drivers.
+ program_transform_name="s&^&${target}-&" ;;
+ esac
+ sedscript="s#${target_noncanonical}#${enable_as_accelerator_for}-accel-${target_noncanonical}#"
+ program_transform_name=`echo $program_transform_name | sed $sedscript`
+ accel_dir_suffix=/accel/${target_noncanonical}
+ real_target_noncanonical=${enable_as_accelerator_for}
+fi
+AC_SUBST(enable_as_accelerator)
+AC_SUBST(real_target_noncanonical)
+AC_SUBST(accel_dir_suffix)
+
+for tgt in `echo $enable_offload_targets | sed 's/,/ /g'`; do
+ tgt=`echo $tgt | sed 's/=.*//'`
+
+ enable_offloading=1
+ case "$tgt" in
+ *-intelmic-* | *-intelmicemul-*)
+ omp_device_property=omp-device-properties-i386
+ omp_device_property_tmake_file="${omp_device_property_tmake_file} \$(srcdir)/config/i386/t-omp-device"
+ ;;
+ amdgcn*)
+ omp_device_property=omp-device-properties-gcn
+ omp_device_property_tmake_file="${omp_device_property_tmake_file} \$(srcdir)/config/gcn/t-omp-device"
+ ;;
+ nvptx*)
+ omp_device_property=omp-device-properties-nvptx
+ omp_device_property_tmake_file="${omp_device_property_tmake_file} \$(srcdir)/config/nvptx/t-omp-device"
+ ;;
+ *)
+ AC_MSG_ERROR([unknown offload target specified])
+ ;;
+ esac
+ omp_device_properties="${omp_device_properties} ${tgt}=${omp_device_property}"
+ omp_device_property_deps="${omp_device_property_deps} ${omp_device_property}"
+
+ if test x"$offload_targets" = x; then
+ offload_targets=$tgt
+ else
+ offload_targets="$offload_targets,$tgt"
+ fi
+done
+AC_SUBST(omp_device_properties)
+AC_SUBST(omp_device_property_deps)
+
+AC_DEFINE_UNQUOTED(OFFLOAD_TARGETS, "$offload_targets",
+ [Define to offload targets, separated by commas.])
+if test x"$enable_offloading" != x; then
+ AC_DEFINE(ENABLE_OFFLOADING, 1,
+ [Define this to enable support for offloading.])
+else
+ AC_DEFINE(ENABLE_OFFLOADING, 0,
+ [Define this to enable support for offloading.])
+fi
+
+if test "x$enable_offload_defaulted" = xyes; then
+ AC_DEFINE(OFFLOAD_DEFAULTED, 1,
+ [Define to 1 to if -foffload is defaulted])
+fi
+
+AC_ARG_WITH(multilib-list,
+[AS_HELP_STRING([--with-multilib-list], [select multilibs (AArch64, ARM, AVR, OR1K, RISC-V, SH and x86-64 only)])],
+:,
+with_multilib_list=default)
+
+AC_ARG_WITH(multilib-generator,
+[AS_HELP_STRING([--with-multilib-generator], [Multi-libs configuration string (RISC-V only)])],
+:,
+with_multilib_generator=default)
+
+# -------------------------
+# Checks for other programs
+# -------------------------
+
+AC_PROG_MAKE_SET
+
+# Find some useful tools
+AC_PROG_AWK
+# We need awk to create options.cc and options.h.
+# Bail out if it's missing.
+case ${AWK} in
+ "") AC_MSG_ERROR([can't build without awk, bailing out]) ;;
+esac
+
+gcc_AC_PROG_LN_S
+ACX_PROG_LN($LN_S)
+AC_PROG_RANLIB
+ranlib_flags=""
+AC_SUBST(ranlib_flags)
+
+gcc_AC_PROG_INSTALL
+
+# See if cmp has --ignore-initial.
+gcc_AC_PROG_CMP_IGNORE_INITIAL
+
+# See if we have the mktemp command.
+AC_CHECK_PROG(have_mktemp_command, mktemp, yes, no)
+
+# See if makeinfo has been installed and is modern enough
+# that we can use it.
+ACX_CHECK_PROG_VER(MAKEINFO, makeinfo, --version,
+ [GNU texinfo.* \([0-9][0-9.]*\)],
+ [4.[7-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*])
+if test $gcc_cv_prog_makeinfo_modern = no; then
+ AC_MSG_WARN([
+*** Makeinfo is missing or too old.
+*** Info documentation will not be built.])
+ BUILD_INFO=
+else
+ BUILD_INFO=info
+fi
+AC_SUBST(BUILD_INFO)
+
+# Is pod2man recent enough to regenerate manpages?
+AC_MSG_CHECKING([for recent Pod::Man])
+if (perl -e 'use 1.10 Pod::Man') >/dev/null 2>&1; then
+ AC_MSG_RESULT(yes)
+ GENERATED_MANPAGES=generated-manpages
+else
+ AC_MSG_RESULT(no)
+ GENERATED_MANPAGES=
+fi
+AC_SUBST(GENERATED_MANPAGES)
+
+MISSING="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing"
+
+# How about lex?
+dnl Don't use AC_PROG_LEX; we insist on flex.
+dnl LEXLIB is not useful in gcc.
+AC_CHECK_PROGS([FLEX], flex, [$MISSING flex])
+
+# Bison?
+AC_CHECK_PROGS([BISON], bison, [$MISSING bison])
+
+# Binutils are not build modules, unlike bison/flex/makeinfo. So we
+# check for build == host before using them.
+
+# NM
+if test x${build} = x${host} && test -f $srcdir/../binutils/nm.c \
+ && test -d ../binutils ; then
+ NM='${objdir}/../binutils/nm-new'
+else
+ AC_CHECK_PROG(NM, nm, nm, ${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing nm)
+fi
+
+# AR
+if test x${build} = x${host} && test -f $srcdir/../binutils/ar.c \
+ && test -d ../binutils ; then
+ AR='${objdir}/../binutils/ar'
+else
+ AC_CHECK_PROG(AR, ar, ar, ${CONFIG_SHELL-/bin/sh} ${srcdir}/../missing ar)
+fi
+
+# The jit documentation looks better if built with sphinx, but can be
+# built with texinfo if sphinx is not available.
+# Set "doc_build_sys" to "sphinx" or "texinfo" accordingly.
+AC_CHECK_PROG(doc_build_sys, sphinx-build, sphinx, texinfo)
+
+# --------------------
+# Checks for C headers
+# --------------------
+
+# Need to reject headers which give warnings, so that the -Werror bootstrap
+# works later. *sigh* This needs to come before all header checks.
+AC_PROG_CPP_WERROR
+
+AC_HEADER_STDC
+AC_HEADER_TIME
+ACX_HEADER_STRING
+AC_HEADER_SYS_WAIT
+AC_HEADER_TIOCGWINSZ
+AC_CHECK_HEADERS(limits.h stddef.h string.h strings.h stdlib.h time.h iconv.h \
+ fcntl.h ftw.h unistd.h sys/file.h sys/time.h sys/mman.h \
+ sys/resource.h sys/param.h sys/times.h sys/stat.h sys/locking.h \
+ direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h)
+
+# Check for thread headers.
+AC_CHECK_HEADER(thread.h, [have_thread_h=yes], [have_thread_h=])
+AC_CHECK_HEADER(pthread.h, [have_pthread_h=yes], [have_pthread_h=])
+
+# These tests can't be done till we know if we have limits.h.
+gcc_AC_C_CHAR_BIT
+AC_C_BIGENDIAN
+
+# ----------------------
+# Checks for C++ headers
+# ----------------------
+
+dnl Autoconf will give an error in the configure script if there is no
+dnl C++ preprocessor. Hack to prevent that.
+m4_pushdef([AC_MSG_ERROR], m4_defn([AC_MSG_WARN]))[]dnl
+AC_PROG_CXXCPP
+m4_popdef([AC_MSG_ERROR])[]dnl
+
+AC_CHECK_HEADERS(unordered_map)
+AC_CHECK_HEADERS(tr1/unordered_map)
+AC_CHECK_HEADERS(ext/hash_map)
+
+# --------
+# Dependency checking.
+# --------
+
+ZW_CREATE_DEPDIR
+AC_CONFIG_COMMANDS([gccdepdir],[
+ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs build/$DEPDIR
+ for lang in $subdirs c-family common analyzer rtl-ssa
+ do
+ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR
+ done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR])
+
+ZW_PROG_COMPILER_DEPENDENCIES([CXX])
+
+# --------
+# UNSORTED
+# --------
+
+
+# These libraries may be used by collect2.
+# We may need a special search path to get them linked.
+AC_CACHE_CHECK(for collect2 libraries, gcc_cv_collect2_libs,
+[save_LIBS="$LIBS"
+for libs in '' -lld -lmld \
+ '-L/usr/lib/cmplrs/cc2.11 -lmld' \
+ '-L/usr/lib/cmplrs/cc3.11 -lmld'
+do
+ LIBS="$libs"
+ AC_TRY_LINK_FUNC(ldopen,
+ [gcc_cv_collect2_libs="$libs"; break])
+done
+LIBS="$save_LIBS"
+test -z "$gcc_cv_collect2_libs" && gcc_cv_collect2_libs='none required'])
+case $gcc_cv_collect2_libs in
+ "none required") ;;
+ *) COLLECT2_LIBS=$gcc_cv_collect2_libs ;;
+esac
+AC_SUBST(COLLECT2_LIBS)
+
+# When building Ada code on Alpha, we need exc_resume which is usually in
+# -lexc. So test for it.
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(exc_resume, exc)
+GNAT_LIBEXC="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(GNAT_LIBEXC)
+
+# To support -mcpu=native on Solaris/SPARC, we need libkstat.
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(kstat_open, kstat)
+EXTRA_GCC_LIBS="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(EXTRA_GCC_LIBS)
+
+# Solaris needs libsocket and libnsl for socket functions before 11.4.
+# C++ needs those for libcody.
+save_LIBS="$LIBS"
+LIBS=
+AX_LIB_SOCKET_NSL
+NETLIBS="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(NETLIBS)
+
+# Some systems put ldexp and frexp in libm instead of libc; assume
+# they're both in the same place. jcf-dump needs them.
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(ldexp, m)
+LDEXP_LIB="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(LDEXP_LIB)
+
+# Some systems need dlopen
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(dlopen, dl)
+DL_LIB="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(DL_LIB)
+
+# Use <inttypes.h> only if it exists,
+# doesn't clash with <sys/types.h>, declares intmax_t and defines
+# PRId64
+AC_MSG_CHECKING(for inttypes.h)
+AC_CACHE_VAL(gcc_cv_header_inttypes_h,
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[#define __STDC_FORMAT_MACROS
+#include <sys/types.h>
+#include <inttypes.h>]],
+ [[intmax_t i = -1;
+#ifndef PRId64
+choke me
+#endif]])],
+ [gcc_cv_header_inttypes_h=yes],
+ [gcc_cv_header_inttypes_h=no])])
+AC_MSG_RESULT($gcc_cv_header_inttypes_h)
+if test $gcc_cv_header_inttypes_h = yes; then
+ AC_DEFINE(HAVE_INTTYPES_H, 1,
+ [Define if you have a working <inttypes.h> header file.])
+fi
+
+# Look for the ZSTD package.
+ZSTD_INCLUDE=
+ZSTD_LIB=
+AC_SUBST(ZSTD_INCLUDE)
+AC_SUBST(ZSTD_LIB)
+ZSTD_CPPFLAGS=
+ZSTD_LDFLAGS=
+AC_SUBST(ZSTD_CPPFLAGS)
+AC_SUBST(ZSTD_LDFLAGS)
+AC_ARG_WITH(zstd,
+ [AS_HELP_STRING([--with-zstd=PATH],
+ [specify prefix directory for installed zstd library.
+ Equivalent to --with-zstd-include=PATH/include
+ plus --with-zstd-lib=PATH/lib])])
+AC_ARG_WITH(zstd-include,
+ [AS_HELP_STRING([--with-zstd-include=PATH],
+ [specify directory for installed zstd include files])])
+AC_ARG_WITH(zstd-lib,
+ [AS_HELP_STRING([--with-zstd-lib=PATH],
+ [specify directory for the installed zstd library])])
+case "x$with_zstd" in
+ x) ;;
+ xno)
+ ZSTD_INCLUDE=
+ ZSTD_LIB=
+ ;;
+ *) ZSTD_INCLUDE=$with_zstd/include
+ ZSTD_LIB=$with_zstd/lib
+ ;;
+esac
+
+if test "x$with_zstd" != xno; then
+if test "x$with_zstd_include" != x; then
+ ZSTD_INCLUDE=$with_zstd_include
+fi
+if test "x$with_zstd_lib" != x; then
+ ZSTD_LIB=$with_zstd_lib
+fi
+if test "x$ZSTD_INCLUDE" != x \
+ && test "x$ZSTD_INCLUDE" != xno; then
+ ZSTD_CPPFLAGS=-I$ZSTD_INCLUDE
+fi
+if test "x$ZSTD_LIB" != x \
+ && test "x$ZSTD_LIB" != xno; then
+ ZSTD_LDFLAGS=-L$ZSTD_LIB
+fi
+
+CXXFLAGS="$CXXFLAGS $ZSTD_CPPFLAGS"
+LDFLAGS="$LDFLAGS $ZSTD_LDFLAGS"
+
+AC_MSG_CHECKING(for zstd.h)
+AC_CACHE_VAL(gcc_cv_header_zstd_h,
+# We require version 1.3.0 or later. This is the first version that has
+# ZSTD_getFrameContentSize.
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+[[#include <zstd.h>
+#if ZSTD_VERSION_NUMBER < 10300
+#error "need zstd 1.3.0 or better"
+#endif]])],
+ [gcc_cv_header_zstd_h=yes],
+ [gcc_cv_header_zstd_h=no])])
+AC_MSG_RESULT($gcc_cv_header_zstd_h)
+if test $gcc_cv_header_zstd_h = yes; then
+ AC_DEFINE(HAVE_ZSTD_H, 1,
+ [Define if you have a working <zstd.h> header file.])
+elif test "x$with_zstd" != x; then
+ as_fn_error $? "Unable to find zstd.h. See config.log for details." "$LINENO" 5
+fi
+
+# LTO can use zstd compression algorithm
+save_LIBS="$LIBS"
+LIBS=
+AC_SEARCH_LIBS(ZSTD_compress, zstd)
+ZSTD_LIB="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST(ZSTD_LIB)
+fi
+
+dnl Disabled until we have a complete test for buggy enum bitfields.
+dnl gcc_AC_C_ENUM_BF_UNSIGNED
+
+define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl
+ ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked dnl
+ fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked dnl
+ fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked dnl
+ putchar_unlocked putc_unlocked)
+AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoq \
+ popen sysconf strsignal getrusage nl_langinfo \
+ gettimeofday mbstowcs wcswidth mmap posix_fallocate setlocale \
+ gcc_UNLOCKED_FUNCS madvise mallinfo mallinfo2 fstatat)
+
+if test x$ac_cv_func_mbstowcs = xyes; then
+ AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
+[ AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <stdlib.h>
+int main()
+{
+ mbstowcs(0, "", 0);
+ return 0;
+}]])],
+ [gcc_cv_func_mbstowcs_works=yes],
+ [gcc_cv_func_mbstowcs_works=no],
+ [gcc_cv_func_mbstowcs_works=yes])])
+ if test x$gcc_cv_func_mbstowcs_works = xyes; then
+ AC_DEFINE(HAVE_WORKING_MBSTOWCS, 1,
+ [Define this macro if mbstowcs does not crash when its
+ first argument is NULL.])
+ fi
+fi
+
+AC_CHECK_TYPE(ssize_t, int)
+AC_CHECK_TYPE(caddr_t, char *)
+AC_CHECK_TYPE(sighander_t,
+ AC_DEFINE(HAVE_SIGHANDLER_T, 1,
+ [Define if <sys/signal.h> defines sighandler_t]),
+ ,signal.h)
+
+GCC_AC_FUNC_MMAP_BLACKLIST
+
+case "${host}" in
+*-*-*vms*)
+ # Under VMS, vfork works very differently than on Unix. The standard test
+ # won't work, and it isn't easily adaptable. It makes more sense to
+ # just force it.
+ ac_cv_func_vfork_works=yes
+ ;;
+esac
+AC_FUNC_FORK
+
+AM_ICONV
+
+# Until we have in-tree GNU iconv:
+LIBICONV_DEP=
+if test -f "$LTLIBICONV"; then
+ LIBICONV_DEP=$LTLIBICONV
+fi
+AC_SUBST(LIBICONV_DEP)
+
+AM_LC_MESSAGES
+
+AM_LANGINFO_CODESET
+
+# We will need to find libiberty.h and ansidecl.h
+saved_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include $GMPINC -I${top_srcdir}/../../sdbinutils/include"
+saved_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include $GMPINC -I${srcdir}/../../sdbinutils/include"
+
+# gcc_AC_CHECK_DECLS doesn't support overloaded functions, so use the
+# normal autoconf function for these. But force definition of
+# HAVE_DECL_BASENAME like gcc_AC_CHECK_DECLS does, to suppress the bizarre
+# basename handling in libiberty.h.
+AC_CHECK_DECLS([basename(const char*), strstr(const char*,const char*)], , ,[
+#undef HAVE_DECL_BASENAME
+#define HAVE_DECL_BASENAME 1
+#include "ansidecl.h"
+#include "system.h"])
+
+gcc_AC_CHECK_DECLS(getenv atol atoll asprintf sbrk abort atof getcwd getwd \
+ madvise stpcpy strnlen strsignal strverscmp \
+ strtol strtoul strtoll strtoull setenv unsetenv \
+ errno snprintf vsnprintf vasprintf malloc realloc calloc \
+ free getopt clock getpagesize ffs gcc_UNLOCKED_FUNCS, , ,[
+#include "ansidecl.h"
+#include "system.h"])
+
+gcc_AC_CHECK_DECLS(getrlimit setrlimit getrusage, , ,[
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+])
+
+gcc_AC_CHECK_DECLS(mallinfo mallinfo2, , ,[
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+])
+
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+]], [[rlim_t l = 0;]])],[],[AC_DEFINE([rlim_t],[long],
+[Define to `long' if <sys/resource.h> doesn't define.])])
+
+# On AIX 5.2, <ldfcn.h> conflicts with <fcntl.h>, as both define incompatible
+# FREAD and FWRITE macros. Fortunately, for GCC's single usage of ldgetname
+# in collect2.cc, <fcntl.h> isn't visible, but the configure test below needs
+# to undef these macros to get the correct value for HAVE_DECL_LDGETNAME.
+gcc_AC_CHECK_DECLS(ldgetname, , ,[
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_LDFCN_H
+#undef FREAD
+#undef FWRITE
+#include <ldfcn.h>
+#endif
+])
+
+gcc_AC_CHECK_DECLS(times, , ,[
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
+])
+
+gcc_AC_CHECK_DECLS(sigaltstack, , ,[
+#include "ansidecl.h"
+#include "system.h"
+#include <signal.h>
+])
+
+# More time-related stuff.
+AC_CACHE_CHECK(for struct tms, ac_cv_struct_tms, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include "ansidecl.h"
+#include "system.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
+]], [[struct tms tms;]])],[ac_cv_struct_tms=yes],[ac_cv_struct_tms=no])])
+if test $ac_cv_struct_tms = yes; then
+ AC_DEFINE(HAVE_STRUCT_TMS, 1,
+ [Define if <sys/times.h> defines struct tms.])
+fi
+
+# use gcc_cv_* here because this doesn't match the behavior of AC_CHECK_TYPE.
+# revisit after autoconf 2.50.
+AC_CACHE_CHECK(for clock_t, gcc_cv_type_clock_t, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include "ansidecl.h"
+#include "system.h"
+]], [[clock_t x;]])],[gcc_cv_type_clock_t=yes],[gcc_cv_type_clock_t=no])])
+if test $gcc_cv_type_clock_t = yes; then
+ AC_DEFINE(HAVE_CLOCK_T, 1,
+ [Define if <time.h> defines clock_t.])
+fi
+
+# Check if F_SETLKW is supported by fcntl.
+AC_CACHE_CHECK(for F_SETLKW, ac_cv_f_setlkw, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <fcntl.h>]], [[
+struct flock fl;
+fl.l_whence = 0;
+fl.l_start = 0;
+fl.l_len = 0;
+fl.l_pid = 0;
+return fcntl (1, F_SETLKW, &fl);]])],
+[ac_cv_f_setlkw=yes],[ac_cv_f_setlkw=no])])
+if test $ac_cv_f_setlkw = yes; then
+ AC_DEFINE(HOST_HAS_F_SETLKW, 1,
+ [Define if F_SETLKW supported by fcntl.])
+fi
+
+# Check if O_CLOEXEC is defined by fcntl
+AC_CACHE_CHECK(for O_CLOEXEC, ac_cv_o_cloexec, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <fcntl.h>]], [[
+return open ("/dev/null", O_RDONLY | O_CLOEXEC);]])],
+[ac_cv_o_cloexec=yes],[ac_cv_o_cloexec=no])])
+if test $ac_cv_o_cloexec = yes; then
+ AC_DEFINE(HOST_HAS_O_CLOEXEC, 1,
+ [Define if O_CLOEXEC supported by fcntl.])
+fi
+
+# C++ Modules would like some networking features to provide the mapping
+# server. You can still use modules without them though.
+# The following network-related checks could probably do with some
+# Windows and other non-linux defenses and checking.
+
+# Local socket connectivity wants AF_UNIX networking
+# Check for AF_UNIX networking
+AC_CACHE_CHECK(for AF_UNIX, ac_cv_af_unix, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>]],[[
+sockaddr_un un;
+un.sun_family = AF_UNSPEC;
+int fd = socket (AF_UNIX, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&un, sizeof (un));]])],
+[ac_cv_af_unix=yes],
+[ac_cv_af_unix=no])])
+if test $ac_cv_af_unix = yes; then
+ AC_DEFINE(HAVE_AF_UNIX, 1,
+ [Define if AF_UNIX supported.])
+fi
+
+# Remote socket connectivity wants AF_INET6 networking
+# Check for AF_INET6 networking
+AC_CACHE_CHECK(for AF_INET6, ac_cv_af_inet6, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>]],[[
+sockaddr_in6 in6;
+in6.sin6_family = AF_UNSPEC;
+struct addrinfo *addrs = 0;
+struct addrinfo hints;
+hints.ai_flags = 0;
+hints.ai_family = AF_INET6;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_protocol = 0;
+hints.ai_canonname = 0;
+hints.ai_addr = 0;
+hints.ai_next = 0;
+int e = getaddrinfo ("localhost", 0, &hints, &addrs);
+const char *str = gai_strerror (e);
+freeaddrinfo (addrs);
+int fd = socket (AF_INET6, SOCK_STREAM, 0);
+connect (fd, (sockaddr *)&in6, sizeof (in6));]])],
+[ac_cv_af_inet6=yes],
+[ac_cv_af_inet6=no])])
+if test $ac_cv_af_inet6 = yes; then
+ AC_DEFINE(HAVE_AF_INET6, 1,
+ [Define if AF_INET6 supported.])
+fi
+
+# Check if _LK_LOCK is supported by _locking
+AC_CACHE_CHECK(for _LK_LOCK, ac_cv_lk_lock, [
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <io.h>
+#include <sys/locking.h>]], [[
+ int fd;
+ return _locking (fd, _LK_LOCK, 0);]])],
+[ac_cv_lk_lock=yes],[ac_cv_lk_lock=no])])
+if test $ac_cv_lk_lock = yes; then
+ AC_DEFINE(HOST_HAS_LK_LOCK, 1,
+ [Define if _LK_LOC supported by _locking.])
+fi
+
+# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
+CFLAGS="$saved_CFLAGS"
+CXXFLAGS="$saved_CXXFLAGS"
+
+# mkdir takes a single argument on some systems.
+gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG
+
+# File extensions
+manext='.1'
+objext='.o'
+AC_SUBST(manext)
+AC_SUBST(objext)
+
+# With Setjmp/Longjmp based exception handling.
+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
+ ;;
+ *)
+ force_sjlj_exceptions=no
+ ;;
+esac])
+if test $force_sjlj_exceptions = yes; then
+ sjlj=`if test $enableval = yes; then echo 1; else echo 0; fi`
+ AC_DEFINE_UNQUOTED(CONFIG_SJLJ_EXCEPTIONS, $sjlj,
+ [Define 0/1 to force the choice for exception handling model.])
+fi
+
+# --------------------------------------------------------
+# Build, host, and target specific configuration fragments
+# --------------------------------------------------------
+
+# Collect build-machine-specific information.
+. ${srcdir}/config.build || exit 1
+
+# Collect host-machine-specific information.
+. ${srcdir}/config.host || exit 1
+
+target_gtfiles=
+
+# Collect target-machine-specific information.
+. ${srcdir}/config.gcc || exit 1
+
+extra_objs="${host_extra_objs} ${extra_objs}"
+extra_gcc_objs="${host_extra_gcc_objs} ${extra_gcc_objs}"
+
+# Default the target-machine variables that were not explicitly set.
+if test x"$tm_file" = x
+then tm_file=$cpu_type/$cpu_type.h; fi
+
+if test x"$extra_headers" = x
+then extra_headers=; fi
+
+if test x$md_file = x
+then md_file=$cpu_type/$cpu_type.md; fi
+
+if test x$out_file = x
+then out_file=$cpu_type/$cpu_type.cc; fi
+
+if test x"$tmake_file" = x
+then tmake_file=$cpu_type/t-$cpu_type
+fi
+
+# Support --enable-initfini-array.
+if test x$enable_initfini_array != xno; then
+ tm_file="${tm_file} initfini-array.h"
+fi
+
+if test x"$dwarf2" = xyes
+then tm_file="$tm_file tm-dwarf2.h"
+fi
+
+# Say what files are being used for the output code and MD file.
+echo "Using \`$srcdir/config/$out_file' for machine-specific logic."
+echo "Using \`$srcdir/config/$md_file' as machine description file."
+
+# If any of the xm_file variables contain nonexistent files, warn
+# about them and drop them.
+
+bx=
+for x in $build_xm_file; do
+ if test -f $srcdir/config/$x
+ then bx="$bx $x"
+ else AC_MSG_WARN($srcdir/config/$x does not exist.)
+ fi
+done
+build_xm_file="$bx"
+
+hx=
+for x in $host_xm_file; do
+ if test -f $srcdir/config/$x
+ then hx="$hx $x"
+ else AC_MSG_WARN($srcdir/config/$x does not exist.)
+ fi
+done
+host_xm_file="$hx"
+
+tx=
+for x in $xm_file; do
+ if test -f $srcdir/config/$x
+ then tx="$tx $x"
+ else AC_MSG_WARN($srcdir/config/$x does not exist.)
+ fi
+done
+xm_file="$tx"
+
+count=a
+for f in $tm_file; do
+ count=${count}x
+done
+if test $count = ax; then
+ echo "Using \`$srcdir/config/$tm_file' as target machine macro file."
+else
+ echo "Using the following target machine macro files:"
+ for f in $tm_file; do
+ echo " $srcdir/config/$f"
+ done
+fi
+
+if test x$use_long_long_for_widest_fast_int = xyes; then
+ AC_DEFINE(USE_LONG_LONG_FOR_WIDEST_FAST_INT, 1,
+[Define to 1 if the 'long long' type is wider than 'long' but still
+efficiently supported by the host hardware.])
+fi
+
+gnu_ld_bool=`if test x"$gnu_ld" = x"yes"; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(HAVE_GNU_LD, $gnu_ld_bool, [Define to 1 if using GNU ld.])
+
+gnu_as_bool=`if test x"$gas" = x"yes"; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(HAVE_GNU_AS, $gnu_as_bool, [Define to 1 if using GNU as.])
+
+count=a
+for f in $host_xm_file; do
+ count=${count}x
+done
+if test $count = a; then
+ :
+elif test $count = ax; then
+ echo "Using \`$srcdir/config/$host_xm_file' as host machine macro file."
+else
+ echo "Using the following host machine macro files:"
+ for f in $host_xm_file; do
+ echo " $srcdir/config/$f"
+ done
+fi
+echo "Using ${out_host_hook_obj} for host machine hooks."
+
+if test "$host_xm_file" != "$build_xm_file"; then
+ count=a
+ for f in $build_xm_file; do
+ count=${count}x
+ done
+ if test $count = a; then
+ :
+ elif test $count = ax; then
+ echo "Using \`$srcdir/config/$build_xm_file' as build machine macro file."
+ else
+ echo "Using the following build machine macro files:"
+ for f in $build_xm_file; do
+ echo " $srcdir/config/$f"
+ done
+ fi
+fi
+
+if test -n "$configured_native_system_header_dir"; then
+ native_system_header_dir=$configured_native_system_header_dir
+fi
+NATIVE_SYSTEM_HEADER_DIR="$native_system_header_dir"
+AC_SUBST(NATIVE_SYSTEM_HEADER_DIR)
+
+case ${host} in
+ powerpc*-*-darwin*)
+ AC_CACHE_CHECK([whether mcontext_t fields have underscores],
+ gcc_cv_mcontext_underscores,
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <sys/cdefs.h>
+#include <sys/signal.h>
+#include <ucontext.h>
+int main() { mcontext_t m; if (m->ss.srr0) return 0; return 0; }
+])],
+ gcc_cv_mcontext_underscores=no, gcc_cv_mcontext_underscores=yes))
+ if test $gcc_cv_mcontext_underscores = yes; then
+ AC_DEFINE(HAS_MCONTEXT_T_UNDERSCORES,,dnl
+ [mcontext_t fields start with __])
+ fi
+ ;;
+esac
+
+# ---------
+# Threading
+# ---------
+
+# Check if a valid thread package
+case ${enable_threads} in
+ "" | no)
+ # No threads
+ target_thread_file='single'
+ ;;
+ yes)
+ # default
+ target_thread_file='single'
+ ;;
+ aix | dce | lynx | mipssde | posix | rtems | \
+ single | tpf | vxworks | win32)
+ target_thread_file=${enable_threads}
+ ;;
+ *)
+ echo "${enable_threads} is an unknown thread package" 1>&2
+ exit 1
+ ;;
+esac
+
+if test x${thread_file} = x; then
+ # No thread file set by target-specific clauses in config.gcc,
+ # so use file chosen by default logic above
+ thread_file=${target_thread_file}
+fi
+
+# --------
+# UNSORTED
+# --------
+
+use_cxa_atexit=no
+if test x$enable___cxa_atexit = xyes || \
+ test x$enable___cxa_atexit = x -a x$default_use_cxa_atexit = xyes; then
+ if test x$host = x$target; then
+ case $host in
+ # mingw32 doesn't have __cxa_atexit but uses atexit registration
+ # keyed to flag_use_cxa_atexit
+ *-*-mingw32*)
+ use_cxa_atexit=yes
+ ;;
+ powerpc-ibm-aix*)
+ use_cxa_atexit=yes
+ ;;
+ *)
+ AC_CHECK_FUNC(__cxa_atexit,[use_cxa_atexit=yes],
+ [echo "__cxa_atexit can't be enabled on this target"])
+ ;;
+ esac
+ else
+ # We can't check for __cxa_atexit when building a cross, so assume
+ # it is available
+ use_cxa_atexit=yes
+ fi
+ if test x$use_cxa_atexit = xyes; then
+ AC_DEFINE(DEFAULT_USE_CXA_ATEXIT, 2,
+ [Define if you want to use __cxa_atexit, rather than atexit, to
+ register C++ destructors for local statics and global objects.
+ This is essential for fully standards-compliant handling of
+ destructors, but requires __cxa_atexit in libc.])
+ fi
+fi
+
+# Look for a file containing extra machine modes.
+if test -n "$extra_modes" && test -f $srcdir/config/$extra_modes; then
+ extra_modes_file='$(srcdir)'/config/${extra_modes}
+ AC_SUBST(extra_modes_file)
+ AC_DEFINE_UNQUOTED(EXTRA_MODES_FILE, "config/$extra_modes",
+ [Define to the name of a file containing a list of extra machine modes
+ for this architecture.])
+fi
+
+# Convert extra_options into a form suitable for Makefile use.
+extra_opt_files=
+all_opt_files=
+for f in $extra_options; do
+ extra_opt_files="$extra_opt_files \$(srcdir)/config/$f"
+ all_opt_files="$all_opt_files $srcdir/config/$f"
+done
+AC_SUBST(extra_opt_files)
+
+# auto-host.h is the file containing items generated by autoconf and is
+# the first file included by config.h.
+# If host=build, it is correct to have bconfig include auto-host.h
+# as well. If host!=build, we are in error and need to do more
+# work to find out the build config parameters.
+if test x$host = x$build
+then
+ build_auto=auto-host.h
+ HAVE_AUTO_BUILD='# '
+else
+ # We create a subdir, then run autoconf in the subdir.
+ # To prevent recursion we set host and build for the new
+ # invocation of configure to the build for this invocation
+ # of configure.
+ tempdir=build.$$
+ rm -rf $tempdir
+ mkdir $tempdir
+ cd $tempdir
+ case ${srcdir} in
+ /* | [A-Za-z]:[\\/]* ) realsrcdir=${srcdir};;
+ *) realsrcdir=../${srcdir};;
+ esac
+ # Clearing GMPINC is necessary to prevent host headers being
+ # used by the build compiler. Defining GENERATOR_FILE stops
+ # system.h from including gmp.h.
+ CC="${CC_FOR_BUILD}" CFLAGS="${CFLAGS_FOR_BUILD}" \
+ CXX="${CXX_FOR_BUILD}" CXXFLAGS="${CXXFLAGS_FOR_BUILD}" \
+ LD="${LD_FOR_BUILD}" LDFLAGS="${LDFLAGS_FOR_BUILD}" \
+ GMPINC="" CPPFLAGS="${CPPFLAGS_FOR_BUILD} -DGENERATOR_FILE" \
+ ${realsrcdir}/configure \
+ --enable-languages=${enable_languages-all} \
+ ${enable_obsolete+--enable-obsolete="$enable_obsolete"} \
+ ${enable_option_checking+--enable-option-checking="$enable_option_checking"} \
+ --target=$target_alias --host=$build_alias \
+ --build=$build_alias || exit # retaining $tempdir
+
+ # We just finished tests for the build machine, so rename
+ # the file auto-build.h in the gcc directory.
+ mv auto-host.h ../auto-build.h
+ cd ..
+ rm -rf $tempdir
+ build_auto=auto-build.h
+ HAVE_AUTO_BUILD=
+fi
+AC_SUBST(build_subdir)
+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.
+# put this back in temporarily.
+xm_file="auto-host.h ansidecl.h ${xm_file}"
+
+# --------
+# UNSORTED
+# --------
+
+changequote(,)dnl
+# Compile in configure arguments.
+if test -f configargs.h ; then
+ # Being re-configured.
+ gcc_config_arguments=`grep configuration_arguments configargs.h | sed -e 's/.*"\([^"]*\)".*/\1/'`
+ gcc_reconf_arguments=`echo "$gcc_config_arguments" | sed -e 's/^.*\( : (reconfigured) .*$\)/\1/'`
+ if [ "$gcc_reconf_arguments" != " : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS" ]; then
+ gcc_config_arguments="$gcc_config_arguments : (reconfigured) $TOPLEVEL_CONFIGURE_ARGUMENTS"
+ fi
+else
+ gcc_config_arguments="$TOPLEVEL_CONFIGURE_ARGUMENTS"
+fi
+
+# Double all backslashes and backslash all quotes to turn
+# gcc_config_arguments into a C string.
+sed -e 's/\\/\\\\/g; s/"/\\"/g' <<EOF >conftest.out
+$gcc_config_arguments
+EOF
+gcc_config_arguments_str=`cat conftest.out`
+rm -f conftest.out
+
+cat > configargs.h <<EOF
+/* Generated automatically. */
+static const char configuration_arguments[] = "$gcc_config_arguments_str";
+static const char thread_model[] = "$thread_file";
+
+static const struct {
+ const char *name, *value;
+} configure_default_options[] = $configure_default_options;
+EOF
+changequote([,])dnl
+
+changequote(,)dnl
+gcc_BASEVER=`cat $srcdir/BASE-VER`
+gcc_DEVPHASE=`cat $srcdir/DEV-PHASE`
+gcc_DATESTAMP=`cat $srcdir/DATESTAMP`
+if test -f $srcdir/REVISION ; then
+ gcc_REVISION=`cat $srcdir/REVISION`
+else
+ gcc_REVISION=""
+fi
+cat > plugin-version.h <<EOF
+#include "configargs.h"
+
+#define GCCPLUGIN_VERSION_MAJOR `echo $gcc_BASEVER | sed -e 's/^\([0-9]*\).*$/\1/'`
+#define GCCPLUGIN_VERSION_MINOR `echo $gcc_BASEVER | sed -e 's/^[0-9]*\.\([0-9]*\).*$/\1/'`
+#define GCCPLUGIN_VERSION_PATCHLEVEL `echo $gcc_BASEVER | sed -e 's/^[0-9]*\.[0-9]*\.\([0-9]*\)$/\1/'`
+#define GCCPLUGIN_VERSION (GCCPLUGIN_VERSION_MAJOR*1000 + GCCPLUGIN_VERSION_MINOR)
+
+static char basever[] = "$gcc_BASEVER";
+static char datestamp[] = "$gcc_DATESTAMP";
+static char devphase[] = "$gcc_DEVPHASE";
+static char revision[] = "$gcc_REVISION";
+
+/* FIXME plugins: We should make the version information more precise.
+ One way to do is to add a checksum. */
+
+static struct plugin_gcc_version gcc_version = {basever, datestamp,
+ devphase, revision,
+ configuration_arguments};
+EOF
+changequote([,])dnl
+
+# Determine what GCC version number to use in filesystem paths.
+GCC_BASE_VER
+
+# Internationalization
+ZW_GNU_GETTEXT_SISTER_DIR
+
+# If LIBINTL contains LIBICONV, then clear LIBICONV so we don't get
+# -liconv on the link line twice.
+case "$LIBINTL" in *$LIBICONV*)
+ LIBICONV= ;;
+esac
+
+AC_ARG_ENABLE(secureplt,
+[AS_HELP_STRING([--enable-secureplt],
+ [enable -msecure-plt by default for PowerPC])],
+[], [])
+
+AC_ARG_ENABLE(mingw-wildcard,
+[AS_HELP_STRING([--enable-mingw-wildcard],
+ [Set whether to expand wildcard on command-line.
+ Default to platform configuration])],
+[],[enable_mingw_wildcard=platform])
+AS_IF([test x"$enable_mingw_wildcard" != xplatform ],
+ [AC_DEFINE_UNQUOTED(MINGW_DOWILDCARD,
+ $(test x"$enable_mingw_wildcard" = xno; echo $?),
+ [Value to set mingw's _dowildcard to.])])
+
+AC_ARG_ENABLE(large-address-aware,
+[AS_HELP_STRING([--enable-large-address-aware],
+ [Link mingw executables with --large-address-aware])])
+AS_IF([test x"$enable_large_address_aware" = xyes],
+ [AC_DEFINE([MINGW_DEFAULT_LARGE_ADDR_AWARE], 1,
+ [Define if we should link mingw executables with --large-address-aware])])
+
+AC_ARG_ENABLE(leading-mingw64-underscores,
+ AS_HELP_STRING([--enable-leading-mingw64-underscores],
+ [enable leading underscores on 64 bit mingw targets]),
+ [],[])
+AS_IF([ test x"$enable_leading_mingw64_underscores" = xyes ],
+ [AC_DEFINE(USE_MINGW64_LEADING_UNDERSCORES, 1,
+ [Define if we should use leading underscore on 64 bit mingw targets])])
+
+AC_ARG_ENABLE(cld,
+[AS_HELP_STRING([--enable-cld], [enable -mcld by default for 32bit x86])], [],
+[enable_cld=no])
+
+AC_ARG_ENABLE(frame-pointer,
+[AS_HELP_STRING([--enable-frame-pointer],
+ [enable -fno-omit-frame-pointer by default for x86])], [],
+[
+case $target_os in
+linux* | gnu* | darwin[[8912]]* | cygwin* | mingw*)
+ # Enable -fomit-frame-pointer by default for these systems with DWARF2.
+ enable_frame_pointer=no
+ ;;
+*)
+ enable_frame_pointer=yes
+ ;;
+esac
+])
+
+case $target in
+i[[34567]]86-*-* | x86_64-*-*)
+ if test "x$enable_cld" = xyes; then
+ tm_defines="${tm_defines} USE_IX86_CLD=1"
+ fi
+ if test "x$enable_frame_pointer" = xyes; then
+ tm_defines="${tm_defines} USE_IX86_FRAME_POINTER=1"
+ fi
+ ;;
+esac
+
+# Windows32 Registry support for specifying GCC installation paths.
+AC_ARG_ENABLE(win32-registry,
+[AS_HELP_STRING([--disable-win32-registry],
+ [disable lookup of installation paths in the
+ Registry on Windows hosts])
+AS_HELP_STRING([--enable-win32-registry], [enable registry lookup (default)])
+AS_HELP_STRING([--enable-win32-registry=KEY],
+ [use KEY instead of GCC version as the last portion
+ of the registry key])],,)
+
+case $host_os in
+ win32 | pe | cygwin* | mingw32*)
+ if test "x$enable_win32_registry" != xno; then
+ AC_SEARCH_LIBS(RegOpenKeyExA, advapi32,, [enable_win32_registry=no])
+ fi
+
+ if test "x$enable_win32_registry" != xno; then
+ AC_DEFINE(ENABLE_WIN32_REGISTRY, 1,
+ [Define to 1 if installation paths should be looked up in the Windows
+ Registry. Ignored on non-Windows hosts.])
+
+ if test "x$enable_win32_registry" != xyes \
+ && test "x$enable_win32_registry" != x; then
+ AC_DEFINE_UNQUOTED(WIN32_REGISTRY_KEY, "$enable_win32_registry",
+ [Define to be the last component of the Windows registry key under which
+ to look for installation paths. The full key used will be
+ HKEY_LOCAL_MACHINE/SOFTWARE/Free Software Foundation/{WIN32_REGISTRY_KEY}.
+ The default is the GCC version number.])
+ fi
+ fi
+ ;;
+esac
+
+# Get an absolute path to the GCC top-level source directory
+holddir=`${PWDCMD-pwd}`
+cd $srcdir
+topdir=`${PWDCMD-pwd}`
+cd $holddir
+
+# Conditionalize the makefile for this host machine.
+xmake_file=
+for f in ${host_xmake_file}
+do
+ if test -f ${srcdir}/config/$f
+ then
+ xmake_file="${xmake_file} \$(srcdir)/config/$f"
+ fi
+done
+
+# Conditionalize the makefile for this target machine.
+tmake_file_=
+for f in ${tmake_file}
+do
+ if test -f ${srcdir}/config/$f
+ then
+ tmake_file_="${tmake_file_} \$(srcdir)/config/$f"
+ fi
+done
+tmake_file="${tmake_file_}${omp_device_property_tmake_file}"
+
+out_object_file=`basename $out_file .cc`.o
+common_out_file=default-common.cc
+common_out_object_file=`basename $common_out_file .cc`.o
+
+tm_file_list="options.h"
+tm_include_list="options.h insn-constants.h"
+for f in $tm_file; do
+ case $f in
+ ./* )
+ f=`echo $f | sed 's/^..//'`
+ tm_file_list="${tm_file_list} $f"
+ tm_include_list="${tm_include_list} $f"
+ ;;
+ defaults.h )
+ tm_file_list="${tm_file_list} \$(srcdir)/$f"
+ tm_include_list="${tm_include_list} $f"
+ ;;
+ * )
+ tm_file_list="${tm_file_list} \$(srcdir)/config/$f"
+ tm_include_list="${tm_include_list} config/$f"
+ ;;
+ esac
+done
+
+tm_p_file_list=
+tm_p_include_list=
+for f in $tm_p_file; do
+ case $f in
+ tm-preds.h )
+ tm_p_file_list="${tm_p_file_list} $f"
+ tm_p_include_list="${tm_p_include_list} $f"
+ ;;
+ * )
+ tm_p_file_list="${tm_p_file_list} \$(srcdir)/config/$f"
+ tm_p_include_list="${tm_p_include_list} config/$f"
+ esac
+done
+
+tm_d_file_list=
+tm_d_include_list="options.h insn-constants.h"
+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"
+ ;;
+ esac
+done
+
+xm_file_list=
+xm_include_list=
+for f in $xm_file; do
+ case $f in
+ ansidecl.h )
+ xm_file_list="${xm_file_list} \$(srcdir)/../include/$f"
+ xm_include_list="${xm_include_list} $f"
+ ;;
+ auto-host.h )
+ xm_file_list="${xm_file_list} $f"
+ xm_include_list="${xm_include_list} $f"
+ ;;
+ * )
+ xm_file_list="${xm_file_list} \$(srcdir)/config/$f"
+ xm_include_list="${xm_include_list} config/$f"
+ ;;
+ esac
+done
+
+host_xm_file_list=
+host_xm_include_list=
+for f in $host_xm_file; do
+ case $f in
+ ansidecl.h )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/../include/$f"
+ host_xm_include_list="${host_xm_include_list} $f"
+ ;;
+ auto-host.h )
+ host_xm_file_list="${host_xm_file_list} $f"
+ host_xm_include_list="${host_xm_include_list} $f"
+ ;;
+ * )
+ host_xm_file_list="${host_xm_file_list} \$(srcdir)/config/$f"
+ host_xm_include_list="${host_xm_include_list} config/$f"
+ ;;
+ esac
+done
+
+build_xm_file_list=
+for f in $build_xm_file; do
+ case $f in
+ ansidecl.h )
+ build_xm_file_list="${build_xm_file_list} \$(srcdir)/../include/$f"
+ build_xm_include_list="${build_xm_include_list} $f"
+ ;;
+ auto-build.h | auto-host.h )
+ build_xm_file_list="${build_xm_file_list} $f"
+ build_xm_include_list="${build_xm_include_list} $f"
+ ;;
+ * )
+ build_xm_file_list="${build_xm_file_list} \$(srcdir)/config/$f"
+ build_xm_include_list="${build_xm_include_list} config/$f"
+ ;;
+ esac
+done
+
+# Define macro CROSS_DIRECTORY_STRUCTURE in compilation if this is a
+# cross-compiler which does not use the native headers and libraries.
+# Also use all.cross instead of all.internal and adjust SYSTEM_HEADER_DIR.
+CROSS= AC_SUBST(CROSS)
+ALL=all.internal AC_SUBST(ALL)
+SYSTEM_HEADER_DIR='$(NATIVE_SYSTEM_HEADER_DIR)' AC_SUBST(SYSTEM_HEADER_DIR)
+BUILD_SYSTEM_HEADER_DIR=$SYSTEM_HEADER_DIR AC_SUBST(BUILD_SYSTEM_HEADER_DIR)
+
+if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x ||
+ test x$build != x$host || test "x$with_build_sysroot" != x; then
+ if test "x$with_build_sysroot" != x; then
+ BUILD_SYSTEM_HEADER_DIR=$with_build_sysroot'$${sysroot_headers_suffix}$(NATIVE_SYSTEM_HEADER_DIR)'
+ else
+ BUILD_SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ fi
+
+ if test x$host != x$target
+ then
+ CROSS="-DCROSS_DIRECTORY_STRUCTURE"
+ ALL=all.cross
+ SYSTEM_HEADER_DIR=$BUILD_SYSTEM_HEADER_DIR
+ elif test "x$TARGET_SYSTEM_ROOT" != x; then
+ SYSTEM_HEADER_DIR='$(CROSS_SYSTEM_HEADER_DIR)'
+ fi
+
+ if test "x$with_build_sysroot" != "x"; then
+ target_header_dir="${with_build_sysroot}${native_system_header_dir}"
+ elif test "x$with_sysroot" = x; then
+ target_header_dir="${test_exec_prefix}/${target_noncanonical}/sys-include"
+ elif test "x$with_sysroot" = xyes; then
+ target_header_dir="${test_exec_prefix}/${target_noncanonical}/sys-root${native_system_header_dir}"
+ else
+ target_header_dir="${with_sysroot}${native_system_header_dir}"
+ fi
+else
+ target_header_dir=${native_system_header_dir}
+fi
+
+# If this is a cross-compiler that does not
+# have its own set of headers then define
+# inhibit_libc
+
+# If this is using newlib, without having the headers available now,
+# then define inhibit_libc in LIBGCC2_CFLAGS.
+# This prevents libgcc2 from containing any code which requires libc
+# support.
+: ${inhibit_libc=false}
+if { { test x$host != x$target && test "x$with_sysroot" = x ; } ||
+ test x$with_newlib = xyes ; } &&
+ { test "x$with_headers" = xno || test ! -f "$target_header_dir/stdio.h"; } ; then
+ inhibit_libc=true
+fi
+AC_SUBST(inhibit_libc)
+
+# When building gcc with a cross-compiler, we need to adjust things so
+# that the generator programs are still built with the native compiler.
+# Also, we cannot run fixincludes.
+
+# These are the normal (build=host) settings:
+CC_FOR_BUILD='$(CC)' AC_SUBST(CC_FOR_BUILD)
+CXX_FOR_BUILD='$(CXX)' AC_SUBST(CXX_FOR_BUILD)
+BUILD_CFLAGS='$(ALL_CFLAGS)' AC_SUBST(BUILD_CFLAGS)
+BUILD_CXXFLAGS='$(ALL_CXXFLAGS)' AC_SUBST(BUILD_CXXFLAGS)
+BUILD_LDFLAGS='$(LDFLAGS)' AC_SUBST(BUILD_LDFLAGS)
+STMP_FIXINC=stmp-fixinc AC_SUBST(STMP_FIXINC)
+
+# And these apply if build != host, or we are generating coverage data
+if test x$build != x$host || test "x$coverage_flags" != x
+then
+ BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CFLAGS_FOR_BUILD)'
+ BUILD_CXXFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS-$@) $(CXXFLAGS_FOR_BUILD)'
+ BUILD_LDFLAGS='$(LDFLAGS_FOR_BUILD)'
+fi
+
+# Expand extra_headers to include complete path.
+# This substitutes for lots of t-* files.
+extra_headers_list=
+# Prepend $(srcdir)/config/${cpu_type}/ to every entry in extra_headers.
+for file in ${extra_headers} ; do
+ extra_headers_list="${extra_headers_list} \$(srcdir)/config/${cpu_type}/${file}"
+done
+
+# If use_gcc_tgmath is set, append ginclude/tgmath.h.
+if test x"$use_gcc_tgmath" = xyes
+then extra_headers_list="${extra_headers_list} \$(srcdir)/ginclude/tgmath.h"
+fi
+
+# Define collect2 in Makefile.
+case $host_can_use_collect2 in
+ no) collect2= ;;
+ *) collect2='collect2$(exeext)' ;;
+esac
+AC_SUBST([collect2])
+
+# Add a definition of USE_COLLECT2 if system wants one.
+case $use_collect2 in
+ no) use_collect2= ;;
+ "") ;;
+ *)
+ host_xm_defines="${host_xm_defines} USE_COLLECT2"
+ xm_defines="${xm_defines} USE_COLLECT2"
+ case $host_can_use_collect2 in
+ no)
+ AC_MSG_ERROR([collect2 is required but cannot be built on this system])
+ ;;
+ esac
+ ;;
+esac
+
+AC_DEFINE_UNQUOTED(LTOPLUGINSONAME,"${host_lto_plugin_soname}",
+[Define to the name of the LTO plugin DSO that must be
+ passed to the linker's -plugin=LIB option.])
+
+# ---------------------------
+# Assembler & linker features
+# ---------------------------
+
+# During stage 2, ld is actually gcc/collect-ld, which is a small script to
+# discern between when to use prev-ld/ld-new and when to use ld/ld-new.
+# However when ld-new is first executed from the build tree, libtool will
+# relink it as .libs/lt-ld-new, so that it can give it an RPATH that refers
+# to the build tree. While doing this we need to use the previous-stage
+# linker, or we have an infinite loop. The presence of a shell script as
+# ld/ld-new, and the fact that the script *uses ld itself*, is what confuses
+# the gcc/collect-ld script. So we need to know how libtool works, or
+# exec-tool will fail.
+
+m4_defun([_LT_CONFIG_COMMANDS], [])
+AC_PROG_LIBTOOL
+AC_SUBST(objdir)
+AC_SUBST(enable_fast_install)
+
+# Identify the assembler which will work hand-in-glove with the newly
+# built GCC, so that we can examine its features. This is the assembler
+# which will be driven by the driver program.
+#
+# If build != host, and we aren't building gas in-tree, we identify a
+# build->target assembler and hope that it will have the same features
+# as the host->target assembler we'll be using.
+gcc_cv_as_gas_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gas
+
+m4_pattern_allow([AS_FOR_TARGET])dnl
+AS_VAR_SET_IF(gcc_cv_as,, [
+if test -x "$DEFAULT_ASSEMBLER"; then
+ gcc_cv_as="$DEFAULT_ASSEMBLER"
+elif test -f $gcc_cv_as_gas_srcdir/configure.ac \
+ && test -f ../gas/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_as=../gas/as-new$build_exeext
+elif test -x as$build_exeext; then
+ # Build using assembler in the current directory.
+ gcc_cv_as=./as$build_exeext
+elif ( set dummy $AS_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_as="$AS_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_as, $AS_FOR_TARGET)
+fi])
+
+ORIGINAL_AS_FOR_TARGET=$gcc_cv_as
+AC_SUBST(ORIGINAL_AS_FOR_TARGET)
+case "$ORIGINAL_AS_FOR_TARGET" in
+ ./as | ./as$build_exeext) ;;
+ *) AC_CONFIG_FILES(as:exec-tool.in, [chmod +x as]) ;;
+esac
+
+default_ld=
+AC_ARG_ENABLE(ld,
+[[ --enable-ld[=ARG] build ld [ARG={default,yes,no}]]],
+[case "${enableval}" in
+ no)
+ default_ld=ld.gold
+ ;;
+ esac])
+
+install_gold_as_default=no
+AC_ARG_ENABLE(gold,
+[[ --enable-gold[=ARG] build gold [ARG={default,yes,no}]]],
+[case "${enableval}" in
+ default)
+ install_gold_as_default=yes
+ ;;
+ yes)
+ if test x${default_ld} != x; then
+ install_gold_as_default=yes
+ fi
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR([invalid --enable-gold argument])
+ ;;
+ esac])
+
+# Identify the linker which will work hand-in-glove with the newly
+# built GCC, so that we can examine its features. This is the linker
+# which will be driven by the driver program.
+#
+# If build != host, and we aren't building gas in-tree, we identify a
+# build->target linker and hope that it will have the same features
+# as the host->target linker we'll be using.
+gcc_cv_gld_major_version=
+gcc_cv_gld_minor_version=
+gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld
+gcc_cv_ld_gold_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gold
+gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd
+
+AS_VAR_SET_IF(gcc_cv_ld,, [
+if test -x "$DEFAULT_LINKER"; then
+ gcc_cv_ld="$DEFAULT_LINKER"
+elif test $install_gold_as_default = yes \
+ && test -f $gcc_cv_ld_gold_srcdir/configure.ac \
+ && test -f ../gold/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_ld=../gold/ld-new$build_exeext
+elif test -f $gcc_cv_ld_gld_srcdir/configure.ac \
+ && test -f ../ld/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_ld=../ld/ld-new$build_exeext
+elif test -x collect-ld$build_exeext; then
+ # Build using linker in the current directory.
+ gcc_cv_ld=./collect-ld$build_exeext
+elif ( set dummy $LD_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_ld="$LD_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_ld, $LD_FOR_TARGET)
+fi])
+
+ORIGINAL_PLUGIN_LD_FOR_TARGET=$gcc_cv_ld
+PLUGIN_LD_SUFFIX=`basename $gcc_cv_ld | sed -e "s,$target_alias-,,"`
+# if the PLUGIN_LD is set ld-new, just have it as ld
+# as that is the installed named.
+if test x$PLUGIN_LD_SUFFIX = xld-new \
+ || test x$PLUGIN_LD_SUFFIX = xcollect-ld ; then
+ PLUGIN_LD_SUFFIX=ld
+fi
+AC_ARG_WITH(plugin-ld,
+[AS_HELP_STRING([[--with-plugin-ld=[ARG]]], [specify the plugin linker])],
+[if test x"$withval" != x; then
+ ORIGINAL_PLUGIN_LD_FOR_TARGET="$withval"
+ PLUGIN_LD_SUFFIX="$withval"
+ fi])
+AC_SUBST(ORIGINAL_PLUGIN_LD_FOR_TARGET)
+AC_DEFINE_UNQUOTED(PLUGIN_LD_SUFFIX, "$PLUGIN_LD_SUFFIX", [Specify plugin linker])
+
+# Check to see if we are using gold instead of ld
+AC_MSG_CHECKING(whether we are using gold)
+ld_is_gold=no
+if test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --version 2>/dev/null | sed 1q \
+ | grep "GNU gold" > /dev/null; then
+ ld_is_gold=yes
+ fi
+fi
+AC_MSG_RESULT($ld_is_gold)
+
+# Check to see if we are using mold instead of ld
+AC_MSG_CHECKING(whether we are using mold)
+ld_is_mold=no
+if test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --version 2>/dev/null | sed 1q \
+ | grep "mold" > /dev/null; then
+ ld_is_mold=yes
+ fi
+fi
+AC_MSG_RESULT($ld_is_mold)
+
+
+AC_MSG_CHECKING(gold linker with split stack support as non default)
+# Check to see if default ld is not gold, but gold is
+# available and has support for split stack. If gcc was configured
+# with gold then no checking is done.
+#
+if test x$ld_is_gold = xno && which ${gcc_cv_ld}.gold >/dev/null 2>&1; then
+
+# For platforms other than powerpc64*, enable as appropriate.
+
+ gold_non_default=no
+ ld_gold=`which ${gcc_cv_ld}.gold`
+# Make sure this gold has minimal split stack support
+ if $ld_gold --help 2>/dev/null | grep split-stack-adjust-size >/dev/null 2>&1; then
+ ld_vers=`$ld_gold --version | sed 1q`
+ gold_vers=`echo $ld_vers | sed -n \
+ -e 's,^[[^)]]*[[ ]]\([[0-9]][[0-9]]*\.[[0-9]][[0-9]]*[[^)]]*\)) .*$,\1,p'`
+ case $target in
+# check that the gold version contains the complete split stack support
+# on powerpc64 big and little endian
+ powerpc64*-*-*)
+ case "$gold_vers" in
+ 2.25.[[1-9]]*|2.2[[6-9]][[.0-9]]*|2.[[3-9]][[.0-9]]*|[[3-9]].[[.0-9]]*) gold_non_default=yes
+ ;;
+ *) gold_non_default=no
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ if test $gold_non_default = yes; then
+ AC_DEFINE(HAVE_GOLD_NON_DEFAULT_SPLIT_STACK, 1,
+ [Define if the gold linker supports split stack and is available as a non-default])
+ fi
+fi
+AC_MSG_RESULT($gold_non_default)
+
+ORIGINAL_LD_FOR_TARGET=$gcc_cv_ld
+AC_SUBST(ORIGINAL_LD_FOR_TARGET)
+case "$ORIGINAL_LD_FOR_TARGET" in
+ ./collect-ld | ./collect-ld$build_exeext) ;;
+ *) AC_CONFIG_FILES(collect-ld:exec-tool.in, [chmod +x collect-ld]) ;;
+esac
+
+AC_MSG_CHECKING(what linker to use)
+if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext \
+ || test "$gcc_cv_ld" = ../gold/ld-new$build_exeext; then
+ # Single tree build which includes ld. We want to prefer it
+ # over whatever linker top-level may have detected, since
+ # we'll use what we're building after installation anyway.
+ AC_MSG_RESULT(newly built ld)
+ in_tree_ld=yes
+ in_tree_ld_is_elf=no
+ if (grep 'EMUL = .*elf' ../ld/Makefile \
+ || grep 'EMUL = .*linux' ../ld/Makefile \
+ || grep 'EMUL = .*lynx' ../ld/Makefile) > /dev/null; then
+ in_tree_ld_is_elf=yes
+ elif test "$ld_is_gold" = yes; then
+ in_tree_ld_is_elf=yes
+ fi
+ for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.ac $gcc_cv_ld_gld_srcdir/Makefile.in
+ do
+changequote(,)dnl
+ gcc_cv_gld_version=`sed -n -e 's/^[ ]*VERSION=[^0-9A-Za-z_]*\([0-9]*\.[0-9]*.*\)/VERSION=\1/p' < $f`
+ if test x$gcc_cv_gld_version != x; then
+ break
+ fi
+ done
+ case $gcc_cv_gld_version in
+ VERSION=[0-9]*) ;;
+changequote([,])dnl
+ *) AC_MSG_ERROR([[cannot find version of in-tree linker]]) ;;
+changequote(,)dnl
+ esac
+ gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"`
+ gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"`
+changequote([,])dnl
+ ORIGINAL_LD_BFD_FOR_TARGET=../ld/ld-new$build_exeext
+ ORIGINAL_LD_GOLD_FOR_TARGET=../gold/ld-new$build_exeext
+else
+ AC_MSG_RESULT($gcc_cv_ld)
+ in_tree_ld=no
+ gcc_cvs_ld_program=false # `dirname $gcc_cv_ld`/`basename $gcc_cv_ld $host_exeext`
+ ORIGINAL_LD_BFD_FOR_TARGET=${gcc_cvs_ld_program}.bfd$host_exeext
+ ORIGINAL_LD_GOLD_FOR_TARGET=${gcc_cvs_ld_program}.gold$host_exeext
+fi
+
+AC_SUBST(ORIGINAL_LD_BFD_FOR_TARGET)
+AC_SUBST(ORIGINAL_LD_GOLD_FOR_TARGET)
+
+# Figure out what nm we will be using.
+gcc_cv_binutils_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/binutils
+AS_VAR_SET_IF(gcc_cv_nm,, [
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ gcc_cv_nm=../binutils/nm-new$build_exeext
+elif test -x nm$build_exeext; then
+ gcc_cv_nm=./nm$build_exeext
+elif ( set dummy $NM_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_nm="$NM_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_nm, $NM_FOR_TARGET)
+fi])
+
+AC_MSG_CHECKING(what nm to use)
+if test "$gcc_cv_nm" = ../binutils/nm-new$build_exeext; then
+ # Single tree build which includes binutils.
+ AC_MSG_RESULT(newly built nm)
+ in_tree_nm=yes
+else
+ AC_MSG_RESULT($gcc_cv_nm)
+ in_tree_nm=no
+fi
+
+ORIGINAL_NM_FOR_TARGET=$gcc_cv_nm
+AC_SUBST(ORIGINAL_NM_FOR_TARGET)
+case "$ORIGINAL_NM_FOR_TARGET" in
+ ./nm | ./nm$build_exeext) ;;
+ *) AC_CONFIG_FILES(nm:exec-tool.in, [chmod +x nm]) ;;
+esac
+
+
+# Figure out what objdump we will be using.
+AS_VAR_SET_IF(gcc_cv_objdump,, [
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_objdump=../binutils/objdump$build_exeext
+elif test -x objdump$build_exeext; then
+ gcc_cv_objdump=./objdump$build_exeext
+elif ( set dummy $OBJDUMP_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_objdump="$OBJDUMP_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_objdump, $OBJDUMP_FOR_TARGET)
+fi])
+
+AC_MSG_CHECKING(what objdump to use)
+if test "$gcc_cv_objdump" = ../binutils/objdump$build_exeext; then
+ # Single tree build which includes binutils.
+ AC_MSG_RESULT(newly built objdump)
+elif test x$gcc_cv_objdump = x; then
+ AC_MSG_RESULT(not found)
+else
+ AC_MSG_RESULT($gcc_cv_objdump)
+fi
+
+# Figure out what readelf we will be using.
+AS_VAR_SET_IF(gcc_cv_readelf,, [
+if test -f $gcc_cv_binutils_srcdir/configure.ac \
+ && test -f ../binutils/Makefile \
+ && test x$build = x$host; then
+ # Single tree build which includes binutils.
+ gcc_cv_readelf=../binutils/readelf$build_exeext
+elif test -x readelf$build_exeext; then
+ gcc_cv_readelf=./readelf$build_exeext
+elif ( set dummy $READELF_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_readelf="$READELF_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_readelf, $READELF_FOR_TARGET)
+fi])
+
+AC_MSG_CHECKING(what readelf to use)
+if test "$gcc_cv_readelf" = ../binutils/readelf$build_exeext; then
+ # Single tree build which includes binutils.
+ AC_MSG_RESULT(newly built readelf)
+elif test x$gcc_cv_readelf = x; then
+ AC_MSG_RESULT(not found)
+else
+ AC_MSG_RESULT($gcc_cv_readelf)
+fi
+
+# Figure out what otool we will be using.
+AS_VAR_SET_IF(gcc_cv_otool,, [
+if test -x otool$build_exeext; then
+ gcc_cv_otool=./otool$build_exeext
+elif ( set dummy $OTOOL_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_otool="$OTOOL_FOR_TARGET"
+else
+ AC_PATH_PROG(gcc_cv_otool, $OTOOL_FOR_TARGET)
+fi])
+
+AC_MSG_CHECKING(what otool to use)
+if test x$gcc_cv_otool = x; then
+ AC_MSG_RESULT(not found)
+else
+ AC_MSG_RESULT($gcc_cv_otool)
+fi
+
+# Figure out the dsymutil we will use.
+AS_VAR_SET_IF(gcc_cv_dsymutil,, [
+if test -x "$DEFAULT_DSYMUTIL"; then
+ gcc_cv_dsymutil="$DEFAULT_DSYMUTIL"
+elif test -x dsymutil$build_exeext; then
+ gcc_cv_dsymutil=./dsymutil$build_exeext
+elif ( set dummy $DSYMUTIL_FOR_TARGET; test -x $[2] ); then
+ gcc_cv_dsymutil=$DSYMUTIL_FOR_TARGET
+elif ( set dummy $DSYMUTIL; test -x $[2] ); then
+ gcc_cv_dsymutil=$DSYMUTIL
+else
+ AC_PATH_PROG(gcc_cv_dsymutil, $DSYMUTIL_FOR_TARGET)
+fi])
+
+ORIGINAL_DSYMUTIL_FOR_TARGET=$gcc_cv_dsymutil
+AC_SUBST(ORIGINAL_DSYMUTIL_FOR_TARGET)
+case "$ORIGINAL_DSYMUTIL_FOR_TARGET" in
+ ./dsymutil | ./dsymutil$build_exeext) ;;
+ *) AC_CONFIG_FILES(dsymutil:exec-tool.in, [chmod +x dsymutil]) ;;
+esac
+
+# Figure out what assembler alignment features are present.
+gcc_GAS_CHECK_FEATURE([.balign and .p2align], gcc_cv_as_balign_and_p2align,,
+[.balign 4
+.p2align 2],,
+[AC_DEFINE(HAVE_GAS_BALIGN_AND_P2ALIGN, 1,
+ [Define if your assembler supports .balign and .p2align.])])
+
+gcc_GAS_CHECK_FEATURE([.p2align with maximum skip], gcc_cv_as_max_skip_p2align,,
+ [.p2align 4,,7],,
+[AC_DEFINE(HAVE_GAS_MAX_SKIP_P2ALIGN, 1,
+ [Define if your assembler supports specifying the maximum number
+ of bytes to skip when using the GAS .p2align command.])])
+
+gcc_GAS_CHECK_FEATURE([.literal16], gcc_cv_as_literal16,,
+ [.literal16],,
+[AC_DEFINE(HAVE_GAS_LITERAL16, 1,
+ [Define if your assembler supports .literal16.])])
+
+gcc_GAS_CHECK_FEATURE([working .subsection -1], gcc_cv_as_subsection_m1,,
+ [conftest_label1: .word 0
+.subsection -1
+conftest_label2: .word 0
+.previous],
+ [if test x$gcc_cv_nm != x; then
+ $gcc_cv_nm conftest.o | grep conftest_label1 > conftest.nm1
+ $gcc_cv_nm conftest.o | grep conftest_label2 | sed -e 's/label2/label1/' > conftest.nm2
+ if cmp conftest.nm1 conftest.nm2 > /dev/null 2>&1
+ then :
+ else gcc_cv_as_subsection_m1=yes
+ fi
+ rm -f conftest.nm1 conftest.nm2
+ fi],
+ [AC_DEFINE(HAVE_GAS_SUBSECTION_ORDERING, 1,
+ [Define if your assembler supports .subsection and .subsection -1 starts
+ emitting at the beginning of your section.])])
+
+gcc_GAS_CHECK_FEATURE([.weak], gcc_cv_as_weak,,
+ [ .weak foobar],,
+[AC_DEFINE(HAVE_GAS_WEAK, 1, [Define if your assembler supports .weak.])])
+
+gcc_GAS_CHECK_FEATURE([.weakref], gcc_cv_as_weakref,,
+ [ .weakref foobar, barfnot],,
+[AC_DEFINE(HAVE_GAS_WEAKREF, 1, [Define if your assembler supports .weakref.])])
+
+gcc_GAS_CHECK_FEATURE([.nsubspa comdat], gcc_cv_as_nsubspa_comdat,,
+ [ .SPACE $TEXT$
+ .NSUBSPA $CODE$,COMDAT],,
+[AC_DEFINE(HAVE_GAS_NSUBSPA_COMDAT, 1, [Define if your assembler supports .nsubspa comdat option.])])
+
+# .hidden needs to be supported in both the assembler and the linker,
+# because GNU LD versions before 2.12.1 have buggy support for STV_HIDDEN.
+# This is irritatingly difficult to feature test for; we have to check the
+# date string after the version number. If we've got an in-tree
+# ld, we don't know its patchlevel version, so we set the baseline at 2.13
+# to be safe.
+# The gcc_GAS_CHECK_FEATURE call just sets a cache variable.
+case "${target}" in
+ *-*-aix*)
+ conftest_s=' .globl foobar,hidden'
+ ;;
+ *)
+ conftest_s=' .hidden foobar
+foobar:'
+ ;;
+esac
+gcc_GAS_CHECK_FEATURE([.hidden], gcc_cv_as_hidden,, [$conftest_s])
+case "${target}" in
+ *-*-darwin*)
+ # Darwin as has some visibility support, though with a different syntax.
+ gcc_cv_as_hidden=yes
+ ;;
+esac
+
+# gnu_indirect_function type is an extension proposed at
+# http://groups.google/com/group/generic-abi/files. It allows dynamic runtime
+# selection of function implementation
+AC_ARG_ENABLE(gnu-indirect-function,
+ [AS_HELP_STRING([--enable-gnu-indirect-function],
+ [enable the use of the @gnu_indirect_function to glibc systems])],
+ [case $enable_gnu_indirect_function in
+ yes | no) ;;
+ *) AC_MSG_ERROR(['$enable_gnu_indirect_function' is an invalid value for --enable-gnu-indirect-function.
+Valid choices are 'yes' and 'no'.]) ;;
+ esac],
+ [enable_gnu_indirect_function="$default_gnu_indirect_function"])
+
+case "${target}" in
+ riscv*-*-linux*)
+ AC_MSG_CHECKING(linker ifunc IRELATIVE support)
+ cat > conftest.s <<EOF
+ .text
+ .type foo_resolver, @function
+foo_resolver:
+ ret
+ .size foo_resolver, .-foo_resolver
+
+ .globl foo
+ .type foo, %gnu_indirect_function
+ .set foo, foo_resolver
+
+ .globl bar
+ .type bar, @function
+bar:
+ call foo
+ ret
+ .size bar, .-bar
+EOF
+ if test x$gcc_cv_as != x \
+ && test x$gcc_cv_ld != x \
+ && test x$gcc_cv_readelf != x \
+ && $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1 \
+ && $gcc_cv_readelf --relocs --wide conftest \
+ | grep R_RISCV_IRELATIVE > /dev/null 2>&1; then
+ enable_gnu_indirect_function=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ AC_MSG_RESULT($enable_gnu_indirect_function)
+ ;;
+esac
+
+gif=`if test x$enable_gnu_indirect_function = xyes; then echo 1; else echo 0; fi`
+AC_DEFINE_UNQUOTED(HAVE_GNU_INDIRECT_FUNCTION, $gif,
+[Define if your system supports gnu indirect functions.])
+
+
+changequote(,)dnl
+if test $in_tree_ld != yes ; then
+ ld_ver=`$gcc_cv_ld --version 2>/dev/null | sed 1q`
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ if test x"$ld_is_gold" = xyes; then
+ # GNU gold --version looks like this:
+ #
+ # GNU gold (GNU Binutils 2.21.51.20110225) 1.11
+ #
+ # We extract the binutils version which is more familiar and specific
+ # than the gold version.
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
+ else
+ # GNU ld --version looks like this:
+ #
+ # GNU ld (GNU Binutils) 2.21.51.20110225
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
+ fi
+ ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)\(-*\)\([01][0-9]\)\2\([0-3][0-9]\).*$,\1\3\4,p'`
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ ld_vers_patch=`expr "$ld_vers" : '[0-9]*\.[0-9]*\.\([0-9]*\)'`
+ else
+ case "${target}" in
+ *-*-solaris2*)
+ # Solaris 2 ld -V output looks like this for a regular version:
+ #
+ # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1699
+ #
+ # but test versions add stuff at the end:
+ #
+ # ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.1701:onnv-ab196087-6931056-03/25/10
+ #
+ # ld and ld.so.1 are guaranteed to be updated in lockstep, so ld version
+ # numbers can be used in ld.so.1 feature checks even if a different
+ # linker is configured.
+ ld_ver=`$gcc_cv_ld -V 2>&1`
+ if echo "$ld_ver" | grep 'Solaris Link Editors' > /dev/null; then
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^.*: 5\.[0-9][0-9]*-\([0-9]\.[0-9][0-9]*\).*$,\1,p'`
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ fi
+ ;;
+ esac
+ fi
+fi
+changequote([,])dnl
+
+AC_CACHE_CHECK(linker for .hidden support, gcc_cv_ld_hidden,
+[[if test $in_tree_ld = yes ; then
+ gcc_cv_ld_hidden=no
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 13 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_hidden=yes
+ fi
+else
+ gcc_cv_ld_hidden=yes
+ if test x"$ld_is_gold" = xyes; then
+ :
+ elif test x"$ld_is_mold" = xyes; then
+ :
+ elif echo "$ld_ver" | grep GNU > /dev/null; then
+ if test 0"$ld_date" -lt 20020404; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2002-04-04, fail
+ gcc_cv_ld_hidden=no
+ elif test -z "$ld_vers"; then
+ # If there was no date string nor ld version number, something is wrong
+ gcc_cv_ld_hidden=no
+ else
+ test -z "$ld_vers_patch" && ld_vers_patch=0
+ if test "$ld_vers_major" -lt 2; then
+ gcc_cv_ld_hidden=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 12; then
+ gcc_cv_ld_hidden="no"
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -eq 12 -a "$ld_vers_patch" -eq 0; then
+ gcc_cv_ld_hidden=no
+ fi
+ fi
+ fi
+ else
+ case "${target}" in
+ *-*-aix[789]*)
+ gcc_cv_ld_hidden=yes
+ ;;
+ *-*-darwin*)
+ # Darwin ld has some visibility support.
+ gcc_cv_ld_hidden=yes
+ ;;
+ hppa64*-*-hpux* | ia64*-*-hpux*)
+ gcc_cv_ld_hidden=yes
+ ;;
+ *-*-solaris2*)
+ # Support for .hidden in Sun ld appeared in Solaris 9 FCS, but
+ # .symbolic was only added in Solaris 9 12/02.
+ gcc_cv_ld_hidden=yes
+ ;;
+ *)
+ gcc_cv_ld_hidden=no
+ ;;
+ esac
+ fi
+fi]])
+libgcc_visibility=no
+AC_SUBST(libgcc_visibility)
+GCC_TARGET_TEMPLATE([HAVE_GAS_HIDDEN])
+if test $gcc_cv_as_hidden = yes && test $gcc_cv_ld_hidden = yes; then
+ libgcc_visibility=yes
+ AC_DEFINE(HAVE_GAS_HIDDEN, 1,
+ [Define if your assembler and linker support .hidden.])
+fi
+
+AC_MSG_CHECKING(linker read-only and read-write section mixing)
+gcc_cv_ld_ro_rw_mix=unknown
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ echo '.section myfoosect, "a"' > conftest1.s
+ echo '.section myfoosect, "aw"' > conftest2.s
+ echo '.byte 1' >> conftest2.s
+ echo '.section myfoosect, "a"' > conftest3.s
+ echo '.byte 0' >> conftest3.s
+ if $gcc_cv_as -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_as -o conftest3.o conftest3.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -shared -o conftest1.so conftest1.o \
+ conftest2.o conftest3.o > /dev/null 2>&1; then
+ gcc_cv_ld_ro_rw_mix=`$gcc_cv_objdump -h conftest1.so \
+ | sed -e '/myfoosect/!d' -e N`
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep CONTENTS > /dev/null; then
+ if echo "$gcc_cv_ld_ro_rw_mix" | grep READONLY > /dev/null; then
+ gcc_cv_ld_ro_rw_mix=read-only
+ else
+ gcc_cv_ld_ro_rw_mix=read-write
+ fi
+ fi
+ fi
+changequote(,)dnl
+ rm -f conftest.* conftest[123].*
+changequote([,])dnl
+fi
+if test x$gcc_cv_ld_ro_rw_mix = xread-write; then
+ AC_DEFINE(HAVE_LD_RO_RW_SECTION_MIXING, 1,
+ [Define if your linker links a mix of read-only
+ and read-write sections into a read-write section.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_ro_rw_mix)
+
+gcc_AC_INITFINI_ARRAY
+
+# Check if we have .[us]leb128, and support symbol arithmetic with it.
+# Older versions of GAS and some non-GNU assemblers, have a bugs handling
+# these directives, even when they appear to accept them.
+gcc_GAS_CHECK_FEATURE([.sleb128 and .uleb128], gcc_cv_as_leb128,,
+[ .data
+ .uleb128 L2 - L1
+L1:
+ .uleb128 1280
+ .sleb128 -1010
+L2:
+ .uleb128 0x8000000000000000
+],
+[[
+if test "x$gcc_cv_objdump" != x; then
+ if $gcc_cv_objdump -s conftest.o 2>/dev/null \
+ | grep '04800a8e 78808080 80808080 808001' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+elif test "x$gcc_cv_otool" != x; then
+ if $gcc_cv_otool -d conftest.o 2>/dev/null \
+ | grep '04 80 0a 8e 78 80 80 80 80 80 80 80 80 80 01' >/dev/null; then
+ gcc_cv_as_leb128=yes
+ fi
+else
+ # play safe, assume the assembler is broken.
+ :
+fi
+]],
+ [AC_DEFINE(HAVE_AS_LEB128, 1,
+ [Define if your assembler supports .sleb128 and .uleb128.])],
+ [AC_DEFINE(HAVE_AS_LEB128, 0,
+ [Define if your assembler supports .sleb128 and .uleb128.])])
+
+# Determine if an .eh_frame section is read-only.
+gcc_fn_eh_frame_ro () {
+ $gcc_cv_as $1 -o conftest.o conftest.s > /dev/null 2>&1 && \
+ $gcc_cv_objdump -h conftest.o 2>/dev/null | \
+ sed -e '/.eh_frame/!d' -e N | grep READONLY > /dev/null
+}
+
+# Check if we have assembler support for unwind directives.
+gcc_GAS_CHECK_FEATURE([cfi directives], gcc_cv_as_cfi_directive,,
+[ .text
+ .cfi_startproc
+ .cfi_offset 0, 0
+ .cfi_same_value 1
+ .cfi_def_cfa 1, 2
+ .cfi_escape 1, 2, 3, 4, 5
+ .cfi_endproc],
+[case "$target" in
+ *-*-solaris*)
+ # If the linker used on Solaris (like Sun ld) isn't capable of merging
+ # read-only and read-write sections, we need to make sure that the
+ # assembler used emits read-write .eh_frame sections.
+ if test "x$gcc_cv_ld_ro_rw_mix" = xread-write; then
+ gcc_cv_as_cfi_directive=yes
+ elif test "x$gcc_cv_objdump" = x; then
+ # No objdump, err on the side of caution.
+ gcc_cv_as_cfi_directive=no
+ else
+ if test x$gas = xyes; then
+ as_32_opt="--32"
+ as_64_opt="--64"
+ else
+ as_32_opt="-m32"
+ as_64_opt="-m64"
+ fi
+ case "$target" in
+ sparc*-*-solaris2.*)
+ # On Solaris/SPARC, .eh_frame sections should always be read-write.
+ if gcc_fn_eh_frame_ro $as_32_opt \
+ || gcc_fn_eh_frame_ro $as_64_opt; then
+ gcc_cv_as_cfi_directive=no
+ else
+ gcc_cv_as_cfi_directive=yes
+ fi
+ ;;
+ i?86-*-solaris2.* | x86_64-*-solaris2.*)
+ # On Solaris/x86, make sure that GCC and assembler agree on using
+ # read-only .eh_frame sections for 64-bit.
+ if gcc_fn_eh_frame_ro $as_32_opt; then
+ gcc_cv_as_cfi_directive=no
+ elif gcc_fn_eh_frame_ro $as_64_opt; then
+ gcc_cv_as_cfi_directive=yes
+ else
+ gcc_cv_as_cfi_directive=no
+ fi
+ ;;
+ esac
+ fi
+ ;;
+ *-*-*)
+ gcc_cv_as_cfi_directive=yes
+ ;;
+esac])
+if test $gcc_cv_as_cfi_directive = yes && test x$gcc_cv_objdump != x; then
+gcc_GAS_CHECK_FEATURE([working cfi advance], gcc_cv_as_cfi_advance_working,,
+[ .text
+ .cfi_startproc
+ .cfi_adjust_cfa_offset 64
+ .skip 75040, 0
+ .cfi_adjust_cfa_offset 128
+ .cfi_endproc],
+[[
+if $gcc_cv_objdump -Wf conftest.o 2>/dev/null \
+ | grep 'DW_CFA_advance_loc[24]:[ ][ ]*75040[ ]' >/dev/null; then
+ gcc_cv_as_cfi_advance_working=yes
+fi
+]])
+else
+ # no objdump, err on the side of caution
+ gcc_cv_as_cfi_advance_working=no
+fi
+GCC_TARGET_TEMPLATE(HAVE_GAS_CFI_DIRECTIVE)
+AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_DIRECTIVE,
+ [`if test $gcc_cv_as_cfi_directive = yes \
+ && test $gcc_cv_as_cfi_advance_working = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports CFI directives.])
+
+GCC_TARGET_TEMPLATE(HAVE_GAS_CFI_PERSONALITY_DIRECTIVE)
+gcc_GAS_CHECK_FEATURE([cfi personality directive],
+ gcc_cv_as_cfi_personality_directive,,
+[ .text
+ .cfi_startproc
+ .cfi_personality 0, symbol
+ .cfi_endproc])
+AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_PERSONALITY_DIRECTIVE,
+ [`if test $gcc_cv_as_cfi_personality_directive = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports .cfi_personality.])
+
+gcc_GAS_CHECK_FEATURE([cfi sections directive],
+ gcc_cv_as_cfi_sections_directive,,
+[ .text
+ .cfi_sections .debug_frame, .eh_frame
+ .cfi_startproc
+ .cfi_endproc],
+[case $target_os in
+ win32 | pe | cygwin* | mingw32*)
+ # Need to check that we generated the correct relocation for the
+ # .debug_frame section. This was fixed for binutils 2.21.
+ gcc_cv_as_cfi_sections_directive=no
+ if test "x$gcc_cv_objdump" != x; then
+ if $gcc_cv_objdump -j .debug_frame -r conftest.o 2>/dev/null | \
+ grep secrel > /dev/null; then
+ gcc_cv_as_cfi_sections_directive=yes
+ fi
+ fi
+ ;;
+ *)
+ gcc_cv_as_cfi_sections_directive=yes
+ ;;
+esac])
+GCC_TARGET_TEMPLATE(HAVE_GAS_CFI_SECTIONS_DIRECTIVE)
+AC_DEFINE_UNQUOTED(HAVE_GAS_CFI_SECTIONS_DIRECTIVE,
+ [`if test $gcc_cv_as_cfi_sections_directive = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports .cfi_sections.])
+
+# GAS versions up to and including 2.11.0 may mis-optimize
+# .eh_frame data.
+gcc_GAS_CHECK_FEATURE(eh_frame optimization, gcc_cv_as_eh_frame,,
+[ .text
+.LFB1:
+ .4byte 0
+.L1:
+ .4byte 0
+.LFE1:
+ .section .eh_frame,"aw",@progbits
+__FRAME_BEGIN__:
+ .4byte .LECIE1-.LSCIE1
+.LSCIE1:
+ .4byte 0x0
+ .byte 0x1
+ .ascii "z\0"
+ .byte 0x1
+ .byte 0x78
+ .byte 0x1a
+ .byte 0x0
+ .byte 0x4
+ .4byte 1
+ .p2align 1
+.LECIE1:
+.LSFDE1:
+ .4byte .LEFDE1-.LASFDE1
+.LASFDE1:
+ .4byte .LASFDE1-__FRAME_BEGIN__
+ .4byte .LFB1
+ .4byte .LFE1-.LFB1
+ .byte 0x4
+ .4byte .LFE1-.LFB1
+ .byte 0x4
+ .4byte .L1-.LFB1
+.LEFDE1:],
+[ dnl # For autoconf 2.5x, must protect trailing spaces with @&t@.
+cat > conftest.lit <<EOF
+ 0000 10000000 00000000 017a0001 781a0004 .........z..x...
+ 0010 01000000 12000000 18000000 00000000 ................
+ 0020 08000000 04080000 0044 .........D @&t@
+EOF
+cat > conftest.big <<EOF
+ 0000 00000010 00000000 017a0001 781a0004 .........z..x...
+ 0010 00000001 00000012 00000018 00000000 ................
+ 0020 00000008 04000000 0844 .........D @&t@
+EOF
+ # If the assembler didn't choke, and we can objdump,
+ # and we got the correct data, then succeed.
+ # The text in the here-document typically retains its unix-style line
+ # endings, while the output of objdump will use host line endings.
+ # Therefore, use diff -b for the comparisons.
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -s -j .eh_frame conftest.o 2>/dev/null \
+ | tail -3 > conftest.got \
+ && { diff -b conftest.lit conftest.got > /dev/null 2>&1 \
+ || diff -b conftest.big conftest.got > /dev/null 2>&1; }
+ then
+ gcc_cv_as_eh_frame=yes
+ elif AC_TRY_COMMAND($gcc_cv_as -o conftest.o --traditional-format /dev/null); then
+ gcc_cv_as_eh_frame=buggy
+ else
+ # Uh oh, what do we do now?
+ gcc_cv_as_eh_frame=no
+ fi])
+
+if test $gcc_cv_as_eh_frame = buggy; then
+ AC_DEFINE(USE_AS_TRADITIONAL_FORMAT, 1,
+ [Define if your assembler mis-optimizes .eh_frame data.])
+fi
+
+# Test if the assembler supports the section flag 'e' or #exclude for
+# specifying an excluded section.
+gcc_GAS_CHECK_FEATURE([section exclude flag], gcc_cv_as_section_exclude_e,
+ [--fatal-warnings],
+ [.section foo1,"e"
+ .byte 0,0,0,0])
+if test $gcc_cv_as_section_exclude_e = no; then
+ case "${target}" in
+ # Solaris as uses #exclude instead.
+ *-*-solaris2*)
+ case "${target}" in
+ sparc*-*-solaris2*)
+ conftest_s='.section "foo1", #exclude'
+ ;;
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ conftest_s='.section foo1, #exclude'
+ ;;
+ esac
+ ;;
+ esac
+ gcc_GAS_CHECK_FEATURE([section exclude flag], gcc_cv_as_section_exclude_hash,,
+ [$conftest_s
+ .byte 0,0,0,0])
+fi
+AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE,
+ [`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`],
+[Define if your assembler supports specifying the exclude section flag.])
+
+# Test if the assembler supports the section flag 'R' for specifying
+# section with SHF_GNU_RETAIN.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'R', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_shf_gnu_retain=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'R' flag], gcc_cv_as_shf_gnu_retain,
+ [--fatal-warnings],
+ [.section .foo,"awR",%progbits
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
+ [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
+
+# Test if the assembler supports the section flag 'o' for specifying
+# section with link-order.
+case "${target}" in
+ # Solaris may use GNU assembler with Solairs ld. Even if GNU
+ # assembler supports the section flag 'o', it doesn't mean that
+ # Solairs ld supports it.
+ *-*-solaris2*)
+ gcc_cv_as_section_link_order=no
+ ;;
+ *)
+ gcc_GAS_CHECK_FEATURE([section 'o' flag], gcc_cv_as_section_link_order,
+ [--fatal-warnings],
+ [.section .foo,"a"
+.byte 0
+.section __patchable_function_entries,"awo",%progbits,.foo
+.byte 0])
+ ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_LINK_ORDER,
+ [`if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler supports 'o' flag in .section directive.])
+
+gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
+ [--fatal-warnings],
+ [.section .rodata.str, "aMS", @progbits, 1])
+if test $gcc_cv_as_shf_merge = no; then
+ gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
+ [--fatal-warnings],
+ [.section .rodata.str, "aMS", %progbits, 1])
+fi
+AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_MERGE,
+ [`if test $gcc_cv_as_shf_merge = yes; then echo 1; else echo 0; fi`],
+[Define 0/1 if your assembler supports marking sections with SHF_MERGE flag.])
+
+gcc_cv_ld_aligned_shf_merge=yes
+case "$target" in
+ # SHF_MERGE support is broken in Solaris ld up to Solaris 11.3/SPARC for
+ # alignment > 1.
+ sparc*-*-solaris2.11*)
+ if test x"$gnu_ld" = xno \
+ && test "$ld_vers_major" -lt 2 && test "$ld_vers_minor" -lt 3159; then
+ gcc_cv_ld_aligned_shf_merge=no
+ fi
+ ;;
+esac
+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],
+ [.section .text,"axG",@progbits,.foo,comdat])
+if test $gcc_cv_as_comdat_group = yes; then
+ gcc_cv_as_comdat_group_percent=no
+ gcc_cv_as_comdat_group_group=no
+else
+ gcc_GAS_CHECK_FEATURE([COMDAT group support (GNU as, %type)],
+ gcc_cv_as_comdat_group_percent,
+ [--fatal-warnings],
+ [.section .text,"axG",%progbits,.foo,comdat])
+ if test $gcc_cv_as_comdat_group_percent = yes; then
+ gcc_cv_as_comdat_group_group=no
+ else
+ case "${target}" in
+ # Sun as uses a completely different syntax.
+ *-*-solaris2*)
+ case "${target}" in
+ sparc*-*-solaris2*)
+ conftest_s='
+ .group foo,".text%foo",#comdat
+ .section ".text%foo", #alloc,#execinstr,#progbits
+ .globl foo
+ foo:
+ '
+ ;;
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ conftest_s='
+ .group foo,.text%foo,#comdat
+ .section .text%foo, "ax", @progbits
+ .globl foo
+ foo:
+ '
+ ;;
+ esac
+ gcc_GAS_CHECK_FEATURE([COMDAT group support (Sun as, .group)],
+ gcc_cv_as_comdat_group_group,
+ , [$conftest_s])
+ ;;
+ esac
+ if test -z "${gcc_cv_as_comdat_group_group+set}"; then
+ gcc_cv_as_comdat_group_group=no
+ fi
+ fi
+fi
+if test x"$ld_is_gold" = xyes; then
+ comdat_group=yes
+elif test x"$ld_is_mold" = xyes; then
+ comdat_group=yes
+elif test $in_tree_ld = yes ; then
+ comdat_group=no
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ comdat_group=yes
+ fi
+elif echo "$ld_ver" | grep GNU > /dev/null; then
+ comdat_group=yes
+ if test 0"$ld_date" -lt 20050308; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2005-03-08, fail
+ comdat_group=no
+ elif test "$ld_vers_major" -lt 2; then
+ comdat_group=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 16; then
+ comdat_group=no
+ fi
+ fi
+else
+changequote(,)dnl
+ case "${target}" in
+ *-*-solaris2.1[1-9]*)
+ comdat_group=no
+ # Sun ld has COMDAT group support since Solaris 9, but it doesn't
+ # interoperate with GNU as until Solaris 11 build 130, i.e. ld
+ # version 1.688.
+ #
+ # If using Sun as for COMDAT group as emitted by GCC, one needs at
+ # least ld version 1.2267.
+ if test "$ld_vers_major" -gt 1; then
+ comdat_group=yes
+ elif test "x$gas_flag" = xyes && test "$ld_vers_minor" -ge 1688; then
+ comdat_group=yes
+ elif test "$ld_vers_minor" -ge 2267; then
+ comdat_group=yes
+ fi
+ ;;
+ *)
+ # Assume linkers other than GNU ld don't support COMDAT group.
+ comdat_group=no
+ ;;
+ esac
+changequote([,])dnl
+fi
+# Allow overriding the automatic COMDAT group tests above.
+AC_ARG_ENABLE(comdat,
+ [AS_HELP_STRING([--enable-comdat], [enable COMDAT group support])],
+ [comdat_group="$enable_comdat"])
+if test $comdat_group = no; then
+ gcc_cv_as_comdat_group=no
+ gcc_cv_as_comdat_group_percent=no
+ gcc_cv_as_comdat_group_group=no
+fi
+AC_DEFINE_UNQUOTED(HAVE_COMDAT_GROUP,
+ [`if test $gcc_cv_as_comdat_group = yes \
+ || test $gcc_cv_as_comdat_group_percent = yes \
+ || test $gcc_cv_as_comdat_group_group = yes; then echo 1; else echo 0; fi`],
+[Define 0/1 if your assembler and linker support COMDAT groups.])
+
+# Restrict this test to Solaris/x86: other targets define this statically.
+case "${target}" in
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ AC_MSG_CHECKING(support for hidden thunks in linkonce sections)
+ if test $in_tree_ld = yes || echo "$ld_ver" | grep GNU > /dev/null; then
+ hidden_linkonce=yes
+ else
+ case "${target}" in
+ # Full support for hidden thunks in linkonce sections only appeared in
+ # Solaris 11/OpenSolaris.
+ *-*-solaris2.1[[1-9]]*)
+ hidden_linkonce=yes
+ ;;
+ *)
+ hidden_linkonce=no
+ ;;
+ esac
+ fi
+ AC_MSG_RESULT($hidden_linkonce)
+ AC_DEFINE_UNQUOTED(USE_HIDDEN_LINKONCE,
+ [`if test $hidden_linkonce = yes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your linker supports hidden thunks in linkonce sections.])
+ ;;
+esac
+
+gcc_GAS_CHECK_FEATURE([line table is_stmt support],
+ gcc_cv_as_is_stmt,,
+[ .text
+ .file 1 "conf.c"
+ .loc 1 1 0 is_stmt 1],,
+[AC_DEFINE(HAVE_GAS_LOC_STMT, 1,
+ [Define if your assembler supports the .loc is_stmt sub-directive.])])
+
+gcc_GAS_CHECK_FEATURE([line table discriminator support],
+ gcc_cv_as_discriminator,,
+[ .text
+ .file 1 "conf.c"
+ .loc 1 1 0 discriminator 1],,
+[AC_DEFINE(HAVE_GAS_DISCRIMINATOR, 1,
+ [Define if your assembler supports the .loc discriminator sub-directive.])])
+
+# Catch the newlib flag of the same name so we can gate GCC features on it.
+AC_ARG_ENABLE(newlib-nano-formatted-io,
+[AS_HELP_STRING([--enable-newlib-nano-formatted-io], [Use nano version
+ formatted IO])],
+[case "${enableval}" in
+ yes|no)
+ ;;
+ *)
+ AC_MSG_ERROR([unknown newlib-nano-formatted-io setting $enableval])
+ ;;
+esac], [])
+
+# Thread-local storage - the check is heavily parameterized.
+conftest_s=
+tls_as_opt=
+case "$target" in
+changequote(,)dnl
+ alpha*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ ldq $27,__tls_get_addr($29) !literal!1
+ lda $16,foo($29) !tlsgd!1
+ jsr $26,($27),__tls_get_addr !lituse_tlsgd!1
+ ldq $27,__tls_get_addr($29) !literal!2
+ lda $16,foo($29) !tlsldm!2
+ jsr $26,($27),__tls_get_addr !lituse_tlsldm!2
+ ldq $1,foo($29) !gotdtprel
+ ldah $2,foo($29) !dtprelhi
+ lda $3,foo($2) !dtprello
+ lda $4,foo($29) !dtprel
+ ldq $1,foo($29) !gottprel
+ ldah $2,foo($29) !tprelhi
+ lda $3,foo($2) !tprello
+ lda $4,foo($29) !tprel'
+ tls_as_opt=--fatal-warnings
+ ;;
+ arc*-*-*)
+ conftest_s='
+ add_s r0,r0, @foo@tpoff'
+ ;;
+ cris-*-*|crisv32-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+x: .long 25
+ .text
+ move.d x:IE,$r10
+ nop'
+ tls_as_opt=--fatal-warnings
+ ;;
+ frv*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+x: .long 25
+ .text
+ call #gettlsoff(x)'
+ ;;
+ hppa*-*-linux*)
+ conftest_s='
+t1: .reg %r20
+t2: .reg %r21
+gp: .reg %r19
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .align 4
+ addil LT%foo-$tls_gdidx$,gp
+ ldo RT%foo-$tls_gdidx$(%r1),%arg0
+ b __tls_get_addr
+ nop
+ addil LT%foo-$tls_ldidx$,gp
+ b __tls_get_addr
+ ldo RT%foo-$tls_ldidx$(%r1),%arg0
+ addil LR%foo-$tls_dtpoff$,%ret0
+ ldo RR%foo-$tls_dtpoff$(%r1),%t1
+ mfctl %cr27,%t1
+ addil LT%foo-$tls_ieoff$,gp
+ ldw RT%foo-$tls_ieoff$(%r1),%t2
+ add %t1,%t2,%t3
+ mfctl %cr27,%t1
+ addil LR%foo-$tls_leoff$,%t1
+ ldo RR%foo-$tls_leoff$(%r1),%t2'
+ tls_as_opt=--fatal-warnings
+ ;;
+ arm*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+.word foo(gottpoff)
+.word foo(tpoff)
+.word foo(tlsgd)
+.word foo(tlsldm)
+.word foo(tlsldo)'
+ ;;
+ i[34567]86-*-* | x86_64-*-*)
+ case "$target" in
+ i[34567]86-*-solaris2.* | x86_64-*-solaris2.*)
+ on_solaris=yes
+ ;;
+ *)
+ on_solaris=no
+ ;;
+ esac
+ if test x$on_solaris = xyes && test x$gas_flag = xno; then
+ conftest_s='
+ .section .tdata,"awt",@progbits'
+ tls_section_flag=t
+changequote([,])dnl
+ AC_DEFINE(TLS_SECTION_ASM_FLAG, 't',
+[Define to the flag used to mark TLS sections if the default (`T') doesn't work.])
+changequote(,)dnl
+ else
+ conftest_s='
+ .section ".tdata","awT",@progbits'
+ tls_section_flag=T
+ tls_as_opt="--fatal-warnings"
+ fi
+ case "$target" in
+ i[34567]86-*-*)
+ if test x$on_solaris = xyes; then
+ case $gas_flag in
+ yes) tls_as_opt="$tls_as_opt --32" ;;
+ esac
+ fi
+ conftest_s="$conftest_s
+foo: .long 25
+ .text
+ movl %gs:0, %eax
+ leal foo@tlsgd(,%ebx,1), %eax
+ leal foo@tlsldm(%ebx), %eax
+ leal foo@dtpoff(%eax), %edx
+ movl foo@gottpoff(%ebx), %eax
+ subl foo@gottpoff(%ebx), %eax
+ addl foo@gotntpoff(%ebx), %eax
+ movl foo@indntpoff, %eax
+ movl \$foo@tpoff, %eax
+ subl \$foo@tpoff, %eax
+ leal foo@ntpoff(%ecx), %eax"
+ ;;
+ x86_64-*-*)
+ if test x$on_solaris = xyes; then
+ case $gas_flag in
+ yes) tls_as_opt="$tls_as_opt --64" ;;
+ no) tls_as_opt="$tls_as_opt -xarch=amd64" ;;
+ esac
+ fi
+ conftest_s="$conftest_s
+foo: .long 25
+ .text
+ movq %fs:0, %rax
+ leaq foo@tlsgd(%rip), %rdi
+ leaq foo@tlsld(%rip), %rdi
+ leaq foo@dtpoff(%rax), %rdx
+ movq foo@gottpoff(%rip), %rax
+ movq \$foo@tpoff, %rax"
+ ;;
+ esac
+ ;;
+ ia64-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: data8 25
+ .text
+ addl r16 = @ltoff(@dtpmod(foo#)), gp
+ addl r17 = @ltoff(@dtprel(foo#)), gp
+ addl r18 = @ltoff(@tprel(foo#)), gp
+ addl r19 = @dtprel(foo#), gp
+ adds r21 = @dtprel(foo#), r13
+ movl r23 = @dtprel(foo#)
+ addl r20 = @tprel(foo#), gp
+ adds r22 = @tprel(foo#), r13
+ movl r24 = @tprel(foo#)'
+ tls_as_opt=--fatal-warnings
+ ;;
+ loongarch*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x: .word 2
+ .text
+ la.tls.gd $a0,x
+ bl __tls_get_addr'
+ tls_first_major=0
+ tls_first_minor=0
+ tls_as_opt='--fatal-warnings'
+ ;;
+ microblaze*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ addik r5,r20,x@TLSGD
+ addik r5,r20,x@TLSLDM'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ mips*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ addiu $4, $28, %tlsgd(x)
+ addiu $4, $28, %tlsldm(x)
+ lui $4, %dtprel_hi(x)
+ addiu $4, $4, %dtprel_lo(x)
+ lw $4, %gottprel(x)($28)
+ lui $4, %tprel_hi(x)
+ addiu $4, $4, %tprel_lo(x)'
+ tls_as_opt='-32 --fatal-warnings'
+ ;;
+ m68k-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+foo:
+ move.l x@TLSGD(%a5),%a0
+ move.l x@TLSLDM(%a5),%a0
+ move.l x@TLSLDO(%a5),%a0
+ move.l x@TLSIE(%a5),%a0
+ move.l x@TLSLE(%a5),%a0'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ nios2-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits'
+ tls_as_opt="--fatal-warnings"
+ ;;
+ aarch64*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+ adrp x0, :tlsgd:x
+ add x0, x0, #:tlsgd_lo12:x
+ bl __tls_get_addr
+ nop'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ or1k*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ l.movhi r3, tpoffha(foo)
+ l.add r3, r3, r10
+ l.lwz r4, tpofflo(foo)(r3)'
+ tls_as_opt=--fatal-warnings
+ ;;
+ powerpc-ibm-aix*)
+ conftest_s='
+ .extern __get_tpointer
+ .toc
+LC..1:
+ .tc a[TC],a[TL]@le
+ .csect .text[PR]
+.tlstest:
+ lwz 9,LC..1(2)
+ bla __get_tpointer
+ lwzx 3,9,3
+ .globl a
+ .csect a[TL],4
+a:
+ .space 4'
+ ;;
+ powerpc64*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+ .align 3
+ld0: .space 8
+ld1: .space 8
+x1: .space 8
+x2: .space 8
+x3: .space 8
+ .text
+ addi 3,2,ld0@got@tlsgd
+ bl .__tls_get_addr
+ nop
+ addi 3,2,ld1@toc
+ bl .__tls_get_addr
+ nop
+ addi 3,2,x1@got@tlsld
+ bl .__tls_get_addr
+ nop
+ addi 9,3,x1@dtprel
+ bl .__tls_get_addr
+ nop
+ addis 9,3,x2@dtprel@ha
+ addi 9,9,x2@dtprel@l
+ bl .__tls_get_addr
+ nop
+ ld 9,x3@got@dtprel(2)
+ add 9,9,3
+ bl .__tls_get_addr
+ nop'
+ tls_as_opt="-a64 --fatal-warnings"
+ ;;
+ powerpc*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+ .align 2
+ld0: .space 4
+ld1: .space 4
+x1: .space 4
+x2: .space 4
+x3: .space 4
+ .text
+ addi 3,31,ld0@got@tlsgd
+ bl __tls_get_addr
+ addi 3,31,x1@got@tlsld
+ bl __tls_get_addr
+ addi 9,3,x1@dtprel
+ addis 9,3,x2@dtprel@ha
+ addi 9,9,x2@dtprel@l
+ lwz 9,x3@got@tprel(31)
+ add 9,9,x@tls
+ addi 9,2,x1@tprel
+ addis 9,2,x2@tprel@ha
+ addi 9,9,x2@tprel@l'
+ tls_as_opt="-a32 --fatal-warnings"
+ ;;
+ riscv*-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x: .word 2
+ .text
+ la.tls.gd a0,x
+ call __tls_get_addr'
+ tls_as_opt='--fatal-warnings'
+ ;;
+ s390-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@NTPOFF
+ .long foo@GOTNTPOFF
+ .long foo@INDNTPOFF
+ l %r1,foo@GOTNTPOFF(%r12)
+ l %r1,0(%r1):tls_load:foo
+ bas %r14,0(%r1,%r13):tls_gdcall:foo
+ bas %r14,0(%r1,%r13):tls_ldcall:foo'
+ tls_as_opt="-m31 --fatal-warnings"
+ ;;
+ s390x-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .quad foo@TLSGD
+ .quad foo@TLSLDM
+ .quad foo@DTPOFF
+ .quad foo@NTPOFF
+ .quad foo@GOTNTPOFF
+ lg %r1,foo@GOTNTPOFF(%r12)
+ larl %r1,foo@INDNTPOFF
+ brasl %r14,__tls_get_offset@PLT:tls_gdcall:foo
+ brasl %r14,__tls_get_offset@PLT:tls_ldcall:foo'
+ tls_as_opt="-m64 -Aesame --fatal-warnings"
+ ;;
+ sh-*-* | sh[123456789lbe]*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ .long foo@TLSGD
+ .long foo@TLSLDM
+ .long foo@DTPOFF
+ .long foo@GOTTPOFF
+ .long foo@TPOFF'
+ tls_as_opt=--fatal-warnings
+ ;;
+ sparc*-*-*)
+ case "$target" in
+ sparc*-sun-solaris2.*)
+ on_solaris=yes
+ ;;
+ *)
+ on_solaris=no
+ ;;
+ esac
+ if test x$on_solaris = xyes && test x$gas_flag = xno; then
+ conftest_s='
+ .section ".tdata",#alloc,#write,#tls'
+ else
+ conftest_s='
+ .section ".tdata","awT",@progbits'
+ tls_as_opt="-32 --fatal-warnings"
+ fi
+ conftest_s="$conftest_s
+foo: .long 25
+ .text
+ sethi %tgd_hi22(foo), %o0
+ add %o0, %tgd_lo10(foo), %o1
+ add %l7, %o1, %o0, %tgd_add(foo)
+ call __tls_get_addr, %tgd_call(foo)
+ sethi %tldm_hi22(foo), %l1
+ add %l1, %tldm_lo10(foo), %l2
+ add %l7, %l2, %o0, %tldm_add(foo)
+ call __tls_get_addr, %tldm_call(foo)
+ sethi %tldo_hix22(foo), %l3
+ xor %l3, %tldo_lox10(foo), %l4
+ add %o0, %l4, %l5, %tldo_add(foo)
+ sethi %tie_hi22(foo), %o3
+ add %o3, %tie_lo10(foo), %o3
+ ld [%l7 + %o3], %o2, %tie_ld(foo)
+ add %g7, %o2, %o4, %tie_add(foo)
+ sethi %tle_hix22(foo), %l1
+ xor %l1, %tle_lox10(foo), %o5
+ ld [%g7 + %o5], %o1"
+ ;;
+ tilepro*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ addli r0, zero, tls_gd(foo)
+ auli r0, zero, tls_gd_ha16(foo)
+ addli r0, r0, tls_gd_lo16(foo)
+ jal __tls_get_addr
+ addli r0, zero, tls_ie(foo)
+ auli r0, r0, tls_ie_ha16(foo)
+ addli r0, r0, tls_ie_lo16(foo)'
+ tls_as_opt="--fatal-warnings"
+ ;;
+ tilegx*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ shl16insli r0, zero, hw0_last_tls_gd(foo)
+ shl16insli r0, zero, hw1_last_tls_gd(foo)
+ shl16insli r0, r0, hw0_tls_gd(foo)
+ jal __tls_get_addr
+ shl16insli r0, zero, hw1_last_tls_ie(foo)
+ shl16insli r0, r0, hw0_tls_ie(foo)'
+ tls_as_opt="--fatal-warnings"
+ ;;
+ xtensa*-*-*)
+ conftest_s='
+ .section ".tdata","awT",@progbits
+foo: .long 25
+ .text
+ movi a8, foo@TLSFUNC
+ movi a10, foo@TLSARG
+ callx8.tls a8, foo@TLSCALL'
+ ;;
+changequote([,])dnl
+esac
+set_have_as_tls=no
+if test "x$enable_tls" = xno ; then
+ : # TLS explicitly disabled.
+elif test "x$enable_tls" = xyes ; then
+ set_have_as_tls=yes # TLS explicitly enabled.
+elif test -z "$conftest_s"; then
+ : # If we don't have a check, assume no support.
+else
+ gcc_GAS_CHECK_FEATURE(thread-local storage support, gcc_cv_as_tls,
+ [$tls_as_opt], [$conftest_s],,
+ [set_have_as_tls=yes])
+fi
+if test $set_have_as_tls = yes ; then
+ AC_DEFINE(HAVE_AS_TLS, 1,
+ [Define if your assembler and linker support thread-local storage.])
+fi
+
+# Target-specific assembler checks.
+
+AC_MSG_CHECKING(linker -Bstatic/-Bdynamic option)
+gcc_cv_ld_static_dynamic=no
+gcc_cv_ld_static_option='-Bstatic'
+gcc_cv_ld_dynamic_option='-Bdynamic'
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 10 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_static_dynamic=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -Bstatic/-Bdynamic option
+ if $gcc_cv_ld --help 2>&1 | grep -- -Bstatic > /dev/null \
+ && $gcc_cv_ld --help 2>&1 | grep -- -Bdynamic > /dev/null; then
+ gcc_cv_ld_static_dynamic=yes
+ else
+ case "$target" in
+ # AIX ld uses -b flags
+ *-*-aix4.[[23]]* | *-*-aix[[5-9]]*)
+ gcc_cv_ld_static_dynamic=yes
+ gcc_cv_ld_static_option="-bstatic"
+ gcc_cv_ld_dynamic_option="-bdynamic"
+ ;;
+ # HP-UX ld uses -a flags to select between shared and archive.
+ *-*-hpux*)
+ if test x"$gnu_ld" = xno; then
+ gcc_cv_ld_static_dynamic=yes
+ gcc_cv_ld_static_option="-aarchive_shared"
+ gcc_cv_ld_dynamic_option="-adefault"
+ fi
+ ;;
+ # Solaris 2 ld always supports -Bstatic/-Bdynamic.
+ *-*-solaris2*)
+ gcc_cv_ld_static_dynamic=yes
+ ;;
+ esac
+ fi
+fi
+if test x"$gcc_cv_ld_static_dynamic" = xyes; then
+ AC_DEFINE(HAVE_LD_STATIC_DYNAMIC, 1,
+[Define if your linker supports -Bstatic/-Bdynamic or equivalent options.])
+ AC_DEFINE_UNQUOTED(LD_STATIC_OPTION, "$gcc_cv_ld_static_option",
+[Define to the linker option to disable use of shared objects.])
+ AC_DEFINE_UNQUOTED(LD_DYNAMIC_OPTION, "$gcc_cv_ld_dynamic_option",
+[Define to the linker option to enable use of shared objects.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_static_dynamic)
+
+AC_MSG_CHECKING(linker --version-script option)
+gcc_cv_ld_version_script=no
+ld_version_script_option=''
+if test $in_tree_ld = yes || test x"$gnu_ld" = xyes; then
+ gcc_cv_ld_version_script=yes
+ ld_version_script_option='--version-script'
+elif test x$gcc_cv_ld != x; then
+ case "$target" in
+ # Solaris 2 ld always supports -M. It also supports a subset of
+ # --version-script since Solaris 11.4, but requires
+ # -z gnu-version-script-compat to activate.
+ *-*-solaris2*)
+ gcc_cv_ld_version_script=yes
+ ld_version_script_option='-M'
+ ;;
+ esac
+fi
+# Don't AC_DEFINE result, only used in jit/Make-lang.in so far.
+AC_MSG_RESULT($gcc_cv_ld_version_script)
+AC_SUBST(ld_version_script_option)
+
+AC_MSG_CHECKING(linker soname option)
+gcc_cv_ld_soname=no
+if test $in_tree_ld = yes || test x"$gnu_ld" = xyes; then
+ gcc_cv_ld_soname=yes
+ ld_soname_option='-soname'
+elif test x$gcc_cv_ld != x; then
+ case "$target" in
+ *-*-darwin*)
+ gcc_cv_ld_soname=yes
+ ld_soname_option='-install_name'
+ ;;
+ # Solaris 2 ld always supports -h. It also supports --soname for GNU
+ # ld compatiblity since some Solaris 10 update.
+ *-*-solaris2*)
+ gcc_cv_ld_soname=yes
+ ld_soname_option='-h'
+ ;;
+ esac
+fi
+# Don't AC_DEFINE result, only used in jit/Make-lang.in so far.
+AC_MSG_RESULT($gcc_cv_ld_soname)
+AC_SUBST(ld_soname_option)
+
+if test x"$demangler_in_ld" = xyes; then
+ AC_MSG_CHECKING(linker --demangle support)
+ gcc_cv_ld_demangle=no
+ if test $in_tree_ld = yes; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 14 -o "$gcc_cv_gld_major_version" -gt 2; then \
+ gcc_cv_ld_demangle=yes
+ fi
+ elif test x$gcc_cv_ld != x -a x"$gnu_ld" = xyes; then
+ # Check if the GNU linker supports --demangle option
+ if $gcc_cv_ld --help 2>&1 | grep no-demangle > /dev/null; then
+ gcc_cv_ld_demangle=yes
+ fi
+ fi
+ if test x"$gcc_cv_ld_demangle" = xyes; then
+ AC_DEFINE(HAVE_LD_DEMANGLE, 1,
+[Define if your linker supports --demangle option.])
+ fi
+ AC_MSG_RESULT($gcc_cv_ld_demangle)
+fi
+
+AC_MSG_CHECKING(linker plugin support)
+gcc_cv_lto_plugin=0
+if test -f liblto_plugin.la; then
+ save_ld_ver="$ld_ver"
+ save_ld_vers_major="$ld_vers_major"
+ save_ld_vers_minor="$ld_vers_minor"
+ save_ld_is_gold="$ld_is_gold"
+
+ ld_is_gold=no
+
+ if test $in_tree_ld = yes -a x"$ORIGINAL_PLUGIN_LD_FOR_TARGET" = x"$gcc_cv_ld"; then
+ ld_ver="GNU ld"
+ # FIXME: ld_is_gold?
+ ld_vers_major="$gcc_cv_gld_major_version"
+ ld_vers_minor="$gcc_cv_gld_minor_version"
+ else
+ # Determine plugin linker version.
+ # FIXME: Partial duplicate from above, generalize.
+changequote(,)dnl
+ ld_ver=`$ORIGINAL_PLUGIN_LD_FOR_TARGET --version 2>/dev/null | sed 1q`
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ if echo "$ld_ver" | grep "GNU gold" > /dev/null; then
+ ld_is_gold=yes
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^[^)]*[ ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
+ else
+ ld_vers=`echo $ld_ver | sed -n \
+ -e 's,^.*[ ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
+ fi
+ ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
+ ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
+ fi
+changequote([,])dnl
+ fi
+
+ # Determine plugin support.
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ # Require GNU ld or gold 2.21+ for plugin support by default.
+ if test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -ge 21; then
+ gcc_cv_lto_plugin=2
+ elif test "$ld_is_mold" = yes; then
+ gcc_cv_lto_plugin=2
+ # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
+ elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -eq 20; then
+ gcc_cv_lto_plugin=1
+ fi
+ fi
+
+ ld_ver="$save_ld_ver"
+ ld_vers_major="$save_ld_vers_major"
+ ld_vers_minor="$save_ld_vers_minor"
+ ld_is_gold="$save_ld_is_gold"
+fi
+AC_DEFINE_UNQUOTED(HAVE_LTO_PLUGIN, $gcc_cv_lto_plugin,
+ [Define to the level of your linker's plugin support.])
+AC_MSG_RESULT($gcc_cv_lto_plugin)
+
+# Target OS-specific assembler checks.
+
+case "$target_os" in
+ darwin*)
+ gcc_GAS_CHECK_FEATURE([-mmacosx-version-min option],
+ gcc_cv_as_mmacosx_version_min,
+ [-mmacosx-version-min=10.1], [.text],,
+ [AC_DEFINE(HAVE_AS_MMACOSX_VERSION_MIN_OPTION, 1,
+ [Define if your Mac OS X assembler supports the -mmacos-version-min option.])])
+ ;;
+esac
+
+# Target CPU-specific assembler checks.
+
+case "$target" in
+ aarch64*-*-*)
+ gcc_GAS_CHECK_FEATURE([-mabi option], gcc_cv_as_aarch64_mabi,
+ [-mabi=lp64], [.text],,,)
+ if test x$gcc_cv_as_aarch64_mabi = xyes; then
+ AC_DEFINE(HAVE_AS_MABI_OPTION, 1,
+ [Define if your assembler supports the -mabi option.])
+ else
+ if test x$with_abi = xilp32; then
+ AC_MSG_ERROR([Assembler does not support -mabi=ilp32.\
+ Upgrade the Assembler.])
+ fi
+ if test x"$with_multilib_list" = xdefault; then
+ TM_MULTILIB_CONFIG=lp64
+ else
+ aarch64_multilibs=`echo $with_multilib_list | sed -e 's/,/ /g'`
+ for aarch64_multilib in ${aarch64_multilibs}; do
+ case ${aarch64_multilib} in
+ ilp32)
+ AC_MSG_ERROR([Assembler does not support -mabi=ilp32.\
+ Upgrade the Assembler.])
+ ;;
+ *)
+ ;;
+ esac
+ done
+ fi
+ fi
+ # Check if we have binutils support for relocations types needed by -fpic
+ gcc_GAS_CHECK_FEATURE([-fpic relocs], gcc_cv_as_aarch64_picreloc,,
+ [
+ .text
+ ldr x0, [[x2, #:gotpage_lo15:globalsym]]
+ ],,[AC_DEFINE(HAVE_AS_SMALL_PIC_RELOCS, 1,
+ [Define if your assembler supports relocs needed by -fpic.])])
+ # Enable Branch Target Identification Mechanism and Return Address
+ # Signing by default.
+ AC_ARG_ENABLE(standard-branch-protection,
+ [
+AS_HELP_STRING([--enable-standard-branch-protection],
+ [enable Branch Target Identification Mechanism and Return Address Signing by default for AArch64])
+AS_HELP_STRING([--disable-standard-branch-protection],
+ [disable Branch Target Identification Mechanism and Return Address Signing by default for AArch64])
+ ],
+ [
+ case $enableval in
+ yes)
+ tm_defines="${tm_defines} TARGET_ENABLE_BTI=1 TARGET_ENABLE_PAC_RET=1"
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR(['$enableval' is an invalid value for --enable-standard-branch-protection.\
+ Valid choices are 'yes' and 'no'.])
+ ;;
+ esac
+ ],
+ [])
+ # Enable default workaround for AArch64 Cortex-A53 erratum 835769.
+ AC_ARG_ENABLE(fix-cortex-a53-835769,
+ [
+AS_HELP_STRING([--enable-fix-cortex-a53-835769],
+ [enable workaround for AArch64 Cortex-A53 erratum 835769 by default])
+AS_HELP_STRING([--disable-fix-cortex-a53-835769],
+ [disable workaround for AArch64 Cortex-A53 erratum 835769 by default])
+ ],
+ [
+ case $enableval in
+ yes)
+ tm_defines="${tm_defines} TARGET_FIX_ERR_A53_835769_DEFAULT=1"
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR(['$enableval' is an invalid value for --enable-fix-cortex-a53-835769.\
+ Valid choices are 'yes' and 'no'.])
+ ;;
+
+ esac
+ ],
+ [])
+ # Enable default workaround for AArch64 Cortex-A53 erratum 843419.
+ AC_ARG_ENABLE(fix-cortex-a53-843419,
+ [
+AS_HELP_STRING([--enable-fix-cortex-a53-843419],
+ [enable workaround for AArch64 Cortex-A53 erratum 843419 by default])
+AS_HELP_STRING([--disable-fix-cortex-a53-843419],
+ [disable workaround for AArch64 Cortex-A53 erratum 843419 by default])
+ ],
+ [
+ case $enableval in
+ yes)
+ tm_defines="${tm_defines} TARGET_FIX_ERR_A53_843419_DEFAULT=1"
+ ;;
+ no)
+ ;;
+ *)
+ AC_MSG_ERROR(['$enableval' is an invalid value for --enable-fix-cortex-a53-843419.\
+ Valid choices are 'yes' and 'no'.])
+ ;;
+
+ esac
+ ],
+ [])
+ ;;
+
+ # All TARGET_ABI_OSF targets.
+ alpha*-*-linux* | alpha*-*-*bsd*)
+ gcc_GAS_CHECK_FEATURE([explicit relocation support],
+ gcc_cv_as_alpha_explicit_relocs,,
+[ .set nomacro
+ .text
+ extbl $3, $2, $3 !lituse_bytoff!1
+ ldq $2, a($29) !literal!1
+ ldq $4, b($29) !literal!2
+ ldq_u $3, 0($2) !lituse_base!1
+ ldq $27, f($29) !literal!5
+ jsr $26, ($27), f !lituse_jsr!5
+ ldah $29, 0($26) !gpdisp!3
+ lda $0, c($29) !gprel
+ ldah $1, d($29) !gprelhigh
+ lda $1, d($1) !gprellow
+ lda $29, 0($29) !gpdisp!3],,
+ [AC_DEFINE(HAVE_AS_EXPLICIT_RELOCS, 1,
+ [Define if your assembler supports explicit relocations.])])
+ gcc_GAS_CHECK_FEATURE([jsrdirect relocation support],
+ gcc_cv_as_alpha_jsrdirect_relocs,,
+[ .set nomacro
+ .text
+ ldq $27, a($29) !literal!1
+ jsr $26, ($27), a !lituse_jsrdirect!1],,
+ [AC_DEFINE(HAVE_AS_JSRDIRECT_RELOCS, 1,
+ [Define if your assembler supports the lituse_jsrdirect relocation.])])
+ ;;
+
+ avr-*-*)
+ gcc_GAS_CHECK_FEATURE([--mlink-relax option], gcc_cv_as_avr_mlink_relax,
+ [--mlink-relax], [.text],,
+ [AC_DEFINE(HAVE_AS_AVR_MLINK_RELAX_OPTION, 1,
+ [Define if your avr assembler supports --mlink-relax option.])])
+
+ gcc_GAS_CHECK_FEATURE([-mrmw option], gcc_cv_as_avr_mrmw,
+ [-mrmw], [.text],,
+ [AC_DEFINE(HAVE_AS_AVR_MRMW_OPTION, 1,
+ [Define if your avr assembler supports -mrmw option.])])
+
+ gcc_GAS_CHECK_FEATURE([__gcc_isr pseudo instruction],
+ gcc_cv_as_avr_mgccisr,
+ [-mgcc-isr], [.text
+ __gcc_isr 1
+ __gcc_isr 2
+ __gcc_isr 0,r24
+ ],,
+ [AC_DEFINE(HAVE_AS_AVR_MGCCISR_OPTION, 1,
+ [Define if your avr assembler supports -mgcc-isr option.])])
+
+ # Check how default linker description file implements .rodata for
+ # avrxmega3 (PR21472). avr-gcc assumes .rodata is *not* loaded to
+ # RAM so avr-gcc skips __do_copy_data for .rodata objects.
+ AC_MSG_CHECKING(binutils for avrxmega3 .rodata support)
+ cat > conftest.s <<EOF
+ .section .rodata,"a",@progbits
+ .global xxvaryy
+ ;; avr-nm should print "... R xxvaryy", not "... D xxvaryy".
+ xxvaryy:
+ .word 1
+EOF
+ rm -f conftest.nm
+ AC_TRY_COMMAND([$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o])
+ AC_TRY_COMMAND([$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf])
+ AC_TRY_COMMAND([$gcc_cv_nm conftest.elf > conftest.nm])
+ if test -s conftest.nm
+ then
+ if grep ' R xxvaryy' conftest.nm > /dev/null; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH, 1,
+ [Define if your default avr linker script for avrxmega3 leaves .rodata in flash.])
+ else
+ AC_MSG_RESULT(no: avrxmega3 .rodata located in RAM)
+ echo "$as_me: nm output was" >&AS_MESSAGE_LOG_FD
+ cat conftest.nm >&AS_MESSAGE_LOG_FD
+ avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
+ AC_MSG_WARN([[support for avrxmega3 .rodata in flash needs Binutils 2.29 or higher (have $avr_ld_ver)]])
+ fi
+ else
+ AC_MSG_RESULT(test failed)
+ echo "$as_me: failed program was" >&AS_MESSAGE_LOG_FD
+ cat conftest.s >&AS_MESSAGE_LOG_FD
+ AC_MSG_WARN([[see `config.log' for details]])
+ fi
+ rm -f conftest.s conftest.o conftest.elf conftest.nm
+ ;;
+
+ cris-*-*)
+ gcc_GAS_CHECK_FEATURE([-no-mul-bug-abort option],
+ gcc_cv_as_cris_no_mul_bug,
+ [-no-mul-bug-abort], [.text],,
+ [AC_DEFINE(HAVE_AS_NO_MUL_BUG_ABORT_OPTION, 1,
+ [Define if your assembler supports the -no-mul-bug-abort option.])])
+ ;;
+
+ sparc*-*-*)
+ gcc_GAS_CHECK_FEATURE([-relax option], gcc_cv_as_sparc_relax,
+ [-relax], [.text],,
+ [AC_DEFINE(HAVE_AS_RELAX_OPTION, 1,
+ [Define if your assembler supports -relax option.])])
+
+ gcc_GAS_CHECK_FEATURE([GOTDATA_OP relocs],
+ gcc_cv_as_sparc_gotdata_op,
+ [-K PIC],
+[.text
+.align 4
+foo:
+ nop
+bar:
+ sethi %gdop_hix22(foo), %g1
+ xor %g1, %gdop_lox10(foo), %g1
+ ld [[%l7 + %g1]], %g2, %gdop(foo)],
+ [if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o -G > /dev/null 2>&1; then
+ if test x$gcc_cv_objdump != x; then
+ if $gcc_cv_objdump -s -j .text conftest 2> /dev/null \
+ | grep ' 03000004 82186004 c405c001'> /dev/null 2>&1; then
+ gcc_cv_as_sparc_gotdata_op=no
+ else
+ gcc_cv_as_sparc_gotdata_op=yes
+ fi
+ fi
+ fi
+ rm -f conftest],
+ [AC_DEFINE(HAVE_AS_SPARC_GOTDATA_OP, 1,
+ [Define if your assembler and linker support GOTDATA_OP relocs.])])
+
+ gcc_GAS_CHECK_FEATURE([unaligned pcrel relocs],
+ gcc_cv_as_sparc_ua_pcrel,
+ [-K PIC],
+[.text
+foo:
+ nop
+.data
+.align 4
+.byte 0
+.uaword %r_disp32(foo)],
+ [if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o -G > /dev/null 2>&1; then
+ gcc_cv_as_sparc_ua_pcrel=yes
+ fi
+ rm -f conftest],
+ [AC_DEFINE(HAVE_AS_SPARC_UA_PCREL, 1,
+ [Define if your assembler and linker support unaligned PC relative relocs.])
+
+ gcc_GAS_CHECK_FEATURE([unaligned pcrel relocs against hidden symbols],
+ gcc_cv_as_sparc_ua_pcrel_hidden,
+ [-K PIC],
+[.data
+.align 4
+.byte 0x31
+.uaword %r_disp32(foo)
+.byte 0x32, 0x33, 0x34
+.global foo
+.hidden foo
+foo:
+.skip 4],
+ [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+ && $gcc_cv_ld -o conftest conftest.o -G > /dev/null 2>&1 \
+ && $gcc_cv_objdump -s -j .data conftest 2> /dev/null \
+ | grep ' 31000000 07323334' > /dev/null 2>&1; then
+ if $gcc_cv_objdump -R conftest 2> /dev/null \
+ | grep 'DISP32' > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_as_sparc_ua_pcrel_hidden=yes
+ fi
+ fi
+ rm -f conftest],
+ [AC_DEFINE(HAVE_AS_SPARC_UA_PCREL_HIDDEN, 1,
+ [Define if your assembler and linker support unaligned PC relative relocs against hidden symbols.])])
+ ]) # unaligned pcrel relocs
+
+ gcc_GAS_CHECK_FEATURE([offsetable %lo()],
+ gcc_cv_as_sparc_offsetable_lo10,
+ [-xarch=v9],
+[.text
+ or %g1, %lo(ab) + 12, %g1
+ or %g1, %lo(ab + 12), %g1],
+ [if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -s -j .text conftest.o 2> /dev/null \
+ | grep ' 82106000 82106000' > /dev/null 2>&1; then
+ gcc_cv_as_sparc_offsetable_lo10=yes
+ fi],
+ [AC_DEFINE(HAVE_AS_OFFSETABLE_LO10, 1,
+ [Define if your assembler supports offsetable %lo().])])
+
+ gcc_GAS_CHECK_FEATURE([FMAF, HPC, and VIS 3.0 instructions],
+ gcc_cv_as_sparc_fmaf,
+ [-xarch=v9d],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ fmaddd %f0, %f2, %f4, %f6
+ addxccc %g1, %g2, %g3
+ fsrl32 %f2, %f4, %f8
+ fnaddd %f10, %f12, %f14],,
+ [AC_DEFINE(HAVE_AS_FMAF_HPC_VIS3, 1,
+ [Define if your assembler supports FMAF, HPC, and VIS 3.0 instructions.])])
+
+ gcc_GAS_CHECK_FEATURE([SPARC4 instructions],
+ gcc_cv_as_sparc_sparc4,
+ [-xarch=sparc4],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ cxbe %g2, %g3, 1f
+1: cwbneg %g2, %g3, 1f
+1: sha1
+ md5
+ aes_kexpand0 %f4, %f6, %f8
+ des_round %f38, %f40, %f42, %f44
+ camellia_f %f54, %f56, %f58, %f60
+ kasumi_fi_xor %f46, %f48, %f50, %f52],,
+ [AC_DEFINE(HAVE_AS_SPARC4, 1,
+ [Define if your assembler supports SPARC4 instructions.])])
+
+ gcc_GAS_CHECK_FEATURE([SPARC5 and VIS 4.0 instructions],
+ gcc_cv_as_sparc_sparc5,
+ [-xarch=sparc5],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ subxc %g1, %g2, %g3
+ fpadd8 %f0, %f2, %f4],,
+ [AC_DEFINE(HAVE_AS_SPARC5_VIS4, 1,
+ [Define if your assembler supports SPARC5 and VIS 4.0 instructions.])])
+
+ gcc_GAS_CHECK_FEATURE([SPARC6 instructions],
+ gcc_cv_as_sparc_sparc6,
+ [-xarch=sparc6],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ rd %entropy, %g1
+ fpsll64x %f0, %f2, %f4],,
+ [AC_DEFINE(HAVE_AS_SPARC6, 1,
+ [Define if your assembler supports SPARC6 instructions.])])
+
+ gcc_GAS_CHECK_FEATURE([LEON instructions],
+ gcc_cv_as_sparc_leon,
+ [-Aleon],
+ [.text
+ .register %g2, #scratch
+ .register %g3, #scratch
+ .align 4
+ smac %g2, %g3, %g1
+ umac %g2, %g3, %g1
+ casa [[%g2]] 0xb, %g3, %g1],,
+ [AC_DEFINE(HAVE_AS_LEON, 1,
+ [Define if your assembler supports LEON instructions.])])
+ ;;
+
+changequote(,)dnl
+ i[34567]86-*-* | x86_64-*-*)
+changequote([,])dnl
+ case $target_os in
+ cygwin*)
+ # Full C++ conformance when using a shared libstdc++-v3 requires some
+ # support from the Cygwin DLL, which in more recent versions exports
+ # wrappers to aid in interposing and redirecting operators new, delete,
+ # etc., as per n2800 #17.6.4.6 [replacement.functions]. Check if we
+ # are configuring for a version of Cygwin that exports the wrappers.
+ if test x$host = x$target && test x$host_cpu = xi686; then
+ AC_CHECK_FUNC([__wrap__Znaj],[gcc_ac_cygwin_dll_wrappers=yes],[gcc_ac_cygwin_dll_wrappers=no])
+ else
+ # Can't check presence of libc functions during cross-compile, so
+ # we just have to assume we're building for an up-to-date target.
+ gcc_ac_cygwin_dll_wrappers=yes
+ fi
+ AC_DEFINE_UNQUOTED(USE_CYGWIN_LIBSTDCXX_WRAPPERS,
+ [`if test $gcc_ac_cygwin_dll_wrappers = yes; then echo 1; else echo 0; fi`],
+ [Define if you want to generate code by default that assumes that the
+ Cygwin DLL exports wrappers to support libstdc++ function replacement.])
+ esac
+ case $target_os in
+ cygwin* | pe | mingw32*)
+ # Recent binutils allows the three-operand form of ".comm" on PE. This
+ # definition is used unconditionally to initialise the default state of
+ # the target option variable that governs usage of the feature.
+ gcc_GAS_CHECK_FEATURE([.comm with alignment], gcc_cv_as_comm_has_align,,
+ [.comm foo,1,32])
+ AC_DEFINE_UNQUOTED(HAVE_GAS_ALIGNED_COMM,
+ [`if test $gcc_cv_as_comm_has_align = yes; then echo 1; else echo 0; fi`],
+ [Define if your assembler supports specifying the alignment
+ of objects allocated using the GAS .comm command.])
+ # Used for DWARF 2 in PE
+ gcc_GAS_CHECK_FEATURE([.secrel32 relocs],
+ gcc_cv_as_ix86_pe_secrel32,,
+[.text
+foo: nop
+.data
+ .secrel32 foo],
+ [if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_as_ix86_pe_secrel32=yes
+ fi
+ rm -f conftest],
+ [AC_DEFINE(HAVE_GAS_PE_SECREL32_RELOC, 1,
+ [Define if your assembler and linker support 32-bit section relative relocs via '.secrel32 label'.])])
+ # Test if the assembler supports the extended form of the .section
+ # directive that specifies section alignment. LTO support uses this,
+ # but normally only after installation, so we warn but don't fail the
+ # configure if LTO is enabled but the assembler does not support it.
+ gcc_GAS_CHECK_FEATURE([.section with alignment], gcc_cv_as_section_has_align,
+ -fatal-warnings,[.section lto_test,"dr0"])
+ if test x$gcc_cv_as_section_has_align != xyes; then
+ case ",$enable_languages," in
+ *,lto,*)
+ AC_MSG_WARN([LTO for $target requires binutils >= 2.20.1, but version found appears insufficient; LTO will not work until binutils is upgraded.])
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ case $target_os in
+ darwin2* | darwin19*)
+ gcc_GAS_CHECK_FEATURE([llvm assembler x86-pad-for-align option],
+ gcc_cv_as_mllvm_x86_pad_for_align,
+ [-mllvm -x86-pad-for-align=false], [.text],,
+ [AC_DEFINE(HAVE_AS_MLLVM_X86_PAD_FOR_ALIGN, 1,
+ [Define if your Mac OS X assembler supports -mllvm -x86-pad-for-align=false.])])
+ ;;
+ esac
+
+ gcc_GAS_CHECK_FEATURE([-xbrace_comment], gcc_cv_as_ix86_xbrace_comment,
+ [-xbrace_comment=no], [.text],,
+ [AC_DEFINE(HAVE_AS_XBRACE_COMMENT_OPTION, 1,
+ [Define if your assembler supports -xbrace_comment option.])])
+
+ gcc_GAS_CHECK_FEATURE([filds and fists mnemonics],
+ gcc_cv_as_ix86_filds,,
+ [filds (%ebp); fists (%ebp)],,
+ [AC_DEFINE(HAVE_AS_IX86_FILDS, 1,
+ [Define if your assembler uses filds and fists mnemonics.])])
+
+ gcc_GAS_CHECK_FEATURE([fildq and fistpq mnemonics],
+ gcc_cv_as_ix86_fildq,,
+ [fildq (%ebp); fistpq (%ebp)],,
+ [AC_DEFINE(HAVE_AS_IX86_FILDQ, 1,
+ [Define if your assembler uses fildq and fistq mnemonics.])])
+
+ gcc_GAS_CHECK_FEATURE([cmov syntax],
+ gcc_cv_as_ix86_cmov_sun_syntax,,
+ [cmovl.l %edx, %eax],,
+ [AC_DEFINE(HAVE_AS_IX86_CMOV_SUN_SYNTAX, 1,
+ [Define if your assembler supports the Sun syntax for cmov.])])
+
+ gcc_GAS_CHECK_FEATURE([ffreep mnemonic],
+ gcc_cv_as_ix86_ffreep,,
+ [ffreep %st(1)],,
+ [AC_DEFINE(HAVE_AS_IX86_FFREEP, 1,
+ [Define if your assembler supports the ffreep mnemonic.])])
+
+ gcc_GAS_CHECK_FEATURE([.quad directive],
+ gcc_cv_as_ix86_quad,,
+ [.quad 0],,
+ [AC_DEFINE(HAVE_AS_IX86_QUAD, 1,
+ [Define if your assembler supports the .quad directive.])])
+
+ gcc_GAS_CHECK_FEATURE([sahf mnemonic],
+ gcc_cv_as_ix86_sahf,,
+ [.code64
+ sahf],,
+ [AC_DEFINE(HAVE_AS_IX86_SAHF, 1,
+ [Define if your assembler supports the sahf mnemonic in 64bit mode.])])
+
+ gcc_GAS_CHECK_FEATURE([interunit movq mnemonic],
+ gcc_cv_as_ix86_interunit_movq,,
+ [.code64
+ movq %mm0, %rax
+ movq %rax, %xmm0])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_INTERUNIT_MOVQ,
+ [`if test $gcc_cv_as_ix86_interunit_movq = yes; then echo 1; else echo 0; fi`],
+ [Define if your assembler supports interunit movq mnemonic.])
+
+ gcc_GAS_CHECK_FEATURE([hle prefixes],
+ gcc_cv_as_ix86_hle,,
+ [lock xacquire cmpxchg %esi, (%ecx)],,
+ [AC_DEFINE(HAVE_AS_IX86_HLE, 1,
+ [Define if your assembler supports HLE prefixes.])])
+
+ gcc_GAS_CHECK_FEATURE([swap suffix],
+ gcc_cv_as_ix86_swap,,
+ [movl.s %esp, %ebp],,
+ [AC_DEFINE(HAVE_AS_IX86_SWAP, 1,
+ [Define if your assembler supports the swap suffix.])])
+
+ gcc_GAS_CHECK_FEATURE([different section symbol subtraction],
+ gcc_cv_as_ix86_diff_sect_delta,,
+ [.section .rodata
+.L1:
+ .long .L2-.L1
+ .long .L3-.L1
+ .text
+.L3: nop
+.L2: nop],,
+ [AC_DEFINE(HAVE_AS_IX86_DIFF_SECT_DELTA, 1,
+ [Define if your assembler supports the subtraction of symbols in different sections.])])
+
+ gcc_GAS_CHECK_FEATURE([rep and lock prefix],
+ gcc_cv_as_ix86_rep_lock_prefix,,
+ [rep movsl
+ rep ret
+ rep nop
+ rep bsf %ecx, %eax
+ rep bsr %ecx, %eax
+ lock addl %edi, (%eax,%esi)
+ lock orl $0, (%esp)],,
+ [AC_DEFINE(HAVE_AS_IX86_REP_LOCK_PREFIX, 1,
+ [Define if the assembler supports 'rep <insn>, lock <insn>'.])])
+
+ gcc_GAS_CHECK_FEATURE([ud2 mnemonic],
+ gcc_cv_as_ix86_ud2,,
+ [ud2],,
+ [AC_DEFINE(HAVE_AS_IX86_UD2, 1,
+ [Define if your assembler supports the 'ud2' mnemonic.])])
+
+ # Enforce 32-bit output with gas and gld.
+ if test x$gas = xyes; then
+ as_ix86_gas_32_opt="--32"
+ fi
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ if $gcc_cv_ld -V 2>/dev/null | grep elf_i386_sol2 > /dev/null; then
+ ld_ix86_gld_32_opt="-melf_i386_sol2"
+ else
+ ld_ix86_gld_32_opt="-melf_i386"
+ fi
+ fi
+
+ gcc_GAS_CHECK_FEATURE([R_386_TLS_GD_PLT reloc],
+ gcc_cv_as_ix86_tlsgdplt,
+ [$as_ix86_gas_32_opt],
+ [call tls_gd@tlsgdplt],
+ [if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o -G > /dev/null 2>&1; then
+ gcc_cv_as_ix86_tlsgdplt=yes
+ fi
+ rm -f conftest],
+ [AC_DEFINE(HAVE_AS_IX86_TLSGDPLT, 1,
+ [Define if your assembler and linker support @tlsgdplt.])])
+
+ conftest_s='
+ .section .tdata,"aw'$tls_section_flag'",@progbits
+tls_ld:
+ .section .text,"ax",@progbits
+ call tls_ld@tlsldmplt'
+
+ gcc_GAS_CHECK_FEATURE([R_386_TLS_LDM_PLT reloc],
+ gcc_cv_as_ix86_tlsldmplt,
+ [$as_ix86_gas_32_opt],
+ [$conftest_s],
+ [if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o -G > /dev/null 2>&1; then
+ gcc_cv_as_ix86_tlsldmplt=yes
+ fi
+ rm -f conftest])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_TLSLDMPLT,
+ [`if test $gcc_cv_as_ix86_tlsldmplt = yes; then echo 1; else echo 0; fi`],
+ [Define to 1 if your assembler and linker support @tlsldmplt.])
+
+ conftest_s='
+ .section .text,"ax",@progbits
+ .globl _start
+ .type _start, @function
+_start:
+ leal value@tlsldm(%ebx), %eax
+ call ___tls_get_addr@plt
+
+ .section .tdata,"aw'$tls_section_flag'",@progbits
+ .type value, @object
+value:'
+ gcc_GAS_CHECK_FEATURE([R_386_TLS_LDM reloc],
+ gcc_cv_as_ix86_tlsldm,
+ [$as_ix86_gas_32_opt],
+ [$conftest_s],
+ [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o $ld_tls_libs -lc > /dev/null 2>&1; then
+ if $gcc_cv_objdump -d conftest 2>/dev/null | grep nop > /dev/null \
+ || dis conftest 2>/dev/null | grep nop > /dev/null; then
+ gcc_cv_as_ix86_tlsldm=yes
+ fi
+ fi
+ rm -f conftest])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_TLSLDM,
+ [`if test $gcc_cv_as_ix86_tlsldm = yes; then echo 1; else echo 0; fi`],
+ [Define to 1 if your assembler and linker support @tlsldm.])
+
+ conftest_s='
+ .data
+bar:
+ .byte 1
+ .text
+ .global _start
+_start:
+ cmpl $0, bar@GOT
+ jmp *_start@GOT'
+ gcc_GAS_CHECK_FEATURE([R_386_GOT32X reloc],
+ gcc_cv_as_ix86_got32x,
+ [$as_ix86_gas_32_opt],
+ [$conftest_s],
+ [if test x$gcc_cv_ld != x && test x$gcc_cv_objdump != x \
+ && test x$gcc_cv_readelf != x \
+ && $gcc_cv_readelf --relocs --wide conftest.o 2>&1 \
+ | grep R_386_GOT32X > /dev/null 2>&1 \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o > /dev/null 2>&1; then
+ if $gcc_cv_objdump -dw conftest 2>&1 \
+ | grep 0xffffff > /dev/null 2>&1; then
+ gcc_cv_as_ix86_got32x=no
+ else
+ gcc_cv_as_ix86_got32x=yes
+ fi
+ fi
+ rm -f conftest])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_GOT32X,
+ [`if test x"$gcc_cv_as_ix86_got32x" = xyes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler and linker support @GOT.])
+
+ gcc_GAS_CHECK_FEATURE([GOTOFF in data],
+ gcc_cv_as_ix86_gotoff_in_data,
+ [$as_ix86_gas_32_opt],
+[ .text
+.L0:
+ nop
+ .data
+ .long .L0@GOTOFF])
+ AC_DEFINE_UNQUOTED(HAVE_AS_GOTOFF_IN_DATA,
+ [`if test $gcc_cv_as_ix86_gotoff_in_data = yes; then echo 1; else echo 0; fi`],
+ [Define true if the assembler supports '.long foo@GOTOFF'.])
+
+ conftest_s='
+ .section .text,"ax",@progbits
+ .globl _start
+ .type _start, @function
+_start:
+ leal ld@tlsldm(%ecx), %eax
+ call *___tls_get_addr@GOT(%ecx)
+ leal gd@tlsgd(%ecx), %eax
+ call *___tls_get_addr@GOT(%ecx)
+
+ .section .tdata,"aw'$tls_section_flag'",@progbits
+ .type ld, @object
+ld:
+ .byte 0
+ .globl gd
+ .type gd, @object
+gd:
+ .byte 0'
+ gcc_GAS_CHECK_FEATURE([calling ___tls_get_addr via GOT],
+ gcc_cv_as_ix86_tls_get_addr_via_got,
+ [$as_ix86_gas_32_opt],
+ [$conftest_s],
+ [if test x$gcc_cv_ld != x \
+ && $gcc_cv_ld $ld_ix86_gld_32_opt -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_as_ix86_tls_get_addr_via_got=yes
+ fi
+ rm -f conftest])
+ AC_DEFINE_UNQUOTED(HAVE_AS_IX86_TLS_GET_ADDR_GOT,
+ [`if test x"$gcc_cv_as_ix86_tls_get_addr_via_got" = xyes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your assembler and linker support calling ___tls_get_addr via GOT.])
+ ;;
+
+ ia64*-*-*)
+ gcc_GAS_CHECK_FEATURE([ltoffx and ldxmov relocs],
+ gcc_cv_as_ia64_ltoffx_ldxmov_relocs,,
+[ .text
+ addl r15 = @ltoffx(x#), gp
+ ;;
+ ld8.mov r16 = [[r15]], x#
+],,
+ [AC_DEFINE(HAVE_AS_LTOFFX_LDXMOV_RELOCS, 1,
+ [Define if your assembler supports ltoffx and ldxmov relocations.])])
+
+ ;;
+
+ powerpc*-*-*)
+
+ case $target in
+ *-*-darwin*)
+ gcc_GAS_CHECK_FEATURE([.machine directive support],
+ gcc_cv_as_machine_directive,,
+ [ .machine ppc7400])
+ if test x$gcc_cv_as_machine_directive != xyes; then
+ echo "*** This target requires an assembler supporting \".machine\"" >&2
+ echo you can get it from: https://gcc.gnu.org/pub/gcc/infrastructure/cctools-528.5.dmg >&2
+ test x$build = x$target && exit 1
+ fi
+ ;;
+ esac
+
+ case $target in
+ *-*-aix*) conftest_s=' .machine "pwr5"
+ .csect .text[[PR]]
+ mfcr 3,128';;
+ *-*-darwin*) conftest_s=' .text
+ mfcr r3,128';;
+ *) conftest_s=' .machine power4
+ .text
+ mfcr 3,128';;
+ esac
+
+ gcc_GAS_CHECK_FEATURE([mfcr field support],
+ gcc_cv_as_powerpc_mfcrf,,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_MFCRF, 1,
+ [Define if your assembler supports mfcr field.])])
+
+ case $target in
+ *-*-aix*) conftest_s=' .csect .text[[PR]]
+LCF..0:
+ addis 11,30,_GLOBAL_OFFSET_TABLE_-LCF..0@ha';;
+ *-*-darwin*)
+ conftest_s=' .text
+LCF0:
+ addis r11,r30,_GLOBAL_OFFSET_TABLE_-LCF0@ha';;
+ *) conftest_s=' .text
+.LCF0:
+ addis 11,30,_GLOBAL_OFFSET_TABLE_-.LCF0@ha';;
+ esac
+
+ gcc_GAS_CHECK_FEATURE([rel16 relocs],
+ gcc_cv_as_powerpc_rel16, -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_REL16, 1,
+ [Define if your assembler supports R_PPC_REL16 relocs.])])
+
+ case $target in
+ *-*-aix*) conftest_s=' .machine "pwr7"
+ .csect .text[[PR]]
+ lxvd2x 1,2,3';;
+ *) conftest_s=' .machine power7
+ .text
+ lxvd2x 1,2,3';;
+ esac
+
+ gcc_GAS_CHECK_FEATURE([vector-scalar support],
+ gcc_cv_as_powerpc_vsx, -a32,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_VSX, 1,
+ [Define if your assembler supports VSX instructions.])])
+
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_powerpc_gnu_attribute,,
+ [.gnu_attribute 4,1],,
+ [AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
+ [Define if your assembler supports .gnu_attribute.])])
+
+ gcc_GAS_CHECK_FEATURE([prologue entry point marker support],
+ gcc_cv_as_powerpc_entry_markers,-a64 --fatal-warnings,
+ [ .reloc .,R_PPC64_ENTRY; nop],,
+ [AC_DEFINE(HAVE_AS_ENTRY_MARKERS, 1,
+ [Define if your assembler supports the R_PPC64_ENTRY relocation.])])
+
+ gcc_GAS_CHECK_FEATURE([plt sequence marker support],
+ gcc_cv_as_powerpc_pltseq_markers,-a32 --fatal-warnings,
+ [ .reloc .,R_PPC_PLTSEQ; nop],,
+ [AC_DEFINE(HAVE_AS_PLTSEQ, 1,
+ [Define if your assembler supports R_PPC*_PLTSEQ relocations.])])
+
+ case $target in
+ *-*-aix*)
+ gcc_GAS_CHECK_FEATURE([AIX .ref support],
+ gcc_cv_as_aix_ref,,
+ [ .csect stuff[[rw]]
+ stuff:
+ .long 1
+ .extern sym
+ .ref sym
+ ],,
+ [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
+ ;;
+
+ mips*-*-*)
+ gcc_GAS_CHECK_FEATURE([explicit relocation support],
+ gcc_cv_as_mips_explicit_relocs,,
+[ lw $4,%gp_rel(foo)($4)],,
+ [if test x$target_cpu_default = x
+ then target_cpu_default=MASK_EXPLICIT_RELOCS
+ else target_cpu_default="($target_cpu_default)|MASK_EXPLICIT_RELOCS"
+ fi])
+
+ gcc_GAS_CHECK_FEATURE([-mno-shared support],
+ gcc_cv_as_mips_no_shared,[-mno-shared], [nop],,
+ [AC_DEFINE(HAVE_AS_NO_SHARED, 1,
+ [Define if the assembler understands -mno-shared.])])
+
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_mips_gnu_attribute,,
+ [.gnu_attribute 4,1],,
+ [AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
+ [Define if your assembler supports .gnu_attribute.])])
+
+ gcc_GAS_CHECK_FEATURE([.module support],
+ gcc_cv_as_mips_dot_module,[-32],
+ [.module mips2
+ .module fp=xx],,
+ [AC_DEFINE(HAVE_AS_DOT_MODULE, 1,
+ [Define if your assembler supports .module.])])
+ if test x$gcc_cv_as_mips_dot_module = xno \
+ && test x$with_fp_32 != x; then
+ AC_MSG_ERROR(
+ [Requesting --with-fp-32= requires assembler support for .module.])
+ fi
+
+ gcc_GAS_CHECK_FEATURE([.micromips support],
+ gcc_cv_as_micromips_support,[--fatal-warnings],
+ [.set micromips],,
+ [AC_DEFINE(HAVE_GAS_MICROMIPS, 1,
+ [Define if your assembler supports the .set micromips directive])])
+
+ gcc_GAS_CHECK_FEATURE([.dtprelword support],
+ gcc_cv_as_mips_dtprelword,,
+ [.section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ .dtprelword x+0x8000],,
+ [AC_DEFINE(HAVE_AS_DTPRELWORD, 1,
+ [Define if your assembler supports .dtprelword.])])
+
+ gcc_GAS_CHECK_FEATURE([DSPR1 mult with four accumulators support],
+ gcc_cv_as_mips_dspr1_mult,,
+[ .set mips32r2
+ .set nodspr2
+ .set dsp
+ madd $ac3,$4,$5
+ maddu $ac3,$4,$5
+ msub $ac3,$4,$5
+ msubu $ac3,$4,$5
+ mult $ac3,$4,$5
+ multu $ac3,$4,$5],,
+ [AC_DEFINE(HAVE_AS_DSPR1_MULT, 1,
+ [Define if your assembler supports DSPR1 mult.])])
+
+ AC_MSG_CHECKING(assembler and linker for explicit JALR relocation)
+ gcc_cv_as_ld_jalr_reloc=no
+ if test $gcc_cv_as_mips_explicit_relocs = yes; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 20 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_as_ld_jalr_reloc=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x; then
+ echo ' .ent x' > conftest.s
+ echo 'x: lw $2,%got_disp(y)($3)' >> conftest.s
+ echo ' lw $25,%call16(y)($28)' >> conftest.s
+ echo ' .reloc 1f,R_MIPS_JALR,y' >> conftest.s
+ echo '1: jalr $25' >> conftest.s
+ echo ' .reloc 1f,R_MIPS_JALR,x' >> conftest.s
+ echo '1: jalr $25' >> conftest.s
+ echo ' .end x' >> conftest.s
+ if $gcc_cv_as -o conftest.o conftest.s >/dev/null 2>&AS_MESSAGE_LOG_FD \
+ && $gcc_cv_ld -shared -o conftest.so conftest.o >/dev/null 2>&AS_MESSAGE_LOG_FD; then
+ if $gcc_cv_objdump -d conftest.so | grep jalr >/dev/null 2>&1 \
+ && $gcc_cv_objdump -d conftest.so | grep "bal.*<x>" >/dev/null 2>&1; then
+ gcc_cv_as_ld_jalr_reloc=yes
+ fi
+ fi
+ rm -f conftest.*
+ fi
+ fi
+ if test $gcc_cv_as_ld_jalr_reloc = yes; then
+ if test x$target_cpu_default = x; then
+ target_cpu_default=MASK_RELAX_PIC_CALLS
+ else
+ target_cpu_default="($target_cpu_default)|MASK_RELAX_PIC_CALLS"
+ fi
+ fi
+ AC_MSG_RESULT($gcc_cv_as_ld_jalr_reloc)
+
+ AC_CACHE_CHECK([linker for .eh_frame personality relaxation],
+ [gcc_cv_ld_mips_personality_relaxation],
+ [gcc_cv_ld_mips_personality_relaxation=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 \
+ -a "$gcc_cv_gld_minor_version" -ge 21 \
+ -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_mips_personality_relaxation=yes
+ fi
+ elif test x$gcc_cv_as != x \
+ -a x$gcc_cv_ld != x \
+ -a x$gcc_cv_readelf != x ; then
+ cat > conftest.s <<EOF
+ .cfi_startproc
+ .cfi_personality 0x80,indirect_ptr
+ .ent test
+test:
+ nop
+ .end test
+ .cfi_endproc
+
+ .section .data,"aw",@progbits
+indirect_ptr:
+ .dc.a personality
+EOF
+ if $gcc_cv_as -KPIC -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -o conftest conftest.o -shared > /dev/null 2>&1; then
+ if $gcc_cv_readelf -d conftest 2>&1 \
+ | grep TEXTREL > /dev/null 2>&1; then
+ :
+ elif $gcc_cv_readelf --relocs conftest 2>&1 \
+ | grep 'R_MIPS_REL32 *$' > /dev/null 2>&1; then
+ :
+ else
+ gcc_cv_ld_mips_personality_relaxation=yes
+ fi
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest])
+ if test x$gcc_cv_ld_mips_personality_relaxation = xyes; then
+ AC_DEFINE(HAVE_LD_PERSONALITY_RELAXATION, 1,
+ [Define if your linker can relax absolute .eh_frame personality
+pointers into PC-relative form.])
+ fi
+
+ gcc_GAS_CHECK_FEATURE([-mnan= support],
+ gcc_cv_as_mips_nan,
+ [-mnan=2008],,,
+ [AC_DEFINE(HAVE_AS_NAN, 1,
+ [Define if the assembler understands -mnan=.])])
+ if test x$gcc_cv_as_mips_nan = xno \
+ && test x$with_nan != x; then
+ AC_MSG_ERROR(
+ [Requesting --with-nan= requires assembler support for -mnan=])
+ fi
+ ;;
+ msp430-*-*)
+ # Earlier GAS versions generically support .gnu_attribute, but the
+ # msp430 assembler will not do anything with it.
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_msp430_gnu_attribute,,
+ [.gnu_attribute 4,1],,
+ [AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
+ [Define if your assembler supports .gnu_attribute.])])
+ gcc_GAS_CHECK_FEATURE([.mspabi_attribute support],
+ gcc_cv_as_msp430_mspabi_attribute,,
+ [.mspabi_attribute 4,2],,
+ [AC_DEFINE(HAVE_AS_MSPABI_ATTRIBUTE, 1,
+ [Define if your assembler supports .mspabi_attribute.])])
+ if test x$enable_newlib_nano_formatted_io = xyes; then
+ AC_DEFINE(HAVE_NEWLIB_NANO_FORMATTED_IO, 1, [Define if GCC has been
+configured with --enable-newlib-nano-formatted-io.])
+ fi
+ ;;
+ nios2-*-*)
+ # Versions 2.33 and earlier lacked support for the %gotoff relocation
+ # syntax that is documented in the ABI specification.
+ gcc_GAS_CHECK_FEATURE([support for %gotoff relocations in constant data],
+ gcc_cv_as_nios2_gotoff_relocation,,
+[ .extern foo
+ .data
+ .long %gotoff(foo)],,
+ [AC_DEFINE(HAVE_AS_NIOS2_GOTOFF_RELOCATION, 1,
+ [Define if your assembler supports %gotoff relocation syntax.])])
+ ;;
+ riscv*-*-*)
+ gcc_GAS_CHECK_FEATURE([.attribute support],
+ gcc_cv_as_riscv_attribute,,
+ [.attribute stack_align,4],,
+ [AC_DEFINE(HAVE_AS_RISCV_ATTRIBUTE, 1,
+ [Define if your assembler supports .attribute.])])
+ gcc_GAS_CHECK_FEATURE([-misa-spec= support],
+ gcc_cv_as_riscv_isa_spec,
+ [-misa-spec=2.2],,,
+ [AC_DEFINE(HAVE_AS_MISA_SPEC, 1,
+ [Define if the assembler understands -misa-spec=.])])
+ gcc_GAS_CHECK_FEATURE([-march=rv32i_zifencei support],
+ gcc_cv_as_riscv_march_zifencei,
+ [-march=rv32i_zifencei2p0],,,
+ [AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1,
+ [Define if the assembler understands -march=rv*_zifencei.])])
+ ;;
+ loongarch*-*-*)
+ gcc_GAS_CHECK_FEATURE([.dtprelword support],
+ gcc_cv_as_loongarch_dtprelword, [2,18,0],,
+ [.section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+ .dtprelword x+0x8000],,
+ [AC_DEFINE(HAVE_AS_DTPRELWORD, 1,
+ [Define if your assembler supports .dtprelword.])])
+ ;;
+ s390*-*-*)
+ gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
+ gcc_cv_as_s390_gnu_attribute,,
+ [.gnu_attribute 8,1],,
+ [AC_DEFINE(HAVE_AS_GNU_ATTRIBUTE, 1,
+ [Define if your assembler supports .gnu_attribute.])])
+ gcc_GAS_CHECK_FEATURE([.machine and .machinemode support],
+ gcc_cv_as_s390_machine_machinemode,,
+ [ .machinemode push
+ .machinemode pop
+ .machine push
+ .machine pop],,
+ [AC_DEFINE(HAVE_AS_MACHINE_MACHINEMODE, 1,
+ [Define if your assembler supports .machine and .machinemode.])])
+ gcc_GAS_CHECK_FEATURE([architecture modifiers support],
+ gcc_cv_as_s390_architecture_modifiers,,
+ [ .machine z13+vx ],,
+ [AC_DEFINE(HAVE_AS_ARCHITECTURE_MODIFIERS, 1,
+ [Define if your assembler supports architecture modifiers.])])
+ gcc_GAS_CHECK_FEATURE([vector load/store alignment hints],
+ gcc_cv_as_s390_vector_loadstore_alignment_hints,,
+ [ vl %v24,0(%r15),3 ],,
+ [AC_DEFINE(HAVE_AS_VECTOR_LOADSTORE_ALIGNMENT_HINTS, 1,
+ [Define if your assembler supports vl/vst/vlm/vstm with an optional alignment hint argument.])])
+ gcc_GAS_CHECK_FEATURE([vector load/store alignment hints on z13],
+ gcc_cv_as_s390_vector_loadstore_alignment_hints_on_z13, [-mzarch -march=z13],
+ [ vl %v24,0(%r15),3 ],,
+ [AC_DEFINE(HAVE_AS_VECTOR_LOADSTORE_ALIGNMENT_HINTS_ON_Z13, 1,
+ [Define if your assembler supports vl/vst/vlm/vstm with an optional alignment hint argument on z13.])])
+
+ ;;
+esac
+
+# Mips, LoongArch and HP-UX need the GNU assembler.
+# Linux on IA64 might be able to use the Intel assembler.
+
+case "$target" in
+ mips*-*-* | loongarch*-*-* | *-*-hpux* )
+ if test x$gas_flag = xyes \
+ || test x"$host" != x"$build" \
+ || test ! -x "$gcc_cv_as" \
+ || "$gcc_cv_as" -v < /dev/null 2>&1 | grep GNU > /dev/null; then
+ :
+ else
+ echo "*** This configuration requires the GNU assembler" >&2
+ exit 1
+ fi
+ ;;
+esac
+
+# This tests if the assembler supports two registers for global_load functions
+# (like in LLVM versions <12) or one register (like in LLVM 12).
+case "$target" in
+ amdgcn-* | gcn-*)
+ AC_MSG_CHECKING(assembler fix for global_load functions)
+ gcc_cv_as_gcn_global_load_fixed=yes
+ if test x$gcc_cv_as != x; then
+ cat > conftest.s <<EOF
+ global_store_dwordx2 v[[1:2]], v[[4:5]], s[[14:15]]
+EOF
+ if $gcc_cv_as -triple=amdgcn--amdhsa -filetype=obj -mcpu=gfx900 -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_gcn_global_load_fixed=no
+ fi
+ rm -f conftest.s conftest.o conftest
+ fi
+ global_load_fixed=`if test x$gcc_cv_as_gcn_global_load_fixed = xyes; then echo 1; else echo 0; fi`
+ AC_DEFINE_UNQUOTED(HAVE_GCN_ASM_GLOBAL_LOAD_FIXED, $global_load_fixed,
+ [Define if your assembler has fixed global_load functions.])
+ AC_MSG_RESULT($gcc_cv_as_gcn_global_load_fixed)
+ ;;
+esac
+
+case "$target" in
+ amdgcn-* | gcn-*)
+ # Test the LLVM assembler syntax dialect; they have made a number of
+ # changes between LLVM 12 & 13 without any backward compatibility.
+ gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v2/3 syntax],
+ gcc_cv_as_gcn_asm_v3_syntax,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack],
+ [.amdgcn_target "amdgcn-unknown-amdhsa--gfx906+xnack"],,
+ [AC_DEFINE(HAVE_GCN_ASM_V3_SYNTAX, 1,
+ [Define if your assembler expects amdgcn_target gfx908+xnack syntax.])])
+ gcc_GAS_CHECK_FEATURE([assembler amdgcn_target v4 syntax],
+ gcc_cv_as_gcn_asm_v4_syntax,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack],
+ [.amdgcn_target "amdgcn-unknown-amdhsa--gfx908:xnack+"],,
+ [AC_DEFINE(HAVE_GCN_ASM_V4_SYNTAX, 1,
+ [Define if your assembler expects amdgcn_target gfx908:xnack+ syntax.])])
+
+ # Some attribute names changed in the move to v4 ...
+ if test $gcc_cv_as_gcn_asm_v3_syntax = yes; then
+ sramopt="+sram-ecc"
+ sramattr="+sram-ecc"
+ xnackattr="+xnack"
+ elif test $gcc_cv_as_gcn_asm_v4_syntax = yes; then
+ sramopt="+sramecc"
+ sramattr=":sramecc+"
+ xnackattr=":xnack+"
+ else
+ AC_MSG_ERROR([Unrecognised assembler version])
+ fi
+
+ # Test whether the LLVM assembler accepts -mattr=+xnack without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # LLVM 12+ throws a warning for GPUs without support.
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for fiji],
+ gcc_cv_as_gcn_xnack_ecc_fiji,
+ [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_fiji=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_FIJI, 1,
+ [Define if your assembler allows -mattr=+xnack for fiji.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx900],
+ gcc_cv_as_gcn_xnack_ecc_gfx900,
+ [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx900=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX900, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx900.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx906],
+ gcc_cv_as_gcn_xnack_ecc_gfx906,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx906=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX906, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx906.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=+xnack for gfx908],
+ gcc_cv_as_gcn_xnack_ecc_gfx908,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=+xnack 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_xnack_ecc_gfx908=yes],
+ [AC_DEFINE(HAVE_GCN_XNACK_GFX908, 1,
+ [Define if your assembler allows -mattr=+xnack for gfx908.])])
+ rm -f conftest.err
+
+ # Test whether the LLVM assembler accepts -mattr=+sramecc without any
+ # diagnostic. LLVM 9 & 10 accept the option whether it makes sense or not,
+ # (some?) LLVM 12 rejects it for all GPUs, and LLVM13 throws a warning
+ # for GPUs without support.
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for fiji],
+ gcc_cv_as_gcn_sram_ecc_fiji,
+ [-triple=amdgcn--amdhsa -mcpu=fiji -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_fiji=yes],
+ [AC_DEFINE(HAVE_GCN_SRAM_ECC_FIJI, 1,
+ [Define if your assembler allows -mattr=+sramecc for fiji.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx900],
+ gcc_cv_as_gcn_sram_ecc_gfx900,
+ [-triple=amdgcn--amdhsa -mcpu=gfx900 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx900=yes],
+ [AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX900, 1,
+ [Define if your assembler allows -mattr=+sramecc for gfx900.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx906],
+ gcc_cv_as_gcn_sram_ecc_gfx906,
+ [-triple=amdgcn--amdhsa -mcpu=gfx906 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx906=yes],
+ [AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX906, 1,
+ [Define if your assembler allows -mattr=+sramecc for gfx906.])])
+ rm -f conftest.err
+ gcc_GAS_CHECK_FEATURE([assembler accepts -mattr=$sramopt for gfx908],
+ gcc_cv_as_gcn_sram_ecc_gfx908,
+ [-triple=amdgcn--amdhsa -mcpu=gfx908 -mattr=$sramopt 2>conftest.err], [],
+ [grep "." conftest.err >&AS_MESSAGE_LOG_FD \
+ || gcc_cv_as_gcn_sram_ecc_gfx908=yes],
+ [AC_DEFINE(HAVE_GCN_SRAM_ECC_GFX908, 1,
+ [Define if your assembler allows -mattr=+sramecc for gfx908.])])
+ rm -f conftest.err
+ ;;
+ arm*)
+ gcc_GAS_CHECK_FEATURE([assembler for arm accepts context-specific architecture extensions],
+ gcc_cv_as_arm_option_extensions,
+ [-march=armv8.1-m.main+mve],
+ [.text
+ .thumb
+ .syntax unified
+ vmov.f32 s0, s1],,
+ [AC_DEFINE(HAVE_GAS_ARM_EXTENDED_ARCH, 1,
+ [Define if your Arm assembler permits context-specific feature extensions.])])
+esac
+
+# ??? Not all targets support dwarf2 debug_line, even within a version
+# of gas. Moreover, we need to emit a valid instruction to trigger any
+# info to the output file. So, as supported targets are added to gas 2.11,
+# add some instruction here to (also) show we expect this might work.
+# ??? Once 2.11 is released, probably need to add first known working
+# version to the per-target configury.
+case "$cpu_type" in
+ aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | loongarch | m32c \
+ | m68k | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \
+ | tilegx | tilepro | visium | xstormy16 | xtensa)
+ insn="nop"
+ ;;
+ ia64 | s390)
+ insn="nop 0"
+ ;;
+ mmix)
+ insn="swym 0"
+ ;;
+esac
+if test x"$insn" != x; then
+ conftest_s="\
+ .file 1 \"conftest.s\"
+ .loc 1 3 0
+ $insn"
+ gcc_GAS_CHECK_FEATURE([dwarf2 debug_line support],
+ gcc_cv_as_dwarf2_debug_line,,
+ [$conftest_s],
+ [if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -h conftest.o 2> /dev/null \
+ | grep debug_line > /dev/null 2>&1; then
+ gcc_cv_as_dwarf2_debug_line=yes
+ elif test x$gcc_cv_otool != x \
+ && $gcc_cv_otool -l conftest.o 2> /dev/null \
+ | grep debug_line > /dev/null 2>&1; then
+ gcc_cv_as_dwarf2_debug_line=yes
+ fi])
+
+# The .debug_line file table must be in the exact order that
+# we specified the files, since these indices are also used
+# by DW_AT_decl_file. Approximate this test by testing if
+# the assembler bitches if the same index is assigned twice.
+ gcc_GAS_CHECK_FEATURE([buggy dwarf2 .file directive],
+ gcc_cv_as_dwarf2_file_buggy,,
+[ .file 1 "foo.s"
+ .file 1 "bar.s"])
+
+ if test $gcc_cv_as_dwarf2_debug_line = yes \
+ && test $gcc_cv_as_dwarf2_file_buggy = no; then
+ AC_DEFINE(HAVE_AS_DWARF2_DEBUG_LINE, 1,
+ [Define if your assembler supports dwarf2 .file/.loc directives,
+ and preserves file table indices exactly as given.])
+
+ if test $gcc_cv_as_leb128 = yes; then
+ conftest_s="\
+ .file 1 \"conftest.s\"
+ .loc 1 3 0 view .LVU1
+ $insn
+ .data
+ .uleb128 .LVU1
+ .uleb128 .LVU1
+"
+ gcc_GAS_CHECK_FEATURE([dwarf2 debug_view support],
+ gcc_cv_as_dwarf2_debug_view,,
+ [$conftest_s],,
+ [AC_DEFINE(HAVE_AS_DWARF2_DEBUG_VIEW, 1,
+ [Define if your assembler supports views in dwarf2 .loc directives.])])
+ fi
+ fi
+
+ gcc_GAS_CHECK_FEATURE([--gdwarf2 option],
+ gcc_cv_as_gdwarf2_flag,
+ [--gdwarf2], [$insn],,
+ [AC_DEFINE(HAVE_AS_GDWARF2_DEBUG_FLAG, 1,
+[Define if your assembler supports the --gdwarf2 option.])])
+
+ gcc_GAS_CHECK_FEATURE([--gdwarf-5 option],
+ gcc_cv_as_gdwarf_5_flag,
+ [--gdwarf-5], [$insn],
+ [if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -Wi conftest.o 2>&1 \
+ | grep DW_TAG_compile_unit > /dev/null 2>&1; then
+ gcc_cv_as_gdwarf_5_flag=yes;
+ fi],[AC_DEFINE(HAVE_AS_GDWARF_5_DEBUG_FLAG, 1,
+[Define if your assembler supports the --gdwarf-5 option.])])
+
+ case $target_os in
+ win32 | pe | cygwin* | mingw32*)
+ section_flags=\"dr\"
+ function_type=".def foo; .scl 2; .type 32; .endef"
+ function_size="";;
+ *)
+ section_flags=\"\",%progbits
+ function_type=".type foo, %function"
+ function_size=".size foo, .-foo";;
+ esac
+ dwarf4_debug_info_size=0x46
+ dwarf4_high_pc_form=7
+ dwarf4_debug_aranges_size=0x2c
+ dwarf4_line_sz=9
+ for dwarf4_addr_size in 8 4; do
+ conftest_s="\
+ .file \"a.c\"
+ .text
+.Ltext0:
+ .p2align 4
+ .globl foo
+ $function_type
+foo:
+.LFB0:
+.LM1:
+ $insn
+.LM2:
+.LFE0:
+ $function_size
+.Letext0:
+ .section .debug_info,$section_flags
+.Ldebug_info0:
+ .4byte $dwarf4_debug_info_size
+ .2byte 0x4
+ .4byte .Ldebug_abbrev0
+ .byte 0x$dwarf4_addr_size
+ .byte 0x1
+ .ascii \"GNU C17\\0\"
+ .byte 0xc
+ .ascii \"a.c\\0\"
+ .ascii \"/\\0\"
+ .${dwarf4_addr_size}byte .Ltext0
+ .${dwarf4_addr_size}byte .Letext0-.Ltext0
+ .4byte .Ldebug_line0
+ .byte 0x2
+ .ascii \"foo\\0\"
+ .byte 0x1
+ .byte 0x2
+ .byte 0x1
+ .${dwarf4_addr_size}byte .LFB0
+ .${dwarf4_addr_size}byte .LFE0-.LFB0
+ .byte 0x1
+ .byte 0x9c
+ .byte 0
+ .section .debug_abbrev,$section_flags
+.Ldebug_abbrev0:
+ .byte 0x1
+ .byte 0x11
+ .byte 0x1
+ .byte 0x25
+ .byte 0x8
+ .byte 0x13
+ .byte 0xb
+ .byte 0x3
+ .byte 0x8
+ .byte 0x1b
+ .byte 0x8
+ .byte 0x11
+ .byte 0x1
+ .byte 0x12
+ .byte 0x$dwarf4_high_pc_form
+ .byte 0x10
+ .byte 0x17
+ .byte 0
+ .byte 0
+ .byte 0x2
+ .byte 0x2e
+ .byte 0
+ .byte 0x3f
+ .byte 0x19
+ .byte 0x3
+ .byte 0x8
+ .byte 0x3a
+ .byte 0xb
+ .byte 0x3b
+ .byte 0xb
+ .byte 0x39
+ .byte 0xb
+ .byte 0x11
+ .byte 0x1
+ .byte 0x12
+ .byte 0x$dwarf4_high_pc_form
+ .byte 0x40
+ .byte 0x18
+ .byte 0
+ .byte 0
+ .byte 0
+ .section .debug_aranges,$section_flags
+ .4byte $dwarf4_debug_aranges_size
+ .2byte 0x2
+ .4byte .Ldebug_info0
+ .byte 0x8
+ .byte 0
+ .2byte 0
+ .2byte 0
+ .${dwarf4_addr_size}byte .Ltext0
+ .${dwarf4_addr_size}byte .Letext0-.Ltext0
+ .${dwarf4_addr_size}byte 0
+ .${dwarf4_addr_size}byte 0
+ .section .debug_line,$section_flags
+.Ldebug_line0:
+ .4byte .LELT0-.LSLT0
+.LSLT0:
+ .2byte 0x4
+ .4byte .LELTP0-.LASLTP0
+.LASLTP0:
+ .byte 0x1
+ .byte 0x1
+ .byte 0x1
+ .byte 0xf6
+ .byte 0xf2
+ .byte 0xd
+ .byte 0
+ .byte 0x1
+ .byte 0x1
+ .byte 0x1
+ .byte 0x1
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0x1
+ .byte 0
+ .byte 0
+ .byte 0x1
+ .byte 0
+ .ascii \"a.c\\0\"
+ .byte 0
+ .byte 0
+ .byte 0
+ .byte 0
+.LELTP0:
+ .byte 0
+ .byte 0x$dwarf4_line_sz
+ .byte 0x2
+ .${dwarf4_addr_size}byte .LM1
+ .byte 0x18
+ .byte 0x5
+ .byte 0x1
+ .byte 0
+ .byte 0x$dwarf4_line_sz
+ .byte 0x2
+ .${dwarf4_addr_size}byte .LM2
+ .byte 0x1
+ .byte 0x5
+ .byte 0x1
+ .byte 0
+ .byte 0x$dwarf4_line_sz
+ .byte 0x2
+ .${dwarf4_addr_size}byte .Letext0
+ .byte 0
+ .byte 0x1
+ .byte 0x1
+.LELT0:
+ .section .debug_str,$section_flags
+ .ident \"GCC\"
+"
+ dwarf4_success=no
+ if test $dwarf4_addr_size = 4; then
+ gcc_GAS_CHECK_FEATURE([assembly of compiler generated 32-bit .debug_line],
+ gcc_cv_as_debug_line_32_flag,,
+ [$conftest_s],,
+ [dwarf4_success=yes])
+ else
+ gcc_GAS_CHECK_FEATURE([assembly of compiler generated 64-bit .debug_line],
+ gcc_cv_as_debug_line_64_flag,,
+ [$conftest_s],,
+ [dwarf4_success=yes])
+ fi
+ if test $dwarf4_success = yes; then
+ dwarf4_success=no
+ gcc_GAS_CHECK_FEATURE([--gdwarf-4 not refusing compiler generated .debug_line],
+ gcc_cv_as_dwarf_4_debug_line_flag,
+ [--gdwarf-4], [$conftest_s],,
+ [dwarf4_success=yes])
+ break
+ fi
+ dwarf4_debug_info_size=0x36
+ dwarf4_high_pc_form=6
+ dwarf4_debug_aranges_size=0x1c
+ dwarf4_line_sz=5
+ done
+
+ if test $dwarf4_success = yes; then
+ conftest_s="\
+ .file \"foo.c\"
+ .text
+bar:
+#APP
+# 82 \"xxx.h\" 1
+ $insn
+# 0 \"\" 2
+#NO_APP
+ $insn
+foo:
+ .file 1 \"foo.c\"
+ $insn
+ .file 2 \"foo.h\"
+ ret
+"
+ dwarf4_success=no
+ gcc_GAS_CHECK_FEATURE([--gdwarf-4 with the APP marker],
+ gcc_cv_as_dwarf_4_app_flag,
+ [--gdwarf-4], [$conftest_s],, [dwarf4_success=yes])
+ fi
+
+ if test $dwarf4_success = yes; then
+ conftest_s="\
+ .text
+ .globl foo
+ $function_type
+foo:
+ $insn
+ $function_size
+ .file 1 \"foo.c\"
+"
+ gcc_GAS_CHECK_FEATURE([working --gdwarf-4/--gdwarf-5 for all sources],
+ gcc_cv_as_working_gdwarf_n_flag,
+ [--gdwarf-4],
+ [$conftest_s],
+ [changequote(,)dnl
+ if test x$gcc_cv_objdump != x \
+ && $gcc_cv_objdump -W conftest.o 2>&1 \
+ | grep conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_working_gdwarf_n_flag=no
+ else
+ gcc_cv_as_working_gdwarf_n_flag=yes
+ fi
+ changequote([,])dnl])
+ if test $gcc_cv_as_working_gdwarf_n_flag = yes; then
+ AC_DEFINE(HAVE_AS_WORKING_DWARF_N_FLAG, 1,
+[Define if your assembler supports --gdwarf-4/--gdwarf-5 even with
+ compiler generated .debug_line.])
+ 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],,
+ [AC_DEFINE(HAVE_AS_DEBUG_PREFIX_MAP, 1,
+[Define if your assembler supports the --debug-prefix-map option.])])
+fi
+
+gcc_GAS_CHECK_FEATURE([compressed debug sections],
+ gcc_cv_as_compress_debug,,,
+ [# gas compiled without zlib cannot compress debug sections and warns
+ # about it, but still exits successfully. So check for this, too.
+ if $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s 2>&1 | grep -i warning > /dev/null
+ then
+ gcc_cv_as_compress_debug=0
+ # Since binutils 2.26, gas supports --compress-debug-sections=type,
+ # defaulting to the ELF gABI format.
+ elif $gcc_cv_as --compress-debug-sections=zlib-gnu -o conftest.o conftest.s > /dev/null 2>&1
+ then
+ gcc_cv_as_compress_debug=2
+ gcc_cv_as_compress_debug_option="--compress-debug-sections"
+ gcc_cv_as_no_compress_debug_option="--nocompress-debug-sections"
+ # Before binutils 2.26, gas only supported --compress-debug-options and
+ # emitted the traditional GNU format.
+ elif $gcc_cv_as --compress-debug-sections -o conftest.o conftest.s > /dev/null 2>&1
+ then
+ gcc_cv_as_compress_debug=1
+ gcc_cv_as_compress_debug_option="--compress-debug-sections"
+ gcc_cv_as_no_compress_debug_option="--nocompress-debug-sections"
+ else
+ gcc_cv_as_compress_debug=0
+ fi])
+AC_DEFINE_UNQUOTED(HAVE_AS_COMPRESS_DEBUG, $gcc_cv_as_compress_debug,
+[Define to the level of your assembler's compressed debug section support.])
+AC_DEFINE_UNQUOTED(AS_COMPRESS_DEBUG_OPTION, "$gcc_cv_as_compress_debug_option",
+[Define to the assembler option to enable compressed debug sections.])
+AC_DEFINE_UNQUOTED(AS_NO_COMPRESS_DEBUG_OPTION, "$gcc_cv_as_no_compress_debug_option",
+[Define to the assembler option to disable compressed debug sections.])
+
+gcc_GAS_CHECK_FEATURE([.lcomm with alignment], gcc_cv_as_lcomm_with_alignment,,
+[.lcomm bar,4,16],,
+[AC_DEFINE(HAVE_GAS_LCOMM_WITH_ALIGNMENT, 1,
+ [Define if your assembler supports .lcomm with an alignment field.])])
+
+if test x$with_sysroot = x && test x$host = x$target \
+ && test "$prefix" != "/usr" && test "x$prefix" != "x$local_prefix" \
+ && test "$prefix" != "NONE"; then
+ AC_DEFINE_UNQUOTED(PREFIX_INCLUDE_DIR, "$prefix/include",
+[Define to PREFIX/include if cpp should also search that directory.])
+fi
+
+# Determine the version of glibc, if any, used on the target.
+AC_MSG_CHECKING([for target glibc version])
+AC_ARG_WITH([glibc-version],
+ [AS_HELP_STRING([--with-glibc-version=M.N],
+ [assume GCC used with glibc version M.N or later])], [
+if [echo "$with_glibc_version" | grep '^[0-9][0-9]*\.[0-9][0-9]*$']; then
+ glibc_version_major=`echo "$with_glibc_version" | sed -e 's/\..*//'`
+ glibc_version_minor=`echo "$with_glibc_version" | sed -e 's/.*\.//'`
+else
+ AC_MSG_ERROR([option --with-glibc-version requires a version number M.N])
+fi], [
+glibc_version_major=0
+glibc_version_minor=0
+[if test -f $target_header_dir/features.h \
+ && glibc_version_major_define=`$EGREP '^[ ]*#[ ]*define[ ]+__GLIBC__[ ]+[0-9]' $target_header_dir/features.h` \
+ && glibc_version_minor_define=`$EGREP '^[ ]*#[ ]*define[ ]+__GLIBC_MINOR__[ ]+[0-9]' $target_header_dir/features.h`; then
+ glibc_version_major=`echo "$glibc_version_major_define" | sed -e 's/.*__GLIBC__[ ]*//'`
+ glibc_version_minor=`echo "$glibc_version_minor_define" | sed -e 's/.*__GLIBC_MINOR__[ ]*//'`
+fi]])
+AC_MSG_RESULT([$glibc_version_major.$glibc_version_minor])
+AC_DEFINE_UNQUOTED([TARGET_GLIBC_MAJOR], [$glibc_version_major],
+[GNU C Library major version number used on the target, or 0.])
+AC_DEFINE_UNQUOTED([TARGET_GLIBC_MINOR], [$glibc_version_minor],
+[GNU C Library minor version number used on the target, or 0.])
+
+AC_ARG_ENABLE(gnu-unique-object,
+ [AS_HELP_STRING([--enable-gnu-unique-object],
+ [enable the use of the @gnu_unique_object ELF extension on glibc systems])],
+ [case $enable_gnu_unique_object in
+ yes | no) ;;
+ *) AC_MSG_ERROR(['$enable_gnu_unique_object' is an invalid value for --enable-gnu-unique-object.
+Valid choices are 'yes' and 'no'.]) ;;
+ esac],
+ [gcc_GAS_CHECK_FEATURE([gnu_unique_object], gcc_cv_as_gnu_unique_object,,
+ [.type foo, '$target_type_format_char'gnu_unique_object],,
+# We need to unquote above to to use the definition from config.gcc.
+# Also check for ld.so support, i.e. glibc 2.11 or higher.
+ [GCC_GLIBC_VERSION_GTE_IFELSE([2], [11], [enable_gnu_unique_object=yes], )]
+ )])
+if test x$enable_gnu_unique_object = xyes; then
+ AC_DEFINE(HAVE_GAS_GNU_UNIQUE_OBJECT, 1,
+ [Define if your assembler supports @gnu_unique_object.])
+fi
+
+AC_CACHE_CHECK([assembler for tolerance to line number 0],
+ [gcc_cv_as_line_zero],
+ [gcc_cv_as_line_zero=no
+ if test "x$gcc_cv_as" != x; then
+ { echo '# 1 "test.s" 1'; echo '# 0 "" 2'; } > conftest.s
+ if AC_TRY_COMMAND([$gcc_cv_as -o conftest.o conftest.s >&AS_MESSAGE_LOG_FD 2>conftest.out]) &&
+ test "x`cat conftest.out`" = x
+ then
+ gcc_cv_as_line_zero=yes
+ else
+ echo "configure: failed program was" >&AS_MESSAGE_LOG_FD
+ cat conftest.s >&AS_MESSAGE_LOG_FD
+ echo "configure: error output was" >&AS_MESSAGE_LOG_FD
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ fi
+ rm -f conftest.o conftest.s conftest.out
+ fi])
+if test "x$gcc_cv_as_line_zero" = xyes; then
+ AC_DEFINE([HAVE_AS_LINE_ZERO], 1,
+[Define if the assembler won't complain about a line such as # 0 "" 2.])
+fi
+
+AC_MSG_CHECKING(support for thin archives)
+thin_archive_support=no
+echo 'int main (void) { return 0; }' > conftest.c
+if ($AR --version | sed 1q | grep "GNU ar" \
+ && $CC $CFLAGS -c conftest.c \
+ && $AR rcT conftest.a conftest.o \
+ && $CC $CFLAGS $LDFLAGS -o conftest conftest.a) >/dev/null 2>&1; then
+ thin_archive_support=yes
+fi
+rm -f conftest.c conftest.o conftest.a conftest
+AC_MSG_RESULT($thin_archive_support)
+AC_SUBST(thin_archive_support)
+
+AC_MSG_CHECKING(linker PT_GNU_EH_FRAME support)
+gcc_cv_ld_eh_frame_hdr=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_frame_hdr=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ # Check if linker supports --eh-frame-hdr option
+ if $gcc_cv_ld --help 2>&1 | grep eh-frame-hdr > /dev/null; then
+ gcc_cv_ld_eh_frame_hdr=yes
+ fi
+ else
+ case "$target" in
+ *-*-solaris2*)
+ # Sun ld has various bugs in .eh_frame_hdr support before version 1.2251.
+ if test "$ld_vers_major" -gt 1 || test "$ld_vers_minor" -ge 2251; then
+ gcc_cv_ld_eh_frame_hdr=yes
+ fi
+ ;;
+ esac
+ fi
+fi
+GCC_TARGET_TEMPLATE([HAVE_LD_EH_FRAME_HDR])
+if test x"$gcc_cv_ld_eh_frame_hdr" = xyes; then
+ AC_DEFINE(HAVE_LD_EH_FRAME_HDR, 1,
+[Define if your linker supports .eh_frame_hdr.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_eh_frame_hdr)
+
+AC_MSG_CHECKING(linker CIEv3 in .eh_frame support)
+gcc_cv_ld_eh_frame_ciev3=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_frame_ciev3=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ gcc_cv_ld_eh_frame_ciev3=yes
+ if test 0"$ld_date" -lt 20040513; then
+ if test -n "$ld_date"; then
+ # If there was date string, but was earlier than 2004-05-13, fail
+ gcc_cv_ld_eh_frame_ciev3=no
+ elif test "$ld_vers_major" -lt 2; then
+ gcc_cv_ld_eh_frame_ciev3=no
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 16; then
+ gcc_cv_ld_eh_frame_ciev3=no
+ fi
+ fi
+ else
+ case "$target" in
+ *-*-solaris2*)
+ # Sun ld added support for CIE v3 in .eh_frame in Solaris 11.1.
+ if test "$ld_vers_major" -gt 1 || test "$ld_vers_minor" -ge 2324; then
+ gcc_cv_ld_eh_frame_ciev3=yes
+ fi
+ ;;
+ esac
+ fi
+fi
+AC_DEFINE_UNQUOTED(HAVE_LD_EH_FRAME_CIEV3,
+ [`if test x"$gcc_cv_ld_eh_frame_ciev3" = xyes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your linker supports CIE v3 in .eh_frame.])
+AC_MSG_RESULT($gcc_cv_ld_eh_frame_ciev3)
+
+AC_MSG_CHECKING(linker position independent executable support)
+gcc_cv_ld_pie=no
+if test $in_tree_ld = yes ; then
+ case "$target" in
+ # Full PIE support on Solaris was only introduced in gld 2.26.
+ *-*-solaris2*) gcc_gld_pie_min_version=26 ;;
+ *) gcc_gld_pie_min_version=15 ;;
+ esac
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge "$gcc_gld_pie_min_version" -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_pie=yes
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -pie option
+ if $gcc_cv_ld --help 2>&1 | grep -- -pie > /dev/null; then
+ gcc_cv_ld_pie=yes
+ case "$target" in
+ *-*-solaris2*)
+ if echo "$ld_ver" | grep GNU > /dev/null \
+ && test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 26; then
+ gcc_cv_ld_pie=no
+ fi
+ ;;
+ esac
+ else
+ case "$target" in
+ *-*-solaris2.1[[1-9]]*)
+ # Solaris 11.3 added PIE support.
+ if $gcc_cv_ld -z help 2>&1 | grep -- type.*pie > /dev/null; then
+ gcc_cv_ld_pie=yes
+ fi
+ ;;
+ esac
+ fi
+fi
+if test x"$gcc_cv_ld_pie" = xyes; then
+ AC_DEFINE(HAVE_LD_PIE, 1,
+[Define if your linker supports PIE option.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_pie)
+
+AC_MSG_CHECKING(linker PIE support with copy reloc)
+gcc_cv_ld_pie_copyreloc=no
+if test $gcc_cv_ld_pie = yes ; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_pie_copyreloc=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ # Check if linker supports -pie option with copy reloc
+ case "$target" in
+ i?86-*-linux* | x86_64-*-linux*)
+ cat > conftest1.s <<EOF
+ .globl a_glob
+ .data
+ .type a_glob, @object
+ .size a_glob, 4
+a_glob:
+ .long 2
+EOF
+ cat > conftest2.s <<EOF
+ .text
+ .globl main
+ .type main, @function
+main:
+ movl %eax, a_glob(%rip)
+ .size main, .-main
+ .globl ptr
+ .section .data.rel,"aw",@progbits
+ .type ptr, @object
+ptr:
+ .quad a_glob
+EOF
+ if $gcc_cv_as --64 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \
+ && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then
+ gcc_cv_ld_pie_copyreloc=yes
+ fi
+ rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s
+ ;;
+ esac
+ fi
+fi
+AC_DEFINE_UNQUOTED(HAVE_LD_PIE_COPYRELOC,
+ [`if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`],
+ [Define 0/1 if your linker supports -pie option with copy reloc.])
+AC_MSG_RESULT($gcc_cv_ld_pie_copyreloc)
+
+AC_MSG_CHECKING(linker EH-compatible garbage collection of sections)
+gcc_cv_ld_eh_gc_sections=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 17 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_gc_sections=yes
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x ; then
+ cat > conftest.s <<EOF
+ .section .text
+.globl _start
+ .type _start, @function
+_start:
+ .long foo
+ .size _start, .-_start
+ .section .text.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .long 0
+ .size foo, .-foo
+ .section .gcc_except_table.foo,"a",@progbits
+.L0:
+ .long 0
+ .section .eh_frame,"a",@progbits
+ .long .L0
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+ | grep "gc-sections option ignored" > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=no
+ elif $gcc_cv_objdump -h conftest 2> /dev/null \
+ | grep gcc_except_table > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=yes
+ # If no COMDAT groups, the compiler will emit .gnu.linkonce.t. sections.
+ if test x$gcc_cv_as_comdat_group != xyes; then
+ gcc_cv_ld_eh_gc_sections=no
+ cat > conftest.s <<EOF
+ .section .text
+.globl _start
+ .type _start, @function
+_start:
+ .long foo
+ .size _start, .-_start
+ .section .gnu.linkonce.t.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .long 0
+ .size foo, .-foo
+ .section .gcc_except_table.foo,"a",@progbits
+.L0:
+ .long 0
+ .section .eh_frame,"a",@progbits
+ .long .L0
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+ | grep "gc-sections option ignored" > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=no
+ elif $gcc_cv_objdump -h conftest 2> /dev/null \
+ | grep gcc_except_table > /dev/null; then
+ gcc_cv_ld_eh_gc_sections=yes
+ fi
+ fi
+ fi
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest
+fi
+case "$target" in
+ hppa*-*-linux*)
+ # ??? This apparently exposes a binutils bug with PC-relative relocations.
+ gcc_cv_ld_eh_gc_sections=no
+ ;;
+esac
+if test x$gcc_cv_ld_eh_gc_sections = xyes; then
+ AC_DEFINE(HAVE_LD_EH_GC_SECTIONS, 1,
+ [Define if your linker supports garbage collection of
+ sections in presence of EH frames.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_eh_gc_sections)
+
+AC_MSG_CHECKING(linker EH garbage collection of sections bug)
+gcc_cv_ld_eh_gc_sections_bug=no
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -lt 19 -o "$gcc_cv_gld_major_version" -lt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_eh_gc_sections_bug=yes
+ fi
+elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_objdump != x -a x$gcc_cv_as_comdat_group = xyes; then
+ gcc_cv_ld_eh_gc_sections_bug=yes
+ cat > conftest.s <<EOF
+ .section .text
+.globl _start
+ .type _start, @function
+_start:
+ .long foo
+ .size _start, .-_start
+ .section .text.startup.foo,"ax",@progbits
+ .type foo, @function
+foo:
+ .long 0
+ .size foo, .-foo
+ .section .gcc_except_table.foo,"a",@progbits
+.L0:
+ .long 0
+ .section .eh_frame,"a",@progbits
+ .long .L0
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ if $gcc_cv_ld -o conftest conftest.o --entry=_start --gc-sections 2>&1 \
+ | grep "gc-sections option ignored" > /dev/null; then
+ :
+ elif $gcc_cv_objdump -h conftest 2> /dev/null \
+ | grep gcc_except_table > /dev/null; then
+ gcc_cv_ld_eh_gc_sections_bug=no
+ fi
+ fi
+ rm -f conftest.s conftest.o conftest
+fi
+if test x$gcc_cv_ld_eh_gc_sections_bug = xyes; then
+ AC_DEFINE(HAVE_LD_EH_GC_SECTIONS_BUG, 1,
+ [Define if your linker has buggy garbage collection of
+ sections support when .text.startup.foo like sections are used.])
+fi
+AC_MSG_RESULT($gcc_cv_ld_eh_gc_sections_bug)
+
+AC_MSG_CHECKING(linker for compressed debug sections)
+# gold/gld support compressed debug sections since binutils 2.19/2.21
+# In binutils 2.26, gld gained support for the ELF gABI format.
+if test $in_tree_ld = yes ; then
+ gcc_cv_ld_compress_debug=0
+ if test $ld_is_mold = yes; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 19 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes && test $ld_is_gold = yes; then
+ gcc_cv_ld_compress_debug=2
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 26 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes && test $ld_is_gold = no; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_compress_debug=1
+ fi
+elif echo "$ld_ver" | grep GNU > /dev/null; then
+ if test $ld_is_mold = yes; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ elif test "$ld_vers_major" -lt 2 \
+ || test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 21; then
+ gcc_cv_ld_compress_debug=0
+ elif test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -lt 26; then
+ gcc_cv_ld_compress_debug=1
+ else
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ fi
+ if test $ld_is_gold = yes; then
+ gcc_cv_ld_compress_debug=2
+ gcc_cv_ld_compress_debug_option="--compress-debug-sections"
+ fi
+else
+changequote(,)dnl
+ case "${target}" in
+ *-*-solaris2*)
+ # Introduced in Solaris 11.2.
+ if $gcc_cv_ld --help 2>&1 | grep -- '-z compress-sections' > /dev/null; then
+ gcc_cv_ld_compress_debug=3
+ gcc_cv_ld_compress_debug_option="-z compress-sections"
+ else
+ gcc_cv_ld_compress_debug=0
+ fi
+ ;;
+ *)
+ # Assume linkers other than GNU ld don't support compessed debug
+ # sections.
+ gcc_cv_ld_compress_debug=0
+ ;;
+ esac
+changequote([,])dnl
+fi
+AC_DEFINE_UNQUOTED(HAVE_LD_COMPRESS_DEBUG, $gcc_cv_ld_compress_debug,
+[Define to the level of your linker's compressed debug section support.])
+AC_DEFINE_UNQUOTED(LD_COMPRESS_DEBUG_OPTION, "$gcc_cv_ld_compress_debug_option",
+[Define to the linker option to enable compressed debug sections.])
+AC_MSG_RESULT($gcc_cv_ld_compress_debug)
+
+if test x"$ld64_flag" = x"yes"; then
+
+ # Set defaults for possibly untestable items.
+ gcc_cv_ld64_export_dynamic=0
+ gcc_cv_ld64_platform_version=0
+
+ if test "$build" = "$host"; then
+ darwin_try_test=1
+ else
+ darwin_try_test=0
+ fi
+
+ # On Darwin, because of FAT library support, it is often possible to execute
+ # exes from compatible archs even when the host differs from the build system.
+ case "$build","$host" in
+ x86_64-*-darwin*,i?86-*-darwin* | powerpc64*-*-darwin*,powerpc*-*-darwin*)
+ darwin_try_test=1;;
+ *) ;;
+ esac
+
+ # If the configurer specified a minimum ld64 version to be supported, then use
+ # that to determine feature support.
+ if test x"${gcc_cv_ld64_version}" != x; then
+ AC_MSG_CHECKING(ld64 specified version)
+ gcc_cv_ld64_major=`echo "$gcc_cv_ld64_version" | sed -e 's/\..*//'`
+ AC_MSG_RESULT($gcc_cv_ld64_major)
+ if test "$gcc_cv_ld64_major" -ge 236; then
+ gcc_cv_ld64_export_dynamic=1
+ fi
+ if test "$gcc_cv_ld64_major" -ge 512; then
+ gcc_cv_ld64_platform_version=1
+ fi
+ elif test -x "$gcc_cv_ld" -a "$darwin_try_test" -eq 1; then
+ # If the version was not specified, try to find it.
+ AC_MSG_CHECKING(linker version)
+ if test x"${gcc_cv_ld64_version}" = x; then
+ gcc_cv_ld64_version=`$gcc_cv_ld -v 2>&1 | grep ld64 | sed s/.*ld64-// | awk '{print $1}'`
+ fi
+ AC_MSG_RESULT($gcc_cv_ld64_version)
+
+ AC_MSG_CHECKING(linker for -export_dynamic support)
+ gcc_cv_ld64_export_dynamic=1
+ if $gcc_cv_ld -export_dynamic < /dev/null 2>&1 | grep 'unknown option' > /dev/null; then
+ gcc_cv_ld64_export_dynamic=0
+ fi
+ AC_MSG_RESULT($gcc_cv_ld64_export_dynamic)
+
+ AC_MSG_CHECKING(linker for -platform_version support)
+ gcc_cv_ld64_platform_version=1
+ if $gcc_cv_ld -platform_version macos 10.5 0.0 < /dev/null 2>&1 | grep 'unknown option' > /dev/null; then
+ gcc_cv_ld64_platform_version=0
+ fi
+ AC_MSG_RESULT($gcc_cv_ld64_platform_version)
+ fi
+
+ if test x"${gcc_cv_ld64_version}" != x; then
+ AC_DEFINE_UNQUOTED(LD64_VERSION, "${gcc_cv_ld64_version}",
+ [Define to ld64 version.])
+ fi
+
+ AC_DEFINE_UNQUOTED(LD64_HAS_EXPORT_DYNAMIC, $gcc_cv_ld64_export_dynamic,
+ [Define to 1 if ld64 supports '-export_dynamic'.])
+
+ AC_DEFINE_UNQUOTED(LD64_HAS_PLATFORM_VERSION, $gcc_cv_ld64_platform_version,
+ [Define to 1 if ld64 supports '-platform_version'.])
+fi
+
+if test x"$dsymutil_flag" = x"yes"; then
+
+ # If the user specified a dsymutil path, then we will already have the
+ # version string, otherwise, pick it up.
+ if test x"$gcc_cv_dsymutil" = x; then
+ AC_MSG_WARN([dsymutil is a required tool for this system, but not found])
+ dsymutil_vers="tool unspecified"
+ elif test x"$dsymutil_vers" = x; then
+ dsymutil_vers=`$gcc_cv_dsymutil -v /dev/null 2>&1`
+ fi
+
+ dsymutil_temp=`echo $dsymutil_vers | sed 1q`
+ AC_MSG_CHECKING(dsymutil version "$dsymutil_temp")
+ if echo $dsymutil_temp | grep dwarfutils- > /dev/null; then
+ dsymutil_kind=DWARFUTILS
+ dsymutil_vers=`echo $dsymutil_temp | sed 's/.*dwarfutils-\([[0-9\.]]*\).*/\1/'`
+ elif echo $dsymutil_temp | grep clang- > /dev/null; then
+ dsymutil_kind=CLANG
+ dsymutil_vers=`echo $dsymutil_temp | sed 's/.*clang-\([[0-9\.]]*\).*/\1/'`
+ elif echo $dsymutil_temp | grep 'LLVM version ' > /dev/null; then
+ dsymutil_kind=LLVM
+ dsymutil_vers=`echo $dsymutil_temp | sed 's/.*LLVM\ version\ \([[0-9\.]]*\).*/\1/'`
+ else
+ dsymutil_kind=UNKNOWN
+ dsymutil_vers="0.0"
+ fi
+ dsymutil_major=`expr "$dsymutil_vers" : '\([[0-9]]*\)'`
+ dsymutil_minor=`expr "$dsymutil_vers" : '[[0-9]]*\.\([[0-9]]*\)'`
+ dsymutil_tiny=`expr "$dsymutil_vers" : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
+ if test x"${dsymutil_minor}" = x; then
+ dsymutil_minor=0
+ fi
+ if test x"${dsymutil_tiny}" = x; then
+ dsymutil_tiny=0
+ fi
+ AC_DEFINE_UNQUOTED(DSYMUTIL_VERSION, [$dsymutil_kind,${dsymutil_major},${dsymutil_minor},${dsymutil_tiny}],
+ [Define to the dsymutil version.])
+ AC_MSG_RESULT($dsymutil_vers : $dsymutil_kind ${dsymutil_major} ${dsymutil_minor} ${dsymutil_tiny} )
+fi
+
+case $target_os in
+ win32 | pe | cygwin* | mingw32*)
+ AC_MSG_CHECKING(broken PE linker dwarf5 support)
+ gcc_cv_ld_broken_pe_dwarf5=yes
+ if test $in_tree_ld = yes ; then
+ if grep -q '\.debug_loclists.*BLOCK.*__section_alignment__.*NOLOAD.*:' \
+ $gcc_cv_ld_gld_srcdir/scripttempl/pe*.sc \
+ && grep -q '\.debug_rnglists.*BLOCK.*__section_alignment__.*NOLOAD.*:' \
+ $gcc_cv_ld_gld_srcdir/scripttempl/pe*.sc; then
+ gcc_cv_ld_broken_pe_dwarf5=no
+ fi
+ else
+ if $gcc_cv_ld --verbose 2>&1 | grep -q '\.debug_loclists.*BLOCK.*__section_alignment__.*NOLOAD.*:' \
+ && $gcc_cv_ld --verbose 2>&1 | grep -q '\.debug_rnglists.*BLOCK.*__section_alignment__.*NOLOAD.*:'; then
+ gcc_cv_ld_broken_pe_dwarf5=no
+ fi
+ fi
+ if test x$gcc_cv_ld_broken_pe_dwarf5 = xyes; then
+ AC_DEFINE(HAVE_LD_BROKEN_PE_DWARF5, 1,
+ [Define if the PE linker has broken DWARF 5 support.])
+ fi
+ AC_MSG_RESULT($gcc_cv_ld_broken_pe_dwarf5)
+
+ AC_MSG_CHECKING(PE linker --disable-dynamicbase support)
+ gcc_cv_ld_disable_dynamicbase=no
+ if test $in_tree_ld = yes; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 36 -o "$gcc_cv_gld_major_version" -gt 2; then \
+ gcc_cv_ld_disable_dynamicbase=yes
+ fi
+ else
+ if $gcc_cv_ld --help 2>&1 | grep -q 'disable\-]dynamicbase' > /dev/null; then
+ gcc_cv_ld_disable_dynamicbase=yes
+ fi
+ fi
+ if test x"$gcc_cv_ld_disable_dynamicbase" = xyes; then
+ AC_DEFINE(HAVE_LD_PE_DISABLE_DYNAMICBASE, 1,
+ [Define if the PE linker supports --disable-dynamicbase option.])
+ fi
+ AC_MSG_RESULT($gcc_cv_ld_disable_dynamicbase)
+ ;;
+esac
+
+# --------
+# UNSORTED
+# --------
+
+AC_CACHE_CHECK(linker --as-needed support,
+gcc_cv_ld_as_needed,
+[gcc_cv_ld_as_needed=no
+gcc_cv_ld_as_needed_option='--as-needed'
+gcc_cv_ld_no_as_needed_option='--no-as-needed'
+if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_as_needed=yes
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 28; then
+ gcc_cv_ld_as_needed_option='--push-state --as-needed'
+ gcc_cv_ld_no_as_needed_option='--pop-state'
+ fi
+ fi
+elif test x$gcc_cv_ld != x; then
+ # Check if linker supports --as-needed and --no-as-needed options
+ if $gcc_cv_ld --help 2>&1 | grep as-needed > /dev/null; then
+ gcc_cv_ld_as_needed=yes
+ if $gcc_cv_ld --help 2>&1 | grep push-state > /dev/null \
+ && $gcc_cv_ld --help 2>&1 | grep pop-state > /dev/null \
+ && echo "$ld_ver" | grep GNU > /dev/null \
+ && test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -ge 28; then
+ # Use these options only when both ld.bfd and ld.gold support
+ # --push-state/--pop-state, which unfortunately wasn't added
+ # at the same time.
+ gcc_cv_ld_as_needed_option='--push-state --as-needed'
+ gcc_cv_ld_no_as_needed_option='--pop-state'
+ fi
+ fi
+ case "$target:$gnu_ld" in
+ *-*-solaris2*:no)
+ # Solaris 2 ld always supports -z ignore/-z record. Prefer the native
+ # forms.
+ gcc_cv_ld_as_needed=yes
+ gcc_cv_ld_as_needed_option="-z ignore"
+ gcc_cv_ld_no_as_needed_option="-z record"
+ ;;
+ esac
+fi
+# --as-needed/-z ignore can only be used if libgcc_s.so.1 uses
+# dl_iterate_phdr, i.e. since Solaris 11.
+case "$target" in
+ *-*-solaris2.1[[1-9]]*)
+ case "$target" in
+ i?86-*-* | x86_64-*-*)
+ if echo "$ld_ver" | grep GNU > /dev/null; then
+ # Doesn't work with gld on Solaris/x86 due to PR ld/12320.
+ gcc_cv_ld_as_needed=no
+ fi
+ ;;
+ esac
+ ;;
+ *-*-solaris2*)
+ gcc_cv_ld_as_needed=no
+ ;;
+esac
+])
+if test x"$gcc_cv_ld_as_needed" = xyes; then
+ AC_DEFINE(HAVE_LD_AS_NEEDED, 1,
+[Define if your linker supports --as-needed/--no-as-needed or equivalent options.])
+ AC_DEFINE_UNQUOTED(LD_AS_NEEDED_OPTION, "$gcc_cv_ld_as_needed_option",
+[Define to the linker option to ignore unused dependencies.])
+ AC_DEFINE_UNQUOTED(LD_NO_AS_NEEDED_OPTION, "$gcc_cv_ld_no_as_needed_option",
+[Define to the linker option to keep unused dependencies.])
+fi
+
+AC_MSG_CHECKING(linker mapfile support for clearing hardware capabilities)
+saved_LDFLAGS="$LDFLAGS"
+for clearcap_map in sol2-clearcapv2.map sol2-clearcap.map; do
+ LDFLAGS="$saved_LDFLAGS -Wl,-M,${srcdir}/config/$clearcap_map"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) {return 0;}])],
+ [gcc_cv_ld_clearcap=yes; break], [gcc_cv_ld_clearcap=no])
+done
+LDFLAGS="$saved_LDFLAGS"
+if test "x$gcc_cv_ld_clearcap" = xyes; then
+ AC_DEFINE([HAVE_LD_CLEARCAP], 1,
+[Define if the linker supports clearing hardware capabilities via mapfile.])
+ AC_CONFIG_LINKS([clearcap.map:${srcdir}/config/$clearcap_map])
+fi
+AC_MSG_RESULT($gcc_cv_ld_clearcap)
+
+case "$target" in
+ powerpc*-*-*)
+ case "$target" in
+ *le-*-linux*)
+ emul_name="-melf32lppc"
+ ;;
+ *)
+ emul_name="-melf32ppc"
+ ;;
+ esac
+ AC_CACHE_CHECK(linker .gnu.attributes long double support,
+ gcc_cv_ld_ppc_attr,
+ [gcc_cv_ld_ppc_attr=no
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_ppc_attr=yes
+ elif test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 \
+ -a "$gcc_cv_gld_minor_version" -ge 28 \
+ -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_ppc_attr=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ # check that merging the long double .gnu_attribute doesn't warn
+ cat > conftest1.s <<EOF
+ .gnu_attribute 4,1
+EOF
+ cat > conftest2.s <<EOF
+ .gnu_attribute 4,9
+EOF
+ if $gcc_cv_as -a32 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -a32 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name -r -o conftest.o conftest1.o conftest2.o > /dev/null 2> conftest.err \
+ && test ! -s conftest.err; then
+ gcc_cv_ld_ppc_attr=yes
+ fi
+ rm -f conftest.err conftest.o conftest1.o conftest2.o conftest1.s conftest2.s
+ fi
+ ])
+ if test x$gcc_cv_ld_ppc_attr = xyes; then
+ AC_DEFINE(HAVE_LD_PPC_GNU_ATTR_LONG_DOUBLE, 1,
+ [Define if your PowerPC linker has .gnu.attributes long double support.])
+ fi
+ ;;
+esac
+
+case "$target:$tm_file" in
+ powerpc64*-*-freebsd* | powerpc64*-*-linux* | powerpc*-*-linux*rs6000/biarch64.h*)
+ case "$target" in
+ *le-*-linux*)
+ emul_name="-melf64lppc"
+ ;;
+ *-*-linux*)
+ emul_name="-melf64ppc"
+ ;;
+ *le-*-freebsd*)
+ emul_name="-melf64lppc_fbsd"
+ ;;
+ *-*-freebsd*)
+ emul_name="-melf64ppc_fbsd"
+ ;;
+ esac
+ AC_CACHE_CHECK(linker support for omitting dot symbols,
+ gcc_cv_ld_no_dot_syms,
+ [gcc_cv_ld_no_dot_syms=no
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_no_dot_syms=yes
+ elif test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_no_dot_syms=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ cat > conftest1.s <<EOF
+ .text
+ bl .foo
+EOF
+ cat > conftest2.s <<EOF
+ .section ".opd","aw"
+ .align 3
+ .globl foo
+ .type foo,@function
+foo:
+ .quad .LEfoo,.TOC.@tocbase,0
+ .text
+.LEfoo:
+ blr
+ .size foo,.-.LEfoo
+EOF
+ if $gcc_cv_as -a64 -o conftest1.o conftest1.s > /dev/null 2>&1 \
+ && $gcc_cv_as -a64 -o conftest2.o conftest2.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name -o conftest conftest1.o conftest2.o > /dev/null 2>&1; then
+ gcc_cv_ld_no_dot_syms=yes
+ fi
+ rm -f conftest conftest1.o conftest2.o conftest1.s conftest2.s
+ fi
+ ])
+ if test x"$gcc_cv_ld_no_dot_syms" = xyes; then
+ AC_DEFINE(HAVE_LD_NO_DOT_SYMS, 1,
+ [Define if your PowerPC64 linker only needs function descriptor syms.])
+ fi
+
+ AC_CACHE_CHECK(linker large toc support,
+ gcc_cv_ld_large_toc,
+ [gcc_cv_ld_large_toc=no
+ if test x"$ld_is_gold" = xyes; then
+ gcc_cv_ld_large_toc=yes
+ elif test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
+ gcc_cv_ld_large_toc=yes
+ fi
+ elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then
+ cat > conftest.s <<EOF
+ .section ".tbss","awT",@nobits
+ .align 3
+ie0: .space 8
+ .global _start
+ .text
+_start:
+ addis 9,13,ie0@got@tprel@ha
+ ld 9,ie0@got@tprel@l(9)
+EOF
+ if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name --no-toc-sort -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_ld_large_toc=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ fi
+ ])
+ if test x"$gcc_cv_ld_large_toc" = xyes; then
+ AC_DEFINE(HAVE_LD_LARGE_TOC, 1,
+ [Define if your PowerPC64 linker supports a large TOC.])
+ fi
+
+ AC_CACHE_CHECK(linker toc pointer alignment,
+ gcc_cv_ld_toc_align,
+ [if test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_nm != x; then
+ cat > conftest.s <<EOF
+ .global _start
+ .text
+_start:
+ addis 9,2,x@got@ha
+ .section .data.rel.ro,"aw",@progbits
+ .p2align 16
+ .space 32768
+x: .quad .TOC.
+EOF
+ if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
+ && $gcc_cv_ld $emul_name -z norelro -o conftest conftest.o > /dev/null 2>&1; then
+ gcc_cv_ld_toc_align=`$gcc_cv_nm conftest | ${AWK} '/\.TOC\./ { match ($0, "0[[[:xdigit:]]]*", a); print strtonum ("0x" substr(a[[0]], length(a[[0]])-3)) }'`
+ fi
+ rm -f conftest conftest.o conftest.s
+ fi
+ ])
+ if test -n "$gcc_cv_ld_toc_align" && test $gcc_cv_ld_toc_align -gt 8; then
+ AC_DEFINE_UNQUOTED(POWERPC64_TOC_POINTER_ALIGNMENT, $gcc_cv_ld_toc_align,
+ [Define to .TOC. alignment forced by your linker.])
+ fi
+ ;;
+esac
+
+case "$target" in
+ *-*-aix*)
+ AC_CACHE_CHECK(linker large toc support,
+ gcc_cv_ld_large_toc,
+ [gcc_cv_ld_large_toc=no
+ if test x$gcc_cv_as != x ; then
+ cat > conftest.s <<EOF
+ .toc
+LC..1:
+ .tc a[[TC]],a[[RW]]
+ .extern a[[RW]]
+ .csect .text[[PR]]
+.largetoctest:
+ addis 9,LC..1@u(2)
+ ld 3,LC..1@l(9)
+EOF
+ if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_ld_large_toc=yes
+ fi
+ rm -f conftest conftest.o conftest.s
+ fi
+ ])
+ if test x"$gcc_cv_ld_large_toc" = xyes; then
+ AC_DEFINE(HAVE_LD_LARGE_TOC, 1,
+ [Define if your PowerPC64 linker supports a large TOC.])
+ fi
+ ;;
+esac
+
+AC_CACHE_CHECK(linker --build-id support,
+ gcc_cv_ld_buildid,
+ [gcc_cv_ld_buildid=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a \
+ "$gcc_cv_gld_minor_version" -ge 18 -o \
+ "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_buildid=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --help 2>&1 | grep build-id > /dev/null; then
+ gcc_cv_ld_buildid=yes
+ fi
+ fi])
+if test x"$gcc_cv_ld_buildid" = xyes; then
+ AC_DEFINE(HAVE_LD_BUILDID, 1,
+ [Define if your linker supports --build-id.])
+fi
+
+AC_ARG_ENABLE(linker-build-id,
+[AS_HELP_STRING([--enable-linker-build-id],
+ [compiler will always pass --build-id to linker])],
+[],
+enable_linker_build_id=no)
+
+if test x"$enable_linker_build_id" = xyes; then
+ if test x"$gcc_cv_ld_buildid" = xyes; then
+ AC_DEFINE(ENABLE_LD_BUILDID, 1,
+ [Define if gcc should always pass --build-id to linker.])
+ else
+ AC_MSG_WARN(--build-id is not supported by your linker; --enable-linker-build-id ignored)
+ fi
+fi
+
+# In binutils 2.21, GNU ld gained support for new emulations fully
+# supporting the Solaris 2 ABI. Detect their presence in the linker used.
+AC_CACHE_CHECK(linker *_sol2 emulation support,
+ gcc_cv_ld_sol2_emulation,
+ [gcc_cv_ld_sol2_emulation=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a \
+ "$gcc_cv_gld_minor_version" -ge 21 -o \
+ "$gcc_cv_gld_major_version" -gt 2 \
+ && test $in_tree_ld_is_elf = yes; then
+ gcc_cv_ld_sol2_emulation=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld -V 2>/dev/null | sed -e '1,/Supported emulations/d;q' | \
+ grep _sol2 > /dev/null; then
+ gcc_cv_ld_sol2_emulation=yes
+ fi
+ fi])
+if test x"$gcc_cv_ld_sol2_emulation" = xyes; then
+ AC_DEFINE(HAVE_LD_SOL2_EMULATION, 1,
+ [Define if your linker supports the *_sol2 emulations.])
+fi
+
+AC_CACHE_CHECK(linker --sysroot support,
+ gcc_cv_ld_sysroot,
+ [gcc_cv_ld_sysroot=no
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 ; then
+ gcc_cv_ld_sysroot=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ if $gcc_cv_ld --help 2>&1 | grep sysroot > /dev/null; then
+ gcc_cv_ld_sysroot=yes
+ fi
+ fi])
+if test x"$gcc_cv_ld_sysroot" = xyes; then
+ AC_DEFINE(HAVE_LD_SYSROOT, 1,
+ [Define if your linker supports --sysroot.])
+fi
+
+case $target in
+*-*-solaris2*)
+ # Check for system-provided CRTs on Solaris 11.x and Solaris 12.
+ AC_CACHE_CHECK([system-provided CRTs on Solaris],
+ gcc_cv_solaris_crts,
+ [gcc_cv_solaris_crts=no
+ if test x$host != x$target; then
+ if test "x$with_sysroot" = xyes; then
+ target_sysroot="${test_exec_prefix}/${target_noncanonical}/sys-root"
+ else
+ target_sysroot="${with_sysroot}"
+ fi
+ fi
+ target_libdir="$target_sysroot/usr/lib"
+ # At the time they were added, gcrt1.o became a symlink for backwards
+ # compatibility on x86, while crt1.o was added on sparc, so check for that.
+ case $target in
+ i?86-*-solaris2* | x86_64-*-solaris2*)
+ if test -h "$target_libdir/gcrt1.o"; then gcc_cv_solaris_crts=yes; fi
+ ;;
+ sparc*-*-solaris2*)
+ if test -f "$target_libdir/crt1.o"; then gcc_cv_solaris_crts=yes; fi
+ ;;
+ esac])
+ ;;
+esac
+if test x$gcc_cv_solaris_crts = xyes; then
+ AC_DEFINE(HAVE_SOLARIS_CRTS, 1,
+ [Define if the system-provided CRTs are present on Solaris.])
+fi
+
+AC_ARG_ENABLE(libssp,
+[AS_HELP_STRING([--enable-libssp], [enable linking against libssp])],
+[case "${enableval}" in
+ yes|no)
+ ;;
+ *)
+ AC_MSG_ERROR([unknown libssp setting $enableval])
+ ;;
+esac], [])
+
+# Test for stack protector support in target C library.
+AC_CACHE_CHECK(__stack_chk_fail in target C library,
+ gcc_cv_libc_provides_ssp,
+ [gcc_cv_libc_provides_ssp=no
+ if test "x$enable_libssp" = "xno"; then
+ gcc_cv_libc_provides_ssp=yes
+ elif test "x$enable_libssp" = "xyes"; then
+ gcc_cv_libc_provides_ssp=no
+ else
+ case "$target" in
+ *-*-musl*)
+ # All versions of musl provide stack protector
+ gcc_cv_libc_provides_ssp=yes;;
+ *-*-linux* | *-*-kfreebsd*-gnu)
+ # glibc 2.4 and later provides __stack_chk_fail and
+ # either __stack_chk_guard, or TLS access to stack guard canary.
+ GCC_GLIBC_VERSION_GTE_IFELSE([2], [4], [gcc_cv_libc_provides_ssp=yes], [
+ [if test -f $target_header_dir/features.h \
+ && $EGREP '^[ ]*#[ ]*define[ ]+__GNU_LIBRARY__[ ]+([1-9][0-9]|[6-9])' \
+ $target_header_dir/features.h > /dev/null; then
+ if $EGREP '^[ ]*#[ ]*define[ ]+__UCLIBC__[ ]+1' \
+ $target_header_dir/features.h > /dev/null && \
+ test -f $target_header_dir/bits/uClibc_config.h && \
+ $EGREP '^[ ]*#[ ]*define[ ]+__UCLIBC_HAS_SSP__[ ]+1' \
+ $target_header_dir/bits/uClibc_config.h > /dev/null; then
+ gcc_cv_libc_provides_ssp=yes
+ fi
+ # all versions of Bionic support stack protector
+ elif test -f $target_header_dir/sys/cdefs.h \
+ && $EGREP '^[ ]*#[ ]*define[ ]+__BIONIC__[ ]+1' \
+ $target_header_dir/sys/cdefs.h > /dev/null; then
+ gcc_cv_libc_provides_ssp=yes
+ fi]])
+ ;;
+ *-*-gnu*)
+ # Avoid complicated tests (see
+ # <http://gcc.gnu.org/ml/gcc/2008-10/msg00130.html>) and for now
+ # simply assert that glibc does provide this, which is true for all
+ # realistically usable GNU/Hurd configurations.
+ # All supported versions of musl provide it as well
+ gcc_cv_libc_provides_ssp=yes;;
+ *-*-darwin* | *-*-freebsd* | *-*-netbsd*)
+ AC_CHECK_FUNC(__stack_chk_fail,[gcc_cv_libc_provides_ssp=yes],
+ [echo "no __stack_chk_fail on this target"])
+ ;;
+ *) gcc_cv_libc_provides_ssp=no ;;
+ esac
+ fi])
+
+if test x$gcc_cv_libc_provides_ssp = xyes; then
+ AC_DEFINE(TARGET_LIBC_PROVIDES_SSP, 1,
+ [Define if your target C library provides stack protector support])
+fi
+
+# Check whether --enable-default-ssp was given.
+AC_ARG_ENABLE(default-ssp,
+[AS_HELP_STRING([--enable-default-ssp],
+ [enable Stack Smashing Protection as default])],[
+if test x$gcc_cv_libc_provides_ssp = xyes; then
+ case "$target" in
+ ia64*-*-*) enable_default_ssp=no ;;
+ *) enable_default_ssp=$enableval ;;
+ esac
+else
+ enable_default_ssp=no
+fi],
+enable_default_ssp=no)
+if test x$enable_default_ssp = xyes ; then
+ AC_DEFINE(ENABLE_DEFAULT_SSP, 1,
+ [Define if your target supports default stack protector and it is enabled.])
+fi
+AC_SUBST([enable_default_ssp])
+
+# Test for <sys/sdt.h> on the target.
+GCC_TARGET_TEMPLATE([HAVE_SYS_SDT_H])
+AC_MSG_CHECKING(sys/sdt.h in the target C library)
+have_sys_sdt_h=no
+if test -f $target_header_dir/sys/sdt.h; then
+ have_sys_sdt_h=yes
+ AC_DEFINE(HAVE_SYS_SDT_H, 1,
+ [Define if your target C library provides sys/sdt.h])
+fi
+AC_MSG_RESULT($have_sys_sdt_h)
+
+# Check if TFmode long double should be used by default or not.
+# Some glibc targets used DFmode long double, but with glibc 2.4
+# and later they can use TFmode.
+case "$target" in
+ powerpc*-*-linux* | \
+ sparc*-*-linux* | \
+ s390*-*-linux* | \
+ alpha*-*-linux*)
+ AC_ARG_WITH(long-double-128,
+ [AS_HELP_STRING([--with-long-double-128],
+ [use 128-bit long double by default])],
+ gcc_cv_target_ldbl128="$with_long_double_128", [
+ case "$target" in
+ s390*-*-linux-musl*)
+ gcc_cv_target_ldbl128=yes
+ ;;
+ powerpc*-*-linux-musl*)
+ gcc_cv_target_ldbl128=no
+ ;;
+ *)]
+ [GCC_GLIBC_VERSION_GTE_IFELSE([2], [4], [gcc_cv_target_ldbl128=yes], [
+ [gcc_cv_target_ldbl128=no
+ grep '^[ ]*#[ ]*define[ ][ ]*__LONG_DOUBLE_MATH_OPTIONAL' \
+ $target_header_dir/bits/wordsize.h > /dev/null 2>&1 \
+ && gcc_cv_target_ldbl128=yes
+ ]])]
+ [
+ ;;
+ esac
+ ])
+ ;;
+esac
+if test x$gcc_cv_target_ldbl128 = xyes; then
+ AC_DEFINE(TARGET_DEFAULT_LONG_DOUBLE_128, 1,
+ [Define if TFmode long double should be the default])
+fi
+
+# Check if TFmode long double target should use the IBM extended double or IEEE
+# 128-bit floating point formats if long doubles are 128-bits long. The long
+# double type can only be switched on powerpc64 bit Linux systems where VSX is
+# supported. Other PowerPC systems do not build the IEEE 128-bit emulator in
+# libgcc.
+AC_ARG_WITH([long-double-format],
+ [AS_HELP_STRING([--with-long-double-format={ieee,ibm}]
+ [Specify whether PowerPC long double uses IEEE or IBM format])],[
+case "$target:$with_long_double_format" in
+ powerpc64le-*-linux*:ieee | powerpc64le-*-linux*:ibm)
+ :
+ ;;
+ powerpc64-*-linux*:ieee | powerpc64-*-linux*:ibm)
+ # IEEE 128-bit emulation is only built on 64-bit VSX Linux systems
+ case "$with_cpu" in
+ power7 | power8 | power9 | power1*)
+ :
+ ;;
+ *)
+ AC_MSG_ERROR([Configuration option --with-long-double-format is only \
+supported if the default cpu is power7 or newer])
+ with_long_double_format=""
+ ;;
+ esac
+ ;;
+ powerpc64*-*-linux*:*)
+ AC_MSG_ERROR([--with-long-double-format argument should be ibm or ieee])
+ with_long_double_format=""
+ ;;
+ *)
+ AC_MSG_ERROR([Configure option --with-long-double-format is only supported \
+on 64-bit PowerPC VSX Linux systems])
+ with_long_double_format=""
+ ;;
+esac],
+ [])
+
+# Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP
+# values in the TCB. Currently, only GLIBC 2.23 and later support this.
+gcc_cv_libc_provides_hwcap_in_tcb=no
+case "$target" in
+ powerpc*-*-linux*)
+ GCC_GLIBC_VERSION_GTE_IFELSE([2], [23], [gcc_cv_libc_provides_hwcap_in_tcb=yes], )
+ ;;
+esac
+if test x$gcc_cv_libc_provides_hwcap_in_tcb = xyes; then
+ AC_DEFINE(TARGET_LIBC_PROVIDES_HWCAP_IN_TCB, 1,
+ [Define if your target C Library provides the AT_HWCAP value in the TCB])
+fi
+
+# Check if the target LIBC handles PT_GNU_STACK.
+gcc_cv_libc_gnustack=unknown
+case "$target" in
+ mips*-*-linux-musl*)
+ gcc_cv_libc_gnustack=yes
+ ;;
+ mips*-*-linux*)
+ GCC_GLIBC_VERSION_GTE_IFELSE([2], [31], [gcc_cv_libc_gnustack=yes], )
+ ;;
+esac
+if test x$gcc_cv_libc_gnustack = xyes; then
+ AC_DEFINE(TARGET_LIBC_GNUSTACK, 1,
+ [Define if your target C Library properly handles PT_GNU_STACK])
+fi
+
+AC_MSG_CHECKING(dl_iterate_phdr in target C library)
+gcc_cv_target_dl_iterate_phdr=unknown
+case "$target" in
+ *-*-solaris2*)
+ # <link.h> needs both a dl_iterate_phdr declaration and support for
+ # compilation with largefile support.
+ if grep dl_iterate_phdr $target_header_dir/link.h > /dev/null 2>&1 \
+ && grep 'large file capable' $target_header_dir/link.h > /dev/null 2>&1; then
+ gcc_cv_target_dl_iterate_phdr=yes
+ else
+ gcc_cv_target_dl_iterate_phdr=no
+ fi
+ ;;
+ *-*-dragonfly* | *-*-freebsd*)
+ if grep dl_iterate_phdr $target_header_dir/sys/link_elf.h > /dev/null 2>&1; then
+ gcc_cv_target_dl_iterate_phdr=yes
+ else
+ gcc_cv_target_dl_iterate_phdr=no
+ fi
+ ;;
+ *-linux-musl*)
+ gcc_cv_target_dl_iterate_phdr=yes
+ ;;
+esac
+GCC_TARGET_TEMPLATE([TARGET_DL_ITERATE_PHDR])
+if test x$gcc_cv_target_dl_iterate_phdr = xyes; then
+ AC_DEFINE(TARGET_DL_ITERATE_PHDR, 1,
+[Define if your target C library provides the `dl_iterate_phdr' function.])
+fi
+AC_MSG_RESULT($gcc_cv_target_dl_iterate_phdr)
+
+# We no longer support different GC mechanisms. Emit an error if
+# the user configures with --with-gc.
+AC_ARG_WITH(gc,
+[AS_HELP_STRING([--with-gc={page,zone}],
+ [this option is not supported anymore. It used to choose
+ the garbage collection mechanism to use with the compiler])],
+[AC_MSG_ERROR([Configure option --with-gc is only supported up to GCC 4.7.x])],
+[])
+
+# Libraries to use on the host. This will normally be set by the top
+# level Makefile. Here we simply capture the value for our Makefile.
+if test -z "${HOST_LIBS+set}"; then
+ HOST_LIBS=
+fi
+AC_SUBST(HOST_LIBS)
+
+# Use the system's zlib library.
+AM_ZLIB
+
+dnl Very limited version of automake's enable-maintainer-mode
+
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode is disabled by default
+ AC_ARG_ENABLE(maintainer-mode,
+[AS_HELP_STRING([--enable-maintainer-mode],
+ [enable make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer])],
+ maintainer_mode=$enableval,
+ maintainer_mode=no)
+
+AC_MSG_RESULT($maintainer_mode)
+
+if test "$maintainer_mode" = "yes"; then
+ MAINT=''
+else
+ MAINT='#'
+fi
+AC_SUBST(MAINT)dnl
+
+dnl Variables for tags utilities; copied from automake 1.16.4+'s init.m4
+if test -z "$CTAGS"; then
+ CTAGS=ctags
+fi
+AC_SUBST([CTAGS])
+if test -z "$ETAGS"; then
+ ETAGS=etags
+fi
+AC_SUBST([ETAGS])
+if test -z "$CSCOPE"; then
+ CSCOPE=cscope
+fi
+AC_SUBST([CSCOPE])
+
+dnl Whether to prevent multiple front-ends from linking at the same time
+
+AC_MSG_CHECKING([whether to avoid linking multiple front-ends at once])
+ AC_ARG_ENABLE(link-mutex,
+[AS_HELP_STRING([--enable-link-mutex],
+ [avoid linking multiple front-ends at once to avoid thrashing
+ on the build machine])],
+ do_link_mutex=$enableval,
+ do_link_mutex=no)
+AC_MSG_RESULT($do_link_mutex)
+
+if test "$do_link_mutex" = "yes"; then
+ DO_LINK_MUTEX=true
+else
+ DO_LINK_MUTEX=false
+fi
+AC_SUBST(DO_LINK_MUTEX)
+
+dnl Whether to prevent multiple GCC front-ends from linking at the same time
+
+AC_MSG_CHECKING([whether to serialize linking of multiple front-ends])
+ AC_ARG_ENABLE(link-serialization,
+[AS_HELP_STRING([--enable-link-serialization],
+ [avoid linking multiple GCC front-ends at once using make
+ dependencies to avoid thrashing on the build machine])],
+ do_link_serialization=$enableval,
+ do_link_serialization=no)
+AC_MSG_RESULT($do_link_serialization)
+
+case "$do_link_serialization" in
+ yes)
+ DO_LINK_SERIALIZATION=1;;
+ [[1-9]] | [[1-9]][[0-9]] | [[1-9]][[0-9]][[0-9]])
+ DO_LINK_SERIALIZATION=$do_link_serialization;;
+ no)
+ DO_LINK_SERIALIZATION=;;
+ *)
+ AC_MSG_ERROR(bad value ${do_link_serialization} given for --enable-link-serialization) ;;
+esac
+AC_SUBST(DO_LINK_SERIALIZATION)
+
+# --------------
+# Language hooks
+# --------------
+
+# Make empty files to contain the specs and options for each language.
+# Then add #include lines to for a compiler that has specs and/or options.
+
+subdirs=
+lang_opt_files=
+lang_specs_files=
+lang_tree_files=
+# These (without "all_") are set in each config-lang.in.
+# `language' must be a single word so is spelled singularly.
+all_languages=
+all_compilers=
+all_outputs='Makefile'
+# List of language configure and makefile fragments.
+all_lang_configurefrags=
+all_lang_makefrags=
+# Additional files for gengtype
+all_gtfiles="$target_gtfiles"
+
+# These are the languages that are set in --enable-languages,
+# and are available in the GCC tree.
+all_selected_languages=
+
+# Add the language fragments.
+# Languages are added via two mechanisms. Some information must be
+# recorded in makefile variables, these are defined in config-lang.in.
+# We accumulate them and plug them into the main Makefile.
+# The other mechanism is a set of hooks for each of the main targets
+# like `clean', `install', etc.
+
+language_hooks="Make-hooks"
+
+for lang in ${srcdir}/*/config-lang.in
+do
+changequote(,)dnl
+ test "$lang" = "${srcdir}/*/config-lang.in" && continue
+
+ lang_alias=`sed -n -e 's,^language=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^language=\([^ ]*\).*$,\1,p' $lang`
+ if test "x$lang_alias" = x
+ then
+ echo "$lang doesn't set \$language." 1>&2
+ exit 1
+ fi
+ subdir="`echo $lang | sed -e 's,^.*/\([^/]*\)/config-lang.in$,\1,'`"
+ subdirs="$subdirs $subdir"
+
+ # $gcc_subdir is where the gcc integration files are to be found
+ # for a language, both for internal compiler purposes (compiler
+ # sources implementing front-end to GCC tree converters), and for
+ # build infrastructure purposes (Make-lang.in, etc.)
+ #
+ # This will be <subdir> (relative to $srcdir) if a line like
+ # gcc_subdir="<subdir>" or gcc_subdir=<subdir>
+ # is found in <langdir>/config-lang.in, and will remain <langdir>
+ # otherwise.
+ #
+ # Except for the language alias (fetched above), the regular
+ # "config-lang.in" contents are always retrieved from $gcc_subdir,
+ # so a <langdir>/config-lang.in setting gcc_subdir typically sets
+ # only this and the language alias.
+
+ gcc_subdir=`sed -n -e 's,^gcc_subdir=['"'"'"'"]\(.*\)["'"'"'"'].*$,\1,p' -e 's,^gcc_subdir=\([^ ]*\).*$,\1,p' $lang`
+ if [ "$gcc_subdir" = "" ]; then
+ gcc_subdir="$subdir"
+ fi
+
+ case ",$enable_languages," in
+ *,$lang_alias,*)
+ all_selected_languages="$all_selected_languages $lang_alias"
+ if test -f $srcdir/$gcc_subdir/lang-specs.h; then
+ lang_specs_files="$lang_specs_files $srcdir/$gcc_subdir/lang-specs.h"
+ fi
+ ;;
+ esac
+changequote([,])dnl
+
+ language=
+ boot_language=
+ compilers=
+ outputs=
+ gtfiles=
+ subdir_requires=
+ . ${srcdir}/$gcc_subdir/config-lang.in
+ if test "x$language" = x
+ then
+ echo "${srcdir}/$gcc_subdir/config-lang.in doesn't set \$language." 1>&2
+ exit 1
+ fi
+
+ ok=:
+ case ",$enable_languages," in
+ *,$lang_alias,*) ;;
+ *)
+ for i in $subdir_requires; do
+ test -f "${srcdir}/$i/config-lang.in" && continue
+ ok=false
+ break
+ done
+ ;;
+ esac
+ $ok || continue
+
+ all_lang_configurefrags="$all_lang_configurefrags \$(srcdir)/$gcc_subdir/config-lang.in"
+ if test "x$language" = xc && test -n "$all_lang_makefrags"; then
+ # Put c/Make-lang.in fragment first to match serialization languages order.
+ all_lang_makefrags="\$(srcdir)/$gcc_subdir/Make-lang.in $all_lang_makefrags"
+ else
+ all_lang_makefrags="$all_lang_makefrags \$(srcdir)/$gcc_subdir/Make-lang.in"
+ fi
+ if test -f $srcdir/$gcc_subdir/lang.opt; then
+ lang_opt_files="$lang_opt_files $srcdir/$gcc_subdir/lang.opt"
+ all_opt_files="$all_opt_files $srcdir/$gcc_subdir/lang.opt"
+ fi
+ if test -f $srcdir/$gcc_subdir/$subdir-tree.def; then
+ lang_tree_files="$lang_tree_files $srcdir/$gcc_subdir/$subdir-tree.def"
+ fi
+ all_languages="$all_languages $language"
+ all_compilers="$all_compilers $compilers"
+ all_outputs="$all_outputs $outputs"
+ all_gtfiles="$all_gtfiles [[$subdir]] $gtfiles"
+ case ",$enable_languages," in
+ *,lto,*)
+ AC_DEFINE(ENABLE_LTO, 1, [Define to enable LTO support.])
+ enable_lto=yes
+ AC_SUBST(enable_lto)
+ ;;
+ *) ;;
+ esac
+done
+
+check_languages=
+for language in $all_selected_languages
+do
+ check_languages="$check_languages check-$language"
+done
+
+selftest_languages=
+for language in $all_selected_languages
+do
+ selftest_languages="$selftest_languages selftest-$language"
+done
+
+# We link each language in with a set of hooks, reached indirectly via
+# lang.${target}. Only do so for selected languages.
+
+rm -f Make-hooks
+touch Make-hooks
+target_list="all.cross start.encap rest.encap tags \
+ install-common install-man install-info install-dvi install-pdf \
+ install-html dvi pdf html uninstall info man srcextra srcman srcinfo \
+ mostlyclean clean distclean maintainer-clean install-plugin"
+
+for t in $target_list
+do
+ x=
+ for lang in $all_selected_languages
+ do
+ x="$x $lang.$t"
+ done
+ echo "lang.$t: $x" >> Make-hooks
+done
+
+echo "ifeq (\$(DO_LINK_SERIALIZATION),)" >> Make-hooks
+echo "SERIAL_LIST =" >> Make-hooks
+echo else >> Make-hooks
+lang_cnt=0
+lang_list=
+prev=c
+serialization_languages=c
+for lang in $all_selected_languages
+do
+ test $lang = c && continue
+ if test $lang = lto; then
+ serialization_languages="$serialization_languages lto1 lto2"
+ else
+ serialization_languages="$serialization_languages $lang"
+ fi
+done
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ lang_cnt=`expr $lang_cnt + 1`
+ lang_list=" $prev$lang_list"
+ prev=${lang}
+done
+echo "SERIAL_LIST = \$(wordlist \$(DO_LINK_SERIALIZATION),$lang_cnt,$lang_list)" >> Make-hooks
+echo endif >> Make-hooks
+echo "SERIAL_COUNT = `expr $lang_cnt + 1`" >> Make-hooks
+echo "INDEX.c = 0" >> Make-hooks
+lang_idx=1
+for lang in $serialization_languages
+do
+ test $lang = c && continue
+ echo "$lang.prev = \$(if \$(word $lang_cnt,\$(SERIAL_LIST)),\$(\$(word $lang_cnt,\$(SERIAL_LIST)).serial))" >> Make-hooks
+ echo "INDEX.$lang = $lang_idx" >> Make-hooks
+ lang_cnt=`expr $lang_cnt - 1`
+ lang_idx=`expr $lang_idx + 1`
+done
+
+# --------
+# Option include files
+# --------
+
+${AWK} -f $srcdir/opt-include.awk $all_opt_files > option-includes.mk
+option_includes="option-includes.mk"
+AC_SUBST_FILE(option_includes)
+
+# --------
+# UNSORTED
+# --------
+
+# Create .gdbinit.
+
+echo "dir ." > .gdbinit
+echo "dir ${srcdir}" >> .gdbinit
+if test x$gdb_needs_out_file_path = xyes
+then
+ echo "dir ${srcdir}/config/"`dirname ${out_file}` >> .gdbinit
+fi
+if test "x$subdirs" != x; then
+ for s in $subdirs
+ do
+ echo "dir ${srcdir}/$s" >> .gdbinit
+ done
+fi
+echo "source ${srcdir}/gdbinit.in" >> .gdbinit
+echo "python import sys; sys.path.append('${srcdir}'); import gdbhooks" >> .gdbinit
+
+# Put a breakpoint on __asan_report_error to help with debugging buffer
+# overflow.
+case "$CFLAGS" in
+*-fsanitize=address*)
+ echo "source ${srcdir}/gdbasan.in" >> .gdbinit
+ ;;
+esac
+
+gcc_tooldir='$(libsubdir)/$(libsubdir_to_prefix)$(target_noncanonical)'
+AC_SUBST(gcc_tooldir)
+AC_SUBST(dollar)
+
+# Find a directory in which to install a shared libgcc.
+
+AC_ARG_ENABLE(version-specific-runtime-libs,
+[AS_HELP_STRING([--enable-version-specific-runtime-libs],
+ [specify that runtime libraries should be
+ installed in a compiler-specific directory])])
+
+# Substitute configuration variables
+AC_SUBST(subdirs)
+AC_SUBST(srcdir)
+AC_SUBST(all_compilers)
+AC_SUBST(all_gtfiles)
+AC_SUBST(all_lang_configurefrags)
+AC_SUBST(all_lang_makefrags)
+AC_SUBST(all_languages)
+AC_SUBST(all_selected_languages)
+AC_SUBST(build_exeext)
+AC_SUBST(build_install_headers_dir)
+AC_SUBST(build_xm_file_list)
+AC_SUBST(build_xm_include_list)
+AC_SUBST(build_xm_defines)
+AC_SUBST(build_file_translate)
+AC_SUBST(check_languages)
+AC_SUBST(selftest_languages)
+AC_SUBST(cpp_install_dir)
+AC_SUBST(xmake_file)
+AC_SUBST(tmake_file)
+AC_SUBST(TM_ENDIAN_CONFIG)
+AC_SUBST(TM_MULTILIB_CONFIG)
+AC_SUBST(TM_MULTILIB_EXCEPTIONS_CONFIG)
+AC_SUBST(extra_gcc_objs)
+AC_SUBST(user_headers_inc_next_pre)
+AC_SUBST(user_headers_inc_next_post)
+AC_SUBST(extra_headers_list)
+AC_SUBST(extra_objs)
+AC_SUBST(extra_programs)
+AC_SUBST(float_h_file)
+AC_SUBST(gcc_config_arguments)
+AC_SUBST(gcc_gxx_include_dir)
+AC_SUBST(gcc_gxx_include_dir_add_sysroot)
+AC_SUBST(gcc_gxx_libcxx_include_dir)
+AC_SUBST(gcc_gxx_libcxx_include_dir_add_sysroot)
+AC_SUBST(host_exeext)
+AC_SUBST(host_xm_file_list)
+AC_SUBST(host_xm_include_list)
+AC_SUBST(host_xm_defines)
+AC_SUBST(out_host_hook_obj)
+AC_SUBST(install)
+AC_SUBST(lang_opt_files)
+AC_SUBST(lang_specs_files)
+AC_SUBST(lang_tree_files)
+AC_SUBST(local_prefix)
+AC_SUBST(md_file)
+AC_SUBST(objc_boehm_gc)
+AC_SUBST(out_file)
+AC_SUBST(out_object_file)
+AC_SUBST(common_out_file)
+AC_SUBST(common_out_object_file)
+AC_SUBST(tm_file_list)
+AC_SUBST(tm_include_list)
+AC_SUBST(tm_defines)
+AC_SUBST(tm_p_file_list)
+AC_SUBST(tm_p_include_list)
+AC_SUBST(tm_d_file_list)
+AC_SUBST(tm_d_include_list)
+AC_SUBST(xm_file_list)
+AC_SUBST(xm_include_list)
+AC_SUBST(xm_defines)
+AC_SUBST(use_gcc_stdint)
+AC_SUBST(c_target_objs)
+AC_SUBST(cxx_target_objs)
+AC_SUBST(fortran_target_objs)
+AC_SUBST(d_target_objs)
+AC_SUBST(target_cpu_default)
+
+AC_SUBST_FILE(language_hooks)
+
+# Echo link setup.
+if test x${build} = x${host} ; then
+ if test x${host} = x${target} ; then
+ echo "Links are now set up to build a native compiler for ${target}." 1>&2
+ else
+ echo "Links are now set up to build a cross-compiler" 1>&2
+ echo " from ${host} to ${target}." 1>&2
+ fi
+else
+ if test x${host} = x${target} ; then
+ echo "Links are now set up to build (on ${build}) a native compiler" 1>&2
+ echo " for ${target}." 1>&2
+ else
+ echo "Links are now set up to build (on ${build}) a cross-compiler" 1>&2
+ echo " from ${host} to ${target}." 1>&2
+ fi
+fi
+
+AC_ARG_VAR(GMPLIBS,[How to link GMP])
+AC_ARG_VAR(GMPINC,[How to find GMP include files])
+
+AC_ARG_VAR(ISLLIBS,[How to link isl])
+AC_ARG_VAR(ISLINC,[How to find isl include files])
+if test "x${ISLLIBS}" != "x" ; then
+ AC_DEFINE(HAVE_isl, 1, [Define if isl is in use.])
+fi
+
+# SDCC GCC_ENABLE_PLUGINS
+AC_SUBST(pluginlibs)
+AC_SUBST(enable_plugin)
+if test x"$enable_plugin" = x"yes"; then
+ AC_DEFINE(ENABLE_PLUGIN, 1, [Define to enable plugin support.])
+fi
+
+
+# Enable --enable-host-shared
+AC_ARG_ENABLE(host-shared,
+[AS_HELP_STRING([--enable-host-shared],
+ [build host code as shared libraries])],
+[PICFLAG=-fPIC], [PICFLAG=])
+AC_SUBST(enable_host_shared)
+AC_SUBST(PICFLAG)
+
+
+AC_ARG_ENABLE(libquadmath-support,
+[AS_HELP_STRING([--disable-libquadmath-support],
+ [disable libquadmath support for Fortran])],
+ENABLE_LIBQUADMATH_SUPPORT=$enableval,
+ENABLE_LIBQUADMATH_SUPPORT=yes)
+if test "${ENABLE_LIBQUADMATH_SUPPORT}" != "no" ; then
+ AC_DEFINE(ENABLE_LIBQUADMATH_SUPPORT, 1,
+ [Define to 1 to enable libquadmath support])
+fi
+
+
+# Specify what hash style to use by default.
+AC_ARG_WITH([linker-hash-style],
+[AC_HELP_STRING([--with-linker-hash-style={sysv,gnu,both}],
+ [specify the linker hash style])],
+[case x"$withval" in
+ xsysv)
+ LINKER_HASH_STYLE=sysv
+ ;;
+ xgnu)
+ LINKER_HASH_STYLE=gnu
+ ;;
+ xboth)
+ LINKER_HASH_STYLE=both
+ ;;
+ *)
+ AC_MSG_ERROR([$withval is an invalid option to --with-linker-hash-style])
+ ;;
+ esac],
+[LINKER_HASH_STYLE=''])
+if test x"${LINKER_HASH_STYLE}" != x; then
+ AC_DEFINE_UNQUOTED(LINKER_HASH_STYLE, "$LINKER_HASH_STYLE",
+ [The linker hash style])
+fi
+
+# Specify what should be the default of -fdiagnostics-color option.
+AC_ARG_WITH([diagnostics-color],
+[AC_HELP_STRING([--with-diagnostics-color={never,auto,auto-if-env,always}],
+ [specify the default of -fdiagnostics-color option
+ auto-if-env stands for -fdiagnostics-color=auto if
+ GCC_COLOR environment variable is present and
+ -fdiagnostics-color=never otherwise])],
+[case x"$withval" in
+ xnever)
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_NO
+ ;;
+ xauto)
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_AUTO
+ ;;
+ xauto-if-env)
+ DIAGNOSTICS_COLOR_DEFAULT=-1
+ ;;
+ xalways)
+ DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_YES
+ ;;
+ *)
+ AC_MSG_ERROR([$withval is an invalid option to --with-diagnostics-color])
+ ;;
+ esac],
+[DIAGNOSTICS_COLOR_DEFAULT=DIAGNOSTICS_COLOR_AUTO])
+AC_DEFINE_UNQUOTED(DIAGNOSTICS_COLOR_DEFAULT, $DIAGNOSTICS_COLOR_DEFAULT,
+ [The default for -fdiagnostics-color option])
+
+# Specify what should be the default of -fdiagnostics-urls option.
+AC_ARG_WITH([diagnostics-urls],
+[AC_HELP_STRING([--with-diagnostics-urls={never,auto,auto-if-env,always}],
+ [specify the default of -fdiagnostics-urls option
+ auto-if-env stands for -fdiagnostics-urls=auto if
+ GCC_URLS or TERM_URLS environment variable is present and
+ -fdiagnostics-urls=never otherwise])],
+[case x"$withval" in
+ xnever)
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_NO
+ ;;
+ xauto)
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_AUTO
+ ;;
+ xauto-if-env)
+ DIAGNOSTICS_URLS_DEFAULT=-1
+ ;;
+ xalways)
+ DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_YES
+ ;;
+ *)
+ AC_MSG_ERROR([$withval is an invalid option to --with-diagnostics-urls])
+ ;;
+ esac],
+[DIAGNOSTICS_URLS_DEFAULT=DIAGNOSTICS_URL_AUTO])
+AC_DEFINE_UNQUOTED(DIAGNOSTICS_URLS_DEFAULT, $DIAGNOSTICS_URLS_DEFAULT,
+ [The default for -fdiagnostics-urls option])
+
+# Generate gcc-driver-name.h containing GCC_DRIVER_NAME for the benefit
+# of jit/jit-playback.cc.
+gcc_driver_version=`eval "${get_gcc_base_ver} $srcdir/BASE-VER"`
+echo "gcc_driver_version: ${gcc_driver_version}"
+cat > gcc-driver-name.h <<EOF
+#define GCC_DRIVER_NAME "${target_noncanonical}-gcc-${gcc_driver_version}${exeext}"
+EOF
+
+# Check whether --enable-default-pie was given.
+AC_ARG_ENABLE(default-pie,
+[AS_HELP_STRING([--enable-default-pie],
+ [enable Position Independent Executable as default])],
+enable_default_pie=$enableval,
+enable_default_pie=no)
+if test x$enable_default_pie = xyes ; then
+ AC_DEFINE(ENABLE_DEFAULT_PIE, 1,
+ [Define if your target supports default PIE and it is enabled.])
+fi
+AC_SUBST([enable_default_pie])
+
+# Check if -fno-PIE works.
+AC_CACHE_CHECK([for -fno-PIE option],
+ [gcc_cv_c_no_fpie],
+ [saved_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS -fno-PIE"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int main(void) {return 0;}])],
+ [gcc_cv_c_no_fpie=yes],
+ [gcc_cv_c_no_fpie=no])
+ CXXFLAGS="$saved_CXXFLAGS"])
+if test "$gcc_cv_c_no_fpie" = "yes"; then
+ NO_PIE_CFLAGS="-fno-PIE"
+fi
+AC_SUBST([NO_PIE_CFLAGS])
+
+# Check if -no-pie works.
+AC_CACHE_CHECK([for -no-pie option],
+ [gcc_cv_no_pie],
+ [saved_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -no-pie"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int main(void) {return 0;}])],
+ [gcc_cv_no_pie=yes],
+ [gcc_cv_no_pie=no])
+ LDFLAGS="$saved_LDFLAGS"])
+if test "$gcc_cv_no_pie" = "yes"; then
+ NO_PIE_FLAG="-no-pie"
+fi
+AC_SUBST([NO_PIE_FLAG])
+
+# Enable Intel CET on Intel CET enabled host if jit is enabled.
+GCC_CET_HOST_FLAGS(CET_HOST_FLAGS)
+case x$enable_languages in
+*jit*)
+ ;;
+*)
+ CET_HOST_FLAGS=
+ ;;
+esac
+AC_SUBST(CET_HOST_FLAGS)
+
+# Check linker supports '-z bndplt'
+ld_bndplt_support=no
+AC_MSG_CHECKING(linker -z bndplt option)
+if test x"$ld_is_gold" = xno; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
+ ld_bndplt_support=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ # Check if linker supports -a bndplt option
+ if $gcc_cv_ld --help 2>&1 | grep -- '-z bndplt' > /dev/null; then
+ ld_bndplt_support=yes
+ fi
+ fi
+fi
+if test x"$ld_bndplt_support" = xyes; then
+ AC_DEFINE(HAVE_LD_BNDPLT_SUPPORT, 1,
+ [Define if your linker supports -z bndplt])
+fi
+AC_MSG_RESULT($ld_bndplt_support)
+
+# Check linker supports '--push-state'/'--pop-state'
+ld_pushpopstate_support=no
+AC_MSG_CHECKING(linker --push-state/--pop-state options)
+if test x"$ld_is_gold" = xno; then
+ if test $in_tree_ld = yes ; then
+ if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then
+ ld_pushpopstate_support=yes
+ fi
+ elif test x$gcc_cv_ld != x; then
+ # Check if linker supports --push-state/--pop-state options
+ if $gcc_cv_ld --help 2>&1 | grep -- '--push-state' > /dev/null; then
+ ld_pushpopstate_support=yes
+ fi
+ fi
+fi
+if test x"$ld_pushpopstate_support" = xyes; then
+ AC_DEFINE(HAVE_LD_PUSHPOPSTATE_SUPPORT, 1,
+ [Define if your linker supports --push-state/--pop-state])
+fi
+AC_MSG_RESULT($ld_pushpopstate_support)
+
+# On s390, float_t has historically been statically defined as double for no
+# good reason. To comply with the C standard in the light of this definition,
+# gcc has evaluated float expressions in double precision when in
+# standards-compatible mode or when given -fexcess-precision=standard. To enable
+# a smooth transition towards the new model used by most architectures, where
+# gcc describes its behavior via the macro __FLT_EVAL_METHOD__ and glibc derives
+# float_t from that, this behavior can be configured with
+# --enable-s390-excess-float-precision. When given as enabled, that flag selects
+# the old model. When omitted, native builds and cross compiles that have target
+# libc headers will detect whether libc clamps float_t to double and in that
+# case maintain the old model. Otherwise, they will default to the new model.
+AC_ARG_ENABLE(s390-excess-float-precision,
+ [AS_HELP_STRING([--enable-s390-excess-float-precision],
+ [on s390 targets, evaluate float with double precision
+ when in standards-conforming mode])],
+ [],[enable_s390_excess_float_precision=auto])
+
+case $target in
+ s390*-linux*)
+ if test x"$enable_s390_excess_float_precision" = xauto; then
+ # Can we autodetect the behavior of the target libc?
+ if test "$target" = "$host" -a "$host" = "$build"; then
+ enable_s390_excess_float_precision=autodetect
+ elif test "x$with_headers" != xno; then
+ # cross build. are target headers available?
+ # carefully coerce the build-system compiler to use target headers
+ saved_CXXFLAGS="$CXXFLAGS"
+ fixed_XGCC_FLAGS_FOR_TARGET=`echo "$XGCC_FLAGS_FOR_TARGET" | sed 's/-B/-idirafter/g'`
+ CROSS_TEST_CXXFLAGS="-nostdinc $fixed_XGCC_FLAGS_FOR_TARGET"
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <math.h>
+]])], [enable_s390_excess_float_precision=autodetect], [])
+ CXXFLAGS="$saved_CXXFLAGS"
+ fi
+
+ if test x"$enable_s390_excess_float_precision" = xautodetect; then
+ saved_CXXFLAGS="$CXXFLAGS"
+ if ! test "$target" = "$host" -a "$host" = "$build"; then
+ CXXFLAGS="$CROSS_TEST_CXXFLAGS"
+ unset CROSS_TEST_CXXFLAGS
+ fi
+ AC_CACHE_CHECK([for glibc clamping float_t to double],
+ gcc_cv_float_t_clamped_to_double, [
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#define __FLT_EVAL_METHOD__ 0
+#include <math.h>
+int dummy[sizeof(float_t) == sizeof(double) ? 1 : -1];
+]])],
+ [gcc_cv_float_t_clamped_to_double=yes],
+ [gcc_cv_float_t_clamped_to_double=no])])
+ CXXFLAGS="$saved_CXXFLAGS"
+ enable_s390_excess_float_precision="$gcc_cv_float_t_clamped_to_double"
+ else
+ # no way to detect behavior of target libc, default to new model
+ enable_s390_excess_float_precision=no
+ fi
+ fi
+
+ GCC_TARGET_TEMPLATE(ENABLE_S390_EXCESS_FLOAT_PRECISION)
+ if test x"$enable_s390_excess_float_precision" = xyes; then
+ AC_DEFINE(ENABLE_S390_EXCESS_FLOAT_PRECISION, 1,
+[Define to enable evaluating float expressions with double precision in
+standards-compatible mode on s390 targets.])
+ fi
+ ;;
+esac
+
+# Configure the subdirectories
+# AC_CONFIG_SUBDIRS($subdirs)
+
+# Create the Makefile
+# and configure language subdirectories
+AC_CONFIG_FILES($all_outputs)
+
+AC_CONFIG_COMMANDS([default],
+[
+case ${CONFIG_HEADERS} in
+ *auto-host.h:config.in*)
+ echo > cstamp-h ;;
+esac
+# Make sure all the subdirs exist.
+for d in $subdirs doc build common c-family
+do
+ test -d $d || mkdir $d
+done
+],
+[subdirs='$subdirs'])
+AC_OUTPUT
+
diff --git a/support/cpp/gcc/context.cc b/support/cpp/gcc/context.cc
new file mode 100644
index 000000000..4eea3f4aa
--- /dev/null
+++ b/support/cpp/gcc/context.cc
@@ -0,0 +1,45 @@
+/* context.cc - Holder for global state
+ Copyright (C) 2013-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 "context.h"
+#include "pass_manager.h"
+#include "dumpfile.h"
+// #include "realmpfr.h"
+
+/* The singleton holder of global state: */
+gcc::context *g;
+
+gcc::context::context ()
+ : m_passes (NULL), m_dumps (new gcc::dump_manager ())
+{
+ have_offload = false;
+}
+
+gcc::context::~context ()
+{
+ delete m_passes;
+ delete m_dumps;
+
+ /* Release MPFR caches to avoid Valgrind leak reports. */
+ // sdcpp
+ // mpfr_free_cache ();
+}
diff --git a/support/cpp/gcc/context.h b/support/cpp/gcc/context.h
new file mode 100644
index 000000000..00c01fedc
--- /dev/null
+++ b/support/cpp/gcc/context.h
@@ -0,0 +1,69 @@
+/* context.h - Holder for global state
+ Copyright (C) 2013-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_CONTEXT_H
+#define GCC_CONTEXT_H
+
+namespace gcc {
+
+class pass_manager;
+class dump_manager;
+
+/* GCC's internal state can be divided into zero or more
+ "parallel universe" of state; an instance of this class is one such
+ context of state. */
+class context
+{
+public:
+ context ();
+ ~context ();
+
+ /* The flag shows if there are symbols to be streamed for offloading. */
+ bool have_offload;
+
+ /* Pass-management. */
+
+ void set_passes (pass_manager *m)
+ {
+ gcc_assert (!m_passes);
+ m_passes = m;
+ }
+
+ pass_manager *get_passes () { gcc_assert (m_passes); return m_passes; }
+
+ /* Handling dump files. */
+
+ dump_manager *get_dumps () {gcc_assert (m_dumps); return m_dumps; }
+
+private:
+ /* Pass-management. */
+ pass_manager *m_passes;
+
+ /* Dump files. */
+ dump_manager *m_dumps;
+
+}; // class context
+
+} // namespace gcc
+
+/* The global singleton context aka "g".
+ (the name is chosen to be easy to type in a debugger). */
+extern gcc::context *g;
+
+#endif /* ! GCC_CONTEXT_H */
diff --git a/support/cpp/gcc/convert.h b/support/cpp/gcc/convert.h
new file mode 100644
index 000000000..323b4af6f
--- /dev/null
+++ b/support/cpp/gcc/convert.h
@@ -0,0 +1,45 @@
+/* Definition of functions in convert.cc.
+ Copyright (C) 1993-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_CONVERT_H
+#define GCC_CONVERT_H
+
+extern tree convert_to_integer (tree, tree);
+extern tree convert_to_integer_maybe_fold (tree, tree, bool);
+extern tree convert_to_pointer (tree, tree);
+extern tree convert_to_pointer_maybe_fold (tree, tree, bool);
+extern tree convert_to_real (tree, tree);
+extern tree convert_to_real_maybe_fold (tree, tree, bool);
+extern tree convert_to_fixed (tree, tree);
+extern tree convert_to_complex (tree, tree);
+extern tree convert_to_complex_maybe_fold (tree, tree, bool);
+extern tree convert_to_vector (tree, tree);
+
+extern inline tree convert_to_integer_nofold (tree t, tree x)
+{ return convert_to_integer_maybe_fold (t, x, false); }
+extern inline tree convert_to_pointer_nofold (tree t, tree x)
+{ return convert_to_pointer_maybe_fold (t, x, false); }
+extern inline tree convert_to_real_nofold (tree t, tree x)
+{ return convert_to_real_maybe_fold (t, x, false); }
+extern inline tree convert_to_complex_nofold (tree t, tree x)
+{ return convert_to_complex_maybe_fold (t, x, false); }
+
+extern tree preserve_any_location_wrapper (tree result, tree orig_expr);
+
+#endif /* GCC_CONVERT_H */
diff --git a/support/cpp/gcc/coretypes.h b/support/cpp/gcc/coretypes.h
new file mode 100644
index 000000000..8c8fba775
--- /dev/null
+++ b/support/cpp/gcc/coretypes.h
@@ -0,0 +1,495 @@
+/* GCC core type declarations.
+ Copyright (C) 2002-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/>. */
+
+/* Provide forward declarations of core types which are referred to by
+ most of the compiler. This allows header files to use these types
+ (e.g. in function prototypes) without concern for whether the full
+ definitions are visible. Some other declarations that need to be
+ universally visible are here, too.
+
+ In the context of tconfig.h, most of these have special definitions
+ which prevent them from being used except in further type
+ declarations. This is a kludge; the right thing is to avoid
+ including the "tm.h" header set in the context of tconfig.h, but
+ we're not there yet. */
+
+#ifndef GCC_CORETYPES_H
+#define GCC_CORETYPES_H
+
+#ifndef GTY
+#define GTY(x) /* nothing - marker for gengtype */
+#endif
+
+#ifndef USED_FOR_TARGET
+
+typedef int64_t gcov_type;
+typedef uint64_t gcov_type_unsigned;
+
+struct bitmap_obstack;
+class bitmap_head;
+typedef class bitmap_head *bitmap;
+typedef const class bitmap_head *const_bitmap;
+struct simple_bitmap_def;
+typedef struct simple_bitmap_def *sbitmap;
+typedef const struct simple_bitmap_def *const_sbitmap;
+struct rtx_def;
+typedef struct rtx_def *rtx;
+typedef const struct rtx_def *const_rtx;
+class scalar_mode;
+class scalar_int_mode;
+class scalar_float_mode;
+class complex_mode;
+class fixed_size_mode;
+template<typename> class opt_mode;
+typedef opt_mode<scalar_mode> opt_scalar_mode;
+typedef opt_mode<scalar_int_mode> opt_scalar_int_mode;
+typedef opt_mode<scalar_float_mode> opt_scalar_float_mode;
+template<typename> struct pod_mode;
+typedef pod_mode<scalar_mode> scalar_mode_pod;
+typedef pod_mode<scalar_int_mode> scalar_int_mode_pod;
+typedef pod_mode<fixed_size_mode> fixed_size_mode_pod;
+
+/* Subclasses of rtx_def, using indentation to show the class
+ hierarchy, along with the relevant invariant.
+ Where possible, keep this list in the same order as in rtl.def. */
+struct rtx_def;
+ struct rtx_expr_list; /* GET_CODE (X) == EXPR_LIST */
+ struct rtx_insn_list; /* GET_CODE (X) == INSN_LIST */
+ struct rtx_sequence; /* GET_CODE (X) == SEQUENCE */
+ struct rtx_insn;
+ struct rtx_debug_insn; /* DEBUG_INSN_P (X) */
+ struct rtx_nonjump_insn; /* NONJUMP_INSN_P (X) */
+ struct rtx_jump_insn; /* JUMP_P (X) */
+ struct rtx_call_insn; /* CALL_P (X) */
+ struct rtx_jump_table_data; /* JUMP_TABLE_DATA_P (X) */
+ struct rtx_barrier; /* BARRIER_P (X) */
+ struct rtx_code_label; /* LABEL_P (X) */
+ struct rtx_note; /* NOTE_P (X) */
+
+struct rtvec_def;
+typedef struct rtvec_def *rtvec;
+typedef const struct rtvec_def *const_rtvec;
+struct hwivec_def;
+typedef struct hwivec_def *hwivec;
+typedef const struct hwivec_def *const_hwivec;
+union tree_node;
+typedef union tree_node *tree;
+typedef const union tree_node *const_tree;
+struct gimple;
+typedef gimple *gimple_seq;
+struct gimple_stmt_iterator;
+
+/* Forward decls for leaf gimple subclasses (for individual gimple codes).
+ Keep this in the same order as the corresponding codes in gimple.def. */
+
+struct gcond;
+struct gdebug;
+struct ggoto;
+struct glabel;
+struct gswitch;
+struct gassign;
+struct gasm;
+struct gcall;
+struct gtransaction;
+struct greturn;
+struct gbind;
+struct gcatch;
+struct geh_filter;
+struct geh_mnt;
+struct geh_else;
+struct gresx;
+struct geh_dispatch;
+struct gphi;
+struct gtry;
+struct gomp_atomic_load;
+struct gomp_atomic_store;
+struct gomp_continue;
+struct gomp_critical;
+struct gomp_ordered;
+struct gomp_for;
+struct gomp_parallel;
+struct gomp_task;
+struct gomp_sections;
+struct gomp_single;
+struct gomp_target;
+struct gomp_teams;
+
+/* Subclasses of symtab_node, using indentation to show the class
+ hierarchy. */
+
+struct symtab_node;
+ struct cgraph_node;
+ struct varpool_node;
+struct cgraph_edge;
+
+union section;
+typedef union section section;
+struct gcc_options;
+struct cl_target_option;
+struct cl_optimization;
+struct cl_option;
+struct cl_decoded_option;
+struct cl_option_handlers;
+struct diagnostic_context;
+class pretty_printer;
+class diagnostic_event_id_t;
+typedef const char * (*diagnostic_input_charset_callback)(const char *);
+
+template<typename T> struct array_traits;
+
+/* Provides a read-only bitmap view of a single integer bitmask or an
+ array of integer bitmasks, or of a wrapper around such bitmasks. */
+template<typename T, typename Traits = array_traits<T>,
+ bool has_constant_size = Traits::has_constant_size>
+class bitmap_view;
+
+/* Address space number for named address space support. */
+typedef unsigned char addr_space_t;
+
+/* The value of addr_space_t that represents the generic address space. */
+#define ADDR_SPACE_GENERIC 0
+#define ADDR_SPACE_GENERIC_P(AS) ((AS) == ADDR_SPACE_GENERIC)
+
+/* The major intermediate representations of GCC. */
+enum ir_type {
+ IR_GIMPLE,
+ IR_RTL_CFGRTL,
+ IR_RTL_CFGLAYOUT
+};
+
+/* Provide forward struct declaration so that we don't have to include
+ all of cpplib.h whenever a random prototype includes a pointer.
+ Note that the cpp_reader and cpp_token typedefs remain part of
+ cpplib.h. */
+
+struct cpp_reader;
+struct cpp_token;
+
+/* The thread-local storage model associated with a given VAR_DECL
+ or SYMBOL_REF. This isn't used much, but both trees and RTL refer
+ to it, so it's here. */
+enum tls_model {
+ TLS_MODEL_NONE,
+ TLS_MODEL_EMULATED,
+ TLS_MODEL_REAL,
+ TLS_MODEL_GLOBAL_DYNAMIC = TLS_MODEL_REAL,
+ TLS_MODEL_LOCAL_DYNAMIC,
+ TLS_MODEL_INITIAL_EXEC,
+ TLS_MODEL_LOCAL_EXEC
+};
+
+/* Types of ABI for an offload compiler. */
+enum offload_abi {
+ OFFLOAD_ABI_UNSET,
+ OFFLOAD_ABI_LP64,
+ OFFLOAD_ABI_ILP32
+};
+
+/* Types of profile update methods. */
+enum profile_update {
+ PROFILE_UPDATE_SINGLE,
+ PROFILE_UPDATE_ATOMIC,
+ PROFILE_UPDATE_PREFER_ATOMIC
+};
+
+/* Type of profile reproducibility methods. */
+enum profile_reproducibility {
+ PROFILE_REPRODUCIBILITY_SERIAL,
+ PROFILE_REPRODUCIBILITY_PARALLEL_RUNS,
+ PROFILE_REPRODUCIBILITY_MULTITHREADED
+};
+
+/* Type of -fstack-protector-*. */
+enum stack_protector {
+ SPCT_FLAG_DEFAULT = 1,
+ SPCT_FLAG_ALL = 2,
+ SPCT_FLAG_STRONG = 3,
+ SPCT_FLAG_EXPLICIT = 4
+};
+
+/* Types of unwind/exception handling info that can be generated.
+ Note that a UI_TARGET (or larger) setting is considered to be
+ incompatible with -freorder-blocks-and-partition. */
+
+enum unwind_info_type
+{
+ UI_NONE,
+ UI_SJLJ,
+ UI_DWARF2,
+ UI_SEH,
+ UI_TARGET
+};
+
+/* Callgraph node profile representation. */
+enum node_frequency {
+ /* This function most likely won't be executed at all.
+ (set only when profile feedback is available or via function attribute). */
+ NODE_FREQUENCY_UNLIKELY_EXECUTED,
+ /* For functions that are known to be executed once (i.e. constructors, destructors
+ and main function. */
+ NODE_FREQUENCY_EXECUTED_ONCE,
+ /* The default value. */
+ NODE_FREQUENCY_NORMAL,
+ /* Optimize this function hard
+ (set only when profile feedback is available or via function attribute). */
+ NODE_FREQUENCY_HOT
+};
+
+/* Ways of optimizing code. */
+enum optimization_type {
+ /* Prioritize speed over size. */
+ OPTIMIZE_FOR_SPEED,
+
+ /* Only do things that are good for both size and speed. */
+ OPTIMIZE_FOR_BOTH,
+
+ /* Prioritize size over speed. */
+ OPTIMIZE_FOR_SIZE
+};
+
+/* Enumerates a padding direction. */
+enum pad_direction {
+ /* No padding is required. */
+ PAD_NONE,
+
+ /* Insert padding above the data, i.e. at higher memeory addresses
+ when dealing with memory, and at the most significant end when
+ dealing with registers. */
+ PAD_UPWARD,
+
+ /* Insert padding below the data, i.e. at lower memeory addresses
+ when dealing with memory, and at the least significant end when
+ dealing with registers. */
+ PAD_DOWNWARD
+};
+
+/* Possible initialization status of a variable. When requested
+ by the user, this information is tracked and recorded in the DWARF
+ debug information, along with the variable's location. */
+enum var_init_status
+{
+ VAR_INIT_STATUS_UNKNOWN,
+ VAR_INIT_STATUS_UNINITIALIZED,
+ VAR_INIT_STATUS_INITIALIZED
+};
+
+/* Names for the different levels of -Wstrict-overflow=N. The numeric
+ values here correspond to N. */
+enum warn_strict_overflow_code
+{
+ /* Overflow warning that should be issued with -Wall: a questionable
+ construct that is easy to avoid even when using macros. Example:
+ folding (x + CONSTANT > x) to 1. */
+ WARN_STRICT_OVERFLOW_ALL = 1,
+ /* Overflow warning about folding a comparison to a constant because
+ of undefined signed overflow, other than cases covered by
+ WARN_STRICT_OVERFLOW_ALL. Example: folding (abs (x) >= 0) to 1
+ (this is false when x == INT_MIN). */
+ WARN_STRICT_OVERFLOW_CONDITIONAL = 2,
+ /* Overflow warning about changes to comparisons other than folding
+ them to a constant. Example: folding (x + 1 > 1) to (x > 0). */
+ WARN_STRICT_OVERFLOW_COMPARISON = 3,
+ /* Overflow warnings not covered by the above cases. Example:
+ folding ((x * 10) / 5) to (x * 2). */
+ WARN_STRICT_OVERFLOW_MISC = 4,
+ /* Overflow warnings about reducing magnitude of constants in
+ comparison. Example: folding (x + 2 > y) to (x + 1 >= y). */
+ WARN_STRICT_OVERFLOW_MAGNITUDE = 5
+};
+
+/* The type of an alias set. Code currently assumes that variables of
+ this type can take the values 0 (the alias set which aliases
+ everything) and -1 (sometimes indicating that the alias set is
+ unknown, sometimes indicating a memory barrier) and -2 (indicating
+ that the alias set should be set to a unique value but has not been
+ set yet). */
+typedef int alias_set_type;
+
+class edge_def;
+typedef class edge_def *edge;
+typedef const class edge_def *const_edge;
+struct basic_block_def;
+typedef struct basic_block_def *basic_block;
+typedef const struct basic_block_def *const_basic_block;
+
+#if !defined (GENERATOR_FILE)
+# define OBSTACK_CHUNK_SIZE memory_block_pool::block_size
+# define obstack_chunk_alloc mempool_obstack_chunk_alloc
+# define obstack_chunk_free mempool_obstack_chunk_free
+#else
+# define OBSTACK_CHUNK_SIZE 0
+# define obstack_chunk_alloc xmalloc
+# define obstack_chunk_free free
+#endif
+
+#define gcc_obstack_init(OBSTACK) \
+ obstack_specify_allocation ((OBSTACK), OBSTACK_CHUNK_SIZE, 0, \
+ obstack_chunk_alloc, \
+ obstack_chunk_free)
+
+/* enum reg_class is target specific, so it should not appear in
+ target-independent code or interfaces, like the target hook declarations
+ in target.h. */
+typedef int reg_class_t;
+
+class rtl_opt_pass;
+
+namespace gcc {
+ class context;
+}
+
+typedef std::pair <tree, tree> tree_pair;
+typedef std::pair <const char *, int> string_int_pair;
+
+/* Define a name->value mapping. */
+template <typename ValueType>
+struct kv_pair
+{
+ const char *const name; /* the name of the value */
+ const ValueType value; /* the value of the name */
+};
+
+#else
+
+struct _dont_use_rtx_here_;
+struct _dont_use_rtvec_here_;
+struct _dont_use_rtx_insn_here_;
+union _dont_use_tree_here_;
+#define rtx struct _dont_use_rtx_here_ *
+#define const_rtx struct _dont_use_rtx_here_ *
+#define rtvec struct _dont_use_rtvec_here *
+#define const_rtvec struct _dont_use_rtvec_here *
+#define rtx_insn struct _dont_use_rtx_insn_here_
+#define tree union _dont_use_tree_here_ *
+#define const_tree union _dont_use_tree_here_ *
+
+typedef struct scalar_mode scalar_mode;
+typedef struct scalar_int_mode scalar_int_mode;
+typedef struct scalar_float_mode scalar_float_mode;
+typedef struct complex_mode complex_mode;
+
+#endif
+
+/* Classes of functions that compiler needs to check
+ whether they are present at the runtime or not. */
+enum function_class {
+ function_c94,
+ function_c99_misc,
+ function_c99_math_complex,
+ function_sincos,
+ function_c11_misc,
+ function_c2x_misc
+};
+
+/* Enumerate visibility settings. This is deliberately ordered from most
+ to least visibility. */
+enum symbol_visibility
+{
+ VISIBILITY_DEFAULT,
+ VISIBILITY_PROTECTED,
+ VISIBILITY_HIDDEN,
+ VISIBILITY_INTERNAL
+};
+
+/* enums used by the targetm.excess_precision hook. */
+
+enum flt_eval_method
+{
+ FLT_EVAL_METHOD_UNPREDICTABLE = -1,
+ FLT_EVAL_METHOD_PROMOTE_TO_FLOAT = 0,
+ FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE = 1,
+ FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE = 2,
+ FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 = 16
+};
+
+enum excess_precision_type
+{
+ EXCESS_PRECISION_TYPE_IMPLICIT,
+ EXCESS_PRECISION_TYPE_STANDARD,
+ EXCESS_PRECISION_TYPE_FAST,
+ EXCESS_PRECISION_TYPE_FLOAT16
+};
+
+/* Level of size optimization. */
+
+enum optimize_size_level
+{
+ /* Do not optimize for size. */
+ OPTIMIZE_SIZE_NO,
+ /* Optimize for size but not at extreme performance costs. */
+ OPTIMIZE_SIZE_BALANCED,
+ /* Optimize for size as much as possible. */
+ OPTIMIZE_SIZE_MAX
+};
+
+/* Support for user-provided GGC and PCH markers. The first parameter
+ is a pointer to a pointer, the second either NULL if the pointer to
+ pointer points into a GC object or the actual pointer address if
+ the first argument points to a temporary and the third a cookie. */
+typedef void (*gt_pointer_operator) (void *, void *, void *);
+
+#if !defined (HAVE_UCHAR)
+typedef unsigned char uchar;
+#endif
+
+/* Most source files will require the following headers. */
+#if !defined (USED_FOR_TARGET)
+#include "insn-modes.h"
+#include "signop.h"
+// sdcpp #include "wide-int.h"
+// sdcpp #include "wide-int-print.h"
+
+/* On targets that don't need polynomial offsets, target-specific code
+ should be able to treat poly_int like a normal constant, with a
+ conversion operator going from the former to the latter. We also
+ allow this for gencondmd.cc for all targets, so that we can treat
+ machine_modes as enums without causing build failures. */
+#if (defined (IN_TARGET_CODE) \
+ && (defined (USE_ENUM_MODES) || NUM_POLY_INT_COEFFS == 1))
+#define POLY_INT_CONVERSION 1
+#else
+#define POLY_INT_CONVERSION 0
+#endif
+
+// sdcpp #include "poly-int.h"
+// sdcpp #include "poly-int-types.h"
+#include "insn-modes-inline.h"
+#include "machmode.h"
+#include "double-int.h"
+#include "align.h"
+/* Most host source files will require the following headers. */
+#if !defined (GENERATOR_FILE)
+#include "iterator-utils.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "hash-table.h"
+#include "hash-set.h"
+#include "input.h"
+#include "is-a.h"
+#include "memory-block.h"
+#include "dumpfile.h"
+#endif
+#endif /* GENERATOR_FILE && !USED_FOR_TARGET */
+
+#endif /* coretypes.h */
diff --git a/support/cpp/gcc/coroutine-builtins.def b/support/cpp/gcc/coroutine-builtins.def
new file mode 100644
index 000000000..feecdb5ad
--- /dev/null
+++ b/support/cpp/gcc/coroutine-builtins.def
@@ -0,0 +1,53 @@
+/* This file contains the definitions and documentation for the
+ coroutines builtins used in GCC.
+
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+
+ Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
+
+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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_BUILTIN_STUB(ENUM, NAME)
+ DEF_COROUTINE_BUILTIN (ENUM, NAME, TYPE, ATTRS)
+
+ See builtins.def for details.
+ The builtins are created used by library implementations of C++
+ coroutines. */
+
+/* This has to come before all the coroutine builtins. */
+DEF_BUILTIN_STUB (BEGIN_COROUTINE_BUILTINS, (const char *) 0)
+
+/* These are the builtins that are externally-visible and used by the
+ standard library implementation of the coroutine header. */
+
+DEF_COROUTINE_BUILTIN (BUILT_IN_CORO_PROMISE, "promise",
+ BT_FN_PTR_PTR_CONST_SIZE_BOOL,
+ ATTR_CONST_NOTHROW_LEAF_LIST)
+
+DEF_COROUTINE_BUILTIN (BUILT_IN_CORO_RESUME, "resume", BT_FN_VOID_PTR,
+ ATTR_NULL)
+
+DEF_COROUTINE_BUILTIN (BUILT_IN_CORO_DESTROY, "destroy", BT_FN_VOID_PTR,
+ ATTR_NULL)
+
+DEF_COROUTINE_BUILTIN (BUILT_IN_CORO_DONE, "done", BT_FN_BOOL_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+
+/* This has to come after all the coroutine builtins. */
+DEF_BUILTIN_STUB (END_COROUTINE_BUILTINS, (const char *) 0)
diff --git a/support/cpp/gcc/cppbuiltin.h b/support/cpp/gcc/cppbuiltin.h
new file mode 100644
index 000000000..e84bcc66e
--- /dev/null
+++ b/support/cpp/gcc/cppbuiltin.h
@@ -0,0 +1,33 @@
+/* Define builtin-in macros for all front ends that perform preprocessing
+ Copyright (C) 2010-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_CPPBUILTIN_H
+#define GCC_CPPBUILTIN_H
+
+/* Parse a BASEVER version string of the format "major.minor.patchlevel"
+ or "major.minor" to extract its components. */
+extern void parse_basever (int *, int *, int *);
+
+/* Define macros builtins common to all language performing CPP
+ preprocessing. */
+extern void define_language_independent_builtin_macros (cpp_reader *);
+
+
+#endif /* ! GCC_CPPBUILTIN_H */
+
diff --git a/support/cpp/gcc/cppdefault.cc b/support/cpp/gcc/cppdefault.cc
new file mode 100644
index 000000000..dd333c672
--- /dev/null
+++ b/support/cpp/gcc/cppdefault.cc
@@ -0,0 +1,138 @@
+/* CPP Library.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
+ Contributed by Per Bothner, 1994-95.
+ Based on CCCP program by Paul Rubin, June 1986
+ Adapted to ANSI C, Richard Stallman, Jan 1987
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; 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 "cppdefault.h"
+
+#ifndef NATIVE_SYSTEM_HEADER_COMPONENT
+#define NATIVE_SYSTEM_HEADER_COMPONENT 0
+#endif
+
+#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT)
+# undef LOCAL_INCLUDE_DIR
+# undef NATIVE_SYSTEM_HEADER_DIR
+#else
+# undef CROSS_INCLUDE_DIR
+#endif
+
+const struct default_include cpp_include_defaults[]
+#ifdef INCLUDE_DEFAULTS
+= INCLUDE_DEFAULTS;
+#else
+= {
+#ifdef GPLUSPLUS_INCLUDE_DIR
+ /* Pick up GNU C++ generic include files. */
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1,
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
+#endif
+#ifdef GPLUSPLUS_TOOL_INCLUDE_DIR
+ /* Pick up GNU C++ target-dependent include files. */
+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1,
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 1 },
+#endif
+#ifdef GPLUSPLUS_BACKWARD_INCLUDE_DIR
+ /* Pick up GNU C++ backward and deprecated include files. */
+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1,
+ GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
+#endif
+#ifdef GPLUSPLUS_LIBCXX_INCLUDE_DIR
+ /* Pick up libc++ include files, if we have -stdlib=libc++. */
+ { GPLUSPLUS_LIBCXX_INCLUDE_DIR, "G++", 2, 1,
+ GPLUSPLUS_LIBCXX_INCLUDE_DIR_ADD_SYSROOT, 0 },
+#endif
+#ifdef GCC_INCLUDE_DIR
+ /* This is the dir for gcc's private headers. */
+ { GCC_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },
+#endif
+#ifdef LOCAL_INCLUDE_DIR
+ /* /usr/local/include comes before the fixincluded header files. */
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 },
+ { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 },
+#endif
+#ifdef PREFIX_INCLUDE_DIR
+ { PREFIX_INCLUDE_DIR, 0, 0, 1, 0, 0 },
+#endif
+#ifdef FIXED_INCLUDE_DIR
+ /* This is the dir for fixincludes. */
+ { FIXED_INCLUDE_DIR, "GCC", 0, 0, 0,
+ /* A multilib suffix needs adding if different multilibs use
+ different headers. */
+#ifdef SYSROOT_HEADERS_SUFFIX_SPEC
+ 1
+#else
+ 0
+#endif
+ },
+#endif
+#ifdef CROSS_INCLUDE_DIR
+ /* One place the target system's headers might be. */
+ { CROSS_INCLUDE_DIR, "GCC", 0, 0, 0, 0 },
+#endif
+#ifdef TOOL_INCLUDE_DIR
+ /* Another place the target system's headers might be. */
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0 },
+#endif
+#ifdef NATIVE_SYSTEM_HEADER_DIR
+ /* /usr/include comes dead last. */
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0, 1, 2 },
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0, 1, 0 },
+#endif
+ { 0, 0, 0, 0, 0, 0 }
+ };
+#endif /* no INCLUDE_DEFAULTS */
+
+#ifdef GCC_INCLUDE_DIR
+const char cpp_GCC_INCLUDE_DIR[] = GCC_INCLUDE_DIR;
+const size_t cpp_GCC_INCLUDE_DIR_len = sizeof GCC_INCLUDE_DIR - 8;
+#else
+const char cpp_GCC_INCLUDE_DIR[] = "";
+const size_t cpp_GCC_INCLUDE_DIR_len = 0;
+#endif
+
+/* The configured prefix. */
+const char cpp_PREFIX[] = PREFIX;
+const size_t cpp_PREFIX_len = sizeof PREFIX - 1;
+const char cpp_EXEC_PREFIX[] = STANDARD_EXEC_PREFIX;
+
+/* This value is set by cpp_relocated at runtime */
+const char *gcc_exec_prefix;
+
+/* Return true if the toolchain is relocated. */
+bool
+cpp_relocated (void)
+{
+ static int relocated = -1;
+
+ /* A relocated toolchain ignores standard include directories. */
+ if (relocated == -1)
+ {
+ /* Check if the toolchain was relocated? */
+ gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX");
+ if (gcc_exec_prefix)
+ relocated = 1;
+ else
+ relocated = 0;
+ }
+
+ return relocated;
+}
diff --git a/support/cpp/gcc/cppdefault.h b/support/cpp/gcc/cppdefault.h
new file mode 100644
index 000000000..854d4850e
--- /dev/null
+++ b/support/cpp/gcc/cppdefault.h
@@ -0,0 +1,70 @@
+/* CPP Library.
+ Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+ Contributed by Per Bothner, 1994-95.
+ Based on CCCP program by Paul Rubin, June 1986
+ Adapted to ANSI C, Richard Stallman, Jan 1987
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_CPPDEFAULT_H
+#define GCC_CPPDEFAULT_H
+
+/* This is the default list of directories to search for include files.
+ It may be overridden by the various -I and -ixxx options.
+
+ #include "file" looks in the same directory as the current file,
+ then this list.
+ #include <file> just looks in this list.
+
+ All these directories are treated as `system' include directories
+ (they are not subject to pedantic warnings in some cases). */
+
+struct default_include
+{
+ const char *const fname; /* The name of the directory. */
+ const char *const component; /* The component containing the directory
+ (see update_path in prefix.c) */
+ const char cplusplus; /* Only look here if we're compiling C++. */
+ const char cxx_aware; /* Includes in this directory don't need to
+ be wrapped in extern "C" when compiling
+ C++. */
+ const char add_sysroot; /* FNAME should be prefixed by
+ cpp_SYSROOT. */
+ const char multilib; /* FNAME should have the multilib path
+ specified with -imultilib
+ appended. */
+};
+
+extern const struct default_include cpp_include_defaults[];
+extern const char cpp_GCC_INCLUDE_DIR[];
+extern const size_t cpp_GCC_INCLUDE_DIR_len;
+
+/* The configure-time prefix, i.e., the value supplied as the argument
+ to --prefix=. */
+extern const char cpp_PREFIX[];
+/* The length of the configure-time prefix. */
+extern const size_t cpp_PREFIX_len;
+/* The configure-time execution prefix. This is typically the lib/gcc
+ subdirectory of cpp_PREFIX. */
+extern const char cpp_EXEC_PREFIX[];
+/* The run-time execution prefix. This is typically the lib/gcc
+ subdirectory of the actual installation. */
+extern const char *gcc_exec_prefix;
+
+/* Return true if the toolchain is relocated. */
+bool cpp_relocated (void);
+
+#endif /* ! GCC_CPPDEFAULT_H */
diff --git a/support/cpp/gcc/cselib.h b/support/cpp/gcc/cselib.h
new file mode 100644
index 000000000..9ae65e645
--- /dev/null
+++ b/support/cpp/gcc/cselib.h
@@ -0,0 +1,142 @@
+/* Common subexpression elimination for 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/>. */
+
+#ifndef GCC_CSELIB_H
+#define GCC_CSELIB_H
+
+/* Describe a value. */
+struct cselib_val
+{
+ /* The hash value. */
+ unsigned int hash;
+
+ /* A unique id assigned to values. */
+ int uid;
+
+ /* A VALUE rtx that points back to this structure. */
+ rtx val_rtx;
+
+ /* All rtl expressions that hold this value at the current time during a
+ scan. */
+ struct elt_loc_list *locs;
+
+ /* If this value is used as an address, points to a list of values that
+ use it as an address in a MEM. */
+ struct elt_list *addr_list;
+
+ struct cselib_val *next_containing_mem;
+};
+
+/* A list of rtl expressions that hold the same value. */
+struct elt_loc_list {
+ /* Next element in the list. */
+ struct elt_loc_list *next;
+ /* An rtl expression that holds the value. */
+ rtx loc;
+ /* The insn that made the equivalence. */
+ rtx_insn *setting_insn;
+};
+
+/* Describe a single set that is part of an insn. */
+struct cselib_set
+{
+ rtx src;
+ rtx dest;
+ cselib_val *src_elt;
+ cselib_val *dest_addr_elt;
+};
+
+enum cselib_record_what
+{
+ CSELIB_RECORD_MEMORY = 1,
+ CSELIB_PRESERVE_CONSTANTS = 2
+};
+
+extern void (*cselib_discard_hook) (cselib_val *);
+extern void (*cselib_record_sets_hook) (rtx_insn *insn, struct cselib_set *sets,
+ int n_sets);
+
+extern cselib_val *cselib_lookup (rtx, machine_mode,
+ int, machine_mode);
+extern cselib_val *cselib_lookup_from_insn (rtx, machine_mode,
+ int, machine_mode, rtx_insn *);
+extern void cselib_init (int);
+extern void cselib_clear_table (void);
+extern void cselib_finish (void);
+extern void cselib_process_insn (rtx_insn *);
+extern bool fp_setter_insn (rtx_insn *);
+extern machine_mode cselib_reg_set_mode (const_rtx);
+extern int rtx_equal_for_cselib_1 (rtx, rtx, machine_mode, int);
+extern int references_value_p (const_rtx, int);
+extern rtx cselib_expand_value_rtx (rtx, bitmap, int);
+typedef rtx (*cselib_expand_callback)(rtx, bitmap, int, void *);
+extern rtx cselib_expand_value_rtx_cb (rtx, bitmap, int,
+ cselib_expand_callback, void *);
+extern bool cselib_dummy_expand_value_rtx_cb (rtx, bitmap, int,
+ cselib_expand_callback, void *);
+extern rtx cselib_subst_to_values (rtx, machine_mode);
+extern rtx cselib_subst_to_values_from_insn (rtx, machine_mode, rtx_insn *);
+extern void cselib_invalidate_rtx (rtx);
+
+extern void cselib_reset_table (unsigned int);
+extern unsigned int cselib_get_next_uid (void);
+extern void cselib_preserve_value (cselib_val *);
+extern bool cselib_preserved_value_p (cselib_val *);
+extern void cselib_preserve_only_values (void);
+extern void cselib_preserve_cfa_base_value (cselib_val *, unsigned int);
+extern void cselib_add_permanent_equiv (cselib_val *, rtx, rtx_insn *);
+extern bool cselib_have_permanent_equivalences (void);
+extern void cselib_set_value_sp_based (cselib_val *);
+extern bool cselib_sp_based_value_p (cselib_val *);
+extern void cselib_record_sp_cfa_base_equiv (HOST_WIDE_INT, rtx_insn *);
+extern bool cselib_sp_derived_value_p (cselib_val *);
+
+extern void dump_cselib_table (FILE *);
+
+/* Return the canonical value for VAL, following the equivalence chain
+ towards the earliest (== lowest uid) equivalent value. */
+
+static inline cselib_val *
+canonical_cselib_val (cselib_val *val)
+{
+ cselib_val *canon;
+
+ if (!val->locs || val->locs->next
+ || !val->locs->loc || GET_CODE (val->locs->loc) != VALUE
+ || val->uid < CSELIB_VAL_PTR (val->locs->loc)->uid)
+ return val;
+
+ canon = CSELIB_VAL_PTR (val->locs->loc);
+ gcc_checking_assert (canonical_cselib_val (canon) == canon);
+ return canon;
+}
+
+/* Return nonzero if we can prove that X and Y contain the same value, taking
+ our gathered information into account. */
+
+static inline int
+rtx_equal_for_cselib_p (rtx x, rtx y)
+{
+ if (x == y)
+ return 1;
+
+ return rtx_equal_for_cselib_1 (x, y, VOIDmode, 0);
+}
+
+#endif /* GCC_CSELIB_H */
diff --git a/support/cpp/gcc/ctfc.h b/support/cpp/gcc/ctfc.h
new file mode 100644
index 000000000..001e544ef
--- /dev/null
+++ b/support/cpp/gcc/ctfc.h
@@ -0,0 +1,448 @@
+/* ctfc.h - Declarations and definitions related to the CTF container.
+ Copyright (C) 2019-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 defines the data structures and functions used by the compiler
+ to generate the CTF debug info. The definitions below are compiler internal
+ representations and closely reflect the CTF format requirements in <ctf.h>.
+
+ The contents of the CTF container are used eventually for emission of both
+ CTF (ctfout.cc) and BTF debug info (btfout.cc), as the two type debug formats
+ are close cousins. */
+
+#ifndef GCC_CTFC_H
+#define GCC_CTFC_H 1
+
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "dwarf2ctf.h"
+#include "ctf.h"
+#include "btf.h"
+
+/* Invalid CTF type ID definition. */
+
+#define CTF_NULL_TYPEID 0
+
+/* Value to start generating the CTF type ID from. */
+
+#define CTF_INIT_TYPEID 1
+
+/* CTF type ID. */
+
+typedef uint64_t ctf_id_t;
+
+/* CTF string table element (list node). */
+
+typedef struct GTY ((chain_next ("%h.cts_next"))) ctf_string
+{
+ const char * cts_str; /* CTF string. */
+ struct ctf_string * cts_next; /* A list node. */
+} ctf_string_t;
+
+/* Internal representation of CTF string table. */
+
+typedef struct GTY (()) ctf_strtable
+{
+ ctf_string_t * ctstab_head; /* Head str ptr. */
+ ctf_string_t * ctstab_tail; /* Tail. new str appended to tail. */
+ int ctstab_num; /* Number of strings in the table. */
+ size_t ctstab_len; /* Size of string table in bytes. */
+ const char * ctstab_estr; /* Empty string "". */
+} ctf_strtable_t;
+
+/* Encoding information for integers, floating-point values etc. The flags
+ field will contain values appropriate for the type defined in <ctf.h>. */
+
+typedef struct GTY (()) ctf_encoding
+{
+ unsigned int cte_format; /* Data format (CTF_INT_* or CTF_FP_* flags). */
+ unsigned int cte_offset; /* Offset of value in bits. */
+ unsigned int cte_bits; /* Size of storage in bits. */
+} ctf_encoding_t;
+
+/* Array information for CTF generation. */
+
+typedef struct GTY (()) ctf_arinfo
+{
+ ctf_id_t ctr_contents; /* Type of array contents. */
+ ctf_id_t ctr_index; /* Type of array index. */
+ unsigned int ctr_nelems; /* Number of elements. */
+} ctf_arinfo_t;
+
+/* Function information for CTF generation. */
+
+typedef struct GTY (()) ctf_funcinfo
+{
+ ctf_id_t ctc_return; /* Function return type. */
+ unsigned int ctc_argc; /* Number of typed arguments to function. */
+ unsigned int ctc_flags; /* Function attributes (see below). */
+} ctf_funcinfo_t;
+
+typedef struct GTY (()) ctf_sliceinfo
+{
+ unsigned int cts_type; /* Reference CTF type. */
+ unsigned short cts_offset; /* Offset in bits of the first bit. */
+ unsigned short cts_bits; /* Size in bits. */
+} ctf_sliceinfo_t;
+
+/* CTF type representation internal to the compiler. It closely reflects the
+ ctf_type_t type node in <ctf.h> except the GTY (()) tags. */
+
+typedef struct GTY (()) ctf_itype
+{
+ uint32_t ctti_name; /* Reference to name in string table. */
+ uint32_t ctti_info; /* Encoded kind, variant length (see below). */
+ union GTY ((desc ("0")))
+ {
+ uint32_t GTY ((tag ("0"))) _size;/* Size of entire type in bytes. */
+ uint32_t GTY ((tag ("1"))) _type;/* Reference to another type. */
+ } _u;
+ uint32_t ctti_lsizehi; /* High 32 bits of type size in bytes. */
+ uint32_t ctti_lsizelo; /* Low 32 bits of type size in bytes. */
+} ctf_itype_t;
+
+#define ctti_size _u._size
+#define ctti_type _u._type
+
+/* Function arguments end with varargs. */
+
+#define CTF_FUNC_VARARG 0x1
+
+/* Struct/union/enum member definition for CTF generation. */
+
+typedef struct GTY ((chain_next ("%h.dmd_next"))) ctf_dmdef
+{
+ const char * dmd_name; /* Name of this member. */
+ ctf_id_t dmd_type; /* Type of this member (for sou). */
+ uint32_t dmd_name_offset; /* Offset of the name in str table. */
+ uint64_t dmd_offset; /* Offset of this member in bits (for sou). */
+ int dmd_value; /* Value of this member (for enum). */
+ struct ctf_dmdef * dmd_next; /* A list node. */
+} ctf_dmdef_t;
+
+#define ctf_dmd_list_next(elem) ((ctf_dmdef_t *)((elem)->dmd_next))
+
+/* Function Argument. */
+
+typedef struct GTY (()) ctf_func_arg
+{
+ ctf_id_t farg_type; /* Type identifier of the argument. */
+ const char * farg_name; /* Name of the argument. */
+ uint32_t farg_name_offset; /* Offset of the name in str table. */
+ struct ctf_func_arg * farg_next;/* A list node. */
+} ctf_func_arg_t;
+
+#define ctf_farg_list_next(elem) ((ctf_func_arg_t *)((elem)->farg_next))
+
+/* Type definition for CTF generation. */
+
+struct GTY ((for_user)) ctf_dtdef
+{
+ dw_die_ref dtd_key; /* Type key for hashing. */
+ const char * dtd_name; /* Name associated with definition (if any). */
+ ctf_id_t dtd_type; /* Type identifier for this definition. */
+ ctf_itype_t dtd_data; /* Type node. */
+ bool from_global_func; /* Whether this type was added from a global
+ function. */
+ union GTY ((desc ("ctf_dtu_d_union_selector (&%1)")))
+ {
+ /* struct, union, or enum. */
+ ctf_dmdef_t * GTY ((tag ("CTF_DTU_D_MEMBERS"))) dtu_members;
+ /* array. */
+ ctf_arinfo_t GTY ((tag ("CTF_DTU_D_ARRAY"))) dtu_arr;
+ /* integer or float. */
+ ctf_encoding_t GTY ((tag ("CTF_DTU_D_ENCODING"))) dtu_enc;
+ /* function. */
+ ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv;
+ /* slice. */
+ ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice;
+ } dtd_u;
+};
+
+typedef struct ctf_dtdef ctf_dtdef_t;
+
+/* Variable definition for CTF generation. */
+
+struct GTY ((for_user)) ctf_dvdef
+{
+ dw_die_ref dvd_key; /* DWARF DIE corresponding to the variable. */
+ const char * dvd_name; /* Name associated with variable. */
+ uint32_t dvd_name_offset; /* Offset of the name in str table. */
+ unsigned int dvd_visibility; /* External visibility. 0=static,1=global. */
+ ctf_id_t dvd_type; /* Type of variable. */
+};
+
+typedef struct ctf_dvdef ctf_dvdef_t;
+
+typedef ctf_dvdef_t * ctf_dvdef_ref;
+typedef ctf_dtdef_t * ctf_dtdef_ref;
+
+/* Location information for CTF Types and CTF Variables. */
+
+typedef struct GTY (()) ctf_srcloc
+{
+ const char * ctsloc_file;
+ unsigned int ctsloc_line;
+ unsigned int ctsloc_col;
+} ctf_srcloc_t;
+
+typedef ctf_srcloc_t * ctf_srcloc_ref;
+
+/* Helper enum and api for the GTY machinery to work on union dtu_d. */
+
+enum ctf_dtu_d_union_enum {
+ CTF_DTU_D_MEMBERS,
+ CTF_DTU_D_ARRAY,
+ CTF_DTU_D_ENCODING,
+ CTF_DTU_D_ARGUMENTS,
+ CTF_DTU_D_SLICE
+};
+
+enum ctf_dtu_d_union_enum
+ctf_dtu_d_union_selector (ctf_dtdef_ref);
+
+struct ctfc_dtd_hasher : ggc_ptr_hash <ctf_dtdef_t>
+{
+ typedef ctf_dtdef_ref compare_type;
+
+ static hashval_t hash (ctf_dtdef_ref);
+ static bool equal (ctf_dtdef_ref, ctf_dtdef_ref);
+};
+
+inline hashval_t
+ctfc_dtd_hasher::hash (ctf_dtdef_ref dtd)
+{
+ return htab_hash_pointer (dtd->dtd_key);
+}
+
+inline bool
+ctfc_dtd_hasher::equal (ctf_dtdef_ref dtd, ctf_dtdef_ref dtd2)
+{
+ return (dtd->dtd_key == dtd2->dtd_key);
+}
+
+struct ctfc_dvd_hasher : ggc_ptr_hash <ctf_dvdef_t>
+{
+ typedef ctf_dvdef_ref compare_type;
+
+ static hashval_t hash (ctf_dvdef_ref);
+ static bool equal (ctf_dvdef_ref, ctf_dvdef_ref);
+};
+
+inline hashval_t
+ctfc_dvd_hasher::hash (ctf_dvdef_ref dvd)
+{
+ return htab_hash_pointer (dvd->dvd_key);
+}
+
+inline bool
+ctfc_dvd_hasher::equal (ctf_dvdef_ref dvd, ctf_dvdef_ref dvd2)
+{
+ return (dvd->dvd_key == dvd2->dvd_key);
+}
+
+/* CTF container structure.
+ It is the context passed around when generating ctf debug info. There is
+ one container per translation unit. */
+
+typedef struct GTY (()) ctf_container
+{
+ /* CTF Preamble. */
+ unsigned short ctfc_magic;
+ unsigned char ctfc_version;
+ unsigned char ctfc_flags;
+ uint32_t ctfc_cuname_offset;
+
+ /* CTF types. */
+ hash_table <ctfc_dtd_hasher> * GTY (()) ctfc_types;
+ /* CTF variables. */
+ hash_table <ctfc_dvd_hasher> * GTY (()) ctfc_vars;
+ /* CTF variables to be ignored. */
+ hash_table <ctfc_dvd_hasher> * GTY (()) ctfc_ignore_vars;
+
+ /* CTF string table. */
+ ctf_strtable_t ctfc_strtable;
+ /* Auxilliary string table. At this time, used for keeping func arg names
+ for BTF. */
+ ctf_strtable_t ctfc_aux_strtable;
+
+ uint64_t ctfc_num_types;
+ uint64_t ctfc_num_stypes;
+ uint64_t ctfc_num_global_funcs;
+ uint64_t ctfc_num_global_objts;
+
+ /* Number of vlen bytes - the variable length portion after ctf_type_t and
+ ctf_stype_t in the CTF section. This is used to calculate the offsets in
+ the CTF header. */
+ uint64_t ctfc_num_vlen_bytes;
+
+ /* Next CTF type id to assign. */
+ ctf_id_t ctfc_nextid;
+
+ /* Specify an explicit length of 0 so that the GC marking routines steer
+ clear of marking the CTF vars and CTF types twice. These lists below do
+ not own the pointed to objects, they simply hold references to them. */
+
+ /* List of pre-processed CTF Variables. CTF requires that the variables
+ appear in the sorted order of their names. */
+ ctf_dvdef_t ** GTY ((length ("0"))) ctfc_vars_list;
+ /* Count of pre-processed CTF Variables in the list. */
+ uint64_t ctfc_vars_list_count;
+ /* List of pre-processed CTF types. CTF requires that a shared type must
+ appear before the type that uses it. For the compiler, this means types
+ are emitted in sorted order of their type IDs. */
+ ctf_dtdef_t ** GTY ((length ("0"))) ctfc_types_list;
+ /* List of CTF function types for global functions. The order of global
+ function entries in the CTF funcinfo section is undefined by the
+ compiler. */
+ ctf_dtdef_t ** GTY ((length ("0"))) ctfc_gfuncs_list;
+ /* List of CTF variables at global scope. The order of global object entries
+ in the CTF objinfo section is undefined by the compiler. */
+ ctf_dvdef_t ** GTY ((length ("0"))) ctfc_gobjts_list;
+
+ /* Following members are for debugging only. They do not add functional
+ value to the task of CTF creation. These can be cleaned up once CTF
+ generation stabilizes. */
+
+ /* Keep a count of the number of bytes dumped in asm for debugging
+ purposes. */
+ uint64_t ctfc_numbytes_asm;
+ /* Total length of all strings in CTF. */
+ size_t ctfc_strlen;
+ /* Total length of all strings in aux string table. */
+ size_t ctfc_aux_strlen;
+
+} ctf_container_t;
+
+/* Markers for which string table from the CTF container to use. */
+
+#define CTF_STRTAB 0 /* CTF string table. */
+#define CTF_AUX_STRTAB 1 /* CTF auxilliary string table. */
+
+typedef ctf_container_t * ctf_container_ref;
+
+extern GTY (()) ctf_container_ref tu_ctfc;
+
+extern void ctfc_delete_container (ctf_container_ref);
+
+/* If the next ctf type id is still set to the init value, no ctf records to
+ report. */
+extern bool ctfc_is_empty_container (ctf_container_ref);
+
+/* Get the total number of CTF types in the container. */
+
+extern unsigned int ctfc_get_num_ctf_types (ctf_container_ref);
+
+/* Get the total number of CTF variables in the container. */
+
+extern unsigned int ctfc_get_num_ctf_vars (ctf_container_ref);
+
+/* Get reference to the CTF string table or the CTF auxilliary
+ string table. */
+
+extern ctf_strtable_t * ctfc_get_strtab (ctf_container_ref, int);
+
+/* Get the length of the specified string table in the CTF container. */
+
+extern size_t ctfc_get_strtab_len (ctf_container_ref, int);
+
+/* Get the number of bytes to represent the variable length portion of all CTF
+ types in the CTF container. */
+
+extern size_t ctfc_get_num_vlen_bytes (ctf_container_ref);
+
+/* The compiler demarcates whether types are visible at top-level scope or not.
+ The only example so far of a type not visible at top-level scope is slices.
+ CTF_ADD_NONROOT is used to indicate the latter. */
+#define CTF_ADD_NONROOT 0 /* CTF type only visible in nested scope. */
+#define CTF_ADD_ROOT 1 /* CTF type visible at top-level scope. */
+
+/* These APIs allow to initialize and finalize the CTF machinery and
+ to add types to the CTF container associated to the current
+ translation unit. Used in dwarf2ctf.cc. */
+
+extern void ctf_init (void);
+extern void ctf_output (const char * filename);
+extern void ctf_finalize (void);
+
+extern void btf_output (const char * filename);
+extern void btf_init_postprocess (void);
+extern void btf_finalize (void);
+
+extern ctf_container_ref ctf_get_tu_ctfc (void);
+
+extern bool ctf_type_exists (ctf_container_ref, dw_die_ref, ctf_id_t *);
+
+extern void ctf_add_cuname (ctf_container_ref, const char *);
+
+extern ctf_dtdef_ref ctf_dtd_lookup (const ctf_container_ref ctfc,
+ dw_die_ref die);
+extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref ctfc,
+ dw_die_ref die);
+extern bool ctf_dvd_ignore_lookup (const ctf_container_ref ctfc,
+ dw_die_ref die);
+
+extern const char * ctf_add_string (ctf_container_ref, const char *,
+ uint32_t *, int);
+
+extern ctf_id_t ctf_add_reftype (ctf_container_ref, uint32_t, ctf_id_t,
+ uint32_t, dw_die_ref);
+extern ctf_id_t ctf_add_enum (ctf_container_ref, uint32_t, const char *,
+ HOST_WIDE_INT, dw_die_ref);
+extern ctf_id_t ctf_add_slice (ctf_container_ref, uint32_t, ctf_id_t,
+ uint32_t, uint32_t, dw_die_ref);
+extern ctf_id_t ctf_add_float (ctf_container_ref, uint32_t, const char *,
+ const ctf_encoding_t *, dw_die_ref);
+extern ctf_id_t ctf_add_integer (ctf_container_ref, uint32_t, const char *,
+ const ctf_encoding_t *, dw_die_ref);
+extern ctf_id_t ctf_add_unknown (ctf_container_ref, uint32_t, const char *,
+ const ctf_encoding_t *, dw_die_ref);
+extern ctf_id_t ctf_add_pointer (ctf_container_ref, uint32_t, ctf_id_t,
+ dw_die_ref);
+extern ctf_id_t ctf_add_array (ctf_container_ref, uint32_t,
+ const ctf_arinfo_t *, dw_die_ref);
+extern ctf_id_t ctf_add_forward (ctf_container_ref, uint32_t, const char *,
+ uint32_t, dw_die_ref);
+extern ctf_id_t ctf_add_typedef (ctf_container_ref, uint32_t, const char *,
+ ctf_id_t, dw_die_ref);
+extern ctf_id_t ctf_add_function (ctf_container_ref, uint32_t, const char *,
+ const ctf_funcinfo_t *, dw_die_ref, bool);
+extern ctf_id_t ctf_add_sou (ctf_container_ref, uint32_t, const char *,
+ uint32_t, size_t, dw_die_ref);
+
+extern int ctf_add_enumerator (ctf_container_ref, ctf_id_t, const char *,
+ HOST_WIDE_INT, dw_die_ref);
+extern int ctf_add_member_offset (ctf_container_ref, dw_die_ref, const char *,
+ ctf_id_t, uint64_t);
+extern int ctf_add_function_arg (ctf_container_ref, dw_die_ref,
+ const char *, ctf_id_t);
+extern int ctf_add_variable (ctf_container_ref, const char *, ctf_id_t,
+ dw_die_ref, unsigned int, dw_die_ref);
+
+extern ctf_id_t ctf_lookup_tree_type (ctf_container_ref, const tree);
+extern ctf_id_t get_btf_id (ctf_id_t);
+
+/* CTF section does not emit location information; at this time, location
+ information is needed for BTF CO-RE use-cases. */
+
+extern int ctfc_get_dtd_srcloc (ctf_dtdef_ref, ctf_srcloc_ref);
+extern int ctfc_get_dvd_srcloc (ctf_dvdef_ref, ctf_srcloc_ref);
+
+#endif /* GCC_CTFC_H */
diff --git a/support/cpp/gcc/data-streamer.h b/support/cpp/gcc/data-streamer.h
new file mode 100644
index 000000000..1d1578262
--- /dev/null
+++ b/support/cpp/gcc/data-streamer.h
@@ -0,0 +1,353 @@
+/* Generic streaming support for various data types.
+
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+ Contributed by Diego Novillo <dnovillo@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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_DATA_STREAMER_H
+#define GCC_DATA_STREAMER_H
+
+#include "lto-streamer.h"
+
+/* Data structures used to pack values and bitflags into a vector of
+ words. Used to stream values of a fixed number of bits in a space
+ efficient way. */
+static unsigned const BITS_PER_BITPACK_WORD = HOST_BITS_PER_WIDE_INT;
+
+typedef unsigned HOST_WIDE_INT bitpack_word_t;
+
+struct bitpack_d
+{
+ /* The position of the first unused or unconsumed bit in the word. */
+ unsigned pos;
+
+ /* The current word we are (un)packing. */
+ bitpack_word_t word;
+
+ /* The lto_output_stream or the lto_input_block we are streaming to/from. */
+ void *stream;
+};
+
+/* In data-streamer.cc */
+void bp_pack_var_len_unsigned (struct bitpack_d *, unsigned HOST_WIDE_INT);
+void bp_pack_var_len_int (struct bitpack_d *, HOST_WIDE_INT);
+unsigned HOST_WIDE_INT bp_unpack_var_len_unsigned (struct bitpack_d *);
+HOST_WIDE_INT bp_unpack_var_len_int (struct bitpack_d *);
+
+/* In data-streamer-out.cc */
+void streamer_write_zero (struct output_block *);
+void streamer_write_uhwi (struct output_block *, unsigned HOST_WIDE_INT);
+void streamer_write_hwi (struct output_block *, HOST_WIDE_INT);
+// sdcpp void streamer_write_poly_uint64 (struct output_block *, poly_uint64);
+// sdcpp void streamer_write_poly_int64 (struct output_block *, poly_int64);
+void streamer_write_gcov_count (struct output_block *, gcov_type);
+void streamer_write_string (struct output_block *, struct lto_output_stream *,
+ const char *, bool);
+void streamer_write_string_with_length (struct output_block *,
+ struct lto_output_stream *,
+ const char *, unsigned int, bool);
+void bp_pack_string_with_length (struct output_block *, struct bitpack_d *,
+ const char *, unsigned int, bool);
+void bp_pack_string (struct output_block *, struct bitpack_d *,
+ const char *, bool);
+void streamer_write_uhwi_stream (struct lto_output_stream *,
+ unsigned HOST_WIDE_INT);
+void streamer_write_hwi_stream (struct lto_output_stream *, HOST_WIDE_INT);
+void streamer_write_gcov_count_stream (struct lto_output_stream *, gcov_type);
+void streamer_write_data_stream (struct lto_output_stream *, const void *,
+ size_t);
+// sdcpp void streamer_write_wide_int (struct output_block *, const wide_int &);
+// sdcpp void streamer_write_widest_int (struct output_block *, const widest_int &);
+
+/* In data-streamer-in.cc */
+const char *streamer_read_string (class data_in *, class lto_input_block *);
+const char *streamer_read_indexed_string (class data_in *,
+ class lto_input_block *,
+ unsigned int *);
+const char *bp_unpack_indexed_string (class data_in *, struct bitpack_d *,
+ unsigned int *);
+const char *bp_unpack_string (class data_in *, struct bitpack_d *);
+unsigned HOST_WIDE_INT streamer_read_uhwi (class lto_input_block *);
+HOST_WIDE_INT streamer_read_hwi (class lto_input_block *);
+// sdcpp poly_uint64 streamer_read_poly_uint64 (class lto_input_block *);
+// sdcpp poly_int64 streamer_read_poly_int64 (class lto_input_block *);
+gcov_type streamer_read_gcov_count (class lto_input_block *);
+// sdcpp wide_int streamer_read_wide_int (class lto_input_block *);
+// sdcpp widest_int streamer_read_widest_int (class lto_input_block *);
+
+/* Returns a new bit-packing context for bit-packing into S. */
+static inline struct bitpack_d
+bitpack_create (struct lto_output_stream *s)
+{
+ struct bitpack_d bp;
+ bp.pos = 0;
+ bp.word = 0;
+ bp.stream = (void *)s;
+ return bp;
+}
+
+/* Pack the NBITS bit sized value VAL into the bit-packing context BP. */
+static inline void
+bp_pack_value (struct bitpack_d *bp, bitpack_word_t val, unsigned nbits)
+{
+ bitpack_word_t word = bp->word;
+ int pos = bp->pos;
+
+ /* Verify that VAL fits in the NBITS. */
+ gcc_checking_assert (nbits == BITS_PER_BITPACK_WORD
+ || !(val & ~(((bitpack_word_t)1<<nbits)-1)));
+
+ /* If val does not fit into the current bitpack word switch to the
+ next one. */
+ if (pos + nbits > BITS_PER_BITPACK_WORD)
+ {
+ streamer_write_uhwi_stream ((struct lto_output_stream *) bp->stream,
+ word);
+ word = val;
+ pos = nbits;
+ }
+ else
+ {
+ word |= val << pos;
+ pos += nbits;
+ }
+ bp->word = word;
+ bp->pos = pos;
+}
+
+#if 0 // sdcpp
+/* Pack VAL into the bit-packing context BP, using NBITS for each
+ coefficient. */
+static inline void
+bp_pack_poly_value (struct bitpack_d *bp,
+ const poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t> &val,
+ unsigned nbits)
+{
+ for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ bp_pack_value (bp, val.coeffs[i], nbits);
+}
+#endif // sdcpp
+
+/* Finishes bit-packing of BP. */
+static inline void
+streamer_write_bitpack (struct bitpack_d *bp)
+{
+ streamer_write_uhwi_stream ((struct lto_output_stream *) bp->stream,
+ bp->word);
+ bp->word = 0;
+ bp->pos = 0;
+}
+
+/* Returns a new bit-packing context for bit-unpacking from IB. */
+static inline struct bitpack_d
+streamer_read_bitpack (class lto_input_block *ib)
+{
+ struct bitpack_d bp;
+ bp.word = streamer_read_uhwi (ib);
+ bp.pos = 0;
+ bp.stream = (void *)ib;
+ return bp;
+}
+
+/* Unpacks NBITS bits from the bit-packing context BP and returns them. */
+static inline bitpack_word_t
+bp_unpack_value (struct bitpack_d *bp, unsigned nbits)
+{
+ bitpack_word_t mask, val;
+ int pos = bp->pos;
+
+ mask = (nbits == BITS_PER_BITPACK_WORD
+ ? (bitpack_word_t) -1
+ : ((bitpack_word_t) 1 << nbits) - 1);
+
+ /* If there are not continuous nbits in the current bitpack word
+ switch to the next one. */
+ if (pos + nbits > BITS_PER_BITPACK_WORD)
+ {
+ bp->word = val
+ = streamer_read_uhwi ((class lto_input_block *)bp->stream);
+ bp->pos = nbits;
+ return val & mask;
+ }
+ val = bp->word;
+ val >>= pos;
+ bp->pos = pos + nbits;
+
+ return val & mask;
+}
+
+#if 0 // sdcpp
+/* Unpacks a polynomial value from the bit-packing context BP in which each
+ coefficient has NBITS bits. */
+static inline poly_int<NUM_POLY_INT_COEFFS, bitpack_word_t>
+bp_unpack_poly_value (struct bitpack_d *bp, unsigned nbits)
+{
+ poly_int_pod<NUM_POLY_INT_COEFFS, bitpack_word_t> x;
+ for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ x.coeffs[i] = bp_unpack_value (bp, nbits);
+ return x;
+}
+
+
+/* Write a character to the output block. */
+
+static inline void
+streamer_write_char_stream (struct lto_output_stream *obs, char c)
+{
+ /* No space left. */
+ if (obs->left_in_block == 0)
+ lto_append_block (obs);
+
+ /* Write the actual character. */
+ char *current_pointer = obs->current_pointer;
+ *(current_pointer++) = c;
+ obs->current_pointer = current_pointer;
+ obs->total_size++;
+ obs->left_in_block--;
+}
+
+
+/* Read byte from the input block. */
+
+static inline unsigned char
+streamer_read_uchar (class lto_input_block *ib)
+{
+ if (ib->p >= ib->len)
+ lto_section_overrun (ib);
+ return (ib->data[ib->p++]);
+}
+
+/* Output VAL into OBS and verify it is in range MIN...MAX that is supposed
+ to be compile time constant.
+ Be host independent, limit range to 31bits. */
+
+static inline void
+streamer_write_hwi_in_range (struct lto_output_stream *obs,
+ HOST_WIDE_INT min,
+ HOST_WIDE_INT max,
+ HOST_WIDE_INT val)
+{
+ HOST_WIDE_INT range = max - min;
+
+ gcc_checking_assert (val >= min && val <= max && range > 0
+ && range < 0x7fffffff);
+
+ val -= min;
+ streamer_write_uhwi_stream (obs, (unsigned HOST_WIDE_INT) val);
+}
+
+/* Input VAL into OBS and verify it is in range MIN...MAX that is supposed
+ to be compile time constant. PURPOSE is used for error reporting. */
+
+static inline HOST_WIDE_INT
+streamer_read_hwi_in_range (class lto_input_block *ib,
+ const char *purpose,
+ HOST_WIDE_INT min,
+ HOST_WIDE_INT max)
+{
+ HOST_WIDE_INT range = max - min;
+ unsigned HOST_WIDE_INT uval = streamer_read_uhwi (ib);
+
+ gcc_checking_assert (range > 0 && range < 0x7fffffff);
+
+ HOST_WIDE_INT val = (HOST_WIDE_INT) (uval + (unsigned HOST_WIDE_INT) min);
+ if (val < min || val > max)
+ lto_value_range_error (purpose, val, min, max);
+ return val;
+}
+
+/* Output VAL into BP and verify it is in range MIN...MAX that is supposed
+ to be compile time constant.
+ Be host independent, limit range to 31bits. */
+
+static inline void
+bp_pack_int_in_range (struct bitpack_d *bp,
+ HOST_WIDE_INT min,
+ HOST_WIDE_INT max,
+ HOST_WIDE_INT val)
+{
+ HOST_WIDE_INT range = max - min;
+ int nbits = floor_log2 (range) + 1;
+
+ gcc_checking_assert (val >= min && val <= max && range > 0
+ && range < 0x7fffffff);
+
+ val -= min;
+ bp_pack_value (bp, val, nbits);
+}
+
+/* Input VAL into BP and verify it is in range MIN...MAX that is supposed
+ to be compile time constant. PURPOSE is used for error reporting. */
+
+static inline HOST_WIDE_INT
+bp_unpack_int_in_range (struct bitpack_d *bp,
+ const char *purpose,
+ HOST_WIDE_INT min,
+ HOST_WIDE_INT max)
+{
+ HOST_WIDE_INT range = max - min;
+ int nbits = floor_log2 (range) + 1;
+ HOST_WIDE_INT val = bp_unpack_value (bp, nbits);
+
+ gcc_checking_assert (range > 0 && range < 0x7fffffff);
+
+ if (val < min || val > max)
+ lto_value_range_error (purpose, val, min, max);
+ return val;
+}
+
+/* Output VAL of type "enum enum_name" into OBS.
+ Assume range 0...ENUM_LAST - 1. */
+#define streamer_write_enum(obs,enum_name,enum_last,val) \
+ streamer_write_hwi_in_range ((obs), 0, (int)(enum_last) - 1, (int)(val))
+
+/* Input enum of type "enum enum_name" from IB.
+ Assume range 0...ENUM_LAST - 1. */
+#define streamer_read_enum(ib,enum_name,enum_last) \
+ (enum enum_name)streamer_read_hwi_in_range ((ib), #enum_name, 0, \
+ (int)(enum_last) - 1)
+
+/* Output VAL of type "enum enum_name" into BP.
+ Assume range 0...ENUM_LAST - 1. */
+#define bp_pack_enum(bp,enum_name,enum_last,val) \
+ bp_pack_int_in_range ((bp), 0, (int)(enum_last) - 1, (int)(val))
+
+/* Input enum of type "enum enum_name" from BP.
+ Assume range 0...ENUM_LAST - 1. */
+#define bp_unpack_enum(bp,enum_name,enum_last) \
+ (enum enum_name)bp_unpack_int_in_range ((bp), #enum_name, 0, \
+ (int)(enum_last) - 1)
+
+/* Output the start of a record with TAG to output block OB. */
+
+static inline void
+streamer_write_record_start (struct output_block *ob, enum LTO_tags tag)
+{
+ streamer_write_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS, tag);
+}
+
+/* Return the next tag in the input block IB. */
+
+static inline enum LTO_tags
+streamer_read_record_start (class lto_input_block *ib)
+{
+ return streamer_read_enum (ib, LTO_tags, LTO_NUM_TAGS);
+}
+#endif // sdcpp
+
+#endif /* GCC_DATA_STREAMER_H */
diff --git a/support/cpp/gcc/dbgcnt.def b/support/cpp/gcc/dbgcnt.def
new file mode 100644
index 000000000..3aa18cd0c
--- /dev/null
+++ b/support/cpp/gcc/dbgcnt.def
@@ -0,0 +1,216 @@
+/* This file contains the list of the debug counter for GCC.
+ Copyright (C) 2006-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/>. */
+
+
+/* A debug counter provides you a way to count an event
+ and return false after the counter has exceeded the threshold
+ specified by the option.
+
+ What is it used for ?
+
+ This is primarily used to speed up the search for the bad transformation
+ an optimization pass does. By doing a binary search on N,
+ you can quickly narrow down to one transformation
+ which is bad, or which triggers the bad behavior downstream
+ (usually in the form of the badly generated code).
+
+ How does it work ?
+
+ Every time dbg_cnt(named-counter) is called,
+ the counter is incremented for the named-counter.
+ And the incremented value is compared against the threshold (limit)
+ specified by the option.
+ dbg_cnt () returns true if it is at or below threshold, and false if above.
+
+ How to add a new one ?
+
+ To add a new counter, simply add an entry below with some descriptive name,
+ and add call(s) to dbg_cnt(your-counter-name) in appropriate places.
+ Usually, you want to control at the finest granularity
+ any particular transformation can happen.
+ e.g. for each instruction in a dead code elimination,
+ or for each copy instruction in register coalescing,
+ or constant-propagation for each insn,
+ or a block straightening, etc.
+ See dce.cc for an example. With the dbg_cnt () call in dce.cc,
+ now a developer can use -fdbg-cnt=dce:N
+ to stop doing the dead code elimination after N times.
+
+ How to use it ?
+
+ By default, all limits are UINT_MAX.
+ Since debug count is unsigned int, <= UINT_MAX returns true always.
+ i.e. dbg_cnt() returns true always regardless of the counter value
+ (although it still counts the event).
+ Use -fdbg-cnt=counter1:N,counter2:M,...
+ which sets the limit for counter1 to N, and the limit for counter2 to M, etc.
+ e.g. setting a limit to zero will make dbg_cnt () return false *always*.
+
+ The following shell file can then be used to binary search for
+ exact transformation that causes the bug. A second shell script
+ should be written, say "tryTest", which exits with 1 if the
+ compiled program fails and exits with 0 if the program succeeds.
+ This shell script should take 1 parameter, the value to be passed
+ to set the counter of the compilation command in tryTest. Then,
+ assuming that the following script is called binarySearch,
+ the command:
+
+ binarySearch tryTest
+
+ will automatically find the highest value of the counter for which
+ the program fails. If tryTest never fails, binarySearch will
+ produce unpredictable results as it will try to find an upper bound
+ that does not exist.
+
+ When dbgcnt does hits the limit, it writes a comment in the current
+ dump_file of the form:
+
+ ***dbgcnt: limit reached for %s.***
+
+ Assuming that the dump file is logging the analysis/transformations
+ it is making, this pinpoints the exact position in the log file
+ where the problem transformation is being logged.
+
+=====================================
+#!/bin/bash
+
+while getopts "l:u:i:" opt
+do
+ case $opt in
+ l) lb="$OPTARG";;
+ u) ub="$OPTARG";;
+ i) init="$OPTARG";;
+ ?) usage; exit 3;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+echo $@
+cmd=${1+"${@}"}
+
+lb=${lb:=0}
+init=${init:=100}
+
+$cmd $lb
+lb_val=$?
+if [ -z "$ub" ]; then
+ # find the upper bound
+ ub=$(($init + $lb))
+ true
+ while [ $? -eq $lb_val ]; do
+ ub=$(($ub * 10))
+ #ub=`expr $ub \* 10`
+ $cmd $ub
+ done
+fi
+
+echo command: $cmd
+
+true
+while [ `expr $ub - $lb` -gt 1 ]; do
+ try=$(($lb + ( $ub - $lb ) / 2))
+ $cmd $try
+ if [ $? -eq $lb_val ]; then
+ lb=$try
+ else
+ ub=$try
+ fi
+done
+
+echo lbound: $lb
+echo ubound: $ub
+
+=====================================
+
+*/
+
+/* Debug counter definitions.
+ Please keep the list sorted in alphabetic order. */
+DEBUG_COUNTER (asan_use_after_scope)
+DEBUG_COUNTER (auto_inc_dec)
+DEBUG_COUNTER (back_thread1)
+DEBUG_COUNTER (back_thread2)
+DEBUG_COUNTER (back_threadfull1)
+DEBUG_COUNTER (back_threadfull2)
+DEBUG_COUNTER (ccp)
+DEBUG_COUNTER (cfg_cleanup)
+DEBUG_COUNTER (cprop)
+DEBUG_COUNTER (cse2_move2add)
+DEBUG_COUNTER (dce)
+DEBUG_COUNTER (dce_fast)
+DEBUG_COUNTER (dce_ud)
+DEBUG_COUNTER (delete_trivial_dead)
+DEBUG_COUNTER (devirt)
+DEBUG_COUNTER (df_byte_scan)
+DEBUG_COUNTER (dom_unreachable_edges)
+DEBUG_COUNTER (dse)
+DEBUG_COUNTER (dse1)
+DEBUG_COUNTER (dse2)
+DEBUG_COUNTER (gcse2_delete)
+DEBUG_COUNTER (gimple_unroll)
+DEBUG_COUNTER (global_alloc_at_func)
+DEBUG_COUNTER (global_alloc_at_reg)
+DEBUG_COUNTER (graphite_scop)
+DEBUG_COUNTER (hoist)
+DEBUG_COUNTER (hoist_insn)
+DEBUG_COUNTER (ia64_sched2)
+DEBUG_COUNTER (if_after_combine)
+DEBUG_COUNTER (if_after_reload)
+DEBUG_COUNTER (if_conversion)
+DEBUG_COUNTER (if_conversion_tree)
+DEBUG_COUNTER (if_to_switch)
+DEBUG_COUNTER (ipa_attr)
+DEBUG_COUNTER (ipa_cp_bits)
+DEBUG_COUNTER (ipa_cp_values)
+DEBUG_COUNTER (ipa_cp_vr)
+DEBUG_COUNTER (ipa_mod_ref)
+DEBUG_COUNTER (ipa_mod_ref_pta)
+DEBUG_COUNTER (ipa_sra_params)
+DEBUG_COUNTER (ipa_sra_retvalues)
+DEBUG_COUNTER (ira_move)
+DEBUG_COUNTER (ivopts_loop)
+DEBUG_COUNTER (lim)
+DEBUG_COUNTER (local_alloc_for_sched)
+DEBUG_COUNTER (match)
+DEBUG_COUNTER (merged_ipa_icf)
+DEBUG_COUNTER (phiopt_edge_range)
+DEBUG_COUNTER (postreload_cse)
+DEBUG_COUNTER (pre)
+DEBUG_COUNTER (pre_insn)
+DEBUG_COUNTER (prefetch)
+DEBUG_COUNTER (registered_jump_thread)
+DEBUG_COUNTER (sched2_func)
+DEBUG_COUNTER (sched_block)
+DEBUG_COUNTER (sched_breakdep)
+DEBUG_COUNTER (sched_func)
+DEBUG_COUNTER (sched_insn)
+DEBUG_COUNTER (sched_region)
+DEBUG_COUNTER (sel_sched_cnt)
+DEBUG_COUNTER (sel_sched_insn_cnt)
+DEBUG_COUNTER (sel_sched_region_cnt)
+DEBUG_COUNTER (sms_sched_loop)
+DEBUG_COUNTER (split_for_sched2)
+DEBUG_COUNTER (store_merging)
+DEBUG_COUNTER (store_motion)
+DEBUG_COUNTER (stv_conversion)
+DEBUG_COUNTER (tail_call)
+DEBUG_COUNTER (tree_sra)
+DEBUG_COUNTER (treepre_insert)
+DEBUG_COUNTER (vect_loop)
+DEBUG_COUNTER (vect_slp)
diff --git a/support/cpp/gcc/dbgcnt.h b/support/cpp/gcc/dbgcnt.h
new file mode 100644
index 000000000..39873ff60
--- /dev/null
+++ b/support/cpp/gcc/dbgcnt.h
@@ -0,0 +1,40 @@
+/* Debug counter for debugging support
+ Copyright (C) 2006-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/>.
+
+See dbgcnt.def for usage information. */
+
+#ifndef GCC_DBGCNT_H
+#define GCC_DBGCNT_H
+
+#define DEBUG_COUNTER(a) a,
+
+enum debug_counter {
+#include "dbgcnt.def"
+ debug_counter_number_of_counters
+};
+
+#undef DEBUG_COUNTER
+
+extern bool dbg_cnt_is_enabled (enum debug_counter index);
+extern bool dbg_cnt (enum debug_counter index);
+extern unsigned dbg_cnt_counter (enum debug_counter index);
+extern void dbg_cnt_process_opt (const char *arg);
+extern void dbg_cnt_list_all_counters (void);
+
+#endif /* GCC_DBGCNT_H */
diff --git a/support/cpp/gcc/debug.cc b/support/cpp/gcc/debug.cc
new file mode 100644
index 000000000..270a2a459
--- /dev/null
+++ b/support/cpp/gcc/debug.cc
@@ -0,0 +1,166 @@
+/* Do-nothing debug hooks for GCC.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "debug.h"
+
+/* The do-nothing debug hooks. */
+const struct gcc_debug_hooks do_nothing_debug_hooks =
+{
+ debug_nothing_charstar,
+ debug_nothing_charstar,
+ debug_nothing_charstar, /* early_finish */
+ debug_nothing_void,
+ debug_nothing_int_charstar,
+ debug_nothing_int_charstar,
+ debug_nothing_int_charstar,
+ debug_nothing_int,
+ debug_nothing_int_int, /* begin_block */
+ debug_nothing_int_int, /* end_block */
+ debug_true_const_tree, /* ignore_block */
+ debug_nothing_int_int_charstar_int_bool, /* source_line */
+ debug_nothing_int_int_charstar, /* set_ignored_loc */
+ debug_nothing_int_int_charstar, /* begin_prologue */
+ debug_nothing_int_charstar, /* end_prologue */
+ debug_nothing_int_charstar, /* begin_epilogue */
+ debug_nothing_int_charstar, /* end_epilogue */
+ debug_nothing_tree, /* begin_function */
+ debug_nothing_int, /* end_function */
+ debug_nothing_tree, /* register_main_translation_unit */
+ debug_nothing_tree, /* function_decl */
+ debug_nothing_tree, /* early_global_decl */
+ debug_nothing_tree, /* late_global_decl */
+ debug_nothing_tree_int, /* 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 */
+ debug_nothing_int, /* 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 */
+};
+
+/* This file contains implementations of each debug hook that do
+ nothing. */
+
+void
+debug_nothing_void (void)
+{
+}
+
+void
+debug_nothing_tree (tree decl ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_tree_tree (tree t1 ATTRIBUTE_UNUSED,
+ tree t2 ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_tree_tree_tree_bool_bool (tree t1 ATTRIBUTE_UNUSED,
+ tree t2 ATTRIBUTE_UNUSED,
+ tree t3 ATTRIBUTE_UNUSED,
+ bool b1 ATTRIBUTE_UNUSED,
+ bool b2 ATTRIBUTE_UNUSED)
+{
+}
+
+bool
+debug_true_const_tree (const_tree block ATTRIBUTE_UNUSED)
+{
+ return true;
+}
+
+void
+debug_nothing_rtx_insn (rtx_insn *insn ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_rtx_code_label (rtx_code_label *label ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_charstar (const char *main_filename ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_int_charstar (unsigned int line ATTRIBUTE_UNUSED,
+ const char *text ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_int_int_charstar (unsigned int line ATTRIBUTE_UNUSED,
+ unsigned int column ATTRIBUTE_UNUSED,
+ const char *text ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_int_int_charstar_int_bool (unsigned int line ATTRIBUTE_UNUSED,
+ unsigned int column ATTRIBUTE_UNUSED,
+ const char *text ATTRIBUTE_UNUSED,
+ int discriminator ATTRIBUTE_UNUSED,
+ bool is_stmt ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_int (unsigned int line ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_int_int (unsigned int line ATTRIBUTE_UNUSED,
+ unsigned int n ATTRIBUTE_UNUSED)
+{
+}
+
+void
+debug_nothing_tree_int (tree decl ATTRIBUTE_UNUSED,
+ int local ATTRIBUTE_UNUSED)
+{
+}
+
+bool
+debug_false_tree_charstarstar_uhwistar (tree, const char **,
+ unsigned HOST_WIDE_INT *)
+{
+ return false;
+}
+
+void
+debug_nothing_tree_charstar_uhwi (tree, const char *,
+ unsigned HOST_WIDE_INT)
+{
+}
diff --git a/support/cpp/gcc/debug.h b/support/cpp/gcc/debug.h
new file mode 100644
index 000000000..61e96b02e
--- /dev/null
+++ b/support/cpp/gcc/debug.h
@@ -0,0 +1,284 @@
+/* Debug hooks for GCC.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_DEBUG_H
+#define GCC_DEBUG_H
+
+#include "hash-map.h" // sdcpp
+
+/* This structure contains hooks for the debug information output
+ functions, accessed through the global instance debug_hooks set in
+ toplev.cc according to command line options. */
+/* WARNING: Do not add new debug hook targets - DWARF will be the only
+ way to speak debug to the middle-end once we are able to get rid of
+ the remaining targets. If you need alternate output formats instead
+ generate them off the DWARF representation. */
+struct gcc_debug_hooks
+{
+ /* Initialize debug output. MAIN_FILENAME is the name of the main
+ input file. */
+ void (* init) (const char *main_filename);
+
+ /* Output debug symbols. */
+ void (* finish) (const char *main_filename);
+
+ /* Run cleanups necessary after early debug generation. */
+ void (* early_finish) (const char *main_filename);
+
+ /* Called from cgraph_optimize before starting to assemble
+ functions/variables/toplevel asms. */
+ void (* assembly_start) (void);
+
+ /* Macro defined on line LINE with name and expansion TEXT. */
+ void (* define) (unsigned int line, const char *text);
+
+ /* MACRO undefined on line LINE. */
+ void (* undef) (unsigned int line, const char *macro);
+
+ /* Record the beginning of a new source file FILE from LINE number
+ in the previous one. */
+ void (* start_source_file) (unsigned int line, const char *file);
+
+ /* Record the resumption of a source file. LINE is the line number
+ in the source file we are returning to. */
+ void (* end_source_file) (unsigned int line);
+
+ /* Record the beginning of block N, counting from 1 and not
+ including the function-scope block, at LINE. */
+ void (* begin_block) (unsigned int line, unsigned int n);
+
+ /* Record the end of a block. Arguments as for begin_block. */
+ void (* end_block) (unsigned int line, unsigned int n);
+
+ /* Returns nonzero if it is appropriate not to emit any debugging
+ information for BLOCK, because it doesn't contain any
+ instructions. This may not be the case for blocks containing
+ nested functions, since we may actually call such a function even
+ though the BLOCK information is messed up. Defaults to true. */
+ bool (* ignore_block) (const_tree);
+
+ /* Record a source file location at (FILE, LINE, COLUMN, DISCRIMINATOR). */
+ void (* source_line) (unsigned int line, unsigned int column,
+ const char *file, int discriminator, bool is_stmt);
+
+ /* Record a source file location for a DECL_IGNORED_P function. */
+ void (* set_ignored_loc) (unsigned int line, unsigned int column,
+ const char *file);
+
+ /* Called at start of prologue code. LINE is the first line in the
+ function. */
+ void (* begin_prologue) (unsigned int line, unsigned int column,
+ const char *file);
+
+ /* Called at end of prologue code. LINE is the first line in the
+ function. */
+ void (* end_prologue) (unsigned int line, const char *file);
+
+ /* Called at beginning of epilogue code. */
+ void (* begin_epilogue) (unsigned int line, const char *file);
+
+ /* Record end of epilogue code. */
+ void (* end_epilogue) (unsigned int line, const char *file);
+
+ /* Called at start of function DECL, before it is declared. */
+ void (* begin_function) (tree decl);
+
+ /* Record end of function. LINE is highest line number in function. */
+ void (* end_function) (unsigned int line);
+
+ /* Register UNIT as the main translation unit. Called from front-ends when
+ they create their main translation unit. */
+ void (* register_main_translation_unit) (tree);
+
+ /* Debug information for a function DECL. This might include the
+ function name (a symbol), its parameters, and the block that
+ makes up the function's body, and the local variables of the
+ function.
+
+ This is only called for FUNCTION_DECLs. It is part of the late
+ debug pass and is called from rest_of_handle_final.
+
+ Location information is available at this point.
+
+ See the documentation for early_global_decl and late_global_decl
+ for other entry points into the debugging back-ends for DECLs. */
+ void (* function_decl) (tree decl);
+
+ /* Debug information for a global DECL. Called from the parser
+ after the parsing process has finished.
+
+ This gets called for both variables and functions.
+
+ Location information is not available at this point, but it is a
+ good probe point to get access to symbols before they get
+ optimized away.
+
+ This hook may be called on VAR_DECLs or FUNCTION_DECLs. It is up
+ to the hook to use what it needs. */
+ void (* early_global_decl) (tree decl);
+
+ /* Augment debug information generated by early_global_decl with
+ more complete debug info (if applicable). Called from toplev.cc
+ after the compilation proper has finished and cgraph information
+ is available.
+
+ This gets called for both variables and functions.
+
+ Location information is usually available at this point, unless
+ the hook is being called for a decl that has been optimized away.
+
+ This hook may be called on VAR_DECLs or FUNCTION_DECLs. It is up
+ to the hook to use what it needs. */
+ void (* late_global_decl) (tree decl);
+
+ /* Debug information for a type DECL. Called from toplev.cc after
+ compilation proper, also from various language front ends to
+ record built-in types. The second argument is properly a
+ boolean, which indicates whether or not the type is a "local"
+ type as determined by the language. (It's not a boolean for
+ legacy reasons.) */
+ void (* type_decl) (tree decl, int local);
+
+ /* Debug information for imported modules and declarations. */
+ void (* imported_module_or_decl) (tree decl, tree name,
+ tree context, bool child,
+ bool implicit);
+
+ /* Return true if a DIE for the tree is available and return a symbol
+ and offset that can be used to refer to it externally. */
+ bool (* die_ref_for_decl) (tree, const char **, unsigned HOST_WIDE_INT *);
+
+ /* Early debug information for the tree is available at symbol plus
+ offset externally. */
+ void (* register_external_die) (tree, const char *, unsigned HOST_WIDE_INT);
+
+ /* DECL is an inline function, whose body is present, but which is
+ not being output at this point. */
+ void (* deferred_inline_function) (tree decl);
+
+ /* DECL is an inline function which is about to be emitted out of
+ line. The hook is useful to, e.g., emit abstract debug info for
+ the inline before it gets mangled by optimization. */
+ void (* outlining_inline_function) (tree decl);
+
+ /* Called from final_scan_insn for any CODE_LABEL insn whose
+ LABEL_NAME is non-null. */
+ void (* label) (rtx_code_label *);
+
+ /* Called after the start and before the end of writing a PCH file.
+ The parameter is 0 if after the start, 1 if before the end. */
+ void (* handle_pch) (unsigned int);
+
+ /* Called from final_scan_insn for any NOTE_INSN_VAR_LOCATION note. */
+ void (* var_location) (rtx_insn *);
+
+ /* Called from final_scan_insn for any NOTE_INSN_INLINE_ENTRY note. */
+ void (* inline_entry) (tree block);
+
+ /* Called from finalize_size_functions for size functions so that their body
+ can be encoded in the debug info to describe the layout of variable-length
+ structures. */
+ void (* size_function) (tree decl);
+
+ /* Called from final_scan_insn if there is a switch between hot and cold
+ text sections. */
+ void (* switch_text_section) (void);
+
+ /* Called from grokdeclarator. Replaces the anonymous name with the
+ type name. */
+ void (* set_name) (tree, tree);
+
+ /* This is 1 if the debug writer wants to see start and end commands for the
+ main source files, and 0 otherwise. */
+ int start_end_main_source_file;
+
+ /* The type of symtab field used by these debug hooks. This is one
+ of the TYPE_SYMTAB_IS_xxx values defined in tree.h. */
+ int tree_type_symtab_field;
+};
+
+extern const struct gcc_debug_hooks *debug_hooks;
+
+/* The do-nothing hooks. */
+extern void debug_nothing_void (void);
+extern void debug_nothing_charstar (const char *);
+extern void debug_nothing_int_int_charstar (unsigned int, unsigned int,
+ const char *);
+extern void debug_nothing_int_charstar (unsigned int, const char *);
+extern void debug_nothing_int_int_charstar_int_bool (unsigned int,
+ unsigned int,
+ const char *,
+ int, bool);
+extern void debug_nothing_int (unsigned int);
+extern void debug_nothing_int_int (unsigned int, unsigned int);
+extern void debug_nothing_tree (tree);
+extern void debug_nothing_tree_tree (tree, tree);
+extern void debug_nothing_tree_int (tree, int);
+extern void debug_nothing_tree_tree_tree_bool_bool (tree, tree, tree,
+ bool, bool);
+extern bool debug_true_const_tree (const_tree);
+extern void debug_nothing_rtx_insn (rtx_insn *);
+extern void debug_nothing_rtx_code_label (rtx_code_label *);
+extern bool debug_false_tree_charstarstar_uhwistar (tree, const char **,
+ unsigned HOST_WIDE_INT *);
+extern void debug_nothing_tree_charstar_uhwi (tree, const char *,
+ unsigned HOST_WIDE_INT);
+
+/* 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;
+extern const struct gcc_debug_hooks vmsdbg_debug_hooks;
+
+/* Dwarf2 frame information. */
+
+extern void dwarf2out_begin_prologue (unsigned int, unsigned int,
+ const char *);
+extern void dwarf2out_vms_end_prologue (unsigned int, const char *);
+extern void dwarf2out_vms_begin_epilogue (unsigned int, const char *);
+extern void dwarf2out_end_epilogue (unsigned int, const char *);
+extern void dwarf2out_frame_finish (void);
+extern bool dwarf2out_do_eh_frame (void);
+extern bool dwarf2out_do_frame (void);
+extern bool dwarf2out_do_cfi_asm (void);
+extern void dwarf2out_switch_text_section (void);
+extern bool dwarf2out_default_as_loc_support (void);
+extern bool dwarf2out_default_as_locview_support (void);
+
+/* For -fdump-go-spec. */
+
+extern const struct gcc_debug_hooks *
+dump_go_spec_init (const char *, const struct gcc_debug_hooks *);
+
+/* Instance discriminator mapping table. See final.cc. */
+typedef hash_map<const_tree, int> decl_to_instance_map_t;
+extern decl_to_instance_map_t *decl_to_instance_map;
+
+/* Allocate decl_to_instance_map with COUNT slots to begin wtih, if it
+ * hasn't been allocated yet. */
+
+static inline decl_to_instance_map_t *
+maybe_create_decl_to_instance_map (int count = 13)
+{
+ if (!decl_to_instance_map)
+ decl_to_instance_map = new decl_to_instance_map_t (count);
+ return decl_to_instance_map;
+}
+
+#endif /* !GCC_DEBUG_H */
diff --git a/support/cpp/gcc/defaults.h b/support/cpp/gcc/defaults.h
new file mode 100644
index 000000000..59134cfe2
--- /dev/null
+++ b/support/cpp/gcc/defaults.h
@@ -0,0 +1,1459 @@
+/* Definitions of various defaults for tm.h macros.
+ Copyright (C) 1992-2022 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.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/>. */
+
+#ifndef GCC_DEFAULTS_H
+#define GCC_DEFAULTS_H
+
+/* How to start an assembler comment. */
+#ifndef ASM_COMMENT_START
+#define ASM_COMMENT_START ";#"
+#endif
+
+/* Store in OUTPUT a string (made with alloca) containing an
+ assembler-name for a local static variable or function named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#ifndef ASM_PN_FORMAT
+# ifndef NO_DOT_IN_LABEL
+# define ASM_PN_FORMAT "%s.%lu"
+# else
+# ifndef NO_DOLLAR_IN_LABEL
+# define ASM_PN_FORMAT "%s$%lu"
+# else
+# define ASM_PN_FORMAT "__%s_%lu"
+# endif
+# endif
+#endif /* ! ASM_PN_FORMAT */
+
+#ifndef ASM_FORMAT_PRIVATE_NAME
+# define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+ do { const char *const name_ = (NAME); \
+ char *const output_ = (OUTPUT) = \
+ (char *) alloca (strlen (name_) + 32); \
+ sprintf (output_, ASM_PN_FORMAT, name_, (unsigned long)(LABELNO)); \
+ } while (0)
+#endif
+
+/* Choose a reasonable default for ASM_OUTPUT_ASCII. */
+
+#ifndef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \
+ do { \
+ FILE *_my_file = (MYFILE); \
+ const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \
+ int _hide_thissize = (MYLENGTH); \
+ { \
+ const unsigned char *p = _hide_p; \
+ int thissize = _hide_thissize; \
+ int i; \
+ fprintf (_my_file, "\t.ascii \""); \
+ \
+ for (i = 0; i < thissize; i++) \
+ { \
+ int c = p[i]; \
+ if (c == '\"' || c == '\\') \
+ putc ('\\', _my_file); \
+ if (ISPRINT (c)) \
+ putc (c, _my_file); \
+ else \
+ { \
+ fprintf (_my_file, "\\%o", c); \
+ /* After an octal-escape, if a digit follows, \
+ terminate one string constant and start another. \
+ The VAX assembler fails to stop reading the escape \
+ after three digits, so this is the only way we \
+ can get it to parse the data properly. */ \
+ if (i < thissize - 1 && ISDIGIT (p[i + 1])) \
+ fprintf (_my_file, "\"\n\t.ascii \""); \
+ } \
+ } \
+ fprintf (_my_file, "\"\n"); \
+ } \
+ } \
+ while (0)
+#endif
+
+/* This is how we tell the assembler to equate two values. */
+#ifdef SET_ASM_OP
+#ifndef ASM_OUTPUT_DEF
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+ do { fprintf ((FILE), "%s", SET_ASM_OP); \
+ assemble_name (FILE, LABEL1); \
+ fprintf (FILE, ","); \
+ assemble_name (FILE, LABEL2); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+#endif
+#endif
+
+#ifndef IFUNC_ASM_TYPE
+#define IFUNC_ASM_TYPE "gnu_indirect_function"
+#endif
+
+#ifndef TLS_COMMON_ASM_OP
+#define TLS_COMMON_ASM_OP ".tls_common"
+#endif
+
+#if defined (HAVE_AS_TLS) && !defined (ASM_OUTPUT_TLS_COMMON)
+#define ASM_OUTPUT_TLS_COMMON(FILE, DECL, NAME, SIZE) \
+ do \
+ { \
+ fprintf ((FILE), "\t%s\t", TLS_COMMON_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", \
+ (SIZE), DECL_ALIGN (DECL) / BITS_PER_UNIT); \
+ } \
+ while (0)
+#endif
+
+/* Decide whether to defer emitting the assembler output for an equate
+ of two values. The default is to not defer output. */
+#ifndef TARGET_DEFERRED_OUTPUT_DEFS
+#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) false
+#endif
+
+/* This is how to output the definition of a user-level label named
+ NAME, such as the label on variable NAME. */
+
+#ifndef ASM_OUTPUT_LABEL
+#define ASM_OUTPUT_LABEL(FILE,NAME) \
+ do { \
+ assemble_name ((FILE), (NAME)); \
+ fputs (":\n", (FILE)); \
+ } while (0)
+#endif
+
+/* This is how to output the definition of a user-level label named
+ NAME, such as the label on a function. */
+
+#ifndef ASM_OUTPUT_FUNCTION_LABEL
+#define ASM_OUTPUT_FUNCTION_LABEL(FILE, NAME, DECL) \
+ ASM_OUTPUT_LABEL ((FILE), (NAME))
+#endif
+
+/* Output the definition of a compiler-generated label named NAME. */
+#ifndef ASM_OUTPUT_INTERNAL_LABEL
+#define ASM_OUTPUT_INTERNAL_LABEL(FILE,NAME) \
+ do { \
+ assemble_name_raw ((FILE), (NAME)); \
+ fputs (":\n", (FILE)); \
+ } while (0)
+#endif
+
+/* This is how to output a reference to a user-level label named NAME. */
+
+#ifndef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { \
+ fputs (user_label_prefix, (FILE)); \
+ fputs ((NAME), (FILE)); \
+ } while (0)
+#endif
+
+/* Allow target to print debug info labels specially. This is useful for
+ VLIW targets, since debug info labels should go into the middle of
+ instruction bundles instead of breaking them. */
+
+#ifndef ASM_OUTPUT_DEBUG_LABEL
+#define ASM_OUTPUT_DEBUG_LABEL(FILE, PREFIX, NUM) \
+ (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM)
+#endif
+
+/* This is how we tell the assembler that a symbol is weak. */
+#ifndef ASM_OUTPUT_WEAK_ALIAS
+#if defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_DEF)
+#define ASM_OUTPUT_WEAK_ALIAS(STREAM, NAME, VALUE) \
+ do \
+ { \
+ ASM_WEAKEN_LABEL (STREAM, NAME); \
+ if (VALUE) \
+ ASM_OUTPUT_DEF (STREAM, NAME, VALUE); \
+ } \
+ while (0)
+#endif
+#endif
+
+/* This is how we tell the assembler that a symbol is a weak alias to
+ another symbol that doesn't require the other symbol to be defined.
+ Uses of the former will turn into weak uses of the latter, i.e.,
+ uses that, in case the latter is undefined, will not cause errors,
+ and will add it to the symbol table as weak undefined. However, if
+ the latter is referenced directly, a strong reference prevails. */
+#ifndef ASM_OUTPUT_WEAKREF
+#if defined HAVE_GAS_WEAKREF
+#define ASM_OUTPUT_WEAKREF(FILE, DECL, NAME, VALUE) \
+ do \
+ { \
+ fprintf ((FILE), "\t.weakref\t"); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ","); \
+ assemble_name ((FILE), (VALUE)); \
+ fprintf ((FILE), "\n"); \
+ } \
+ while (0)
+#endif
+#endif
+
+/* How to emit a .type directive. */
+#ifndef ASM_OUTPUT_TYPE_DIRECTIVE
+#if defined TYPE_ASM_OP && defined TYPE_OPERAND_FMT
+#define ASM_OUTPUT_TYPE_DIRECTIVE(STREAM, NAME, TYPE) \
+ do \
+ { \
+ fputs (TYPE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", ", STREAM); \
+ fprintf (STREAM, TYPE_OPERAND_FMT, TYPE); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+#endif
+#endif
+
+/* How to emit a .size directive. */
+#ifndef ASM_OUTPUT_SIZE_DIRECTIVE
+#ifdef SIZE_ASM_OP
+#define ASM_OUTPUT_SIZE_DIRECTIVE(STREAM, NAME, SIZE) \
+ do \
+ { \
+ HOST_WIDE_INT size_ = (SIZE); \
+ fputs (SIZE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, ", " HOST_WIDE_INT_PRINT_DEC "\n", size_); \
+ } \
+ while (0)
+
+#define ASM_OUTPUT_MEASURED_SIZE(STREAM, NAME) \
+ do \
+ { \
+ fputs (SIZE_ASM_OP, STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (", .-", STREAM); \
+ assemble_name (STREAM, NAME); \
+ putc ('\n', STREAM); \
+ } \
+ while (0)
+
+#endif
+#endif
+
+/* This determines whether or not we support weak symbols. SUPPORTS_WEAK
+ must be a preprocessor constant. */
+#ifndef SUPPORTS_WEAK
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
+#define SUPPORTS_WEAK 1
+#else
+#define SUPPORTS_WEAK 0
+#endif
+#endif
+
+/* This determines whether or not we support weak symbols during target
+ code generation. TARGET_SUPPORTS_WEAK can be any valid C expression. */
+#ifndef TARGET_SUPPORTS_WEAK
+#define TARGET_SUPPORTS_WEAK (SUPPORTS_WEAK)
+#endif
+
+/* This determines whether or not we support the discriminator
+ attribute in the .loc directive. */
+#ifndef SUPPORTS_DISCRIMINATOR
+#ifdef HAVE_GAS_DISCRIMINATOR
+#define SUPPORTS_DISCRIMINATOR 1
+#else
+#define SUPPORTS_DISCRIMINATOR 0
+#endif
+#endif
+
+/* This determines whether or not we support marking sections with
+ SHF_GNU_RETAIN flag. Also require .init_array/.fini_array section
+ for constructors and destructors. */
+#ifndef SUPPORTS_SHF_GNU_RETAIN
+#if HAVE_GAS_SHF_GNU_RETAIN && HAVE_INITFINI_ARRAY_SUPPORT
+#define SUPPORTS_SHF_GNU_RETAIN 1
+#else
+#define SUPPORTS_SHF_GNU_RETAIN 0
+#endif
+#endif
+
+/* This determines whether or not we support link-once semantics. */
+#ifndef SUPPORTS_ONE_ONLY
+#ifdef MAKE_DECL_ONE_ONLY
+#define SUPPORTS_ONE_ONLY 1
+#else
+#define SUPPORTS_ONE_ONLY 0
+#endif
+#endif
+
+/* This determines whether weak symbols must be left out of a static
+ archive's table of contents. Defining this macro to be nonzero has
+ the consequence that certain symbols will not be made weak that
+ otherwise would be. The C++ ABI requires this macro to be zero;
+ see the documentation. */
+#ifndef TARGET_WEAK_NOT_IN_ARCHIVE_TOC
+#define TARGET_WEAK_NOT_IN_ARCHIVE_TOC 0
+#endif
+
+/* This determines whether or not we need linkonce unwind information. */
+#ifndef TARGET_USES_WEAK_UNWIND_INFO
+#define TARGET_USES_WEAK_UNWIND_INFO 0
+#endif
+
+/* By default, there is no prefix on user-defined symbols. */
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+
+/* If the target supports weak symbols, define TARGET_ATTRIBUTE_WEAK to
+ provide a weak attribute. Else define it to nothing.
+
+ This would normally belong in ansidecl.h, but SUPPORTS_WEAK is
+ not available at that time.
+
+ Note, this is only for use by target files which we know are to be
+ compiled by GCC. */
+#ifndef TARGET_ATTRIBUTE_WEAK
+# if SUPPORTS_WEAK
+# define TARGET_ATTRIBUTE_WEAK __attribute__ ((weak))
+# else
+# define TARGET_ATTRIBUTE_WEAK
+# endif
+#endif
+
+/* By default we can assume that all global symbols are in one namespace,
+ across all shared libraries. */
+#ifndef MULTIPLE_SYMBOL_SPACES
+# define MULTIPLE_SYMBOL_SPACES 0
+#endif
+
+/* If the target supports init_priority C++ attribute, give
+ SUPPORTS_INIT_PRIORITY a nonzero value. */
+#ifndef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY 1
+#endif /* SUPPORTS_INIT_PRIORITY */
+
+/* If we have a definition of INCOMING_RETURN_ADDR_RTX, assume that
+ the rest of the DWARF 2 frame unwind support is also provided. */
+#if !defined (DWARF2_UNWIND_INFO) && defined (INCOMING_RETURN_ADDR_RTX)
+#define DWARF2_UNWIND_INFO 1
+#endif
+
+/* If we have named sections, and we're using crtstuff to run ctors,
+ use them for registering eh frame information. */
+#if defined (TARGET_ASM_NAMED_SECTION) && DWARF2_UNWIND_INFO \
+ && !defined (EH_FRAME_THROUGH_COLLECT2)
+#ifndef EH_FRAME_SECTION_NAME
+#define EH_FRAME_SECTION_NAME ".eh_frame"
+#endif
+#endif
+
+/* On many systems, different EH table encodings are used under
+ difference circumstances. Some will require runtime relocations;
+ some will not. For those that do not require runtime relocations,
+ we would like to make the table read-only. However, since the
+ read-only tables may need to be combined with read-write tables
+ that do require runtime relocation, it is not safe to make the
+ tables read-only unless the linker will merge read-only and
+ read-write sections into a single read-write section. If your
+ linker does not have this ability, but your system is such that no
+ encoding used with non-PIC code will ever require a runtime
+ relocation, then you can define EH_TABLES_CAN_BE_READ_ONLY to 1 in
+ your target configuration file. */
+#ifndef EH_TABLES_CAN_BE_READ_ONLY
+#ifdef HAVE_LD_RO_RW_SECTION_MIXING
+#define EH_TABLES_CAN_BE_READ_ONLY 1
+#else
+#define EH_TABLES_CAN_BE_READ_ONLY 0
+#endif
+#endif
+
+/* Provide defaults for stuff that may not be defined when using
+ sjlj exceptions. */
+#ifndef EH_RETURN_DATA_REGNO
+#define EH_RETURN_DATA_REGNO(N) INVALID_REGNUM
+#endif
+
+/* Offset between the eh handler address and entry in eh tables. */
+#ifndef RETURN_ADDR_OFFSET
+#define RETURN_ADDR_OFFSET 0
+#endif
+
+#ifndef MASK_RETURN_ADDR
+#define MASK_RETURN_ADDR NULL_RTX
+#endif
+
+/* Number of hardware registers that go into the DWARF-2 unwind info.
+ If not defined, equals FIRST_PSEUDO_REGISTER */
+
+#ifndef DWARF_FRAME_REGISTERS
+#define DWARF_FRAME_REGISTERS FIRST_PSEUDO_REGISTER
+#endif
+
+/* Offsets recorded in opcodes are a multiple of this alignment factor. */
+#ifndef DWARF_CIE_DATA_ALIGNMENT
+#ifdef STACK_GROWS_DOWNWARD
+#define DWARF_CIE_DATA_ALIGNMENT (-((int) UNITS_PER_WORD))
+#else
+#define DWARF_CIE_DATA_ALIGNMENT ((int) UNITS_PER_WORD)
+#endif
+#endif
+
+/* The DWARF 2 CFA column which tracks the return address. Normally this
+ is the column for PC, or the first column after all of the hard
+ registers. */
+#ifndef DWARF_FRAME_RETURN_COLUMN
+#ifdef PC_REGNUM
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM)
+#else
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS
+#endif
+#endif
+
+/* How to renumber registers for dbx and gdb. If not defined, assume
+ no renumbering is necessary. */
+
+#ifndef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(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)
+#endif
+
+/* The mapping from dwarf CFA reg number to internal dwarf reg numbers. */
+#ifndef DWARF_REG_TO_UNWIND_COLUMN
+#define DWARF_REG_TO_UNWIND_COLUMN(REGNO) (REGNO)
+#endif
+
+/* Map register numbers held in the call frame info that gcc has
+ collected using DWARF_FRAME_REGNUM to those that should be output in
+ .debug_frame and .eh_frame. */
+#ifndef DWARF2_FRAME_REG_OUT
+#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO)
+#endif
+
+/* The size of addresses as they appear in the Dwarf 2 data.
+ Some architectures use word addresses to refer to code locations,
+ but Dwarf 2 info always uses byte addresses. On such machines,
+ Dwarf 2 addresses need to be larger than the architecture's
+ pointers. */
+#ifndef DWARF2_ADDR_SIZE
+#define DWARF2_ADDR_SIZE ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
+#endif
+
+/* The size in bytes of a DWARF field indicating an offset or length
+ relative to a debug info section, specified to be 4 bytes in the
+ DWARF-2 specification. The SGI/MIPS ABI defines it to be the same
+ as PTR_SIZE. */
+#ifndef DWARF_OFFSET_SIZE
+#define DWARF_OFFSET_SIZE 4
+#endif
+
+/* The size in bytes of a DWARF 4 type signature. */
+#ifndef DWARF_TYPE_SIGNATURE_SIZE
+#define DWARF_TYPE_SIGNATURE_SIZE 8
+#endif
+
+/* Default sizes for base C types. If the sizes are different for
+ your target, you should override these values by defining the
+ appropriate symbols in your tm.h file. */
+
+#ifndef BITS_PER_WORD
+#define BITS_PER_WORD (BITS_PER_UNIT * UNITS_PER_WORD)
+#endif
+
+#ifndef CHAR_TYPE_SIZE
+#define CHAR_TYPE_SIZE BITS_PER_UNIT
+#endif
+
+#ifndef BOOL_TYPE_SIZE
+/* `bool' has size and alignment `1', on almost all platforms. */
+#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE
+#endif
+
+#ifndef SHORT_TYPE_SIZE
+#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
+#endif
+
+#ifndef INT_TYPE_SIZE
+#define INT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef LONG_LONG_TYPE_SIZE
+#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
+#endif
+
+#ifndef FLOAT_TYPE_SIZE
+#define FLOAT_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef DOUBLE_TYPE_SIZE
+#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
+#endif
+
+#ifndef DECIMAL32_TYPE_SIZE
+#define DECIMAL32_TYPE_SIZE 32
+#endif
+
+#ifndef DECIMAL64_TYPE_SIZE
+#define DECIMAL64_TYPE_SIZE 64
+#endif
+
+#ifndef DECIMAL128_TYPE_SIZE
+#define DECIMAL128_TYPE_SIZE 128
+#endif
+
+#ifndef SHORT_FRACT_TYPE_SIZE
+#define SHORT_FRACT_TYPE_SIZE BITS_PER_UNIT
+#endif
+
+#ifndef FRACT_TYPE_SIZE
+#define FRACT_TYPE_SIZE (BITS_PER_UNIT * 2)
+#endif
+
+#ifndef LONG_FRACT_TYPE_SIZE
+#define LONG_FRACT_TYPE_SIZE (BITS_PER_UNIT * 4)
+#endif
+
+#ifndef LONG_LONG_FRACT_TYPE_SIZE
+#define LONG_LONG_FRACT_TYPE_SIZE (BITS_PER_UNIT * 8)
+#endif
+
+#ifndef SHORT_ACCUM_TYPE_SIZE
+#define SHORT_ACCUM_TYPE_SIZE (SHORT_FRACT_TYPE_SIZE * 2)
+#endif
+
+#ifndef ACCUM_TYPE_SIZE
+#define ACCUM_TYPE_SIZE (FRACT_TYPE_SIZE * 2)
+#endif
+
+#ifndef LONG_ACCUM_TYPE_SIZE
+#define LONG_ACCUM_TYPE_SIZE (LONG_FRACT_TYPE_SIZE * 2)
+#endif
+
+#ifndef LONG_LONG_ACCUM_TYPE_SIZE
+#define LONG_LONG_ACCUM_TYPE_SIZE (LONG_LONG_FRACT_TYPE_SIZE * 2)
+#endif
+
+/* We let tm.h override the types used here, to handle trivial differences
+ such as the choice of unsigned int or long unsigned int for size_t.
+ When machines start needing nontrivial differences in the size type,
+ it would be best to do something here to figure out automatically
+ from other information what type to use. */
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
+
+#ifndef SIZETYPE
+#define SIZETYPE SIZE_TYPE
+#endif
+
+#ifndef PID_TYPE
+#define PID_TYPE "int"
+#endif
+
+/* If GCC knows the exact uint_least16_t and uint_least32_t types from
+ <stdint.h>, use them for char16_t and char32_t. Otherwise, use
+ these guesses; getting the wrong type of a given width will not
+ affect C++ name mangling because in C++ these are distinct types
+ not typedefs. */
+
+#ifndef CHAR8_TYPE
+#define CHAR8_TYPE "unsigned char"
+#endif
+
+#ifdef UINT_LEAST16_TYPE
+#define CHAR16_TYPE UINT_LEAST16_TYPE
+#else
+#define CHAR16_TYPE "short unsigned int"
+#endif
+
+#ifdef UINT_LEAST32_TYPE
+#define CHAR32_TYPE UINT_LEAST32_TYPE
+#else
+#define CHAR32_TYPE "unsigned int"
+#endif
+
+#ifndef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#endif
+
+/* WCHAR_TYPE gets overridden by -fshort-wchar. */
+#define MODIFIED_WCHAR_TYPE \
+ (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
+
+#ifndef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+#endif
+
+#ifndef WINT_TYPE
+#define WINT_TYPE "unsigned int"
+#endif
+
+#ifndef INTMAX_TYPE
+#define INTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "int" \
+ : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "long int" \
+ : "long long int"))
+#endif
+
+#ifndef UINTMAX_TYPE
+#define UINTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "unsigned int" \
+ : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "long unsigned int" \
+ : "long long unsigned int"))
+#endif
+
+
+/* There are no default definitions of these <stdint.h> types. */
+
+#ifndef SIG_ATOMIC_TYPE
+#define SIG_ATOMIC_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT8_TYPE
+#define INT8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT16_TYPE
+#define INT16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT32_TYPE
+#define INT32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT64_TYPE
+#define INT64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT8_TYPE
+#define UINT8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT16_TYPE
+#define UINT16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT32_TYPE
+#define UINT32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT64_TYPE
+#define UINT64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST8_TYPE
+#define INT_LEAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST16_TYPE
+#define INT_LEAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST32_TYPE
+#define INT_LEAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST64_TYPE
+#define INT_LEAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST8_TYPE
+#define UINT_LEAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST16_TYPE
+#define UINT_LEAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST32_TYPE
+#define UINT_LEAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST64_TYPE
+#define UINT_LEAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST8_TYPE
+#define INT_FAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST16_TYPE
+#define INT_FAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST32_TYPE
+#define INT_FAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST64_TYPE
+#define INT_FAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST8_TYPE
+#define UINT_FAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST16_TYPE
+#define UINT_FAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST32_TYPE
+#define UINT_FAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST64_TYPE
+#define UINT_FAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INTPTR_TYPE
+#define INTPTR_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINTPTR_TYPE
+#define UINTPTR_TYPE ((const char *) NULL)
+#endif
+
+/* Width in bits of a pointer. Mind the value of the macro `Pmode'. */
+#ifndef POINTER_SIZE
+#define POINTER_SIZE BITS_PER_WORD
+#endif
+#ifndef POINTER_SIZE_UNITS
+#define POINTER_SIZE_UNITS ((POINTER_SIZE + BITS_PER_UNIT - 1) / BITS_PER_UNIT)
+#endif
+
+
+#ifndef PIC_OFFSET_TABLE_REGNUM
+#define PIC_OFFSET_TABLE_REGNUM INVALID_REGNUM
+#endif
+
+#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 0
+#endif
+
+#ifndef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 0
+#endif
+
+#ifndef TARGET_DECLSPEC
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
+/* If the target supports the "dllimport" attribute, users are
+ probably used to the "__declspec" syntax. */
+#define TARGET_DECLSPEC 1
+#else
+#define TARGET_DECLSPEC 0
+#endif
+#endif
+
+/* By default, the preprocessor should be invoked the same way in C++
+ as in C. */
+#ifndef CPLUSPLUS_CPP_SPEC
+#ifdef CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC CPP_SPEC
+#endif
+#endif
+
+#ifndef ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 0
+#endif
+
+/* By default, use the GNU runtime for Objective C. */
+#ifndef NEXT_OBJC_RUNTIME
+#define NEXT_OBJC_RUNTIME 0
+#endif
+
+/* Decide whether a function's arguments should be processed
+ from first to last or from last to first.
+
+ They should if the stack and args grow in opposite directions, but
+ only if we have push insns. */
+
+#ifdef PUSH_ROUNDING
+
+#ifndef PUSH_ARGS_REVERSED
+#if defined (STACK_GROWS_DOWNWARD) != defined (ARGS_GROW_DOWNWARD)
+#define PUSH_ARGS_REVERSED targetm.calls.push_argument (0)
+#endif
+#endif
+
+#endif
+
+#ifndef PUSH_ARGS_REVERSED
+#define PUSH_ARGS_REVERSED 0
+#endif
+
+/* Default value for the alignment (in bits) a C conformant malloc has to
+ provide. This default is intended to be safe and always correct. */
+#ifndef MALLOC_ABI_ALIGNMENT
+#define MALLOC_ABI_ALIGNMENT BITS_PER_WORD
+#endif
+
+/* If PREFERRED_STACK_BOUNDARY is not defined, set it to STACK_BOUNDARY.
+ STACK_BOUNDARY is required. */
+#ifndef PREFERRED_STACK_BOUNDARY
+#define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
+#endif
+
+/* Set INCOMING_STACK_BOUNDARY to PREFERRED_STACK_BOUNDARY if it is not
+ defined. */
+#ifndef INCOMING_STACK_BOUNDARY
+#define INCOMING_STACK_BOUNDARY PREFERRED_STACK_BOUNDARY
+#endif
+
+#ifndef TARGET_DEFAULT_PACK_STRUCT
+#define TARGET_DEFAULT_PACK_STRUCT 0
+#endif
+
+/* By default, the vtable entries are void pointers, the so the alignment
+ is the same as pointer alignment. The value of this macro specifies
+ the alignment of the vtable entry in bits. It should be defined only
+ when special alignment is necessary. */
+#ifndef TARGET_VTABLE_ENTRY_ALIGN
+#define TARGET_VTABLE_ENTRY_ALIGN POINTER_SIZE
+#endif
+
+/* There are a few non-descriptor entries in the vtable at offsets below
+ zero. If these entries must be padded (say, to preserve the alignment
+ specified by TARGET_VTABLE_ENTRY_ALIGN), set this to the number of
+ words in each data entry. */
+#ifndef TARGET_VTABLE_DATA_ENTRY_DISTANCE
+#define TARGET_VTABLE_DATA_ENTRY_DISTANCE 1
+#endif
+
+/* Decide whether it is safe to use a local alias for a virtual function
+ when constructing thunks. */
+#ifndef TARGET_USE_LOCAL_THUNK_ALIAS_P
+#ifdef ASM_OUTPUT_DEF
+#define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) 1
+#else
+#define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) 0
+#endif
+#endif
+
+/* Decide whether target supports aliases. */
+#ifndef TARGET_SUPPORTS_ALIASES
+#ifdef ASM_OUTPUT_DEF
+#define TARGET_SUPPORTS_ALIASES 1
+#else
+#define TARGET_SUPPORTS_ALIASES 0
+#endif
+#endif
+
+/* Select a format to encode pointers in exception handling data. We
+ prefer those that result in fewer dynamic relocations. Assume no
+ special support here and encode direct references. */
+#ifndef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) DW_EH_PE_absptr
+#endif
+
+/* 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, if FUNCTION_BOUNDARY indicates
+ function addresses aren't always even, the lowest bit of the delta
+ field will be used. */
+#ifndef TARGET_PTRMEMFUNC_VBIT_LOCATION
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION \
+ (FUNCTION_BOUNDARY >= 2 * BITS_PER_UNIT \
+ ? ptrmemfunc_vbit_in_pfn : ptrmemfunc_vbit_in_delta)
+#endif
+
+#ifndef DEFAULT_GDB_EXTENSIONS
+#define DEFAULT_GDB_EXTENSIONS 1
+#endif
+
+/* Default to DWARF2_DEBUGGING_INFO. Legacy targets can choose different
+ by defining PREFERRED_DEBUGGING_TYPE. */
+#ifndef PREFERRED_DEBUGGING_TYPE
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#else
+#error You must define PREFERRED_DEBUGGING_TYPE if DWARF is not supported
+#endif
+#endif
+
+#ifndef FLOAT_LIB_COMPARE_RETURNS_BOOL
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) false
+#endif
+
+/* True if the targets integer-comparison functions return { 0, 1, 2
+ } to indicate { <, ==, > }. False if { -1, 0, 1 } is used
+ instead. The libgcc routines are biased. */
+#ifndef TARGET_LIB_INT_CMP_BIASED
+#define TARGET_LIB_INT_CMP_BIASED (true)
+#endif
+
+/* If FLOAT_WORDS_BIG_ENDIAN is not defined in the header files,
+ then the word-endianness is the same as for integers. */
+#ifndef FLOAT_WORDS_BIG_ENDIAN
+#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+#ifndef REG_WORDS_BIG_ENDIAN
+#define REG_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+
+#ifndef TARGET_DEC_EVAL_METHOD
+#define TARGET_DEC_EVAL_METHOD 2
+#endif
+
+#ifndef HAS_LONG_COND_BRANCH
+#define HAS_LONG_COND_BRANCH 0
+#endif
+
+#ifndef HAS_LONG_UNCOND_BRANCH
+#define HAS_LONG_UNCOND_BRANCH 0
+#endif
+
+/* Determine whether __cxa_atexit, rather than atexit, is used to
+ register C++ destructors for local statics and global objects. */
+#ifndef DEFAULT_USE_CXA_ATEXIT
+#define DEFAULT_USE_CXA_ATEXIT 0
+#endif
+
+#if GCC_VERSION >= 3000 && defined IN_GCC
+/* These old constraint macros shouldn't appear anywhere in a
+ configuration using MD constraint definitions. */
+#endif
+
+/* Determin whether the target runtime library is Bionic */
+#ifndef TARGET_HAS_BIONIC
+#define TARGET_HAS_BIONIC 0
+#endif
+
+/* Indicate that CLZ and CTZ are undefined at zero. */
+#ifndef CLZ_DEFINED_VALUE_AT_ZERO
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) 0
+#endif
+#ifndef CTZ_DEFINED_VALUE_AT_ZERO
+#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) 0
+#endif
+
+/* Provide a default value for STORE_FLAG_VALUE. */
+#ifndef STORE_FLAG_VALUE
+#define STORE_FLAG_VALUE 1
+#endif
+
+/* This macro is used to determine what the largest unit size that
+ move_by_pieces can use is. */
+
+/* MOVE_MAX_PIECES is the number of bytes at a time which we can
+ move efficiently, as opposed to MOVE_MAX which is the maximum
+ number of bytes we can move with a single instruction. */
+
+#ifndef MOVE_MAX_PIECES
+#define MOVE_MAX_PIECES MOVE_MAX
+#endif
+
+/* STORE_MAX_PIECES is the number of bytes at a time that we can
+ store efficiently. Due to internal GCC limitations, this is
+ MOVE_MAX_PIECES limited by the number of bytes GCC can represent
+ for an immediate constant. */
+
+#ifndef STORE_MAX_PIECES
+#define STORE_MAX_PIECES MIN (MOVE_MAX_PIECES, 2 * sizeof (HOST_WIDE_INT))
+#endif
+
+/* Likewise for block comparisons. */
+#ifndef COMPARE_MAX_PIECES
+#define COMPARE_MAX_PIECES MOVE_MAX_PIECES
+#endif
+
+#ifndef MAX_MOVE_MAX
+#define MAX_MOVE_MAX MOVE_MAX
+#endif
+
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+#ifndef MAX_BITS_PER_WORD
+#define MAX_BITS_PER_WORD BITS_PER_WORD
+#endif
+
+#ifndef STACK_POINTER_OFFSET
+#define STACK_POINTER_OFFSET 0
+#endif
+
+#ifndef LOCAL_REGNO
+#define LOCAL_REGNO(REGNO) 0
+#endif
+
+#ifndef HONOR_REG_ALLOC_ORDER
+#define HONOR_REG_ALLOC_ORDER 0
+#endif
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers. */
+#ifndef EXIT_IGNORE_STACK
+#define EXIT_IGNORE_STACK 0
+#endif
+
+/* Assume that case vectors are not pc-relative. */
+#ifndef CASE_VECTOR_PC_RELATIVE
+#define CASE_VECTOR_PC_RELATIVE 0
+#endif
+
+/* Force minimum alignment to be able to use the least significant bits
+ for distinguishing descriptor addresses from code addresses. */
+#define FUNCTION_ALIGNMENT(ALIGN) \
+ (lang_hooks.custom_function_descriptors \
+ && targetm.calls.custom_function_descriptors > 0 \
+ ? MAX ((ALIGN), \
+ 2 * targetm.calls.custom_function_descriptors * BITS_PER_UNIT)\
+ : (ALIGN))
+
+/* Assume that trampolines need function alignment. */
+#ifndef TRAMPOLINE_ALIGNMENT
+#define TRAMPOLINE_ALIGNMENT FUNCTION_ALIGNMENT (FUNCTION_BOUNDARY)
+#endif
+
+/* Register mappings for target machines without register windows. */
+#ifndef INCOMING_REGNO
+#define INCOMING_REGNO(N) (N)
+#endif
+
+#ifndef OUTGOING_REGNO
+#define OUTGOING_REGNO(N) (N)
+#endif
+
+#ifndef SHIFT_COUNT_TRUNCATED
+#define SHIFT_COUNT_TRUNCATED 0
+#endif
+
+#ifndef LEGITIMATE_PIC_OPERAND_P
+#define LEGITIMATE_PIC_OPERAND_P(X) 1
+#endif
+
+#ifndef TARGET_MEM_CONSTRAINT
+#define TARGET_MEM_CONSTRAINT 'm'
+#endif
+
+#ifndef REVERSIBLE_CC_MODE
+#define REVERSIBLE_CC_MODE(MODE) 0
+#endif
+
+/* Biggest alignment supported by the object file format of this machine. */
+#ifndef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
+#endif
+
+#ifndef FRAME_GROWS_DOWNWARD
+#define FRAME_GROWS_DOWNWARD 0
+#endif
+
+#ifndef RETURN_ADDR_IN_PREVIOUS_FRAME
+#define RETURN_ADDR_IN_PREVIOUS_FRAME 0
+#endif
+
+/* On most machines, the CFA coincides with the first incoming parm. */
+#ifndef ARG_POINTER_CFA_OFFSET
+#define ARG_POINTER_CFA_OFFSET(FNDECL) \
+ (FIRST_PARM_OFFSET (FNDECL) + crtl->args.pretend_args_size)
+#endif
+
+/* On most machines, we use the CFA as DW_AT_frame_base. */
+#ifndef CFA_FRAME_BASE_OFFSET
+#define CFA_FRAME_BASE_OFFSET(FNDECL) 0
+#endif
+
+/* The offset from the incoming value of %sp to the top of the stack frame
+ for the current function. */
+#ifndef INCOMING_FRAME_SP_OFFSET
+#define INCOMING_FRAME_SP_OFFSET 0
+#endif
+
+#ifndef HARD_REGNO_NREGS_HAS_PADDING
+#define HARD_REGNO_NREGS_HAS_PADDING(REGNO, MODE) 0
+#define HARD_REGNO_NREGS_WITH_PADDING(REGNO, MODE) -1
+#endif
+
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 0
+#endif
+
+/* MAX_STACK_ALIGNMENT is the maximum stack alignment guaranteed by
+ the backend. MAX_SUPPORTED_STACK_ALIGNMENT is the maximum best
+ effort stack alignment supported by the backend. If the backend
+ supports stack alignment, MAX_SUPPORTED_STACK_ALIGNMENT and
+ MAX_STACK_ALIGNMENT are the same. Otherwise, the incoming stack
+ boundary will limit the maximum guaranteed stack alignment. */
+#ifdef MAX_STACK_ALIGNMENT
+#define MAX_SUPPORTED_STACK_ALIGNMENT MAX_STACK_ALIGNMENT
+#else
+#define MAX_STACK_ALIGNMENT STACK_BOUNDARY
+#define MAX_SUPPORTED_STACK_ALIGNMENT PREFERRED_STACK_BOUNDARY
+#endif
+
+#define SUPPORTS_STACK_ALIGNMENT (MAX_STACK_ALIGNMENT > STACK_BOUNDARY)
+
+#ifndef LOCAL_ALIGNMENT
+#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
+#endif
+
+#ifndef STACK_SLOT_ALIGNMENT
+#define STACK_SLOT_ALIGNMENT(TYPE,MODE,ALIGN) \
+ ((TYPE) ? LOCAL_ALIGNMENT ((TYPE), (ALIGN)) : (ALIGN))
+#endif
+
+#ifndef LOCAL_DECL_ALIGNMENT
+#define LOCAL_DECL_ALIGNMENT(DECL) \
+ LOCAL_ALIGNMENT (TREE_TYPE (DECL), DECL_ALIGN (DECL))
+#endif
+
+#ifndef MINIMUM_ALIGNMENT
+#define MINIMUM_ALIGNMENT(EXP,MODE,ALIGN) (ALIGN)
+#endif
+
+/* Alignment value for attribute ((aligned)). */
+#ifndef ATTRIBUTE_ALIGNED_VALUE
+#define ATTRIBUTE_ALIGNED_VALUE BIGGEST_ALIGNMENT
+#endif
+
+/* For most ports anything that evaluates to a constant symbolic
+ or integer value is acceptable as a constant address. */
+#ifndef CONSTANT_ADDRESS_P
+#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X) && GET_CODE (X) != CONST_DOUBLE)
+#endif
+
+#ifndef MAX_FIXED_MODE_SIZE
+#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)
+#endif
+
+/* Nonzero if structures and unions should be returned in memory.
+
+ This should only be defined if compatibility with another compiler or
+ with an ABI is needed, because it results in slower code. */
+
+#ifndef DEFAULT_PCC_STRUCT_RETURN
+#define DEFAULT_PCC_STRUCT_RETURN 1
+#endif
+
+#ifndef PCC_BITFIELD_TYPE_MATTERS
+#define PCC_BITFIELD_TYPE_MATTERS false
+#endif
+
+#ifndef INSN_SETS_ARE_DELAYED
+#define INSN_SETS_ARE_DELAYED(INSN) false
+#endif
+
+#ifndef INSN_REFERENCES_ARE_DELAYED
+#define INSN_REFERENCES_ARE_DELAYED(INSN) false
+#endif
+
+#ifndef NO_FUNCTION_CSE
+#define NO_FUNCTION_CSE false
+#endif
+
+#ifndef HARD_REGNO_RENAME_OK
+#define HARD_REGNO_RENAME_OK(FROM, TO) true
+#endif
+
+#ifndef EPILOGUE_USES
+#define EPILOGUE_USES(REG) false
+#endif
+
+#ifndef ARGS_GROW_DOWNWARD
+#define ARGS_GROW_DOWNWARD 0
+#endif
+
+#ifndef STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 0
+#endif
+
+#ifndef STACK_PUSH_CODE
+#if STACK_GROWS_DOWNWARD
+#define STACK_PUSH_CODE PRE_DEC
+#else
+#define STACK_PUSH_CODE PRE_INC
+#endif
+#endif
+
+/* Default value for flag_pie when flag_pie is initialized to -1:
+ --enable-default-pie: Default flag_pie to -fPIE.
+ --disable-default-pie: Default flag_pie to 0.
+ */
+#ifdef ENABLE_DEFAULT_PIE
+# ifndef DEFAULT_FLAG_PIE
+# define DEFAULT_FLAG_PIE 2
+# endif
+#else
+# define DEFAULT_FLAG_PIE 0
+#endif
+
+#ifndef SWITCHABLE_TARGET
+#define SWITCHABLE_TARGET 0
+#endif
+
+/* If the target supports integers that are wider than two
+ HOST_WIDE_INTs on the host compiler, then the target should define
+ TARGET_SUPPORTS_WIDE_INT and make the appropriate fixups.
+ Otherwise the compiler really is not robust. */
+#ifndef TARGET_SUPPORTS_WIDE_INT
+#define TARGET_SUPPORTS_WIDE_INT 0
+#endif
+
+#ifndef SHORT_IMMEDIATES_SIGN_EXTEND
+#define SHORT_IMMEDIATES_SIGN_EXTEND 0
+#endif
+
+#ifndef WORD_REGISTER_OPERATIONS
+#define WORD_REGISTER_OPERATIONS 0
+#endif
+
+#ifndef LOAD_EXTEND_OP
+#define LOAD_EXTEND_OP(M) UNKNOWN
+#endif
+
+#ifndef INITIAL_FRAME_ADDRESS_RTX
+#define INITIAL_FRAME_ADDRESS_RTX NULL
+#endif
+
+#ifndef SETUP_FRAME_ADDRESSES
+#define SETUP_FRAME_ADDRESSES() do { } while (0)
+#endif
+
+#ifndef DYNAMIC_CHAIN_ADDRESS
+#define DYNAMIC_CHAIN_ADDRESS(x) (x)
+#endif
+
+#ifndef FRAME_ADDR_RTX
+#define FRAME_ADDR_RTX(x) (x)
+#endif
+
+#ifndef REVERSE_CONDITION
+#define REVERSE_CONDITION(code, mode) reverse_condition (code)
+#endif
+
+#ifndef TARGET_PECOFF
+#define TARGET_PECOFF 0
+#endif
+
+#ifndef TARGET_COFF
+#define TARGET_COFF 0
+#endif
+
+#ifndef EH_RETURN_HANDLER_RTX
+#define EH_RETURN_HANDLER_RTX NULL
+#endif
+
+#ifdef GCC_INSN_FLAGS_H
+/* Dependent default target macro definitions
+
+ This section of defaults.h defines target macros that depend on generated
+ headers. This is a bit awkward: We want to put all default definitions
+ for target macros in defaults.h, but some of the defaults depend on the
+ HAVE_* flags defines of insn-flags.h. But insn-flags.h is not always
+ included by files that do include defaults.h.
+
+ Fortunately, the default macro definitions that depend on the HAVE_*
+ macros are also the ones that will only be used inside GCC itself, i.e.
+ not in the gen* programs or in target objects like libgcc.
+
+ Obviously, it would be best to keep this section of defaults.h as small
+ as possible, by converting the macros defined below to target hooks or
+ functions.
+*/
+
+/* The default branch cost is 1. */
+#ifndef BRANCH_COST
+#define BRANCH_COST(speed_p, predictable_p) 1
+#endif
+
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction sequences, we will do a cpymem or libcall instead. */
+
+#ifndef MOVE_RATIO
+#if defined (HAVE_cpymemqi) || defined (HAVE_cpymemhi) || defined (HAVE_cpymemsi) || defined (HAVE_cpymemdi) || defined (HAVE_cpymemti)
+#define MOVE_RATIO(speed) 2
+#else
+/* If we are optimizing for space (-Os), cut down the default move ratio. */
+#define MOVE_RATIO(speed) ((speed) ? 15 : 3)
+#endif
+#endif
+
+/* If a clear memory operation would take CLEAR_RATIO or more simple
+ move-instruction sequences, we will do a setmem or libcall instead. */
+
+#ifndef CLEAR_RATIO
+#if defined (HAVE_setmemqi) || defined (HAVE_setmemhi) || defined (HAVE_setmemsi) || defined (HAVE_setmemdi) || defined (HAVE_setmemti)
+#define CLEAR_RATIO(speed) 2
+#else
+/* If we are optimizing for space, cut down the default clear ratio. */
+#define CLEAR_RATIO(speed) ((speed) ? 15 :3)
+#endif
+#endif
+
+/* If a memory set (to value other than zero) operation would take
+ SET_RATIO or more simple move-instruction sequences, we will do a setmem
+ or libcall instead. */
+#ifndef SET_RATIO
+#define SET_RATIO(speed) MOVE_RATIO (speed)
+#endif
+
+/* Supply a default definition of STACK_SAVEAREA_MODE for emit_stack_save.
+ Normally move_insn, so Pmode stack pointer. */
+
+#ifndef STACK_SAVEAREA_MODE
+#define STACK_SAVEAREA_MODE(LEVEL) Pmode
+#endif
+
+/* Supply a default definition of STACK_SIZE_MODE for
+ allocate_dynamic_stack_space. Normally PLUS/MINUS, so word_mode. */
+
+#ifndef STACK_SIZE_MODE
+#define STACK_SIZE_MODE word_mode
+#endif
+
+/* Default value for flag_stack_protect when flag_stack_protect is initialized to -1:
+ --enable-default-ssp: Default flag_stack_protect to -fstack-protector-strong.
+ --disable-default-ssp: Default flag_stack_protect to 0.
+ */
+#ifdef ENABLE_DEFAULT_SSP
+bla
+# ifndef DEFAULT_FLAG_SSP
+# define DEFAULT_FLAG_SSP 3
+# endif
+#else
+# define DEFAULT_FLAG_SSP 0
+#endif
+
+/* Provide default values for the macros controlling stack checking. */
+
+/* The default is neither full builtin stack checking... */
+#ifndef STACK_CHECK_BUILTIN
+#define STACK_CHECK_BUILTIN 0
+#endif
+
+/* ...nor static builtin stack checking. */
+#ifndef STACK_CHECK_STATIC_BUILTIN
+#define STACK_CHECK_STATIC_BUILTIN 0
+#endif
+
+/* The default interval is one page (4096 bytes). */
+#ifndef STACK_CHECK_PROBE_INTERVAL_EXP
+#define STACK_CHECK_PROBE_INTERVAL_EXP 12
+#endif
+
+/* The default is not to move the stack pointer. */
+#ifndef STACK_CHECK_MOVING_SP
+#define STACK_CHECK_MOVING_SP 0
+#endif
+
+/* This is a kludge to try to capture the discrepancy between the old
+ mechanism (generic stack checking) and the new mechanism (static
+ builtin stack checking). STACK_CHECK_PROTECT needs to be bumped
+ for the latter because part of the protection area is effectively
+ included in STACK_CHECK_MAX_FRAME_SIZE for the former. */
+#ifdef STACK_CHECK_PROTECT
+#define STACK_OLD_CHECK_PROTECT STACK_CHECK_PROTECT
+#else
+#define STACK_OLD_CHECK_PROTECT \
+ (!global_options.x_flag_exceptions \
+ ? 75 * UNITS_PER_WORD \
+ : targetm_common.except_unwind_info (&global_options) == UI_SJLJ \
+ ? 4 * 1024 \
+ : 8 * 1024)
+#endif
+
+/* Minimum amount of stack required to recover from an anticipated stack
+ overflow detection. The default value conveys an estimate of the amount
+ of stack required to propagate an exception. */
+#ifndef STACK_CHECK_PROTECT
+#define STACK_CHECK_PROTECT \
+ (!global_options.x_flag_exceptions \
+ ? 4 * 1024 \
+ : targetm_common.except_unwind_info (&global_options) == UI_SJLJ \
+ ? 8 * 1024 \
+ : 12 * 1024)
+#endif
+
+/* Make the maximum frame size be the largest we can and still only need
+ one probe per function. */
+#ifndef STACK_CHECK_MAX_FRAME_SIZE
+#define STACK_CHECK_MAX_FRAME_SIZE \
+ ((1 << STACK_CHECK_PROBE_INTERVAL_EXP) - UNITS_PER_WORD)
+#endif
+
+/* This is arbitrary, but should be large enough everywhere. */
+#ifndef STACK_CHECK_FIXED_FRAME_SIZE
+#define STACK_CHECK_FIXED_FRAME_SIZE (4 * UNITS_PER_WORD)
+#endif
+
+/* Provide a reasonable default for the maximum size of an object to
+ allocate in the fixed frame. We may need to be able to make this
+ controllable by the user at some point. */
+#ifndef STACK_CHECK_MAX_VAR_SIZE
+#define STACK_CHECK_MAX_VAR_SIZE (STACK_CHECK_MAX_FRAME_SIZE / 100)
+#endif
+
+/* By default, the C++ compiler will use function addresses in the
+ vtable entries. Setting this nonzero tells the compiler to use
+ function descriptors instead. The value of this macro says how
+ many words wide the descriptor is (normally 2). It is assumed
+ that the address of a function descriptor may be treated as a
+ pointer to a function. */
+#ifndef TARGET_VTABLE_USES_DESCRIPTORS
+#define TARGET_VTABLE_USES_DESCRIPTORS 0
+#endif
+
+#endif /* GCC_INSN_FLAGS_H */
+
+#ifndef DWARF_GNAT_ENCODINGS_DEFAULT
+#define DWARF_GNAT_ENCODINGS_DEFAULT DWARF_GNAT_ENCODINGS_GDB
+#endif
+
+#ifndef USED_FOR_TARGET
+/* Done this way to keep gengtype happy. */
+#if BITS_PER_UNIT == 8
+#define TARGET_UNIT uint8_t
+#elif BITS_PER_UNIT == 16
+#define TARGET_UNIT uint16_t
+#elif BITS_PER_UNIT == 32
+#define TARGET_UNIT uint32_t
+#else
+#error Unknown BITS_PER_UNIT
+#endif
+typedef TARGET_UNIT target_unit;
+#endif
+
+#endif /* ! GCC_DEFAULTS_H */
diff --git a/support/cpp/gcc/df.h b/support/cpp/gcc/df.h
new file mode 100644
index 000000000..bd329205d
--- /dev/null
+++ b/support/cpp/gcc/df.h
@@ -0,0 +1,1252 @@
+/* Form lists of pseudo register references for autoinc optimization
+ for GNU compiler. This is part of flow optimization.
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
+ Originally contributed by Michael P. Hayes
+ (m.hayes@elec.canterbury.ac.nz, mhayes@redhat.com)
+ Major rewrite contributed by Danny Berlin (dberlin@dberlin.org)
+ and Kenneth Zadeck (zadeck@naturalbridge.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.
+
+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_DF_H
+#define GCC_DF_H
+
+#include "regset.h"
+#include "alloc-pool.h"
+#include "timevar.h"
+
+struct dataflow;
+class df_d;
+struct df_problem;
+struct df_link;
+struct df_insn_info;
+union df_ref_d;
+
+/* Data flow problems. All problems must have a unique id here. */
+
+/* Scanning is not really a dataflow problem, but it is useful to have
+ the basic block functions in the vector so that things get done in
+ a uniform manner. The last four problems can be added or deleted
+ at any time are always defined (though LIVE is always there at -O2
+ or higher); the others are always there. */
+enum df_problem_id
+ {
+ DF_SCAN,
+ DF_LR, /* Live Registers backward. */
+ DF_LIVE, /* Live Registers & Uninitialized Registers */
+ DF_RD, /* Reaching Defs. */
+ DF_CHAIN, /* Def-Use and/or Use-Def Chains. */
+ DF_WORD_LR, /* Subreg tracking lr. */
+ DF_NOTE, /* REG_DEAD and REG_UNUSED notes. */
+ DF_MD, /* Multiple Definitions. */
+ DF_MIR, /* Must-initialized Registers. */
+
+ DF_LAST_PROBLEM_PLUS1
+ };
+
+/* Dataflow direction. */
+enum df_flow_dir
+ {
+ DF_NONE,
+ DF_FORWARD,
+ DF_BACKWARD
+ };
+
+/* Descriminator for the various df_ref types. */
+enum df_ref_class {DF_REF_BASE, DF_REF_ARTIFICIAL, DF_REF_REGULAR};
+
+/* The first of these us a set of a registers. The remaining three
+ are all uses of a register (the mem_load and mem_store relate to
+ how the register as an addressing operand). */
+enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE,
+ DF_REF_REG_MEM_LOAD, DF_REF_REG_MEM_STORE};
+
+enum df_ref_flags
+ {
+ /* This flag is set if this ref occurs inside of a conditional
+ execution instruction. */
+ DF_REF_CONDITIONAL = 1 << 0,
+
+ /* If this flag is set for an artificial use or def, that ref
+ logically happens at the top of the block. If it is not set
+ for an artificial use or def, that ref logically happens at the
+ bottom of the block. This is never set for regular refs. */
+ DF_REF_AT_TOP = 1 << 1,
+
+ /* This flag is set if the use is inside a REG_EQUAL or REG_EQUIV
+ note. */
+ DF_REF_IN_NOTE = 1 << 2,
+
+ /* This bit is true if this ref can make regs_ever_live true for
+ this regno. */
+ DF_HARD_REG_LIVE = 1 << 3,
+
+
+ /* This flag is set if this ref is a partial use or def of the
+ associated register. */
+ DF_REF_PARTIAL = 1 << 4,
+
+ /* Read-modify-write refs generate both a use and a def and
+ these are marked with this flag to show that they are not
+ independent. */
+ DF_REF_READ_WRITE = 1 << 5,
+
+ /* This flag is set if this ref, generally a def, may clobber the
+ referenced register. This is generally only set for hard
+ registers that cross a call site. With better information
+ about calls, some of these could be changed in the future to
+ DF_REF_MUST_CLOBBER. */
+ DF_REF_MAY_CLOBBER = 1 << 6,
+
+ /* This flag is set if this ref, generally a def, is a real
+ clobber. This is not currently set for registers live across a
+ call because that clobbering may or may not happen.
+
+ Most of the uses of this are with sets that have a
+ GET_CODE(..)==CLOBBER. Note that this is set even if the
+ clobber is to a subreg. So in order to tell if the clobber
+ wipes out the entire register, it is necessary to also check
+ the DF_REF_PARTIAL flag. */
+ DF_REF_MUST_CLOBBER = 1 << 7,
+
+
+ /* If the ref has one of the following two flags set, then the
+ struct df_ref can be cast to struct df_ref_extract to access
+ the width and offset fields. */
+
+ /* This flag is set if the ref contains a SIGN_EXTRACT. */
+ DF_REF_SIGN_EXTRACT = 1 << 8,
+
+ /* This flag is set if the ref contains a ZERO_EXTRACT. */
+ DF_REF_ZERO_EXTRACT = 1 << 9,
+
+ /* This flag is set if the ref contains a STRICT_LOW_PART. */
+ DF_REF_STRICT_LOW_PART = 1 << 10,
+
+ /* This flag is set if the ref contains a SUBREG. */
+ DF_REF_SUBREG = 1 << 11,
+
+
+ /* This bit is true if this ref is part of a multiword hardreg. */
+ DF_REF_MW_HARDREG = 1 << 12,
+
+ /* This flag is set if this ref is a usage of the stack pointer by
+ a function call. */
+ DF_REF_CALL_STACK_USAGE = 1 << 13,
+
+ /* This flag is used for verification of existing refs. */
+ DF_REF_REG_MARKER = 1 << 14,
+
+ /* This flag is set if this ref is inside a pre/post modify. */
+ DF_REF_PRE_POST_MODIFY = 1 << 15
+
+ };
+
+/* The possible ordering of refs within the df_ref_info. */
+enum df_ref_order
+ {
+ /* There is not table. */
+ DF_REF_ORDER_NO_TABLE,
+
+ /* There is a table of refs but it is not (or no longer) organized
+ by one of the following methods. */
+ DF_REF_ORDER_UNORDERED,
+ DF_REF_ORDER_UNORDERED_WITH_NOTES,
+
+ /* Organize the table by reg order, all of the refs with regno 0
+ followed by all of the refs with regno 1 ... . Within all of
+ the regs for a particular regno, the refs are unordered. */
+ DF_REF_ORDER_BY_REG,
+
+ /* For uses, the refs within eq notes may be added for
+ DF_REF_ORDER_BY_REG. */
+ DF_REF_ORDER_BY_REG_WITH_NOTES,
+
+ /* Organize the refs in insn order. The insns are ordered within a
+ block, and the blocks are ordered by FOR_ALL_BB_FN. */
+ DF_REF_ORDER_BY_INSN,
+
+ /* For uses, the refs within eq notes may be added for
+ DF_REF_ORDER_BY_INSN. */
+ DF_REF_ORDER_BY_INSN_WITH_NOTES
+ };
+
+/* Function prototypes added to df_problem instance. */
+
+/* Allocate the problem specific data. */
+typedef void (*df_alloc_function) (bitmap);
+
+/* This function is called if the problem has global data that needs
+ to be cleared when ever the set of blocks changes. The bitmap
+ contains the set of blocks that may require special attention.
+ This call is only made if some of the blocks are going to change.
+ If everything is to be deleted, the wholesale deletion mechanisms
+ apply. */
+typedef void (*df_reset_function) (bitmap);
+
+/* Free the basic block info. Called from the block reordering code
+ to get rid of the blocks that have been squished down. */
+typedef void (*df_free_bb_function) (basic_block, void *);
+
+/* Local compute function. */
+typedef void (*df_local_compute_function) (bitmap);
+
+/* Init the solution specific data. */
+typedef void (*df_init_function) (bitmap);
+
+/* Iterative dataflow function. */
+typedef void (*df_dataflow_function) (struct dataflow *, bitmap, int *, int);
+
+/* Confluence operator for blocks with 0 out (or in) edges. */
+typedef void (*df_confluence_function_0) (basic_block);
+
+/* Confluence operator for blocks with 1 or more out (or in) edges.
+ Return true if BB input data has changed. */
+typedef bool (*df_confluence_function_n) (edge);
+
+/* Transfer function for blocks.
+ Return true if BB output data has changed. */
+typedef bool (*df_transfer_function) (int);
+
+/* Function to massage the information after the problem solving. */
+typedef void (*df_finalizer_function) (bitmap);
+
+/* Function to free all of the problem specific datastructures. */
+typedef void (*df_free_function) (void);
+
+/* Function to remove this problem from the stack of dataflow problems
+ without effecting the other problems in the stack except for those
+ that depend on this problem. */
+typedef void (*df_remove_problem_function) (void);
+
+/* Function to dump basic block independent results to FILE. */
+typedef void (*df_dump_problem_function) (FILE *);
+
+/* Function to dump top or bottom of basic block results to FILE. */
+typedef void (*df_dump_bb_problem_function) (basic_block, FILE *);
+
+/* Function to dump before or after an insn to FILE. */
+typedef void (*df_dump_insn_problem_function) (const rtx_insn *, FILE *);
+
+/* Function to dump top or bottom of basic block results to FILE. */
+typedef void (*df_verify_solution_start) (void);
+
+/* Function to dump top or bottom of basic block results to FILE. */
+typedef void (*df_verify_solution_end) (void);
+
+/* The static description of a dataflow problem to solve. See above
+ typedefs for doc for the function fields. */
+
+struct df_problem {
+ /* The unique id of the problem. This is used it index into
+ df->defined_problems to make accessing the problem data easy. */
+ enum df_problem_id id;
+ enum df_flow_dir dir; /* Dataflow direction. */
+ df_alloc_function alloc_fun;
+ df_reset_function reset_fun;
+ df_free_bb_function free_bb_fun;
+ df_local_compute_function local_compute_fun;
+ df_init_function init_fun;
+ df_dataflow_function dataflow_fun;
+ df_confluence_function_0 con_fun_0;
+ df_confluence_function_n con_fun_n;
+ df_transfer_function trans_fun;
+ df_finalizer_function finalize_fun;
+ df_free_function free_fun;
+ df_remove_problem_function remove_problem_fun;
+ df_dump_problem_function dump_start_fun;
+ df_dump_bb_problem_function dump_top_fun;
+ df_dump_bb_problem_function dump_bottom_fun;
+ df_dump_insn_problem_function dump_insn_top_fun;
+ df_dump_insn_problem_function dump_insn_bottom_fun;
+ df_verify_solution_start verify_start_fun;
+ df_verify_solution_end verify_end_fun;
+ const struct df_problem *dependent_problem;
+ unsigned int block_info_elt_size;
+
+ /* The timevar id associated with this pass. */
+ timevar_id_t tv_id;
+
+ /* True if the df_set_blocks should null out the basic block info if
+ this block drops out of df->blocks_to_analyze. */
+ bool free_blocks_on_set_blocks;
+};
+
+
+/* The specific instance of the problem to solve. */
+struct dataflow
+{
+ const struct df_problem *problem; /* The problem to be solved. */
+
+ /* Array indexed by bb->index, that contains basic block problem and
+ solution specific information. */
+ void *block_info;
+ unsigned int block_info_size;
+
+ /* The pool to allocate the block_info from. */
+ object_allocator<df_link> *block_pool;
+
+ /* The lr and live problems have their transfer functions recomputed
+ only if necessary. This is possible for them because, the
+ problems are kept active for the entire backend and their
+ transfer functions are indexed by the REGNO. These are not
+ defined for any other problem. */
+ bitmap out_of_date_transfer_functions;
+
+ /* Other problem specific data that is not on a per basic block
+ basis. The structure is generally defined privately for the
+ problem. The exception being the scanning problem where it is
+ fully public. */
+ void *problem_data;
+
+ /* Local flags for some of the problems. */
+ unsigned int local_flags;
+
+ /* True if this problem of this instance has been initialized. This
+ is used by the dumpers to keep garbage out of the dumps if, for
+ debugging a dump is produced before the first call to
+ df_analyze after a new problem is added. */
+ bool computed;
+
+ /* True if the something has changed which invalidates the dataflow
+ solutions. Note that this bit is always true for all problems except
+ lr and live. */
+ bool solutions_dirty;
+
+ /* If true, this pass is deleted by df_finish_pass. This is never
+ true for DF_SCAN and DF_LR. It is true for DF_LIVE if optimize >
+ 1. It is always true for the other problems. */
+ bool optional_p;
+};
+
+
+/* The set of multiword hardregs used as operands to this
+ instruction. These are factored into individual uses and defs but
+ the aggregate is still needed to service the REG_DEAD and
+ REG_UNUSED notes. */
+struct df_mw_hardreg
+{
+ df_mw_hardreg *next; /* Next entry for this instruction. */
+ rtx mw_reg; /* The multiword hardreg. */
+ /* These two bitfields are intentionally oversized, in the hope that
+ accesses to 16-bit fields will usually be quicker. */
+ ENUM_BITFIELD(df_ref_type) type : 16;
+ /* Used to see if the ref is read or write. */
+ int flags : 16; /* Various df_ref_flags. */
+ unsigned int start_regno; /* First word of the multi word subreg. */
+ unsigned int end_regno; /* Last word of the multi word subreg. */
+ unsigned int mw_order; /* Same as df_ref.ref_order. */
+};
+
+
+/* Define a register reference structure. One of these is allocated
+ for every register reference (use or def). Note some register
+ references (e.g., post_inc, subreg) generate both a def and a use. */
+struct df_base_ref
+{
+ /* These three bitfields are intentionally oversized, in the hope that
+ accesses to 8 and 16-bit fields will usually be quicker. */
+ ENUM_BITFIELD(df_ref_class) cl : 8;
+
+ ENUM_BITFIELD(df_ref_type) type : 8;
+ /* Type of ref. */
+ int flags : 16; /* Various df_ref_flags. */
+ unsigned int regno; /* The register number referenced. */
+ rtx reg; /* The register referenced. */
+ union df_ref_d *next_loc; /* Next ref for same insn or bb. */
+ struct df_link *chain; /* Head of def-use, use-def. */
+ /* Pointer to the insn info of the containing instruction. FIXME!
+ Currently this is NULL for artificial refs but this will be used
+ when FUDs are added. */
+ struct df_insn_info *insn_info;
+ /* For each regno, there are three chains of refs, one for the uses,
+ the eq_uses and the defs. These chains go through the refs
+ themselves rather than using an external structure. */
+ union df_ref_d *next_reg; /* Next ref with same regno and type. */
+ union df_ref_d *prev_reg; /* Prev ref with same regno and type. */
+ /* Location in the ref table. This is only valid after a call to
+ df_maybe_reorganize_[use,def]_refs which is an expensive operation. */
+ int id;
+ /* The index at which the operand was scanned in the insn. This is
+ used to totally order the refs in an insn. */
+ unsigned int ref_order;
+};
+
+
+/* The three types of df_refs. Note that the df_ref_extract is an
+ extension of the df_regular_ref, not the df_base_ref. */
+struct df_artificial_ref
+{
+ struct df_base_ref base;
+
+ /* Artificial refs do not have an insn, so to get the basic block,
+ it must be explicitly here. */
+ basic_block bb;
+};
+
+
+struct df_regular_ref
+{
+ struct df_base_ref base;
+ /* The loc is the address in the insn of the reg. This is not
+ defined for special registers, such as clobbers and stack
+ pointers that are also associated with call insns and so those
+ just use the base. */
+ rtx *loc;
+};
+
+/* Union of the different kinds of defs/uses placeholders. */
+union df_ref_d
+{
+ struct df_base_ref base;
+ struct df_regular_ref regular_ref;
+ struct df_artificial_ref artificial_ref;
+};
+typedef union df_ref_d *df_ref;
+
+
+/* One of these structures is allocated for every insn. */
+struct df_insn_info
+{
+ rtx_insn *insn; /* The insn this info comes from. */
+ df_ref defs; /* Head of insn-def chain. */
+ df_ref uses; /* Head of insn-use chain. */
+ /* Head of insn-use chain for uses in REG_EQUAL/EQUIV notes. */
+ df_ref eq_uses;
+ struct df_mw_hardreg *mw_hardregs;
+ /* The logical uid of the insn in the basic block. This is valid
+ after any call to df_analyze but may rot after insns are added,
+ deleted or moved. */
+ int luid;
+};
+
+/* These links are used for ref-ref chains. Currently only DEF-USE and
+ USE-DEF chains can be built by DF. */
+struct df_link
+{
+ df_ref ref;
+ struct df_link *next;
+};
+
+
+enum df_chain_flags
+{
+ /* Flags that control the building of chains. */
+ DF_DU_CHAIN = 1, /* Build DU chains. */
+ DF_UD_CHAIN = 2 /* Build UD chains. */
+};
+
+enum df_scan_flags
+{
+ /* Flags for the SCAN problem. */
+ DF_SCAN_EMPTY_ENTRY_EXIT = 1 /* Don't define any registers in the entry
+ block; don't use any in the exit block. */
+};
+
+enum df_changeable_flags
+{
+ /* Scanning flags. */
+ /* Flag to control the running of dce as a side effect of building LR. */
+ DF_LR_RUN_DCE = 1 << 0, /* Run DCE. */
+ DF_NO_HARD_REGS = 1 << 1, /* Skip hard registers in RD and CHAIN Building. */
+
+ DF_EQ_NOTES = 1 << 2, /* Build chains with uses present in EQUIV/EQUAL notes. */
+ DF_NO_REGS_EVER_LIVE = 1 << 3, /* Do not compute the regs_ever_live. */
+
+ /* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to
+ return immediately. This is used by passes that know how to update
+ the scanning them selves. */
+ DF_NO_INSN_RESCAN = 1 << 4,
+
+ /* Cause df_insn_rescan df_notes_rescan and df_insn_delete, to
+ return after marking the insn for later processing. This allows all
+ rescans to be batched. */
+ DF_DEFER_INSN_RESCAN = 1 << 5,
+
+ /* Compute the reaching defs problem as "live and reaching defs" (LR&RD).
+ A DEF is reaching and live at insn I if DEF reaches I and REGNO(DEF)
+ is in LR_IN of the basic block containing I. */
+ DF_RD_PRUNE_DEAD_DEFS = 1 << 6,
+
+ DF_VERIFY_SCHEDULED = 1 << 7
+};
+
+/* Two of these structures are inline in df, one for the uses and one
+ for the defs. This structure is only contains the refs within the
+ boundary of the df_set_blocks if that has been defined. */
+struct df_ref_info
+{
+ df_ref *refs; /* Ref table, indexed by id. */
+ unsigned int *begin; /* First ref_index for this pseudo. */
+ unsigned int *count; /* Count of refs for this pseudo. */
+ unsigned int refs_size; /* Size of currently allocated refs table. */
+
+ /* Table_size is the number of elements in the refs table. This
+ will also be the width of the bitvectors in the rd and ru
+ problems. Total_size is the number of refs. These will be the
+ same if the focus has not been reduced by df_set_blocks. If the
+ focus has been reduced, table_size will be smaller since it only
+ contains the refs in the set blocks. */
+ unsigned int table_size;
+ unsigned int total_size;
+
+ enum df_ref_order ref_order;
+};
+
+/* Three of these structures are allocated for every pseudo reg. One
+ for the uses, one for the eq_uses and one for the defs. */
+struct df_reg_info
+{
+ /* Head of chain for refs of that type and regno. */
+ df_ref reg_chain;
+ /* Number of refs in the chain. */
+ unsigned int n_refs;
+};
+
+
+/*----------------------------------------------------------------------------
+ Problem data for the scanning dataflow problem. Unlike the other
+ dataflow problems, the problem data for scanning is fully exposed and
+ used by owners of the problem.
+----------------------------------------------------------------------------*/
+
+class df_d
+{
+public:
+
+ /* The set of problems to be solved is stored in two arrays. In
+ PROBLEMS_IN_ORDER, the problems are stored in the order that they
+ are solved. This is an internally dense array that may have
+ nulls at the end of it. In PROBLEMS_BY_INDEX, the problem is
+ stored by the value in df_problem.id. These are used to access
+ the problem local data without having to search the first
+ array. */
+
+ struct dataflow *problems_in_order[DF_LAST_PROBLEM_PLUS1];
+ struct dataflow *problems_by_index[DF_LAST_PROBLEM_PLUS1];
+
+ /* If not NULL, this subset of blocks of the program to be
+ considered for analysis. At certain times, this will contain all
+ the blocks in the function so it cannot be used as an indicator
+ of if we are analyzing a subset. See analyze_subset. */
+ bitmap blocks_to_analyze;
+
+ /* The following information is really the problem data for the
+ scanning instance but it is used too often by the other problems
+ to keep getting it from there. */
+ struct df_ref_info def_info; /* Def info. */
+ struct df_ref_info use_info; /* Use info. */
+
+ /* The following three arrays are allocated in parallel. They contain
+ the sets of refs of each type for each reg. */
+ struct df_reg_info **def_regs; /* Def reg info. */
+ struct df_reg_info **use_regs; /* Eq_use reg info. */
+ struct df_reg_info **eq_use_regs; /* Eq_use info. */
+ unsigned int regs_size; /* Size of currently allocated regs table. */
+ unsigned int regs_inited; /* Number of regs with reg_infos allocated. */
+
+
+ struct df_insn_info **insns; /* Insn table, indexed by insn UID. */
+ unsigned int insns_size; /* Size of insn table. */
+
+ int num_problems_defined;
+
+ bitmap_head hardware_regs_used; /* The set of hardware registers used. */
+ /* The set of hard regs that are in the artificial uses at the end
+ of a regular basic block. */
+ bitmap_head regular_block_artificial_uses;
+ /* The set of hard regs that are in the artificial uses at the end
+ of a basic block that has an EH pred. */
+ bitmap_head eh_block_artificial_uses;
+ /* The set of hardware registers live on entry to the function. */
+ bitmap entry_block_defs;
+ bitmap exit_block_uses; /* The set of hardware registers used in exit block. */
+
+ /* Insns to delete, rescan or reprocess the notes at next
+ df_rescan_all or df_process_deferred_rescans. */
+ bitmap_head insns_to_delete;
+ bitmap_head insns_to_rescan;
+ bitmap_head insns_to_notes_rescan;
+ int *postorder; /* The current set of basic blocks
+ in reverse postorder. */
+ vec<int> postorder_inverted; /* The current set of basic blocks
+ in reverse postorder of inverted CFG. */
+ int n_blocks; /* The number of blocks in reverse postorder. */
+
+ /* An array [FIRST_PSEUDO_REGISTER], indexed by regno, of the number
+ of refs that qualify as being real hard regs uses. Artificial
+ uses and defs as well as refs in eq notes are ignored. If the
+ ref is a def, it cannot be a MAY_CLOBBER def. If the ref is a
+ use, it cannot be the emim_reg_set or be the frame or arg pointer
+ register. Uses in debug insns are ignored.
+
+ IT IS NOT ACCEPTABLE TO MANUALLY CHANGE THIS ARRAY. This array
+ always reflects the actual number of refs in the insn stream that
+ satisfy the above criteria. */
+ unsigned int *hard_regs_live_count;
+
+ /* This counter provides a way to totally order refs without using
+ addresses. It is incremented whenever a ref is created. */
+ unsigned int ref_order;
+
+ /* Problem specific control information. This is a combination of
+ enum df_changeable_flags values. */
+ int changeable_flags : 8;
+
+ /* If this is true, then only a subset of the blocks of the program
+ is considered to compute the solutions of dataflow problems. */
+ bool analyze_subset;
+
+ /* True if someone added or deleted something from regs_ever_live so
+ that the entry and exit blocks need be reprocessed. */
+ bool redo_entry_and_exit;
+};
+
+#define DF_SCAN_BB_INFO(BB) (df_scan_get_bb_info ((BB)->index))
+#define DF_RD_BB_INFO(BB) (df_rd_get_bb_info ((BB)->index))
+#define DF_LR_BB_INFO(BB) (df_lr_get_bb_info ((BB)->index))
+#define DF_LIVE_BB_INFO(BB) (df_live_get_bb_info ((BB)->index))
+#define DF_WORD_LR_BB_INFO(BB) (df_word_lr_get_bb_info ((BB)->index))
+#define DF_MD_BB_INFO(BB) (df_md_get_bb_info ((BB)->index))
+#define DF_MIR_BB_INFO(BB) (df_mir_get_bb_info ((BB)->index))
+
+/* Most transformations that wish to use live register analysis will
+ use these macros. This info is the and of the lr and live sets. */
+#define DF_LIVE_IN(BB) (&DF_LIVE_BB_INFO (BB)->in)
+#define DF_LIVE_OUT(BB) (&DF_LIVE_BB_INFO (BB)->out)
+
+#define DF_MIR_IN(BB) (&DF_MIR_BB_INFO (BB)->in)
+#define DF_MIR_OUT(BB) (&DF_MIR_BB_INFO (BB)->out)
+
+/* These macros are used by passes that are not tolerant of
+ uninitialized variables. This intolerance should eventually
+ be fixed. */
+#define DF_LR_IN(BB) (&DF_LR_BB_INFO (BB)->in)
+#define DF_LR_OUT(BB) (&DF_LR_BB_INFO (BB)->out)
+
+/* These macros are used by passes that are not tolerant of
+ uninitialized variables. This intolerance should eventually
+ be fixed. */
+#define DF_WORD_LR_IN(BB) (&DF_WORD_LR_BB_INFO (BB)->in)
+#define DF_WORD_LR_OUT(BB) (&DF_WORD_LR_BB_INFO (BB)->out)
+
+/* Macros to access the elements within the ref structure. */
+
+
+#define DF_REF_REAL_REG(REF) (GET_CODE ((REF)->base.reg) == SUBREG \
+ ? SUBREG_REG ((REF)->base.reg) : ((REF)->base.reg))
+#define DF_REF_REGNO(REF) ((REF)->base.regno)
+#define DF_REF_REAL_LOC(REF) (GET_CODE (*((REF)->regular_ref.loc)) == SUBREG \
+ ? &SUBREG_REG (*((REF)->regular_ref.loc)) : ((REF)->regular_ref.loc))
+#define DF_REF_REG(REF) ((REF)->base.reg)
+#define DF_REF_LOC(REF) (DF_REF_CLASS (REF) == DF_REF_REGULAR ? \
+ (REF)->regular_ref.loc : NULL)
+#define DF_REF_BB(REF) (DF_REF_IS_ARTIFICIAL (REF) \
+ ? (REF)->artificial_ref.bb \
+ : BLOCK_FOR_INSN (DF_REF_INSN (REF)))
+#define DF_REF_BBNO(REF) (DF_REF_BB (REF)->index)
+#define DF_REF_INSN_INFO(REF) ((REF)->base.insn_info)
+#define DF_REF_INSN(REF) ((REF)->base.insn_info->insn)
+#define DF_REF_INSN_UID(REF) (INSN_UID (DF_REF_INSN(REF)))
+#define DF_REF_CLASS(REF) ((REF)->base.cl)
+#define DF_REF_TYPE(REF) ((REF)->base.type)
+#define DF_REF_CHAIN(REF) ((REF)->base.chain)
+#define DF_REF_ID(REF) ((REF)->base.id)
+#define DF_REF_FLAGS(REF) ((REF)->base.flags)
+#define DF_REF_FLAGS_IS_SET(REF, v) ((DF_REF_FLAGS (REF) & (v)) != 0)
+#define DF_REF_FLAGS_SET(REF, v) (DF_REF_FLAGS (REF) |= (v))
+#define DF_REF_FLAGS_CLEAR(REF, v) (DF_REF_FLAGS (REF) &= ~(v))
+#define DF_REF_ORDER(REF) ((REF)->base.ref_order)
+/* If DF_REF_IS_ARTIFICIAL () is true, this is not a real
+ definition/use, but an artificial one created to model always live
+ registers, eh uses, etc. */
+#define DF_REF_IS_ARTIFICIAL(REF) (DF_REF_CLASS (REF) == DF_REF_ARTIFICIAL)
+#define DF_REF_REG_MARK(REF) (DF_REF_FLAGS_SET ((REF),DF_REF_REG_MARKER))
+#define DF_REF_REG_UNMARK(REF) (DF_REF_FLAGS_CLEAR ((REF),DF_REF_REG_MARKER))
+#define DF_REF_IS_REG_MARKED(REF) (DF_REF_FLAGS_IS_SET ((REF),DF_REF_REG_MARKER))
+#define DF_REF_NEXT_LOC(REF) ((REF)->base.next_loc)
+#define DF_REF_NEXT_REG(REF) ((REF)->base.next_reg)
+#define DF_REF_PREV_REG(REF) ((REF)->base.prev_reg)
+/* The following two macros may only be applied if one of
+ DF_REF_SIGN_EXTRACT | DF_REF_ZERO_EXTRACT is true. */
+#define DF_REF_EXTRACT_WIDTH(REF) ((REF)->extract_ref.width)
+#define DF_REF_EXTRACT_OFFSET(REF) ((REF)->extract_ref.offset)
+#define DF_REF_EXTRACT_MODE(REF) ((REF)->extract_ref.mode)
+
+/* Macros to determine the reference type. */
+#define DF_REF_REG_DEF_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_DEF)
+#define DF_REF_REG_USE_P(REF) (!DF_REF_REG_DEF_P (REF))
+#define DF_REF_REG_MEM_STORE_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_STORE)
+#define DF_REF_REG_MEM_LOAD_P(REF) (DF_REF_TYPE (REF) == DF_REF_REG_MEM_LOAD)
+#define DF_REF_REG_MEM_P(REF) (DF_REF_REG_MEM_STORE_P (REF) \
+ || DF_REF_REG_MEM_LOAD_P (REF))
+
+#define DF_MWS_REG_DEF_P(MREF) (DF_MWS_TYPE (MREF) == DF_REF_REG_DEF)
+#define DF_MWS_REG_USE_P(MREF) (!DF_MWS_REG_DEF_P (MREF))
+#define DF_MWS_NEXT(MREF) ((MREF)->next)
+#define DF_MWS_TYPE(MREF) ((MREF)->type)
+
+/* Macros to get the refs out of def_info or use_info refs table. If
+ the focus of the dataflow has been set to some subset of blocks
+ with df_set_blocks, these macros will only find the uses and defs
+ in that subset of blocks.
+
+ These macros should be used with care. The def macros are only
+ usable after a call to df_maybe_reorganize_def_refs and the use
+ macros are only usable after a call to
+ df_maybe_reorganize_use_refs. HOWEVER, BUILDING AND USING THESE
+ ARRAYS ARE A CACHE LOCALITY KILLER. */
+
+#define DF_DEFS_TABLE_SIZE() (df->def_info.table_size)
+#define DF_DEFS_GET(ID) (df->def_info.refs[(ID)])
+#define DF_DEFS_SET(ID,VAL) (df->def_info.refs[(ID)]=(VAL))
+#define DF_DEFS_COUNT(ID) (df->def_info.count[(ID)])
+#define DF_DEFS_BEGIN(ID) (df->def_info.begin[(ID)])
+#define DF_USES_TABLE_SIZE() (df->use_info.table_size)
+#define DF_USES_GET(ID) (df->use_info.refs[(ID)])
+#define DF_USES_SET(ID,VAL) (df->use_info.refs[(ID)]=(VAL))
+#define DF_USES_COUNT(ID) (df->use_info.count[(ID)])
+#define DF_USES_BEGIN(ID) (df->use_info.begin[(ID)])
+
+/* Macros to access the register information from scan dataflow record. */
+
+#define DF_REG_SIZE(DF) (df->regs_inited)
+#define DF_REG_DEF_GET(REG) (df->def_regs[(REG)])
+#define DF_REG_DEF_CHAIN(REG) (df->def_regs[(REG)]->reg_chain)
+#define DF_REG_DEF_COUNT(REG) (df->def_regs[(REG)]->n_refs)
+#define DF_REG_USE_GET(REG) (df->use_regs[(REG)])
+#define DF_REG_USE_CHAIN(REG) (df->use_regs[(REG)]->reg_chain)
+#define DF_REG_USE_COUNT(REG) (df->use_regs[(REG)]->n_refs)
+#define DF_REG_EQ_USE_GET(REG) (df->eq_use_regs[(REG)])
+#define DF_REG_EQ_USE_CHAIN(REG) (df->eq_use_regs[(REG)]->reg_chain)
+#define DF_REG_EQ_USE_COUNT(REG) (df->eq_use_regs[(REG)]->n_refs)
+
+/* Macros to access the elements within the reg_info structure table. */
+
+#define DF_REGNO_FIRST_DEF(REGNUM) \
+(DF_REG_DEF_GET(REGNUM) ? DF_REG_DEF_GET (REGNUM) : 0)
+#define DF_REGNO_LAST_USE(REGNUM) \
+(DF_REG_USE_GET(REGNUM) ? DF_REG_USE_GET (REGNUM) : 0)
+
+/* Macros to access the elements within the insn_info structure table. */
+
+#define DF_INSN_SIZE() ((df)->insns_size)
+#define DF_INSN_INFO_GET(INSN) (df->insns[(INSN_UID (INSN))])
+#define DF_INSN_INFO_SET(INSN,VAL) (df->insns[(INSN_UID (INSN))]=(VAL))
+#define DF_INSN_INFO_LUID(II) ((II)->luid)
+#define DF_INSN_INFO_DEFS(II) ((II)->defs)
+#define DF_INSN_INFO_USES(II) ((II)->uses)
+#define DF_INSN_INFO_EQ_USES(II) ((II)->eq_uses)
+#define DF_INSN_INFO_MWS(II) ((II)->mw_hardregs)
+
+#define DF_INSN_LUID(INSN) (DF_INSN_INFO_LUID (DF_INSN_INFO_GET (INSN)))
+#define DF_INSN_DEFS(INSN) (DF_INSN_INFO_DEFS (DF_INSN_INFO_GET (INSN)))
+#define DF_INSN_USES(INSN) (DF_INSN_INFO_USES (DF_INSN_INFO_GET (INSN)))
+#define DF_INSN_EQ_USES(INSN) (DF_INSN_INFO_EQ_USES (DF_INSN_INFO_GET (INSN)))
+
+#define DF_INSN_UID_GET(UID) (df->insns[(UID)])
+#define DF_INSN_UID_SET(UID,VAL) (df->insns[(UID)]=(VAL))
+#define DF_INSN_UID_SAFE_GET(UID) (((unsigned)(UID) < DF_INSN_SIZE ()) \
+ ? DF_INSN_UID_GET (UID) \
+ : NULL)
+#define DF_INSN_UID_LUID(INSN) (DF_INSN_UID_GET (INSN)->luid)
+#define DF_INSN_UID_DEFS(INSN) (DF_INSN_UID_GET (INSN)->defs)
+#define DF_INSN_UID_USES(INSN) (DF_INSN_UID_GET (INSN)->uses)
+#define DF_INSN_UID_EQ_USES(INSN) (DF_INSN_UID_GET (INSN)->eq_uses)
+#define DF_INSN_UID_MWS(INSN) (DF_INSN_UID_GET (INSN)->mw_hardregs)
+
+#define FOR_EACH_INSN_INFO_DEF(ITER, INSN) \
+ for (ITER = DF_INSN_INFO_DEFS (INSN); ITER; ITER = DF_REF_NEXT_LOC (ITER))
+
+#define FOR_EACH_INSN_INFO_USE(ITER, INSN) \
+ for (ITER = DF_INSN_INFO_USES (INSN); ITER; ITER = DF_REF_NEXT_LOC (ITER))
+
+#define FOR_EACH_INSN_INFO_EQ_USE(ITER, INSN) \
+ for (ITER = DF_INSN_INFO_EQ_USES (INSN); ITER; ITER = DF_REF_NEXT_LOC (ITER))
+
+#define FOR_EACH_INSN_INFO_MW(ITER, INSN) \
+ for (ITER = DF_INSN_INFO_MWS (INSN); ITER; ITER = DF_MWS_NEXT (ITER))
+
+#define FOR_EACH_INSN_DEF(ITER, INSN) \
+ FOR_EACH_INSN_INFO_DEF(ITER, DF_INSN_INFO_GET (INSN))
+
+#define FOR_EACH_INSN_USE(ITER, INSN) \
+ FOR_EACH_INSN_INFO_USE(ITER, DF_INSN_INFO_GET (INSN))
+
+#define FOR_EACH_INSN_EQ_USE(ITER, INSN) \
+ FOR_EACH_INSN_INFO_EQ_USE(ITER, DF_INSN_INFO_GET (INSN))
+
+#define FOR_EACH_ARTIFICIAL_USE(ITER, BB_INDEX) \
+ for (ITER = df_get_artificial_uses (BB_INDEX); ITER; \
+ ITER = DF_REF_NEXT_LOC (ITER))
+
+#define FOR_EACH_ARTIFICIAL_DEF(ITER, BB_INDEX) \
+ for (ITER = df_get_artificial_defs (BB_INDEX); ITER; \
+ ITER = DF_REF_NEXT_LOC (ITER))
+
+/* An obstack for bitmap not related to specific dataflow problems.
+ This obstack should e.g. be used for bitmaps with a short life time
+ such as temporary bitmaps. This obstack is declared in df-core.cc. */
+
+extern bitmap_obstack df_bitmap_obstack;
+
+
+/* One of these structures is allocated for every basic block. */
+struct df_scan_bb_info
+{
+ /* The entry block has many artificial defs and these are at the
+ bottom of the block.
+
+ Blocks that are targets of exception edges may have some
+ artificial defs. These are logically located at the top of the
+ block.
+
+ Blocks that are the targets of non-local goto's have the hard
+ frame pointer defined at the top of the block. */
+ df_ref artificial_defs;
+
+ /* Blocks that are targets of exception edges may have some
+ artificial uses. These are logically at the top of the block.
+
+ Most blocks have artificial uses at the bottom of the block. */
+ df_ref artificial_uses;
+};
+
+
+/* Reaching definitions. All bitmaps are indexed by the id field of
+ the ref except sparse_kill which is indexed by regno. For the
+ LR&RD problem, the kill set is not complete: It does not contain
+ DEFs killed because the set register has died in the LR set. */
+class df_rd_bb_info
+{
+public:
+ /* Local sets to describe the basic blocks. */
+ bitmap_head kill;
+ bitmap_head sparse_kill;
+ bitmap_head gen; /* The set of defs generated in this block. */
+
+ /* The results of the dataflow problem. */
+ bitmap_head in; /* At the top of the block. */
+ bitmap_head out; /* At the bottom of the block. */
+};
+
+
+/* Multiple reaching definitions. All bitmaps are referenced by the
+ register number. */
+
+class df_md_bb_info
+{
+public:
+ /* Local sets to describe the basic blocks. */
+ bitmap_head gen; /* Partial/conditional definitions live at BB out. */
+ bitmap_head kill; /* Other definitions that are live at BB out. */
+ bitmap_head init; /* Definitions coming from dominance frontier edges. */
+
+ /* The results of the dataflow problem. */
+ bitmap_head in; /* Just before the block itself. */
+ bitmap_head out; /* At the bottom of the block. */
+};
+
+
+/* Live registers, a backwards dataflow problem. All bitmaps are
+ referenced by the register number. */
+
+class df_lr_bb_info
+{
+public:
+ /* Local sets to describe the basic blocks. */
+ bitmap_head def; /* The set of registers set in this block
+ - except artificial defs at the top. */
+ bitmap_head use; /* The set of registers used in this block. */
+
+ /* The results of the dataflow problem. */
+ bitmap_head in; /* Just before the block itself. */
+ bitmap_head out; /* At the bottom of the block. */
+};
+
+
+/* Uninitialized registers. All bitmaps are referenced by the
+ register number. Anded results of the forwards and backward live
+ info. Note that the forwards live information is not available
+ separately. */
+class df_live_bb_info
+{
+public:
+ /* Local sets to describe the basic blocks. */
+ bitmap_head kill; /* The set of registers unset in this block. Calls,
+ for instance, unset registers. */
+ bitmap_head gen; /* The set of registers set in this block. */
+
+ /* The results of the dataflow problem. */
+ bitmap_head in; /* At the top of the block. */
+ bitmap_head out; /* At the bottom of the block. */
+};
+
+
+/* Live registers, a backwards dataflow problem. These bitmaps are
+ indexed by 2 * regno for each pseudo and have two entries for each
+ pseudo. Only pseudos that have a size of 2 * UNITS_PER_WORD are
+ meaningfully tracked. */
+
+class df_word_lr_bb_info
+{
+public:
+ /* Local sets to describe the basic blocks. */
+ bitmap_head def; /* The set of registers set in this block
+ - except artificial defs at the top. */
+ bitmap_head use; /* The set of registers used in this block. */
+
+ /* The results of the dataflow problem. */
+ bitmap_head in; /* Just before the block itself. */
+ bitmap_head out; /* At the bottom of the block. */
+};
+
+/* Must-initialized registers. All bitmaps are referenced by the
+ register number. */
+class df_mir_bb_info
+{
+public:
+ /* Local sets to describe the basic blocks. */
+ bitmap_head kill; /* The set of registers unset in this block. Calls,
+ for instance, unset registers. */
+ bitmap_head gen; /* The set of registers set in this block, excluding the
+ ones killed later on in this block. */
+
+ /* The results of the dataflow problem. */
+ bitmap_head in; /* At the top of the block. */
+ bitmap_head out; /* At the bottom of the block. */
+ bool con_visited; /* Visited by con_fun_{0,n}. */
+};
+
+
+/* This is used for debugging and for the dumpers to find the latest
+ instance so that the df info can be added to the dumps. This
+ should not be used by regular code. */
+extern class df_d *df;
+#define df_scan (df->problems_by_index[DF_SCAN])
+#define df_rd (df->problems_by_index[DF_RD])
+#define df_lr (df->problems_by_index[DF_LR])
+#define df_live (df->problems_by_index[DF_LIVE])
+#define df_chain (df->problems_by_index[DF_CHAIN])
+#define df_word_lr (df->problems_by_index[DF_WORD_LR])
+#define df_note (df->problems_by_index[DF_NOTE])
+#define df_md (df->problems_by_index[DF_MD])
+#define df_mir (df->problems_by_index[DF_MIR])
+
+/* This symbol turns on checking that each modification of the cfg has
+ been identified to the appropriate df routines. It is not part of
+ verification per se because the check that the final solution has
+ not changed covers this. However, if the solution is not being
+ properly recomputed because the cfg is being modified, adding in
+ calls to df_check_cfg_clean can be used to find the source of that
+ kind of problem. */
+#if 0
+#define DF_DEBUG_CFG
+#endif
+
+
+/* Functions defined in df-core.cc. */
+
+extern void df_add_problem (const struct df_problem *);
+extern int df_set_flags (int);
+extern int df_clear_flags (int);
+extern void df_set_blocks (bitmap);
+extern void df_remove_problem (struct dataflow *);
+extern void df_finish_pass (bool);
+extern void df_analyze_problem (struct dataflow *, bitmap, int *, int);
+extern void df_analyze ();
+extern void df_analyze_loop (class loop *);
+extern int df_get_n_blocks (enum df_flow_dir);
+extern int *df_get_postorder (enum df_flow_dir);
+extern void df_simple_dataflow (enum df_flow_dir, df_init_function,
+ df_confluence_function_0, df_confluence_function_n,
+ df_transfer_function, bitmap, int *, int);
+extern void df_mark_solutions_dirty (void);
+extern bool df_get_bb_dirty (basic_block);
+extern void df_set_bb_dirty (basic_block);
+extern void df_compact_blocks (void);
+extern void df_bb_replace (int, basic_block);
+extern void df_bb_delete (int);
+extern void df_verify (void);
+#ifdef DF_DEBUG_CFG
+extern void df_check_cfg_clean (void);
+#endif
+extern df_ref df_bb_regno_first_def_find (basic_block, unsigned int);
+extern df_ref df_bb_regno_last_def_find (basic_block, unsigned int);
+extern df_ref df_find_def (rtx_insn *, rtx);
+extern bool df_reg_defined (rtx_insn *, rtx);
+extern df_ref df_find_use (rtx_insn *, rtx);
+extern bool df_reg_used (rtx_insn *, rtx);
+extern void df_worklist_dataflow (struct dataflow *,bitmap, int *, int);
+extern void df_print_regset (FILE *file, const_bitmap r);
+extern void df_print_word_regset (FILE *file, const_bitmap r);
+extern void df_dump (FILE *);
+extern void df_dump_region (FILE *);
+extern void df_dump_start (FILE *);
+extern void df_dump_top (basic_block, FILE *);
+extern void df_dump_bottom (basic_block, FILE *);
+extern void df_dump_insn_top (const rtx_insn *, FILE *);
+extern void df_dump_insn_bottom (const rtx_insn *, FILE *);
+extern void df_refs_chain_dump (df_ref, bool, FILE *);
+extern void df_regs_chain_dump (df_ref, FILE *);
+extern void df_insn_debug (rtx_insn *, bool, FILE *);
+extern void df_insn_debug_regno (rtx_insn *, FILE *);
+extern void df_regno_debug (unsigned int, FILE *);
+extern void df_ref_debug (df_ref, FILE *);
+extern void debug_df_insn (rtx_insn *);
+extern void debug_df_regno (unsigned int);
+extern void debug_df_reg (rtx);
+extern void debug_df_defno (unsigned int);
+extern void debug_df_useno (unsigned int);
+extern void debug_df_ref (df_ref);
+extern void debug_df_chain (struct df_link *);
+
+/* Functions defined in df-problems.cc. */
+
+extern struct df_link *df_chain_create (df_ref, df_ref);
+extern void df_chain_unlink (df_ref);
+extern void df_chain_copy (df_ref, struct df_link *);
+extern void df_grow_bb_info (struct dataflow *);
+extern void df_chain_dump (struct df_link *, FILE *);
+extern void df_print_bb_index (basic_block bb, FILE *file);
+extern void df_rd_add_problem (void);
+extern void df_rd_simulate_artificial_defs_at_top (basic_block, bitmap);
+extern void df_rd_simulate_one_insn (basic_block, rtx_insn *, bitmap);
+extern void df_lr_add_problem (void);
+extern void df_lr_verify_transfer_functions (void);
+extern void df_live_verify_transfer_functions (void);
+extern void df_live_add_problem (void);
+extern void df_live_set_all_dirty (void);
+extern void df_chain_add_problem (unsigned int);
+extern void df_word_lr_add_problem (void);
+extern bool df_word_lr_mark_ref (df_ref, bool, bitmap);
+extern bool df_word_lr_simulate_defs (rtx_insn *, bitmap);
+extern void df_word_lr_simulate_uses (rtx_insn *, bitmap);
+extern void df_word_lr_simulate_artificial_refs_at_top (basic_block, bitmap);
+extern void df_word_lr_simulate_artificial_refs_at_end (basic_block, bitmap);
+extern void df_note_add_problem (void);
+extern void df_md_add_problem (void);
+extern void df_md_simulate_artificial_defs_at_top (basic_block, bitmap);
+extern void df_md_simulate_one_insn (basic_block, rtx_insn *, bitmap);
+extern void df_mir_add_problem (void);
+extern void df_mir_simulate_one_insn (basic_block, rtx_insn *, bitmap, bitmap);
+extern void df_simulate_find_noclobber_defs (rtx_insn *, bitmap);
+extern void df_simulate_find_defs (rtx_insn *, bitmap);
+extern void df_simulate_defs (rtx_insn *, bitmap);
+extern void df_simulate_uses (rtx_insn *, bitmap);
+extern void df_simulate_initialize_backwards (basic_block, bitmap);
+extern void df_simulate_one_insn_backwards (basic_block, rtx_insn *, bitmap);
+extern void df_simulate_finalize_backwards (basic_block, bitmap);
+extern void df_simulate_initialize_forwards (basic_block, bitmap);
+extern void df_simulate_one_insn_forwards (basic_block, rtx_insn *, bitmap);
+extern void simulate_backwards_to_point (basic_block, regset, rtx);
+extern bool can_move_insns_across (rtx_insn *, rtx_insn *,
+ rtx_insn *, rtx_insn *,
+ basic_block, regset,
+ regset, rtx_insn **);
+/* Functions defined in df-scan.cc. */
+
+extern void df_scan_alloc (bitmap);
+extern void df_scan_add_problem (void);
+extern void df_grow_reg_info (void);
+extern void df_grow_insn_info (void);
+extern void df_scan_blocks (void);
+extern void df_uses_create (rtx *, rtx_insn *, int);
+extern struct df_insn_info * df_insn_create_insn_record (rtx_insn *);
+extern void df_insn_delete (rtx_insn *);
+extern void df_bb_refs_record (int, bool);
+extern bool df_insn_rescan (rtx_insn *);
+extern bool df_insn_rescan_debug_internal (rtx_insn *);
+extern void df_insn_rescan_all (void);
+extern void df_process_deferred_rescans (void);
+extern void df_recompute_luids (basic_block);
+extern void df_insn_change_bb (rtx_insn *, basic_block);
+extern void df_maybe_reorganize_use_refs (enum df_ref_order);
+extern void df_maybe_reorganize_def_refs (enum df_ref_order);
+extern void df_ref_change_reg_with_loc (rtx, unsigned int);
+extern void df_notes_rescan (rtx_insn *);
+extern void df_hard_reg_init (void);
+extern void df_update_entry_block_defs (void);
+extern void df_update_exit_block_uses (void);
+extern void df_update_entry_exit_and_calls (void);
+extern bool df_hard_reg_used_p (unsigned int);
+extern unsigned int df_hard_reg_used_count (unsigned int);
+extern bool df_regs_ever_live_p (unsigned int);
+extern bool df_epilogue_uses_p (unsigned int);
+extern void df_set_regs_ever_live (unsigned int, bool);
+extern void df_compute_regs_ever_live (bool);
+extern void df_scan_verify (void);
+
+
+/*----------------------------------------------------------------------------
+ Public functions access functions for the dataflow problems.
+----------------------------------------------------------------------------*/
+
+static inline struct df_scan_bb_info *
+df_scan_get_bb_info (unsigned int index)
+{
+ if (index < df_scan->block_info_size)
+ return &((struct df_scan_bb_info *) df_scan->block_info)[index];
+ else
+ return NULL;
+}
+
+static inline class df_rd_bb_info *
+df_rd_get_bb_info (unsigned int index)
+{
+ if (index < df_rd->block_info_size)
+ return &((class df_rd_bb_info *) df_rd->block_info)[index];
+ else
+ return NULL;
+}
+
+static inline class df_lr_bb_info *
+df_lr_get_bb_info (unsigned int index)
+{
+ if (index < df_lr->block_info_size)
+ return &((class df_lr_bb_info *) df_lr->block_info)[index];
+ else
+ return NULL;
+}
+
+static inline class df_md_bb_info *
+df_md_get_bb_info (unsigned int index)
+{
+ if (index < df_md->block_info_size)
+ return &((class df_md_bb_info *) df_md->block_info)[index];
+ else
+ return NULL;
+}
+
+static inline class df_live_bb_info *
+df_live_get_bb_info (unsigned int index)
+{
+ if (index < df_live->block_info_size)
+ return &((class df_live_bb_info *) df_live->block_info)[index];
+ else
+ return NULL;
+}
+
+static inline class df_word_lr_bb_info *
+df_word_lr_get_bb_info (unsigned int index)
+{
+ if (index < df_word_lr->block_info_size)
+ return &((class df_word_lr_bb_info *) df_word_lr->block_info)[index];
+ else
+ return NULL;
+}
+
+static inline class df_mir_bb_info *
+df_mir_get_bb_info (unsigned int index)
+{
+ if (index < df_mir->block_info_size)
+ return &((class df_mir_bb_info *) df_mir->block_info)[index];
+ else
+ return NULL;
+}
+
+/* Get the live at out set for BB no matter what problem happens to be
+ defined. This function is used by the register allocators who
+ choose different dataflow problems depending on the optimization
+ level. */
+
+static inline bitmap
+df_get_live_out (basic_block bb)
+{
+ gcc_checking_assert (df_lr);
+
+ if (df_live)
+ return DF_LIVE_OUT (bb);
+ else
+ return DF_LR_OUT (bb);
+}
+
+/* Get the live at in set for BB no matter what problem happens to be
+ defined. This function is used by the register allocators who
+ choose different dataflow problems depending on the optimization
+ level. */
+
+static inline bitmap
+df_get_live_in (basic_block bb)
+{
+ gcc_checking_assert (df_lr);
+
+ if (df_live)
+ return DF_LIVE_IN (bb);
+ else
+ return DF_LR_IN (bb);
+}
+
+/* Get basic block info. */
+/* Get the artificial defs for a basic block. */
+
+static inline df_ref
+df_get_artificial_defs (unsigned int bb_index)
+{
+ return df_scan_get_bb_info (bb_index)->artificial_defs;
+}
+
+
+/* Get the artificial uses for a basic block. */
+
+static inline df_ref
+df_get_artificial_uses (unsigned int bb_index)
+{
+ return df_scan_get_bb_info (bb_index)->artificial_uses;
+}
+
+/* If INSN defines exactly one register, return the associated reference,
+ otherwise return null. */
+
+static inline df_ref
+df_single_def (const df_insn_info *info)
+{
+ df_ref defs = DF_INSN_INFO_DEFS (info);
+ return defs && !DF_REF_NEXT_LOC (defs) ? defs : NULL;
+}
+
+/* If INSN uses exactly one register, return the associated reference,
+ otherwise return null. */
+
+static inline df_ref
+df_single_use (const df_insn_info *info)
+{
+ df_ref uses = DF_INSN_INFO_USES (info);
+ return uses && !DF_REF_NEXT_LOC (uses) ? uses : NULL;
+}
+
+/* web */
+
+struct web_entry_base
+{
+ private:
+ /* Reference to the parent in the union/find tree. */
+ web_entry_base *pred_pvt;
+
+ public:
+ /* Accessors. */
+ web_entry_base *pred () { return pred_pvt; }
+ void set_pred (web_entry_base *p) { pred_pvt = p; }
+
+ /* Find representative in union-find tree. */
+ web_entry_base *unionfind_root ();
+
+ /* Union with another set, returning TRUE if they are already unioned. */
+ friend bool unionfind_union (web_entry_base *first, web_entry_base *second);
+};
+
+#endif /* GCC_DF_H */
diff --git a/support/cpp/gcc/diagnostic-color.cc b/support/cpp/gcc/diagnostic-color.cc
new file mode 100644
index 000000000..640adfad5
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-color.cc
@@ -0,0 +1,348 @@
+/* Output colorization.
+ Copyright (C) 2011-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "diagnostic-color.h"
+#include "diagnostic-url.h"
+
+#ifdef __MINGW32__
+# include <windows.h>
+#endif
+
+#include "color-macros.h"
+
+/* The context and logic for choosing default --color screen attributes
+ (foreground and background colors, etc.) are the following.
+ -- There are eight basic colors available, each with its own
+ nominal luminosity to the human eye and foreground/background
+ codes (black [0 %, 30/40], blue [11 %, 34/44], red [30 %, 31/41],
+ magenta [41 %, 35/45], green [59 %, 32/42], cyan [70 %, 36/46],
+ yellow [89 %, 33/43], and white [100 %, 37/47]).
+ -- Sometimes, white as a background is actually implemented using
+ a shade of light gray, so that a foreground white can be visible
+ on top of it (but most often not).
+ -- Sometimes, black as a foreground is actually implemented using
+ a shade of dark gray, so that it can be visible on top of a
+ background black (but most often not).
+ -- Sometimes, more colors are available, as extensions.
+ -- Other attributes can be selected/deselected (bold [1/22],
+ underline [4/24], standout/inverse [7/27], blink [5/25], and
+ invisible/hidden [8/28]). They are sometimes implemented by
+ using colors instead of what their names imply; e.g., bold is
+ often achieved by using brighter colors. In practice, only bold
+ is really available to us, underline sometimes being mapped by
+ the terminal to some strange color choice, and standout best
+ being left for use by downstream programs such as less(1).
+ -- We cannot assume that any of the extensions or special features
+ are available for the purpose of choosing defaults for everyone.
+ -- The most prevalent default terminal backgrounds are pure black
+ and pure white, and are not necessarily the same shades of
+ those as if they were selected explicitly with SGR sequences.
+ Some terminals use dark or light pictures as default background,
+ but those are covered over by an explicit selection of background
+ color with an SGR sequence; their users will appreciate their
+ background pictures not be covered like this, if possible.
+ -- Some uses of colors attributes is to make some output items
+ more understated (e.g., context lines); this cannot be achieved
+ by changing the background color.
+ -- For these reasons, the GCC color defaults should strive not
+ to change the background color from its default, unless it's
+ for a short item that should be highlighted, not understated.
+ -- The GCC foreground color defaults (without an explicitly set
+ background) should provide enough contrast to be readable on any
+ terminal with either a black (dark) or white (light) background.
+ This only leaves red, magenta, green, and cyan (and their bold
+ counterparts) and possibly bold blue. */
+/* Default colors. The user can overwrite them using environment
+ variable GCC_COLORS. */
+struct color_cap
+{
+ const char *name;
+ const char *val;
+ unsigned char name_len;
+ bool free_val;
+};
+
+/* For GCC_COLORS. */
+static struct color_cap color_dict[] =
+{
+ { "error", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_RED), 5, false },
+ { "warning", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_MAGENTA),
+ 7, false },
+ { "note", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
+ { "range1", SGR_SEQ (COLOR_FG_GREEN), 6, false },
+ { "range2", SGR_SEQ (COLOR_FG_BLUE), 6, false },
+ { "locus", SGR_SEQ (COLOR_BOLD), 5, false },
+ { "quote", SGR_SEQ (COLOR_BOLD), 5, false },
+ { "path", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_CYAN), 4, false },
+ { "fixit-insert", SGR_SEQ (COLOR_FG_GREEN), 12, false },
+ { "fixit-delete", SGR_SEQ (COLOR_FG_RED), 12, false },
+ { "diff-filename", SGR_SEQ (COLOR_BOLD), 13, false },
+ { "diff-hunk", SGR_SEQ (COLOR_FG_CYAN), 9, false },
+ { "diff-delete", SGR_SEQ (COLOR_FG_RED), 11, false },
+ { "diff-insert", SGR_SEQ (COLOR_FG_GREEN), 11, false },
+ { "type-diff", SGR_SEQ (COLOR_BOLD COLOR_SEPARATOR COLOR_FG_GREEN), 9, false },
+ { NULL, NULL, 0, false }
+};
+
+const char *
+colorize_start (bool show_color, const char *name, size_t name_len)
+{
+ struct color_cap const *cap;
+
+ if (!show_color)
+ return "";
+
+ for (cap = color_dict; cap->name; cap++)
+ if (cap->name_len == name_len
+ && memcmp (cap->name, name, name_len) == 0)
+ break;
+ if (cap->name == NULL)
+ return "";
+
+ return cap->val;
+}
+
+const char *
+colorize_stop (bool show_color)
+{
+ return show_color ? SGR_RESET : "";
+}
+
+/* Parse GCC_COLORS. The default would look like:
+ GCC_COLORS='error=01;31:warning=01;35:note=01;36:\
+ range1=32:range2=34:locus=01:quote=01:path=01;36:\
+ fixit-insert=32:fixit-delete=31:'\
+ diff-filename=01:diff-hunk=32:diff-delete=31:diff-insert=32:\
+ type-diff=01;32'
+ No character escaping is needed or supported. */
+static bool
+parse_gcc_colors (void)
+{
+ const char *p, *q, *name, *val;
+ char *b;
+ size_t name_len = 0, val_len = 0;
+
+ p = getenv ("GCC_COLORS"); /* Plural! */
+ if (p == NULL)
+ return true;
+ if (*p == '\0')
+ return false;
+
+ name = q = p;
+ val = NULL;
+ /* From now on, be well-formed or you're gone. */
+ for (;;)
+ if (*q == ':' || *q == '\0')
+ {
+ struct color_cap *cap;
+
+ if (val)
+ val_len = q - val;
+ else
+ name_len = q - name;
+ /* Empty name without val (empty cap)
+ won't match and will be ignored. */
+ for (cap = color_dict; cap->name; cap++)
+ if (cap->name_len == name_len
+ && memcmp (cap->name, name, name_len) == 0)
+ break;
+ /* If name unknown, go on for forward compatibility. */
+ if (cap->val && val)
+ {
+ if (cap->free_val)
+ free (CONST_CAST (char *, cap->val));
+ b = XNEWVEC (char, val_len + sizeof (SGR_SEQ ("")));
+ memcpy (b, SGR_START, strlen (SGR_START));
+ memcpy (b + strlen (SGR_START), val, val_len);
+ memcpy (b + strlen (SGR_START) + val_len, SGR_END,
+ sizeof (SGR_END));
+ cap->val = (const char *) b;
+ cap->free_val = true;
+ }
+ if (*q == '\0')
+ return true;
+ name = ++q;
+ val = NULL;
+ }
+ else if (*q == '=')
+ {
+ if (q == name || val)
+ return true;
+
+ name_len = q - name;
+ val = ++q; /* Can be the empty string. */
+ }
+ else if (val == NULL)
+ q++; /* Accumulate name. */
+ else if (*q == ';' || (*q >= '0' && *q <= '9'))
+ q++; /* Accumulate val. Protect the terminal from being sent
+ garbage. */
+ else
+ return true;
+}
+
+/* Return true if we should use color when in auto mode, false otherwise. */
+static bool
+should_colorize (void)
+{
+#ifdef __MINGW32__
+ /* For consistency reasons, one should check the handle returned by
+ _get_osfhandle(_fileno(stderr)) because the function
+ pp_write_text_to_stream() in pretty-print.cc calls fputs() on
+ that stream. However, the code below for non-Windows doesn't seem
+ to care about it either... */
+ HANDLE h;
+ DWORD m;
+
+ h = GetStdHandle (STD_ERROR_HANDLE);
+ return (h != INVALID_HANDLE_VALUE) && (h != NULL)
+ && GetConsoleMode (h, &m);
+#else
+ char const *t = getenv ("TERM");
+ /* emacs M-x shell sets TERM="dumb". */
+ return t && strcmp (t, "dumb") != 0 && isatty (STDERR_FILENO);
+#endif
+}
+
+bool
+colorize_init (diagnostic_color_rule_t rule)
+{
+ switch (rule)
+ {
+ case DIAGNOSTICS_COLOR_NO:
+ return false;
+ case DIAGNOSTICS_COLOR_YES:
+ return parse_gcc_colors ();
+ case DIAGNOSTICS_COLOR_AUTO:
+ if (should_colorize ())
+ return parse_gcc_colors ();
+ else
+ return false;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return URL_FORMAT_XXX which tells how we should emit urls
+ when in always mode.
+ We use GCC_URLS and if that is not defined TERM_URLS.
+ If neither is defined the feature is enabled by default. */
+
+static diagnostic_url_format
+parse_env_vars_for_urls ()
+{
+ const char *p;
+
+ p = getenv ("GCC_URLS"); /* Plural! */
+ if (p == NULL)
+ p = getenv ("TERM_URLS");
+
+ if (p == NULL)
+ return URL_FORMAT_DEFAULT;
+
+ if (*p == '\0')
+ return URL_FORMAT_NONE;
+
+ if (!strcmp (p, "no"))
+ return URL_FORMAT_NONE;
+
+ if (!strcmp (p, "st"))
+ return URL_FORMAT_ST;
+
+ if (!strcmp (p, "bel"))
+ return URL_FORMAT_BEL;
+
+ return URL_FORMAT_DEFAULT;
+}
+
+/* Return true if we should use urls when in auto mode, false otherwise. */
+
+static bool
+auto_enable_urls ()
+{
+#ifdef __MINGW32__
+ return false;
+#else
+ const char *term, *colorterm;
+
+ /* First check the terminal is capable of printing color escapes,
+ if not URLs won't work either. */
+ if (!should_colorize ())
+ return false;
+
+ /* xfce4-terminal is known to not implement URLs at this time.
+ Recently new installations (0.8) will safely ignore the URL escape
+ sequences, but a large number of legacy installations (0.6.3) print
+ garbage when URLs are printed. Therefore we lose nothing by
+ disabling this feature for that specific terminal type. */
+ colorterm = getenv ("COLORTERM");
+ if (colorterm && !strcmp (colorterm, "xfce4-terminal"))
+ return false;
+
+ /* Old versions of gnome-terminal where URL escapes cause screen
+ corruptions set COLORTERM="gnome-terminal", recent versions
+ with working URL support set this to "truecolor". */
+ if (colorterm && !strcmp (colorterm, "gnome-terminal"))
+ return false;
+
+ /* Since the following checks are less specific than the ones
+ above, let GCC_URLS and TERM_URLS override the decision. */
+ if (getenv ("GCC_URLS") || getenv ("TERM_URLS"))
+ return true;
+
+ /* In an ssh session the COLORTERM is not there, but TERM=xterm
+ can be used as an indication of a incompatible terminal while
+ TERM=xterm-256color appears to be a working terminal. */
+ term = getenv ("TERM");
+ if (!colorterm && term && !strcmp (term, "xterm"))
+ return false;
+
+ /* When logging in a linux over serial line, we see TERM=linux
+ and no COLORTERM, it is unlikely that the URL escapes will
+ work in that environmen either. */
+ if (!colorterm && term && !strcmp (term, "linux"))
+ return false;
+
+ return true;
+#endif
+}
+
+/* Determine if URLs should be enabled, based on RULE,
+ and, if so, which format to use.
+ This reuses the logic for colorization. */
+
+diagnostic_url_format
+determine_url_format (diagnostic_url_rule_t rule)
+{
+ switch (rule)
+ {
+ case DIAGNOSTICS_URL_NO:
+ return URL_FORMAT_NONE;
+ case DIAGNOSTICS_URL_YES:
+ return parse_env_vars_for_urls ();
+ case DIAGNOSTICS_URL_AUTO:
+ if (auto_enable_urls ())
+ return parse_env_vars_for_urls ();
+ else
+ return URL_FORMAT_NONE;
+ default:
+ gcc_unreachable ();
+ }
+}
diff --git a/support/cpp/gcc/diagnostic-color.h b/support/cpp/gcc/diagnostic-color.h
new file mode 100644
index 000000000..f0b50c5d4
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-color.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2013-2022 Free Software Foundation, Inc.
+ Contributed by Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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/>. */
+
+/* Based on code from: */
+/* grep.c - main driver file for grep.
+ Copyright (C) 1992-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Written July 1992 by Mike Haertel. */
+
+#ifndef GCC_DIAGNOSTIC_COLOR_H
+#define GCC_DIAGNOSTIC_COLOR_H
+
+/* Whether to add color to diagnostics:
+ o DIAGNOSTICS_COLOR_NO: never
+ o DIAGNOSTICS_COLOR_YES: always
+ o DIAGNOSTICS_COLOR_AUTO: depending on the output stream. */
+typedef enum
+{
+ DIAGNOSTICS_COLOR_NO = 0,
+ DIAGNOSTICS_COLOR_YES = 1,
+ DIAGNOSTICS_COLOR_AUTO = 2
+} diagnostic_color_rule_t;
+
+const char *colorize_start (bool, const char *, size_t);
+const char *colorize_stop (bool);
+bool colorize_init (diagnostic_color_rule_t);
+
+inline const char *
+colorize_start (bool show_color, const char *name)
+{
+ return colorize_start (show_color, name, strlen (name));
+}
+
+#endif /* ! GCC_DIAGNOSTIC_COLOR_H */
diff --git a/support/cpp/gcc/diagnostic-core.h b/support/cpp/gcc/diagnostic-core.h
new file mode 100644
index 000000000..286954ac2
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-core.h
@@ -0,0 +1,128 @@
+/* Declarations of core diagnostic functionality for code that does
+ not need to deal with diagnostic contexts or diagnostic info
+ structures.
+ 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_DIAGNOSTIC_CORE_H
+#define GCC_DIAGNOSTIC_CORE_H
+
+#include "bversion.h"
+
+/* Constants used to discriminate diagnostics. */
+typedef enum
+{
+#define DEFINE_DIAGNOSTIC_KIND(K, msgid, C) K,
+#include "diagnostic.def"
+#undef DEFINE_DIAGNOSTIC_KIND
+ DK_LAST_DIAGNOSTIC_KIND,
+ /* This is used for tagging pragma pops in the diagnostic
+ classification history chain. */
+ DK_POP
+} diagnostic_t;
+
+/* RAII-style class for grouping related diagnostics. */
+
+class auto_diagnostic_group
+{
+ public:
+ auto_diagnostic_group ();
+ ~auto_diagnostic_group ();
+};
+
+/* Forward decl. */
+class diagnostic_metadata; /* See diagnostic-metadata.h. */
+
+extern const char *progname;
+
+extern const char *trim_filename (const char *);
+
+/* If we haven't already defined a front-end-specific diagnostics
+ style, use the generic one. */
+#ifndef GCC_DIAG_STYLE
+#define GCC_DIAG_STYLE __gcc_tdiag__
+#endif
+/* None of these functions are suitable for ATTRIBUTE_PRINTF, because
+ each language front end can extend them with its own set of format
+ specifiers. We must use custom format checks. */
+#if (CHECKING_P && GCC_VERSION >= 4001) || GCC_VERSION == BUILDING_GCC_VERSION
+#define ATTRIBUTE_GCC_DIAG(m, n) __attribute__ ((__format__ (GCC_DIAG_STYLE, m, n))) ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_DIAG(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+extern void internal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
+ ATTRIBUTE_NORETURN;
+extern void internal_error_no_backtrace (const char *, ...)
+ ATTRIBUTE_GCC_DIAG(1,2) ATTRIBUTE_NORETURN;
+/* Pass one of the OPT_W* from options.h as the first parameter. */
+extern bool warning (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern bool warning_n (location_t, int, unsigned HOST_WIDE_INT,
+ const char *, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
+extern bool warning_n (rich_location *, int, unsigned HOST_WIDE_INT,
+ const char *, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(4, 6) ATTRIBUTE_GCC_DIAG(5, 6);
+extern bool warning_at (location_t, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+extern bool warning_at (rich_location *, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+extern bool warning_meta (rich_location *,
+ const diagnostic_metadata &, int,
+ const char *, ...)
+ ATTRIBUTE_GCC_DIAG(4,5);
+extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void error_n (location_t, unsigned HOST_WIDE_INT, const char *,
+ const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
+extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void error_at (rich_location *, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(2,3);
+extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
+ ATTRIBUTE_NORETURN;
+/* Pass one of the OPT_W* from options.h as the second parameter. */
+extern bool pedwarn (location_t, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+extern bool pedwarn (rich_location *, int, const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,4);
+extern bool permerror (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern bool permerror (rich_location *, const char *,
+ ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void sorry_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void inform (rich_location *, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
+extern void inform_n (location_t, unsigned HOST_WIDE_INT, const char *,
+ const char *, ...)
+ ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
+extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern bool emit_diagnostic (diagnostic_t, location_t, int,
+ const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
+extern bool emit_diagnostic (diagnostic_t, rich_location *, int,
+ const char *, ...) ATTRIBUTE_GCC_DIAG(4,5);
+extern bool emit_diagnostic_valist (diagnostic_t, location_t, int, const char *,
+ va_list *) ATTRIBUTE_GCC_DIAG (4,0);
+extern bool seen_error (void);
+
+#ifdef BUFSIZ
+ /* N.B. Unlike all the others, fnotice is just gettext+fprintf, and
+ therefore it can have ATTRIBUTE_PRINTF. */
+extern void fnotice (FILE *, const char *, ...)
+ ATTRIBUTE_PRINTF_2;
+#endif
+
+#endif /* ! GCC_DIAGNOSTIC_CORE_H */
diff --git a/support/cpp/gcc/diagnostic-event-id.h b/support/cpp/gcc/diagnostic-event-id.h
new file mode 100644
index 000000000..35c6697ba
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-event-id.h
@@ -0,0 +1,61 @@
+/* A class for referring to events within a diagnostic_path.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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_DIAGNOSTIC_EVENT_ID_H
+#define GCC_DIAGNOSTIC_EVENT_ID_H
+
+/* A class for referring to events within a diagnostic_path.
+
+ They are stored as 0-based offsets into the events, but
+ printed (e.g. via %@) as 1-based numbers.
+
+ For example, a 3-event path has event offsets 0, 1, and 2,
+ which would be shown to the user as "(1)", "(2)" and "(3)".
+
+ This has its own header so that pretty-print.cc can use this
+ to implement "%@" without bringing in all of diagnostic_path
+ (which e.g. refers to "tree"). */
+
+class diagnostic_event_id_t
+{
+ public:
+ diagnostic_event_id_t () : m_index (UNKNOWN_EVENT_IDX) {}
+ diagnostic_event_id_t (int zero_based_idx) : m_index (zero_based_idx) {}
+
+ bool known_p () const { return m_index != UNKNOWN_EVENT_IDX; }
+
+ int one_based () const
+ {
+ gcc_assert (known_p ());
+ return m_index + 1;
+ }
+
+ private:
+ static const int UNKNOWN_EVENT_IDX = -1;
+ int m_index; // zero-based
+};
+
+/* A pointer to a diagnostic_event_id_t, for use with the "%@" format
+ code, which will print a 1-based representation for it, with suitable
+ colorization, e.g. "(1)".
+ The %@ format code requires that known_p be true for the event ID. */
+typedef diagnostic_event_id_t *diagnostic_event_id_ptr;
+
+#endif /* ! GCC_DIAGNOSTIC_EVENT_ID_H */
diff --git a/support/cpp/gcc/diagnostic-format-json.cc b/support/cpp/gcc/diagnostic-format-json.cc
new file mode 100644
index 000000000..def371816
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-format-json.cc
@@ -0,0 +1,391 @@
+/* JSON output for diagnostics
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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 "diagnostic.h"
+#include "selftest-diagnostic.h"
+#include "diagnostic-metadata.h"
+#include "json.h"
+#include "selftest.h"
+
+/* The top-level JSON array of pending diagnostics. */
+
+static json::array *toplevel_array;
+
+/* The JSON object for the current diagnostic group. */
+
+static json::object *cur_group;
+
+/* The JSON array for the "children" array within the current diagnostic
+ group. */
+
+static json::array *cur_children_array;
+
+/* Generate a JSON object for LOC. */
+
+json::value *
+json_from_expanded_location (diagnostic_context *context, location_t loc)
+{
+ expanded_location exploc = expand_location (loc);
+ json::object *result = new json::object ();
+ if (exploc.file)
+ result->set ("file", new json::string (exploc.file));
+ result->set ("line", new json::integer_number (exploc.line));
+
+ const enum diagnostics_column_unit orig_unit = context->column_unit;
+ struct
+ {
+ const char *name;
+ enum diagnostics_column_unit unit;
+ } column_fields[] = {
+ {"display-column", DIAGNOSTICS_COLUMN_UNIT_DISPLAY},
+ {"byte-column", DIAGNOSTICS_COLUMN_UNIT_BYTE}
+ };
+ int the_column = INT_MIN;
+ for (int i = 0; i != sizeof column_fields / sizeof (*column_fields); ++i)
+ {
+ context->column_unit = column_fields[i].unit;
+ const int col = diagnostic_converted_column (context, exploc);
+ result->set (column_fields[i].name, new json::integer_number (col));
+ if (column_fields[i].unit == orig_unit)
+ the_column = col;
+ }
+ gcc_assert (the_column != INT_MIN);
+ result->set ("column", new json::integer_number (the_column));
+ context->column_unit = orig_unit;
+ return result;
+}
+
+/* Generate a JSON object for LOC_RANGE. */
+
+static json::object *
+json_from_location_range (diagnostic_context *context,
+ const location_range *loc_range, unsigned range_idx)
+{
+ location_t caret_loc = get_pure_location (loc_range->m_loc);
+
+ if (caret_loc == UNKNOWN_LOCATION)
+ return NULL;
+
+ location_t start_loc = get_start (loc_range->m_loc);
+ location_t finish_loc = get_finish (loc_range->m_loc);
+
+ json::object *result = new json::object ();
+ result->set ("caret", json_from_expanded_location (context, caret_loc));
+ if (start_loc != caret_loc
+ && start_loc != UNKNOWN_LOCATION)
+ result->set ("start", json_from_expanded_location (context, start_loc));
+ if (finish_loc != caret_loc
+ && finish_loc != UNKNOWN_LOCATION)
+ result->set ("finish", json_from_expanded_location (context, finish_loc));
+
+ if (loc_range->m_label)
+ {
+ label_text text;
+ text = loc_range->m_label->get_text (range_idx);
+ if (text.m_buffer)
+ result->set ("label", new json::string (text.m_buffer));
+ text.maybe_free ();
+ }
+
+ return result;
+}
+
+/* Generate a JSON object for HINT. */
+
+static json::object *
+json_from_fixit_hint (diagnostic_context *context, const fixit_hint *hint)
+{
+ json::object *fixit_obj = new json::object ();
+
+ location_t start_loc = hint->get_start_loc ();
+ fixit_obj->set ("start", json_from_expanded_location (context, start_loc));
+ location_t next_loc = hint->get_next_loc ();
+ fixit_obj->set ("next", json_from_expanded_location (context, next_loc));
+ fixit_obj->set ("string", new json::string (hint->get_string ()));
+
+ return fixit_obj;
+}
+
+/* Generate a JSON object for METADATA. */
+
+static json::object *
+json_from_metadata (const diagnostic_metadata *metadata)
+{
+ json::object *metadata_obj = new json::object ();
+
+ if (metadata->get_cwe ())
+ metadata_obj->set ("cwe",
+ new json::integer_number (metadata->get_cwe ()));
+
+ return metadata_obj;
+}
+
+/* No-op implementation of "begin_diagnostic" for JSON output. */
+
+static void
+json_begin_diagnostic (diagnostic_context *, diagnostic_info *)
+{
+}
+
+/* Implementation of "end_diagnostic" for JSON output.
+ Generate a JSON object for DIAGNOSTIC, and store for output
+ within current diagnostic group. */
+
+static void
+json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
+ diagnostic_t orig_diag_kind)
+{
+ json::object *diag_obj = new json::object ();
+
+ /* Get "kind" of diagnostic. */
+ {
+ static const char *const diagnostic_kind_text[] = {
+#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
+#include "diagnostic.def"
+#undef DEFINE_DIAGNOSTIC_KIND
+ "must-not-happen"
+ };
+ /* Lose the trailing ": ". */
+ const char *kind_text = diagnostic_kind_text[diagnostic->kind];
+ size_t len = strlen (kind_text);
+ gcc_assert (len > 2);
+ gcc_assert (kind_text[len - 2] == ':');
+ gcc_assert (kind_text[len - 1] == ' ');
+ char *rstrip = xstrdup (kind_text);
+ rstrip[len - 2] = '\0';
+ diag_obj->set ("kind", new json::string (rstrip));
+ free (rstrip);
+ }
+
+ // FIXME: encoding of the message (json::string requires UTF-8)
+ diag_obj->set ("message",
+ new json::string (pp_formatted_text (context->printer)));
+ pp_clear_output_area (context->printer);
+
+ char *option_text;
+ option_text = context->option_name (context, diagnostic->option_index,
+ orig_diag_kind, diagnostic->kind);
+ if (option_text)
+ {
+ diag_obj->set ("option", new json::string (option_text));
+ free (option_text);
+ }
+
+ if (context->get_option_url)
+ {
+ char *option_url = context->get_option_url (context,
+ diagnostic->option_index);
+ if (option_url)
+ {
+ diag_obj->set ("option_url", new json::string (option_url));
+ free (option_url);
+ }
+ }
+
+ /* If we've already emitted a diagnostic within this auto_diagnostic_group,
+ then add diag_obj to its "children" array. */
+ if (cur_group)
+ {
+ gcc_assert (cur_children_array);
+ cur_children_array->append (diag_obj);
+ }
+ else
+ {
+ /* Otherwise, make diag_obj be the top-level object within the group;
+ add a "children" array and record the column origin. */
+ toplevel_array->append (diag_obj);
+ cur_group = diag_obj;
+ cur_children_array = new json::array ();
+ diag_obj->set ("children", cur_children_array);
+ diag_obj->set ("column-origin",
+ new json::integer_number (context->column_origin));
+ }
+
+ const rich_location *richloc = diagnostic->richloc;
+
+ json::array *loc_array = new json::array ();
+ diag_obj->set ("locations", loc_array);
+
+ for (unsigned int i = 0; i < richloc->get_num_locations (); i++)
+ {
+ const location_range *loc_range = richloc->get_range (i);
+ json::object *loc_obj = json_from_location_range (context, loc_range, i);
+ if (loc_obj)
+ loc_array->append (loc_obj);
+ }
+
+ if (richloc->get_num_fixit_hints ())
+ {
+ json::array *fixit_array = new json::array ();
+ diag_obj->set ("fixits", fixit_array);
+ for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
+ {
+ const fixit_hint *hint = richloc->get_fixit_hint (i);
+ json::object *fixit_obj = json_from_fixit_hint (context, hint);
+ fixit_array->append (fixit_obj);
+ }
+ }
+
+ /* TODO: tree-ish things:
+ TODO: functions
+ TODO: inlining information
+ TODO: macro expansion information. */
+
+ if (diagnostic->metadata)
+ {
+ json::object *metadata_obj = json_from_metadata (diagnostic->metadata);
+ diag_obj->set ("metadata", metadata_obj);
+ }
+
+ const diagnostic_path *path = richloc->get_path ();
+ if (path && context->make_json_for_path)
+ {
+ json::value *path_value = context->make_json_for_path (context, path);
+ diag_obj->set ("path", path_value);
+ }
+
+ diag_obj->set ("escape-source",
+ new json::literal (richloc->escape_on_output_p ()));
+}
+
+/* No-op implementation of "begin_group_cb" for JSON output. */
+
+static void
+json_begin_group (diagnostic_context *)
+{
+}
+
+/* Implementation of "end_group_cb" for JSON output. */
+
+static void
+json_end_group (diagnostic_context *)
+{
+ cur_group = NULL;
+ cur_children_array = NULL;
+}
+
+/* Callback for final cleanup for JSON output. */
+
+static void
+json_final_cb (diagnostic_context *)
+{
+ /* Flush the top-level array. */
+ toplevel_array->dump (stderr);
+ fprintf (stderr, "\n");
+ delete toplevel_array;
+ toplevel_array = NULL;
+}
+
+/* Set the output format for CONTEXT to FORMAT. */
+
+void
+diagnostic_output_format_init (diagnostic_context *context,
+ enum diagnostics_output_format format)
+{
+ switch (format)
+ {
+ default:
+ gcc_unreachable ();
+ case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
+ /* The default; do nothing. */
+ break;
+
+ case DIAGNOSTICS_OUTPUT_FORMAT_JSON:
+ {
+ /* Set up top-level JSON array. */
+ if (toplevel_array == NULL)
+ toplevel_array = new json::array ();
+
+ /* Override callbacks. */
+ context->begin_diagnostic = json_begin_diagnostic;
+ context->end_diagnostic = json_end_diagnostic;
+ context->begin_group_cb = json_begin_group;
+ context->end_group_cb = json_end_group;
+ context->final_cb = json_final_cb;
+ context->print_path = NULL; /* handled in json_end_diagnostic. */
+
+ /* The metadata is handled in JSON format, rather than as text. */
+ context->show_cwe = false;
+
+ /* The option is handled in JSON format, rather than as text. */
+ context->show_option_requested = false;
+
+ /* Don't colorize the text. */
+ pp_show_color (context->printer) = false;
+ }
+ break;
+ }
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* We shouldn't call json_from_expanded_location on UNKNOWN_LOCATION,
+ but verify that we handle this gracefully. */
+
+static void
+test_unknown_location ()
+{
+ test_diagnostic_context dc;
+ delete json_from_expanded_location (&dc, UNKNOWN_LOCATION);
+}
+
+/* Verify that we gracefully handle attempts to serialize bad
+ compound locations. */
+
+static void
+test_bad_endpoints ()
+{
+ location_t bad_endpoints
+ = make_location (BUILTINS_LOCATION,
+ UNKNOWN_LOCATION, UNKNOWN_LOCATION);
+
+ location_range loc_range;
+ loc_range.m_loc = bad_endpoints;
+ loc_range.m_range_display_kind = SHOW_RANGE_WITH_CARET;
+ loc_range.m_label = NULL;
+
+ test_diagnostic_context dc;
+ json::object *obj = json_from_location_range (&dc, &loc_range, 0);
+ /* We should have a "caret" value, but no "start" or "finish" values. */
+ ASSERT_TRUE (obj != NULL);
+ ASSERT_TRUE (obj->get ("caret") != NULL);
+ ASSERT_TRUE (obj->get ("start") == NULL);
+ ASSERT_TRUE (obj->get ("finish") == NULL);
+ delete obj;
+}
+
+/* Run all of the selftests within this file. */
+
+void
+diagnostic_format_json_cc_tests ()
+{
+ test_unknown_location ();
+ test_bad_endpoints ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/support/cpp/gcc/diagnostic-metadata.h b/support/cpp/gcc/diagnostic-metadata.h
new file mode 100644
index 000000000..ae59942c6
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-metadata.h
@@ -0,0 +1,42 @@
+/* Additional metadata for a diagnostic.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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_DIAGNOSTIC_METADATA_H
+#define GCC_DIAGNOSTIC_METADATA_H
+
+/* A bundle of additional metadata that can be associated with a
+ diagnostic.
+
+ Currently this only supports associating a CWE identifier with a
+ diagnostic. */
+
+class diagnostic_metadata
+{
+ public:
+ diagnostic_metadata () : m_cwe (0) {}
+
+ void add_cwe (int cwe) { m_cwe = cwe; }
+ int get_cwe () const { return m_cwe; }
+
+ private:
+ int m_cwe;
+};
+
+#endif /* ! GCC_DIAGNOSTIC_METADATA_H */
diff --git a/support/cpp/gcc/diagnostic-path.h b/support/cpp/gcc/diagnostic-path.h
new file mode 100644
index 000000000..3bd89d65a
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-path.h
@@ -0,0 +1,149 @@
+/* Paths through the code associated with a diagnostic.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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_DIAGNOSTIC_PATH_H
+#define GCC_DIAGNOSTIC_PATH_H
+
+#include "diagnostic.h" /* for ATTRIBUTE_GCC_DIAG. */
+#include "diagnostic-event-id.h"
+
+/* A diagnostic_path is an optional additional piece of metadata associated
+ with a diagnostic (via its rich_location).
+
+ It describes a sequence of events predicted by the compiler that
+ lead to the problem occurring, with their locations in the user's source,
+ and text descriptions.
+
+ For example, the following error has a 3-event path:
+
+ test.c: In function 'demo':
+ test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
+ requires a non-NULL parameter
+ 29 | PyList_Append(list, item);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~
+ 'demo': events 1-3
+ |
+ | 25 | list = PyList_New(0);
+ | | ^~~~~~~~~~~~~
+ | | |
+ | | (1) when 'PyList_New' fails, returning NULL
+ | 26 |
+ | 27 | for (i = 0; i < count; i++) {
+ | | ~~~
+ | | |
+ | | (2) when 'i < count'
+ | 28 | item = PyLong_FromLong(random());
+ | 29 | PyList_Append(list, item);
+ | | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | | |
+ | | (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
+ |
+
+ The diagnostic-printing code has consolidated the path into a single
+ run of events, since all the events are near each other and within the same
+ function; more complicated examples (such as interprocedural paths)
+ might be printed as multiple runs of events. */
+
+/* Abstract base classes, describing events within a path, and the paths
+ themselves. */
+
+/* One event within a diagnostic_path. */
+
+class diagnostic_event
+{
+ public:
+ virtual ~diagnostic_event () {}
+
+ virtual location_t get_location () const = 0;
+
+ virtual tree get_fndecl () const = 0;
+
+ /* Stack depth, so that consumers can visualizes the interprocedural
+ calls, returns, and frame nesting. */
+ virtual int get_stack_depth () const = 0;
+
+ /* Get a localized (and possibly colorized) description of this event. */
+ virtual label_text get_desc (bool can_colorize) const = 0;
+};
+
+/* Abstract base class for getting at a sequence of events. */
+
+class diagnostic_path
+{
+ public:
+ virtual ~diagnostic_path () {}
+ virtual unsigned num_events () const = 0;
+ virtual const diagnostic_event & get_event (int idx) const = 0;
+
+ bool interprocedural_p () const;
+};
+
+/* Concrete subclasses. */
+
+/* A simple implementation of diagnostic_event. */
+
+class simple_diagnostic_event : public diagnostic_event
+{
+ public:
+ simple_diagnostic_event (location_t loc, tree fndecl, int depth,
+ const char *desc);
+ ~simple_diagnostic_event ();
+
+ location_t get_location () const FINAL OVERRIDE { return m_loc; }
+ tree get_fndecl () const FINAL OVERRIDE { return m_fndecl; }
+ int get_stack_depth () const FINAL OVERRIDE { return m_depth; }
+ label_text get_desc (bool) const FINAL OVERRIDE
+ {
+ return label_text::borrow (m_desc);
+ }
+
+ private:
+ location_t m_loc;
+ tree m_fndecl;
+ int m_depth;
+ char *m_desc; // has been i18n-ed and formatted
+};
+
+/* A simple implementation of diagnostic_path, as a vector of
+ simple_diagnostic_event instances. */
+
+class simple_diagnostic_path : public diagnostic_path
+{
+ public:
+ simple_diagnostic_path (pretty_printer *event_pp)
+ : m_event_pp (event_pp) {}
+
+ unsigned num_events () const FINAL OVERRIDE;
+ const diagnostic_event & get_event (int idx) const FINAL OVERRIDE;
+
+ diagnostic_event_id_t add_event (location_t loc, tree fndecl, int depth,
+ const char *fmt, ...)
+ ATTRIBUTE_GCC_DIAG(5,6);
+
+ private:
+ auto_delete_vec<simple_diagnostic_event> m_events;
+
+ /* (for use by add_event). */
+ pretty_printer *m_event_pp;
+};
+
+extern void debug (diagnostic_path *path);
+
+#endif /* ! GCC_DIAGNOSTIC_PATH_H */
diff --git a/support/cpp/gcc/diagnostic-show-locus.cc b/support/cpp/gcc/diagnostic-show-locus.cc
new file mode 100644
index 000000000..6eafe1978
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-show-locus.cc
@@ -0,0 +1,5703 @@
+/* Diagnostic subroutines for printing source-code
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@codesourcery.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.
+
+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 "version.h"
+#include "demangle.h"
+#include "intl.h"
+#include "backtrace.h"
+#include "diagnostic.h"
+#include "diagnostic-color.h"
+#include "gcc-rich-location.h"
+#include "selftest.h"
+#include "selftest-diagnostic.h"
+#include "cpplib.h"
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
+#ifdef GWINSZ_IN_SYS_IOCTL
+# include <sys/ioctl.h>
+#endif
+
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
+/* Classes for rendering source code and diagnostics, within an
+ anonymous namespace.
+ The work is done by "class layout", which embeds and uses
+ "class colorizer" and "class layout_range" to get things done. */
+
+namespace {
+
+/* The state at a given point of the source code, assuming that we're
+ in a range: which range are we in, and whether we should draw a caret at
+ this point. */
+
+struct point_state
+{
+ int range_idx;
+ bool draw_caret_p;
+};
+
+/* A class to inject colorization codes when printing the diagnostic locus.
+
+ It has one kind of colorization for each of:
+ - normal text
+ - range 0 (the "primary location")
+ - range 1
+ - range 2
+
+ The class caches the lookup of the color codes for the above.
+
+ The class also has responsibility for tracking which of the above is
+ active, filtering out unnecessary changes. This allows
+ layout::print_source_line and layout::print_annotation_line
+ to simply request a colorization code for *every* character they print,
+ via this class, and have the filtering be done for them here. */
+
+class colorizer
+{
+ public:
+ colorizer (diagnostic_context *context,
+ diagnostic_t diagnostic_kind);
+ ~colorizer ();
+
+ void set_range (int range_idx)
+ {
+ /* Normally we emphasize the primary location, then alternate between
+ two colors for the secondary locations.
+ But if we're printing a run of events in a diagnostic path, that
+ makes no sense, so print all of them with the same colorization. */
+ if (m_diagnostic_kind == DK_DIAGNOSTIC_PATH)
+ set_state (0);
+ else
+ set_state (range_idx);
+ }
+ void set_normal_text () { set_state (STATE_NORMAL_TEXT); }
+ void set_fixit_insert () { set_state (STATE_FIXIT_INSERT); }
+ void set_fixit_delete () { set_state (STATE_FIXIT_DELETE); }
+
+ private:
+ void set_state (int state);
+ void begin_state (int state);
+ void finish_state (int state);
+ const char *get_color_by_name (const char *);
+
+ private:
+ static const int STATE_NORMAL_TEXT = -1;
+ static const int STATE_FIXIT_INSERT = -2;
+ static const int STATE_FIXIT_DELETE = -3;
+
+ diagnostic_context *m_context;
+ diagnostic_t m_diagnostic_kind;
+ int m_current_state;
+ const char *m_range1;
+ const char *m_range2;
+ const char *m_fixit_insert;
+ const char *m_fixit_delete;
+ const char *m_stop_color;
+};
+
+/* In order to handle multibyte sources properly, all of this logic needs to be
+ aware of the distinction between the number of bytes and the number of
+ display columns occupied by a character, which are not the same for non-ASCII
+ characters. For example, the Unicode pi symbol, U+03C0, is encoded in UTF-8
+ as "\xcf\x80", and thus occupies 2 bytes of space while only occupying 1
+ display column when it is output. A typical emoji, such as U+1F602 (in
+ UTF-8, "\xf0\x9f\x98\x82"), requires 4 bytes and has a display width of 2.
+
+ The below example line, which is also used for selftests below, shows how the
+ display column and byte column are related:
+
+ 0000000001111111111222222 display
+ 1234567890123456789012345 columns
+ SS_foo = P_bar.SS_fieldP;
+ 0000000111111111222222223 byte
+ 1356789012456789134567891 columns
+
+ Here SS represents the two display columns for the U+1F602 emoji, and P
+ represents the one display column for the U+03C0 pi symbol. As an example, a
+ diagnostic pointing to the final P on this line is at byte column 29 and
+ display column 24. This reflects the fact that the three extended characters
+ before the final P occupy cumulatively 5 more bytes than they do display
+ columns (a difference of 2 for each of the two SSs, and one for the other P).
+
+ One or the other of the two column units is more useful depending on the
+ context. For instance, in order to output the caret at the correct location,
+ we need to count display columns; in order to colorize a source line, we need
+ to count the bytes. All locations are provided to us as byte counts, which
+ we augment with the display column on demand so that it can be used when
+ needed. This is not the most efficient way to do things since it requires
+ looping over the whole line each time, but it should be fine for the purpose
+ of outputting diagnostics.
+
+ In order to keep straight which units (byte or display) are in use at a
+ given time, the following enum lets us specify that explicitly. */
+
+enum column_unit {
+ /* Measured in raw bytes. */
+ CU_BYTES = 0,
+
+ /* Measured in display units. */
+ CU_DISPLAY_COLS,
+
+ /* For arrays indexed by column_unit. */
+ CU_NUM_UNITS
+};
+
+/* Utility class to augment an exploc with the corresponding display column. */
+
+class exploc_with_display_col : public expanded_location
+{
+ public:
+ exploc_with_display_col (const expanded_location &exploc,
+ const cpp_char_column_policy &policy,
+ enum location_aspect aspect)
+ : expanded_location (exploc),
+ m_display_col (location_compute_display_column (exploc, policy))
+ {
+ if (exploc.column > 0)
+ {
+ /* m_display_col is now the final column of the byte.
+ If escaping has happened, we may want the first column instead. */
+ if (aspect != LOCATION_ASPECT_FINISH)
+ {
+ expanded_location prev_exploc (exploc);
+ prev_exploc.column--;
+ int prev_display_col
+ = (location_compute_display_column (prev_exploc, policy));
+ m_display_col = prev_display_col + 1;
+ }
+ }
+ }
+
+ int m_display_col;
+};
+
+
+/* A point within a layout_range; similar to an exploc_with_display_col,
+ but after filtering on file. */
+
+class layout_point
+{
+ public:
+ layout_point (const exploc_with_display_col &exploc)
+ : m_line (exploc.line)
+ {
+ m_columns[CU_BYTES] = exploc.column;
+ m_columns[CU_DISPLAY_COLS] = exploc.m_display_col;
+ }
+
+ linenum_type m_line;
+ int m_columns[CU_NUM_UNITS];
+};
+
+/* A class for use by "class layout" below: a filtered location_range. */
+
+class layout_range
+{
+ public:
+ layout_range (const exploc_with_display_col &start_exploc,
+ const exploc_with_display_col &finish_exploc,
+ enum range_display_kind range_display_kind,
+ const exploc_with_display_col &caret_exploc,
+ unsigned original_idx,
+ const range_label *label);
+
+ bool contains_point (linenum_type row, int column,
+ enum column_unit col_unit) const;
+ bool intersects_line_p (linenum_type row) const;
+
+ layout_point m_start;
+ layout_point m_finish;
+ enum range_display_kind m_range_display_kind;
+ layout_point m_caret;
+ unsigned m_original_idx;
+ const range_label *m_label;
+};
+
+/* A struct for use by layout::print_source_line for telling
+ layout::print_annotation_line the extents of the source line that
+ it printed, so that underlines can be clipped appropriately. Units
+ are 1-based display columns. */
+
+struct line_bounds
+{
+ int m_first_non_ws_disp_col;
+ int m_last_non_ws_disp_col;
+
+ line_bounds ()
+ {
+ m_first_non_ws_disp_col = INT_MAX;
+ m_last_non_ws_disp_col = 0;
+ }
+};
+
+/* A range of contiguous source lines within a layout (e.g. "lines 5-10"
+ or "line 23"). During the layout ctor, layout::calculate_line_spans
+ splits the pertinent source lines into a list of disjoint line_span
+ instances (e.g. lines 5-10, lines 15-20, line 23). */
+
+class line_span
+{
+public:
+ line_span (linenum_type first_line, linenum_type last_line)
+ : m_first_line (first_line), m_last_line (last_line)
+ {
+ gcc_assert (first_line <= last_line);
+ }
+ linenum_type get_first_line () const { return m_first_line; }
+ linenum_type get_last_line () const { return m_last_line; }
+
+ bool contains_line_p (linenum_type line) const
+ {
+ return line >= m_first_line && line <= m_last_line;
+ }
+
+ static int comparator (const void *p1, const void *p2)
+ {
+ const line_span *ls1 = (const line_span *)p1;
+ const line_span *ls2 = (const line_span *)p2;
+ int first_line_cmp = compare (ls1->m_first_line, ls2->m_first_line);
+ if (first_line_cmp)
+ return first_line_cmp;
+ return compare (ls1->m_last_line, ls2->m_last_line);
+ }
+
+ linenum_type m_first_line;
+ linenum_type m_last_line;
+};
+
+#if CHECKING_P
+
+/* Selftests for line_span. */
+
+static void
+test_line_span ()
+{
+ line_span line_one (1, 1);
+ ASSERT_EQ (1, line_one.get_first_line ());
+ ASSERT_EQ (1, line_one.get_last_line ());
+ ASSERT_FALSE (line_one.contains_line_p (0));
+ ASSERT_TRUE (line_one.contains_line_p (1));
+ ASSERT_FALSE (line_one.contains_line_p (2));
+
+ line_span lines_1_to_3 (1, 3);
+ ASSERT_EQ (1, lines_1_to_3.get_first_line ());
+ ASSERT_EQ (3, lines_1_to_3.get_last_line ());
+ ASSERT_TRUE (lines_1_to_3.contains_line_p (1));
+ ASSERT_TRUE (lines_1_to_3.contains_line_p (3));
+
+ ASSERT_EQ (0, line_span::comparator (&line_one, &line_one));
+ ASSERT_GT (line_span::comparator (&lines_1_to_3, &line_one), 0);
+ ASSERT_LT (line_span::comparator (&line_one, &lines_1_to_3), 0);
+
+ /* A linenum > 2^31. */
+ const linenum_type LARGEST_LINE = 0xffffffff;
+ line_span largest_line (LARGEST_LINE, LARGEST_LINE);
+ ASSERT_EQ (LARGEST_LINE, largest_line.get_first_line ());
+ ASSERT_EQ (LARGEST_LINE, largest_line.get_last_line ());
+
+ ASSERT_GT (line_span::comparator (&largest_line, &line_one), 0);
+ ASSERT_LT (line_span::comparator (&line_one, &largest_line), 0);
+}
+
+#endif /* #if CHECKING_P */
+
+/* A bundle of information containing how to print unicode
+ characters and bytes when quoting source code.
+
+ Provides a unified place to support escaping some subset
+ of characters to some format.
+
+ Extends char_column_policy; printing is split out to avoid
+ libcpp having to know about pretty_printer. */
+
+struct char_display_policy : public cpp_char_column_policy
+{
+ public:
+ char_display_policy (int tabstop,
+ int (*width_cb) (cppchar_t c),
+ void (*print_cb) (pretty_printer *pp,
+ const cpp_decoded_char &cp))
+ : cpp_char_column_policy (tabstop, width_cb),
+ m_print_cb (print_cb)
+ {
+ }
+
+ void (*m_print_cb) (pretty_printer *pp,
+ const cpp_decoded_char &cp);
+};
+
+/* A class to control the overall layout when printing a diagnostic.
+
+ The layout is determined within the constructor.
+ It is then printed by repeatedly calling the "print_source_line",
+ "print_annotation_line" and "print_any_fixits" methods.
+
+ We assume we have disjoint ranges. */
+
+class layout
+{
+ public:
+ layout (diagnostic_context *context,
+ rich_location *richloc,
+ diagnostic_t diagnostic_kind);
+
+ bool maybe_add_location_range (const location_range *loc_range,
+ unsigned original_idx,
+ bool restrict_to_current_line_spans);
+
+ int get_num_line_spans () const { return m_line_spans.length (); }
+ const line_span *get_line_span (int idx) const { return &m_line_spans[idx]; }
+
+ int get_linenum_width () const { return m_linenum_width; }
+ int get_x_offset_display () const { return m_x_offset_display; }
+
+ void print_gap_in_line_numbering ();
+ bool print_heading_for_line_span_index_p (int line_span_idx) const;
+
+ expanded_location get_expanded_location (const line_span *) const;
+
+ void print_line (linenum_type row);
+
+ void on_bad_codepoint (const char *ptr, cppchar_t ch, size_t ch_sz);
+
+ private:
+ bool will_show_line_p (linenum_type row) const;
+ void print_leading_fixits (linenum_type row);
+ line_bounds print_source_line (linenum_type row, const char *line,
+ int line_bytes);
+ bool should_print_annotation_line_p (linenum_type row) const;
+ void start_annotation_line (char margin_char = ' ') const;
+ void print_annotation_line (linenum_type row, const line_bounds lbounds);
+ void print_any_labels (linenum_type row);
+ void print_trailing_fixits (linenum_type row);
+
+ bool annotation_line_showed_range_p (linenum_type line, int start_column,
+ int finish_column) const;
+ void show_ruler (int max_column) const;
+
+ bool validate_fixit_hint_p (const fixit_hint *hint);
+
+ void calculate_line_spans ();
+ void calculate_linenum_width ();
+ void calculate_x_offset_display ();
+
+ void print_newline ();
+
+ bool
+ get_state_at_point (/* Inputs. */
+ linenum_type row, int column,
+ int first_non_ws, int last_non_ws,
+ enum column_unit col_unit,
+ /* Outputs. */
+ point_state *out_state);
+
+ int
+ get_x_bound_for_row (linenum_type row, int caret_column,
+ int last_non_ws);
+
+ void
+ move_to_column (int *column, int dest_column, bool add_left_margin);
+
+ private:
+ diagnostic_context *m_context;
+ pretty_printer *m_pp;
+ char_display_policy m_policy;
+ location_t m_primary_loc;
+ exploc_with_display_col m_exploc;
+ colorizer m_colorizer;
+ bool m_colorize_source_p;
+ bool m_show_labels_p;
+ bool m_show_line_numbers_p;
+ bool m_diagnostic_path_p;
+ auto_vec <layout_range> m_layout_ranges;
+ auto_vec <const fixit_hint *> m_fixit_hints;
+ auto_vec <line_span> m_line_spans;
+ int m_linenum_width;
+ int m_x_offset_display;
+ bool m_escape_on_output;
+};
+
+/* Implementation of "class colorizer". */
+
+/* The constructor for "colorizer". Lookup and store color codes for the
+ different kinds of things we might need to print. */
+
+colorizer::colorizer (diagnostic_context *context,
+ diagnostic_t diagnostic_kind) :
+ m_context (context),
+ m_diagnostic_kind (diagnostic_kind),
+ m_current_state (STATE_NORMAL_TEXT)
+{
+ m_range1 = get_color_by_name ("range1");
+ m_range2 = get_color_by_name ("range2");
+ m_fixit_insert = get_color_by_name ("fixit-insert");
+ m_fixit_delete = get_color_by_name ("fixit-delete");
+ m_stop_color = colorize_stop (pp_show_color (context->printer));
+}
+
+/* The destructor for "colorize". If colorization is on, print a code to
+ turn it off. */
+
+colorizer::~colorizer ()
+{
+ finish_state (m_current_state);
+}
+
+/* Update state, printing color codes if necessary if there's a state
+ change. */
+
+void
+colorizer::set_state (int new_state)
+{
+ if (m_current_state != new_state)
+ {
+ finish_state (m_current_state);
+ m_current_state = new_state;
+ begin_state (new_state);
+ }
+}
+
+/* Turn on any colorization for STATE. */
+
+void
+colorizer::begin_state (int state)
+{
+ switch (state)
+ {
+ case STATE_NORMAL_TEXT:
+ break;
+
+ case STATE_FIXIT_INSERT:
+ pp_string (m_context->printer, m_fixit_insert);
+ break;
+
+ case STATE_FIXIT_DELETE:
+ pp_string (m_context->printer, m_fixit_delete);
+ break;
+
+ case 0:
+ /* Make range 0 be the same color as the "kind" text
+ (error vs warning vs note). */
+ pp_string
+ (m_context->printer,
+ colorize_start (pp_show_color (m_context->printer),
+ diagnostic_get_color_for_kind (m_diagnostic_kind)));
+ break;
+
+ case 1:
+ pp_string (m_context->printer, m_range1);
+ break;
+
+ case 2:
+ pp_string (m_context->printer, m_range2);
+ break;
+
+ default:
+ /* For ranges beyond 2, alternate between color 1 and color 2. */
+ {
+ gcc_assert (state > 2);
+ pp_string (m_context->printer,
+ state % 2 ? m_range1 : m_range2);
+ }
+ break;
+ }
+}
+
+/* Turn off any colorization for STATE. */
+
+void
+colorizer::finish_state (int state)
+{
+ if (state != STATE_NORMAL_TEXT)
+ pp_string (m_context->printer, m_stop_color);
+}
+
+/* Get the color code for NAME (or the empty string if
+ colorization is disabled). */
+
+const char *
+colorizer::get_color_by_name (const char *name)
+{
+ return colorize_start (pp_show_color (m_context->printer), name);
+}
+
+/* Implementation of class layout_range. */
+
+/* The constructor for class layout_range.
+ Initialize various layout_point fields from expanded_location
+ equivalents; we've already filtered on file. */
+
+layout_range::layout_range (const exploc_with_display_col &start_exploc,
+ const exploc_with_display_col &finish_exploc,
+ enum range_display_kind range_display_kind,
+ const exploc_with_display_col &caret_exploc,
+ unsigned original_idx,
+ const range_label *label)
+: m_start (start_exploc),
+ m_finish (finish_exploc),
+ m_range_display_kind (range_display_kind),
+ m_caret (caret_exploc),
+ m_original_idx (original_idx),
+ m_label (label)
+{
+}
+
+/* Is (column, row) within the given range?
+ We've already filtered on the file.
+
+ Ranges are closed (both limits are within the range).
+
+ Example A: a single-line range:
+ start: (col=22, line=2)
+ finish: (col=38, line=2)
+
+ |00000011111111112222222222333333333344444444444
+ |34567890123456789012345678901234567890123456789
+--+-----------------------------------------------
+01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+02|bbbbbbbbbbbbbbbbbbbSwwwwwwwwwwwwwwwFaaaaaaaaaaa
+03|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+ Example B: a multiline range with
+ start: (col=14, line=3)
+ finish: (col=08, line=5)
+
+ |00000011111111112222222222333333333344444444444
+ |34567890123456789012345678901234567890123456789
+--+-----------------------------------------------
+01|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+02|bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+03|bbbbbbbbbbbSwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+04|wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+05|wwwwwFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+06|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+--+-----------------------------------------------
+
+ Legend:
+ - 'b' indicates a point *before* the range
+ - 'S' indicates the start of the range
+ - 'w' indicates a point within the range
+ - 'F' indicates the finish of the range (which is
+ within it).
+ - 'a' indicates a subsequent point *after* the range.
+
+ COL_UNIT controls whether we check the byte column or
+ the display column; one or the other is more convenient
+ depending on the context. */
+
+bool
+layout_range::contains_point (linenum_type row, int column,
+ enum column_unit col_unit) const
+{
+ gcc_assert (m_start.m_line <= m_finish.m_line);
+ /* ...but the equivalent isn't true for the columns;
+ consider example B in the comment above. */
+
+ if (row < m_start.m_line)
+ /* Points before the first line of the range are
+ outside it (corresponding to line 01 in example A
+ and lines 01 and 02 in example B above). */
+ return false;
+
+ if (row == m_start.m_line)
+ /* On same line as start of range (corresponding
+ to line 02 in example A and line 03 in example B). */
+ {
+ if (column < m_start.m_columns[col_unit])
+ /* Points on the starting line of the range, but
+ before the column in which it begins. */
+ return false;
+
+ if (row < m_finish.m_line)
+ /* This is a multiline range; the point
+ is within it (corresponds to line 03 in example B
+ from column 14 onwards) */
+ return true;
+ else
+ {
+ /* This is a single-line range. */
+ gcc_assert (row == m_finish.m_line);
+ return column <= m_finish.m_columns[col_unit];
+ }
+ }
+
+ /* The point is in a line beyond that containing the
+ start of the range: lines 03 onwards in example A,
+ and lines 04 onwards in example B. */
+ gcc_assert (row > m_start.m_line);
+
+ if (row > m_finish.m_line)
+ /* The point is beyond the final line of the range
+ (lines 03 onwards in example A, and lines 06 onwards
+ in example B). */
+ return false;
+
+ if (row < m_finish.m_line)
+ {
+ /* The point is in a line that's fully within a multiline
+ range (e.g. line 04 in example B). */
+ gcc_assert (m_start.m_line < m_finish.m_line);
+ return true;
+ }
+
+ gcc_assert (row == m_finish.m_line);
+
+ return column <= m_finish.m_columns[col_unit];
+}
+
+/* Does this layout_range contain any part of line ROW? */
+
+bool
+layout_range::intersects_line_p (linenum_type row) const
+{
+ gcc_assert (m_start.m_line <= m_finish.m_line);
+ if (row < m_start.m_line)
+ return false;
+ if (row > m_finish.m_line)
+ return false;
+ return true;
+}
+
+#if CHECKING_P
+
+/* Default for when we don't care what the tab expansion is set to. */
+static const int def_tabstop = 8;
+
+static cpp_char_column_policy def_policy ()
+{
+ return cpp_char_column_policy (def_tabstop, cpp_wcwidth);
+}
+
+/* Create some expanded locations for testing layout_range. The filename
+ member of the explocs is set to the empty string. This member will only be
+ inspected by the calls to location_compute_display_column() made from the
+ layout_point constructors. That function will check for an empty filename
+ argument and not attempt to open it, rather treating the non-existent data
+ as if the display width were the same as the byte count. Tests exercising a
+ real difference between byte count and display width are performed later,
+ e.g. in test_diagnostic_show_locus_one_liner_utf8(). */
+
+static layout_range
+make_range (int start_line, int start_col, int end_line, int end_col)
+{
+ const expanded_location start_exploc
+ = {"", start_line, start_col, NULL, false};
+ const expanded_location finish_exploc
+ = {"", end_line, end_col, NULL, false};
+ return layout_range (exploc_with_display_col (start_exploc, def_policy (),
+ LOCATION_ASPECT_START),
+ exploc_with_display_col (finish_exploc, def_policy (),
+ LOCATION_ASPECT_FINISH),
+ SHOW_RANGE_WITHOUT_CARET,
+ exploc_with_display_col (start_exploc, def_policy (),
+ LOCATION_ASPECT_CARET),
+ 0, NULL);
+}
+
+/* Selftests for layout_range::contains_point and
+ layout_range::intersects_line_p. */
+
+/* Selftest for layout_range, where the layout_range
+ is a range with start==end i.e. a single point. */
+
+static void
+test_layout_range_for_single_point ()
+{
+ layout_range point = make_range (7, 10, 7, 10);
+
+ /* Tests for layout_range::contains_point. */
+
+ for (int i = 0; i != CU_NUM_UNITS; ++i)
+ {
+ const enum column_unit col_unit = (enum column_unit) i;
+
+ /* Before the line. */
+ ASSERT_FALSE (point.contains_point (6, 1, col_unit));
+
+ /* On the line, but before start. */
+ ASSERT_FALSE (point.contains_point (7, 9, col_unit));
+
+ /* At the point. */
+ ASSERT_TRUE (point.contains_point (7, 10, col_unit));
+
+ /* On the line, after the point. */
+ ASSERT_FALSE (point.contains_point (7, 11, col_unit));
+
+ /* After the line. */
+ ASSERT_FALSE (point.contains_point (8, 1, col_unit));
+ }
+
+ /* Tests for layout_range::intersects_line_p. */
+ ASSERT_FALSE (point.intersects_line_p (6));
+ ASSERT_TRUE (point.intersects_line_p (7));
+ ASSERT_FALSE (point.intersects_line_p (8));
+}
+
+/* Selftest for layout_range, where the layout_range
+ is the single-line range shown as "Example A" above. */
+
+static void
+test_layout_range_for_single_line ()
+{
+ layout_range example_a = make_range (2, 22, 2, 38);
+
+ /* Tests for layout_range::contains_point. */
+
+ for (int i = 0; i != CU_NUM_UNITS; ++i)
+ {
+ const enum column_unit col_unit = (enum column_unit) i;
+
+ /* Before the line. */
+ ASSERT_FALSE (example_a.contains_point (1, 1, col_unit));
+
+ /* On the line, but before start. */
+ ASSERT_FALSE (example_a.contains_point (2, 21, col_unit));
+
+ /* On the line, at the start. */
+ ASSERT_TRUE (example_a.contains_point (2, 22, col_unit));
+
+ /* On the line, within the range. */
+ ASSERT_TRUE (example_a.contains_point (2, 23, col_unit));
+
+ /* On the line, at the end. */
+ ASSERT_TRUE (example_a.contains_point (2, 38, col_unit));
+
+ /* On the line, after the end. */
+ ASSERT_FALSE (example_a.contains_point (2, 39, col_unit));
+
+ /* After the line. */
+ ASSERT_FALSE (example_a.contains_point (2, 39, col_unit));
+ }
+
+ /* Tests for layout_range::intersects_line_p. */
+ ASSERT_FALSE (example_a.intersects_line_p (1));
+ ASSERT_TRUE (example_a.intersects_line_p (2));
+ ASSERT_FALSE (example_a.intersects_line_p (3));
+}
+
+/* Selftest for layout_range, where the layout_range
+ is the multi-line range shown as "Example B" above. */
+
+static void
+test_layout_range_for_multiple_lines ()
+{
+ layout_range example_b = make_range (3, 14, 5, 8);
+
+ /* Tests for layout_range::contains_point. */
+
+ for (int i = 0; i != CU_NUM_UNITS; ++i)
+ {
+ const enum column_unit col_unit = (enum column_unit) i;
+
+ /* Before first line. */
+ ASSERT_FALSE (example_b.contains_point (1, 1, col_unit));
+
+ /* On the first line, but before start. */
+ ASSERT_FALSE (example_b.contains_point (3, 13, col_unit));
+
+ /* At the start. */
+ ASSERT_TRUE (example_b.contains_point (3, 14, col_unit));
+
+ /* On the first line, within the range. */
+ ASSERT_TRUE (example_b.contains_point (3, 15, col_unit));
+
+ /* On an interior line.
+ The column number should not matter; try various boundary
+ values. */
+ ASSERT_TRUE (example_b.contains_point (4, 1, col_unit));
+ ASSERT_TRUE (example_b.contains_point (4, 7, col_unit));
+ ASSERT_TRUE (example_b.contains_point (4, 8, col_unit));
+ ASSERT_TRUE (example_b.contains_point (4, 9, col_unit));
+ ASSERT_TRUE (example_b.contains_point (4, 13, col_unit));
+ ASSERT_TRUE (example_b.contains_point (4, 14, col_unit));
+ ASSERT_TRUE (example_b.contains_point (4, 15, col_unit));
+
+ /* On the final line, before the end. */
+ ASSERT_TRUE (example_b.contains_point (5, 7, col_unit));
+
+ /* On the final line, at the end. */
+ ASSERT_TRUE (example_b.contains_point (5, 8, col_unit));
+
+ /* On the final line, after the end. */
+ ASSERT_FALSE (example_b.contains_point (5, 9, col_unit));
+
+ /* After the line. */
+ ASSERT_FALSE (example_b.contains_point (6, 1, col_unit));
+ }
+
+ /* Tests for layout_range::intersects_line_p. */
+ ASSERT_FALSE (example_b.intersects_line_p (2));
+ ASSERT_TRUE (example_b.intersects_line_p (3));
+ ASSERT_TRUE (example_b.intersects_line_p (4));
+ ASSERT_TRUE (example_b.intersects_line_p (5));
+ ASSERT_FALSE (example_b.intersects_line_p (6));
+}
+
+#endif /* #if CHECKING_P */
+
+/* Given a source line LINE of length LINE_BYTES bytes, determine the length
+ (still in bytes, not display cols) without any trailing whitespace. */
+
+static int
+get_line_bytes_without_trailing_whitespace (const char *line, int line_bytes)
+{
+ int result = line_bytes;
+ while (result > 0)
+ {
+ char ch = line[result - 1];
+ if (ch == ' ' || ch == '\t' || ch == '\r')
+ result--;
+ else
+ break;
+ }
+ gcc_assert (result >= 0);
+ gcc_assert (result <= line_bytes);
+ gcc_assert (result == 0 ||
+ (line[result - 1] != ' '
+ && line[result -1] != '\t'
+ && line[result -1] != '\r'));
+ return result;
+}
+
+#if CHECKING_P
+
+/* A helper function for testing get_line_bytes_without_trailing_whitespace. */
+
+static void
+assert_eq (const char *line, int expected_bytes)
+{
+ int actual_value
+ = get_line_bytes_without_trailing_whitespace (line, strlen (line));
+ ASSERT_EQ (actual_value, expected_bytes);
+}
+
+/* Verify that get_line_bytes_without_trailing_whitespace is sane for
+ various inputs. It is not required to handle newlines. */
+
+static void
+test_get_line_bytes_without_trailing_whitespace ()
+{
+ assert_eq ("", 0);
+ assert_eq (" ", 0);
+ assert_eq ("\t", 0);
+ assert_eq ("\r", 0);
+ assert_eq ("hello world", 11);
+ assert_eq ("hello world ", 11);
+ assert_eq ("hello world \t\t ", 11);
+ assert_eq ("hello world\r", 11);
+}
+
+#endif /* #if CHECKING_P */
+
+/* Helper function for layout's ctor, for sanitizing locations relative
+ to the primary location within a diagnostic.
+
+ Compare LOC_A and LOC_B to see if it makes sense to print underlines
+ connecting their expanded locations. Doing so is only guaranteed to
+ make sense if the locations share the same macro expansion "history"
+ i.e. they can be traced through the same macro expansions, eventually
+ reaching an ordinary map.
+
+ This may be too strong a condition, but it effectively sanitizes
+ PR c++/70105, which has an example of printing an expression where the
+ final location of the expression is in a different macro, which
+ erroneously was leading to hundreds of lines of irrelevant source
+ being printed. */
+
+static bool
+compatible_locations_p (location_t loc_a, location_t loc_b)
+{
+ if (IS_ADHOC_LOC (loc_a))
+ loc_a = get_location_from_adhoc_loc (line_table, loc_a);
+ if (IS_ADHOC_LOC (loc_b))
+ loc_b = get_location_from_adhoc_loc (line_table, loc_b);
+
+ /* If either location is one of the special locations outside of a
+ linemap, they are only compatible if they are equal. */
+ if (loc_a < RESERVED_LOCATION_COUNT
+ || loc_b < RESERVED_LOCATION_COUNT)
+ return loc_a == loc_b;
+
+ const line_map *map_a = linemap_lookup (line_table, loc_a);
+ linemap_assert (map_a);
+
+ const line_map *map_b = linemap_lookup (line_table, loc_b);
+ linemap_assert (map_b);
+
+ /* Are they within the same map? */
+ if (map_a == map_b)
+ {
+ /* Are both within the same macro expansion? */
+ if (linemap_macro_expansion_map_p (map_a))
+ {
+ /* If so, then they're only compatible if either both are
+ from the macro definition, or both from the macro arguments. */
+ bool loc_a_from_defn
+ = linemap_location_from_macro_definition_p (line_table, loc_a);
+ bool loc_b_from_defn
+ = linemap_location_from_macro_definition_p (line_table, loc_b);
+ if (loc_a_from_defn != loc_b_from_defn)
+ return false;
+
+ /* Expand each location towards the spelling location, and
+ recurse. */
+ const line_map_macro *macro_map = linemap_check_macro (map_a);
+ location_t loc_a_toward_spelling
+ = linemap_macro_map_loc_unwind_toward_spelling (line_table,
+ macro_map,
+ loc_a);
+ location_t loc_b_toward_spelling
+ = linemap_macro_map_loc_unwind_toward_spelling (line_table,
+ macro_map,
+ loc_b);
+ return compatible_locations_p (loc_a_toward_spelling,
+ loc_b_toward_spelling);
+ }
+
+ /* Otherwise they are within the same ordinary map. */
+ return true;
+ }
+ else
+ {
+ /* Within different maps. */
+
+ /* If either is within a macro expansion, they are incompatible. */
+ if (linemap_macro_expansion_map_p (map_a)
+ || linemap_macro_expansion_map_p (map_b))
+ return false;
+
+ /* Within two different ordinary maps; they are compatible iff they
+ are in the same file. */
+ const line_map_ordinary *ord_map_a = linemap_check_ordinary (map_a);
+ const line_map_ordinary *ord_map_b = linemap_check_ordinary (map_b);
+ return ord_map_a->to_file == ord_map_b->to_file;
+ }
+}
+
+/* Comparator for sorting fix-it hints. */
+
+static int
+fixit_cmp (const void *p_a, const void *p_b)
+{
+ const fixit_hint * hint_a = *static_cast<const fixit_hint * const *> (p_a);
+ const fixit_hint * hint_b = *static_cast<const fixit_hint * const *> (p_b);
+ return hint_a->get_start_loc () - hint_b->get_start_loc ();
+}
+
+/* Callbacks for use when not escaping the source. */
+
+/* The default callback for char_column_policy::m_width_cb is cpp_wcwidth. */
+
+/* Callback for char_display_policy::m_print_cb for printing source chars
+ when not escaping the source. */
+
+static void
+default_print_decoded_ch (pretty_printer *pp,
+ const cpp_decoded_char &decoded_ch)
+{
+ for (const char *ptr = decoded_ch.m_start_byte;
+ ptr != decoded_ch.m_next_byte; ptr++)
+ {
+ if (*ptr == '\0' || *ptr == '\r')
+ {
+ pp_space (pp);
+ continue;
+ }
+
+ pp_character (pp, *ptr);
+ }
+}
+
+/* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_BYTES. */
+
+static const int width_per_escaped_byte = 4;
+
+/* Callback for char_column_policy::m_width_cb for determining the
+ display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES. */
+
+static int
+escape_as_bytes_width (cppchar_t ch)
+{
+ if (ch < 0x80 && ISPRINT (ch))
+ return cpp_wcwidth (ch);
+ else
+ {
+ if (ch <= 0x7F) return 1 * width_per_escaped_byte;
+ if (ch <= 0x7FF) return 2 * width_per_escaped_byte;
+ if (ch <= 0xFFFF) return 3 * width_per_escaped_byte;
+ return 4 * width_per_escaped_byte;
+ }
+}
+
+/* Callback for char_display_policy::m_print_cb for printing source chars
+ when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES. */
+
+static void
+escape_as_bytes_print (pretty_printer *pp,
+ const cpp_decoded_char &decoded_ch)
+{
+ if (!decoded_ch.m_valid_ch)
+ {
+ for (const char *iter = decoded_ch.m_start_byte;
+ iter != decoded_ch.m_next_byte; ++iter)
+ {
+ char buf[16];
+ sprintf (buf, "<%02x>", (unsigned char)*iter);
+ pp_string (pp, buf);
+ }
+ return;
+ }
+
+ cppchar_t ch = decoded_ch.m_ch;
+ if (ch < 0x80 && ISPRINT (ch))
+ pp_character (pp, ch);
+ else
+ {
+ for (const char *iter = decoded_ch.m_start_byte;
+ iter < decoded_ch.m_next_byte; ++iter)
+ {
+ char buf[16];
+ sprintf (buf, "<%02x>", (unsigned char)*iter);
+ pp_string (pp, buf);
+ }
+ }
+}
+
+/* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE. */
+
+/* Callback for char_column_policy::m_width_cb for determining the
+ display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE. */
+
+static int
+escape_as_unicode_width (cppchar_t ch)
+{
+ if (ch < 0x80 && ISPRINT (ch))
+ return cpp_wcwidth (ch);
+ else
+ {
+ // Width of "<U+%04x>"
+ if (ch > 0xfffff)
+ return 10;
+ else if (ch > 0xffff)
+ return 9;
+ else
+ return 8;
+ }
+}
+
+/* Callback for char_display_policy::m_print_cb for printing source chars
+ when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE. */
+
+static void
+escape_as_unicode_print (pretty_printer *pp,
+ const cpp_decoded_char &decoded_ch)
+{
+ if (!decoded_ch.m_valid_ch)
+ {
+ escape_as_bytes_print (pp, decoded_ch);
+ return;
+ }
+
+ cppchar_t ch = decoded_ch.m_ch;
+ if (ch < 0x80 && ISPRINT (ch))
+ pp_character (pp, ch);
+ else
+ {
+ char buf[16];
+ sprintf (buf, "<U+%04X>", ch);
+ pp_string (pp, buf);
+ }
+}
+
+/* Populate a char_display_policy based on DC and RICHLOC. */
+
+static char_display_policy
+make_policy (const diagnostic_context &dc,
+ const rich_location &richloc)
+{
+ /* The default is to not escape non-ASCII bytes. */
+ char_display_policy result
+ (dc.tabstop, cpp_wcwidth, default_print_decoded_ch);
+
+ /* If the diagnostic suggests escaping non-ASCII bytes, then
+ use policy from user-supplied options. */
+ if (richloc.escape_on_output_p ())
+ {
+ result.m_undecoded_byte_width = width_per_escaped_byte;
+ switch (dc.escape_format)
+ {
+ default:
+ gcc_unreachable ();
+ case DIAGNOSTICS_ESCAPE_FORMAT_UNICODE:
+ result.m_width_cb = escape_as_unicode_width;
+ result.m_print_cb = escape_as_unicode_print;
+ break;
+ case DIAGNOSTICS_ESCAPE_FORMAT_BYTES:
+ result.m_width_cb = escape_as_bytes_width;
+ result.m_print_cb = escape_as_bytes_print;
+ break;
+ }
+ }
+
+ return result;
+}
+
+/* Implementation of class layout. */
+
+/* Constructor for class layout.
+
+ Filter the ranges from the rich_location to those that we can
+ sanely print, populating m_layout_ranges and m_fixit_hints.
+ Determine the range of lines that we will print, splitting them
+ up into an ordered list of disjoint spans of contiguous line numbers.
+ Determine m_x_offset_display, to ensure that the primary caret
+ will fit within the max_width provided by the diagnostic_context. */
+
+layout::layout (diagnostic_context * context,
+ rich_location *richloc,
+ diagnostic_t diagnostic_kind)
+: m_context (context),
+ m_pp (context->printer),
+ m_policy (make_policy (*context, *richloc)),
+ m_primary_loc (richloc->get_range (0)->m_loc),
+ m_exploc (richloc->get_expanded_location (0), m_policy,
+ LOCATION_ASPECT_CARET),
+ m_colorizer (context, diagnostic_kind),
+ m_colorize_source_p (context->colorize_source_p),
+ m_show_labels_p (context->show_labels_p),
+ m_show_line_numbers_p (context->show_line_numbers_p),
+ m_diagnostic_path_p (diagnostic_kind == DK_DIAGNOSTIC_PATH),
+ m_layout_ranges (richloc->get_num_locations ()),
+ m_fixit_hints (richloc->get_num_fixit_hints ()),
+ m_line_spans (1 + richloc->get_num_locations ()),
+ m_linenum_width (0),
+ m_x_offset_display (0),
+ m_escape_on_output (richloc->escape_on_output_p ())
+{
+ for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
+ {
+ /* This diagnostic printer can only cope with "sufficiently sane" ranges.
+ Ignore any ranges that are awkward to handle. */
+ const location_range *loc_range = richloc->get_range (idx);
+ maybe_add_location_range (loc_range, idx, false);
+ }
+
+ /* Populate m_fixit_hints, filtering to only those that are in the
+ same file. */
+ for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
+ {
+ const fixit_hint *hint = richloc->get_fixit_hint (i);
+ if (validate_fixit_hint_p (hint))
+ m_fixit_hints.safe_push (hint);
+ }
+
+ /* Sort m_fixit_hints. */
+ m_fixit_hints.qsort (fixit_cmp);
+
+ /* Populate the indicated members. */
+ calculate_line_spans ();
+ calculate_linenum_width ();
+ calculate_x_offset_display ();
+
+ if (context->show_ruler_p)
+ show_ruler (m_x_offset_display + m_context->caret_max_width);
+}
+
+
+/* Attempt to add LOC_RANGE to m_layout_ranges, filtering them to
+ those that we can sanely print.
+
+ ORIGINAL_IDX is the index of LOC_RANGE within its rich_location,
+ (for use as extrinsic state by label ranges FIXME).
+
+ If RESTRICT_TO_CURRENT_LINE_SPANS is true, then LOC_RANGE is also
+ filtered against this layout instance's current line spans: it
+ will only be added if the location is fully within the lines
+ already specified by other locations.
+
+ Return true iff LOC_RANGE was added. */
+
+bool
+layout::maybe_add_location_range (const location_range *loc_range,
+ unsigned original_idx,
+ bool restrict_to_current_line_spans)
+{
+ gcc_assert (loc_range);
+
+ /* Split the "range" into caret and range information. */
+ source_range src_range = get_range_from_loc (line_table, loc_range->m_loc);
+
+ /* Expand the various locations. */
+ expanded_location start
+ = linemap_client_expand_location_to_spelling_point
+ (src_range.m_start, LOCATION_ASPECT_START);
+ expanded_location finish
+ = linemap_client_expand_location_to_spelling_point
+ (src_range.m_finish, LOCATION_ASPECT_FINISH);
+ expanded_location caret
+ = linemap_client_expand_location_to_spelling_point
+ (loc_range->m_loc, LOCATION_ASPECT_CARET);
+
+ /* If any part of the range isn't in the same file as the primary
+ location of this diagnostic, ignore the range. */
+ if (start.file != m_exploc.file)
+ return false;
+ if (finish.file != m_exploc.file)
+ return false;
+ if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
+ if (caret.file != m_exploc.file)
+ return false;
+
+ /* Sanitize the caret location for non-primary ranges. */
+ if (m_layout_ranges.length () > 0)
+ if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
+ if (!compatible_locations_p (loc_range->m_loc, m_primary_loc))
+ /* Discard any non-primary ranges that can't be printed
+ sanely relative to the primary location. */
+ return false;
+
+ /* Everything is now known to be in the correct source file,
+ but it may require further sanitization. */
+ layout_range ri (exploc_with_display_col (start, m_policy,
+ LOCATION_ASPECT_START),
+ exploc_with_display_col (finish, m_policy,
+ LOCATION_ASPECT_FINISH),
+ loc_range->m_range_display_kind,
+ exploc_with_display_col (caret, m_policy,
+ LOCATION_ASPECT_CARET),
+ original_idx, loc_range->m_label);
+
+ /* If we have a range that finishes before it starts (perhaps
+ from something built via macro expansion), printing the
+ range is likely to be nonsensical. Also, attempting to do so
+ breaks assumptions within the printing code (PR c/68473).
+ Similarly, don't attempt to print ranges if one or both ends
+ of the range aren't sane to print relative to the
+ primary location (PR c++/70105). */
+ if (start.line > finish.line
+ || !compatible_locations_p (src_range.m_start, m_primary_loc)
+ || !compatible_locations_p (src_range.m_finish, m_primary_loc))
+ {
+ /* Is this the primary location? */
+ if (m_layout_ranges.length () == 0)
+ {
+ /* We want to print the caret for the primary location, but
+ we must sanitize away m_start and m_finish. */
+ ri.m_start = ri.m_caret;
+ ri.m_finish = ri.m_caret;
+ }
+ else
+ /* This is a non-primary range; ignore it. */
+ return false;
+ }
+
+ /* Potentially filter to just the lines already specified by other
+ locations. This is for use by gcc_rich_location::add_location_if_nearby.
+ The layout ctor doesn't use it, and can't because m_line_spans
+ hasn't been set up at that point. */
+ if (restrict_to_current_line_spans)
+ {
+ if (!will_show_line_p (start.line))
+ return false;
+ if (!will_show_line_p (finish.line))
+ return false;
+ if (loc_range->m_range_display_kind == SHOW_RANGE_WITH_CARET)
+ if (!will_show_line_p (caret.line))
+ return false;
+ }
+
+ /* Passed all the tests; add the range to m_layout_ranges so that
+ it will be printed. */
+ m_layout_ranges.safe_push (ri);
+ return true;
+}
+
+/* Return true iff ROW is within one of the line spans for this layout. */
+
+bool
+layout::will_show_line_p (linenum_type row) const
+{
+ for (int line_span_idx = 0; line_span_idx < get_num_line_spans ();
+ line_span_idx++)
+ {
+ const line_span *line_span = get_line_span (line_span_idx);
+ if (line_span->contains_line_p (row))
+ return true;
+ }
+ return false;
+}
+
+/* Print a line showing a gap in the line numbers, for showing the boundary
+ between two line spans. */
+
+void
+layout::print_gap_in_line_numbering ()
+{
+ gcc_assert (m_show_line_numbers_p);
+
+ pp_emit_prefix (m_pp);
+
+ for (int i = 0; i < m_linenum_width + 1; i++)
+ pp_character (m_pp, '.');
+
+ pp_newline (m_pp);
+}
+
+/* Return true iff we should print a heading when starting the
+ line span with the given index. */
+
+bool
+layout::print_heading_for_line_span_index_p (int line_span_idx) const
+{
+ /* We print a heading for every change of line span, hence for every
+ line span after the initial one. */
+ if (line_span_idx > 0)
+ return true;
+
+ /* We also do it for the initial span if the primary location of the
+ diagnostic is in a different span. */
+ if (m_exploc.line > (int)get_line_span (0)->m_last_line)
+ return true;
+
+ return false;
+}
+
+/* Get an expanded_location for the first location of interest within
+ the given line_span.
+ Used when printing a heading to indicate a new line span. */
+
+expanded_location
+layout::get_expanded_location (const line_span *line_span) const
+{
+ /* Whenever possible, use the caret location. */
+ if (line_span->contains_line_p (m_exploc.line))
+ return m_exploc;
+
+ /* Otherwise, use the start of the first range that's present
+ within the line_span. */
+ for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
+ {
+ const layout_range *lr = &m_layout_ranges[i];
+ if (line_span->contains_line_p (lr->m_start.m_line))
+ {
+ expanded_location exploc = m_exploc;
+ exploc.line = lr->m_start.m_line;
+ exploc.column = lr->m_start.m_columns[CU_BYTES];
+ return exploc;
+ }
+ }
+
+ /* Otherwise, use the location of the first fixit-hint present within
+ the line_span. */
+ for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
+ {
+ const fixit_hint *hint = m_fixit_hints[i];
+ location_t loc = hint->get_start_loc ();
+ expanded_location exploc = expand_location (loc);
+ if (line_span->contains_line_p (exploc.line))
+ return exploc;
+ }
+
+ /* It should not be possible to have a line span that didn't
+ contain any of the layout_range or fixit_hint instances. */
+ gcc_unreachable ();
+ return m_exploc;
+}
+
+/* Determine if HINT is meaningful to print within this layout. */
+
+bool
+layout::validate_fixit_hint_p (const fixit_hint *hint)
+{
+ if (LOCATION_FILE (hint->get_start_loc ()) != m_exploc.file)
+ return false;
+ if (LOCATION_FILE (hint->get_next_loc ()) != m_exploc.file)
+ return false;
+
+ return true;
+}
+
+/* Determine the range of lines affected by HINT.
+ This assumes that HINT has already been filtered by
+ validate_fixit_hint_p, and so affects the correct source file. */
+
+static line_span
+get_line_span_for_fixit_hint (const fixit_hint *hint)
+{
+ gcc_assert (hint);
+
+ int start_line = LOCATION_LINE (hint->get_start_loc ());
+
+ /* For line-insertion fix-it hints, add the previous line to the
+ span, to give the user more context on the proposed change. */
+ if (hint->ends_with_newline_p ())
+ if (start_line > 1)
+ start_line--;
+
+ return line_span (start_line,
+ LOCATION_LINE (hint->get_next_loc ()));
+}
+
+/* We want to print the pertinent source code at a diagnostic. The
+ rich_location can contain multiple locations. This will have been
+ filtered into m_exploc (the caret for the primary location) and
+ m_layout_ranges, for those ranges within the same source file.
+
+ We will print a subset of the lines within the source file in question,
+ as a collection of "spans" of lines.
+
+ This function populates m_line_spans with an ordered, disjoint list of
+ the line spans of interest.
+
+ Printing a gap between line spans takes one line, so, when printing
+ line numbers, we allow a gap of up to one line between spans when
+ merging, since it makes more sense to print the source line rather than a
+ "gap-in-line-numbering" line. When not printing line numbers, it's
+ better to be more explicit about what's going on, so keeping them as
+ separate spans is preferred.
+
+ For example, if the primary range is on lines 8-10, with secondary ranges
+ covering lines 5-6 and lines 13-15:
+
+ 004
+ 005 |RANGE 1
+ 006 |RANGE 1
+ 007
+ 008 |PRIMARY RANGE
+ 009 |PRIMARY CARET
+ 010 |PRIMARY RANGE
+ 011
+ 012
+ 013 |RANGE 2
+ 014 |RANGE 2
+ 015 |RANGE 2
+ 016
+
+ With line numbering on, we want two spans: lines 5-10 and lines 13-15.
+
+ With line numbering off (with span headers), we want three spans: lines 5-6,
+ lines 8-10, and lines 13-15. */
+
+void
+layout::calculate_line_spans ()
+{
+ /* This should only be called once, by the ctor. */
+ gcc_assert (m_line_spans.length () == 0);
+
+ /* Populate tmp_spans with individual spans, for each of
+ m_exploc, and for m_layout_ranges. */
+ auto_vec<line_span> tmp_spans (1 + m_layout_ranges.length ());
+ tmp_spans.safe_push (line_span (m_exploc.line, m_exploc.line));
+ for (unsigned int i = 0; i < m_layout_ranges.length (); i++)
+ {
+ const layout_range *lr = &m_layout_ranges[i];
+ gcc_assert (lr->m_start.m_line <= lr->m_finish.m_line);
+ tmp_spans.safe_push (line_span (lr->m_start.m_line,
+ lr->m_finish.m_line));
+ }
+
+ /* Also add spans for any fix-it hints, in case they cover other lines. */
+ for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
+ {
+ const fixit_hint *hint = m_fixit_hints[i];
+ gcc_assert (hint);
+ tmp_spans.safe_push (get_line_span_for_fixit_hint (hint));
+ }
+
+ /* Sort them. */
+ tmp_spans.qsort(line_span::comparator);
+
+ /* Now iterate through tmp_spans, copying into m_line_spans, and
+ combining where possible. */
+ gcc_assert (tmp_spans.length () > 0);
+ m_line_spans.safe_push (tmp_spans[0]);
+ for (unsigned int i = 1; i < tmp_spans.length (); i++)
+ {
+ line_span *current = &m_line_spans[m_line_spans.length () - 1];
+ const line_span *next = &tmp_spans[i];
+ gcc_assert (next->m_first_line >= current->m_first_line);
+ const int merger_distance = m_show_line_numbers_p ? 1 : 0;
+ if ((linenum_arith_t)next->m_first_line
+ <= (linenum_arith_t)current->m_last_line + 1 + merger_distance)
+ {
+ /* We can merge them. */
+ if (next->m_last_line > current->m_last_line)
+ current->m_last_line = next->m_last_line;
+ }
+ else
+ {
+ /* No merger possible. */
+ m_line_spans.safe_push (*next);
+ }
+ }
+
+ /* Verify the result, in m_line_spans. */
+ gcc_assert (m_line_spans.length () > 0);
+ for (unsigned int i = 1; i < m_line_spans.length (); i++)
+ {
+ const line_span *prev = &m_line_spans[i - 1];
+ const line_span *next = &m_line_spans[i];
+ /* The individual spans must be sane. */
+ gcc_assert (prev->m_first_line <= prev->m_last_line);
+ gcc_assert (next->m_first_line <= next->m_last_line);
+ /* The spans must be ordered. */
+ gcc_assert (prev->m_first_line < next->m_first_line);
+ /* There must be a gap of at least one line between separate spans. */
+ gcc_assert ((prev->m_last_line + 1) < next->m_first_line);
+ }
+}
+
+/* Determine how many display columns need to be reserved for line numbers,
+ based on the largest line number that will be needed, and populate
+ m_linenum_width. */
+
+void
+layout::calculate_linenum_width ()
+{
+ gcc_assert (m_line_spans.length () > 0);
+ const line_span *last_span = &m_line_spans[m_line_spans.length () - 1];
+ int highest_line = last_span->m_last_line;
+ if (highest_line < 0)
+ highest_line = 0;
+ m_linenum_width = num_digits (highest_line);
+ /* If we're showing jumps in the line-numbering, allow at least 3 chars. */
+ if (m_line_spans.length () > 1)
+ m_linenum_width = MAX (m_linenum_width, 3);
+ /* If there's a minimum margin width, apply it (subtracting 1 for the space
+ after the line number. */
+ m_linenum_width = MAX (m_linenum_width, m_context->min_margin_width - 1);
+}
+
+/* Calculate m_x_offset_display, which improves readability in case the source
+ line of interest is longer than the user's display. All lines output will be
+ shifted to the left (so that their beginning is no longer displayed) by
+ m_x_offset_display display columns, so that the caret is in a reasonable
+ location. */
+
+void
+layout::calculate_x_offset_display ()
+{
+ m_x_offset_display = 0;
+
+ const int max_width = m_context->caret_max_width;
+ if (!max_width)
+ {
+ /* Nothing to do, the width is not capped. */
+ return;
+ }
+
+ const char_span line = location_get_source_line (m_exploc.file,
+ m_exploc.line);
+ if (!line)
+ {
+ /* Nothing to do, we couldn't find the source line. */
+ return;
+ }
+ int caret_display_column = m_exploc.m_display_col;
+ const int line_bytes
+ = get_line_bytes_without_trailing_whitespace (line.get_buffer (),
+ line.length ());
+ int eol_display_column
+ = cpp_display_width (line.get_buffer (), line_bytes, m_policy);
+ if (caret_display_column > eol_display_column
+ || !caret_display_column)
+ {
+ /* This does not make sense, so don't try to do anything in this case. */
+ return;
+ }
+
+ /* Adjust caret and eol positions to include the left margin. If we are
+ outputting line numbers, then the left margin is equal to m_linenum_width
+ plus three for the " | " which follows it. Otherwise the left margin width
+ is equal to 1, because layout::print_source_line() will prefix each line
+ with a space. */
+ const int source_display_cols = eol_display_column;
+ int left_margin_size = 1;
+ if (m_show_line_numbers_p)
+ left_margin_size = m_linenum_width + 3;
+ caret_display_column += left_margin_size;
+ eol_display_column += left_margin_size;
+
+ if (eol_display_column <= max_width)
+ {
+ /* Nothing to do, everything fits in the display. */
+ return;
+ }
+
+ /* The line is too long for the display. Calculate an offset such that the
+ caret is not too close to the right edge of the screen. It will be
+ CARET_LINE_MARGIN display columns from the right edge, unless it is closer
+ than that to the end of the source line anyway. */
+ int right_margin_size = CARET_LINE_MARGIN;
+ right_margin_size = MIN (eol_display_column - caret_display_column,
+ right_margin_size);
+ if (right_margin_size + left_margin_size >= max_width)
+ {
+ /* The max_width is very small, so anything we try to do will not be very
+ effective; just punt in this case and output with no offset. */
+ return;
+ }
+ const int max_caret_display_column = max_width - right_margin_size;
+ if (caret_display_column > max_caret_display_column)
+ {
+ m_x_offset_display = caret_display_column - max_caret_display_column;
+ /* Make sure we don't offset the line into oblivion. */
+ static const int min_cols_visible = 2;
+ if (source_display_cols - m_x_offset_display < min_cols_visible)
+ m_x_offset_display = 0;
+ }
+}
+
+/* Print line ROW of source code, potentially colorized at any ranges, and
+ return the line bounds. LINE is the source line (not necessarily
+ 0-terminated) and LINE_BYTES is its length in bytes. In order to handle both
+ colorization and tab expansion, this function tracks the line position in
+ both byte and display column units. */
+
+line_bounds
+layout::print_source_line (linenum_type row, const char *line, int line_bytes)
+{
+ m_colorizer.set_normal_text ();
+
+ pp_emit_prefix (m_pp);
+ if (m_show_line_numbers_p)
+ {
+ int width = num_digits (row);
+ for (int i = 0; i < m_linenum_width - width; i++)
+ pp_space (m_pp);
+ pp_printf (m_pp, "%i | ", row);
+ }
+ else
+ pp_space (m_pp);
+
+ /* We will stop printing the source line at any trailing whitespace. */
+ line_bytes = get_line_bytes_without_trailing_whitespace (line,
+ line_bytes);
+
+ /* This object helps to keep track of which display column we are at, which is
+ necessary for computing the line bounds in display units, for doing
+ tab expansion, and for implementing m_x_offset_display. */
+ cpp_display_width_computation dw (line, line_bytes, m_policy);
+
+ /* Skip the first m_x_offset_display display columns. In case the leading
+ portion that will be skipped ends with a character with wcwidth > 1, then
+ it is possible we skipped too much, so account for that by padding with
+ spaces. Note that this does the right thing too in case a tab was the last
+ character to be skipped over; the tab is effectively replaced by the
+ correct number of trailing spaces needed to offset by the desired number of
+ display columns. */
+ for (int skipped_display_cols = dw.advance_display_cols (m_x_offset_display);
+ skipped_display_cols > m_x_offset_display; --skipped_display_cols)
+ pp_space (m_pp);
+
+ /* Print the line and compute the line_bounds. */
+ line_bounds lbounds;
+ while (!dw.done ())
+ {
+ /* Assuming colorization is enabled for the caret and underline
+ characters, we may also colorize the associated characters
+ within the source line.
+
+ For frontends that generate range information, we color the
+ associated characters in the source line the same as the
+ carets and underlines in the annotation line, to make it easier
+ for the reader to see the pertinent code.
+
+ For frontends that only generate carets, we don't colorize the
+ characters above them, since this would look strange (e.g.
+ colorizing just the first character in a token). */
+ if (m_colorize_source_p)
+ {
+ bool in_range_p;
+ point_state state;
+ const int start_byte_col = dw.bytes_processed () + 1;
+ in_range_p = get_state_at_point (row, start_byte_col,
+ 0, INT_MAX,
+ CU_BYTES,
+ &state);
+ if (in_range_p)
+ m_colorizer.set_range (state.range_idx);
+ else
+ m_colorizer.set_normal_text ();
+ }
+
+ /* Get the display width of the next character to be output, expanding
+ tabs and replacing some control bytes with spaces as necessary. */
+ const char *c = dw.next_byte ();
+ const int start_disp_col = dw.display_cols_processed () + 1;
+ cpp_decoded_char cp;
+ const int this_display_width = dw.process_next_codepoint (&cp);
+ if (*c == '\t')
+ {
+ /* The returned display width is the number of spaces into which the
+ tab should be expanded. */
+ for (int i = 0; i != this_display_width; ++i)
+ pp_space (m_pp);
+ continue;
+ }
+
+ /* We have a (possibly multibyte) character to output; update the line
+ bounds if it is not whitespace. */
+ if (*c != ' ')
+ {
+ lbounds.m_last_non_ws_disp_col = dw.display_cols_processed ();
+ if (lbounds.m_first_non_ws_disp_col == INT_MAX)
+ lbounds.m_first_non_ws_disp_col = start_disp_col;
+ }
+
+ /* Output the character. */
+ m_policy.m_print_cb (m_pp, cp);
+ c = dw.next_byte ();
+ }
+ print_newline ();
+ return lbounds;
+}
+
+/* Determine if we should print an annotation line for ROW.
+ i.e. if any of m_layout_ranges contains ROW. */
+
+bool
+layout::should_print_annotation_line_p (linenum_type row) const
+{
+ layout_range *range;
+ int i;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
+ return false;
+ if (range->intersects_line_p (row))
+ return true;
+ }
+ return false;
+}
+
+/* Begin an annotation line. If m_show_line_numbers_p, print the left
+ margin, which is empty for annotation lines. Otherwise, do nothing. */
+
+void
+layout::start_annotation_line (char margin_char) const
+{
+ pp_emit_prefix (m_pp);
+ if (m_show_line_numbers_p)
+ {
+ /* Print the margin. If MARGIN_CHAR != ' ', then print up to 3
+ of it, right-aligned, padded with spaces. */
+ int i;
+ for (i = 0; i < m_linenum_width - 3; i++)
+ pp_space (m_pp);
+ for (; i < m_linenum_width; i++)
+ pp_character (m_pp, margin_char);
+ pp_string (m_pp, " |");
+ }
+}
+
+/* Print a line consisting of the caret/underlines for the given
+ source line. */
+
+void
+layout::print_annotation_line (linenum_type row, const line_bounds lbounds)
+{
+ int x_bound = get_x_bound_for_row (row, m_exploc.m_display_col,
+ lbounds.m_last_non_ws_disp_col);
+
+ start_annotation_line ();
+ pp_space (m_pp);
+
+ for (int column = 1 + m_x_offset_display; column < x_bound; column++)
+ {
+ bool in_range_p;
+ point_state state;
+ in_range_p = get_state_at_point (row, column,
+ lbounds.m_first_non_ws_disp_col,
+ lbounds.m_last_non_ws_disp_col,
+ CU_DISPLAY_COLS,
+ &state);
+ if (in_range_p)
+ {
+ /* Within a range. Draw either the caret or an underline. */
+ m_colorizer.set_range (state.range_idx);
+ if (state.draw_caret_p)
+ {
+ /* Draw the caret. */
+ char caret_char;
+ if (state.range_idx < rich_location::STATICALLY_ALLOCATED_RANGES)
+ caret_char = m_context->caret_chars[state.range_idx];
+ else
+ caret_char = '^';
+ pp_character (m_pp, caret_char);
+ }
+ else
+ pp_character (m_pp, '~');
+ }
+ else
+ {
+ /* Not in a range. */
+ m_colorizer.set_normal_text ();
+ pp_character (m_pp, ' ');
+ }
+ }
+ print_newline ();
+}
+
+/* Implementation detail of layout::print_any_labels.
+
+ A label within the given row of source. */
+
+class line_label
+{
+public:
+ line_label (const cpp_char_column_policy &policy,
+ int state_idx, int column,
+ label_text text)
+ : m_state_idx (state_idx), m_column (column),
+ m_text (text), m_label_line (0), m_has_vbar (true)
+ {
+ const int bytes = strlen (text.m_buffer);
+ m_display_width = cpp_display_width (text.m_buffer, bytes, policy);
+ }
+
+ /* Sorting is primarily by column, then by state index. */
+ static int comparator (const void *p1, const void *p2)
+ {
+ const line_label *ll1 = (const line_label *)p1;
+ const line_label *ll2 = (const line_label *)p2;
+ int column_cmp = compare (ll1->m_column, ll2->m_column);
+ if (column_cmp)
+ return column_cmp;
+ /* Order by reverse state index, so that labels are printed
+ in order of insertion into the rich_location when the
+ sorted list is walked backwards. */
+ return -compare (ll1->m_state_idx, ll2->m_state_idx);
+ }
+
+ int m_state_idx;
+ int m_column;
+ label_text m_text;
+ size_t m_display_width;
+ int m_label_line;
+ bool m_has_vbar;
+};
+
+/* Print any labels in this row. */
+void
+layout::print_any_labels (linenum_type row)
+{
+ int i;
+ auto_vec<line_label> labels;
+
+ /* Gather the labels that are to be printed into "labels". */
+ {
+ layout_range *range;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ /* Most ranges don't have labels, so reject this first. */
+ if (range->m_label == NULL)
+ continue;
+
+ /* The range's caret must be on this line. */
+ if (range->m_caret.m_line != row)
+ continue;
+
+ /* Reject labels that aren't fully visible due to clipping
+ by m_x_offset_display. */
+ const int disp_col = range->m_caret.m_columns[CU_DISPLAY_COLS];
+ if (disp_col <= m_x_offset_display)
+ continue;
+
+ label_text text;
+ text = range->m_label->get_text (range->m_original_idx);
+
+ /* Allow for labels that return NULL from their get_text
+ implementation (so e.g. such labels can control their own
+ visibility). */
+ if (text.m_buffer == NULL)
+ continue;
+
+ labels.safe_push (line_label (m_policy, i, disp_col, text));
+ }
+ }
+
+ /* Bail out if there are no labels on this row. */
+ if (labels.length () == 0)
+ return;
+
+ /* Sort them. */
+ labels.qsort(line_label::comparator);
+
+ /* Figure out how many "label lines" we need, and which
+ one each label is printed in.
+
+ For example, if the labels aren't too densely packed,
+ we can fit them on the same line, giving two "label lines":
+
+ foo + bar
+ ~~~ ~~~
+ | | : label line 0
+ l0 l1 : label line 1
+
+ If they would touch each other or overlap, then we need
+ additional "label lines":
+
+ foo + bar
+ ~~~ ~~~
+ | | : label line 0
+ | label 1 : label line 1
+ label 0 : label line 2
+
+ Place the final label on label line 1, and work backwards, adding
+ label lines as needed.
+
+ If multiple labels are at the same place, put them on separate
+ label lines:
+
+ foo + bar
+ ^ : label line 0
+ | : label line 1
+ label 0 : label line 2
+ label 1 : label line 3. */
+
+ int max_label_line = 1;
+ {
+ int next_column = INT_MAX;
+ line_label *label;
+ FOR_EACH_VEC_ELT_REVERSE (labels, i, label)
+ {
+ /* Would this label "touch" or overlap the next label? */
+ if (label->m_column + label->m_display_width >= (size_t)next_column)
+ {
+ max_label_line++;
+
+ /* If we've already seen labels with the same column, suppress the
+ vertical bar for subsequent ones in this backwards iteration;
+ hence only the one with the highest label_line has m_has_vbar set. */
+ if (label->m_column == next_column)
+ label->m_has_vbar = false;
+ }
+
+ label->m_label_line = max_label_line;
+ next_column = label->m_column;
+ }
+ }
+
+ /* Print the "label lines". For each label within the line, print
+ either a vertical bar ('|') for the labels that are lower down, or the
+ labels themselves once we've reached their line. */
+ {
+ for (int label_line = 0; label_line <= max_label_line; label_line++)
+ {
+ start_annotation_line ();
+ pp_space (m_pp);
+ int column = 1 + m_x_offset_display;
+ line_label *label;
+ FOR_EACH_VEC_ELT (labels, i, label)
+ {
+ if (label_line > label->m_label_line)
+ /* We've printed all the labels for this label line. */
+ break;
+
+ if (label_line == label->m_label_line)
+ {
+ gcc_assert (column <= label->m_column);
+ move_to_column (&column, label->m_column, true);
+ /* Colorize the text, unless it's for events in a
+ diagnostic_path. */
+ if (!m_diagnostic_path_p)
+ m_colorizer.set_range (label->m_state_idx);
+ pp_string (m_pp, label->m_text.m_buffer);
+ m_colorizer.set_normal_text ();
+ column += label->m_display_width;
+ }
+ else if (label->m_has_vbar)
+ {
+ gcc_assert (column <= label->m_column);
+ move_to_column (&column, label->m_column, true);
+ m_colorizer.set_range (label->m_state_idx);
+ pp_character (m_pp, '|');
+ m_colorizer.set_normal_text ();
+ column++;
+ }
+ }
+ print_newline ();
+ }
+ }
+
+ /* Clean up. */
+ {
+ line_label *label;
+ FOR_EACH_VEC_ELT (labels, i, label)
+ label->m_text.maybe_free ();
+ }
+}
+
+/* If there are any fixit hints inserting new lines before source line ROW,
+ print them.
+
+ They are printed on lines of their own, before the source line
+ itself, with a leading '+'. */
+
+void
+layout::print_leading_fixits (linenum_type row)
+{
+ for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
+ {
+ const fixit_hint *hint = m_fixit_hints[i];
+
+ if (!hint->ends_with_newline_p ())
+ /* Not a newline fixit; print it in print_trailing_fixits. */
+ continue;
+
+ gcc_assert (hint->insertion_p ());
+
+ if (hint->affects_line_p (m_exploc.file, row))
+ {
+ /* Printing the '+' with normal colorization
+ and the inserted line with "insert" colorization
+ helps them stand out from each other, and from
+ the surrounding text. */
+ m_colorizer.set_normal_text ();
+ start_annotation_line ('+');
+ pp_character (m_pp, '+');
+ m_colorizer.set_fixit_insert ();
+ /* Print all but the trailing newline of the fix-it hint.
+ We have to print the newline separately to avoid
+ getting additional pp prefixes printed. */
+ for (size_t i = 0; i < hint->get_length () - 1; i++)
+ pp_character (m_pp, hint->get_string ()[i]);
+ m_colorizer.set_normal_text ();
+ pp_newline (m_pp);
+ }
+ }
+}
+
+/* Subroutine of layout::print_trailing_fixits.
+
+ Determine if the annotation line printed for LINE contained
+ the exact range from START_COLUMN to FINISH_COLUMN (in display units). */
+
+bool
+layout::annotation_line_showed_range_p (linenum_type line, int start_column,
+ int finish_column) const
+{
+ layout_range *range;
+ int i;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ if (range->m_start.m_line == line
+ && range->m_start.m_columns[CU_DISPLAY_COLS] == start_column
+ && range->m_finish.m_line == line
+ && range->m_finish.m_columns[CU_DISPLAY_COLS] == finish_column)
+ return true;
+ return false;
+}
+
+/* Classes for printing trailing fix-it hints i.e. those that
+ don't add new lines.
+
+ For insertion, these can look like:
+
+ new_text
+
+ For replacement, these can look like:
+
+ ------------- : underline showing affected range
+ new_text
+
+ For deletion, these can look like:
+
+ ------------- : underline showing affected range
+
+ This can become confusing if they overlap, and so we need
+ to do some preprocessing to decide what to print.
+ We use the list of fixit_hint instances affecting the line
+ to build a list of "correction" instances, and print the
+ latter.
+
+ For example, consider a set of fix-its for converting
+ a C-style cast to a C++ const_cast.
+
+ Given:
+
+ ..000000000111111111122222222223333333333.
+ ..123456789012345678901234567890123456789.
+ foo *f = (foo *)ptr->field;
+ ^~~~~
+
+ and the fix-it hints:
+ - replace col 10 (the open paren) with "const_cast<"
+ - replace col 16 (the close paren) with "> ("
+ - insert ")" before col 27
+
+ then we would get odd-looking output:
+
+ foo *f = (foo *)ptr->field;
+ ^~~~~
+ -
+ const_cast<
+ -
+ > ( )
+
+ It would be better to detect when fixit hints are going to
+ overlap (those that require new lines), and to consolidate
+ the printing of such fixits, giving something like:
+
+ foo *f = (foo *)ptr->field;
+ ^~~~~
+ -----------------
+ const_cast<foo *> (ptr->field)
+
+ This works by detecting when the printing would overlap, and
+ effectively injecting no-op replace hints into the gaps between
+ such fix-its, so that the printing joins up.
+
+ In the above example, the overlap of:
+ - replace col 10 (the open paren) with "const_cast<"
+ and:
+ - replace col 16 (the close paren) with "> ("
+ is fixed by injecting a no-op:
+ - replace cols 11-15 with themselves ("foo *")
+ and consolidating these, making:
+ - replace cols 10-16 with "const_cast<" + "foo *" + "> ("
+ i.e.:
+ - replace cols 10-16 with "const_cast<foo *> ("
+
+ This overlaps with the final fix-it hint:
+ - insert ")" before col 27
+ and so we repeat the consolidation process, by injecting
+ a no-op:
+ - replace cols 17-26 with themselves ("ptr->field")
+ giving:
+ - replace cols 10-26 with "const_cast<foo *> (" + "ptr->field" + ")"
+ i.e.:
+ - replace cols 10-26 with "const_cast<foo *> (ptr->field)"
+
+ and is thus printed as desired. */
+
+/* A range of (byte or display) columns within a line. */
+
+class column_range
+{
+public:
+ column_range (int start_, int finish_) : start (start_), finish (finish_)
+ {
+ /* We must have either a range, or an insertion. */
+ gcc_assert (start <= finish || finish == start - 1);
+ }
+
+ bool operator== (const column_range &other) const
+ {
+ return start == other.start && finish == other.finish;
+ }
+
+ int start;
+ int finish;
+};
+
+/* Get the range of bytes or display columns that HINT would affect. */
+static column_range
+get_affected_range (const cpp_char_column_policy &policy,
+ const fixit_hint *hint, enum column_unit col_unit)
+{
+ expanded_location exploc_start = expand_location (hint->get_start_loc ());
+ expanded_location exploc_finish = expand_location (hint->get_next_loc ());
+ --exploc_finish.column;
+
+ int start_column;
+ int finish_column;
+ if (col_unit == CU_DISPLAY_COLS)
+ {
+ start_column = location_compute_display_column (exploc_start, policy);
+ if (hint->insertion_p ())
+ finish_column = start_column - 1;
+ else
+ finish_column = location_compute_display_column (exploc_finish, policy);
+ }
+ else
+ {
+ start_column = exploc_start.column;
+ finish_column = exploc_finish.column;
+ }
+ return column_range (start_column, finish_column);
+}
+
+/* Get the range of display columns that would be printed for HINT. */
+
+static column_range
+get_printed_columns (const cpp_char_column_policy &policy,
+ const fixit_hint *hint)
+{
+ expanded_location exploc = expand_location (hint->get_start_loc ());
+ int start_column = location_compute_display_column (exploc, policy);
+ int hint_width = cpp_display_width (hint->get_string (), hint->get_length (),
+ policy);
+ int final_hint_column = start_column + hint_width - 1;
+ if (hint->insertion_p ())
+ {
+ return column_range (start_column, final_hint_column);
+ }
+ else
+ {
+ exploc = expand_location (hint->get_next_loc ());
+ --exploc.column;
+ int finish_column = location_compute_display_column (exploc, policy);
+ return column_range (start_column,
+ MAX (finish_column, final_hint_column));
+ }
+}
+
+/* A correction on a particular line.
+ This describes a plan for how to print one or more fixit_hint
+ instances that affected the line, potentially consolidating hints
+ into corrections to make the result easier for the user to read. */
+
+class correction
+{
+public:
+ correction (column_range affected_bytes,
+ column_range affected_columns,
+ column_range printed_columns,
+ const char *new_text, size_t new_text_len,
+ const cpp_char_column_policy &policy)
+ : m_affected_bytes (affected_bytes),
+ m_affected_columns (affected_columns),
+ m_printed_columns (printed_columns),
+ m_text (xstrdup (new_text)),
+ m_byte_length (new_text_len),
+ m_policy (policy),
+ m_alloc_sz (new_text_len + 1)
+ {
+ compute_display_cols ();
+ }
+
+ ~correction () { free (m_text); }
+
+ bool insertion_p () const
+ {
+ return m_affected_bytes.start == m_affected_bytes.finish + 1;
+ }
+
+ void ensure_capacity (size_t len);
+ void ensure_terminated ();
+
+ void compute_display_cols ()
+ {
+ m_display_cols = cpp_display_width (m_text, m_byte_length, m_policy);
+ }
+
+ void overwrite (int dst_offset, const char_span &src_span)
+ {
+ gcc_assert (dst_offset >= 0);
+ gcc_assert (dst_offset + src_span.length () < m_alloc_sz);
+ memcpy (m_text + dst_offset, src_span.get_buffer (),
+ src_span.length ());
+ }
+
+ /* If insert, then start: the column before which the text
+ is to be inserted, and finish is offset by the length of
+ the replacement.
+ If replace, then the range of columns affected. */
+ column_range m_affected_bytes;
+ column_range m_affected_columns;
+
+ /* If insert, then start: the column before which the text
+ is to be inserted, and finish is offset by the length of
+ the replacement.
+ If replace, then the range of columns affected. */
+ column_range m_printed_columns;
+
+ /* The text to be inserted/used as replacement. */
+ char *m_text;
+ size_t m_byte_length; /* Not including null-terminator. */
+ int m_display_cols;
+ const cpp_char_column_policy &m_policy;
+ size_t m_alloc_sz;
+};
+
+/* Ensure that m_text can hold a string of length LEN
+ (plus 1 for 0-termination). */
+
+void
+correction::ensure_capacity (size_t len)
+{
+ /* Allow 1 extra byte for 0-termination. */
+ if (m_alloc_sz < (len + 1))
+ {
+ size_t new_alloc_sz = (len + 1) * 2;
+ m_text = (char *)xrealloc (m_text, new_alloc_sz);
+ m_alloc_sz = new_alloc_sz;
+ }
+}
+
+/* Ensure that m_text is 0-terminated. */
+
+void
+correction::ensure_terminated ()
+{
+ /* 0-terminate the buffer. */
+ gcc_assert (m_byte_length < m_alloc_sz);
+ m_text[m_byte_length] = '\0';
+}
+
+/* A list of corrections affecting a particular line.
+ This is used by layout::print_trailing_fixits for planning
+ how to print the fix-it hints affecting the line. */
+
+class line_corrections
+{
+public:
+ line_corrections (const char_display_policy &policy,
+ const char *filename,
+ linenum_type row)
+ : m_policy (policy), m_filename (filename), m_row (row)
+ {}
+ ~line_corrections ();
+
+ void add_hint (const fixit_hint *hint);
+
+ const char_display_policy &m_policy;
+ const char *m_filename;
+ linenum_type m_row;
+ auto_vec <correction *> m_corrections;
+};
+
+/* struct line_corrections. */
+
+line_corrections::~line_corrections ()
+{
+ unsigned i;
+ correction *c;
+ FOR_EACH_VEC_ELT (m_corrections, i, c)
+ delete c;
+}
+
+/* A struct wrapping a particular source line, allowing
+ run-time bounds-checking of accesses in a checked build. */
+
+class source_line
+{
+public:
+ source_line (const char *filename, int line);
+
+ char_span as_span () { return char_span (chars, width); }
+
+ const char *chars;
+ int width;
+};
+
+/* source_line's ctor. */
+
+source_line::source_line (const char *filename, int line)
+{
+ char_span span = location_get_source_line (filename, line);
+ chars = span.get_buffer ();
+ width = span.length ();
+}
+
+/* Add HINT to the corrections for this line.
+ Attempt to consolidate nearby hints so that they will not
+ overlap with printed. */
+
+void
+line_corrections::add_hint (const fixit_hint *hint)
+{
+ column_range affected_bytes = get_affected_range (m_policy, hint, CU_BYTES);
+ column_range affected_columns = get_affected_range (m_policy, hint,
+ CU_DISPLAY_COLS);
+ column_range printed_columns = get_printed_columns (m_policy, hint);
+
+ /* Potentially consolidate. */
+ if (!m_corrections.is_empty ())
+ {
+ correction *last_correction
+ = m_corrections[m_corrections.length () - 1];
+
+ /* The following consolidation code assumes that the fix-it hints
+ have been sorted by start (done within layout's ctor). */
+ gcc_assert (affected_bytes.start
+ >= last_correction->m_affected_bytes.start);
+ gcc_assert (printed_columns.start
+ >= last_correction->m_printed_columns.start);
+
+ if (printed_columns.start <= last_correction->m_printed_columns.finish)
+ {
+ /* We have two hints for which the printed forms of the hints
+ would touch or overlap, so we need to consolidate them to avoid
+ confusing the user.
+ Attempt to inject a "replace" correction from immediately
+ after the end of the last hint to immediately before the start
+ of the next hint. */
+ column_range between (last_correction->m_affected_bytes.finish + 1,
+ affected_bytes.start - 1);
+
+ /* Try to read the source. */
+ source_line line (m_filename, m_row);
+ if (line.chars && between.finish < line.width)
+ {
+ /* Consolidate into the last correction:
+ add a no-op "replace" of the "between" text, and
+ add the text from the new hint. */
+ int old_byte_len = last_correction->m_byte_length;
+ gcc_assert (old_byte_len >= 0);
+ int between_byte_len = between.finish + 1 - between.start;
+ gcc_assert (between_byte_len >= 0);
+ int new_byte_len
+ = old_byte_len + between_byte_len + hint->get_length ();
+ gcc_assert (new_byte_len >= 0);
+ last_correction->ensure_capacity (new_byte_len);
+ last_correction->overwrite
+ (old_byte_len,
+ line.as_span ().subspan (between.start - 1,
+ between.finish + 1 - between.start));
+ last_correction->overwrite (old_byte_len + between_byte_len,
+ char_span (hint->get_string (),
+ hint->get_length ()));
+ last_correction->m_byte_length = new_byte_len;
+ last_correction->ensure_terminated ();
+ last_correction->m_affected_bytes.finish
+ = affected_bytes.finish;
+ last_correction->m_affected_columns.finish
+ = affected_columns.finish;
+ int prev_display_cols = last_correction->m_display_cols;
+ last_correction->compute_display_cols ();
+ last_correction->m_printed_columns.finish
+ += last_correction->m_display_cols - prev_display_cols;
+ return;
+ }
+ }
+ }
+
+ /* If no consolidation happened, add a new correction instance. */
+ m_corrections.safe_push (new correction (affected_bytes,
+ affected_columns,
+ printed_columns,
+ hint->get_string (),
+ hint->get_length (),
+ m_policy));
+}
+
+/* If there are any fixit hints on source line ROW, print them.
+ They are printed in order, attempting to combine them onto lines, but
+ starting new lines if necessary.
+ Fix-it hints that insert new lines are handled separately,
+ in layout::print_leading_fixits. */
+
+void
+layout::print_trailing_fixits (linenum_type row)
+{
+ /* Build a list of correction instances for the line,
+ potentially consolidating hints (for the sake of readability). */
+ line_corrections corrections (m_policy, m_exploc.file, row);
+ for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
+ {
+ const fixit_hint *hint = m_fixit_hints[i];
+
+ /* Newline fixits are handled by layout::print_leading_fixits. */
+ if (hint->ends_with_newline_p ())
+ continue;
+
+ if (hint->affects_line_p (m_exploc.file, row))
+ corrections.add_hint (hint);
+ }
+
+ /* Now print the corrections. */
+ unsigned i;
+ correction *c;
+ int column = m_x_offset_display;
+
+ if (!corrections.m_corrections.is_empty ())
+ start_annotation_line ();
+
+ FOR_EACH_VEC_ELT (corrections.m_corrections, i, c)
+ {
+ /* For now we assume each fixit hint can only touch one line. */
+ if (c->insertion_p ())
+ {
+ /* This assumes the insertion just affects one line. */
+ int start_column = c->m_printed_columns.start;
+ move_to_column (&column, start_column, true);
+ m_colorizer.set_fixit_insert ();
+ pp_string (m_pp, c->m_text);
+ m_colorizer.set_normal_text ();
+ column += c->m_display_cols;
+ }
+ else
+ {
+ /* If the range of the replacement wasn't printed in the
+ annotation line, then print an extra underline to
+ indicate exactly what is being replaced.
+ Always show it for removals. */
+ int start_column = c->m_affected_columns.start;
+ int finish_column = c->m_affected_columns.finish;
+ if (!annotation_line_showed_range_p (row, start_column,
+ finish_column)
+ || c->m_byte_length == 0)
+ {
+ move_to_column (&column, start_column, true);
+ m_colorizer.set_fixit_delete ();
+ for (; column <= finish_column; column++)
+ pp_character (m_pp, '-');
+ m_colorizer.set_normal_text ();
+ }
+ /* Print the replacement text. REPLACE also covers
+ removals, so only do this extra work (potentially starting
+ a new line) if we have actual replacement text. */
+ if (c->m_byte_length > 0)
+ {
+ move_to_column (&column, start_column, true);
+ m_colorizer.set_fixit_insert ();
+ pp_string (m_pp, c->m_text);
+ m_colorizer.set_normal_text ();
+ column += c->m_display_cols;
+ }
+ }
+ }
+
+ /* Add a trailing newline, if necessary. */
+ move_to_column (&column, 0, false);
+}
+
+/* Disable any colorization and emit a newline. */
+
+void
+layout::print_newline ()
+{
+ m_colorizer.set_normal_text ();
+ pp_newline (m_pp);
+}
+
+/* Return true if (ROW/COLUMN) is within a range of the layout.
+ If it returns true, OUT_STATE is written to, with the
+ range index, and whether we should draw the caret at
+ (ROW/COLUMN) (as opposed to an underline). COL_UNIT controls
+ whether all inputs and outputs are in bytes or display column units. */
+
+bool
+layout::get_state_at_point (/* Inputs. */
+ linenum_type row, int column,
+ int first_non_ws, int last_non_ws,
+ enum column_unit col_unit,
+ /* Outputs. */
+ point_state *out_state)
+{
+ layout_range *range;
+ int i;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ if (range->m_range_display_kind == SHOW_LINES_WITHOUT_RANGE)
+ /* Bail out early, so that such ranges don't affect underlining or
+ source colorization. */
+ continue;
+
+ if (range->contains_point (row, column, col_unit))
+ {
+ out_state->range_idx = i;
+
+ /* Are we at the range's caret? is it visible? */
+ out_state->draw_caret_p = false;
+ if (range->m_range_display_kind == SHOW_RANGE_WITH_CARET
+ && row == range->m_caret.m_line
+ && column == range->m_caret.m_columns[col_unit])
+ out_state->draw_caret_p = true;
+
+ /* Within a multiline range, don't display any underline
+ in any leading or trailing whitespace on a line.
+ We do display carets, however. */
+ if (!out_state->draw_caret_p)
+ if (column < first_non_ws || column > last_non_ws)
+ return false;
+
+ /* We are within a range. */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Helper function for use by layout::print_line when printing the
+ annotation line under the source line.
+ Get the display column beyond the rightmost one that could contain a caret
+ or range marker, given that we stop rendering at trailing whitespace.
+ ROW is the source line within the given file.
+ CARET_COLUMN is the display column of range 0's caret.
+ LAST_NON_WS_COLUMN is the last display column containing a non-whitespace
+ character of source (as determined when printing the source line). */
+
+int
+layout::get_x_bound_for_row (linenum_type row, int caret_column,
+ int last_non_ws_column)
+{
+ int result = caret_column + 1;
+
+ layout_range *range;
+ int i;
+ FOR_EACH_VEC_ELT (m_layout_ranges, i, range)
+ {
+ if (row >= range->m_start.m_line)
+ {
+ if (range->m_finish.m_line == row)
+ {
+ /* On the final line within a range; ensure that
+ we render up to the end of the range. */
+ const int disp_col = range->m_finish.m_columns[CU_DISPLAY_COLS];
+ if (result <= disp_col)
+ result = disp_col + 1;
+ }
+ else if (row < range->m_finish.m_line)
+ {
+ /* Within a multiline range; ensure that we render up to the
+ last non-whitespace column. */
+ if (result <= last_non_ws_column)
+ result = last_non_ws_column + 1;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Given *COLUMN as an x-coordinate, print spaces to position
+ successive output at DEST_COLUMN, printing a newline if necessary,
+ and updating *COLUMN. If ADD_LEFT_MARGIN, then print the (empty)
+ left margin after any newline. */
+
+void
+layout::move_to_column (int *column, int dest_column, bool add_left_margin)
+{
+ /* Start a new line if we need to. */
+ if (*column > dest_column)
+ {
+ print_newline ();
+ if (add_left_margin)
+ start_annotation_line ();
+ *column = m_x_offset_display;
+ }
+
+ while (*column < dest_column)
+ {
+ pp_space (m_pp);
+ (*column)++;
+ }
+}
+
+/* For debugging layout issues, render a ruler giving column numbers
+ (after the 1-column indent). */
+
+void
+layout::show_ruler (int max_column) const
+{
+ /* Hundreds. */
+ if (max_column > 99)
+ {
+ start_annotation_line ();
+ pp_space (m_pp);
+ for (int column = 1 + m_x_offset_display; column <= max_column; column++)
+ if (column % 10 == 0)
+ pp_character (m_pp, '0' + (column / 100) % 10);
+ else
+ pp_space (m_pp);
+ pp_newline (m_pp);
+ }
+
+ /* Tens. */
+ start_annotation_line ();
+ pp_space (m_pp);
+ for (int column = 1 + m_x_offset_display; column <= max_column; column++)
+ if (column % 10 == 0)
+ pp_character (m_pp, '0' + (column / 10) % 10);
+ else
+ pp_space (m_pp);
+ pp_newline (m_pp);
+
+ /* Units. */
+ start_annotation_line ();
+ pp_space (m_pp);
+ for (int column = 1 + m_x_offset_display; column <= max_column; column++)
+ pp_character (m_pp, '0' + (column % 10));
+ pp_newline (m_pp);
+}
+
+/* Print leading fix-its (for new lines inserted before the source line)
+ then the source line, followed by an annotation line
+ consisting of any caret/underlines, then any fixits.
+ If the source line can't be read, print nothing. */
+void
+layout::print_line (linenum_type row)
+{
+ char_span line = location_get_source_line (m_exploc.file, row);
+ if (!line)
+ return;
+
+ print_leading_fixits (row);
+ const line_bounds lbounds
+ = print_source_line (row, line.get_buffer (), line.length ());
+ if (should_print_annotation_line_p (row))
+ print_annotation_line (row, lbounds);
+ if (m_show_labels_p)
+ print_any_labels (row);
+ print_trailing_fixits (row);
+}
+
+} /* End of anonymous namespace. */
+
+/* If LOC is within the spans of lines that will already be printed for
+ this gcc_rich_location, then add it as a secondary location and return true.
+
+ Otherwise return false. */
+
+bool
+gcc_rich_location::add_location_if_nearby (location_t loc,
+ bool restrict_to_current_line_spans,
+ const range_label *label)
+{
+ /* Use the layout location-handling logic to sanitize LOC,
+ filtering it to the current line spans within a temporary
+ layout instance. */
+ layout layout (global_dc, this, DK_ERROR);
+ location_range loc_range;
+ loc_range.m_loc = loc;
+ loc_range.m_range_display_kind = SHOW_RANGE_WITHOUT_CARET;
+ if (!layout.maybe_add_location_range (&loc_range, 0,
+ restrict_to_current_line_spans))
+ return false;
+
+ add_range (loc, SHOW_RANGE_WITHOUT_CARET, label);
+ return true;
+}
+
+/* Print the physical source code corresponding to the location of
+ this diagnostic, with additional annotations. */
+
+void
+diagnostic_show_locus (diagnostic_context * context,
+ rich_location *richloc,
+ diagnostic_t diagnostic_kind)
+{
+ location_t loc = richloc->get_loc ();
+ /* Do nothing if source-printing has been disabled. */
+ if (!context->show_caret)
+ return;
+
+ /* Don't attempt to print source for UNKNOWN_LOCATION and for builtins. */
+ if (loc <= BUILTINS_LOCATION)
+ return;
+
+ /* Don't print the same source location twice in a row, unless we have
+ fix-it hints, or multiple locations, or a label. */
+ if (loc == context->last_location
+ && richloc->get_num_fixit_hints () == 0
+ && richloc->get_num_locations () == 1
+ && richloc->get_range (0)->m_label == NULL)
+ return;
+
+ context->last_location = loc;
+
+ layout layout (context, richloc, diagnostic_kind);
+ for (int line_span_idx = 0; line_span_idx < layout.get_num_line_spans ();
+ line_span_idx++)
+ {
+ const line_span *line_span = layout.get_line_span (line_span_idx);
+ if (context->show_line_numbers_p)
+ {
+ /* With line numbers, we should show whenever the line-numbering
+ "jumps". */
+ if (line_span_idx > 0)
+ layout.print_gap_in_line_numbering ();
+ }
+ else
+ {
+ /* Without line numbers, we print headings for some line spans. */
+ if (layout.print_heading_for_line_span_index_p (line_span_idx))
+ {
+ expanded_location exploc
+ = layout.get_expanded_location (line_span);
+ context->start_span (context, exploc);
+ }
+ }
+ /* Iterate over the lines within this span (using linenum_arith_t to
+ avoid overflow with 0xffffffff causing an infinite loop). */
+ linenum_arith_t last_line = line_span->get_last_line ();
+ for (linenum_arith_t row = line_span->get_first_line ();
+ row <= last_line; row++)
+ layout.print_line (row);
+ }
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for diagnostic_show_locus. */
+
+/* Verify that cpp_display_width correctly handles escaping. */
+
+static void
+test_display_widths ()
+{
+ gcc_rich_location richloc (UNKNOWN_LOCATION);
+
+ /* U+03C0 "GREEK SMALL LETTER PI". */
+ const char *pi = "\xCF\x80";
+ /* U+1F642 "SLIGHTLY SMILING FACE". */
+ const char *emoji = "\xF0\x9F\x99\x82";
+ /* Stray trailing byte of a UTF-8 character. */
+ const char *stray = "\xBF";
+ /* U+10FFFF. */
+ const char *max_codepoint = "\xF4\x8F\xBF\xBF";
+
+ /* No escaping. */
+ {
+ test_diagnostic_context dc;
+ char_display_policy policy (make_policy (dc, richloc));
+ ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 1);
+ ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 2);
+ ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 1);
+ /* Don't check width of U+10FFFF; it's in a private use plane. */
+ }
+
+ richloc.set_escape_on_output (true);
+
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+ char_display_policy policy (make_policy (dc, richloc));
+ ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
+ ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 9);
+ ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
+ ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
+ policy),
+ strlen ("<U+10FFFF>"));
+ }
+
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+ char_display_policy policy (make_policy (dc, richloc));
+ ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
+ ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 16);
+ ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
+ ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
+ policy),
+ 16);
+ }
+}
+
+/* For precise tests of the layout, make clear where the source line will
+ start. test_left_margin sets the total byte count from the left side of the
+ screen to the start of source lines, after the line number and the separator,
+ which consists of the three characters " | ". */
+static const int test_linenum_sep = 3;
+static const int test_left_margin = 7;
+
+/* Helper function for test_layout_x_offset_display_utf8(). */
+static void
+test_offset_impl (int caret_byte_col, int max_width,
+ int expected_x_offset_display,
+ int left_margin = test_left_margin)
+{
+ test_diagnostic_context dc;
+ dc.caret_max_width = max_width;
+ /* diagnostic_context::min_margin_width sets the minimum space reserved for
+ the line number plus one space after. */
+ dc.min_margin_width = left_margin - test_linenum_sep + 1;
+ dc.show_line_numbers_p = true;
+ rich_location richloc (line_table,
+ linemap_position_for_column (line_table,
+ caret_byte_col));
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ ASSERT_EQ (left_margin - test_linenum_sep,
+ test_layout.get_linenum_width ());
+ ASSERT_EQ (expected_x_offset_display,
+ test_layout.get_x_offset_display ());
+}
+
+/* Test that layout::calculate_x_offset_display() works. */
+static void
+test_layout_x_offset_display_utf8 (const line_table_case &case_)
+{
+
+ const char *content
+ = "This line is very long, so that we can use it to test the logic for "
+ "clipping long lines. Also this: \xf0\x9f\x98\x82\xf0\x9f\x98\x82 is a "
+ "pair of emojis that occupies 8 bytes and 4 display columns, starting at "
+ "column #102.\n";
+
+ /* Number of bytes in the line, subtracting one to remove the newline. */
+ const int line_bytes = strlen (content) - 1;
+
+ /* Number of display columns occupied by the line; each of the 2 emojis
+ takes up 2 fewer display columns than it does bytes. */
+ const int line_display_cols = line_bytes - 2*2;
+
+ /* The column of the first emoji. Byte or display is the same as there are
+ no multibyte characters earlier on the line. */
+ const int emoji_col = 102;
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ location_t line_end = linemap_position_for_column (line_table, line_bytes);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end));
+ ASSERT_EQ (1, LOCATION_LINE (line_end));
+ ASSERT_EQ (line_bytes, LOCATION_COLUMN (line_end));
+
+ char_span lspan = location_get_source_line (tmp.get_filename (), 1);
+ ASSERT_EQ (line_display_cols,
+ cpp_display_width (lspan.get_buffer (), lspan.length (),
+ def_policy ()));
+ ASSERT_EQ (line_display_cols,
+ location_compute_display_column (expand_location (line_end),
+ def_policy ()));
+ ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1),
+ "\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8));
+
+ /* (caret_byte, max_width, expected_x_offset_display, [left_margin]) */
+
+ /* No constraint on the width -> no offset. */
+ test_offset_impl (emoji_col, 0, 0);
+
+ /* Caret is before the beginning -> no offset. */
+ test_offset_impl (0, 100, 0);
+
+ /* Caret is past the end of the line -> no offset. */
+ test_offset_impl (line_bytes+1, 100, 0);
+
+ /* Line fits in the display -> no offset. */
+ test_offset_impl (line_bytes, line_display_cols + test_left_margin, 0);
+ test_offset_impl (emoji_col, line_display_cols + test_left_margin, 0);
+
+ /* Line is too long for the display but caret location is OK
+ anyway -> no offset. */
+ static const int small_width = 24;
+ test_offset_impl (1, small_width, 0);
+
+ /* Width constraint is very small -> no offset. */
+ test_offset_impl (emoji_col, CARET_LINE_MARGIN, 0);
+
+ /* Line would be offset, but due to large line numbers, offsetting
+ would remove the whole line -> no offset. */
+ static const int huge_left_margin = 100;
+ test_offset_impl (emoji_col, huge_left_margin, 0, huge_left_margin);
+
+ /* Line is the same length as the display, but the line number makes it too
+ long, so offset is required. Caret is at the end so padding on the right
+ is not in effect. */
+ for (int excess = 1; excess <= 3; ++excess)
+ test_offset_impl (line_bytes, line_display_cols + test_left_margin - excess,
+ excess);
+
+ /* Line is much too long for the display, caret is near the end ->
+ offset should be such that the line fits in the display and caret
+ remains the same distance from the end that it was. */
+ for (int caret_offset = 0, max_offset = MIN (CARET_LINE_MARGIN, 10);
+ caret_offset <= max_offset; ++caret_offset)
+ test_offset_impl (line_bytes - caret_offset, small_width,
+ line_display_cols + test_left_margin - small_width);
+
+ /* As previous case but caret is closer to the middle; now we want it to end
+ up CARET_LINE_MARGIN bytes from the end. */
+ ASSERT_GT (line_display_cols - emoji_col, CARET_LINE_MARGIN);
+ test_offset_impl (emoji_col, small_width,
+ emoji_col + test_left_margin
+ - (small_width - CARET_LINE_MARGIN));
+
+ /* Test that the source line is offset as expected when printed. */
+ {
+ test_diagnostic_context dc;
+ dc.caret_max_width = small_width - 6;
+ dc.min_margin_width = test_left_margin - test_linenum_sep + 1;
+ dc.show_line_numbers_p = true;
+ dc.show_ruler_p = true;
+ rich_location richloc (line_table,
+ linemap_position_for_column (line_table,
+ emoji_col));
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ test_layout.print_line (1);
+ ASSERT_STREQ (" | 1 \n"
+ " | 1 \n"
+ " | 234567890123456789\n"
+ " 1 | \xf0\x9f\x98\x82\xf0\x9f\x98\x82 is a pair of emojis "
+ "that occupies 8 bytes and 4 display columns, starting at "
+ "column #102.\n"
+ " | ^\n\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Similar to the previous example, but now the offset called for would split
+ the first emoji in the middle of the UTF-8 sequence. Check that we replace
+ it with a padding space in this case. */
+ {
+ test_diagnostic_context dc;
+ dc.caret_max_width = small_width - 5;
+ dc.min_margin_width = test_left_margin - test_linenum_sep + 1;
+ dc.show_line_numbers_p = true;
+ dc.show_ruler_p = true;
+ rich_location richloc (line_table,
+ linemap_position_for_column (line_table,
+ emoji_col + 2));
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ test_layout.print_line (1);
+ ASSERT_STREQ (" | 1 1 \n"
+ " | 1 2 \n"
+ " | 3456789012345678901\n"
+ " 1 | \xf0\x9f\x98\x82 is a pair of emojis "
+ "that occupies 8 bytes and 4 display columns, starting at "
+ "column #102.\n"
+ " | ^\n\n",
+ pp_formatted_text (dc.printer));
+ }
+
+}
+
+static void
+test_layout_x_offset_display_tab (const line_table_case &case_)
+{
+ const char *content
+ = "This line is very long, so that we can use it to test the logic for "
+ "clipping long lines. Also this: `\t' is a tab that occupies 1 byte and "
+ "a variable number of display columns, starting at column #103.\n";
+
+ /* Number of bytes in the line, subtracting one to remove the newline. */
+ const int line_bytes = strlen (content) - 1;
+
+ /* The column where the tab begins. Byte or display is the same as there are
+ no multibyte characters earlier on the line. */
+ const int tab_col = 103;
+
+ /* Effective extra size of the tab beyond what a single space would have taken
+ up, indexed by tabstop. */
+ static const int num_tabstops = 11;
+ int extra_width[num_tabstops];
+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+ {
+ const int this_tab_size = tabstop - (tab_col - 1) % tabstop;
+ extra_width[tabstop] = this_tab_size - 1;
+ }
+ /* Example of this calculation: if tabstop is 10, the tab starting at column
+ #103 has to expand into 8 spaces, covering columns 103-110, so that the
+ next character is at column #111. So it takes up 7 more columns than
+ a space would have taken up. */
+ ASSERT_EQ (7, extra_width[10]);
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ location_t line_end = linemap_position_for_column (line_table, line_bytes);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Check that cpp_display_width handles the tabs as expected. */
+ char_span lspan = location_get_source_line (tmp.get_filename (), 1);
+ ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1)));
+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+ {
+ cpp_char_column_policy policy (tabstop, cpp_wcwidth);
+ ASSERT_EQ (line_bytes + extra_width[tabstop],
+ cpp_display_width (lspan.get_buffer (), lspan.length (),
+ policy));
+ ASSERT_EQ (line_bytes + extra_width[tabstop],
+ location_compute_display_column (expand_location (line_end),
+ policy));
+ }
+
+ /* Check that the tab is expanded to the expected number of spaces. */
+ rich_location richloc (line_table,
+ linemap_position_for_column (line_table,
+ tab_col + 1));
+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+ {
+ test_diagnostic_context dc;
+ dc.tabstop = tabstop;
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ test_layout.print_line (1);
+ const char *out = pp_formatted_text (dc.printer);
+ ASSERT_EQ (NULL, strchr (out, '\t'));
+ const char *left_quote = strchr (out, '`');
+ const char *right_quote = strchr (out, '\'');
+ ASSERT_NE (NULL, left_quote);
+ ASSERT_NE (NULL, right_quote);
+ ASSERT_EQ (right_quote - left_quote, extra_width[tabstop] + 2);
+ }
+
+ /* Check that the line is offset properly and that the tab is broken up
+ into the expected number of spaces when it is the last character skipped
+ over. */
+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
+ {
+ test_diagnostic_context dc;
+ dc.tabstop = tabstop;
+ static const int small_width = 24;
+ dc.caret_max_width = small_width - 4;
+ dc.min_margin_width = test_left_margin - test_linenum_sep + 1;
+ dc.show_line_numbers_p = true;
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ test_layout.print_line (1);
+
+ /* We have arranged things so that two columns will be printed before
+ the caret. If the tab results in more than one space, this should
+ produce two spaces in the output; otherwise, it will be a single space
+ preceded by the opening quote before the tab character. */
+ const char *output1
+ = " 1 | ' is a tab that occupies 1 byte and a variable number of "
+ "display columns, starting at column #103.\n"
+ " | ^\n\n";
+ const char *output2
+ = " 1 | ` ' is a tab that occupies 1 byte and a variable number of "
+ "display columns, starting at column #103.\n"
+ " | ^\n\n";
+ const char *expected_output = (extra_width[tabstop] ? output1 : output2);
+ ASSERT_STREQ (expected_output, pp_formatted_text (dc.printer));
+ }
+}
+
+
+/* Verify that diagnostic_show_locus works sanely on UNKNOWN_LOCATION. */
+
+static void
+test_diagnostic_show_locus_unknown_location ()
+{
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("", pp_formatted_text (dc.printer));
+}
+
+/* Verify that diagnostic_show_locus works sanely for various
+ single-line cases.
+
+ All of these work on the following 1-line source file:
+ .0000000001111111
+ .1234567890123456
+ "foo = bar.field;\n"
+ which is set up by test_diagnostic_show_locus_one_liner and calls
+ them. */
+
+/* Just a caret. */
+
+static void
+test_one_liner_simple_caret ()
+{
+ test_diagnostic_context dc;
+ location_t caret = linemap_position_for_column (line_table, 10);
+ rich_location richloc (line_table, caret);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Caret and range. */
+
+static void
+test_one_liner_caret_and_range ()
+{
+ test_diagnostic_context dc;
+ location_t caret = linemap_position_for_column (line_table, 10);
+ location_t start = linemap_position_for_column (line_table, 7);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ location_t loc = make_location (caret, start, finish);
+ rich_location richloc (line_table, loc);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ~~~^~~~~~\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Multiple ranges and carets. */
+
+static void
+test_one_liner_multiple_carets_and_ranges ()
+{
+ test_diagnostic_context dc;
+ location_t foo
+ = make_location (linemap_position_for_column (line_table, 2),
+ linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 3));
+ dc.caret_chars[0] = 'A';
+
+ location_t bar
+ = make_location (linemap_position_for_column (line_table, 8),
+ linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 9));
+ dc.caret_chars[1] = 'B';
+
+ location_t field
+ = make_location (linemap_position_for_column (line_table, 13),
+ linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 15));
+ dc.caret_chars[2] = 'C';
+
+ rich_location richloc (line_table, foo);
+ richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
+ richloc.add_range (field, SHOW_RANGE_WITH_CARET);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ~A~ ~B~ ~~C~~\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Insertion fix-it hint: adding an "&" to the front of "bar.field". */
+
+static void
+test_one_liner_fixit_insert_before ()
+{
+ test_diagnostic_context dc;
+ location_t caret = linemap_position_for_column (line_table, 7);
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_insert_before ("&");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^\n"
+ " &\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Insertion fix-it hint: adding a "[0]" after "foo". */
+
+static void
+test_one_liner_fixit_insert_after ()
+{
+ test_diagnostic_context dc;
+ location_t start = linemap_position_for_column (line_table, 1);
+ location_t finish = linemap_position_for_column (line_table, 3);
+ location_t foo = make_location (start, start, finish);
+ rich_location richloc (line_table, foo);
+ richloc.add_fixit_insert_after ("[0]");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~\n"
+ " [0]\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Removal fix-it hint: removal of the ".field".
+ Also verify the interaction of pp_set_prefix with rulers and
+ fix-it hints. */
+
+static void
+test_one_liner_fixit_remove ()
+{
+ location_t start = linemap_position_for_column (line_table, 10);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ location_t dot = make_location (start, start, finish);
+ rich_location richloc (line_table, dot);
+ richloc.add_fixit_remove ();
+
+ /* Normal. */
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~~~~\n"
+ " ------\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Test of adding a prefix. */
+ {
+ test_diagnostic_context dc;
+ pp_prefixing_rule (dc.printer) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+ pp_set_prefix (dc.printer, xstrdup ("TEST PREFIX:"));
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("TEST PREFIX: foo = bar.field;\n"
+ "TEST PREFIX: ^~~~~~\n"
+ "TEST PREFIX: ------\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Normal, with ruler. */
+ {
+ test_diagnostic_context dc;
+ dc.show_ruler_p = true;
+ dc.caret_max_width = 104;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" 0 0 0 0 0 0 0 0 0 1 \n"
+ " 1 2 3 4 5 6 7 8 9 0 \n"
+ " 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234\n"
+ " foo = bar.field;\n"
+ " ^~~~~~\n"
+ " ------\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Test of adding a prefix, with ruler. */
+ {
+ test_diagnostic_context dc;
+ dc.show_ruler_p = true;
+ dc.caret_max_width = 50;
+ pp_prefixing_rule (dc.printer) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+ pp_set_prefix (dc.printer, xstrdup ("TEST PREFIX:"));
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("TEST PREFIX: 1 2 3 4 5\n"
+ "TEST PREFIX: 12345678901234567890123456789012345678901234567890\n"
+ "TEST PREFIX: foo = bar.field;\n"
+ "TEST PREFIX: ^~~~~~\n"
+ "TEST PREFIX: ------\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Test of adding a prefix, with ruler and line numbers. */
+ {
+ test_diagnostic_context dc;
+ dc.show_ruler_p = true;
+ dc.caret_max_width = 50;
+ dc.show_line_numbers_p = true;
+ pp_prefixing_rule (dc.printer) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+ pp_set_prefix (dc.printer, xstrdup ("TEST PREFIX:"));
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("TEST PREFIX: | 1 2 3 4 5\n"
+ "TEST PREFIX: | 12345678901234567890123456789012345678901234567890\n"
+ "TEST PREFIX: 1 | foo = bar.field;\n"
+ "TEST PREFIX: | ^~~~~~\n"
+ "TEST PREFIX: | ------\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Replace fix-it hint: replacing "field" with "m_field". */
+
+static void
+test_one_liner_fixit_replace ()
+{
+ test_diagnostic_context dc;
+ location_t start = linemap_position_for_column (line_table, 11);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ location_t field = make_location (start, start, finish);
+ rich_location richloc (line_table, field);
+ richloc.add_fixit_replace ("m_field");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~~~\n"
+ " m_field\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Replace fix-it hint: replacing "field" with "m_field",
+ but where the caret was elsewhere. */
+
+static void
+test_one_liner_fixit_replace_non_equal_range ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 5);
+ location_t start = linemap_position_for_column (line_table, 11);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ rich_location richloc (line_table, equals);
+ source_range range;
+ range.m_start = start;
+ range.m_finish = finish;
+ richloc.add_fixit_replace (range, "m_field");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ /* The replacement range is not indicated in the annotation line, so
+ it should be indicated via an additional underline. */
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^\n"
+ " -----\n"
+ " m_field\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Replace fix-it hint: replacing "field" with "m_field",
+ where the caret was elsewhere, but where a secondary range
+ exactly covers "field". */
+
+static void
+test_one_liner_fixit_replace_equal_secondary_range ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 5);
+ location_t start = linemap_position_for_column (line_table, 11);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ rich_location richloc (line_table, equals);
+ location_t field = make_location (start, start, finish);
+ richloc.add_range (field);
+ richloc.add_fixit_replace (field, "m_field");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ /* The replacement range is indicated in the annotation line,
+ so it shouldn't be indicated via an additional underline. */
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^ ~~~~~\n"
+ " m_field\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Verify that we can use ad-hoc locations when adding fixits to a
+ rich_location. */
+
+static void
+test_one_liner_fixit_validation_adhoc_locations ()
+{
+ /* Generate a range that's too long to be packed, so must
+ be stored as an ad-hoc location (given the defaults
+ of 5 bits or 0 bits of packed range); 41 columns > 2**5. */
+ const location_t c7 = linemap_position_for_column (line_table, 7);
+ const location_t c47 = linemap_position_for_column (line_table, 47);
+ const location_t loc = make_location (c7, c7, c47);
+
+ if (c47 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ ASSERT_TRUE (IS_ADHOC_LOC (loc));
+
+ /* Insert. */
+ {
+ rich_location richloc (line_table, loc);
+ richloc.add_fixit_insert_before (loc, "test");
+ /* It should not have been discarded by the validator. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~~~~~~~~ \n"
+ " test\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Remove. */
+ {
+ rich_location richloc (line_table, loc);
+ source_range range = source_range::from_locations (loc, c47);
+ richloc.add_fixit_remove (range);
+ /* It should not have been discarded by the validator. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~~~~~~~~ \n"
+ " -----------------------------------------\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Replace. */
+ {
+ rich_location richloc (line_table, loc);
+ source_range range = source_range::from_locations (loc, c47);
+ richloc.add_fixit_replace (range, "test");
+ /* It should not have been discarded by the validator. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~~~~~~~~ \n"
+ " test\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Test of consolidating insertions at the same location. */
+
+static void
+test_one_liner_many_fixits_1 ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 5);
+ rich_location richloc (line_table, equals);
+ for (int i = 0; i < 19; i++)
+ richloc.add_fixit_insert_before ("a");
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^\n"
+ " aaaaaaaaaaaaaaaaaaa\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Ensure that we can add an arbitrary number of fix-it hints to a
+ rich_location, even if they are not consolidated. */
+
+static void
+test_one_liner_many_fixits_2 ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 5);
+ rich_location richloc (line_table, equals);
+ for (int i = 0; i < 19; i++)
+ {
+ location_t loc = linemap_position_for_column (line_table, (i * 2) + 1);
+ richloc.add_fixit_insert_before (loc, "a");
+ }
+ ASSERT_EQ (19, richloc.get_num_fixit_hints ());
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^\n"
+ " a a a a a a a a a a a a a a a a a a a\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Test of labeling the ranges within a rich_location. */
+
+static void
+test_one_liner_labels ()
+{
+ location_t foo
+ = make_location (linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 3));
+ location_t bar
+ = make_location (linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 9));
+ location_t field
+ = make_location (linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 11),
+ linemap_position_for_column (line_table, 15));
+
+ /* Example where all the labels fit on one line. */
+ {
+ text_range_label label0 ("0");
+ text_range_label label1 ("1");
+ text_range_label label2 ("2");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " 0 1 2\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Verify that we can disable label-printing. */
+ {
+ test_diagnostic_context dc;
+ dc.show_labels_p = false;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+ }
+
+ /* Example where the labels need extra lines. */
+ {
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " | | label 2\n"
+ " | label 1\n"
+ " label 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of boundary conditions: label 0 and 1 have just enough clearance,
+ but label 1 just touches label 2. */
+ {
+ text_range_label label0 ("aaaaa");
+ text_range_label label1 ("bbbb");
+ text_range_label label2 ("c");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~ ~~~ ~~~~~\n"
+ " | | |\n"
+ " | | c\n"
+ " aaaaa bbbb\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of out-of-order ranges (thus requiring a sort). */
+ {
+ text_range_label label0 ("0");
+ text_range_label label1 ("1");
+ text_range_label label2 ("2");
+ gcc_rich_location richloc (field, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ~~~ ~~~ ^~~~~\n"
+ " | | |\n"
+ " 2 1 0\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Ensure we don't ICE if multiple ranges with labels are on
+ the same point. */
+ {
+ text_range_label label0 ("label 0");
+ text_range_label label1 ("label 1");
+ text_range_label label2 ("label 2");
+ gcc_rich_location richloc (bar, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~\n"
+ " |\n"
+ " label 0\n"
+ " label 1\n"
+ " label 2\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of out-of-order ranges (thus requiring a sort), where
+ they overlap, and there are multiple ranges on the same point. */
+ {
+ text_range_label label_0a ("label 0a");
+ text_range_label label_1a ("label 1a");
+ text_range_label label_2a ("label 2a");
+ text_range_label label_0b ("label 0b");
+ text_range_label label_1b ("label 1b");
+ text_range_label label_2b ("label 2b");
+ text_range_label label_0c ("label 0c");
+ text_range_label label_1c ("label 1c");
+ text_range_label label_2c ("label 2c");
+ gcc_rich_location richloc (field, &label_0a);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1a);
+ richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2a);
+
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0b);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1b);
+ richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2b);
+
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label_0c);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label_1c);
+ richloc.add_range (foo, SHOW_RANGE_WITHOUT_CARET, &label_2c);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ~~~ ~~~ ^~~~~\n"
+ " | | |\n"
+ " | | label 0a\n"
+ " | | label 0b\n"
+ " | | label 0c\n"
+ " | label 1a\n"
+ " | label 1b\n"
+ " | label 1c\n"
+ " label 2a\n"
+ " label 2b\n"
+ " label 2c\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Verify that a NULL result from range_label::get_text is
+ handled gracefully. */
+ {
+ text_range_label label (NULL);
+ gcc_rich_location richloc (bar, &label);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar.field;\n"
+ " ^~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* TODO: example of formatted printing (needs to be in
+ gcc-rich-location.cc due to Makefile.in issues). */
+}
+
+/* Run the various one-liner tests. */
+
+static void
+test_diagnostic_show_locus_one_liner (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ....................0000000001111111.
+ ....................1234567890123456. */
+ const char *content = "foo = bar.field;\n";
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ location_t line_end = linemap_position_for_column (line_table, 16);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end));
+ ASSERT_EQ (1, LOCATION_LINE (line_end));
+ ASSERT_EQ (16, LOCATION_COLUMN (line_end));
+
+ test_one_liner_simple_caret ();
+ test_one_liner_caret_and_range ();
+ test_one_liner_multiple_carets_and_ranges ();
+ test_one_liner_fixit_insert_before ();
+ test_one_liner_fixit_insert_after ();
+ test_one_liner_fixit_remove ();
+ test_one_liner_fixit_replace ();
+ test_one_liner_fixit_replace_non_equal_range ();
+ test_one_liner_fixit_replace_equal_secondary_range ();
+ test_one_liner_fixit_validation_adhoc_locations ();
+ test_one_liner_many_fixits_1 ();
+ test_one_liner_many_fixits_2 ();
+ test_one_liner_labels ();
+}
+
+/* Version of all one-liner tests exercising multibyte awareness. For
+ simplicity we stick to using two multibyte characters in the test, U+1F602
+ == "\xf0\x9f\x98\x82", which uses 4 bytes and 2 display columns, and U+03C0
+ == "\xcf\x80", which uses 2 bytes and 1 display column. Note: all of the
+ below asserts would be easier to read if we used UTF-8 directly in the
+ string constants, but it seems better not to demand the host compiler
+ support this, when it isn't otherwise necessary. Instead, whenever an
+ extended character appears in a string, we put a line break after it so that
+ all succeeding characters can appear visually at the correct display column.
+
+ All of these work on the following 1-line source file:
+
+ .0000000001111111111222222 display
+ .1234567890123456789012345 columns
+ "SS_foo = P_bar.SS_fieldP;\n"
+ .0000000111111111222222223 byte
+ .1356789012456789134567891 columns
+
+ which is set up by test_diagnostic_show_locus_one_liner and calls
+ them. Here SS represents the two display columns for the U+1F602 emoji and
+ P represents the one display column for the U+03C0 pi symbol. */
+
+/* Just a caret. */
+
+static void
+test_one_liner_simple_caret_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t caret = linemap_position_for_column (line_table, 18);
+ rich_location richloc (line_table, caret);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Caret and range. */
+static void
+test_one_liner_caret_and_range_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t caret = linemap_position_for_column (line_table, 18);
+ location_t start = linemap_position_for_column (line_table, 12);
+ location_t finish = linemap_position_for_column (line_table, 30);
+ location_t loc = make_location (caret, start, finish);
+ rich_location richloc (line_table, loc);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ~~~~~^~~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Multiple ranges and carets. */
+
+static void
+test_one_liner_multiple_carets_and_ranges_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t foo
+ = make_location (linemap_position_for_column (line_table, 7),
+ linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 8));
+ dc.caret_chars[0] = 'A';
+
+ location_t bar
+ = make_location (linemap_position_for_column (line_table, 16),
+ linemap_position_for_column (line_table, 12),
+ linemap_position_for_column (line_table, 17));
+ dc.caret_chars[1] = 'B';
+
+ location_t field
+ = make_location (linemap_position_for_column (line_table, 26),
+ linemap_position_for_column (line_table, 19),
+ linemap_position_for_column (line_table, 30));
+ dc.caret_chars[2] = 'C';
+ rich_location richloc (line_table, foo);
+ richloc.add_range (bar, SHOW_RANGE_WITH_CARET);
+ richloc.add_range (field, SHOW_RANGE_WITH_CARET);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ~~~~A~ ~~~B~ ~~~~~C~~~\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Insertion fix-it hint: adding an "&" to the front of "P_bar.field". */
+
+static void
+test_one_liner_fixit_insert_before_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t caret = linemap_position_for_column (line_table, 12);
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_insert_before ("&");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^\n"
+ " &\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Insertion fix-it hint: adding a "[0]" after "SS_foo". */
+
+static void
+test_one_liner_fixit_insert_after_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t start = linemap_position_for_column (line_table, 1);
+ location_t finish = linemap_position_for_column (line_table, 8);
+ location_t foo = make_location (start, start, finish);
+ rich_location richloc (line_table, foo);
+ richloc.add_fixit_insert_after ("[0]");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~\n"
+ " [0]\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Removal fix-it hint: removal of the ".SS_fieldP". */
+
+static void
+test_one_liner_fixit_remove_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t start = linemap_position_for_column (line_table, 18);
+ location_t finish = linemap_position_for_column (line_table, 30);
+ location_t dot = make_location (start, start, finish);
+ rich_location richloc (line_table, dot);
+ richloc.add_fixit_remove ();
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~\n"
+ " ----------\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP". */
+
+static void
+test_one_liner_fixit_replace_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t start = linemap_position_for_column (line_table, 19);
+ location_t finish = linemap_position_for_column (line_table, 30);
+ location_t field = make_location (start, start, finish);
+ rich_location richloc (line_table, field);
+ richloc.add_fixit_replace ("m_\xf0\x9f\x98\x82_field\xcf\x80");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~\n"
+ " m_\xf0\x9f\x98\x82"
+ "_field\xcf\x80\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP",
+ but where the caret was elsewhere. */
+
+static void
+test_one_liner_fixit_replace_non_equal_range_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 10);
+ location_t start = linemap_position_for_column (line_table, 19);
+ location_t finish = linemap_position_for_column (line_table, 30);
+ rich_location richloc (line_table, equals);
+ source_range range;
+ range.m_start = start;
+ range.m_finish = finish;
+ richloc.add_fixit_replace (range, "m_\xf0\x9f\x98\x82_field\xcf\x80");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ /* The replacement range is not indicated in the annotation line, so
+ it should be indicated via an additional underline. */
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^\n"
+ " ---------\n"
+ " m_\xf0\x9f\x98\x82"
+ "_field\xcf\x80\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Replace fix-it hint: replacing "SS_fieldP" with "m_SSfieldP",
+ where the caret was elsewhere, but where a secondary range
+ exactly covers "field". */
+
+static void
+test_one_liner_fixit_replace_equal_secondary_range_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 10);
+ location_t start = linemap_position_for_column (line_table, 19);
+ location_t finish = linemap_position_for_column (line_table, 30);
+ rich_location richloc (line_table, equals);
+ location_t field = make_location (start, start, finish);
+ richloc.add_range (field);
+ richloc.add_fixit_replace (field, "m_\xf0\x9f\x98\x82_field\xcf\x80");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ /* The replacement range is indicated in the annotation line,
+ so it shouldn't be indicated via an additional underline. */
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^ ~~~~~~~~~\n"
+ " m_\xf0\x9f\x98\x82"
+ "_field\xcf\x80\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Verify that we can use ad-hoc locations when adding fixits to a
+ rich_location. */
+
+static void
+test_one_liner_fixit_validation_adhoc_locations_utf8 ()
+{
+ /* Generate a range that's too long to be packed, so must
+ be stored as an ad-hoc location (given the defaults
+ of 5 bits or 0 bits of packed range); 41 columns > 2**5. */
+ const location_t c12 = linemap_position_for_column (line_table, 12);
+ const location_t c52 = linemap_position_for_column (line_table, 52);
+ const location_t loc = make_location (c12, c12, c52);
+
+ if (c52 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ ASSERT_TRUE (IS_ADHOC_LOC (loc));
+
+ /* Insert. */
+ {
+ rich_location richloc (line_table, loc);
+ richloc.add_fixit_insert_before (loc, "test");
+ /* It should not have been discarded by the validator. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~~~~~~ \n"
+ " test\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Remove. */
+ {
+ rich_location richloc (line_table, loc);
+ source_range range = source_range::from_locations (loc, c52);
+ richloc.add_fixit_remove (range);
+ /* It should not have been discarded by the validator. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~~~~~~ \n"
+ " -------------------------------------\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Replace. */
+ {
+ rich_location richloc (line_table, loc);
+ source_range range = source_range::from_locations (loc, c52);
+ richloc.add_fixit_replace (range, "test");
+ /* It should not have been discarded by the validator. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~~~~~~ \n"
+ " test\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Test of consolidating insertions at the same location. */
+
+static void
+test_one_liner_many_fixits_1_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 10);
+ rich_location richloc (line_table, equals);
+ for (int i = 0; i < 19; i++)
+ richloc.add_fixit_insert_before (i & 1 ? "@" : "\xcf\x80");
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^\n"
+ " \xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@"
+ "\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80@\xcf\x80\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Ensure that we can add an arbitrary number of fix-it hints to a
+ rich_location, even if they are not consolidated. */
+
+static void
+test_one_liner_many_fixits_2_utf8 ()
+{
+ test_diagnostic_context dc;
+ location_t equals = linemap_position_for_column (line_table, 10);
+ rich_location richloc (line_table, equals);
+ const int nlocs = 19;
+ int locs[nlocs] = {1, 5, 7, 9, 11, 14, 16, 18, 23, 25, 27, 29, 32,
+ 34, 36, 38, 40, 42, 44};
+ for (int i = 0; i != nlocs; ++i)
+ {
+ location_t loc = linemap_position_for_column (line_table, locs[i]);
+ richloc.add_fixit_insert_before (loc, i & 1 ? "@" : "\xcf\x80");
+ }
+
+ ASSERT_EQ (nlocs, richloc.get_num_fixit_hints ());
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^\n"
+ " \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @"
+ " \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80 @ \xcf\x80\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Test of labeling the ranges within a rich_location. */
+
+static void
+test_one_liner_labels_utf8 ()
+{
+ location_t foo
+ = make_location (linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 1),
+ linemap_position_for_column (line_table, 8));
+ location_t bar
+ = make_location (linemap_position_for_column (line_table, 12),
+ linemap_position_for_column (line_table, 12),
+ linemap_position_for_column (line_table, 17));
+ location_t field
+ = make_location (linemap_position_for_column (line_table, 19),
+ linemap_position_for_column (line_table, 19),
+ linemap_position_for_column (line_table, 30));
+
+ /* Example where all the labels fit on one line. */
+ {
+ /* These three labels contain multibyte characters such that their byte
+ lengths are respectively (12, 10, 18), but their display widths are only
+ (6, 5, 9). All three fit on the line when considering the display
+ widths, but not when considering the byte widths, so verify that we do
+ indeed put them all on one line. */
+ text_range_label label0
+ ("\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80");
+ text_range_label label1
+ ("\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80");
+ text_range_label label2
+ ("\xf0\x9f\x98\x82\xcf\x80\xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80"
+ "\xcf\x80");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~ ~~~~~ ~~~~~~~~~\n"
+ " | | |\n"
+ " \xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80\xcf\x80"
+ " \xf0\x9f\x98\x82\xf0\x9f\x98\x82\xcf\x80"
+ " \xf0\x9f\x98\x82\xcf\x80\xf0\x9f\x98\x82"
+ "\xf0\x9f\x98\x82\xcf\x80\xcf\x80\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ }
+
+ /* Example where the labels need extra lines. */
+ {
+ text_range_label label0 ("label 0\xf0\x9f\x98\x82");
+ text_range_label label1 ("label 1\xcf\x80");
+ text_range_label label2 ("label 2\xcf\x80");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~ ~~~~~ ~~~~~~~~~\n"
+ " | | |\n"
+ " | | label 2\xcf\x80\n"
+ " | label 1\xcf\x80\n"
+ " label 0\xf0\x9f\x98\x82\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of boundary conditions: label 0 and 1 have just enough clearance,
+ but label 1 just touches label 2. */
+ {
+ text_range_label label0 ("aaaaa\xf0\x9f\x98\x82\xcf\x80");
+ text_range_label label1 ("bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82");
+ text_range_label label2 ("c");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" \xf0\x9f\x98\x82"
+ "_foo = \xcf\x80"
+ "_bar.\xf0\x9f\x98\x82"
+ "_field\xcf\x80"
+ ";\n"
+ " ^~~~~~ ~~~~~ ~~~~~~~~~\n"
+ " | | |\n"
+ " | | c\n"
+ " aaaaa\xf0\x9f\x98\x82\xcf\x80"
+ " bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of escaping the source lines. */
+ {
+ text_range_label label0 ("label 0\xf0\x9f\x98\x82");
+ text_range_label label1 ("label 1\xcf\x80");
+ text_range_label label2 ("label 2\xcf\x80");
+ gcc_rich_location richloc (foo, &label0);
+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
+ richloc.set_escape_on_output (true);
+
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
+ " ^~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
+ " | | |\n"
+ " | | label 2\xcf\x80\n"
+ " | label 1\xcf\x80\n"
+ " label 0\xf0\x9f\x98\x82\n",
+ pp_formatted_text (dc.printer));
+ }
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ
+ (" <f0><9f><98><82>_foo = <cf><80>_bar.<f0><9f><98><82>_field<cf><80>;\n"
+ " ^~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
+ " | | |\n"
+ " | | label 2\xcf\x80\n"
+ " | label 1\xcf\x80\n"
+ " label 0\xf0\x9f\x98\x82\n",
+ pp_formatted_text (dc.printer));
+ }
+ }
+}
+
+/* Make sure that colorization codes don't interrupt a multibyte
+ sequence, which would corrupt it. */
+static void
+test_one_liner_colorized_utf8 ()
+{
+ test_diagnostic_context dc;
+ dc.colorize_source_p = true;
+ diagnostic_color_init (&dc, DIAGNOSTICS_COLOR_YES);
+ const location_t pi = linemap_position_for_column (line_table, 12);
+ rich_location richloc (line_table, pi);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+
+ /* In order to avoid having the test depend on exactly how the colorization
+ was effected, just confirm there are two pi characters in the output. */
+ const char *result = pp_formatted_text (dc.printer);
+ const char *null_term = result + strlen (result);
+ const char *first_pi = strstr (result, "\xcf\x80");
+ ASSERT_TRUE (first_pi && first_pi <= null_term - 2);
+ ASSERT_STR_CONTAINS (first_pi + 2, "\xcf\x80");
+}
+
+/* Run the various one-liner tests. */
+
+static void
+test_diagnostic_show_locus_one_liner_utf8 (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it. */
+ const char *content
+ /* Display columns.
+ 0000000000000000000000011111111111111111111111111111112222222222222
+ 1111111122222222345678900000000123456666666677777777890123444444445 */
+ = "\xf0\x9f\x98\x82_foo = \xcf\x80_bar.\xf0\x9f\x98\x82_field\xcf\x80;\n";
+ /* 0000000000000000000001111111111111111111222222222222222222222233333
+ 1111222233334444567890122223333456789999000011112222345678999900001
+ Byte columns. */
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ location_t line_end = linemap_position_for_column (line_table, 31);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ ASSERT_STREQ (tmp.get_filename (), LOCATION_FILE (line_end));
+ ASSERT_EQ (1, LOCATION_LINE (line_end));
+ ASSERT_EQ (31, LOCATION_COLUMN (line_end));
+
+ char_span lspan = location_get_source_line (tmp.get_filename (), 1);
+ ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (),
+ def_policy ()));
+ ASSERT_EQ (25, location_compute_display_column (expand_location (line_end),
+ def_policy ()));
+
+ test_one_liner_simple_caret_utf8 ();
+ test_one_liner_caret_and_range_utf8 ();
+ test_one_liner_multiple_carets_and_ranges_utf8 ();
+ test_one_liner_fixit_insert_before_utf8 ();
+ test_one_liner_fixit_insert_after_utf8 ();
+ test_one_liner_fixit_remove_utf8 ();
+ test_one_liner_fixit_replace_utf8 ();
+ test_one_liner_fixit_replace_non_equal_range_utf8 ();
+ test_one_liner_fixit_replace_equal_secondary_range_utf8 ();
+ test_one_liner_fixit_validation_adhoc_locations_utf8 ();
+ test_one_liner_many_fixits_1_utf8 ();
+ test_one_liner_many_fixits_2_utf8 ();
+ test_one_liner_labels_utf8 ();
+ test_one_liner_colorized_utf8 ();
+}
+
+/* Verify that gcc_rich_location::add_location_if_nearby works. */
+
+static void
+test_add_location_if_nearby (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ...000000000111111111122222222223333333333.
+ ...123456789012345678901234567890123456789. */
+ const char *content
+ = ("struct same_line { double x; double y; ;\n" /* line 1. */
+ "struct different_line\n" /* line 2. */
+ "{\n" /* line 3. */
+ " double x;\n" /* line 4. */
+ " double y;\n" /* line 5. */
+ ";\n"); /* line 6. */
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ const line_map_ordinary *ord_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ tmp.get_filename (), 0));
+
+ linemap_line_start (line_table, 1, 100);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 7);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Test of add_location_if_nearby on the same line as the
+ primary location. */
+ {
+ const location_t missing_close_brace_1_39
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 39);
+ const location_t matching_open_brace_1_18
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
+ gcc_rich_location richloc (missing_close_brace_1_39);
+ bool added = richloc.add_location_if_nearby (matching_open_brace_1_18);
+ ASSERT_TRUE (added);
+ ASSERT_EQ (2, richloc.get_num_locations ());
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" struct same_line { double x; double y; ;\n"
+ " ~ ^\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Test of add_location_if_nearby on a different line to the
+ primary location. */
+ {
+ const location_t missing_close_brace_6_1
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 1);
+ const location_t matching_open_brace_3_1
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 1);
+ gcc_rich_location richloc (missing_close_brace_6_1);
+ bool added = richloc.add_location_if_nearby (matching_open_brace_3_1);
+ ASSERT_FALSE (added);
+ ASSERT_EQ (1, richloc.get_num_locations ());
+ }
+}
+
+/* Verify that we print fixits even if they only affect lines
+ outside those covered by the ranges in the rich_location. */
+
+static void
+test_diagnostic_show_locus_fixit_lines (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ...000000000111111111122222222223333333333.
+ ...123456789012345678901234567890123456789. */
+ const char *content
+ = ("struct point { double x; double y; };\n" /* line 1. */
+ "struct point origin = {x: 0.0,\n" /* line 2. */
+ " y\n" /* line 3. */
+ "\n" /* line 4. */
+ "\n" /* line 5. */
+ " : 0.0};\n"); /* line 6. */
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ const line_map_ordinary *ord_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ tmp.get_filename (), 0));
+
+ linemap_line_start (line_table, 1, 100);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 36);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* A pair of tests for modernizing the initializers to C99-style. */
+
+ /* The one-liner case (line 2). */
+ {
+ test_diagnostic_context dc;
+ const location_t x
+ = linemap_position_for_line_and_column (line_table, ord_map, 2, 24);
+ const location_t colon
+ = linemap_position_for_line_and_column (line_table, ord_map, 2, 25);
+ rich_location richloc (line_table, colon);
+ richloc.add_fixit_insert_before (x, ".");
+ richloc.add_fixit_replace (colon, "=");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" struct point origin = {x: 0.0,\n"
+ " ^\n"
+ " .=\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* The multiline case. The caret for the rich_location is on line 6;
+ verify that insertion fixit on line 3 is still printed (and that
+ span starts are printed due to the gap between the span at line 3
+ and that at line 6). */
+ {
+ test_diagnostic_context dc;
+ const location_t y
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
+ const location_t colon
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
+ rich_location richloc (line_table, colon);
+ richloc.add_fixit_insert_before (y, ".");
+ richloc.add_fixit_replace (colon, "=");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("FILENAME:3:24:\n"
+ " y\n"
+ " .\n"
+ "FILENAME:6:25:\n"
+ " : 0.0};\n"
+ " ^\n"
+ " =\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* As above, but verify the behavior of multiple line spans
+ with line-numbering enabled. */
+ {
+ const location_t y
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 24);
+ const location_t colon
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 25);
+ rich_location richloc (line_table, colon);
+ richloc.add_fixit_insert_before (y, ".");
+ richloc.add_fixit_replace (colon, "=");
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" 3 | y\n"
+ " | .\n"
+ "......\n"
+ " 6 | : 0.0};\n"
+ " | ^\n"
+ " | =\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+
+/* Verify that fix-it hints are appropriately consolidated.
+
+ If any fix-it hints in a rich_location involve locations beyond
+ LINE_MAP_MAX_LOCATION_WITH_COLS, then we can't reliably apply
+ the fix-it as a whole, so there should be none.
+
+ Otherwise, verify that consecutive "replace" and "remove" fix-its
+ are merged, and that other fix-its remain separate. */
+
+static void
+test_fixit_consolidation (const line_table_case &case_)
+{
+ line_table_test ltt (case_);
+
+ linemap_add (line_table, LC_ENTER, false, "test.c", 1);
+
+ const location_t c10 = linemap_position_for_column (line_table, 10);
+ const location_t c15 = linemap_position_for_column (line_table, 15);
+ const location_t c16 = linemap_position_for_column (line_table, 16);
+ const location_t c17 = linemap_position_for_column (line_table, 17);
+ const location_t c20 = linemap_position_for_column (line_table, 20);
+ const location_t c21 = linemap_position_for_column (line_table, 21);
+ const location_t caret = c10;
+
+ /* Insert + insert. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_insert_before (c10, "foo");
+ richloc.add_fixit_insert_before (c15, "bar");
+
+ if (c15 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ /* They should not have been merged. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ }
+
+ /* Insert + replace. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_insert_before (c10, "foo");
+ richloc.add_fixit_replace (source_range::from_locations (c15, c17),
+ "bar");
+
+ if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ /* They should not have been merged. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ }
+
+ /* Replace + non-consecutive insert. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ "bar");
+ richloc.add_fixit_insert_before (c17, "foo");
+
+ if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ /* They should not have been merged. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ }
+
+ /* Replace + non-consecutive replace. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ "foo");
+ richloc.add_fixit_replace (source_range::from_locations (c17, c20),
+ "bar");
+
+ if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ /* They should not have been merged. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ }
+
+ /* Replace + consecutive replace. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ "foo");
+ richloc.add_fixit_replace (source_range::from_locations (c16, c20),
+ "bar");
+
+ if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ {
+ /* They should have been merged into a single "replace". */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint = richloc.get_fixit_hint (0);
+ ASSERT_STREQ ("foobar", hint->get_string ());
+ ASSERT_EQ (c10, hint->get_start_loc ());
+ ASSERT_EQ (c21, hint->get_next_loc ());
+ }
+ }
+
+ /* Replace + consecutive removal. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_replace (source_range::from_locations (c10, c15),
+ "foo");
+ richloc.add_fixit_remove (source_range::from_locations (c16, c20));
+
+ if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ {
+ /* They should have been merged into a single replace, with the
+ range extended to cover that of the removal. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint = richloc.get_fixit_hint (0);
+ ASSERT_STREQ ("foo", hint->get_string ());
+ ASSERT_EQ (c10, hint->get_start_loc ());
+ ASSERT_EQ (c21, hint->get_next_loc ());
+ }
+ }
+
+ /* Consecutive removals. */
+ {
+ rich_location richloc (line_table, caret);
+ richloc.add_fixit_remove (source_range::from_locations (c10, c15));
+ richloc.add_fixit_remove (source_range::from_locations (c16, c20));
+
+ if (c20 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* Bogus column info for 2nd fixit, so no fixits. */
+ ASSERT_EQ (0, richloc.get_num_fixit_hints ());
+ else
+ {
+ /* They should have been merged into a single "replace-with-empty". */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint = richloc.get_fixit_hint (0);
+ ASSERT_STREQ ("", hint->get_string ());
+ ASSERT_EQ (c10, hint->get_start_loc ());
+ ASSERT_EQ (c21, hint->get_next_loc ());
+ }
+ }
+}
+
+/* Verify that the line_corrections machinery correctly prints
+ overlapping fixit-hints. */
+
+static void
+test_overlapped_fixit_printing (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ...000000000111111111122222222223333333333.
+ ...123456789012345678901234567890123456789. */
+ const char *content
+ = (" foo *f = (foo *)ptr->field;\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+ line_table_test ltt (case_);
+
+ const line_map_ordinary *ord_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ tmp.get_filename (), 0));
+
+ linemap_line_start (line_table, 1, 100);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 36);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* A test for converting a C-style cast to a C++-style cast. */
+ const location_t open_paren
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 12);
+ const location_t close_paren
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 18);
+ const location_t expr_start
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 19);
+ const location_t expr_finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 28);
+ const location_t expr = make_location (expr_start, expr_start, expr_finish);
+
+ /* Various examples of fix-it hints that aren't themselves consolidated,
+ but for which the *printing* may need consolidation. */
+
+ /* Example where 3 fix-it hints are printed as one. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_replace (open_paren, "const_cast<");
+ richloc.add_fixit_replace (close_paren, "> (");
+ richloc.add_fixit_insert_after (")");
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo *f = (foo *)ptr->field;\n"
+ " ^~~~~~~~~~\n"
+ " -----------------\n"
+ " const_cast<foo *> (ptr->field)\n",
+ pp_formatted_text (dc.printer));
+
+ /* Unit-test the line_corrections machinery. */
+ char_display_policy policy (make_policy (dc, richloc));
+ ASSERT_EQ (3, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+ ASSERT_EQ (column_range (12, 12),
+ get_affected_range (policy, hint_0, CU_BYTES));
+ ASSERT_EQ (column_range (12, 12),
+ get_affected_range (policy, hint_0, CU_DISPLAY_COLS));
+ ASSERT_EQ (column_range (12, 22), get_printed_columns (policy, hint_0));
+ const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+ ASSERT_EQ (column_range (18, 18),
+ get_affected_range (policy, hint_1, CU_BYTES));
+ ASSERT_EQ (column_range (18, 18),
+ get_affected_range (policy, hint_1, CU_DISPLAY_COLS));
+ ASSERT_EQ (column_range (18, 20), get_printed_columns (policy, hint_1));
+ const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
+ ASSERT_EQ (column_range (29, 28),
+ get_affected_range (policy, hint_2, CU_BYTES));
+ ASSERT_EQ (column_range (29, 28),
+ get_affected_range (policy, hint_2, CU_DISPLAY_COLS));
+ ASSERT_EQ (column_range (29, 29), get_printed_columns (policy, hint_2));
+
+ /* Add each hint in turn to a line_corrections instance,
+ and verify that they are consolidated into one correction instance
+ as expected. */
+ line_corrections lc (policy, tmp.get_filename (), 1);
+
+ /* The first replace hint by itself. */
+ lc.add_hint (hint_0);
+ ASSERT_EQ (1, lc.m_corrections.length ());
+ ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_bytes);
+ ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_columns);
+ ASSERT_EQ (column_range (12, 22), lc.m_corrections[0]->m_printed_columns);
+ ASSERT_STREQ ("const_cast<", lc.m_corrections[0]->m_text);
+
+ /* After the second replacement hint, they are printed together
+ as a replacement (along with the text between them). */
+ lc.add_hint (hint_1);
+ ASSERT_EQ (1, lc.m_corrections.length ());
+ ASSERT_STREQ ("const_cast<foo *> (", lc.m_corrections[0]->m_text);
+ ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_bytes);
+ ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_columns);
+ ASSERT_EQ (column_range (12, 30), lc.m_corrections[0]->m_printed_columns);
+
+ /* After the final insertion hint, they are all printed together
+ as a replacement (along with the text between them). */
+ lc.add_hint (hint_2);
+ ASSERT_STREQ ("const_cast<foo *> (ptr->field)",
+ lc.m_corrections[0]->m_text);
+ ASSERT_EQ (1, lc.m_corrections.length ());
+ ASSERT_EQ (column_range (12, 28), lc.m_corrections[0]->m_affected_bytes);
+ ASSERT_EQ (column_range (12, 28), lc.m_corrections[0]->m_affected_columns);
+ ASSERT_EQ (column_range (12, 41), lc.m_corrections[0]->m_printed_columns);
+ }
+
+ /* Example where two are consolidated during printing. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_replace (open_paren, "CAST (");
+ richloc.add_fixit_replace (close_paren, ") (");
+ richloc.add_fixit_insert_after (")");
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo *f = (foo *)ptr->field;\n"
+ " ^~~~~~~~~~\n"
+ " -\n"
+ " CAST (-\n"
+ " ) ( )\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example where none are consolidated during printing. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_replace (open_paren, "CST (");
+ richloc.add_fixit_replace (close_paren, ") (");
+ richloc.add_fixit_insert_after (")");
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo *f = (foo *)ptr->field;\n"
+ " ^~~~~~~~~~\n"
+ " -\n"
+ " CST ( -\n"
+ " ) ( )\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of deletion fix-it hints. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_insert_before (open_paren, "(bar *)");
+ source_range victim = {open_paren, close_paren};
+ richloc.add_fixit_remove (victim);
+
+ /* This case is actually handled by fixit-consolidation,
+ rather than by line_corrections. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo *f = (foo *)ptr->field;\n"
+ " ^~~~~~~~~~\n"
+ " -------\n"
+ " (bar *)\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of deletion fix-it hints that would overlap. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_insert_before (open_paren, "(longer *)");
+ source_range victim = {expr_start, expr_finish};
+ richloc.add_fixit_remove (victim);
+
+ /* These fixits are not consolidated. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+
+ /* But the corrections are. */
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo *f = (foo *)ptr->field;\n"
+ " ^~~~~~~~~~\n"
+ " -----------------\n"
+ " (longer *)(foo *)\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of insertion fix-it hints that would overlap. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_insert_before (open_paren, "LONGER THAN THE CAST");
+ richloc.add_fixit_insert_after (close_paren, "TEST");
+
+ /* The first insertion is long enough that if printed naively,
+ it would overlap with the second.
+ Verify that they are printed as a single replacement. */
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo *f = (foo *)ptr->field;\n"
+ " ^~~~~~~~~~\n"
+ " -------\n"
+ " LONGER THAN THE CAST(foo *)TEST\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Multibyte-aware version of preceding tests. See comments above
+ test_one_liner_simple_caret_utf8() too, we use the same two multibyte
+ characters here. */
+
+static void
+test_overlapped_fixit_printing_utf8 (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it. */
+
+ const char *content
+ /* Display columns.
+ 00000000000000000000000111111111111111111111111222222222222222223
+ 12344444444555555556789012344444444555555556789012345678999999990 */
+ = " f\xf0\x9f\x98\x82 *f = (f\xf0\x9f\x98\x82 *)ptr->field\xcf\x80;\n";
+ /* 00000000000000000000011111111111111111111112222222222333333333333
+ 12344445555666677778901234566667777888899990123456789012333344445
+ Byte columns. */
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+ line_table_test ltt (case_);
+
+ const line_map_ordinary *ord_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ tmp.get_filename (), 0));
+
+ linemap_line_start (line_table, 1, 100);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 6, 50);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* A test for converting a C-style cast to a C++-style cast. */
+ const location_t open_paren
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 14);
+ const location_t close_paren
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 22);
+ const location_t expr_start
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
+ const location_t expr_finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 34);
+ const location_t expr = make_location (expr_start, expr_start, expr_finish);
+
+ /* Various examples of fix-it hints that aren't themselves consolidated,
+ but for which the *printing* may need consolidation. */
+
+ /* Example where 3 fix-it hints are printed as one. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_replace (open_paren, "const_cast<");
+ richloc.add_fixit_replace (close_paren, "> (");
+ richloc.add_fixit_insert_after (")");
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" f\xf0\x9f\x98\x82"
+ " *f = (f\xf0\x9f\x98\x82"
+ " *)ptr->field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~\n"
+ " ------------------\n"
+ " const_cast<f\xf0\x9f\x98\x82"
+ " *> (ptr->field\xcf\x80"
+ ")\n",
+ pp_formatted_text (dc.printer));
+
+ /* Unit-test the line_corrections machinery. */
+ char_display_policy policy (make_policy (dc, richloc));
+ ASSERT_EQ (3, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+ ASSERT_EQ (column_range (14, 14),
+ get_affected_range (policy, hint_0, CU_BYTES));
+ ASSERT_EQ (column_range (12, 12),
+ get_affected_range (policy, hint_0, CU_DISPLAY_COLS));
+ ASSERT_EQ (column_range (12, 22), get_printed_columns (policy, hint_0));
+ const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+ ASSERT_EQ (column_range (22, 22),
+ get_affected_range (policy, hint_1, CU_BYTES));
+ ASSERT_EQ (column_range (18, 18),
+ get_affected_range (policy, hint_1, CU_DISPLAY_COLS));
+ ASSERT_EQ (column_range (18, 20), get_printed_columns (policy, hint_1));
+ const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
+ ASSERT_EQ (column_range (35, 34),
+ get_affected_range (policy, hint_2, CU_BYTES));
+ ASSERT_EQ (column_range (30, 29),
+ get_affected_range (policy, hint_2, CU_DISPLAY_COLS));
+ ASSERT_EQ (column_range (30, 30), get_printed_columns (policy, hint_2));
+
+ /* Add each hint in turn to a line_corrections instance,
+ and verify that they are consolidated into one correction instance
+ as expected. */
+ line_corrections lc (policy, tmp.get_filename (), 1);
+
+ /* The first replace hint by itself. */
+ lc.add_hint (hint_0);
+ ASSERT_EQ (1, lc.m_corrections.length ());
+ ASSERT_EQ (column_range (14, 14), lc.m_corrections[0]->m_affected_bytes);
+ ASSERT_EQ (column_range (12, 12), lc.m_corrections[0]->m_affected_columns);
+ ASSERT_EQ (column_range (12, 22), lc.m_corrections[0]->m_printed_columns);
+ ASSERT_STREQ ("const_cast<", lc.m_corrections[0]->m_text);
+
+ /* After the second replacement hint, they are printed together
+ as a replacement (along with the text between them). */
+ lc.add_hint (hint_1);
+ ASSERT_EQ (1, lc.m_corrections.length ());
+ ASSERT_STREQ ("const_cast<f\xf0\x9f\x98\x82 *> (",
+ lc.m_corrections[0]->m_text);
+ ASSERT_EQ (column_range (14, 22), lc.m_corrections[0]->m_affected_bytes);
+ ASSERT_EQ (column_range (12, 18), lc.m_corrections[0]->m_affected_columns);
+ ASSERT_EQ (column_range (12, 30), lc.m_corrections[0]->m_printed_columns);
+
+ /* After the final insertion hint, they are all printed together
+ as a replacement (along with the text between them). */
+ lc.add_hint (hint_2);
+ ASSERT_STREQ ("const_cast<f\xf0\x9f\x98\x82 *> (ptr->field\xcf\x80)",
+ lc.m_corrections[0]->m_text);
+ ASSERT_EQ (1, lc.m_corrections.length ());
+ ASSERT_EQ (column_range (14, 34), lc.m_corrections[0]->m_affected_bytes);
+ ASSERT_EQ (column_range (12, 29), lc.m_corrections[0]->m_affected_columns);
+ ASSERT_EQ (column_range (12, 42), lc.m_corrections[0]->m_printed_columns);
+ }
+
+ /* Example where two are consolidated during printing. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_replace (open_paren, "CAST (");
+ richloc.add_fixit_replace (close_paren, ") (");
+ richloc.add_fixit_insert_after (")");
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" f\xf0\x9f\x98\x82"
+ " *f = (f\xf0\x9f\x98\x82"
+ " *)ptr->field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~\n"
+ " -\n"
+ " CAST (-\n"
+ " ) ( )\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example where none are consolidated during printing. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_replace (open_paren, "CST (");
+ richloc.add_fixit_replace (close_paren, ") (");
+ richloc.add_fixit_insert_after (")");
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" f\xf0\x9f\x98\x82"
+ " *f = (f\xf0\x9f\x98\x82"
+ " *)ptr->field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~\n"
+ " -\n"
+ " CST ( -\n"
+ " ) ( )\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of deletion fix-it hints. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_insert_before (open_paren, "(bar\xf0\x9f\x98\x82 *)");
+ source_range victim = {open_paren, close_paren};
+ richloc.add_fixit_remove (victim);
+
+ /* This case is actually handled by fixit-consolidation,
+ rather than by line_corrections. */
+ ASSERT_EQ (1, richloc.get_num_fixit_hints ());
+
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" f\xf0\x9f\x98\x82"
+ " *f = (f\xf0\x9f\x98\x82"
+ " *)ptr->field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~\n"
+ " -------\n"
+ " (bar\xf0\x9f\x98\x82"
+ " *)\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of deletion fix-it hints that would overlap. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_insert_before (open_paren, "(long\xf0\x9f\x98\x82 *)");
+ source_range victim = {expr_start, expr_finish};
+ richloc.add_fixit_remove (victim);
+
+ /* These fixits are not consolidated. */
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+
+ /* But the corrections are. */
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" f\xf0\x9f\x98\x82"
+ " *f = (f\xf0\x9f\x98\x82"
+ " *)ptr->field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~\n"
+ " ------------------\n"
+ " (long\xf0\x9f\x98\x82"
+ " *)(f\xf0\x9f\x98\x82"
+ " *)\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Example of insertion fix-it hints that would overlap. */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, expr);
+ richloc.add_fixit_insert_before
+ (open_paren, "L\xf0\x9f\x98\x82NGER THAN THE CAST");
+ richloc.add_fixit_insert_after (close_paren, "TEST");
+
+ /* The first insertion is long enough that if printed naively,
+ it would overlap with the second.
+ Verify that they are printed as a single replacement. */
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" f\xf0\x9f\x98\x82"
+ " *f = (f\xf0\x9f\x98\x82"
+ " *)ptr->field\xcf\x80"
+ ";\n"
+ " ^~~~~~~~~~~\n"
+ " -------\n"
+ " L\xf0\x9f\x98\x82"
+ "NGER THAN THE CAST(f\xf0\x9f\x98\x82"
+ " *)TEST\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Verify that the line_corrections machinery correctly prints
+ overlapping fixit-hints that have been added in the wrong
+ order.
+ Adapted from PR c/81405 seen on gcc.dg/init-excess-1.c*/
+
+static void
+test_overlapped_fixit_printing_2 (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ...000000000111111111122222222223333333333.
+ ...123456789012345678901234567890123456789. */
+ const char *content
+ = ("int a5[][0][0] = { 1, 2 };\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+
+ const line_map_ordinary *ord_map
+ = linemap_check_ordinary (linemap_add (line_table, LC_ENTER, false,
+ tmp.get_filename (), 0));
+
+ linemap_line_start (line_table, 1, 100);
+
+ const location_t final_line_end
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 100);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ if (final_line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ const location_t col_1
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
+ const location_t col_20
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 20);
+ const location_t col_21
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 21);
+ const location_t col_23
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 23);
+ const location_t col_25
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 25);
+
+ /* Two insertions, in the wrong order. */
+ {
+ test_diagnostic_context dc;
+
+ rich_location richloc (line_table, col_20);
+ richloc.add_fixit_insert_before (col_23, "{");
+ richloc.add_fixit_insert_before (col_21, "}");
+
+ /* These fixits should be accepted; they can't be consolidated. */
+ char_display_policy policy (make_policy (dc, richloc));
+ ASSERT_EQ (2, richloc.get_num_fixit_hints ());
+ const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
+ ASSERT_EQ (column_range (23, 22),
+ get_affected_range (policy, hint_0, CU_BYTES));
+ ASSERT_EQ (column_range (23, 23), get_printed_columns (policy, hint_0));
+ const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
+ ASSERT_EQ (column_range (21, 20),
+ get_affected_range (policy, hint_1, CU_BYTES));
+ ASSERT_EQ (column_range (21, 21), get_printed_columns (policy, hint_1));
+
+ /* Verify that they're printed correctly. */
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
+ " ^\n"
+ " } {\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Various overlapping insertions, some occurring "out of order"
+ (reproducing the fix-it hints from PR c/81405). */
+ {
+ test_diagnostic_context dc;
+ rich_location richloc (line_table, col_20);
+
+ richloc.add_fixit_insert_before (col_20, "{{");
+ richloc.add_fixit_insert_before (col_21, "}}");
+ richloc.add_fixit_insert_before (col_23, "{");
+ richloc.add_fixit_insert_before (col_21, "}");
+ richloc.add_fixit_insert_before (col_23, "{{");
+ richloc.add_fixit_insert_before (col_25, "}");
+ richloc.add_fixit_insert_before (col_21, "}");
+ richloc.add_fixit_insert_before (col_1, "{");
+ richloc.add_fixit_insert_before (col_25, "}");
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
+ " ^\n"
+ " { -----\n"
+ " {{1}}}}, {{{2 }}\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Insertion fix-it hint: adding a "break;" on a line by itself. */
+
+static void
+test_fixit_insert_containing_newline (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = (" case 'a':\n" /* line 1. */
+ " x = a;\n" /* line 2. */
+ " case 'b':\n" /* line 3. */
+ " x = b;\n");/* line 4. */
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+
+ location_t case_start = linemap_position_for_column (line_table, 5);
+ location_t case_finish = linemap_position_for_column (line_table, 13);
+ location_t case_loc = make_location (case_start, case_start, case_finish);
+ location_t line_start = linemap_position_for_column (line_table, 1);
+
+ if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Add a "break;" on a line by itself before line 3 i.e. before
+ column 1 of line 3. */
+ {
+ rich_location richloc (line_table, case_loc);
+ richloc.add_fixit_insert_before (line_start, " break;\n");
+
+ /* Without line numbers. */
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" x = a;\n"
+ "+ break;\n"
+ " case 'b':\n"
+ " ^~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* With line numbers. */
+ {
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" 2 | x = a;\n"
+ " +++ |+ break;\n"
+ " 3 | case 'b':\n"
+ " | ^~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+ }
+
+ /* Verify that attempts to add text with a newline fail when the
+ insertion point is *not* at the start of a line. */
+ {
+ rich_location richloc (line_table, case_loc);
+ richloc.add_fixit_insert_before (case_start, "break;\n");
+ ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" case 'b':\n"
+ " ^~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Insertion fix-it hint: adding a "#include <stdio.h>\n" to the top
+ of the file, where the fix-it is printed in a different line-span
+ to the primary range of the diagnostic. */
+
+static void
+test_fixit_insert_containing_newline_2 (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = ("test (int ch)\n" /* line 1. */
+ "{\n" /* line 2. */
+ " putchar (ch);\n" /* line 3. */
+ "}\n"); /* line 4. */
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ line_table_test ltt (case_);
+
+ const line_map_ordinary *ord_map = linemap_check_ordinary
+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+ linemap_line_start (line_table, 1, 100);
+
+ /* The primary range is the "putchar" token. */
+ location_t putchar_start
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 2);
+ location_t putchar_finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 3, 8);
+ location_t putchar_loc
+ = make_location (putchar_start, putchar_start, putchar_finish);
+ rich_location richloc (line_table, putchar_loc);
+
+ /* Add a "#include <stdio.h>" on a line by itself at the top of the file. */
+ location_t file_start
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
+ richloc.add_fixit_insert_before (file_start, "#include <stdio.h>\n");
+
+ if (putchar_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ ("FILENAME:1:1:\n"
+ "+#include <stdio.h>\n"
+ " test (int ch)\n"
+ "FILENAME:3:2:\n"
+ " putchar (ch);\n"
+ " ^~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* With line-numbering, the line spans are close enough to be
+ consolidated, since it makes little sense to skip line 2. */
+ {
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" +++ |+#include <stdio.h>\n"
+ " 1 | test (int ch)\n"
+ " 2 | {\n"
+ " 3 | putchar (ch);\n"
+ " | ^~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Replacement fix-it hint containing a newline.
+ This will fail, as newlines are only supported when inserting at the
+ beginning of a line. */
+
+static void
+test_fixit_replace_containing_newline (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111.
+ .........................1234567890123. */
+ const char *old_content = "foo = bar ();\n";
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ /* Replace the " = " with "\n = ", as if we were reformatting an
+ overly long line. */
+ location_t start = linemap_position_for_column (line_table, 4);
+ location_t finish = linemap_position_for_column (line_table, 6);
+ location_t loc = linemap_position_for_column (line_table, 13);
+ rich_location richloc (line_table, loc);
+ source_range range = source_range::from_locations (start, finish);
+ richloc.add_fixit_replace (range, "\n =");
+
+ /* Arbitrary newlines are not yet supported within fix-it hints, so
+ the fix-it should not be displayed. */
+ ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+
+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar ();\n"
+ " ^\n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Fix-it hint, attempting to delete a newline.
+ This will fail, as we currently only support fix-it hints that
+ affect one line at a time. */
+
+static void
+test_fixit_deletion_affecting_newline (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ..........................0000000001111.
+ ..........................1234567890123. */
+ const char *old_content = ("foo = bar (\n"
+ " );\n");
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ line_table_test ltt (case_);
+ const line_map_ordinary *ord_map = linemap_check_ordinary
+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+ linemap_line_start (line_table, 1, 100);
+
+ /* Attempt to delete the " (\n...)". */
+ location_t start
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 10);
+ location_t caret
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
+ location_t finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 2, 7);
+ location_t loc = make_location (caret, start, finish);
+ rich_location richloc (line_table, loc);
+ richloc. add_fixit_remove ();
+
+ /* Fix-it hints that affect more than one line are not yet supported, so
+ the fix-it should not be displayed. */
+ ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+
+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" foo = bar (\n"
+ " ~^\n"
+ " );\n"
+ " ~ \n",
+ pp_formatted_text (dc.printer));
+}
+
+static void
+test_tab_expansion (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it. This example uses a tabstop
+ of 8, as the column numbers attempt to indicate:
+
+ .....................000.01111111111.22222333333 display
+ .....................123.90123456789.56789012345 columns */
+ const char *content = " \t This: `\t' is a tab.\n";
+ /* ....................000 00000011111 11111222222 byte
+ ....................123 45678901234 56789012345 columns */
+
+ const int tabstop = 8;
+ cpp_char_column_policy policy (tabstop, cpp_wcwidth);
+ const int first_non_ws_byte_col = 7;
+ const int right_quote_byte_col = 15;
+ const int last_byte_col = 25;
+ ASSERT_EQ (35, cpp_display_width (content, last_byte_col, policy));
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ /* Don't attempt to run the tests if column data might be unavailable. */
+ location_t line_end = linemap_position_for_column (line_table, last_byte_col);
+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Check that the leading whitespace with mixed tabs and spaces is expanded
+ into 11 spaces. Recall that print_line() also puts one space before
+ everything too. */
+ {
+ test_diagnostic_context dc;
+ dc.tabstop = tabstop;
+ rich_location richloc (line_table,
+ linemap_position_for_column (line_table,
+ first_non_ws_byte_col));
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ test_layout.print_line (1);
+ ASSERT_STREQ (" This: ` ' is a tab.\n"
+ " ^\n",
+ pp_formatted_text (dc.printer));
+ }
+
+ /* Confirm the display width was tracked correctly across the internal tab
+ as well. */
+ {
+ test_diagnostic_context dc;
+ dc.tabstop = tabstop;
+ rich_location richloc (line_table,
+ linemap_position_for_column (line_table,
+ right_quote_byte_col));
+ layout test_layout (&dc, &richloc, DK_ERROR);
+ test_layout.print_line (1);
+ ASSERT_STREQ (" This: ` ' is a tab.\n"
+ " ^\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Verify that the escaping machinery can cope with a variety of different
+ invalid bytes. */
+
+static void
+test_escaping_bytes_1 (const line_table_case &case_)
+{
+ const char content[] = "before\0\1\2\3\r\x80\xff""after\n";
+ const size_t sz = sizeof (content);
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
+ line_table_test ltt (case_);
+ const line_map_ordinary *ord_map = linemap_check_ordinary
+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+ linemap_line_start (line_table, 1, 100);
+
+ location_t finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 1,
+ strlen (content));
+
+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Locations of the NUL and \r bytes. */
+ location_t nul_loc
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 7);
+ location_t r_loc
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
+ gcc_rich_location richloc (nul_loc);
+ richloc.add_range (r_loc);
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" before \1\2\3 \x80\xff""after\n"
+ " ^ ~\n",
+ pp_formatted_text (dc.printer));
+ }
+ richloc.set_escape_on_output (true);
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ
+ (" before<U+0000><U+0001><U+0002><U+0003><U+000D><80><ff>after\n"
+ " ^~~~~~~~ ~~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" before<00><01><02><03><0d><80><ff>after\n"
+ " ^~~~ ~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* As above, but verify that we handle the initial byte of a line
+ correctly. */
+
+static void
+test_escaping_bytes_2 (const line_table_case &case_)
+{
+ const char content[] = "\0after\n";
+ const size_t sz = sizeof (content);
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
+ line_table_test ltt (case_);
+ const line_map_ordinary *ord_map = linemap_check_ordinary
+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+ linemap_line_start (line_table, 1, 100);
+
+ location_t finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 1,
+ strlen (content));
+
+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Location of the NUL byte. */
+ location_t nul_loc
+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
+ gcc_rich_location richloc (nul_loc);
+
+ {
+ test_diagnostic_context dc;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" after\n"
+ " ^\n",
+ pp_formatted_text (dc.printer));
+ }
+ richloc.set_escape_on_output (true);
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" <U+0000>after\n"
+ " ^~~~~~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+ {
+ test_diagnostic_context dc;
+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" <00>after\n"
+ " ^~~~\n",
+ pp_formatted_text (dc.printer));
+ }
+}
+
+/* Verify that line numbers are correctly printed for the case of
+ a multiline range in which the width of the line numbers changes
+ (e.g. from "9" to "10"). */
+
+static void
+test_line_numbers_multiline_range ()
+{
+ /* Create a tempfile and write some text to it. */
+ pretty_printer pp;
+ for (int i = 0; i < 20; i++)
+ /* .........0000000001111111.
+ .............1234567890123456. */
+ pp_printf (&pp, "this is line %i\n", i + 1);
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", pp_formatted_text (&pp));
+ line_table_test ltt;
+
+ const line_map_ordinary *ord_map = linemap_check_ordinary
+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
+ linemap_line_start (line_table, 1, 100);
+
+ /* Create a multi-line location, starting at the "line" of line 9, with
+ a caret on the "is" of line 10, finishing on the "this" line 11. */
+
+ location_t start
+ = linemap_position_for_line_and_column (line_table, ord_map, 9, 9);
+ location_t caret
+ = linemap_position_for_line_and_column (line_table, ord_map, 10, 6);
+ location_t finish
+ = linemap_position_for_line_and_column (line_table, ord_map, 11, 4);
+ location_t loc = make_location (caret, start, finish);
+
+ test_diagnostic_context dc;
+ dc.show_line_numbers_p = true;
+ dc.min_margin_width = 0;
+ gcc_rich_location richloc (loc);
+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
+ ASSERT_STREQ (" 9 | this is line 9\n"
+ " | ~~~~~~\n"
+ "10 | this is line 10\n"
+ " | ~~~~~^~~~~~~~~~\n"
+ "11 | this is line 11\n"
+ " | ~~~~ \n",
+ pp_formatted_text (dc.printer));
+}
+
+/* Run all of the selftests within this file. */
+
+void
+diagnostic_show_locus_cc_tests ()
+{
+ test_line_span ();
+
+ test_layout_range_for_single_point ();
+ test_layout_range_for_single_line ();
+ test_layout_range_for_multiple_lines ();
+
+ test_display_widths ();
+
+ for_each_line_table_case (test_layout_x_offset_display_utf8);
+ for_each_line_table_case (test_layout_x_offset_display_tab);
+
+ test_get_line_bytes_without_trailing_whitespace ();
+
+ test_diagnostic_show_locus_unknown_location ();
+
+ for_each_line_table_case (test_diagnostic_show_locus_one_liner);
+ for_each_line_table_case (test_diagnostic_show_locus_one_liner_utf8);
+ for_each_line_table_case (test_add_location_if_nearby);
+ for_each_line_table_case (test_diagnostic_show_locus_fixit_lines);
+ for_each_line_table_case (test_fixit_consolidation);
+ for_each_line_table_case (test_overlapped_fixit_printing);
+ for_each_line_table_case (test_overlapped_fixit_printing_utf8);
+ for_each_line_table_case (test_overlapped_fixit_printing_2);
+ for_each_line_table_case (test_fixit_insert_containing_newline);
+ for_each_line_table_case (test_fixit_insert_containing_newline_2);
+ for_each_line_table_case (test_fixit_replace_containing_newline);
+ for_each_line_table_case (test_fixit_deletion_affecting_newline);
+ for_each_line_table_case (test_tab_expansion);
+ for_each_line_table_case (test_escaping_bytes_1);
+ for_each_line_table_case (test_escaping_bytes_2);
+
+ test_line_numbers_multiline_range ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/support/cpp/gcc/diagnostic-spec.cc b/support/cpp/gcc/diagnostic-spec.cc
new file mode 100644
index 000000000..4341ccfaa
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-spec.cc
@@ -0,0 +1,205 @@
+/* Functions to enable and disable individual warnings on an expression
+ and statement basis.
+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
+ Contributed by Martin Sebor <msebor@redhat.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.
+
+ 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 "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+#include "pretty-print.h"
+#include "options.h"
+
+/* Initialize *THIS from warning option OPT. */
+
+nowarn_spec_t::nowarn_spec_t (opt_code opt)
+{
+ /* Create a very simple mapping based on testing and experience.
+ It should become more refined with time. */
+ switch (opt)
+ {
+ case no_warning:
+ m_bits = 0;
+ break;
+
+ case all_warnings:
+ m_bits = -1;
+ break;
+
+ /* Flow-sensitive warnings about pointer problems issued by both
+ front ends and the middle end. */
+ case OPT_Waddress:
+ case OPT_Wnonnull:
+ m_bits = NW_NONNULL;
+ break;
+
+ /* Flow-sensitive warnings about arithmetic overflow issued by both
+ front ends and the middle end. */
+ case OPT_Woverflow:
+ case OPT_Wshift_count_negative:
+ case OPT_Wshift_count_overflow:
+ case OPT_Wstrict_overflow:
+ m_bits = NW_VFLOW;
+ break;
+
+ /* Lexical warnings issued by front ends. */
+ case OPT_Wabi:
+ case OPT_Wlogical_op:
+ case OPT_Wparentheses:
+ case OPT_Wreturn_type:
+ case OPT_Wsizeof_array_div:
+ case OPT_Wstrict_aliasing:
+ case OPT_Wunused:
+ case OPT_Wunused_function:
+ case OPT_Wunused_but_set_variable:
+ case OPT_Wunused_variable:
+ case OPT_Wunused_but_set_parameter:
+ m_bits = NW_LEXICAL;
+ break;
+
+ /* Access warning group. */
+ case OPT_Warray_bounds:
+ case OPT_Warray_bounds_:
+ case OPT_Wformat_overflow_:
+ case OPT_Wformat_truncation_:
+ case OPT_Wrestrict:
+ case OPT_Wsizeof_pointer_memaccess:
+ case OPT_Wstrict_aliasing_:
+ case OPT_Wstringop_overflow_:
+ case OPT_Wstringop_overread:
+ case OPT_Wstringop_truncation:
+ m_bits = NW_ACCESS;
+ break;
+
+ /* Initialization warning group. */
+ case OPT_Winit_self:
+ case OPT_Wuninitialized:
+ case OPT_Wmaybe_uninitialized:
+ m_bits = NW_UNINIT;
+ break;
+
+ case OPT_Wdangling_pointer_:
+ case OPT_Wreturn_local_addr:
+ case OPT_Wuse_after_free_:
+ m_bits = NW_DANGLING;
+ break;
+
+ default:
+ /* A catchall group for everything else. */
+ m_bits = NW_OTHER;
+ }
+}
+
+/* A mapping from a 'location_t' to the warning spec set for it. */
+
+GTY(()) nowarn_map_t *nowarn_map;
+
+/* Return the no-warning disposition for location LOC and option OPT
+ or for all/any otions by default. */
+
+bool
+warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
+{
+ gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
+ if (!nowarn_map)
+ return false;
+
+ if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
+ {
+ const nowarn_spec_t optspec (opt);
+ return *pspec & optspec;
+ }
+
+ return false;
+}
+
+ /* Change the supression of warnings for location LOC.
+ OPT controls which warnings are affected.
+ The wildcard OPT of -1 controls all warnings.
+ If SUPP is true (the default), enable the suppression of the warnings.
+ If SUPP is false, disable the suppression of the warnings. */
+
+bool
+suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
+ bool supp /* = true */)
+{
+ gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
+ const nowarn_spec_t optspec (supp ? opt : opt_code ());
+
+ if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
+ {
+ if (supp)
+ {
+ *pspec |= optspec;
+ return true;
+ }
+
+ *pspec &= optspec;
+ if (*pspec)
+ return true;
+
+ nowarn_map->remove (loc);
+ return false;
+ }
+
+ if (!supp || opt == no_warning)
+ return false;
+
+ if (!nowarn_map)
+ nowarn_map = nowarn_map_t::create_ggc (32);
+
+ nowarn_map->put (loc, optspec);
+ return true;
+}
+
+/* Copy the no-warning disposition from one location to another. */
+
+void
+copy_warning (location_t to, location_t from)
+{
+ if (!nowarn_map)
+ return;
+
+ nowarn_spec_t *from_spec;
+ if (RESERVED_LOCATION_P (from))
+ from_spec = NULL;
+ else
+ from_spec = nowarn_map->get (from);
+ if (RESERVED_LOCATION_P (to))
+ /* We cannot set no-warning dispositions for 'to', so we have no chance but
+ lose those potentially set for 'from'. */
+ ;
+ else
+ {
+ if (from_spec)
+ {
+ nowarn_spec_t tem = *from_spec;
+ nowarn_map->put (to, tem);
+ }
+ else
+ nowarn_map->remove (to);
+ }
+}
diff --git a/support/cpp/gcc/diagnostic-spec.h b/support/cpp/gcc/diagnostic-spec.h
new file mode 100644
index 000000000..28e5e5ccc
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-spec.h
@@ -0,0 +1,140 @@
+/* Language-independent APIs to enable/disable per-location warnings.
+
+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
+ Contributed by Martin Sebor <msebor@redhat.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.
+
+ 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 DIAGNOSTIC_SPEC_H_INCLUDED
+#define DIAGNOSTIC_SPEC_H_INCLUDED
+
+#include "hash-map.h"
+
+/* A "bitset" of warning groups. */
+
+class nowarn_spec_t
+{
+public:
+ enum
+ {
+ /* Middle end warnings about invalid accesses. */
+ NW_ACCESS = 1 << 0,
+ /* Front end/lexical warnings. */
+ NW_LEXICAL = 1 << 1,
+ /* Warnings about null pointers. */
+ NW_NONNULL = 1 << 2,
+ /* Warnings about uninitialized reads. */
+ NW_UNINIT = 1 << 3,
+ /* Warnings about arithmetic overflow. */
+ NW_VFLOW = 1 << 4,
+ /* Warnings about dangling pointers. */
+ NW_DANGLING = 1 << 5,
+ /* All other unclassified warnings. */
+ NW_OTHER = 1 << 6,
+ /* All groups of warnings. */
+ NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
+ | NW_UNINIT | NW_VFLOW | NW_DANGLING | NW_OTHER)
+ };
+
+ nowarn_spec_t (): m_bits () { }
+
+ nowarn_spec_t (opt_code);
+
+ /* Return the raw bitset. */
+ operator unsigned() const
+ {
+ return m_bits;
+ }
+
+ /* Return true if the bitset is clear. */
+ bool operator!() const
+ {
+ return !m_bits;
+ }
+
+ /* Return the inverse of the bitset. */
+ nowarn_spec_t operator~() const
+ {
+ nowarn_spec_t res (*this);
+ res.m_bits &= ~NW_ALL;
+ return res;
+ }
+
+ /* Set *THIS to the bitwise OR of *THIS and RHS. */
+ nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+ {
+ m_bits |= rhs.m_bits;
+ return *this;
+ }
+
+ /* Set *THIS to the bitwise AND of *THIS and RHS. */
+ nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+ {
+ m_bits &= rhs.m_bits;
+ return *this;
+ }
+
+ /* Set *THIS to the bitwise exclusive OR of *THIS and RHS. */
+ nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+ {
+ m_bits ^= rhs.m_bits;
+ return *this;
+ }
+
+private:
+ /* Bitset of warning groups. */
+ unsigned m_bits;
+};
+
+/* Return the bitwise OR of LHS and RHS. */
+
+inline nowarn_spec_t
+operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return nowarn_spec_t (lhs) |= rhs;
+}
+
+/* Return the bitwise AND of LHS and RHS. */
+
+inline nowarn_spec_t
+operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return nowarn_spec_t (lhs) &= rhs;
+}
+
+/* Return true if LHS is equal RHS. */
+
+inline bool
+operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
+}
+
+/* Return true if LHS is not equal RHS. */
+
+inline bool
+operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+ return !(lhs == rhs);
+}
+
+typedef hash_map<location_hash, nowarn_spec_t> nowarn_map_t;
+
+/* A mapping from a 'location_t' to the warning spec set for it. */
+extern GTY(()) nowarn_map_t *nowarn_map;
+
+#endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/support/cpp/gcc/diagnostic-url.h b/support/cpp/gcc/diagnostic-url.h
new file mode 100644
index 000000000..f349f9ef6
--- /dev/null
+++ b/support/cpp/gcc/diagnostic-url.h
@@ -0,0 +1,52 @@
+/* Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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_DIAGNOSTIC_URL_H
+#define GCC_DIAGNOSTIC_URL_H
+
+/* Whether to add URLs to diagnostics:
+ - DIAGNOSTICS_URL_NO: never
+ - DIAGNOSTICS_URL_YES: always
+ - DIAGNOSTICS_URL_AUTO: depending on the output stream. */
+typedef enum
+{
+ DIAGNOSTICS_URL_NO = 0,
+ DIAGNOSTICS_URL_YES = 1,
+ DIAGNOSTICS_URL_AUTO = 2
+} diagnostic_url_rule_t;
+
+/* Tells whether URLs should be emitted, and, if so, how to
+ terminate strings within the escape sequence. */
+enum diagnostic_url_format
+{
+ /* No URLs shall be emitted. */
+ URL_FORMAT_NONE,
+
+ /* Use ST string termination. */
+ URL_FORMAT_ST,
+
+ /* Use BEL string termination. */
+ URL_FORMAT_BEL
+};
+
+const diagnostic_url_format URL_FORMAT_DEFAULT = URL_FORMAT_BEL;
+
+extern diagnostic_url_format determine_url_format (diagnostic_url_rule_t);
+
+#endif /* ! GCC_DIAGNOSTIC_URL_H */
diff --git a/support/cpp/gcc/diagnostic.cc b/support/cpp/gcc/diagnostic.cc
new file mode 100644
index 000000000..73324a728
--- /dev/null
+++ b/support/cpp/gcc/diagnostic.cc
@@ -0,0 +1,2494 @@
+/* Language-independent diagnostic subroutines for the GNU Compiler Collection
+ Copyright (C) 1999-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@codesourcery.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.
+
+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 implements the language independent aspect of diagnostic
+ message module. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "version.h"
+#include "demangle.h"
+#include "intl.h"
+#include "backtrace.h"
+#include "diagnostic.h"
+#include "diagnostic-color.h"
+#include "diagnostic-url.h"
+#include "diagnostic-metadata.h"
+#include "diagnostic-path.h"
+#include "edit-context.h"
+#include "selftest.h"
+#include "selftest-diagnostic.h"
+#include "opts.h"
+#include "cpplib.h"
+
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
+#ifdef GWINSZ_IN_SYS_IOCTL
+# include <sys/ioctl.h>
+#endif
+
+/* Disable warnings about quoting issues in the pp_xxx calls below
+ that (intentionally) don't follow GCC diagnostic conventions. */
+#if __GNUC__ >= 10
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
+#define pedantic_warning_kind(DC) \
+ ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
+#define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
+#define permissive_error_option(DC) ((DC)->opt_permissive)
+
+/* Prototypes. */
+static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
+ int, const char *,
+ va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
+static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
+ int, unsigned HOST_WIDE_INT,
+ const char *, const char *, va_list *,
+ diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
+
+static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
+static void real_abort (void) ATTRIBUTE_NORETURN;
+
+/* Name of program invoked, sans directories. */
+
+const char *progname;
+
+/* A diagnostic_context surrogate for stderr. */
+static diagnostic_context global_diagnostic_context;
+diagnostic_context *global_dc = &global_diagnostic_context;
+
+/* Return a malloc'd string containing MSG formatted a la printf. The
+ caller is responsible for freeing the memory. */
+char *
+build_message_string (const char *msg, ...)
+{
+ char *str;
+ va_list ap;
+
+ va_start (ap, msg);
+ str = xvasprintf (msg, ap);
+ va_end (ap);
+
+ return str;
+}
+
+/* Same as diagnostic_build_prefix, but only the source FILE is given. */
+char *
+file_name_as_prefix (diagnostic_context *context, const char *f)
+{
+ const char *locus_cs
+ = colorize_start (pp_show_color (context->printer), "locus");
+ const char *locus_ce = colorize_stop (pp_show_color (context->printer));
+ return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
+}
+
+
+
+/* Return the value of the getenv("COLUMNS") as an integer. If the
+ value is not set to a positive integer, use ioctl to get the
+ terminal width. If it fails, return INT_MAX. */
+int
+get_terminal_width (void)
+{
+ const char * s = getenv ("COLUMNS");
+ if (s != NULL) {
+ int n = atoi (s);
+ if (n > 0)
+ return n;
+ }
+
+#ifdef TIOCGWINSZ
+ struct winsize w;
+ w.ws_col = 0;
+ if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
+ return w.ws_col;
+#endif
+
+ return INT_MAX;
+}
+
+/* Set caret_max_width to value. */
+void
+diagnostic_set_caret_max_width (diagnostic_context *context, int value)
+{
+ /* One minus to account for the leading empty space. */
+ value = value ? value - 1
+ : (isatty (fileno (pp_buffer (context->printer)->stream))
+ ? get_terminal_width () - 1: INT_MAX);
+
+ if (value <= 0)
+ value = INT_MAX;
+
+ context->caret_max_width = value;
+}
+
+/* Default implementation of final_cb. */
+
+static void
+default_diagnostic_final_cb (diagnostic_context *context)
+{
+ /* Some of the errors may actually have been warnings. */
+ if (diagnostic_kind_count (context, DK_WERROR))
+ {
+ /* -Werror was given. */
+ if (context->warning_as_error_requested)
+ pp_verbatim (context->printer,
+ _("%s: all warnings being treated as errors"),
+ progname);
+ /* At least one -Werror= was given. */
+ else
+ pp_verbatim (context->printer,
+ _("%s: some warnings being treated as errors"),
+ progname);
+ pp_newline_and_flush (context->printer);
+ }
+}
+
+/* Initialize the diagnostic message outputting machinery. */
+void
+diagnostic_initialize (diagnostic_context *context, int n_opts)
+{
+ int i;
+
+ /* Allocate a basic pretty-printer. Clients will replace this a
+ much more elaborated pretty-printer if they wish. */
+ context->printer = XNEW (pretty_printer);
+ new (context->printer) pretty_printer ();
+
+ memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
+ context->warning_as_error_requested = false;
+ context->n_opts = n_opts;
+ context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
+ for (i = 0; i < n_opts; i++)
+ context->classify_diagnostic[i] = DK_UNSPECIFIED;
+ context->show_caret = false;
+ diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
+ for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
+ context->caret_chars[i] = '^';
+ context->show_cwe = false;
+ context->path_format = DPF_NONE;
+ context->show_path_depths = false;
+ context->show_option_requested = false;
+ context->abort_on_error = false;
+ context->show_column = false;
+ context->pedantic_errors = false;
+ context->permissive = false;
+ context->opt_permissive = 0;
+ context->fatal_errors = false;
+ context->dc_inhibit_warnings = false;
+ context->dc_warn_system_headers = false;
+ context->max_errors = 0;
+ context->internal_error = NULL;
+ diagnostic_starter (context) = default_diagnostic_starter;
+ context->start_span = default_diagnostic_start_span_fn;
+ diagnostic_finalizer (context) = default_diagnostic_finalizer;
+ context->option_enabled = NULL;
+ context->option_state = NULL;
+ context->option_name = NULL;
+ context->get_option_url = NULL;
+ context->last_location = UNKNOWN_LOCATION;
+ context->last_module = 0;
+ context->x_data = NULL;
+ context->lock = 0;
+ context->inhibit_notes_p = false;
+ context->colorize_source_p = false;
+ context->show_labels_p = false;
+ context->show_line_numbers_p = false;
+ context->min_margin_width = 0;
+ context->show_ruler_p = false;
+ context->report_bug = false;
+
+ if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
+ {
+ if (!strcmp (var, "fixits-v1"))
+ context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
+ else if (!strcmp (var, "fixits-v2"))
+ context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
+ /* Silently ignore unrecognized values. */
+ }
+ context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
+ context->column_origin = 1;
+ context->tabstop = 8;
+ context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
+ context->edit_context_ptr = NULL;
+ context->diagnostic_group_nesting_depth = 0;
+ context->diagnostic_group_emission_count = 0;
+ context->begin_group_cb = NULL;
+ context->end_group_cb = NULL;
+ context->final_cb = default_diagnostic_final_cb;
+ context->includes_seen = NULL;
+}
+
+/* Maybe initialize the color support. We require clients to do this
+ explicitly, since most clients don't want color. When called
+ without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
+
+void
+diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
+{
+ /* value == -1 is the default value. */
+ if (value < 0)
+ {
+ /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
+ -fdiagnostics-color=auto if GCC_COLORS is in the environment,
+ otherwise default to -fdiagnostics-color=never, for other
+ values default to that
+ -fdiagnostics-color={never,auto,always}. */
+ if (DIAGNOSTICS_COLOR_DEFAULT == -1)
+ {
+ if (!getenv ("GCC_COLORS"))
+ return;
+ value = DIAGNOSTICS_COLOR_AUTO;
+ }
+ else
+ value = DIAGNOSTICS_COLOR_DEFAULT;
+ }
+ pp_show_color (context->printer)
+ = colorize_init ((diagnostic_color_rule_t) value);
+}
+
+/* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
+
+void
+diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
+{
+ /* value == -1 is the default value. */
+ if (value < 0)
+ {
+ /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
+ -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
+ environment, otherwise default to -fdiagnostics-urls=never,
+ for other values default to that
+ -fdiagnostics-urls={never,auto,always}. */
+ if (DIAGNOSTICS_URLS_DEFAULT == -1)
+ {
+ if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
+ return;
+ value = DIAGNOSTICS_URL_AUTO;
+ }
+ else
+ value = DIAGNOSTICS_URLS_DEFAULT;
+ }
+
+ context->printer->url_format
+ = determine_url_format ((diagnostic_url_rule_t) value);
+}
+
+/* Create the file_cache, if not already created, and tell it how to
+ translate files on input. */
+void diagnostic_initialize_input_context (diagnostic_context *context,
+ diagnostic_input_charset_callback ccb,
+ bool should_skip_bom)
+{
+ if (!context->m_file_cache)
+ context->m_file_cache = new file_cache;
+ context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
+}
+
+/* Do any cleaning up required after the last diagnostic is emitted. */
+
+void
+diagnostic_finish (diagnostic_context *context)
+{
+ if (context->final_cb)
+ context->final_cb (context);
+
+ diagnostic_file_cache_fini ();
+
+ XDELETEVEC (context->classify_diagnostic);
+ context->classify_diagnostic = NULL;
+
+ /* diagnostic_initialize allocates context->printer using XNEW
+ and placement-new. */
+ context->printer->~pretty_printer ();
+ XDELETE (context->printer);
+ context->printer = NULL;
+
+ if (context->edit_context_ptr)
+ {
+ delete context->edit_context_ptr;
+ context->edit_context_ptr = NULL;
+ }
+
+ if (context->includes_seen)
+ {
+ delete context->includes_seen;
+ context->includes_seen = nullptr;
+ }
+}
+
+/* Initialize DIAGNOSTIC, where the message MSG has already been
+ translated. */
+void
+diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
+ va_list *args, rich_location *richloc,
+ diagnostic_t kind)
+{
+ gcc_assert (richloc);
+ diagnostic->message.err_no = errno;
+ diagnostic->message.args_ptr = args;
+ diagnostic->message.format_spec = msg;
+ diagnostic->message.m_richloc = richloc;
+ diagnostic->richloc = richloc;
+ diagnostic->metadata = NULL;
+ diagnostic->kind = kind;
+ diagnostic->option_index = 0;
+}
+
+/* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
+ translated. */
+void
+diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
+ va_list *args, rich_location *richloc,
+ diagnostic_t kind)
+{
+ gcc_assert (richloc);
+ diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
+}
+
+static const char *const diagnostic_kind_color[] = {
+#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
+#include "diagnostic.def"
+#undef DEFINE_DIAGNOSTIC_KIND
+ NULL
+};
+
+/* Get a color name for diagnostics of type KIND
+ Result could be NULL. */
+
+const char *
+diagnostic_get_color_for_kind (diagnostic_t kind)
+{
+ return diagnostic_kind_color[kind];
+}
+
+/* Given an expanded_location, convert the column (which is in 1-based bytes)
+ to the requested units, without converting the origin.
+ Return -1 if the column is invalid (<= 0). */
+
+static int
+convert_column_unit (enum diagnostics_column_unit column_unit,
+ int tabstop,
+ expanded_location s)
+{
+ if (s.column <= 0)
+ return -1;
+
+ switch (column_unit)
+ {
+ default:
+ gcc_unreachable ();
+
+ case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
+ {
+ cpp_char_column_policy policy (tabstop, cpp_wcwidth);
+ return location_compute_display_column (s, policy);
+ }
+
+ case DIAGNOSTICS_COLUMN_UNIT_BYTE:
+ return s.column;
+ }
+}
+
+/* Given an expanded_location, convert the column (which is in 1-based bytes)
+ to the requested units and origin. Return -1 if the column is
+ invalid (<= 0). */
+int
+diagnostic_converted_column (diagnostic_context *context, expanded_location s)
+{
+ int one_based_col
+ = convert_column_unit (context->column_unit, context->tabstop, s);
+ if (one_based_col <= 0)
+ return -1;
+ return one_based_col + (context->column_origin - 1);
+}
+
+/* Return a formatted line and column ':%line:%column'. Elided if
+ line == 0 or col < 0. (A column of 0 may be valid due to the
+ -fdiagnostics-column-origin option.)
+ The result is a statically allocated buffer. */
+
+static const char *
+maybe_line_and_column (int line, int col)
+{
+ static char result[32];
+
+ if (line)
+ {
+ size_t l
+ = snprintf (result, sizeof (result),
+ col >= 0 ? ":%d:%d" : ":%d", line, col);
+ gcc_checking_assert (l < sizeof (result));
+ }
+ else
+ result[0] = 0;
+ return result;
+}
+
+/* Return a malloc'd string describing a location e.g. "foo.c:42:10".
+ The caller is responsible for freeing the memory. */
+
+static char *
+diagnostic_get_location_text (diagnostic_context *context,
+ expanded_location s)
+{
+ pretty_printer *pp = context->printer;
+ const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
+ const char *locus_ce = colorize_stop (pp_show_color (pp));
+ const char *file = s.file ? s.file : progname;
+ int line = 0;
+ int col = -1;
+ if (strcmp (file, N_("<built-in>")))
+ {
+ line = s.line;
+ if (context->show_column)
+ col = diagnostic_converted_column (context, s);
+ }
+
+ const char *line_col = maybe_line_and_column (line, col);
+ return build_message_string ("%s%s%s:%s", locus_cs, file,
+ line_col, locus_ce);
+}
+
+static const char *const diagnostic_kind_text[] = {
+#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
+#include "diagnostic.def"
+#undef DEFINE_DIAGNOSTIC_KIND
+ "must-not-happen"
+};
+
+/* Return a malloc'd string describing a location and the severity of the
+ diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
+ freeing the memory. */
+char *
+diagnostic_build_prefix (diagnostic_context *context,
+ const diagnostic_info *diagnostic)
+{
+ gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
+
+ const char *text = _(diagnostic_kind_text[diagnostic->kind]);
+ const char *text_cs = "", *text_ce = "";
+ pretty_printer *pp = context->printer;
+
+ if (diagnostic_kind_color[diagnostic->kind])
+ {
+ text_cs = colorize_start (pp_show_color (pp),
+ diagnostic_kind_color[diagnostic->kind]);
+ text_ce = colorize_stop (pp_show_color (pp));
+ }
+
+ expanded_location s = diagnostic_expand_location (diagnostic);
+ char *location_text = diagnostic_get_location_text (context, s);
+
+ char *result = build_message_string ("%s %s%s%s", location_text,
+ text_cs, text, text_ce);
+ free (location_text);
+ return result;
+}
+
+/* Functions at which to stop the backtrace print. It's not
+ particularly helpful to print the callers of these functions. */
+
+static const char * const bt_stop[] =
+{
+ "main",
+ "toplev::main",
+ "execute_one_pass",
+ "compile_file",
+};
+
+/* A callback function passed to the backtrace_full function. */
+
+static int
+bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
+ const char *function)
+{
+ int *pcount = (int *) data;
+
+ /* If we don't have any useful information, don't print
+ anything. */
+ if (filename == NULL && function == NULL)
+ return 0;
+
+ /* Skip functions in diagnostic.cc. */
+ if (*pcount == 0
+ && filename != NULL
+ && strcmp (lbasename (filename), "diagnostic.cc") == 0)
+ return 0;
+
+ /* Print up to 20 functions. We could make this a --param, but
+ since this is only for debugging just use a constant for now. */
+ if (*pcount >= 20)
+ {
+ /* Returning a non-zero value stops the backtrace. */
+ return 1;
+ }
+ ++*pcount;
+
+ char *alc = NULL;
+ if (function != NULL)
+ {
+ char *str = cplus_demangle_v3 (function,
+ (DMGL_VERBOSE | DMGL_ANSI
+ | DMGL_GNU_V3 | DMGL_PARAMS));
+ if (str != NULL)
+ {
+ alc = str;
+ function = str;
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
+ {
+ size_t len = strlen (bt_stop[i]);
+ if (strncmp (function, bt_stop[i], len) == 0
+ && (function[len] == '\0' || function[len] == '('))
+ {
+ if (alc != NULL)
+ free (alc);
+ /* Returning a non-zero value stops the backtrace. */
+ return 1;
+ }
+ }
+ }
+
+ fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
+ (unsigned long) pc,
+ function == NULL ? "???" : function,
+ filename == NULL ? "???" : filename,
+ lineno);
+
+ if (alc != NULL)
+ free (alc);
+
+ return 0;
+}
+
+/* A callback function passed to the backtrace_full function. This is
+ called if backtrace_full has an error. */
+
+static void
+bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
+{
+ if (errnum < 0)
+ {
+ /* This means that no debug info was available. Just quietly
+ skip printing backtrace info. */
+ return;
+ }
+ fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
+ errnum == 0 ? "" : xstrerror (errnum));
+}
+
+/* Check if we've met the maximum error limit, and if so fatally exit
+ with a message. CONTEXT is the context to check, and FLUSH
+ indicates whether a diagnostic_finish call is needed. */
+
+void
+diagnostic_check_max_errors (diagnostic_context *context, bool flush)
+{
+ if (!context->max_errors)
+ return;
+
+ int count = (diagnostic_kind_count (context, DK_ERROR)
+ + diagnostic_kind_count (context, DK_SORRY)
+ + diagnostic_kind_count (context, DK_WERROR));
+
+ if (count >= context->max_errors)
+ {
+ fnotice (stderr,
+ "compilation terminated due to -fmax-errors=%u.\n",
+ context->max_errors);
+ if (flush)
+ diagnostic_finish (context);
+ exit (FATAL_EXIT_CODE);
+ }
+}
+
+/* Take any action which is expected to happen after the diagnostic
+ is written out. This function does not always return. */
+void
+diagnostic_action_after_output (diagnostic_context *context,
+ diagnostic_t diag_kind)
+{
+ switch (diag_kind)
+ {
+ case DK_DEBUG:
+ case DK_NOTE:
+ case DK_ANACHRONISM:
+ case DK_WARNING:
+ break;
+
+ case DK_ERROR:
+ case DK_SORRY:
+ if (context->abort_on_error)
+ real_abort ();
+ if (context->fatal_errors)
+ {
+ fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
+ diagnostic_finish (context);
+ exit (FATAL_EXIT_CODE);
+ }
+ break;
+
+ case DK_ICE:
+ case DK_ICE_NOBT:
+ {
+ struct backtrace_state *state = NULL;
+ if (diag_kind == DK_ICE)
+ state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
+ int count = 0;
+ if (state != NULL)
+ backtrace_full (state, 2, bt_callback, bt_err_callback,
+ (void *) &count);
+
+ if (context->abort_on_error)
+ real_abort ();
+
+ if (context->report_bug)
+ fnotice (stderr, "Please submit a full bug report, "
+ "with preprocessed source.\n");
+ else
+ fnotice (stderr, "Please submit a full bug report, "
+ "with preprocessed source (by using -freport-bug).\n");
+
+ if (count > 0)
+ fnotice (stderr, "Please include the complete backtrace "
+ "with any bug report.\n");
+ fnotice (stderr, "See %s for instructions.\n", bug_report_url);
+
+ exit (ICE_EXIT_CODE);
+ }
+
+ case DK_FATAL:
+ if (context->abort_on_error)
+ real_abort ();
+ diagnostic_finish (context);
+ fnotice (stderr, "compilation terminated.\n");
+ exit (FATAL_EXIT_CODE);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* True if the last module or file in which a diagnostic was reported is
+ different from the current one. */
+
+static bool
+last_module_changed_p (diagnostic_context *context,
+ const line_map_ordinary *map)
+{
+ return context->last_module != map;
+}
+
+/* Remember the current module or file as being the last one in which we
+ report a diagnostic. */
+
+static void
+set_last_module (diagnostic_context *context, const line_map_ordinary *map)
+{
+ context->last_module = map;
+}
+
+/* Only dump the "In file included from..." stack once for each file. */
+
+static bool
+includes_seen (diagnostic_context *context, const line_map_ordinary *map)
+{
+ /* No include path for main. */
+ if (MAIN_FILE_P (map))
+ return true;
+
+ /* Always identify C++ modules, at least for now. */
+ auto probe = map;
+ if (linemap_check_ordinary (map)->reason == LC_RENAME)
+ /* The module source file shows up as LC_RENAME inside LC_MODULE. */
+ probe = linemap_included_from_linemap (line_table, map);
+ if (MAP_MODULE_P (probe))
+ return false;
+
+ if (!context->includes_seen)
+ context->includes_seen = new hash_set<location_t, false, location_hash>;
+
+ /* Hash the location of the #include directive to better handle files
+ that are included multiple times with different macros defined. */
+ return context->includes_seen->add (linemap_included_from (map));
+}
+
+void
+diagnostic_report_current_module (diagnostic_context *context, location_t where)
+{
+ const line_map_ordinary *map = NULL;
+
+ if (pp_needs_newline (context->printer))
+ {
+ pp_newline (context->printer);
+ pp_needs_newline (context->printer) = false;
+ }
+
+ if (where <= BUILTINS_LOCATION)
+ return;
+
+ linemap_resolve_location (line_table, where,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+
+ if (map && last_module_changed_p (context, map))
+ {
+ set_last_module (context, map);
+ if (!includes_seen (context, map))
+ {
+ bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
+ expanded_location s = {};
+ do
+ {
+ where = linemap_included_from (map);
+ map = linemap_included_from_linemap (line_table, map);
+ bool is_module = MAP_MODULE_P (map);
+ s.file = LINEMAP_FILE (map);
+ s.line = SOURCE_LINE (map, where);
+ int col = -1;
+ if (first && context->show_column)
+ {
+ s.column = SOURCE_COLUMN (map, where);
+ col = diagnostic_converted_column (context, s);
+ }
+ const char *line_col = maybe_line_and_column (s.line, col);
+ static const char *const msgs[] =
+ {
+ NULL,
+ N_(" from"),
+ N_("In file included from"), /* 2 */
+ N_(" included from"),
+ N_("In module"), /* 4 */
+ N_("of module"),
+ N_("In module imported at"), /* 6 */
+ N_("imported at"),
+ };
+
+ unsigned index = (was_module ? 6 : is_module ? 4
+ : need_inc ? 2 : 0) + !first;
+
+ pp_verbatim (context->printer, "%s%s %r%s%s%R",
+ first ? "" : was_module ? ", " : ",\n",
+ _(msgs[index]),
+ "locus", s.file, line_col);
+ first = false, need_inc = was_module, was_module = is_module;
+ }
+ while (!includes_seen (context, map));
+ pp_verbatim (context->printer, ":");
+ pp_newline (context->printer);
+ }
+ }
+}
+
+/* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
+ print the path. */
+
+void
+diagnostic_show_any_path (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ const diagnostic_path *path = diagnostic->richloc->get_path ();
+ if (!path)
+ return;
+
+ if (context->print_path)
+ context->print_path (context, path);
+}
+
+/* Return true if the events in this path involve more than one
+ function, or false if it is purely intraprocedural. */
+
+bool
+diagnostic_path::interprocedural_p () const
+{
+ const unsigned num = num_events ();
+ for (unsigned i = 0; i < num; i++)
+ {
+ if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
+ return true;
+ if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
+ return true;
+ }
+ return false;
+}
+
+void
+default_diagnostic_starter (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ diagnostic_report_current_module (context, diagnostic_location (diagnostic));
+ pp_set_prefix (context->printer, diagnostic_build_prefix (context,
+ diagnostic));
+}
+
+void
+default_diagnostic_start_span_fn (diagnostic_context *context,
+ expanded_location exploc)
+{
+ char *text = diagnostic_get_location_text (context, exploc);
+ pp_string (context->printer, text);
+ free (text);
+ pp_newline (context->printer);
+}
+
+void
+default_diagnostic_finalizer (diagnostic_context *context,
+ diagnostic_info *diagnostic,
+ diagnostic_t)
+{
+ char *saved_prefix = pp_take_prefix (context->printer);
+ pp_set_prefix (context->printer, NULL);
+ pp_newline (context->printer);
+ diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
+ pp_set_prefix (context->printer, saved_prefix);
+ pp_flush (context->printer);
+}
+
+/* Interface to specify diagnostic kind overrides. Returns the
+ previous setting, or DK_UNSPECIFIED if the parameters are out of
+ range. If OPTION_INDEX is zero, the new setting is for all the
+ diagnostics. */
+diagnostic_t
+diagnostic_classify_diagnostic (diagnostic_context *context,
+ int option_index,
+ diagnostic_t new_kind,
+ location_t where)
+{
+ diagnostic_t old_kind;
+
+ if (option_index < 0
+ || option_index >= context->n_opts
+ || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
+ return DK_UNSPECIFIED;
+
+ old_kind = context->classify_diagnostic[option_index];
+
+ /* Handle pragmas separately, since we need to keep track of *where*
+ the pragmas were. */
+ if (where != UNKNOWN_LOCATION)
+ {
+ int i;
+
+ /* Record the command-line status, so we can reset it back on DK_POP. */
+ if (old_kind == DK_UNSPECIFIED)
+ {
+ old_kind = !context->option_enabled (option_index,
+ context->lang_mask,
+ context->option_state)
+ ? DK_IGNORED : (context->warning_as_error_requested
+ ? DK_ERROR : DK_WARNING);
+ context->classify_diagnostic[option_index] = old_kind;
+ }
+
+ for (i = context->n_classification_history - 1; i >= 0; i --)
+ if (context->classification_history[i].option == option_index)
+ {
+ old_kind = context->classification_history[i].kind;
+ break;
+ }
+
+ i = context->n_classification_history;
+ context->classification_history =
+ (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
+ * sizeof (diagnostic_classification_change_t));
+ context->classification_history[i].location = where;
+ context->classification_history[i].option = option_index;
+ context->classification_history[i].kind = new_kind;
+ context->n_classification_history ++;
+ }
+ else
+ context->classify_diagnostic[option_index] = new_kind;
+
+ return old_kind;
+}
+
+/* Save all diagnostic classifications in a stack. */
+void
+diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
+{
+ context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
+ context->push_list[context->n_push ++] = context->n_classification_history;
+}
+
+/* Restore the topmost classification set off the stack. If the stack
+ is empty, revert to the state based on command line parameters. */
+void
+diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
+{
+ int jump_to;
+ int i;
+
+ if (context->n_push)
+ jump_to = context->push_list [-- context->n_push];
+ else
+ jump_to = 0;
+
+ i = context->n_classification_history;
+ context->classification_history =
+ (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
+ * sizeof (diagnostic_classification_change_t));
+ context->classification_history[i].location = where;
+ context->classification_history[i].option = jump_to;
+ context->classification_history[i].kind = DK_POP;
+ context->n_classification_history ++;
+}
+
+/* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
+ escaping rules for -fdiagnostics-parseable-fixits. */
+
+static void
+print_escaped_string (pretty_printer *pp, const char *text)
+{
+ gcc_assert (pp);
+ gcc_assert (text);
+
+ pp_character (pp, '"');
+ for (const char *ch = text; *ch; ch++)
+ {
+ switch (*ch)
+ {
+ case '\\':
+ /* Escape backslash as two backslashes. */
+ pp_string (pp, "\\\\");
+ break;
+ case '\t':
+ /* Escape tab as "\t". */
+ pp_string (pp, "\\t");
+ break;
+ case '\n':
+ /* Escape newline as "\n". */
+ pp_string (pp, "\\n");
+ break;
+ case '"':
+ /* Escape doublequotes as \". */
+ pp_string (pp, "\\\"");
+ break;
+ default:
+ if (ISPRINT (*ch))
+ pp_character (pp, *ch);
+ else
+ /* Use octal for non-printable chars. */
+ {
+ unsigned char c = (*ch & 0xff);
+ pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
+ }
+ break;
+ }
+ }
+ pp_character (pp, '"');
+}
+
+/* Implementation of -fdiagnostics-parseable-fixits and
+ GCC_EXTRA_DIAGNOSTIC_OUTPUT.
+ Print a machine-parseable version of all fixits in RICHLOC to PP,
+ using COLUMN_UNIT to express columns.
+ Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
+
+static void
+print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
+ enum diagnostics_column_unit column_unit,
+ int tabstop)
+{
+ gcc_assert (pp);
+ gcc_assert (richloc);
+
+ char *saved_prefix = pp_take_prefix (pp);
+ pp_set_prefix (pp, NULL);
+
+ for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
+ {
+ const fixit_hint *hint = richloc->get_fixit_hint (i);
+ location_t start_loc = hint->get_start_loc ();
+ expanded_location start_exploc = expand_location (start_loc);
+ pp_string (pp, "fix-it:");
+ print_escaped_string (pp, start_exploc.file);
+ /* For compatibility with clang, print as a half-open range. */
+ location_t next_loc = hint->get_next_loc ();
+ expanded_location next_exploc = expand_location (next_loc);
+ int start_col
+ = convert_column_unit (column_unit, tabstop, start_exploc);
+ int next_col
+ = convert_column_unit (column_unit, tabstop, next_exploc);
+ pp_printf (pp, ":{%i:%i-%i:%i}:",
+ start_exploc.line, start_col,
+ next_exploc.line, next_col);
+ print_escaped_string (pp, hint->get_string ());
+ pp_newline (pp);
+ }
+
+ pp_set_prefix (pp, saved_prefix);
+}
+
+/* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
+
+static void
+get_any_inlining_info (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ auto &ilocs = diagnostic->m_iinfo.m_ilocs;
+
+ if (context->set_locations_cb)
+ /* Retrieve the locations into which the expression about to be
+ diagnosed has been inlined, including those of all the callers
+ all the way down the inlining stack. */
+ context->set_locations_cb (context, diagnostic);
+ else
+ {
+ /* When there's no callback use just the one location provided
+ by the caller of the diagnostic function. */
+ location_t loc = diagnostic_location (diagnostic);
+ ilocs.safe_push (loc);
+ diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
+ }
+}
+
+/* Update the kind of DIAGNOSTIC based on its location(s), including
+ any of those in its inlining stack, relative to any
+ #pragma GCC diagnostic
+ directives recorded within CONTEXT.
+
+ Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
+ otherwise. */
+
+static diagnostic_t
+update_effective_level_from_pragmas (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
+ {
+ /* Ignore the diagnostic if all the inlined locations are
+ in system headers and -Wno-system-headers is in effect. */
+ diagnostic->kind = DK_IGNORED;
+ return DK_IGNORED;
+ }
+
+ if (context->n_classification_history <= 0)
+ return DK_UNSPECIFIED;
+
+ /* Iterate over the locations, checking the diagnostic disposition
+ for the diagnostic at each. If it's explicitly set as opposed
+ to unspecified, update the disposition for this instance of
+ the diagnostic and return it. */
+ for (location_t loc: diagnostic->m_iinfo.m_ilocs)
+ {
+ /* FIXME: Stupid search. Optimize later. */
+ for (int i = context->n_classification_history - 1; i >= 0; i --)
+ {
+ const diagnostic_classification_change_t &hist
+ = context->classification_history[i];
+
+ location_t pragloc = hist.location;
+ if (!linemap_location_before_p (line_table, pragloc, loc))
+ continue;
+
+ if (hist.kind == (int) DK_POP)
+ {
+ /* Move on to the next region. */
+ i = hist.option;
+ continue;
+ }
+
+ int option = hist.option;
+ /* The option 0 is for all the diagnostics. */
+ if (option == 0 || option == diagnostic->option_index)
+ {
+ diagnostic_t kind = hist.kind;
+ if (kind != DK_UNSPECIFIED)
+ diagnostic->kind = kind;
+ return kind;
+ }
+ }
+ }
+
+ return DK_UNSPECIFIED;
+}
+
+/* Generate a URL string describing CWE. The caller is responsible for
+ freeing the string. */
+
+static char *
+get_cwe_url (int cwe)
+{
+ return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
+}
+
+/* If DIAGNOSTIC has a CWE identifier, print it.
+
+ For example, if the diagnostic metadata associates it with CWE-119,
+ " [CWE-119]" will be printed, suitably colorized, and with a URL of a
+ description of the security issue. */
+
+static void
+print_any_cwe (diagnostic_context *context,
+ const diagnostic_info *diagnostic)
+{
+ if (diagnostic->metadata == NULL)
+ return;
+
+ int cwe = diagnostic->metadata->get_cwe ();
+ if (cwe)
+ {
+ pretty_printer *pp = context->printer;
+ char *saved_prefix = pp_take_prefix (context->printer);
+ pp_string (pp, " [");
+ pp_string (pp, colorize_start (pp_show_color (pp),
+ diagnostic_kind_color[diagnostic->kind]));
+ if (pp->url_format != URL_FORMAT_NONE)
+ {
+ char *cwe_url = get_cwe_url (cwe);
+ pp_begin_url (pp, cwe_url);
+ free (cwe_url);
+ }
+ pp_printf (pp, "CWE-%i", cwe);
+ pp_set_prefix (context->printer, saved_prefix);
+ if (pp->url_format != URL_FORMAT_NONE)
+ pp_end_url (pp);
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+ pp_character (pp, ']');
+ }
+}
+
+/* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
+ printer, e.g. " [-Werror=uninitialized]".
+ Subroutine of diagnostic_report_diagnostic. */
+
+static void
+print_option_information (diagnostic_context *context,
+ const diagnostic_info *diagnostic,
+ diagnostic_t orig_diag_kind)
+{
+ char *option_text;
+
+ option_text = context->option_name (context, diagnostic->option_index,
+ orig_diag_kind, diagnostic->kind);
+
+ if (option_text)
+ {
+ char *option_url = NULL;
+ if (context->get_option_url
+ && context->printer->url_format != URL_FORMAT_NONE)
+ option_url = context->get_option_url (context,
+ diagnostic->option_index);
+ pretty_printer *pp = context->printer;
+ pp_string (pp, " [");
+ pp_string (pp, colorize_start (pp_show_color (pp),
+ diagnostic_kind_color[diagnostic->kind]));
+ if (option_url)
+ pp_begin_url (pp, option_url);
+ pp_string (pp, option_text);
+ if (option_url)
+ {
+ pp_end_url (pp);
+ free (option_url);
+ }
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+ pp_character (pp, ']');
+ free (option_text);
+ }
+}
+
+/* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
+ as appropriate for #pragma GCC diagnostic and -Werror=foo. */
+
+static bool
+diagnostic_enabled (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ /* Update the inlining stack for this diagnostic. */
+ get_any_inlining_info (context, diagnostic);
+
+ /* Diagnostics with no option or -fpermissive are always enabled. */
+ if (!diagnostic->option_index
+ || diagnostic->option_index == permissive_error_option (context))
+ return true;
+
+ /* This tests if the user provided the appropriate -Wfoo or
+ -Wno-foo option. */
+ if (! context->option_enabled (diagnostic->option_index,
+ context->lang_mask,
+ context->option_state))
+ return false;
+
+ /* This tests for #pragma diagnostic changes. */
+ diagnostic_t diag_class
+ = update_effective_level_from_pragmas (context, diagnostic);
+
+ /* This tests if the user provided the appropriate -Werror=foo
+ option. */
+ if (diag_class == DK_UNSPECIFIED
+ && (context->classify_diagnostic[diagnostic->option_index]
+ != DK_UNSPECIFIED))
+ diagnostic->kind
+ = context->classify_diagnostic[diagnostic->option_index];
+
+ /* This allows for future extensions, like temporarily disabling
+ warnings for ranges of source code. */
+ if (diagnostic->kind == DK_IGNORED)
+ return false;
+
+ return true;
+}
+
+/* Returns whether warning OPT is enabled at LOC. */
+
+bool
+warning_enabled_at (location_t loc, int opt)
+{
+ if (!diagnostic_report_warnings_p (global_dc, loc))
+ return false;
+
+ rich_location richloc (line_table, loc);
+ diagnostic_info diagnostic = {};
+ diagnostic.option_index = opt;
+ diagnostic.richloc = &richloc;
+ diagnostic.message.m_richloc = &richloc;
+ diagnostic.kind = DK_WARNING;
+ return diagnostic_enabled (global_dc, &diagnostic);
+}
+
+/* Report a diagnostic message (an error or a warning) as specified by
+ DC. This function is *the* subroutine in terms of which front-ends
+ should implement their specific diagnostic handling modules. The
+ front-end independent format specifiers are exactly those described
+ in the documentation of output_format.
+ Return true if a diagnostic was printed, false otherwise. */
+
+bool
+diagnostic_report_diagnostic (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ location_t location = diagnostic_location (diagnostic);
+ diagnostic_t orig_diag_kind = diagnostic->kind;
+
+ /* Give preference to being able to inhibit warnings, before they
+ get reclassified to something else. */
+ bool report_warning_p = true;
+ if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
+ {
+ if (context->dc_inhibit_warnings)
+ return false;
+ /* Remember the result of the overall system header warning setting
+ but proceed to also check the inlining context. */
+ report_warning_p = diagnostic_report_warnings_p (context, location);
+ if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
+ return false;
+ }
+
+ if (diagnostic->kind == DK_PEDWARN)
+ {
+ diagnostic->kind = pedantic_warning_kind (context);
+ /* We do this to avoid giving the message for -pedantic-errors. */
+ orig_diag_kind = diagnostic->kind;
+ }
+
+ if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
+ return false;
+
+ if (context->lock > 0)
+ {
+ /* If we're reporting an ICE in the middle of some other error,
+ try to flush out the previous error, then let this one
+ through. Don't do this more than once. */
+ if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
+ && context->lock == 1)
+ pp_newline_and_flush (context->printer);
+ else
+ error_recursion (context);
+ }
+
+ /* If the user requested that warnings be treated as errors, so be
+ it. Note that we do this before the next block so that
+ individual warnings can be overridden back to warnings with
+ -Wno-error=*. */
+ if (context->warning_as_error_requested
+ && diagnostic->kind == DK_WARNING)
+ diagnostic->kind = DK_ERROR;
+
+ diagnostic->message.x_data = &diagnostic->x_data;
+
+ /* Check to see if the diagnostic is enabled at the location and
+ not disabled by #pragma GCC diagnostic anywhere along the inlining
+ stack. . */
+ if (!diagnostic_enabled (context, diagnostic))
+ return false;
+
+ if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
+ /* Bail if the warning is not to be reported because all locations
+ in the inlining stack (if there is one) are in system headers. */
+ return false;
+
+ if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
+ diagnostic_check_max_errors (context);
+
+ context->lock++;
+
+ if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
+ {
+ /* When not checking, ICEs are converted to fatal errors when an
+ error has already occurred. This is counteracted by
+ abort_on_error. */
+ if (!CHECKING_P
+ && (diagnostic_kind_count (context, DK_ERROR) > 0
+ || diagnostic_kind_count (context, DK_SORRY) > 0)
+ && !context->abort_on_error)
+ {
+ expanded_location s
+ = expand_location (diagnostic_location (diagnostic));
+ fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
+ s.file, s.line);
+ exit (ICE_EXIT_CODE);
+ }
+ if (context->internal_error)
+ (*context->internal_error) (context,
+ diagnostic->message.format_spec,
+ diagnostic->message.args_ptr);
+ }
+ if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
+ ++diagnostic_kind_count (context, DK_WERROR);
+ else
+ ++diagnostic_kind_count (context, diagnostic->kind);
+
+ /* Is this the initial diagnostic within the stack of groups? */
+ if (context->diagnostic_group_emission_count == 0)
+ {
+ if (context->begin_group_cb)
+ context->begin_group_cb (context);
+ }
+ context->diagnostic_group_emission_count++;
+
+ pp_format (context->printer, &diagnostic->message);
+ (*diagnostic_starter (context)) (context, diagnostic);
+ pp_output_formatted_text (context->printer);
+ if (context->show_cwe)
+ print_any_cwe (context, diagnostic);
+ if (context->show_option_requested)
+ print_option_information (context, diagnostic, orig_diag_kind);
+ (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
+ switch (context->extra_output_kind)
+ {
+ default:
+ break;
+ case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
+ print_parseable_fixits (context->printer, diagnostic->richloc,
+ DIAGNOSTICS_COLUMN_UNIT_BYTE,
+ context->tabstop);
+ pp_flush (context->printer);
+ break;
+ case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
+ print_parseable_fixits (context->printer, diagnostic->richloc,
+ DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+ context->tabstop);
+ pp_flush (context->printer);
+ break;
+ }
+ diagnostic_action_after_output (context, diagnostic->kind);
+ diagnostic->x_data = NULL;
+
+ if (context->edit_context_ptr)
+ if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
+ context->edit_context_ptr->add_fixits (diagnostic->richloc);
+
+ context->lock--;
+
+ diagnostic_show_any_path (context, diagnostic);
+
+ return true;
+}
+
+/* Get the number of digits in the decimal representation of VALUE. */
+
+int
+num_digits (int value)
+{
+ /* Perhaps simpler to use log10 for this, but doing it this way avoids
+ using floating point. */
+ gcc_assert (value >= 0);
+
+ if (value == 0)
+ return 1;
+
+ int digits = 0;
+ while (value > 0)
+ {
+ digits++;
+ value /= 10;
+ }
+ return digits;
+}
+
+/* Given a partial pathname as input, return another pathname that
+ shares no directory elements with the pathname of __FILE__. This
+ is used by fancy_abort() to print `internal compiler error in expr.cc'
+ instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
+
+const char *
+trim_filename (const char *name)
+{
+ static const char this_file[] = __FILE__;
+ const char *p = name, *q = this_file;
+
+ /* First skip any "../" in each filename. This allows us to give a proper
+ reference to a file in a subdirectory. */
+ while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
+ p += 3;
+
+ while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
+ q += 3;
+
+ /* Now skip any parts the two filenames have in common. */
+ while (*p == *q && *p != 0 && *q != 0)
+ p++, q++;
+
+ /* Now go backwards until the previous directory separator. */
+ while (p > name && !IS_DIR_SEPARATOR (p[-1]))
+ p--;
+
+ return p;
+}
+
+/* Standard error reporting routines in increasing order of severity.
+ All of these take arguments like printf. */
+
+/* Text to be emitted verbatim to the error message stream; this
+ produces no prefix and disables line-wrapping. Use rarely. */
+void
+verbatim (const char *gmsgid, ...)
+{
+ text_info text;
+ va_list ap;
+
+ va_start (ap, gmsgid);
+ text.err_no = errno;
+ text.args_ptr = &ap;
+ text.format_spec = _(gmsgid);
+ text.x_data = NULL;
+ pp_format_verbatim (global_dc->printer, &text);
+ pp_newline_and_flush (global_dc->printer);
+ va_end (ap);
+}
+
+/* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
+void
+diagnostic_append_note (diagnostic_context *context,
+ location_t location,
+ const char * gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+ rich_location richloc (line_table, location);
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
+ if (context->inhibit_notes_p)
+ {
+ va_end (ap);
+ return;
+ }
+ char *saved_prefix = pp_take_prefix (context->printer);
+ pp_set_prefix (context->printer,
+ diagnostic_build_prefix (context, &diagnostic));
+ pp_format (context->printer, &diagnostic.message);
+ pp_output_formatted_text (context->printer);
+ pp_destroy_prefix (context->printer);
+ pp_set_prefix (context->printer, saved_prefix);
+ pp_newline (context->printer);
+ diagnostic_show_locus (context, &richloc, DK_NOTE);
+ va_end (ap);
+}
+
+/* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
+ permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
+ and internal_error_no_backtrace, as documented and defined below. */
+static bool
+diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
+ int opt, const char *gmsgid,
+ va_list *ap, diagnostic_t kind)
+{
+ diagnostic_info diagnostic;
+ if (kind == DK_PERMERROR)
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
+ permissive_error_kind (global_dc));
+ diagnostic.option_index = permissive_error_option (global_dc);
+ }
+ else
+ {
+ diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
+ if (kind == DK_WARNING || kind == DK_PEDWARN)
+ diagnostic.option_index = opt;
+ }
+ diagnostic.metadata = metadata;
+ return diagnostic_report_diagnostic (global_dc, &diagnostic);
+}
+
+/* Implement inform_n, warning_n, and error_n, as documented and
+ defined below. */
+static bool
+diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
+ int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid,
+ va_list *ap, diagnostic_t kind)
+{
+ diagnostic_info diagnostic;
+ unsigned long gtn;
+
+ if (sizeof n <= sizeof gtn)
+ gtn = n;
+ else
+ /* Use the largest number ngettext can handle, otherwise
+ preserve the six least significant decimal digits for
+ languages where the plural form depends on them. */
+ gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
+
+ const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
+ diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
+ if (kind == DK_WARNING)
+ diagnostic.option_index = opt;
+ diagnostic.metadata = metadata;
+ return diagnostic_report_diagnostic (global_dc, &diagnostic);
+}
+
+/* Wrapper around diagnostic_impl taking a variable argument list. */
+
+bool
+emit_diagnostic (diagnostic_t kind, location_t location, int opt,
+ const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, location);
+ bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
+ va_end (ap);
+ return ret;
+}
+
+/* As above, but for rich_location *. */
+
+bool
+emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
+ const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
+ va_end (ap);
+ return ret;
+}
+
+/* Wrapper around diagnostic_impl taking a va_list parameter. */
+
+bool
+emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
+ const char *gmsgid, va_list *ap)
+{
+ rich_location richloc (line_table, location);
+ return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
+}
+
+/* An informative note at LOCATION. Use this for additional details on an error
+ message. */
+void
+inform (location_t location, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, location);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
+ va_end (ap);
+}
+
+/* Same as "inform" above, but at RICHLOC. */
+void
+inform (rich_location *richloc, const char *gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
+ va_end (ap);
+}
+
+/* An informative note at LOCATION. Use this for additional details on an
+ error message. */
+void
+inform_n (location_t location, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+ va_list ap;
+ va_start (ap, plural_gmsgid);
+ auto_diagnostic_group d;
+ rich_location richloc (line_table, location);
+ diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
+ &ap, DK_NOTE);
+ va_end (ap);
+}
+
+/* A warning at INPUT_LOCATION. Use this for code which is correct according
+ to the relevant language specification but is likely to be buggy anyway.
+ Returns true if the warning was printed, false if it was inhibited. */
+bool
+warning (int opt, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, input_location);
+ bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
+ va_end (ap);
+ return ret;
+}
+
+/* A warning at LOCATION. Use this for code which is correct according to the
+ relevant language specification but is likely to be buggy anyway.
+ Returns true if the warning was printed, false if it was inhibited. */
+
+bool
+warning_at (location_t location, int opt, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, location);
+ bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as "warning at" above, but using RICHLOC. */
+
+bool
+warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as "warning at" above, but using METADATA. */
+
+bool
+warning_meta (rich_location *richloc,
+ const diagnostic_metadata &metadata,
+ int opt, const char *gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ bool ret
+ = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
+ DK_WARNING);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as warning_n plural variant below, but using RICHLOC. */
+
+bool
+warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, plural_gmsgid);
+ bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
+ singular_gmsgid, plural_gmsgid,
+ &ap, DK_WARNING);
+ va_end (ap);
+ return ret;
+}
+
+/* A warning at LOCATION. Use this for code which is correct according to the
+ relevant language specification but is likely to be buggy anyway.
+ Returns true if the warning was printed, false if it was inhibited. */
+
+bool
+warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, plural_gmsgid);
+ rich_location richloc (line_table, location);
+ bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
+ singular_gmsgid, plural_gmsgid,
+ &ap, DK_WARNING);
+ va_end (ap);
+ return ret;
+}
+
+/* A "pedantic" warning at LOCATION: issues a warning unless
+ -pedantic-errors was given on the command line, in which case it
+ issues an error. Use this for diagnostics required by the relevant
+ language standard, if you have chosen not to make them errors.
+
+ Note that these diagnostics are issued independent of the setting
+ of the -Wpedantic command-line switch. To get a warning enabled
+ only with that switch, use either "if (pedantic) pedwarn
+ (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
+ pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
+
+ Returns true if the warning was printed, false if it was inhibited. */
+
+bool
+pedwarn (location_t location, int opt, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, location);
+ bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as pedwarn above, but using RICHLOC. */
+
+bool
+pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
+ va_end (ap);
+ return ret;
+}
+
+/* A "permissive" error at LOCATION: issues an error unless
+ -fpermissive was given on the command line, in which case it issues
+ a warning. Use this for things that really should be errors but we
+ want to support legacy code.
+
+ Returns true if the warning was printed, false if it was inhibited. */
+
+bool
+permerror (location_t location, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, location);
+ bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
+ va_end (ap);
+ return ret;
+}
+
+/* Same as "permerror" above, but at RICHLOC. */
+
+bool
+permerror (rich_location *richloc, const char *gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
+ va_end (ap);
+ return ret;
+}
+
+/* A hard error: the code is definitely ill-formed, and an object file
+ will not be produced. */
+void
+error (const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, input_location);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
+ va_end (ap);
+}
+
+/* A hard error: the code is definitely ill-formed, and an object file
+ will not be produced. */
+void
+error_n (location_t location, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, plural_gmsgid);
+ rich_location richloc (line_table, location);
+ diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
+ &ap, DK_ERROR);
+ va_end (ap);
+}
+
+/* Same as above, but use location LOC instead of input_location. */
+void
+error_at (location_t loc, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, loc);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
+ va_end (ap);
+}
+
+/* Same as above, but use RICH_LOC. */
+
+void
+error_at (rich_location *richloc, const char *gmsgid, ...)
+{
+ gcc_assert (richloc);
+
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
+ va_end (ap);
+}
+
+/* "Sorry, not implemented." Use for a language feature which is
+ required by the relevant specification but not implemented by GCC.
+ An object file will not be produced. */
+void
+sorry (const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, input_location);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
+ va_end (ap);
+}
+
+/* Same as above, but use location LOC instead of input_location. */
+void
+sorry_at (location_t loc, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, loc);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
+ va_end (ap);
+}
+
+/* Return true if an error or a "sorry" has been seen. Various
+ processing is disabled after errors. */
+bool
+seen_error (void)
+{
+ return errorcount || sorrycount;
+}
+
+/* An error which is severe enough that we make no attempt to
+ continue. Do not use this for internal consistency checks; that's
+ internal_error. Use of this function should be rare. */
+void
+fatal_error (location_t loc, const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, loc);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
+ va_end (ap);
+
+ gcc_unreachable ();
+}
+
+/* An internal consistency check has failed. We make no attempt to
+ continue. Note that unless there is debugging value to be had from
+ a more specific message, or some other good reason, you should use
+ abort () instead of calling this function directly. */
+void
+internal_error (const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, input_location);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
+ va_end (ap);
+
+ gcc_unreachable ();
+}
+
+/* Like internal_error, but no backtrace will be printed. Used when
+ the internal error does not happen at the current location, but happened
+ somewhere else. */
+void
+internal_error_no_backtrace (const char *gmsgid, ...)
+{
+ auto_diagnostic_group d;
+ va_list ap;
+ va_start (ap, gmsgid);
+ rich_location richloc (line_table, input_location);
+ diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
+ va_end (ap);
+
+ gcc_unreachable ();
+}
+
+/* Special case error functions. Most are implemented in terms of the
+ above, or should be. */
+
+/* Print a diagnostic MSGID on FILE. This is just fprintf, except it
+ runs its second argument through gettext. */
+void
+fnotice (FILE *file, const char *cmsgid, ...)
+{
+ va_list ap;
+
+ va_start (ap, cmsgid);
+ vfprintf (file, _(cmsgid), ap);
+ va_end (ap);
+}
+
+/* Inform the user that an error occurred while trying to report some
+ other error. This indicates catastrophic internal inconsistencies,
+ so give up now. But do try to flush out the previous error.
+ This mustn't use internal_error, that will cause infinite recursion. */
+
+static void
+error_recursion (diagnostic_context *context)
+{
+ if (context->lock < 3)
+ pp_newline_and_flush (context->printer);
+
+ fnotice (stderr,
+ "internal compiler error: error reporting routines re-entered.\n");
+
+ /* Call diagnostic_action_after_output to get the "please submit a bug
+ report" message. */
+ diagnostic_action_after_output (context, DK_ICE);
+
+ /* Do not use gcc_unreachable here; that goes through internal_error
+ and therefore would cause infinite recursion. */
+ real_abort ();
+}
+
+/* Report an internal compiler error in a friendly manner. This is
+ the function that gets called upon use of abort() in the source
+ code generally, thanks to a special macro. */
+
+void
+fancy_abort (const char *file, int line, const char *function)
+{
+ /* If fancy_abort is called before the diagnostic subsystem is initialized,
+ internal_error will crash internally in a way that prevents a
+ useful message reaching the user.
+ This can happen with libgccjit in the case of gcc_assert failures
+ that occur outside of the libgccjit mutex that guards the rest of
+ gcc's state, including global_dc (when global_dc may not be
+ initialized yet, or might be in use by another thread).
+ Handle such cases as gracefully as possible by falling back to a
+ minimal abort handler that only relies on i18n. */
+ if (global_dc->printer == NULL)
+ {
+ /* Print the error message. */
+ fnotice (stderr, diagnostic_kind_text[DK_ICE]);
+ fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
+ fputc ('\n', stderr);
+
+ /* Attempt to print a backtrace. */
+ struct backtrace_state *state
+ = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
+ int count = 0;
+ if (state != NULL)
+ backtrace_full (state, 2, bt_callback, bt_err_callback,
+ (void *) &count);
+
+ /* We can't call warn_if_plugins or emergency_dump_function as these
+ rely on GCC state that might not be initialized, or might be in
+ use by another thread. */
+
+ /* Abort the process. */
+ real_abort ();
+ }
+
+ internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
+}
+
+/* class auto_diagnostic_group. */
+
+/* Constructor: "push" this group into global_dc. */
+
+auto_diagnostic_group::auto_diagnostic_group ()
+{
+ global_dc->diagnostic_group_nesting_depth++;
+}
+
+/* Destructor: "pop" this group from global_dc. */
+
+auto_diagnostic_group::~auto_diagnostic_group ()
+{
+ if (--global_dc->diagnostic_group_nesting_depth == 0)
+ {
+ /* Handle the case where we've popped the final diagnostic group.
+ If any diagnostics were emitted, give the context a chance
+ to do something. */
+ if (global_dc->diagnostic_group_emission_count > 0)
+ {
+ if (global_dc->end_group_cb)
+ global_dc->end_group_cb (global_dc);
+ }
+ global_dc->diagnostic_group_emission_count = 0;
+ }
+}
+
+/* Implementation of diagnostic_path::num_events vfunc for
+ simple_diagnostic_path: simply get the number of events in the vec. */
+
+unsigned
+simple_diagnostic_path::num_events () const
+{
+ return m_events.length ();
+}
+
+/* Implementation of diagnostic_path::get_event vfunc for
+ simple_diagnostic_path: simply return the event in the vec. */
+
+const diagnostic_event &
+simple_diagnostic_path::get_event (int idx) const
+{
+ return *m_events[idx];
+}
+
+/* Add an event to this path at LOC within function FNDECL at
+ stack depth DEPTH.
+
+ Use m_context's printer to format FMT, as the text of the new
+ event.
+
+ Return the id of the new event. */
+
+diagnostic_event_id_t
+simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
+ const char *fmt, ...)
+{
+ pretty_printer *pp = m_event_pp;
+ pp_clear_output_area (pp);
+
+ text_info ti;
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+ va_list ap;
+
+ va_start (ap, fmt);
+
+ ti.format_spec = _(fmt);
+ ti.args_ptr = &ap;
+ ti.err_no = 0;
+ ti.x_data = NULL;
+ ti.m_richloc = &rich_loc;
+
+ pp_format (pp, &ti);
+ pp_output_formatted_text (pp);
+
+ va_end (ap);
+
+ simple_diagnostic_event *new_event
+ = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
+ m_events.safe_push (new_event);
+
+ pp_clear_output_area (pp);
+
+ return diagnostic_event_id_t (m_events.length () - 1);
+}
+
+/* struct simple_diagnostic_event. */
+
+/* simple_diagnostic_event's ctor. */
+
+simple_diagnostic_event::simple_diagnostic_event (location_t loc,
+ tree fndecl,
+ int depth,
+ const char *desc)
+: m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
+{
+}
+
+/* simple_diagnostic_event's dtor. */
+
+simple_diagnostic_event::~simple_diagnostic_event ()
+{
+ free (m_desc);
+}
+
+/* Print PATH by emitting a dummy "note" associated with it. */
+
+DEBUG_FUNCTION
+void debug (diagnostic_path *path)
+{
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+ richloc.set_path (path);
+ inform (&richloc, "debug path");
+}
+
+/* Really call the system 'abort'. This has to go right at the end of
+ this file, so that there are no functions after it that call abort
+ and get the system abort instead of our macro. */
+#undef abort
+static void
+real_abort (void)
+{
+ abort ();
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Helper function for test_print_escaped_string. */
+
+static void
+assert_print_escaped_string (const location &loc, const char *expected_output,
+ const char *input)
+{
+ pretty_printer pp;
+ print_escaped_string (&pp, input);
+ ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
+}
+
+#define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
+ assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
+
+/* Tests of print_escaped_string. */
+
+static void
+test_print_escaped_string ()
+{
+ /* Empty string. */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
+
+ /* Non-empty string. */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
+
+ /* Various things that need to be escaped: */
+ /* Backslash. */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
+ "before\\after");
+ /* Tab. */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
+ "before\tafter");
+ /* Newline. */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
+ "before\nafter");
+ /* Double quote. */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
+ "before\"after");
+
+ /* Non-printable characters: BEL: '\a': 0x07 */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
+ "before\aafter");
+ /* Non-printable characters: vertical tab: '\v': 0x0b */
+ ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
+ "before\vafter");
+}
+
+/* Tests of print_parseable_fixits. */
+
+/* Verify that print_parseable_fixits emits the empty string if there
+ are no fixits. */
+
+static void
+test_print_parseable_fixits_none ()
+{
+ pretty_printer pp;
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+
+ print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+ ASSERT_STREQ ("", pp_formatted_text (&pp));
+}
+
+/* Verify that print_parseable_fixits does the right thing if there
+ is an insertion fixit hint. */
+
+static void
+test_print_parseable_fixits_insert ()
+{
+ pretty_printer pp;
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+
+ linemap_add (line_table, LC_ENTER, false, "test.c", 0);
+ linemap_line_start (line_table, 5, 100);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ location_t where = linemap_position_for_column (line_table, 10);
+ richloc.add_fixit_insert_before (where, "added content");
+
+ print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+ ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
+ pp_formatted_text (&pp));
+}
+
+/* Verify that print_parseable_fixits does the right thing if there
+ is an removal fixit hint. */
+
+static void
+test_print_parseable_fixits_remove ()
+{
+ pretty_printer pp;
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+
+ linemap_add (line_table, LC_ENTER, false, "test.c", 0);
+ linemap_line_start (line_table, 5, 100);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ source_range where;
+ where.m_start = linemap_position_for_column (line_table, 10);
+ where.m_finish = linemap_position_for_column (line_table, 20);
+ richloc.add_fixit_remove (where);
+
+ print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+ ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
+ pp_formatted_text (&pp));
+}
+
+/* Verify that print_parseable_fixits does the right thing if there
+ is an replacement fixit hint. */
+
+static void
+test_print_parseable_fixits_replace ()
+{
+ pretty_printer pp;
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+
+ linemap_add (line_table, LC_ENTER, false, "test.c", 0);
+ linemap_line_start (line_table, 5, 100);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ source_range where;
+ where.m_start = linemap_position_for_column (line_table, 10);
+ where.m_finish = linemap_position_for_column (line_table, 20);
+ richloc.add_fixit_replace (where, "replacement");
+
+ print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
+ ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
+ pp_formatted_text (&pp));
+}
+
+/* Verify that print_parseable_fixits correctly handles
+ DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
+
+static void
+test_print_parseable_fixits_bytes_vs_display_columns ()
+{
+ line_table_test ltt;
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+
+ /* 1-based byte offsets: 12345677778888999900001234567. */
+ const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
+ /* 1-based display cols: 123456[......7-8.....]9012345. */
+ const int tabstop = 8;
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ const char *const fname = tmp.get_filename ();
+
+ linemap_add (line_table, LC_ENTER, false, fname, 0);
+ linemap_line_start (line_table, 1, 100);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+ source_range where;
+ where.m_start = linemap_position_for_column (line_table, 12);
+ where.m_finish = linemap_position_for_column (line_table, 17);
+ richloc.add_fixit_replace (where, "color");
+
+ /* Escape fname. */
+ pretty_printer tmp_pp;
+ print_escaped_string (&tmp_pp, fname);
+ char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
+
+ const int buf_len = strlen (escaped_fname) + 100;
+ char *const expected = XNEWVEC (char, buf_len);
+
+ {
+ pretty_printer pp;
+ print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
+ tabstop);
+ snprintf (expected, buf_len,
+ "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
+ ASSERT_STREQ (expected, pp_formatted_text (&pp));
+ }
+ {
+ pretty_printer pp;
+ print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+ tabstop);
+ snprintf (expected, buf_len,
+ "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
+ ASSERT_STREQ (expected, pp_formatted_text (&pp));
+ }
+
+ XDELETEVEC (expected);
+ free (escaped_fname);
+}
+
+/* Verify that
+ diagnostic_get_location_text (..., SHOW_COLUMN)
+ generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
+ colorization disabled. */
+
+static void
+assert_location_text (const char *expected_loc_text,
+ const char *filename, int line, int column,
+ bool show_column,
+ int origin = 1,
+ enum diagnostics_column_unit column_unit
+ = DIAGNOSTICS_COLUMN_UNIT_BYTE)
+{
+ test_diagnostic_context dc;
+ dc.show_column = show_column;
+ dc.column_unit = column_unit;
+ dc.column_origin = origin;
+
+ expanded_location xloc;
+ xloc.file = filename;
+ xloc.line = line;
+ xloc.column = column;
+ xloc.data = NULL;
+ xloc.sysp = false;
+
+ char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
+ ASSERT_STREQ (expected_loc_text, actual_loc_text);
+ free (actual_loc_text);
+}
+
+/* Verify that diagnostic_get_location_text works as expected. */
+
+static void
+test_diagnostic_get_location_text ()
+{
+ const char *old_progname = progname;
+ progname = "PROGNAME";
+ assert_location_text ("PROGNAME:", NULL, 0, 0, true);
+ assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
+ assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
+ assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
+ assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
+ for (int origin = 0; origin != 2; ++origin)
+ assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
+ assert_location_text ("foo.c:", "foo.c", 0, 10, true);
+ assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
+ assert_location_text ("foo.c:", "foo.c", 0, 10, false);
+
+ maybe_line_and_column (INT_MAX, INT_MAX);
+ maybe_line_and_column (INT_MIN, INT_MIN);
+
+ {
+ /* In order to test display columns vs byte columns, we need to create a
+ file for location_get_source_line() to read. */
+
+ const char *const content = "smile \xf0\x9f\x98\x82\n";
+ const int line_bytes = strlen (content) - 1;
+ const int def_tabstop = 8;
+ const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
+ const int display_width = cpp_display_width (content, line_bytes, policy);
+ ASSERT_EQ (line_bytes - 2, display_width);
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ const char *const fname = tmp.get_filename ();
+ const int buf_len = strlen (fname) + 16;
+ char *const expected = XNEWVEC (char, buf_len);
+
+ snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
+ assert_location_text (expected, fname, 1, line_bytes, true,
+ 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
+
+ snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
+ assert_location_text (expected, fname, 1, line_bytes, true,
+ 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
+
+ snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
+ assert_location_text (expected, fname, 1, line_bytes, true,
+ 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
+
+ snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
+ assert_location_text (expected, fname, 1, line_bytes, true,
+ 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
+
+ XDELETEVEC (expected);
+ }
+
+
+ progname = old_progname;
+}
+
+/* Selftest for num_digits. */
+
+static void
+test_num_digits ()
+{
+ ASSERT_EQ (1, num_digits (0));
+ ASSERT_EQ (1, num_digits (9));
+ ASSERT_EQ (2, num_digits (10));
+ ASSERT_EQ (2, num_digits (99));
+ ASSERT_EQ (3, num_digits (100));
+ ASSERT_EQ (3, num_digits (999));
+ ASSERT_EQ (4, num_digits (1000));
+ ASSERT_EQ (4, num_digits (9999));
+ ASSERT_EQ (5, num_digits (10000));
+ ASSERT_EQ (5, num_digits (99999));
+ ASSERT_EQ (6, num_digits (100000));
+ ASSERT_EQ (6, num_digits (999999));
+ ASSERT_EQ (7, num_digits (1000000));
+ ASSERT_EQ (7, num_digits (9999999));
+ ASSERT_EQ (8, num_digits (10000000));
+ ASSERT_EQ (8, num_digits (99999999));
+}
+
+/* Run all of the selftests within this file. */
+
+void
+c_diagnostic_cc_tests ()
+{
+ test_print_escaped_string ();
+ test_print_parseable_fixits_none ();
+ test_print_parseable_fixits_insert ();
+ test_print_parseable_fixits_remove ();
+ test_print_parseable_fixits_replace ();
+ test_print_parseable_fixits_bytes_vs_display_columns ();
+ test_diagnostic_get_location_text ();
+ test_num_digits ();
+
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+#if __GNUC__ >= 10
+# pragma GCC diagnostic pop
+#endif
diff --git a/support/cpp/gcc/diagnostic.def b/support/cpp/gcc/diagnostic.def
new file mode 100644
index 000000000..502081159
--- /dev/null
+++ b/support/cpp/gcc/diagnostic.def
@@ -0,0 +1,55 @@
+/* Copyright (C) 2001-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/>. */
+
+/* DK_UNSPECIFIED must be first so it has a value of zero. We never
+ assign this kind to an actual diagnostic, we only use this in
+ variables that can hold a kind, to mean they have yet to have a
+ kind specified. I.e. they're uninitialized. Within the diagnostic
+ machinery, this kind also means "don't change the existing kind",
+ meaning "no change is specified". */
+DEFINE_DIAGNOSTIC_KIND (DK_UNSPECIFIED, "", NULL)
+
+/* If a diagnostic is set to DK_IGNORED, it won't get reported at all.
+ This is used by the diagnostic machinery when it wants to disable a
+ diagnostic without disabling the option which causes it. */
+DEFINE_DIAGNOSTIC_KIND (DK_IGNORED, "", NULL)
+
+/* The remainder are real diagnostic types. */
+DEFINE_DIAGNOSTIC_KIND (DK_FATAL, "fatal error: ", "error")
+DEFINE_DIAGNOSTIC_KIND (DK_ICE, "internal compiler error: ", "error")
+DEFINE_DIAGNOSTIC_KIND (DK_ERROR, "error: ", "error")
+DEFINE_DIAGNOSTIC_KIND (DK_SORRY, "sorry, unimplemented: ", "error")
+DEFINE_DIAGNOSTIC_KIND (DK_WARNING, "warning: ", "warning")
+DEFINE_DIAGNOSTIC_KIND (DK_ANACHRONISM, "anachronism: ", "warning")
+DEFINE_DIAGNOSTIC_KIND (DK_NOTE, "note: ", "note")
+DEFINE_DIAGNOSTIC_KIND (DK_DEBUG, "debug: ", "note")
+
+/* For use when using the diagnostic_show_locus machinery to show
+ a range of events within a path. */
+DEFINE_DIAGNOSTIC_KIND (DK_DIAGNOSTIC_PATH, "path: ", "path")
+
+/* These two would be re-classified as DK_WARNING or DK_ERROR, so the
+prefix does not matter. */
+DEFINE_DIAGNOSTIC_KIND (DK_PEDWARN, "pedwarn: ", NULL)
+DEFINE_DIAGNOSTIC_KIND (DK_PERMERROR, "permerror: ", NULL)
+/* This one is just for counting DK_WARNING promoted to DK_ERROR
+ due to -Werror and -Werror=warning. */
+DEFINE_DIAGNOSTIC_KIND (DK_WERROR, "error: ", NULL)
+/* This is like DK_ICE, but backtrace is not printed. Used in the driver
+ when reporting fatal signal in the compiler. */
+DEFINE_DIAGNOSTIC_KIND (DK_ICE_NOBT, "internal compiler error: ", "error")
diff --git a/support/cpp/gcc/diagnostic.h b/support/cpp/gcc/diagnostic.h
new file mode 100644
index 000000000..3ca32979d
--- /dev/null
+++ b/support/cpp/gcc/diagnostic.h
@@ -0,0 +1,590 @@
+/* Various declarations for language-independent diagnostics subroutines.
+ Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@codesourcery.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.
+
+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_DIAGNOSTIC_H
+#define GCC_DIAGNOSTIC_H
+
+#include "pretty-print.h"
+#include "diagnostic-core.h"
+
+/* An enum for controlling what units to use for the column number
+ when diagnostics are output, used by the -fdiagnostics-column-unit option.
+ Tabs will be expanded or not according to the value of -ftabstop. The origin
+ (default 1) is controlled by -fdiagnostics-column-origin. */
+
+enum diagnostics_column_unit
+{
+ /* The default from GCC 11 onwards: display columns. */
+ DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
+
+ /* The behavior in GCC 10 and earlier: simple bytes. */
+ DIAGNOSTICS_COLUMN_UNIT_BYTE
+};
+
+/* An enum for controlling how to print non-ASCII characters/bytes when
+ a diagnostic suggests escaping the source code on output. */
+
+enum diagnostics_escape_format
+{
+ /* Escape non-ASCII Unicode characters in the form <U+XXXX> and
+ non-UTF-8 bytes in the form <XX>. */
+ DIAGNOSTICS_ESCAPE_FORMAT_UNICODE,
+
+ /* Escape non-ASCII bytes in the form <XX> (thus showing the underlying
+ encoding of non-ASCII Unicode characters). */
+ DIAGNOSTICS_ESCAPE_FORMAT_BYTES
+};
+
+/* Enum for overriding the standard output format. */
+
+enum diagnostics_output_format
+{
+ /* The default: textual output. */
+ DIAGNOSTICS_OUTPUT_FORMAT_TEXT,
+
+ /* JSON-based output. */
+ DIAGNOSTICS_OUTPUT_FORMAT_JSON
+};
+
+/* An enum for controlling how diagnostic_paths should be printed. */
+enum diagnostic_path_format
+{
+ /* Don't print diagnostic_paths. */
+ DPF_NONE,
+
+ /* Print diagnostic_paths by emitting a separate "note" for every event
+ in the path. */
+ DPF_SEPARATE_EVENTS,
+
+ /* Print diagnostic_paths by consolidating events together where they
+ are close enough, and printing such runs of events with multiple
+ calls to diagnostic_show_locus, showing the individual events in
+ each run via labels in the source. */
+ DPF_INLINE_EVENTS
+};
+
+/* An enum for capturing values of GCC_EXTRA_DIAGNOSTIC_OUTPUT,
+ and for -fdiagnostics-parseable-fixits. */
+
+enum diagnostics_extra_output_kind
+{
+ /* No extra output, or an unrecognized value. */
+ EXTRA_DIAGNOSTIC_OUTPUT_none,
+
+ /* Emit fix-it hints using the "fixits-v1" format, equivalent to
+ -fdiagnostics-parseable-fixits. */
+ EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1,
+
+ /* Emit fix-it hints using the "fixits-v2" format. */
+ EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
+};
+
+/* A diagnostic is described by the MESSAGE to send, the FILE and LINE of
+ its context and its KIND (ice, error, warning, note, ...) See complete
+ list in diagnostic.def. */
+struct diagnostic_info
+{
+ diagnostic_info ()
+ : message (), richloc (), metadata (), x_data (), kind (), option_index (),
+ m_iinfo ()
+ { }
+
+ /* Text to be formatted. */
+ text_info message;
+
+ /* The location at which the diagnostic is to be reported. */
+ rich_location *richloc;
+
+ /* An optional bundle of metadata associated with the diagnostic
+ (or NULL). */
+ const diagnostic_metadata *metadata;
+
+ /* Auxiliary data for client. */
+ void *x_data;
+ /* The kind of diagnostic it is about. */
+ diagnostic_t kind;
+ /* Which OPT_* directly controls this diagnostic. */
+ int option_index;
+
+ /* Inlining context containing locations for each call site along
+ the inlining stack. */
+ struct inlining_info
+ {
+ /* Locations along the inlining stack. */
+ auto_vec<location_t, 8> m_ilocs;
+ /* The abstract origin of the location. */
+ void *m_ao;
+ /* Set if every M_ILOCS element is in a system header. */
+ bool m_allsyslocs;
+ } m_iinfo;
+};
+
+/* Each time a diagnostic's classification is changed with a pragma,
+ we record the change and the location of the change in an array of
+ these structs. */
+struct diagnostic_classification_change_t
+{
+ location_t location;
+ int option;
+ diagnostic_t kind;
+};
+
+/* Forward declarations. */
+typedef void (*diagnostic_starter_fn) (diagnostic_context *,
+ diagnostic_info *);
+
+typedef void (*diagnostic_start_span_fn) (diagnostic_context *,
+ expanded_location);
+
+typedef void (*diagnostic_finalizer_fn) (diagnostic_context *,
+ diagnostic_info *,
+ diagnostic_t);
+
+class edit_context;
+namespace json { class value; }
+
+/* This data structure bundles altogether any information relevant to
+ the context of a diagnostic message. */
+struct diagnostic_context
+{
+ /* Where most of the diagnostic formatting work is done. */
+ pretty_printer *printer;
+
+ /* Cache of source code. */
+ file_cache *m_file_cache;
+
+ /* The number of times we have issued diagnostics. */
+ int diagnostic_count[DK_LAST_DIAGNOSTIC_KIND];
+
+ /* True if it has been requested that warnings be treated as errors. */
+ bool warning_as_error_requested;
+
+ /* The number of option indexes that can be passed to warning() et
+ al. */
+ int n_opts;
+
+ /* For each option index that can be passed to warning() et al
+ (OPT_* from options.h when using this code with the core GCC
+ options), this array may contain a new kind that the diagnostic
+ should be changed to before reporting, or DK_UNSPECIFIED to leave
+ it as the reported kind, or DK_IGNORED to not report it at
+ all. */
+ diagnostic_t *classify_diagnostic;
+
+ /* History of all changes to the classifications above. This list
+ is stored in location-order, so we can search it, either
+ binary-wise or end-to-front, to find the most recent
+ classification for a given diagnostic, given the location of the
+ diagnostic. */
+ diagnostic_classification_change_t *classification_history;
+
+ /* The size of the above array. */
+ int n_classification_history;
+
+ /* For pragma push/pop. */
+ int *push_list;
+ int n_push;
+
+ /* True if we should print the source line with a caret indicating
+ the location. */
+ bool show_caret;
+
+ /* Maximum width of the source line printed. */
+ int caret_max_width;
+
+ /* Character used for caret diagnostics. */
+ char caret_chars[rich_location::STATICALLY_ALLOCATED_RANGES];
+
+ /* True if we should print any CWE identifiers associated with
+ diagnostics. */
+ bool show_cwe;
+
+ /* How should diagnostic_path objects be printed. */
+ enum diagnostic_path_format path_format;
+
+ /* True if we should print stack depths when printing diagnostic paths. */
+ bool show_path_depths;
+
+ /* True if we should print the command line option which controls
+ each diagnostic, if known. */
+ bool show_option_requested;
+
+ /* True if we should raise a SIGABRT on errors. */
+ bool abort_on_error;
+
+ /* True if we should show the column number on diagnostics. */
+ bool show_column;
+
+ /* True if pedwarns are errors. */
+ bool pedantic_errors;
+
+ /* True if permerrors are warnings. */
+ bool permissive;
+
+ /* The index of the option to associate with turning permerrors into
+ warnings. */
+ int opt_permissive;
+
+ /* True if errors are fatal. */
+ bool fatal_errors;
+
+ /* True if all warnings should be disabled. */
+ bool dc_inhibit_warnings;
+
+ /* True if warnings should be given in system headers. */
+ bool dc_warn_system_headers;
+
+ /* Maximum number of errors to report. */
+ int max_errors;
+
+ /* This function is called before any message is printed out. It is
+ responsible for preparing message prefix and such. For example, it
+ might say:
+ In file included from "/usr/local/include/curses.h:5:
+ from "/home/gdr/src/nifty_printer.h:56:
+ ...
+ */
+ diagnostic_starter_fn begin_diagnostic;
+
+ /* This function is called by diagnostic_show_locus in between
+ disjoint spans of source code, so that the context can print
+ something to indicate that a new span of source code has begun. */
+ diagnostic_start_span_fn start_span;
+
+ /* This function is called after the diagnostic message is printed. */
+ diagnostic_finalizer_fn end_diagnostic;
+
+ /* Client hook to report an internal error. */
+ void (*internal_error) (diagnostic_context *, const char *, va_list *);
+
+ /* Client hook to say whether the option controlling a diagnostic is
+ enabled. Returns nonzero if enabled, zero if disabled. */
+ int (*option_enabled) (int, unsigned, void *);
+
+ /* Client information to pass as second argument to
+ option_enabled. */
+ void *option_state;
+
+ /* Client hook to return the name of an option that controls a
+ diagnostic. Returns malloced memory. The first diagnostic_t
+ argument is the kind of diagnostic before any reclassification
+ (of warnings as errors, etc.); the second is the kind after any
+ reclassification. May return NULL if no name is to be printed.
+ May be passed 0 as well as the index of a particular option. */
+ char *(*option_name) (diagnostic_context *, int, diagnostic_t, diagnostic_t);
+
+ /* Client hook to return a URL describing the option that controls
+ a diagnostic. Returns malloced memory. May return NULL if no URL
+ is available. May be passed 0 as well as the index of a
+ particular option. */
+ char *(*get_option_url) (diagnostic_context *, int);
+
+ void (*print_path) (diagnostic_context *, const diagnostic_path *);
+ json::value *(*make_json_for_path) (diagnostic_context *, const diagnostic_path *);
+
+ /* Auxiliary data for client. */
+ void *x_data;
+
+ /* Used to detect that the last caret was printed at the same location. */
+ location_t last_location;
+
+ /* Used to detect when the input file stack has changed since last
+ described. */
+ const line_map_ordinary *last_module;
+
+ int lock;
+
+ /* A copy of lang_hooks.option_lang_mask (). */
+ unsigned lang_mask;
+
+ bool inhibit_notes_p;
+
+ /* When printing source code, should the characters at carets and ranges
+ be colorized? (assuming colorization is on at all).
+ This should be true for frontends that generate range information
+ (so that the ranges of code are colorized),
+ and false for frontends that merely specify points within the
+ source code (to avoid e.g. colorizing just the first character in
+ a token, which would look strange). */
+ bool colorize_source_p;
+
+ /* When printing source code, should labelled ranges be printed? */
+ bool show_labels_p;
+
+ /* When printing source code, should there be a left-hand margin
+ showing line numbers? */
+ bool show_line_numbers_p;
+
+ /* If printing source code, what should the minimum width of the margin
+ be? Line numbers will be right-aligned, and padded to this width. */
+ int min_margin_width;
+
+ /* Usable by plugins; if true, print a debugging ruler above the
+ source output. */
+ bool show_ruler_p;
+
+ /* True if -freport-bug option is used. */
+ bool report_bug;
+
+ /* Used to specify additional diagnostic output to be emitted after the
+ rest of the diagnostic. This is for implementing
+ -fdiagnostics-parseable-fixits and GCC_EXTRA_DIAGNOSTIC_OUTPUT. */
+ enum diagnostics_extra_output_kind extra_output_kind;
+
+ /* What units to use when outputting the column number. */
+ enum diagnostics_column_unit column_unit;
+
+ /* The origin for the column number (1-based or 0-based typically). */
+ int column_origin;
+
+ /* The size of the tabstop for tab expansion. */
+ int tabstop;
+
+ /* How should non-ASCII/non-printable bytes be escaped when
+ a diagnostic suggests escaping the source code on output. */
+ enum diagnostics_escape_format escape_format;
+
+ /* If non-NULL, an edit_context to which fix-it hints should be
+ applied, for generating patches. */
+ edit_context *edit_context_ptr;
+
+ /* How many diagnostic_group instances are currently alive. */
+ int diagnostic_group_nesting_depth;
+
+ /* How many diagnostics have been emitted since the bottommost
+ diagnostic_group was pushed. */
+ int diagnostic_group_emission_count;
+
+ /* Optional callbacks for handling diagnostic groups. */
+
+ /* If non-NULL, this will be called immediately before the first
+ time a diagnostic is emitted within a stack of groups. */
+ void (*begin_group_cb) (diagnostic_context * context);
+
+ /* If non-NULL, this will be called when a stack of groups is
+ popped if any diagnostics were emitted within that group. */
+ void (*end_group_cb) (diagnostic_context * context);
+
+ /* Callback for final cleanup. */
+ void (*final_cb) (diagnostic_context *context);
+
+ /* Callback to set the locations of call sites along the inlining
+ stack corresponding to a diagnostic location. Needed to traverse
+ the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
+ of a diagnostic's location. */
+ void (*set_locations_cb)(diagnostic_context *, diagnostic_info *);
+
+ /* Include files that diagnostic_report_current_module has already listed the
+ include path for. */
+ hash_set<location_t, false, location_hash> *includes_seen;
+};
+
+static inline void
+diagnostic_inhibit_notes (diagnostic_context * context)
+{
+ context->inhibit_notes_p = true;
+}
+
+
+/* Client supplied function to announce a diagnostic. */
+#define diagnostic_starter(DC) (DC)->begin_diagnostic
+
+/* Client supplied function called after a diagnostic message is
+ displayed. */
+#define diagnostic_finalizer(DC) (DC)->end_diagnostic
+
+/* Extension hooks for client. */
+#define diagnostic_context_auxiliary_data(DC) (DC)->x_data
+#define diagnostic_info_auxiliary_data(DI) (DI)->x_data
+
+/* Same as pp_format_decoder. Works on 'diagnostic_context *'. */
+#define diagnostic_format_decoder(DC) ((DC)->printer->format_decoder)
+
+/* Same as output_prefixing_rule. Works on 'diagnostic_context *'. */
+#define diagnostic_prefixing_rule(DC) ((DC)->printer->wrapping.rule)
+
+/* Raise SIGABRT on any diagnostic of severity DK_ERROR or higher. */
+#define diagnostic_abort_on_error(DC) \
+ (DC)->abort_on_error = true
+
+/* This diagnostic_context is used by front-ends that directly output
+ diagnostic messages without going through `error', `warning',
+ and similar functions. */
+extern diagnostic_context *global_dc;
+
+/* Returns whether the diagnostic framework has been intialized already and is
+ ready for use. */
+#define diagnostic_ready_p() (global_dc->printer != NULL)
+
+/* The total count of a KIND of diagnostics emitted so far. */
+#define diagnostic_kind_count(DC, DK) (DC)->diagnostic_count[(int) (DK)]
+
+/* The number of errors that have been issued so far. Ideally, these
+ would take a diagnostic_context as an argument. */
+#define errorcount diagnostic_kind_count (global_dc, DK_ERROR)
+/* Similarly, but for warnings. */
+#define warningcount diagnostic_kind_count (global_dc, DK_WARNING)
+/* Similarly, but for warnings promoted to errors. */
+#define werrorcount diagnostic_kind_count (global_dc, DK_WERROR)
+/* Similarly, but for sorrys. */
+#define sorrycount diagnostic_kind_count (global_dc, DK_SORRY)
+
+/* Returns nonzero if warnings should be emitted. */
+#define diagnostic_report_warnings_p(DC, LOC) \
+ (!(DC)->dc_inhibit_warnings \
+ && !(in_system_header_at (LOC) && !(DC)->dc_warn_system_headers))
+
+/* Override the option index to be used for reporting a
+ diagnostic. */
+
+static inline void
+diagnostic_override_option_index (diagnostic_info *info, int optidx)
+{
+ info->option_index = optidx;
+}
+
+/* Diagnostic related functions. */
+extern void diagnostic_initialize (diagnostic_context *, int);
+extern void diagnostic_color_init (diagnostic_context *, int value = -1);
+extern void diagnostic_urls_init (diagnostic_context *, int value = -1);
+extern void diagnostic_finish (diagnostic_context *);
+extern void diagnostic_report_current_module (diagnostic_context *, location_t);
+extern void diagnostic_show_locus (diagnostic_context *,
+ rich_location *richloc,
+ diagnostic_t diagnostic_kind);
+extern void diagnostic_show_any_path (diagnostic_context *, diagnostic_info *);
+
+/* Because we read source files a second time after the frontend did it the
+ first time, we need to know how the frontend handled things like character
+ set conversion and UTF-8 BOM stripping, in order to make everything
+ consistent. This function needs to be called by each frontend that requires
+ non-default behavior, to inform the diagnostics infrastructure how input is
+ to be processed. The default behavior is to do no conversion and not to
+ strip a UTF-8 BOM.
+
+ The callback should return the input charset to be used to convert the given
+ file's contents to UTF-8, or it should return NULL if no conversion is needed
+ for this file. SHOULD_SKIP_BOM only applies in case no conversion was
+ performed, and if true, it will cause a UTF-8 BOM to be skipped at the
+ beginning of the file. (In case a conversion was performed, the BOM is
+ rather skipped as part of the conversion process.) */
+
+void diagnostic_initialize_input_context (diagnostic_context *context,
+ diagnostic_input_charset_callback ccb,
+ bool should_skip_bom);
+
+/* Force diagnostics controlled by OPTIDX to be kind KIND. */
+extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
+ int /* optidx */,
+ diagnostic_t /* kind */,
+ location_t);
+extern void diagnostic_push_diagnostics (diagnostic_context *, location_t);
+extern void diagnostic_pop_diagnostics (diagnostic_context *, location_t);
+extern bool diagnostic_report_diagnostic (diagnostic_context *,
+ diagnostic_info *);
+#ifdef ATTRIBUTE_GCC_DIAG
+extern void diagnostic_set_info (diagnostic_info *, const char *, va_list *,
+ rich_location *, diagnostic_t) ATTRIBUTE_GCC_DIAG(2,0);
+extern void diagnostic_set_info_translated (diagnostic_info *, const char *,
+ va_list *, rich_location *,
+ diagnostic_t)
+ ATTRIBUTE_GCC_DIAG(2,0);
+extern void diagnostic_append_note (diagnostic_context *, location_t,
+ const char *, ...) ATTRIBUTE_GCC_DIAG(3,4);
+#endif
+extern char *diagnostic_build_prefix (diagnostic_context *, const diagnostic_info *);
+void default_diagnostic_starter (diagnostic_context *, diagnostic_info *);
+void default_diagnostic_start_span_fn (diagnostic_context *,
+ expanded_location);
+void default_diagnostic_finalizer (diagnostic_context *, diagnostic_info *,
+ diagnostic_t);
+void diagnostic_set_caret_max_width (diagnostic_context *context, int value);
+void diagnostic_action_after_output (diagnostic_context *, diagnostic_t);
+void diagnostic_check_max_errors (diagnostic_context *, bool flush = false);
+
+void diagnostic_file_cache_fini (void);
+
+int get_terminal_width (void);
+
+/* Return the location associated to this diagnostic. Parameter WHICH
+ specifies which location. By default, expand the first one. */
+
+static inline location_t
+diagnostic_location (const diagnostic_info * diagnostic, int which = 0)
+{
+ return diagnostic->message.get_location (which);
+}
+
+/* Return the number of locations to be printed in DIAGNOSTIC. */
+
+static inline unsigned int
+diagnostic_num_locations (const diagnostic_info * diagnostic)
+{
+ return diagnostic->message.m_richloc->get_num_locations ();
+}
+
+/* Expand the location of this diagnostic. Use this function for
+ consistency. Parameter WHICH specifies which location. By default,
+ expand the first one. */
+
+static inline expanded_location
+diagnostic_expand_location (const diagnostic_info * diagnostic, int which = 0)
+{
+ return diagnostic->richloc->get_expanded_location (which);
+}
+
+/* This is somehow the right-side margin of a caret line, that is, we
+ print at least these many characters after the position pointed at
+ by the caret. */
+const int CARET_LINE_MARGIN = 10;
+
+/* Return true if the two locations can be represented within the same
+ caret line. This is used to build a prefix and also to determine
+ whether to print one or two caret lines. */
+
+static inline bool
+diagnostic_same_line (const diagnostic_context *context,
+ expanded_location s1, expanded_location s2)
+{
+ return s2.column && s1.line == s2.line
+ && context->caret_max_width - CARET_LINE_MARGIN > abs (s1.column - s2.column);
+}
+
+extern const char *diagnostic_get_color_for_kind (diagnostic_t kind);
+extern int diagnostic_converted_column (diagnostic_context *context,
+ expanded_location s);
+
+/* Pure text formatting support functions. */
+extern char *file_name_as_prefix (diagnostic_context *, const char *);
+
+extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1;
+
+extern void diagnostic_output_format_init (diagnostic_context *,
+ enum diagnostics_output_format);
+
+/* Compute the number of digits in the decimal representation of an integer. */
+extern int num_digits (int);
+
+extern json::value *json_from_expanded_location (diagnostic_context *context,
+ location_t loc);
+
+extern bool warning_enabled_at (location_t, int);
+
+#endif /* ! GCC_DIAGNOSTIC_H */
diff --git a/support/cpp/gcc/dominance.h b/support/cpp/gcc/dominance.h
new file mode 100644
index 000000000..5c4fe1811
--- /dev/null
+++ b/support/cpp/gcc/dominance.h
@@ -0,0 +1,94 @@
+/* Calculate (post)dominators header file.
+ Copyright (C) 2014-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/>. */
+
+#if 0 // sdcpp ndef GCC_DOMINANCE_H
+#define GCC_DOMINANCE_H
+
+enum cdi_direction
+{
+ CDI_DOMINATORS = 1,
+ CDI_POST_DOMINATORS = 2
+};
+
+/* State of dominance information. */
+
+enum dom_state
+{
+ DOM_NONE, /* Not computed at all. */
+ DOM_NO_FAST_QUERY, /* The data is OK, but the fast query data are not usable. */
+ DOM_OK /* Everything is ok. */
+};
+
+extern void calculate_dominance_info (enum cdi_direction);
+extern void calculate_dominance_info_for_region (enum cdi_direction,
+ vec<basic_block>);
+extern void free_dominance_info (function *, enum cdi_direction);
+extern void free_dominance_info (enum cdi_direction);
+extern void free_dominance_info_for_region (function *,
+ enum cdi_direction,
+ vec<basic_block>);
+extern basic_block get_immediate_dominator (enum cdi_direction, basic_block);
+extern void set_immediate_dominator (enum cdi_direction, basic_block,
+ basic_block);
+extern auto_vec<basic_block> get_dominated_by (enum cdi_direction, basic_block);
+extern auto_vec<basic_block> get_dominated_by_region (enum cdi_direction,
+ basic_block *,
+ unsigned);
+extern auto_vec<basic_block> get_dominated_to_depth (enum cdi_direction,
+ basic_block, int);
+extern auto_vec<basic_block> get_all_dominated_blocks (enum cdi_direction,
+ basic_block);
+extern void redirect_immediate_dominators (enum cdi_direction, basic_block,
+ basic_block);
+extern basic_block nearest_common_dominator (enum cdi_direction,
+ basic_block, basic_block);
+extern basic_block nearest_common_dominator_for_set (enum cdi_direction,
+ bitmap);
+extern bool dominated_by_p (enum cdi_direction, const_basic_block,
+ const_basic_block);
+unsigned bb_dom_dfs_in (enum cdi_direction, basic_block);
+unsigned bb_dom_dfs_out (enum cdi_direction, basic_block);
+extern void verify_dominators (enum cdi_direction);
+
+/* Verify invariants of computed dominance information, if internal consistency
+ checks are enabled. */
+
+static inline void
+checking_verify_dominators (cdi_direction dir)
+{
+ if (flag_checking)
+ verify_dominators (dir);
+}
+
+basic_block recompute_dominator (enum cdi_direction, basic_block);
+extern void iterate_fix_dominators (enum cdi_direction,
+ vec<basic_block> &, bool);
+extern void add_to_dominance_info (enum cdi_direction, basic_block);
+extern void delete_from_dominance_info (enum cdi_direction, basic_block);
+extern basic_block first_dom_son (enum cdi_direction, basic_block);
+extern basic_block next_dom_son (enum cdi_direction, basic_block);
+extern enum dom_state dom_info_state (function *, enum cdi_direction);
+extern enum dom_state dom_info_state (enum cdi_direction);
+extern void set_dom_info_availability (enum cdi_direction, enum dom_state);
+extern bool dom_info_available_p (function *, enum cdi_direction);
+extern bool dom_info_available_p (enum cdi_direction);
+
+
+
+#endif /* GCC_DOMINANCE_H */
diff --git a/support/cpp/gcc/double-int.h b/support/cpp/gcc/double-int.h
new file mode 100644
index 000000000..b5bc96818
--- /dev/null
+++ b/support/cpp/gcc/double-int.h
@@ -0,0 +1,472 @@
+/* Operations with long integers.
+ Copyright (C) 2006-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 DOUBLE_INT_H
+#define DOUBLE_INT_H
+
+/* A large integer is currently represented as a pair of HOST_WIDE_INTs.
+ It therefore represents a number with precision of
+ 2 * HOST_BITS_PER_WIDE_INT bits (it is however possible that the
+ internal representation will change, if numbers with greater precision
+ are needed, so the users should not rely on it). The representation does
+ not contain any information about signedness of the represented value, so
+ it can be used to represent both signed and unsigned numbers. For
+ operations where the results depend on signedness (division, comparisons),
+ it must be specified separately. For each such operation, there are three
+ versions of the function -- double_int_op, that takes an extra UNS argument
+ giving the signedness of the values, and double_int_sop and double_int_uop
+ that stand for its specializations for signed and unsigned values.
+
+ You may also represent with numbers in smaller precision using double_int.
+ You however need to use double_int_ext (that fills in the bits of the
+ number over the prescribed precision with zeros or with the sign bit) before
+ operations that do not perform arithmetics modulo 2^precision (comparisons,
+ division), and possibly before storing the results, if you want to keep
+ them in some canonical form). In general, the signedness of double_int_ext
+ should match the signedness of the operation.
+
+ ??? The components of double_int differ in signedness mostly for
+ historical reasons (they replace an older structure used to represent
+ numbers with precision higher than HOST_WIDE_INT). It might be less
+ confusing to have them both signed or both unsigned. */
+
+struct double_int
+{
+ /* Normally, we would define constructors to create instances.
+ Two things prevent us from doing so.
+ First, defining a constructor makes the class non-POD in C++03,
+ and we certainly want double_int to be a POD.
+ Second, the GCC conding conventions prefer explicit conversion,
+ and explicit conversion operators are not available until C++11. */
+
+ static double_int from_uhwi (unsigned HOST_WIDE_INT cst);
+ static double_int from_shwi (HOST_WIDE_INT cst);
+ static double_int from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low);
+
+ /* Construct from a fuffer of length LEN. BUFFER will be read according
+ to byte endianness and word endianness. */
+ static double_int from_buffer (const unsigned char *buffer, int len);
+
+ /* No copy assignment operator or destructor to keep the type a POD. */
+
+ /* There are some special value-creation static member functions. */
+
+ static double_int mask (unsigned prec);
+ static double_int max_value (unsigned int prec, bool uns);
+ static double_int min_value (unsigned int prec, bool uns);
+
+ /* The following functions are mutating operations. */
+
+ double_int &operator ++ (); // prefix
+ double_int &operator -- (); // prefix
+ double_int &operator *= (double_int);
+ double_int &operator += (double_int);
+ double_int &operator -= (double_int);
+ double_int &operator &= (double_int);
+ double_int &operator ^= (double_int);
+ double_int &operator |= (double_int);
+
+ /* The following functions are non-mutating operations. */
+
+ /* Conversion functions. */
+
+ HOST_WIDE_INT to_shwi () const;
+ unsigned HOST_WIDE_INT to_uhwi () const;
+
+ /* Conversion query functions. */
+
+ bool fits_uhwi () const;
+ bool fits_shwi () const;
+ bool fits_hwi (bool uns) const;
+
+ /* Attribute query functions. */
+
+ int trailing_zeros () const;
+ int popcount () const;
+
+ /* Arithmetic query operations. */
+
+ bool multiple_of (double_int, bool, double_int *) const;
+
+ /* Arithmetic operation functions. */
+
+ /* The following operations perform arithmetics modulo 2^precision, so you
+ do not need to call .ext between them, even if you are representing
+ numbers with precision less than HOST_BITS_PER_DOUBLE_INT bits. */
+
+ double_int set_bit (unsigned) const;
+ double_int mul_with_sign (double_int, bool unsigned_p, bool *overflow) const;
+ double_int wide_mul_with_sign (double_int, bool unsigned_p,
+ double_int *higher, bool *overflow) const;
+ double_int add_with_sign (double_int, bool unsigned_p, bool *overflow) const;
+ double_int sub_with_overflow (double_int, bool *overflow) const;
+ double_int neg_with_overflow (bool *overflow) const;
+
+ double_int operator * (double_int) const;
+ double_int operator + (double_int) const;
+ double_int operator - (double_int) const;
+ double_int operator - () const;
+ double_int operator ~ () const;
+ double_int operator & (double_int) const;
+ double_int operator | (double_int) const;
+ double_int operator ^ (double_int) const;
+ double_int and_not (double_int) const;
+
+ double_int lshift (HOST_WIDE_INT count) const;
+ double_int lshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const;
+ double_int rshift (HOST_WIDE_INT count) const;
+ double_int rshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const;
+ double_int alshift (HOST_WIDE_INT count, unsigned int prec) const;
+ double_int arshift (HOST_WIDE_INT count, unsigned int prec) const;
+ double_int llshift (HOST_WIDE_INT count, unsigned int prec) const;
+ double_int lrshift (HOST_WIDE_INT count, unsigned int prec) const;
+ double_int lrotate (HOST_WIDE_INT count, unsigned int prec) const;
+ double_int rrotate (HOST_WIDE_INT count, unsigned int prec) const;
+
+ /* You must ensure that double_int::ext is called on the operands
+ of the following operations, if the precision of the numbers
+ is less than HOST_BITS_PER_DOUBLE_INT bits. */
+
+ double_int div (double_int, bool, unsigned) const;
+ double_int sdiv (double_int, unsigned) const;
+ double_int udiv (double_int, unsigned) const;
+ double_int mod (double_int, bool, unsigned) const;
+ double_int smod (double_int, unsigned) const;
+ double_int umod (double_int, unsigned) const;
+ double_int divmod_with_overflow (double_int, bool, unsigned,
+ double_int *, bool *) const;
+ double_int divmod (double_int, bool, unsigned, double_int *) const;
+ double_int sdivmod (double_int, unsigned, double_int *) const;
+ double_int udivmod (double_int, unsigned, double_int *) const;
+
+ /* Precision control functions. */
+
+ double_int ext (unsigned prec, bool uns) const;
+ double_int zext (unsigned prec) const;
+ double_int sext (unsigned prec) const;
+
+ /* Comparative functions. */
+
+ bool is_zero () const;
+ bool is_one () const;
+ bool is_minus_one () const;
+ bool is_negative () const;
+
+ int cmp (double_int b, bool uns) const;
+ int ucmp (double_int b) const;
+ int scmp (double_int b) const;
+
+ bool ult (double_int b) const;
+ bool ule (double_int b) const;
+ bool ugt (double_int b) const;
+ bool slt (double_int b) const;
+ bool sle (double_int b) const;
+ bool sgt (double_int b) const;
+
+ double_int max (double_int b, bool uns);
+ double_int smax (double_int b);
+ double_int umax (double_int b);
+
+ double_int min (double_int b, bool uns);
+ double_int smin (double_int b);
+ double_int umin (double_int b);
+
+ bool operator == (double_int cst2) const;
+ bool operator != (double_int cst2) const;
+
+ /* Please migrate away from using these member variables publicly. */
+
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+
+};
+
+#define HOST_BITS_PER_DOUBLE_INT (2 * HOST_BITS_PER_WIDE_INT)
+
+/* Constructors and conversions. */
+
+/* Constructs double_int from integer CST. The bits over the precision of
+ HOST_WIDE_INT are filled with the sign bit. */
+
+inline double_int
+double_int::from_shwi (HOST_WIDE_INT cst)
+{
+ double_int r;
+ r.low = (unsigned HOST_WIDE_INT) cst;
+ r.high = cst < 0 ? -1 : 0;
+ return r;
+}
+
+/* Some useful constants. */
+/* FIXME(crowl): Maybe remove after converting callers?
+ The problem is that a named constant would not be as optimizable,
+ while the functional syntax is more verbose. */
+
+#define double_int_minus_one (double_int::from_shwi (-1))
+#define double_int_zero (double_int::from_shwi (0))
+#define double_int_one (double_int::from_shwi (1))
+#define double_int_two (double_int::from_shwi (2))
+#define double_int_ten (double_int::from_shwi (10))
+
+/* Constructs double_int from unsigned integer CST. The bits over the
+ precision of HOST_WIDE_INT are filled with zeros. */
+
+inline double_int
+double_int::from_uhwi (unsigned HOST_WIDE_INT cst)
+{
+ double_int r;
+ r.low = cst;
+ r.high = 0;
+ return r;
+}
+
+inline double_int
+double_int::from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low)
+{
+ double_int r;
+ r.low = low;
+ r.high = high;
+ return r;
+}
+
+inline double_int &
+double_int::operator ++ ()
+{
+ *this += double_int_one;
+ return *this;
+}
+
+inline double_int &
+double_int::operator -- ()
+{
+ *this -= double_int_one;
+ return *this;
+}
+
+inline double_int &
+double_int::operator &= (double_int b)
+{
+ *this = *this & b;
+ return *this;
+}
+
+inline double_int &
+double_int::operator ^= (double_int b)
+{
+ *this = *this ^ b;
+ return *this;
+}
+
+inline double_int &
+double_int::operator |= (double_int b)
+{
+ *this = *this | b;
+ return *this;
+}
+
+/* Returns value of CST as a signed number. CST must satisfy
+ double_int::fits_signed. */
+
+inline HOST_WIDE_INT
+double_int::to_shwi () const
+{
+ return (HOST_WIDE_INT) low;
+}
+
+/* Returns value of CST as an unsigned number. CST must satisfy
+ double_int::fits_unsigned. */
+
+inline unsigned HOST_WIDE_INT
+double_int::to_uhwi () const
+{
+ return low;
+}
+
+/* Returns true if CST fits in unsigned HOST_WIDE_INT. */
+
+inline bool
+double_int::fits_uhwi () const
+{
+ return high == 0;
+}
+
+/* Logical operations. */
+
+/* Returns ~A. */
+
+inline double_int
+double_int::operator ~ () const
+{
+ double_int result;
+ result.low = ~low;
+ result.high = ~high;
+ return result;
+}
+
+/* Returns A | B. */
+
+inline double_int
+double_int::operator | (double_int b) const
+{
+ double_int result;
+ result.low = low | b.low;
+ result.high = high | b.high;
+ return result;
+}
+
+/* Returns A & B. */
+
+inline double_int
+double_int::operator & (double_int b) const
+{
+ double_int result;
+ result.low = low & b.low;
+ result.high = high & b.high;
+ return result;
+}
+
+/* Returns A & ~B. */
+
+inline double_int
+double_int::and_not (double_int b) const
+{
+ double_int result;
+ result.low = low & ~b.low;
+ result.high = high & ~b.high;
+ return result;
+}
+
+/* Returns A ^ B. */
+
+inline double_int
+double_int::operator ^ (double_int b) const
+{
+ double_int result;
+ result.low = low ^ b.low;
+ result.high = high ^ b.high;
+ return result;
+}
+
+void dump_double_int (FILE *, double_int, bool);
+
+#define ALL_ONES HOST_WIDE_INT_M1U
+
+/* The operands of the following comparison functions must be processed
+ with double_int_ext, if their precision is less than
+ HOST_BITS_PER_DOUBLE_INT bits. */
+
+/* Returns true if CST is zero. */
+
+inline bool
+double_int::is_zero () const
+{
+ return low == 0 && high == 0;
+}
+
+/* Returns true if CST is one. */
+
+inline bool
+double_int::is_one () const
+{
+ return low == 1 && high == 0;
+}
+
+/* Returns true if CST is minus one. */
+
+inline bool
+double_int::is_minus_one () const
+{
+ return low == ALL_ONES && high == -1;
+}
+
+/* Returns true if CST is negative. */
+
+inline bool
+double_int::is_negative () const
+{
+ return high < 0;
+}
+
+/* Returns true if CST1 == CST2. */
+
+inline bool
+double_int::operator == (double_int cst2) const
+{
+ return low == cst2.low && high == cst2.high;
+}
+
+/* Returns true if CST1 != CST2. */
+
+inline bool
+double_int::operator != (double_int cst2) const
+{
+ return low != cst2.low || high != cst2.high;
+}
+
+/* Return number of set bits of CST. */
+
+inline int
+double_int::popcount () const
+{
+ return popcount_hwi (high) + popcount_hwi (low);
+}
+
+
+#ifndef GENERATOR_FILE
+/* Conversion to and from GMP integer representations. */
+
+void mpz_set_double_int (mpz_t, double_int, bool);
+double_int mpz_get_double_int (const_tree, mpz_t, bool);
+#endif
+
+#if 0
+namespace wi
+{
+ template <>
+ struct int_traits <double_int>
+ {
+ static const enum precision_type precision_type = CONST_PRECISION;
+ static const bool host_dependent_precision = true;
+ static const unsigned int precision = HOST_BITS_PER_DOUBLE_INT;
+ static unsigned int get_precision (const double_int &);
+ static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
+ const double_int &);
+ };
+}
+
+inline unsigned int
+wi::int_traits <double_int>::get_precision (const double_int &)
+{
+ return precision;
+}
+
+inline wi::storage_ref
+wi::int_traits <double_int>::decompose (HOST_WIDE_INT *scratch, unsigned int p,
+ const double_int &x)
+{
+ gcc_checking_assert (precision == p);
+ scratch[0] = x.low;
+ if ((x.high == 0 && scratch[0] >= 0) || (x.high == -1 && scratch[0] < 0))
+ return wi::storage_ref (scratch, 1, precision);
+ scratch[1] = x.high;
+ return wi::storage_ref (scratch, 2, precision);
+}
+#endif
+
+#endif /* DOUBLE_INT_H */
diff --git a/support/cpp/gcc/dummies.cc b/support/cpp/gcc/dummies.cc
new file mode 100644
index 000000000..dc6f8cae2
--- /dev/null
+++ b/support/cpp/gcc/dummies.cc
@@ -0,0 +1,31 @@
+// dummies for unused functions in cpp and cc1
+
+#ifdef CC1_DUMMIES
+#define SDCPP_DUMMY_FCT() fprintf(stderr, "unreachable dummy in cc1%s\n", __func__); gcc_assert(false)
+#define SDCPP_DUMMY_FCT_() // fprintf(stderr, "dummy in cc1%s\n", __func__)
+#else
+#define SDCPP_DUMMY_FCT() fprintf(stderr, "unreachable dummy %s\n", __func__); gcc_assert(false)
+#define SDCPP_DUMMY_FCT_() // fprintf(stderr, "dummy %s\n", __func__)
+#endif
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+
+// #include "errors.h" // BUG?
+
+// #include "tree-core.h"
+// #include "langhooks.h"
+// #include "langhooks-def.h"
+
+#include <cassert>
+
+#include "opt-suggestions.h"
+option_proposer::~option_proposer ()
+{ SDCPP_DUMMY_FCT_();
+}
+const char *host_detect_local_cpu (int, const char **)
+{
+ return NULL;
+}
+
diff --git a/support/cpp/gcc/dumpfile.h b/support/cpp/gcc/dumpfile.h
new file mode 100644
index 000000000..00bf0eaac
--- /dev/null
+++ b/support/cpp/gcc/dumpfile.h
@@ -0,0 +1,776 @@
+/* Definitions for the shared dumpfile.
+ Copyright (C) 2004-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_DUMPFILE_H
+#define GCC_DUMPFILE_H 1
+
+#include "profile-count.h"
+
+/* An attribute for annotating formatting printing functions that use
+ the dumpfile/optinfo formatting codes. These are the pretty_printer
+ format codes (see pretty-print.cc), with additional codes for middle-end
+ specific entities (see dumpfile.cc). */
+
+#if GCC_VERSION >= 9000
+#define ATTRIBUTE_GCC_DUMP_PRINTF(m, n) \
+ __attribute__ ((__format__ (__gcc_dump_printf__, m ,n))) \
+ ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_DUMP_PRINTF(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+
+/* Different tree dump places. When you add new tree dump places,
+ extend the DUMP_FILES array in dumpfile.cc. */
+enum tree_dump_index
+{
+ TDI_none, /* No dump */
+ TDI_cgraph, /* dump function call graph. */
+ TDI_inheritance, /* dump type inheritance graph. */
+ TDI_clones, /* dump IPA cloning decisions. */
+ TDI_original, /* dump each function before optimizing it */
+ TDI_gimple, /* dump each function after gimplifying it */
+ TDI_nested, /* dump each function after unnesting it */
+ TDI_lto_stream_out, /* dump information about lto streaming */
+ TDI_profile_report, /* dump information about profile quality */
+
+ TDI_lang_all, /* enable all the language dumps. */
+ TDI_tree_all, /* enable all the GENERIC/GIMPLE dumps. */
+ TDI_rtl_all, /* enable all the RTL dumps. */
+ TDI_ipa_all, /* enable all the IPA dumps. */
+
+ TDI_end
+};
+
+/* Enum used to distinguish dump files to types. */
+
+enum dump_kind
+{
+ DK_none,
+ DK_lang,
+ DK_tree,
+ DK_rtl,
+ DK_ipa
+};
+
+/* Bit masks to control dumping. Not all values are applicable to all
+ dumps. Add new ones at the end. When you define new values, extend
+ the DUMP_OPTIONS array in dumpfile.cc. The TDF_* flags coexist with
+ MSG_* flags (for -fopt-info) and the bit values must be chosen to
+ allow that. */
+enum dump_flag : uint32_t
+{
+ /* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK. */
+ TDF_NONE = 0,
+
+ /* Dump node addresses. */
+ TDF_ADDRESS = (1 << 0),
+
+ /* Don't go wild following links. */
+ TDF_SLIM = (1 << 1),
+
+ /* Don't unparse the function. */
+ TDF_RAW = (1 << 2),
+
+ /* Show more detailed info about each pass. */
+ TDF_DETAILS = (1 << 3),
+
+ /* Dump various statistics about each pass. */
+ TDF_STATS = (1 << 4),
+
+ /* Display basic block boundaries. */
+ TDF_BLOCKS = (1 << 5),
+
+ /* Display virtual operands. */
+ TDF_VOPS = (1 << 6),
+
+ /* Display statement line numbers. */
+ TDF_LINENO = (1 << 7),
+
+ /* Display decl UIDs. */
+ TDF_UID = (1 << 8),
+
+ /* Address of stmt. */
+ TDF_STMTADDR = (1 << 9),
+
+ /* A graph dump is being emitted. */
+ TDF_GRAPH = (1 << 10),
+
+ /* Display memory symbols in expr.
+ Implies TDF_VOPS. */
+ TDF_MEMSYMS = (1 << 11),
+
+ /* A flag to only print the RHS of a gimple stmt. */
+ TDF_RHS_ONLY = (1 << 12),
+
+ /* Display asm names of decls. */
+ TDF_ASMNAME = (1 << 13),
+
+ /* Display EH region number holding this gimple statement. */
+ TDF_EH = (1 << 14),
+
+ /* Omit UIDs from dumps. */
+ TDF_NOUID = (1 << 15),
+
+ /* Display alias information. */
+ TDF_ALIAS = (1 << 16),
+
+ /* Enumerate locals by uid. */
+ TDF_ENUMERATE_LOCALS = (1 << 17),
+
+ /* Dump cselib details. */
+ TDF_CSELIB = (1 << 18),
+
+ /* Dump SCEV details. */
+ TDF_SCEV = (1 << 19),
+
+ /* Dump in GIMPLE FE syntax. */
+ TDF_GIMPLE = (1 << 20),
+
+ /* Dump folding details. */
+ TDF_FOLDING = (1 << 21),
+
+ /* MSG_* flags for expressing the kinds of message to
+ be emitted by -fopt-info. */
+
+ /* -fopt-info optimized sources. */
+ MSG_OPTIMIZED_LOCATIONS = (1 << 22),
+
+ /* Missed opportunities. */
+ MSG_MISSED_OPTIMIZATION = (1 << 23),
+
+ /* General optimization info. */
+ MSG_NOTE = (1 << 24),
+
+ /* Mask for selecting MSG_-kind flags. */
+ MSG_ALL_KINDS = (MSG_OPTIMIZED_LOCATIONS
+ | MSG_MISSED_OPTIMIZATION
+ | MSG_NOTE),
+
+ /* MSG_PRIORITY_* flags for expressing the priority levels of message
+ to be emitted by -fopt-info, and filtering on them.
+ By default, messages at the top-level dump scope are "user-facing",
+ whereas those that are in nested scopes are implicitly "internals".
+ This behavior can be overridden for a given dump message by explicitly
+ specifying one of the MSG_PRIORITY_* flags.
+
+ By default, dump files show both kinds of message, whereas -fopt-info
+ only shows "user-facing" messages, and requires the "-internals"
+ sub-option of -fopt-info to show the internal messages. */
+
+ /* Implicitly supplied for messages at the top-level dump scope. */
+ MSG_PRIORITY_USER_FACING = (1 << 25),
+
+ /* Implicitly supplied for messages within nested dump scopes. */
+ MSG_PRIORITY_INTERNALS = (1 << 26),
+
+ /* Supplied when an opt_problem generated in a nested scope is re-emitted
+ at the top-level. We want to default to showing these in -fopt-info
+ output, but to *not* show them in dump files, as the message would be
+ shown twice, messing up "scan-tree-dump-times" in DejaGnu tests. */
+ MSG_PRIORITY_REEMITTED = (1 << 27),
+
+ /* Mask for selecting MSG_PRIORITY_* flags. */
+ MSG_ALL_PRIORITIES = (MSG_PRIORITY_USER_FACING
+ | MSG_PRIORITY_INTERNALS
+ | MSG_PRIORITY_REEMITTED),
+
+ /* All -fdump- flags. */
+ TDF_ALL_VALUES = (1 << 28) - 1,
+
+ /* Dumping for -fcompare-debug. */
+ TDF_COMPARE_DEBUG = (1 << 28),
+
+ /* Dump a GIMPLE value which means wrapping certain things with _Literal. */
+ TDF_GIMPLE_VAL = (1 << 29),
+
+ /* For error. */
+ TDF_ERROR = ((uint32_t)1 << 30),
+};
+
+/* Dump flags type. */
+
+typedef enum dump_flag dump_flags_t;
+
+static inline dump_flags_t
+operator| (dump_flags_t lhs, dump_flags_t rhs)
+{
+ return (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
+}
+
+static inline dump_flags_t
+operator& (dump_flags_t lhs, dump_flags_t rhs)
+{
+ return (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ & (std::underlying_type<dump_flags_t>::type)rhs);
+}
+
+static inline dump_flags_t
+operator~ (dump_flags_t flags)
+{
+ return (dump_flags_t)~((std::underlying_type<dump_flags_t>::type)flags);
+}
+
+static inline dump_flags_t &
+operator|= (dump_flags_t &lhs, dump_flags_t rhs)
+{
+ lhs = (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
+ return lhs;
+}
+
+static inline dump_flags_t &
+operator&= (dump_flags_t &lhs, dump_flags_t rhs)
+{
+ lhs = (dump_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ & (std::underlying_type<dump_flags_t>::type)rhs);
+ return lhs;
+}
+
+/* Flags to control high-level -fopt-info dumps. Usually these flags
+ define a group of passes. An optimization pass can be part of
+ multiple groups. */
+
+enum optgroup_flag
+{
+ OPTGROUP_NONE = 0,
+
+ /* IPA optimization passes */
+ OPTGROUP_IPA = (1 << 1),
+
+ /* Loop optimization passes */
+ OPTGROUP_LOOP = (1 << 2),
+
+ /* Inlining passes */
+ OPTGROUP_INLINE = (1 << 3),
+
+ /* OMP (Offloading and Multi Processing) transformations */
+ OPTGROUP_OMP = (1 << 4),
+
+ /* Vectorization passes */
+ OPTGROUP_VEC = (1 << 5),
+
+ /* All other passes */
+ OPTGROUP_OTHER = (1 << 6),
+
+ OPTGROUP_ALL = (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE
+ | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER)
+};
+
+typedef enum optgroup_flag optgroup_flags_t;
+
+static inline optgroup_flags_t
+operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
+{
+ return (optgroup_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
+}
+
+static inline optgroup_flags_t &
+operator|= (optgroup_flags_t &lhs, optgroup_flags_t rhs)
+{
+ lhs = (optgroup_flags_t)((std::underlying_type<dump_flags_t>::type)lhs
+ | (std::underlying_type<dump_flags_t>::type)rhs);
+ return lhs;
+}
+
+/* Define a tree dump switch. */
+struct dump_file_info
+{
+ /* Suffix to give output file. */
+ const char *suffix;
+ /* Command line dump switch. */
+ const char *swtch;
+ /* Command line glob. */
+ const char *glob;
+ /* Filename for the pass-specific stream. */
+ const char *pfilename;
+ /* Filename for the -fopt-info stream. */
+ const char *alt_filename;
+ /* Pass-specific dump stream. */
+ FILE *pstream;
+ /* -fopt-info stream. */
+ FILE *alt_stream;
+ /* Dump kind. */
+ dump_kind dkind;
+ /* Dump flags. */
+ dump_flags_t pflags;
+ /* A pass flags for -fopt-info. */
+ dump_flags_t alt_flags;
+ /* Flags for -fopt-info given by a user. */
+ optgroup_flags_t optgroup_flags;
+ /* State of pass-specific stream. */
+ int pstate;
+ /* State of the -fopt-info stream. */
+ int alt_state;
+ /* Dump file number. */
+ int num;
+ /* Fields "suffix", "swtch", "glob" can be const strings,
+ or can be dynamically allocated, needing free. */
+ bool owns_strings;
+ /* When a given dump file is being initialized, this flag is set to true
+ if the corresponding TDF_graph dump file has also been initialized. */
+ bool graph_dump_initialized;
+};
+
+/* A class for describing where in the user's source that a dump message
+ relates to, with various constructors for convenience.
+ In particular, this lets us associate dump messages
+ with hotness information (e.g. from PGO), allowing them to
+ be prioritized by code hotness. */
+
+class dump_user_location_t
+{
+ public:
+ /* Default constructor, analogous to UNKNOWN_LOCATION. */
+ dump_user_location_t () : m_count (), m_loc (UNKNOWN_LOCATION) {}
+
+ /* Construct from a gimple statement (using its location and hotness). */
+ dump_user_location_t (const gimple *stmt);
+
+ /* Construct from an RTL instruction (using its location and hotness). */
+ dump_user_location_t (const rtx_insn *insn);
+
+ /* Construct from a location_t. This one is deprecated (since it doesn't
+ capture hotness information); it thus needs to be spelled out. */
+ static dump_user_location_t
+ from_location_t (location_t loc)
+ {
+ return dump_user_location_t (profile_count (), loc);
+ }
+
+ /* Construct from a function declaration. This one requires spelling out
+ to avoid accidentally constructing from other kinds of tree. */
+ static dump_user_location_t
+ from_function_decl (tree fndecl);
+
+ profile_count get_count () const { return m_count; }
+ location_t get_location_t () const { return m_loc; }
+
+ private:
+ /* Private ctor from count and location, for use by from_location_t. */
+ dump_user_location_t (profile_count count, location_t loc)
+ : m_count (count), m_loc (loc)
+ {}
+
+ profile_count m_count;
+ location_t m_loc;
+};
+
+/* A class for identifying where in the compiler's own source
+ (or a plugin) that a dump message is being emitted from. */
+
+class dump_impl_location_t
+{
+public:
+ dump_impl_location_t (
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+ const char *file = __builtin_FILE (),
+ int line = __builtin_LINE (),
+ const char *function = __builtin_FUNCTION ()
+#else
+ const char *file = __FILE__,
+ int line = __LINE__,
+ const char *function = NULL
+#endif
+ )
+ : m_file (file), m_line (line), m_function (function)
+ {}
+
+ const char *m_file;
+ int m_line;
+ const char *m_function;
+};
+
+/* A bundle of metadata for describing a dump message:
+ (a) the dump_flags
+ (b) the source location within the compiler/plugin.
+
+ The constructors use default parameters so that (b) gets sets up
+ automatically.
+
+ Hence you can pass in e.g. MSG_NOTE, and the dump call
+ will automatically record where in GCC's source code the
+ dump was emitted from. */
+
+class dump_metadata_t
+{
+ public:
+ dump_metadata_t (dump_flags_t dump_flags,
+ const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ : m_dump_flags (dump_flags),
+ m_impl_location (impl_location)
+ {
+ }
+
+ dump_flags_t get_dump_flags () const { return m_dump_flags; }
+
+ const dump_impl_location_t &
+ get_impl_location () const { return m_impl_location; }
+
+ private:
+ dump_flags_t m_dump_flags;
+ dump_impl_location_t m_impl_location;
+};
+
+/* A bundle of information for describing the location of a dump message:
+ (a) the source location and hotness within the user's code, together with
+ (b) the source location within the compiler/plugin.
+
+ The constructors use default parameters so that (b) gets sets up
+ automatically.
+
+ The upshot is that you can pass in e.g. a gimple * to dump_printf_loc,
+ and the dump call will automatically record where in GCC's source
+ code the dump was emitted from. */
+
+class dump_location_t
+{
+ public:
+ /* Default constructor, analogous to UNKNOWN_LOCATION. */
+ dump_location_t (const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ : m_user_location (dump_user_location_t ()),
+ m_impl_location (impl_location)
+ {
+ }
+
+ /* Construct from a gimple statement (using its location and hotness). */
+ dump_location_t (const gimple *stmt,
+ const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ : m_user_location (dump_user_location_t (stmt)),
+ m_impl_location (impl_location)
+ {
+ }
+
+ /* Construct from an RTL instruction (using its location and hotness). */
+ dump_location_t (const rtx_insn *insn,
+ const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ : m_user_location (dump_user_location_t (insn)),
+ m_impl_location (impl_location)
+ {
+ }
+
+ /* Construct from a dump_user_location_t. */
+ dump_location_t (const dump_user_location_t &user_location,
+ const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ : m_user_location (user_location),
+ m_impl_location (impl_location)
+ {
+ }
+
+ /* Construct from a location_t. This one is deprecated (since it doesn't
+ capture hotness information), and thus requires spelling out. */
+ static dump_location_t
+ from_location_t (location_t loc,
+ const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ {
+ return dump_location_t (dump_user_location_t::from_location_t (loc),
+ impl_location);
+ }
+
+ const dump_user_location_t &
+ get_user_location () const { return m_user_location; }
+
+ const dump_impl_location_t &
+ get_impl_location () const { return m_impl_location; }
+
+ location_t get_location_t () const
+ {
+ return m_user_location.get_location_t ();
+ }
+
+ profile_count get_count () const { return m_user_location.get_count (); }
+
+ private:
+ dump_user_location_t m_user_location;
+ dump_impl_location_t m_impl_location;
+};
+
+/* In dumpfile.cc */
+extern FILE *dump_begin (int, dump_flags_t *, int part=-1);
+extern void dump_end (int, FILE *);
+extern int opt_info_switch_p (const char *);
+extern const char *dump_flag_name (int);
+extern const kv_pair<optgroup_flags_t> optgroup_options[];
+extern dump_flags_t
+parse_dump_option (const char *, const char **);
+
+/* Global variables used to communicate with passes. */
+extern FILE *dump_file;
+extern dump_flags_t dump_flags;
+extern const char *dump_file_name;
+
+extern bool dumps_are_enabled;
+
+extern void set_dump_file (FILE *new_dump_file);
+
+/* Return true if any of the dumps is enabled, false otherwise. */
+static inline bool
+dump_enabled_p (void)
+{
+ return dumps_are_enabled;
+}
+
+/* The following API calls (which *don't* take a "FILE *")
+ write the output to zero or more locations.
+
+ Some destinations are written to immediately as dump_* calls
+ are made; for others, the output is consolidated into an "optinfo"
+ instance (with its own metadata), and only emitted once the optinfo
+ is complete.
+
+ The destinations are:
+
+ (a) the "immediate" destinations:
+ (a.1) the active dump_file, if any
+ (a.2) the -fopt-info destination, if any
+ (b) the "optinfo" destinations, if any:
+ (b.1) as optimization records
+
+ dump_* (MSG_*) --> dumpfile.cc --> items --> (a.1) dump_file
+ | `-> (a.2) alt_dump_file
+ |
+ `--> (b) optinfo
+ `---> optinfo destinations
+ (b.1) optimization records
+
+ For optinfos, the dump_*_loc mark the beginning of an optinfo
+ instance: all subsequent dump_* calls are consolidated into
+ that optinfo, until the next dump_*_loc call (or a change in
+ dump scope, or a call to dumpfile_ensure_any_optinfo_are_flushed).
+
+ A group of dump_* calls should be guarded by:
+
+ if (dump_enabled_p ())
+
+ to minimize the work done for the common case where dumps
+ are disabled. */
+
+extern void dump_printf (const dump_metadata_t &, const char *, ...)
+ ATTRIBUTE_GCC_DUMP_PRINTF (2, 3);
+
+extern void dump_printf_loc (const dump_metadata_t &, const dump_user_location_t &,
+ const char *, ...)
+ ATTRIBUTE_GCC_DUMP_PRINTF (3, 0);
+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 &,
+ const dump_user_location_t &,
+ dump_flags_t, tree);
+extern void dump_generic_expr (const dump_metadata_t &, dump_flags_t, tree);
+extern void dump_gimple_stmt_loc (const dump_metadata_t &,
+ const dump_user_location_t &,
+ dump_flags_t, gimple *, int);
+extern void dump_gimple_stmt (const dump_metadata_t &, dump_flags_t, gimple *, int);
+extern void dump_gimple_expr_loc (const dump_metadata_t &,
+ const dump_user_location_t &,
+ dump_flags_t, gimple *, int);
+extern void dump_gimple_expr (const dump_metadata_t &, dump_flags_t, gimple *, int);
+extern void dump_symtab_node (const dump_metadata_t &, symtab_node *);
+
+#if 0 // sdcpp
+template<unsigned int N, typename C>
+void dump_dec (const dump_metadata_t &, const poly_int<N, C> &);
+extern void dump_dec (dump_flags_t, const poly_wide_int &, signop);
+extern void dump_hex (dump_flags_t, const poly_wide_int &);
+#endif
+
+extern void dumpfile_ensure_any_optinfo_are_flushed ();
+
+/* Managing nested scopes, so that dumps can express the call chain
+ leading to a dump message. */
+
+extern unsigned int get_dump_scope_depth ();
+extern void dump_begin_scope (const char *name,
+ const dump_user_location_t &user_location,
+ const dump_impl_location_t &impl_location);
+extern void dump_end_scope ();
+
+/* Implementation detail of the AUTO_DUMP_SCOPE macro below.
+
+ A RAII-style class intended to make it easy to emit dump
+ information about entering and exiting a collection of nested
+ function calls. */
+
+class auto_dump_scope
+{
+ public:
+ auto_dump_scope (const char *name,
+ const dump_user_location_t &user_location,
+ const dump_impl_location_t &impl_location
+ = dump_impl_location_t ())
+ {
+ if (dump_enabled_p ())
+ dump_begin_scope (name, user_location, impl_location);
+ }
+ ~auto_dump_scope ()
+ {
+ if (dump_enabled_p ())
+ dump_end_scope ();
+ }
+};
+
+/* A macro for calling:
+ dump_begin_scope (NAME, USER_LOC);
+ via an RAII object, thus printing "=== MSG ===\n" to the dumpfile etc,
+ and then calling
+ dump_end_scope ();
+ once the object goes out of scope, thus capturing the nesting of
+ the scopes.
+
+ These scopes affect dump messages within them: dump messages at the
+ top level implicitly default to MSG_PRIORITY_USER_FACING, whereas those
+ in a nested scope implicitly default to MSG_PRIORITY_INTERNALS. */
+
+#define AUTO_DUMP_SCOPE(NAME, USER_LOC) \
+ auto_dump_scope scope (NAME, USER_LOC)
+
+extern void dump_function (int phase, tree fn);
+extern void print_combine_total_stats (void);
+extern bool enable_rtl_dump_file (void);
+
+/* In tree-dump.cc */
+extern void dump_node (const_tree, dump_flags_t, FILE *);
+
+/* In combine.cc */
+extern void dump_combine_total_stats (FILE *);
+/* In cfghooks.cc */
+extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
+
+class opt_pass;
+
+namespace gcc {
+
+/* A class for managing all of the various dump files used by the
+ optimization passes. */
+
+class dump_manager
+{
+public:
+
+ dump_manager ();
+ ~dump_manager ();
+
+ /* Register a dumpfile.
+
+ TAKE_OWNERSHIP determines whether callee takes ownership of strings
+ SUFFIX, SWTCH, and GLOB. */
+ unsigned int
+ dump_register (const char *suffix, const char *swtch, const char *glob,
+ dump_kind dkind, optgroup_flags_t optgroup_flags,
+ bool take_ownership);
+
+ /* Allow languages and middle-end to register their dumps before the
+ optimization passes. */
+ void
+ register_dumps ();
+
+ /* Return the dump_file_info for the given phase. */
+ struct dump_file_info *
+ get_dump_file_info (int phase) const;
+
+ struct dump_file_info *
+ get_dump_file_info_by_switch (const char *swtch) const;
+
+ /* Return the name of the dump file for the given phase.
+ If the dump is not enabled, returns NULL. */
+ char *
+ get_dump_file_name (int phase, int part = -1) const;
+
+ char *
+ get_dump_file_name (struct dump_file_info *dfi, int part = -1) const;
+
+ void
+ dump_switch_p (const char *arg);
+
+ /* Start a dump for PHASE. Store user-supplied dump flags in
+ *FLAG_PTR. Return the number of streams opened. Set globals
+ DUMP_FILE, and ALT_DUMP_FILE to point to the opened streams, and
+ set dump_flags appropriately for both pass dump stream and
+ -fopt-info stream. */
+ int
+ dump_start (int phase, dump_flags_t *flag_ptr);
+
+ /* Finish a tree dump for PHASE and close associated dump streams. Also
+ reset the globals DUMP_FILE, ALT_DUMP_FILE, and DUMP_FLAGS. */
+ void
+ dump_finish (int phase);
+
+ FILE *
+ dump_begin (int phase, dump_flags_t *flag_ptr, int part);
+
+ /* Returns nonzero if tree dump PHASE has been initialized. */
+ int
+ dump_initialized_p (int phase) const;
+
+ /* Returns the switch name of PHASE. */
+ const char *
+ dump_flag_name (int phase) const;
+
+ void register_pass (opt_pass *pass);
+
+private:
+
+ int
+ dump_phase_enabled_p (int phase) const;
+
+ int
+ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob);
+
+ int
+ dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename);
+
+ int
+ opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
+ const char *filename);
+
+ bool update_dfi_for_opt_info (dump_file_info *dfi) const;
+
+private:
+
+ /* Dynamically registered dump files and switches. */
+ int m_next_dump;
+ struct dump_file_info *m_extra_dump_files;
+ size_t m_extra_dump_files_in_use;
+ size_t m_extra_dump_files_alloced;
+
+ /* Stored values from -fopt-info, for handling passes created after
+ option-parsing (by backends and by plugins). */
+ optgroup_flags_t m_optgroup_flags;
+ dump_flags_t m_optinfo_flags;
+ char *m_optinfo_filename;
+
+ /* Grant access to dump_enable_all. */
+ friend bool ::enable_rtl_dump_file (void);
+
+ /* Grant access to opt_info_enable_passes. */
+ friend int ::opt_info_switch_p (const char *arg);
+
+}; // class dump_manager
+
+} // namespace gcc
+
+#endif /* GCC_DUMPFILE_H */
diff --git a/support/cpp/gcc/dwarf2out.h b/support/cpp/gcc/dwarf2out.h
new file mode 100644
index 000000000..98bd21a36
--- /dev/null
+++ b/support/cpp/gcc/dwarf2out.h
@@ -0,0 +1,470 @@
+/* dwarf2out.h - Various declarations for functions found in dwarf2out.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/>. */
+
+#if 0 // sdcpp ndef GCC_DWARF2OUT_H
+#define GCC_DWARF2OUT_H 1
+
+#include "dwarf2.h" /* ??? Remove this once only used by dwarf2foo.c. */
+
+typedef struct die_struct *dw_die_ref;
+typedef const struct die_struct *const_dw_die_ref;
+
+typedef struct dw_val_node *dw_val_ref;
+typedef struct dw_cfi_node *dw_cfi_ref;
+typedef struct dw_loc_descr_node *dw_loc_descr_ref;
+typedef struct dw_loc_list_struct *dw_loc_list_ref;
+typedef struct dw_discr_list_node *dw_discr_list_ref;
+typedef wide_int *wide_int_ptr;
+
+
+/* Call frames are described using a sequence of Call Frame
+ Information instructions. The register number, offset
+ and address fields are provided as possible operands;
+ their use is selected by the opcode field. */
+
+enum dw_cfi_oprnd_type {
+ dw_cfi_oprnd_unused,
+ dw_cfi_oprnd_reg_num,
+ dw_cfi_oprnd_offset,
+ dw_cfi_oprnd_addr,
+ dw_cfi_oprnd_loc,
+ dw_cfi_oprnd_cfa_loc
+};
+
+typedef union GTY(()) {
+ unsigned int GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num;
+ HOST_WIDE_INT GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset;
+ const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr;
+ struct dw_loc_descr_node * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc;
+ struct dw_cfa_location * GTY ((tag ("dw_cfi_oprnd_cfa_loc")))
+ dw_cfi_cfa_loc;
+} dw_cfi_oprnd;
+
+struct GTY(()) dw_cfi_node {
+ enum dwarf_call_frame_info dw_cfi_opc;
+ dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)")))
+ dw_cfi_oprnd1;
+ dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)")))
+ dw_cfi_oprnd2;
+};
+
+
+typedef vec<dw_cfi_ref, va_gc> *cfi_vec;
+
+typedef struct dw_fde_node *dw_fde_ref;
+
+/* All call frame descriptions (FDE's) in the GCC generated DWARF
+ refer to a single Common Information Entry (CIE), defined at
+ the beginning of the .debug_frame section. This use of a single
+ CIE obviates the need to keep track of multiple CIE's
+ in the DWARF generation routines below. */
+
+struct GTY(()) dw_fde_node {
+ tree decl;
+ const char *dw_fde_begin;
+ const char *dw_fde_current_label;
+ const char *dw_fde_end;
+ const char *dw_fde_vms_end_prologue;
+ const char *dw_fde_vms_begin_epilogue;
+ const char *dw_fde_second_begin;
+ const char *dw_fde_second_end;
+ cfi_vec dw_fde_cfi;
+ int dw_fde_switch_cfi_index; /* Last CFI before switching sections. */
+ HOST_WIDE_INT stack_realignment;
+
+ unsigned funcdef_number;
+ unsigned fde_index;
+
+ /* Dynamic realign argument pointer register. */
+ unsigned int drap_reg;
+ /* Virtual dynamic realign argument pointer register. */
+ unsigned int vdrap_reg;
+ /* These 3 flags are copied from rtl_data in function.h. */
+ unsigned all_throwers_are_sibcalls : 1;
+ unsigned uses_eh_lsda : 1;
+ unsigned nothrow : 1;
+ /* Whether we did stack realign in this call frame. */
+ unsigned stack_realign : 1;
+ /* Whether dynamic realign argument pointer register has been saved. */
+ unsigned drap_reg_saved: 1;
+ /* True iff dw_fde_begin label is in text_section or cold_text_section. */
+ unsigned in_std_section : 1;
+ /* True iff dw_fde_second_begin label is in text_section or
+ cold_text_section. */
+ unsigned second_in_std_section : 1;
+ /* True if Rule 18 described in dwarf2cfi.cc is in action, i.e. for dynamic
+ stack realignment in between pushing of hard frame pointer to stack
+ and setting hard frame pointer to stack pointer. The register save for
+ hard frame pointer register should be emitted only on the latter
+ instruction. */
+ unsigned rule18 : 1;
+ /* True if this function is to be ignored by debugger. */
+ unsigned ignored_debug : 1;
+};
+
+
+/* This represents a register, in DWARF_FRAME_REGNUM space, for use in CFA
+ definitions and expressions.
+ Most architectures only need a single register number, but some (amdgcn)
+ have pointers that span multiple registers. DWARF permits arbitrary
+ register sets but existing use-cases only require contiguous register
+ sets, as represented here. */
+struct GTY(()) cfa_reg {
+ unsigned int reg;
+ unsigned short span;
+ unsigned short span_width; /* A.K.A. register mode size. */
+
+ cfa_reg& set_by_dwreg (unsigned int r)
+ {
+ reg = r;
+ span = 1;
+ span_width = 0; /* Unknown size (permitted when span == 1). */
+ return *this;
+ }
+
+ bool operator== (const cfa_reg &other) const
+ {
+ return (reg == other.reg && span == other.span
+ && (span_width == other.span_width
+ || (span == 1
+ && (span_width == 0 || other.span_width == 0))));
+ }
+
+ bool operator!= (const cfa_reg &other) const
+ {
+ return !(*this == other);
+ }
+};
+
+/* This is how we define the location of the CFA. We use to handle it
+ as REG + OFFSET all the time, but now it can be more complex.
+ It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET.
+ Instead of passing around REG and OFFSET, we pass a copy
+ of this structure. */
+struct GTY(()) dw_cfa_location {
+ poly_int64_pod offset;
+ poly_int64_pod base_offset;
+ /* REG is in DWARF_FRAME_REGNUM space, *not* normal REGNO space. */
+ struct cfa_reg reg;
+ BOOL_BITFIELD indirect : 1; /* 1 if CFA is accessed via a dereference. */
+ BOOL_BITFIELD in_use : 1; /* 1 if a saved cfa is stored here. */
+};
+
+
+/* Each DIE may have a series of attribute/value pairs. Values
+ can take on several forms. The forms that are used in this
+ implementation are listed below. */
+
+enum dw_val_class
+{
+ dw_val_class_none,
+ dw_val_class_addr,
+ dw_val_class_offset,
+ dw_val_class_loc,
+ dw_val_class_loc_list,
+ dw_val_class_range_list,
+ dw_val_class_const,
+ dw_val_class_unsigned_const,
+ dw_val_class_const_double,
+ dw_val_class_wide_int,
+ dw_val_class_vec,
+ dw_val_class_flag,
+ dw_val_class_die_ref,
+ dw_val_class_fde_ref,
+ dw_val_class_lbl_id,
+ dw_val_class_lineptr,
+ dw_val_class_str,
+ dw_val_class_macptr,
+ dw_val_class_loclistsptr,
+ dw_val_class_file,
+ dw_val_class_data8,
+ dw_val_class_decl_ref,
+ dw_val_class_vms_delta,
+ dw_val_class_high_pc,
+ dw_val_class_discr_value,
+ dw_val_class_discr_list,
+ dw_val_class_const_implicit,
+ dw_val_class_unsigned_const_implicit,
+ dw_val_class_file_implicit,
+ dw_val_class_view_list,
+ dw_val_class_symview
+};
+
+/* Describe a floating point constant value, or a vector constant value. */
+
+struct GTY(()) dw_vec_const {
+ void * GTY((atomic)) array;
+ unsigned length;
+ unsigned elt_size;
+};
+
+/* Describe a single value that a discriminant can match.
+
+ Discriminants (in the "record variant part" meaning) are scalars.
+ dw_discr_list_ref and dw_discr_value are a mean to describe a set of
+ discriminant values that are matched by a particular variant.
+
+ Discriminants can be signed or unsigned scalars, and can be discriminants
+ values. Both have to be consistent, though. */
+
+struct GTY(()) dw_discr_value {
+ int pos; /* Whether the discriminant value is positive (unsigned). */
+ union
+ {
+ HOST_WIDE_INT GTY ((tag ("0"))) sval;
+ unsigned HOST_WIDE_INT GTY ((tag ("1"))) uval;
+ }
+ GTY ((desc ("%1.pos"))) v;
+};
+
+struct addr_table_entry;
+
+/* The dw_val_node describes an attribute's value, as it is
+ represented internally. */
+
+struct GTY(()) dw_val_node {
+ enum dw_val_class val_class;
+ struct addr_table_entry * GTY(()) val_entry;
+ union dw_val_struct_union
+ {
+ rtx GTY ((tag ("dw_val_class_addr"))) val_addr;
+ unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset;
+ dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
+ dw_die_ref GTY ((tag ("dw_val_class_view_list"))) val_view_list;
+ dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
+ HOST_WIDE_INT GTY ((default)) val_int;
+ unsigned HOST_WIDE_INT
+ GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+ double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
+ wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
+ dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
+ struct dw_val_die_union
+ {
+ dw_die_ref die;
+ int external;
+ } GTY ((tag ("dw_val_class_die_ref"))) val_die_ref;
+ unsigned GTY ((tag ("dw_val_class_fde_ref"))) val_fde_index;
+ struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str;
+ char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
+ unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
+ struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file;
+ struct dwarf_file_data *
+ GTY ((tag ("dw_val_class_file_implicit"))) val_file_implicit;
+ unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8];
+ tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref;
+ struct dw_val_vms_delta_union
+ {
+ char * lbl1;
+ char * lbl2;
+ } GTY ((tag ("dw_val_class_vms_delta"))) val_vms_delta;
+ dw_discr_value GTY ((tag ("dw_val_class_discr_value"))) val_discr_value;
+ dw_discr_list_ref GTY ((tag ("dw_val_class_discr_list"))) val_discr_list;
+ char * GTY ((tag ("dw_val_class_symview"))) val_symbolic_view;
+ }
+ GTY ((desc ("%1.val_class"))) v;
+};
+
+/* Locations in memory are described using a sequence of stack machine
+ operations. */
+
+struct GTY((chain_next ("%h.dw_loc_next"))) dw_loc_descr_node {
+ dw_loc_descr_ref dw_loc_next;
+ ENUM_BITFIELD (dwarf_location_atom) dw_loc_opc : 8;
+ /* Used to distinguish DW_OP_addr with a direct symbol relocation
+ from DW_OP_addr with a dtp-relative symbol relocation. */
+ unsigned int dtprel : 1;
+ /* For DW_OP_pick, DW_OP_dup and DW_OP_over operations: true iff.
+ it targets a DWARF prodecure argument. In this case, it needs to be
+ relocated according to the current frame offset. */
+ unsigned int frame_offset_rel : 1;
+ int dw_loc_addr;
+ dw_val_node dw_loc_oprnd1;
+ dw_val_node dw_loc_oprnd2;
+};
+
+/* A variant (inside a record variant part) is selected when the corresponding
+ discriminant matches its set of values (see the comment for dw_discr_value).
+ The following datastructure holds such matching information. */
+
+struct GTY(()) dw_discr_list_node {
+ dw_discr_list_ref dw_discr_next;
+
+ dw_discr_value dw_discr_lower_bound;
+ dw_discr_value dw_discr_upper_bound;
+ /* This node represents only the value in dw_discr_lower_bound when it's
+ zero. It represents the range between the two fields (bounds included)
+ otherwise. */
+ int dw_discr_range;
+};
+
+/* Interface from dwarf2out.cc to dwarf2cfi.cc. */
+extern struct dw_loc_descr_node *build_cfa_loc
+ (dw_cfa_location *, poly_int64);
+extern struct dw_loc_descr_node *build_cfa_aligned_loc
+ (dw_cfa_location *, poly_int64, HOST_WIDE_INT);
+extern struct dw_loc_descr_node *build_span_loc (struct cfa_reg);
+extern struct dw_loc_descr_node *mem_loc_descriptor
+ (rtx, machine_mode mode, machine_mode mem_mode,
+ enum var_init_status);
+extern bool loc_descr_equal_p (dw_loc_descr_ref, dw_loc_descr_ref);
+extern dw_fde_ref dwarf2out_alloc_current_fde (void);
+
+extern unsigned long size_of_locs (dw_loc_descr_ref);
+extern void output_loc_sequence (dw_loc_descr_ref, int);
+extern void output_loc_sequence_raw (dw_loc_descr_ref);
+
+/* Interface from dwarf2cfi.cc to dwarf2out.cc. */
+extern void lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc,
+ dw_cfa_location *remember);
+extern bool cfa_equal_p (const dw_cfa_location *, const dw_cfa_location *);
+
+extern void output_cfi (dw_cfi_ref, dw_fde_ref, int);
+
+extern GTY(()) cfi_vec cie_cfi_vec;
+
+/* Interface from dwarf2*.c to the rest of the compiler. */
+extern enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc
+ (enum dwarf_call_frame_info cfi);
+extern enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc
+ (enum dwarf_call_frame_info cfi);
+
+extern void output_cfi_directive (FILE *f, struct dw_cfi_node *cfi);
+
+extern void dwarf2out_emit_cfi (dw_cfi_ref cfi);
+
+extern void debug_dwarf (void);
+struct die_struct;
+extern void debug_dwarf_die (struct die_struct *);
+extern void debug_dwarf_loc_descr (dw_loc_descr_ref);
+extern void debug (die_struct &ref);
+extern void debug (die_struct *ptr);
+extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
+#ifdef VMS_DEBUGGING_INFO
+extern void dwarf2out_vms_debug_main_pointer (void);
+#endif
+
+enum array_descr_ordering
+{
+ array_descr_ordering_default,
+ array_descr_ordering_row_major,
+ array_descr_ordering_column_major
+};
+
+#define DWARF2OUT_ARRAY_DESCR_INFO_MAX_DIMEN 16
+
+struct array_descr_info
+{
+ int ndimensions;
+ enum array_descr_ordering ordering;
+ tree element_type;
+ tree base_decl;
+ tree data_location;
+ tree allocated;
+ tree associated;
+ tree stride;
+ tree rank;
+ bool stride_in_bits;
+ struct array_descr_dimen
+ {
+ /* GCC uses sizetype for array indices, so lower_bound and upper_bound
+ will likely be "sizetype" values. However, bounds may have another
+ type in the original source code. */
+ tree bounds_type;
+ tree lower_bound;
+ tree upper_bound;
+
+ /* Only Fortran uses more than one dimension for array types. For other
+ languages, the stride can be rather specified for the whole array. */
+ tree stride;
+ } dimen[DWARF2OUT_ARRAY_DESCR_INFO_MAX_DIMEN];
+};
+
+enum fixed_point_scale_factor
+{
+ fixed_point_scale_factor_binary,
+ fixed_point_scale_factor_decimal,
+ fixed_point_scale_factor_arbitrary
+};
+
+struct fixed_point_type_info
+{
+ /* The scale factor is the value one has to multiply the actual data with
+ to get the fixed point value. We support three ways to encode it. */
+ enum fixed_point_scale_factor scale_factor_kind;
+ union
+ {
+ /* For a binary scale factor, the scale factor is 2 ** binary. */
+ int binary;
+ /* For a decimal scale factor, the scale factor is 10 ** decimal. */
+ int decimal;
+ /* For an arbitrary scale factor, the scale factor is the ratio
+ numerator / denominator. */
+ struct { tree numerator; tree denominator; } arbitrary;
+ } scale_factor;
+};
+
+void dwarf2out_cc_finalize (void);
+
+/* Some DWARF internals are exposed for the needs of DWARF-based debug
+ formats. */
+
+/* Each DIE attribute has a field specifying the attribute kind,
+ a link to the next attribute in the chain, and an attribute value.
+ Attributes are typically linked below the DIE they modify. */
+
+typedef struct GTY(()) dw_attr_struct {
+ enum dwarf_attribute dw_attr;
+ dw_val_node dw_attr_val;
+}
+dw_attr_node;
+
+extern dw_attr_node *get_AT (dw_die_ref, enum dwarf_attribute);
+extern HOST_WIDE_INT AT_int (dw_attr_node *);
+extern unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *a);
+extern dw_loc_descr_ref AT_loc (dw_attr_node *);
+extern dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
+extern const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
+extern enum dw_val_class AT_class (dw_attr_node *);
+extern unsigned HOST_WIDE_INT AT_unsigned (dw_attr_node *);
+extern unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
+extern int get_AT_flag (dw_die_ref, enum dwarf_attribute);
+
+extern void add_name_attribute (dw_die_ref, const char *);
+
+extern dw_die_ref new_die_raw (enum dwarf_tag);
+extern dw_die_ref base_type_die (tree, bool);
+
+extern dw_die_ref lookup_decl_die (tree);
+extern dw_die_ref lookup_type_die (tree);
+
+extern dw_die_ref dw_get_die_child (dw_die_ref);
+extern dw_die_ref dw_get_die_sib (dw_die_ref);
+extern enum dwarf_tag dw_get_die_tag (dw_die_ref);
+
+/* Data about a single source file. */
+struct GTY((for_user)) dwarf_file_data {
+ const char * key;
+ const char * filename;
+ int emitted_number;
+};
+
+extern struct dwarf_file_data *get_AT_file (dw_die_ref,
+ enum dwarf_attribute);
+
+#endif /* GCC_DWARF2OUT_H */
diff --git a/support/cpp/gcc/edit-context.cc b/support/cpp/gcc/edit-context.cc
new file mode 100644
index 000000000..6879ddd41
--- /dev/null
+++ b/support/cpp/gcc/edit-context.cc
@@ -0,0 +1,1813 @@
+/* Determining the results of applying fix-it hints.
+ Copyright (C) 2016-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 "line-map.h"
+#include "edit-context.h"
+#include "pretty-print.h"
+#include "diagnostic-color.h"
+#include "selftest.h"
+
+/* This file implements a way to track the effect of fix-its,
+ via a class edit_context; the other classes are support classes for
+ edit_context.
+
+ A complication here is that fix-its are expressed relative to coordinates
+ in the file when it was parsed, before any changes have been made, and
+ so if there's more that one fix-it to be applied, we have to adjust
+ later fix-its to allow for the changes made by earlier ones. This
+ is done by the various "get_effective_column" methods.
+
+ The "filename" params are required to outlive the edit_context (no
+ copy of the underlying str is taken, just the ptr). */
+
+/* Forward decls. class edit_context is declared within edit-context.h.
+ The other types are declared here. */
+class edit_context;
+class edited_file;
+class edited_line;
+class line_event;
+
+/* A struct to hold the params of a print_diff call. */
+
+class diff
+{
+public:
+ diff (pretty_printer *pp, bool show_filenames)
+ : m_pp (pp), m_show_filenames (show_filenames) {}
+
+ pretty_printer *m_pp;
+ bool m_show_filenames;
+};
+
+/* The state of one named file within an edit_context: the filename,
+ and the lines that have been edited so far. */
+
+class edited_file
+{
+ public:
+ edited_file (const char *filename);
+ static void delete_cb (edited_file *file);
+
+ const char *get_filename () const { return m_filename; }
+ char *get_content ();
+
+ bool apply_fixit (int line, int start_column,
+ int next_column,
+ const char *replacement_str,
+ int replacement_len);
+ int get_effective_column (int line, int column);
+
+ static int call_print_diff (const char *, edited_file *file,
+ void *user_data)
+ {
+ diff *d = (diff *)user_data;
+ file->print_diff (d->m_pp, d->m_show_filenames);
+ return 0;
+ }
+
+ private:
+ bool print_content (pretty_printer *pp);
+ void print_diff (pretty_printer *pp, bool show_filenames);
+ int print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
+ int old_end_of_hunk, int new_start_of_hunk);
+ edited_line *get_line (int line);
+ edited_line *get_or_insert_line (int line);
+ int get_num_lines (bool *missing_trailing_newline);
+
+ int get_effective_line_count (int old_start_of_hunk,
+ int old_end_of_hunk);
+
+ void print_run_of_changed_lines (pretty_printer *pp,
+ int start_of_run,
+ int end_of_run);
+
+ const char *m_filename;
+ typed_splay_tree<int, edited_line *> m_edited_lines;
+ int m_num_lines;
+};
+
+/* A line added before an edited_line. */
+
+class added_line
+{
+ public:
+ added_line (const char *content, int len)
+ : m_content (xstrndup (content, len)), m_len (len) {}
+ ~added_line () { free (m_content); }
+
+ const char *get_content () const { return m_content; }
+ int get_len () const { return m_len; }
+
+ private:
+ char *m_content;
+ int m_len;
+};
+
+/* The state of one edited line within an edited_file.
+ As well as the current content of the line, it contains a record of
+ the changes, so that further changes can be applied in the correct
+ place.
+
+ When handling fix-it hints containing newlines, new lines are added
+ as added_line predecessors to an edited_line. Hence it's possible
+ for an "edited_line" to not actually have been changed, but to merely
+ be a placeholder for the lines added before it. This can be tested
+ for with actuall_edited_p, and has a slight effect on how diff hunks
+ are generated. */
+
+class edited_line
+{
+ public:
+ edited_line (const char *filename, int line_num);
+ ~edited_line ();
+ static void delete_cb (edited_line *el);
+
+ int get_line_num () const { return m_line_num; }
+ const char *get_content () const { return m_content; }
+ int get_len () const { return m_len; }
+
+ int get_effective_column (int orig_column) const;
+ bool apply_fixit (int start_column,
+ int next_column,
+ const char *replacement_str,
+ int replacement_len);
+
+ int get_effective_line_count () const;
+
+ /* Has the content of this line actually changed, or are we merely
+ recording predecessor added_lines? */
+ bool actually_edited_p () const { return m_line_events.length () > 0; }
+
+ void print_content (pretty_printer *pp) const;
+ void print_diff_lines (pretty_printer *pp) const;
+
+ private:
+ void ensure_capacity (int len);
+ void ensure_terminated ();
+
+ int m_line_num;
+ char *m_content;
+ int m_len;
+ int m_alloc_sz;
+ auto_vec <line_event> m_line_events;
+ auto_vec <added_line *> m_predecessors;
+};
+
+/* Class for representing edit events that have occurred on one line of
+ one file: the replacement of some text betweeen some columns
+ on the line.
+
+ Subsequent events will need their columns adjusting if they're
+ are on this line and their column is >= the start point. */
+
+class line_event
+{
+ public:
+ line_event (int start, int next, int len) : m_start (start),
+ m_delta (len - (next - start)) {}
+
+ int get_effective_column (int orig_column) const
+ {
+ if (orig_column >= m_start)
+ return orig_column += m_delta;
+ else
+ return orig_column;
+ }
+
+ private:
+ int m_start;
+ int m_delta;
+};
+
+/* Forward decls. */
+
+static void
+print_diff_line (pretty_printer *pp, char prefix_char,
+ const char *line, int line_size);
+
+/* Implementation of class edit_context. */
+
+/* edit_context's ctor. */
+
+edit_context::edit_context ()
+: m_valid (true),
+ m_files (strcmp, NULL, edited_file::delete_cb)
+{}
+
+/* Add any fixits within RICHLOC to this context, recording the
+ changes that they make. */
+
+void
+edit_context::add_fixits (rich_location *richloc)
+{
+ if (!m_valid)
+ return;
+ if (richloc->seen_impossible_fixit_p ())
+ {
+ m_valid = false;
+ return;
+ }
+ for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
+ {
+ const fixit_hint *hint = richloc->get_fixit_hint (i);
+ if (!apply_fixit (hint))
+ m_valid = false;
+ }
+}
+
+/* Get the content of the given file, with fix-its applied.
+ If any errors occurred in this edit_context, return NULL.
+ The ptr should be freed by the caller. */
+
+char *
+edit_context::get_content (const char *filename)
+{
+ if (!m_valid)
+ return NULL;
+ edited_file &file = get_or_insert_file (filename);
+ return file.get_content ();
+}
+
+/* Map a location before the edits to a column number after the edits.
+ This method is for the selftests. */
+
+int
+edit_context::get_effective_column (const char *filename, int line,
+ int column)
+{
+ edited_file *file = get_file (filename);
+ if (!file)
+ return column;
+ return file->get_effective_column (line, column);
+}
+
+/* Generate a unified diff. The resulting string should be freed by the
+ caller. Primarily for selftests.
+ If any errors occurred in this edit_context, return NULL. */
+
+char *
+edit_context::generate_diff (bool show_filenames)
+{
+ if (!m_valid)
+ return NULL;
+
+ pretty_printer pp;
+ print_diff (&pp, show_filenames);
+ return xstrdup (pp_formatted_text (&pp));
+}
+
+/* Print a unified diff to PP, showing the changes made within the
+ context. */
+
+void
+edit_context::print_diff (pretty_printer *pp, bool show_filenames)
+{
+ if (!m_valid)
+ return;
+ diff d (pp, show_filenames);
+ m_files.foreach (edited_file::call_print_diff, &d);
+}
+
+/* Attempt to apply the given fixit. Return true if it can be
+ applied, or false otherwise. */
+
+bool
+edit_context::apply_fixit (const fixit_hint *hint)
+{
+ expanded_location start = expand_location (hint->get_start_loc ());
+ expanded_location next_loc = expand_location (hint->get_next_loc ());
+ if (start.file != next_loc.file)
+ return false;
+ if (start.line != next_loc.line)
+ return false;
+ if (start.column == 0)
+ return false;
+ if (next_loc.column == 0)
+ return false;
+
+ edited_file &file = get_or_insert_file (start.file);
+ if (!m_valid)
+ return false;
+ return file.apply_fixit (start.line, start.column, next_loc.column,
+ hint->get_string (),
+ hint->get_length ());
+}
+
+/* Locate the edited_file * for FILENAME, if any
+ Return NULL if there isn't one. */
+
+edited_file *
+edit_context::get_file (const char *filename)
+{
+ gcc_assert (filename);
+ return m_files.lookup (filename);
+}
+
+/* Locate the edited_file for FILENAME, adding one if there isn't one. */
+
+edited_file &
+edit_context::get_or_insert_file (const char *filename)
+{
+ gcc_assert (filename);
+
+ edited_file *file = get_file (filename);
+ if (file)
+ return *file;
+
+ /* Not found. */
+ file = new edited_file (filename);
+ m_files.insert (filename, file);
+ return *file;
+}
+
+/* Implementation of class edited_file. */
+
+/* Callback for m_edited_lines, for comparing line numbers. */
+
+static int line_comparator (int a, int b)
+{
+ return a - b;
+}
+
+/* edited_file's constructor. */
+
+edited_file::edited_file (const char *filename)
+: m_filename (filename),
+ m_edited_lines (line_comparator, NULL, edited_line::delete_cb),
+ m_num_lines (-1)
+{
+}
+
+/* A callback for deleting edited_file *, for use as a
+ delete_value_fn for edit_context::m_files. */
+
+void
+edited_file::delete_cb (edited_file *file)
+{
+ delete file;
+}
+
+/* Get the content of the file, with fix-its applied.
+ The ptr should be freed by the caller. */
+
+char *
+edited_file::get_content ()
+{
+ pretty_printer pp;
+ if (!print_content (&pp))
+ return NULL;
+ return xstrdup (pp_formatted_text (&pp));
+}
+
+/* Attempt to replace columns START_COLUMN up to but not including NEXT_COLUMN
+ of LINE with the string REPLACEMENT_STR of length REPLACEMENT_LEN,
+ updating the in-memory copy of the line, and the record of edits to
+ the line. */
+
+bool
+edited_file::apply_fixit (int line, int start_column, int next_column,
+ const char *replacement_str,
+ int replacement_len)
+{
+ edited_line *el = get_or_insert_line (line);
+ if (!el)
+ return false;
+ return el->apply_fixit (start_column, next_column, replacement_str,
+ replacement_len);
+}
+
+/* Given line LINE, map from COLUMN in the input file to its current
+ column after edits have been applied. */
+
+int
+edited_file::get_effective_column (int line, int column)
+{
+ const edited_line *el = get_line (line);
+ if (!el)
+ return column;
+ return el->get_effective_column (column);
+}
+
+/* Attempt to print the content of the file to PP, with edits applied.
+ Return true if successful, false otherwise. */
+
+bool
+edited_file::print_content (pretty_printer *pp)
+{
+ bool missing_trailing_newline;
+ int line_count = get_num_lines (&missing_trailing_newline);
+ for (int line_num = 1; line_num <= line_count; line_num++)
+ {
+ edited_line *el = get_line (line_num);
+ if (el)
+ el->print_content (pp);
+ else
+ {
+ char_span line = location_get_source_line (m_filename, line_num);
+ if (!line)
+ return false;
+ for (size_t i = 0; i < line.length (); i++)
+ pp_character (pp, line[i]);
+ }
+ if (line_num < line_count)
+ pp_character (pp, '\n');
+ }
+
+ if (!missing_trailing_newline)
+ pp_character (pp, '\n');
+
+ return true;
+}
+
+/* Print a unified diff to PP, showing any changes that have occurred
+ to this file. */
+
+void
+edited_file::print_diff (pretty_printer *pp, bool show_filenames)
+{
+ if (show_filenames)
+ {
+ pp_string (pp, colorize_start (pp_show_color (pp), "diff-filename"));
+ /* Avoid -Wformat-diag in non-diagnostic output. */
+ pp_string (pp, "--- ");
+ pp_string (pp, m_filename);
+ pp_newline (pp);
+ pp_string (pp, "+++ ");
+ pp_string (pp, m_filename);
+ pp_newline (pp);
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+ }
+
+ edited_line *el = m_edited_lines.min ();
+
+ bool missing_trailing_newline;
+ int line_count = get_num_lines (&missing_trailing_newline);
+
+ const int context_lines = 3;
+
+ /* Track new line numbers minus old line numbers. */
+
+ int line_delta = 0;
+
+ while (el)
+ {
+ int start_of_hunk = el->get_line_num ();
+ start_of_hunk -= context_lines;
+ if (start_of_hunk < 1)
+ start_of_hunk = 1;
+
+ /* Locate end of hunk, merging in changed lines
+ that are sufficiently close. */
+ while (true)
+ {
+ edited_line *next_el
+ = m_edited_lines.successor (el->get_line_num ());
+ if (!next_el)
+ break;
+
+ int end_of_printed_hunk = el->get_line_num () + context_lines;
+ if (!el->actually_edited_p ())
+ end_of_printed_hunk--;
+
+ if (end_of_printed_hunk
+ >= next_el->get_line_num () - context_lines)
+ el = next_el;
+ else
+ break;
+ }
+
+ int end_of_hunk = el->get_line_num ();
+ end_of_hunk += context_lines;
+ if (!el->actually_edited_p ())
+ end_of_hunk--;
+ if (end_of_hunk > line_count)
+ end_of_hunk = line_count;
+
+ int new_start_of_hunk = start_of_hunk + line_delta;
+ line_delta += print_diff_hunk (pp, start_of_hunk, end_of_hunk,
+ new_start_of_hunk);
+ el = m_edited_lines.successor (el->get_line_num ());
+ }
+}
+
+/* Print one hunk within a unified diff to PP, covering the
+ given range of lines. OLD_START_OF_HUNK and OLD_END_OF_HUNK are
+ line numbers in the unedited version of the file.
+ NEW_START_OF_HUNK is a line number in the edited version of the file.
+ Return the change in the line count within the hunk. */
+
+int
+edited_file::print_diff_hunk (pretty_printer *pp, int old_start_of_hunk,
+ int old_end_of_hunk, int new_start_of_hunk)
+{
+ int old_num_lines = old_end_of_hunk - old_start_of_hunk + 1;
+ int new_num_lines
+ = get_effective_line_count (old_start_of_hunk, old_end_of_hunk);
+
+ pp_string (pp, colorize_start (pp_show_color (pp), "diff-hunk"));
+ pp_printf (pp, "%s -%i,%i +%i,%i %s",
+ "@@", old_start_of_hunk, old_num_lines,
+ new_start_of_hunk, new_num_lines, "@@\n");
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+
+ int line_num = old_start_of_hunk;
+ while (line_num <= old_end_of_hunk)
+ {
+ edited_line *el = get_line (line_num);
+ if (el)
+ {
+ /* We have an edited line.
+ Consolidate into runs of changed lines. */
+ const int first_changed_line_in_run = line_num;
+ while (get_line (line_num))
+ line_num++;
+ const int last_changed_line_in_run = line_num - 1;
+ print_run_of_changed_lines (pp, first_changed_line_in_run,
+ last_changed_line_in_run);
+ }
+ else
+ {
+ /* Unchanged line. */
+ char_span old_line = location_get_source_line (m_filename, line_num);
+ print_diff_line (pp, ' ', old_line.get_buffer (), old_line.length ());
+ line_num++;
+ }
+ }
+
+ return new_num_lines - old_num_lines;
+}
+
+/* Subroutine of edited_file::print_diff_hunk: given a run of lines
+ from START_OF_RUN to END_OF_RUN that all have edited_line instances,
+ print the diff to PP. */
+
+void
+edited_file::print_run_of_changed_lines (pretty_printer *pp,
+ int start_of_run,
+ int end_of_run)
+{
+ /* Show old version of lines. */
+ pp_string (pp, colorize_start (pp_show_color (pp),
+ "diff-delete"));
+ for (int line_num = start_of_run;
+ line_num <= end_of_run;
+ line_num++)
+ {
+ edited_line *el_in_run = get_line (line_num);
+ gcc_assert (el_in_run);
+ if (el_in_run->actually_edited_p ())
+ {
+ char_span old_line = location_get_source_line (m_filename, line_num);
+ print_diff_line (pp, '-', old_line.get_buffer (),
+ old_line.length ());
+ }
+ }
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+
+ /* Show new version of lines. */
+ pp_string (pp, colorize_start (pp_show_color (pp),
+ "diff-insert"));
+ for (int line_num = start_of_run;
+ line_num <= end_of_run;
+ line_num++)
+ {
+ edited_line *el_in_run = get_line (line_num);
+ gcc_assert (el_in_run);
+ el_in_run->print_diff_lines (pp);
+ }
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+}
+
+/* Print one line within a diff, starting with PREFIX_CHAR,
+ followed by the LINE of content, of length LEN. LINE is
+ not necessarily 0-terminated. Print a trailing newline. */
+
+static void
+print_diff_line (pretty_printer *pp, char prefix_char,
+ const char *line, int len)
+{
+ pp_character (pp, prefix_char);
+ for (int i = 0; i < len; i++)
+ pp_character (pp, line[i]);
+ pp_character (pp, '\n');
+}
+
+/* Determine the number of lines that will be present after
+ editing for the range of lines from OLD_START_OF_HUNK to
+ OLD_END_OF_HUNK inclusive. */
+
+int
+edited_file::get_effective_line_count (int old_start_of_hunk,
+ int old_end_of_hunk)
+{
+ int line_count = 0;
+ for (int old_line_num = old_start_of_hunk; old_line_num <= old_end_of_hunk;
+ old_line_num++)
+ {
+ edited_line *el = get_line (old_line_num);
+ if (el)
+ line_count += el->get_effective_line_count ();
+ else
+ line_count++;
+ }
+ return line_count;
+}
+
+/* Get the state of LINE within the file, or NULL if it is untouched. */
+
+edited_line *
+edited_file::get_line (int line)
+{
+ return m_edited_lines.lookup (line);
+}
+
+/* Get the state of LINE within the file, creating a state for it
+ if necessary. Return NULL if an error occurs. */
+
+edited_line *
+edited_file::get_or_insert_line (int line)
+{
+ edited_line *el = get_line (line);
+ if (el)
+ return el;
+ el = new edited_line (m_filename, line);
+ if (el->get_content () == NULL)
+ {
+ delete el;
+ return NULL;
+ }
+ m_edited_lines.insert (line, el);
+ return el;
+}
+
+/* Get the total number of lines in m_content, writing
+ true to *MISSING_TRAILING_NEWLINE if the final line
+ if missing a newline, false otherwise. */
+
+int
+edited_file::get_num_lines (bool *missing_trailing_newline)
+{
+ gcc_assert (missing_trailing_newline);
+ if (m_num_lines == -1)
+ {
+ m_num_lines = 0;
+ while (true)
+ {
+ char_span line
+ = location_get_source_line (m_filename, m_num_lines + 1);
+ if (line)
+ m_num_lines++;
+ else
+ break;
+ }
+ }
+ *missing_trailing_newline = location_missing_trailing_newline (m_filename);
+ return m_num_lines;
+}
+
+/* Implementation of class edited_line. */
+
+/* edited_line's ctor. */
+
+edited_line::edited_line (const char *filename, int line_num)
+: m_line_num (line_num),
+ m_content (NULL), m_len (0), m_alloc_sz (0),
+ m_line_events (),
+ m_predecessors ()
+{
+ char_span line = location_get_source_line (filename, line_num);
+ if (!line)
+ return;
+ m_len = line.length ();
+ ensure_capacity (m_len);
+ memcpy (m_content, line.get_buffer (), m_len);
+ ensure_terminated ();
+}
+
+/* edited_line's dtor. */
+
+edited_line::~edited_line ()
+{
+ unsigned i;
+ added_line *pred;
+
+ free (m_content);
+ FOR_EACH_VEC_ELT (m_predecessors, i, pred)
+ delete pred;
+}
+
+/* A callback for deleting edited_line *, for use as a
+ delete_value_fn for edited_file::m_edited_lines. */
+
+void
+edited_line::delete_cb (edited_line *el)
+{
+ delete el;
+}
+
+/* Map a location before the edits to a column number after the edits,
+ within a specific line. */
+
+int
+edited_line::get_effective_column (int orig_column) const
+{
+ int i;
+ line_event *event;
+ FOR_EACH_VEC_ELT (m_line_events, i, event)
+ orig_column = event->get_effective_column (orig_column);
+ return orig_column;
+}
+
+/* Attempt to replace columns START_COLUMN up to but not including
+ NEXT_COLUMN of the line with the string REPLACEMENT_STR of
+ length REPLACEMENT_LEN, updating the in-memory copy of the line,
+ and the record of edits to the line.
+ Return true if successful; false if an error occurred. */
+
+bool
+edited_line::apply_fixit (int start_column,
+ int next_column,
+ const char *replacement_str,
+ int replacement_len)
+{
+ /* Handle newlines. They will only ever be at the end of the
+ replacement text, thanks to the filtering in rich_location. */
+ if (replacement_len > 1)
+ if (replacement_str[replacement_len - 1] == '\n')
+ {
+ /* Stash in m_predecessors, stripping off newline. */
+ m_predecessors.safe_push (new added_line (replacement_str,
+ replacement_len - 1));
+ return true;
+ }
+
+ start_column = get_effective_column (start_column);
+ next_column = get_effective_column (next_column);
+
+ int start_offset = start_column - 1;
+ int next_offset = next_column - 1;
+
+ gcc_assert (start_offset >= 0);
+ gcc_assert (next_offset >= 0);
+
+ if (start_column > next_column)
+ return false;
+ if (start_offset >= (m_len + 1))
+ return false;
+ if (next_offset >= (m_len + 1))
+ return false;
+
+ size_t victim_len = next_offset - start_offset;
+
+ /* Ensure buffer is big enough. */
+ size_t new_len = m_len + replacement_len - victim_len;
+ ensure_capacity (new_len);
+
+ char *suffix = m_content + next_offset;
+ gcc_assert (suffix <= m_content + m_len);
+ size_t len_suffix = (m_content + m_len) - suffix;
+
+ /* Move successor content into position. They overlap, so use memmove. */
+ memmove (m_content + start_offset + replacement_len,
+ suffix, len_suffix);
+
+ /* Replace target content. They don't overlap, so use memcpy. */
+ memcpy (m_content + start_offset,
+ replacement_str,
+ replacement_len);
+
+ m_len = new_len;
+
+ ensure_terminated ();
+
+ /* Record the replacement, so that future changes to the line can have
+ their column information adjusted accordingly. */
+ m_line_events.safe_push (line_event (start_column, next_column,
+ replacement_len));
+ return true;
+}
+
+/* Determine the number of lines that will be present after
+ editing for this line. Typically this is just 1, but
+ if newlines have been added before this line, they will
+ also be counted. */
+
+int
+edited_line::get_effective_line_count () const
+{
+ return m_predecessors.length () + 1;
+}
+
+/* Subroutine of edited_file::print_content.
+ Print this line and any new lines added before it, to PP. */
+
+void
+edited_line::print_content (pretty_printer *pp) const
+{
+ unsigned i;
+ added_line *pred;
+ FOR_EACH_VEC_ELT (m_predecessors, i, pred)
+ {
+ pp_string (pp, pred->get_content ());
+ pp_newline (pp);
+ }
+ pp_string (pp, m_content);
+}
+
+/* Subroutine of edited_file::print_run_of_changed_lines for
+ printing diff hunks to PP.
+ Print the '+' line for this line, and any newlines added
+ before it.
+ Note that if this edited_line was actually edited, the '-'
+ line has already been printed. If it wasn't, then we merely
+ have a placeholder edited_line for adding newlines to, and
+ we need to print a ' ' line for the edited_line as we haven't
+ printed it yet. */
+
+void
+edited_line::print_diff_lines (pretty_printer *pp) const
+{
+ unsigned i;
+ added_line *pred;
+ FOR_EACH_VEC_ELT (m_predecessors, i, pred)
+ print_diff_line (pp, '+', pred->get_content (),
+ pred->get_len ());
+ if (actually_edited_p ())
+ print_diff_line (pp, '+', m_content, m_len);
+ else
+ print_diff_line (pp, ' ', m_content, m_len);
+}
+
+/* Ensure that the buffer for m_content is at least large enough to hold
+ a string of length LEN and its 0-terminator, doubling on repeated
+ allocations. */
+
+void
+edited_line::ensure_capacity (int len)
+{
+ /* Allow 1 extra byte for 0-termination. */
+ if (m_alloc_sz < (len + 1))
+ {
+ size_t new_alloc_sz = (len + 1) * 2;
+ m_content = (char *)xrealloc (m_content, new_alloc_sz);
+ m_alloc_sz = new_alloc_sz;
+ }
+}
+
+/* Ensure that m_content is 0-terminated. */
+
+void
+edited_line::ensure_terminated ()
+{
+ /* 0-terminate the buffer. */
+ gcc_assert (m_len < m_alloc_sz);
+ m_content[m_len] = '\0';
+}
+
+#if CHECKING_P
+
+/* Selftests of code-editing. */
+
+namespace selftest {
+
+/* A wrapper class for ensuring that the underlying pointer is freed. */
+
+template <typename POINTER_T>
+class auto_free
+{
+ public:
+ auto_free (POINTER_T p) : m_ptr (p) {}
+ ~auto_free () { free (m_ptr); }
+
+ operator POINTER_T () { return m_ptr; }
+
+ private:
+ POINTER_T m_ptr;
+};
+
+/* Verify that edit_context::get_content works for unedited files. */
+
+static void
+test_get_content ()
+{
+ /* Test of empty file. */
+ {
+ const char *content = ("");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ edit_context edit;
+ auto_free <char *> result = edit.get_content (tmp.get_filename ());
+ ASSERT_STREQ ("", result);
+ }
+
+ /* Test of simple content. */
+ {
+ const char *content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ edit_context edit;
+ auto_free <char *> result = edit.get_content (tmp.get_filename ());
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n", result);
+ }
+
+ /* Test of omitting the trailing newline on the final line. */
+ {
+ const char *content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
+ edit_context edit;
+ auto_free <char *> result = edit.get_content (tmp.get_filename ());
+ /* We should respect the omitted trailing newline. */
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */", result);
+ }
+}
+
+/* Test applying an "insert" fixit, using insert_before. */
+
+static void
+test_applying_fixits_insert_before (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+
+ /* Add a comment in front of "bar.field". */
+ location_t start = linemap_position_for_column (line_table, 7);
+ rich_location richloc (line_table, start);
+ richloc.add_fixit_insert_before ("/* inserted */");
+
+ if (start > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ if (start <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ ASSERT_STREQ ("/* before */\n"
+ "foo = /* inserted */bar.field;\n"
+ "/* after */\n", new_content);
+
+ /* Verify that locations on other lines aren't affected by the change. */
+ ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
+ ASSERT_EQ (100, edit.get_effective_column (filename, 3, 100));
+
+ /* Verify locations on the line before the change. */
+ ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
+ ASSERT_EQ (6, edit.get_effective_column (filename, 2, 6));
+
+ /* Verify locations on the line at and after the change. */
+ ASSERT_EQ (21, edit.get_effective_column (filename, 2, 7));
+ ASSERT_EQ (22, edit.get_effective_column (filename, 2, 8));
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.field;\n"
+ "+foo = /* inserted */bar.field;\n"
+ " /* after */\n", diff);
+}
+
+/* Test applying an "insert" fixit, using insert_after, with
+ a range of length > 1 (to ensure that the end-point of
+ the input range is used). */
+
+static void
+test_applying_fixits_insert_after (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+
+ /* Add a comment after "field". */
+ location_t start = linemap_position_for_column (line_table, 11);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ location_t field = make_location (start, start, finish);
+ rich_location richloc (line_table, field);
+ richloc.add_fixit_insert_after ("/* inserted */");
+
+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Verify that the text was inserted after the end of "field". */
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar.field/* inserted */;\n"
+ "/* after */\n", new_content);
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.field;\n"
+ "+foo = bar.field/* inserted */;\n"
+ " /* after */\n", diff);
+}
+
+/* Test applying an "insert" fixit, using insert_after at the end of
+ a line (contrast with test_applying_fixits_insert_after_failure
+ below). */
+
+static void
+test_applying_fixits_insert_after_at_line_end (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+
+ /* Add a comment after the semicolon. */
+ location_t loc = linemap_position_for_column (line_table, 16);
+ rich_location richloc (line_table, loc);
+ richloc.add_fixit_insert_after ("/* inserted */");
+
+ if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar.field;/* inserted */\n"
+ "/* after */\n", new_content);
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.field;\n"
+ "+foo = bar.field;/* inserted */\n"
+ " /* after */\n", diff);
+}
+
+/* Test of a failed attempt to apply an "insert" fixit, using insert_after,
+ due to the relevant linemap ending. Contrast with
+ test_applying_fixits_insert_after_at_line_end above. */
+
+static void
+test_applying_fixits_insert_after_failure (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 2);
+
+ /* Add a comment after the semicolon. */
+ location_t loc = linemap_position_for_column (line_table, 16);
+ rich_location richloc (line_table, loc);
+
+ /* We want a failure of linemap_position_for_loc_and_offset.
+ We can do this by starting a new linemap at line 3, so that
+ there is no appropriate location value for the insertion point
+ within the linemap for line 2. */
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+
+ /* The failure fails to happen at the transition point from
+ packed ranges to unpacked ranges (where there are some "spare"
+ location_t values). Skip the test there. */
+ if (loc >= LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES)
+ return;
+
+ /* Offsetting "loc" should now fail (by returning the input loc. */
+ ASSERT_EQ (loc, linemap_position_for_loc_and_offset (line_table, loc, 1));
+
+ /* Hence attempting to use add_fixit_insert_after at the end of the line
+ should now fail. */
+ richloc.add_fixit_insert_after ("/* inserted */");
+ ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ ASSERT_FALSE (edit.valid_p ());
+ ASSERT_EQ (NULL, edit.get_content (filename));
+ ASSERT_EQ (NULL, edit.generate_diff (false));
+}
+
+/* Test applying an "insert" fixit that adds a newline. */
+
+static void
+test_applying_fixits_insert_containing_newline (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = (" case 'a':\n" /* line 1. */
+ " x = a;\n" /* line 2. */
+ " case 'b':\n" /* line 3. */
+ " x = b;\n");/* line 4. */
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 3);
+
+ /* Add a "break;" on a line by itself before line 3 i.e. before
+ column 1 of line 3. */
+ location_t case_start = linemap_position_for_column (line_table, 5);
+ location_t case_finish = linemap_position_for_column (line_table, 13);
+ location_t case_loc = make_location (case_start, case_start, case_finish);
+ rich_location richloc (line_table, case_loc);
+ location_t line_start = linemap_position_for_column (line_table, 1);
+ richloc.add_fixit_insert_before (line_start, " break;\n");
+
+ if (case_finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ ASSERT_STREQ ((" case 'a':\n"
+ " x = a;\n"
+ " break;\n"
+ " case 'b':\n"
+ " x = b;\n"),
+ new_content);
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ (("@@ -1,4 +1,5 @@\n"
+ " case 'a':\n"
+ " x = a;\n"
+ "+ break;\n"
+ " case 'b':\n"
+ " x = b;\n"),
+ diff);
+}
+
+/* Test applying a "replace" fixit that grows the affected line. */
+
+static void
+test_applying_fixits_growing_replace (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111111.
+ .........................1234567890123456. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 2);
+
+ /* Replace "field" with "m_field". */
+ location_t start = linemap_position_for_column (line_table, 11);
+ location_t finish = linemap_position_for_column (line_table, 15);
+ location_t field = make_location (start, start, finish);
+ rich_location richloc (line_table, field);
+ richloc.add_fixit_replace ("m_field");
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ {
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar.m_field;\n"
+ "/* after */\n", new_content);
+
+ /* Verify location of ";" after the change. */
+ ASSERT_EQ (18, edit.get_effective_column (filename, 2, 16));
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.field;\n"
+ "+foo = bar.m_field;\n"
+ " /* after */\n", diff);
+ }
+}
+
+/* Test applying a "replace" fixit that shrinks the affected line. */
+
+static void
+test_applying_fixits_shrinking_replace (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................000000000111111111.
+ .........................123456789012345678. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.m_field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 2);
+
+ /* Replace "field" with "m_field". */
+ location_t start = linemap_position_for_column (line_table, 11);
+ location_t finish = linemap_position_for_column (line_table, 17);
+ location_t m_field = make_location (start, start, finish);
+ rich_location richloc (line_table, m_field);
+ richloc.add_fixit_replace ("field");
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ {
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n", new_content);
+
+ /* Verify location of ";" after the change. */
+ ASSERT_EQ (16, edit.get_effective_column (filename, 2, 18));
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.m_field;\n"
+ "+foo = bar.field;\n"
+ " /* after */\n", diff);
+ }
+}
+
+/* Replacement fix-it hint containing a newline. */
+
+static void
+test_applying_fixits_replace_containing_newline (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................0000000001111.
+ .........................1234567890123. */
+ const char *old_content = "foo = bar ();\n";
+
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 1);
+
+ /* Replace the " = " with "\n = ", as if we were reformatting an
+ overly long line. */
+ location_t start = linemap_position_for_column (line_table, 4);
+ location_t finish = linemap_position_for_column (line_table, 6);
+ location_t loc = linemap_position_for_column (line_table, 13);
+ rich_location richloc (line_table, loc);
+ source_range range = source_range::from_locations (start, finish);
+ richloc.add_fixit_replace (range, "\n = ");
+
+ /* Newlines are only supported within fix-it hints that
+ are at the start of lines (for entirely new lines), hence
+ this fix-it should not be displayed. */
+ ASSERT_TRUE (richloc.seen_impossible_fixit_p ());
+
+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ //ASSERT_STREQ ("foo\n = bar ();\n", new_content);
+}
+
+/* Test applying a "remove" fixit. */
+
+static void
+test_applying_fixits_remove (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................000000000111111111.
+ .........................123456789012345678. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.m_field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 2);
+
+ /* Remove ".m_field". */
+ location_t start = linemap_position_for_column (line_table, 10);
+ location_t finish = linemap_position_for_column (line_table, 17);
+ rich_location richloc (line_table, start);
+ source_range range;
+ range.m_start = start;
+ range.m_finish = finish;
+ richloc.add_fixit_remove (range);
+
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (filename);
+ if (finish <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ {
+ ASSERT_STREQ ("/* before */\n"
+ "foo = bar;\n"
+ "/* after */\n", new_content);
+
+ /* Verify location of ";" after the change. */
+ ASSERT_EQ (10, edit.get_effective_column (filename, 2, 18));
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.m_field;\n"
+ "+foo = bar;\n"
+ " /* after */\n", diff);
+ }
+}
+
+/* Test applying multiple fixits to one line. */
+
+static void
+test_applying_fixits_multiple (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................00000000011111111.
+ .........................12345678901234567. */
+ const char *old_content = ("/* before */\n"
+ "foo = bar.field;\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 2);
+
+ location_t c7 = linemap_position_for_column (line_table, 7);
+ location_t c9 = linemap_position_for_column (line_table, 9);
+ location_t c11 = linemap_position_for_column (line_table, 11);
+ location_t c15 = linemap_position_for_column (line_table, 15);
+ location_t c17 = linemap_position_for_column (line_table, 17);
+
+ if (c17 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Add a comment in front of "bar.field". */
+ rich_location insert_a (line_table, c7);
+ insert_a.add_fixit_insert_before (c7, "/* alpha */");
+
+ /* Add a comment after "bar.field;". */
+ rich_location insert_b (line_table, c17);
+ insert_b.add_fixit_insert_before (c17, "/* beta */");
+
+ /* Replace "bar" with "pub". */
+ rich_location replace_a (line_table, c7);
+ replace_a.add_fixit_replace (source_range::from_locations (c7, c9),
+ "pub");
+
+ /* Replace "field" with "meadow". */
+ rich_location replace_b (line_table, c7);
+ replace_b.add_fixit_replace (source_range::from_locations (c11, c15),
+ "meadow");
+
+ edit_context edit;
+ edit.add_fixits (&insert_a);
+ ASSERT_EQ (100, edit.get_effective_column (filename, 1, 100));
+ ASSERT_EQ (1, edit.get_effective_column (filename, 2, 1));
+ ASSERT_EQ (6, edit.get_effective_column (filename, 2, 6));
+ ASSERT_EQ (18, edit.get_effective_column (filename, 2, 7));
+ ASSERT_EQ (27, edit.get_effective_column (filename, 2, 16));
+ ASSERT_EQ (100, edit.get_effective_column (filename, 3, 100));
+
+ edit.add_fixits (&insert_b);
+ edit.add_fixits (&replace_a);
+ edit.add_fixits (&replace_b);
+
+ if (c17 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ {
+ auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+ ASSERT_STREQ ("/* before */\n"
+ "foo = /* alpha */pub.meadow;/* beta */\n"
+ "/* after */\n",
+ new_content);
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,3 +1,3 @@\n"
+ " /* before */\n"
+ "-foo = bar.field;\n"
+ "+foo = /* alpha */pub.meadow;/* beta */\n"
+ " /* after */\n", diff);
+ }
+}
+
+/* Subroutine of test_applying_fixits_multiple_lines.
+ Add the text "CHANGED: " to the front of the given line. */
+
+static location_t
+change_line (edit_context &edit, int line_num)
+{
+ const line_map_ordinary *ord_map
+ = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+ const int column = 1;
+ location_t loc =
+ linemap_position_for_line_and_column (line_table, ord_map,
+ line_num, column);
+
+ expanded_location exploc = expand_location (loc);
+ if (loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ {
+ ASSERT_EQ (line_num, exploc.line);
+ ASSERT_EQ (column, exploc.column);
+ }
+
+ rich_location insert (line_table, loc);
+ insert.add_fixit_insert_before ("CHANGED: ");
+ edit.add_fixits (&insert);
+ return loc;
+}
+
+/* Subroutine of test_applying_fixits_multiple_lines.
+ Add the text "INSERTED\n" in front of the given line. */
+
+static location_t
+insert_line (edit_context &edit, int line_num)
+{
+ const line_map_ordinary *ord_map
+ = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+ const int column = 1;
+ location_t loc =
+ linemap_position_for_line_and_column (line_table, ord_map,
+ line_num, column);
+
+ expanded_location exploc = expand_location (loc);
+ if (loc <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ {
+ ASSERT_EQ (line_num, exploc.line);
+ ASSERT_EQ (column, exploc.column);
+ }
+
+ rich_location insert (line_table, loc);
+ insert.add_fixit_insert_before ("INSERTED\n");
+ edit.add_fixits (&insert);
+ return loc;
+}
+
+/* Test of editing multiple lines within a long file,
+ to ensure that diffs are generated as expected. */
+
+static void
+test_applying_fixits_multiple_lines (const line_table_case &case_)
+{
+ /* Create a tempfile and write many lines of text to it. */
+ named_temp_file tmp (".txt");
+ const char *filename = tmp.get_filename ();
+ FILE *f = fopen (filename, "w");
+ ASSERT_NE (f, NULL);
+ for (int i = 1; i <= 1000; i++)
+ fprintf (f, "line %i\n", i);
+ fclose (f);
+
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 1);
+ linemap_position_for_column (line_table, 127);
+
+ edit_context edit;
+
+ /* A run of consecutive lines. */
+ change_line (edit, 2);
+ change_line (edit, 3);
+ change_line (edit, 4);
+ insert_line (edit, 5);
+
+ /* A run of nearby lines, within the contextual limit. */
+ change_line (edit, 150);
+ change_line (edit, 151);
+ location_t last_loc = change_line (edit, 153);
+
+ if (last_loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Verify diff. */
+ auto_free <char *> diff = edit.generate_diff (false);
+ ASSERT_STREQ ("@@ -1,7 +1,8 @@\n"
+ " line 1\n"
+ "-line 2\n"
+ "-line 3\n"
+ "-line 4\n"
+ "+CHANGED: line 2\n"
+ "+CHANGED: line 3\n"
+ "+CHANGED: line 4\n"
+ "+INSERTED\n"
+ " line 5\n"
+ " line 6\n"
+ " line 7\n"
+ "@@ -147,10 +148,10 @@\n"
+ " line 147\n"
+ " line 148\n"
+ " line 149\n"
+ "-line 150\n"
+ "-line 151\n"
+ "+CHANGED: line 150\n"
+ "+CHANGED: line 151\n"
+ " line 152\n"
+ "-line 153\n"
+ "+CHANGED: line 153\n"
+ " line 154\n"
+ " line 155\n"
+ " line 156\n", diff);
+
+ /* Ensure tmp stays alive until this point, so that the tempfile
+ persists until after the generate_diff call. */
+ tmp.get_filename ();
+}
+
+/* Test of converting an initializer for a named field from
+ the old GCC extension to C99 syntax.
+ Exercises a shrinking replacement followed by a growing
+ replacement on the same line. */
+
+static void
+test_applying_fixits_modernize_named_init (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ .........................00000000011111111.
+ .........................12345678901234567. */
+ const char *old_content = ("/* before */\n"
+ "bar : 1,\n"
+ "/* after */\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".c", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 2);
+
+ location_t c1 = linemap_position_for_column (line_table, 1);
+ location_t c3 = linemap_position_for_column (line_table, 3);
+ location_t c8 = linemap_position_for_column (line_table, 8);
+
+ if (c8 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Replace "bar" with ".". */
+ rich_location r1 (line_table, c8);
+ r1.add_fixit_replace (source_range::from_locations (c1, c3),
+ ".");
+
+ /* Replace ":" with "bar =". */
+ rich_location r2 (line_table, c8);
+ r2.add_fixit_replace (source_range::from_locations (c8, c8),
+ "bar =");
+
+ /* The order should not matter. Do r1 then r2. */
+ {
+ edit_context edit;
+ edit.add_fixits (&r1);
+
+ /* Verify state after first replacement. */
+ {
+ auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+ /* We should now have:
+ ............00000000011.
+ ............12345678901. */
+ ASSERT_STREQ ("/* before */\n"
+ ". : 1,\n"
+ "/* after */\n",
+ new_content);
+ /* Location of the "1". */
+ ASSERT_EQ (6, edit.get_effective_column (filename, 2, 8));
+ /* Location of the ",". */
+ ASSERT_EQ (9, edit.get_effective_column (filename, 2, 11));
+ }
+
+ edit.add_fixits (&r2);
+
+ auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+ /* Verify state after second replacement.
+ ............00000000011111111.
+ ............12345678901234567. */
+ ASSERT_STREQ ("/* before */\n"
+ ". bar = 1,\n"
+ "/* after */\n",
+ new_content);
+ }
+
+ /* Try again, doing r2 then r1; the new_content should be the same. */
+ {
+ edit_context edit;
+ edit.add_fixits (&r2);
+ edit.add_fixits (&r1);
+ auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+ /*.............00000000011111111.
+ .............12345678901234567. */
+ ASSERT_STREQ ("/* before */\n"
+ ". bar = 1,\n"
+ "/* after */\n",
+ new_content);
+ }
+}
+
+/* Test of a fixit affecting a file that can't be read. */
+
+static void
+test_applying_fixits_unreadable_file ()
+{
+ const char *filename = "this-does-not-exist.txt";
+ line_table_test ltt;
+ linemap_add (line_table, LC_ENTER, false, filename, 1);
+
+ location_t loc = linemap_position_for_column (line_table, 1);
+
+ rich_location insert (line_table, loc);
+ insert.add_fixit_insert_before ("change 1");
+ insert.add_fixit_insert_before ("change 2");
+
+ edit_context edit;
+ /* Attempting to add the fixits affecting the unreadable file
+ should transition the edit from valid to invalid. */
+ ASSERT_TRUE (edit.valid_p ());
+ edit.add_fixits (&insert);
+ ASSERT_FALSE (edit.valid_p ());
+ ASSERT_EQ (NULL, edit.get_content (filename));
+ ASSERT_EQ (NULL, edit.generate_diff (false));
+}
+
+/* Verify that we gracefully handle an attempt to edit a line
+ that's beyond the end of the file. */
+
+static void
+test_applying_fixits_line_out_of_range ()
+{
+ /* Create a tempfile and write some text to it.
+ ........................00000000011111111.
+ ........................12345678901234567. */
+ const char *old_content = "One-liner file\n";
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt;
+ linemap_add (line_table, LC_ENTER, false, filename, 2);
+
+ /* Try to insert a string in line 2. */
+ location_t loc = linemap_position_for_column (line_table, 1);
+
+ rich_location insert (line_table, loc);
+ insert.add_fixit_insert_before ("change");
+
+ /* Verify that attempting the insertion puts an edit_context
+ into an invalid state. */
+ edit_context edit;
+ ASSERT_TRUE (edit.valid_p ());
+ edit.add_fixits (&insert);
+ ASSERT_FALSE (edit.valid_p ());
+ ASSERT_EQ (NULL, edit.get_content (filename));
+ ASSERT_EQ (NULL, edit.generate_diff (false));
+}
+
+/* Verify the boundary conditions of column values in fix-it
+ hints applied to edit_context instances. */
+
+static void
+test_applying_fixits_column_validation (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it.
+ ........................00000000011111111.
+ ........................12345678901234567. */
+ const char *old_content = "One-liner file\n";
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", old_content);
+ const char *filename = tmp.get_filename ();
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, filename, 1);
+
+ location_t c11 = linemap_position_for_column (line_table, 11);
+ location_t c14 = linemap_position_for_column (line_table, 14);
+ location_t c15 = linemap_position_for_column (line_table, 15);
+ location_t c16 = linemap_position_for_column (line_table, 16);
+
+ /* Verify limits of valid columns in insertion fixits. */
+
+ /* Verify inserting at the end of the line. */
+ {
+ rich_location richloc (line_table, c11);
+ richloc.add_fixit_insert_before (c15, " change");
+
+ /* Col 15 is at the end of the line, so the insertion
+ should succeed. */
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+ if (c15 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ ASSERT_STREQ ("One-liner file change\n", new_content);
+ else
+ ASSERT_EQ (NULL, new_content);
+ }
+
+ /* Verify inserting beyond the end of the line. */
+ {
+ rich_location richloc (line_table, c11);
+ richloc.add_fixit_insert_before (c16, " change");
+
+ /* Col 16 is beyond the end of the line, so the insertion
+ should fail gracefully. */
+ edit_context edit;
+ ASSERT_TRUE (edit.valid_p ());
+ edit.add_fixits (&richloc);
+ ASSERT_FALSE (edit.valid_p ());
+ ASSERT_EQ (NULL, edit.get_content (filename));
+ ASSERT_EQ (NULL, edit.generate_diff (false));
+ }
+
+ /* Verify limits of valid columns in replacement fixits. */
+
+ /* Verify replacing the end of the line. */
+ {
+ rich_location richloc (line_table, c11);
+ source_range range = source_range::from_locations (c11, c14);
+ richloc.add_fixit_replace (range, "change");
+
+ /* Col 14 is at the end of the line, so the replacement
+ should succeed. */
+ edit_context edit;
+ edit.add_fixits (&richloc);
+ auto_free <char *> new_content = edit.get_content (tmp.get_filename ());
+ if (c14 <= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ ASSERT_STREQ ("One-liner change\n", new_content);
+ else
+ ASSERT_EQ (NULL, new_content);
+ }
+
+ /* Verify going beyond the end of the line. */
+ {
+ rich_location richloc (line_table, c11);
+ source_range range = source_range::from_locations (c11, c15);
+ richloc.add_fixit_replace (range, "change");
+
+ /* Col 15 is after the end of the line, so the replacement
+ should fail; verify that the attempt fails gracefully. */
+ edit_context edit;
+ ASSERT_TRUE (edit.valid_p ());
+ edit.add_fixits (&richloc);
+ ASSERT_FALSE (edit.valid_p ());
+ ASSERT_EQ (NULL, edit.get_content (filename));
+ ASSERT_EQ (NULL, edit.generate_diff (false));
+ }
+}
+
+/* Run all of the selftests within this file. */
+
+void
+edit_context_cc_tests ()
+{
+ test_get_content ();
+ for_each_line_table_case (test_applying_fixits_insert_before);
+ for_each_line_table_case (test_applying_fixits_insert_after);
+ for_each_line_table_case (test_applying_fixits_insert_after_at_line_end);
+ for_each_line_table_case (test_applying_fixits_insert_after_failure);
+ for_each_line_table_case (test_applying_fixits_insert_containing_newline);
+ for_each_line_table_case (test_applying_fixits_growing_replace);
+ for_each_line_table_case (test_applying_fixits_shrinking_replace);
+ for_each_line_table_case (test_applying_fixits_replace_containing_newline);
+ for_each_line_table_case (test_applying_fixits_remove);
+ for_each_line_table_case (test_applying_fixits_multiple);
+ for_each_line_table_case (test_applying_fixits_multiple_lines);
+ for_each_line_table_case (test_applying_fixits_modernize_named_init);
+ test_applying_fixits_unreadable_file ();
+ test_applying_fixits_line_out_of_range ();
+ for_each_line_table_case (test_applying_fixits_column_validation);
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/support/cpp/gcc/edit-context.h b/support/cpp/gcc/edit-context.h
new file mode 100644
index 000000000..383c181cc
--- /dev/null
+++ b/support/cpp/gcc/edit-context.h
@@ -0,0 +1,67 @@
+/* Determining the results of applying fix-it hints.
+ Copyright (C) 2016-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_EDIT_CONTEXT_H
+#define GCC_EDIT_CONTEXT_H
+
+#include "typed-splay-tree.h"
+
+class edit_context;
+class edited_file;
+
+/* A set of changes to the source code.
+
+ The changes are "atomic" - if any changes can't be applied,
+ none of them can be (tracked by the m_valid flag).
+ Similarly, attempts to add the changes from a rich_location flagged
+ as containing invalid changes mean that the whole of the edit_context
+ is flagged as invalid.
+
+ A complication here is that fix-its are expressed relative to coordinates
+ in the files when they were parsed, before any changes have been made, and
+ so if there's more that one fix-it to be applied, we have to adjust
+ later fix-its to allow for the changes made by earlier ones. This
+ is done by the various "get_effective_column" methods. */
+
+class edit_context
+{
+ public:
+ edit_context ();
+
+ bool valid_p () const { return m_valid; }
+
+ void add_fixits (rich_location *richloc);
+
+ char *get_content (const char *filename);
+
+ int get_effective_column (const char *filename, int line, int column);
+
+ char *generate_diff (bool show_filenames);
+ void print_diff (pretty_printer *pp, bool show_filenames);
+
+ private:
+ bool apply_fixit (const fixit_hint *hint);
+ edited_file *get_file (const char *filename);
+ edited_file &get_or_insert_file (const char *filename);
+
+ bool m_valid;
+ typed_splay_tree<const char *, edited_file *> m_files;
+};
+
+#endif /* GCC_EDIT_CONTEXT_H. */
diff --git a/support/cpp/gcc/emit-rtl.h b/support/cpp/gcc/emit-rtl.h
new file mode 100644
index 000000000..d11f6c59f
--- /dev/null
+++ b/support/cpp/gcc/emit-rtl.h
@@ -0,0 +1,548 @@
+/* Exported functions from emit-rtl.cc
+ Copyright (C) 2004-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/>. */
+
+#if 0 // sdcpp ndef GCC_EMIT_RTL_H
+#define GCC_EMIT_RTL_H
+
+class temp_slot;
+typedef class temp_slot *temp_slot_p;
+class predefined_function_abi;
+namespace rtl_ssa { class function_info; }
+
+/* Information mainlined about RTL representation of incoming arguments. */
+struct GTY(()) incoming_args {
+ /* Number of bytes of args popped by function being compiled on its return.
+ Zero if no bytes are to be popped.
+ May affect compilation of return insn or of function epilogue. */
+ poly_int64_pod pops_args;
+
+ /* If function's args have a fixed size, this is that size, in bytes.
+ Otherwise, it is -1.
+ May affect compilation of return insn or of function epilogue. */
+ poly_int64_pod size;
+
+ /* # bytes the prologue should push and pretend that the caller pushed them.
+ The prologue must do this, but only if parms can be passed in
+ registers. */
+ int pretend_args_size;
+
+ /* This is the offset from the arg pointer to the place where the first
+ anonymous arg can be found, if there is one. */
+ rtx arg_offset_rtx;
+
+ /* Quantities of various kinds of registers
+ used for the current function's args. */
+ CUMULATIVE_ARGS info;
+
+ /* The arg pointer hard register, or the pseudo into which it was copied. */
+ rtx internal_arg_pointer;
+};
+
+
+/* Datastructures maintained for currently processed function in RTL form. */
+struct GTY(()) rtl_data {
+ void init_stack_alignment ();
+
+ struct expr_status expr;
+ struct emit_status emit;
+ struct varasm_status varasm;
+ struct incoming_args args;
+ struct function_subsections subsections;
+ struct rtl_eh eh;
+
+ /* The ABI of the function, i.e. the interface it presents to its callers.
+ This is the ABI that should be queried to see which registers the
+ function needs to save before it uses them.
+
+ Other functions (including those called by this function) might use
+ different ABIs. */
+ const predefined_function_abi *GTY((skip)) abi;
+
+ rtl_ssa::function_info *GTY((skip)) ssa;
+
+ /* For function.cc */
+
+ /* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
+ defined, the needed space is pushed by the prologue. */
+ poly_int64_pod outgoing_args_size;
+
+ /* If nonzero, an RTL expression for the location at which the current
+ function returns its result. If the current function returns its
+ result in a register, current_function_return_rtx will always be
+ the hard register containing the result. */
+ rtx return_rtx;
+
+ /* Vector of initial-value pairs. Each pair consists of a pseudo
+ register of approprite mode that stores the initial value a hard
+ register REGNO, and that hard register itself. */
+ /* ??? This could be a VEC but there is currently no way to define an
+ opaque VEC type. */
+ struct initial_value_struct *hard_reg_initial_vals;
+
+ /* A variable living at the top of the frame that holds a known value.
+ Used for detecting stack clobbers. */
+ tree stack_protect_guard;
+
+ /* The __stack_chk_guard variable or expression holding the stack
+ protector canary value. */
+ tree stack_protect_guard_decl;
+
+ /* List (chain of INSN_LIST) of labels heading the current handlers for
+ nonlocal gotos. */
+ rtx_insn_list *x_nonlocal_goto_handler_labels;
+
+ /* Label that will go on function epilogue.
+ Jumping to this label serves as a "return" instruction
+ on machines which require execution of the epilogue on all returns. */
+ rtx_code_label *x_return_label;
+
+ /* Label that will go on the end of function epilogue.
+ Jumping to this label serves as a "naked return" instruction
+ on machines which require execution of the epilogue on all returns. */
+ rtx_code_label *x_naked_return_label;
+
+ /* List (chain of EXPR_LISTs) of all stack slots in this function.
+ Made for the sake of unshare_all_rtl. */
+ vec<rtx, va_gc> *x_stack_slot_list;
+
+ /* List of empty areas in the stack frame. */
+ class frame_space *frame_space_list;
+
+ /* Place after which to insert the tail_recursion_label if we need one. */
+ rtx_note *x_stack_check_probe_note;
+
+ /* Location at which to save the argument pointer if it will need to be
+ referenced. There are two cases where this is done: if nonlocal gotos
+ exist, or if vars stored at an offset from the argument pointer will be
+ needed by inner routines. */
+ rtx x_arg_pointer_save_area;
+
+ /* Dynamic Realign Argument Pointer used for realigning stack. */
+ rtx drap_reg;
+
+ /* Offset to end of allocated area of stack frame.
+ If stack grows down, this is the address of the last stack slot allocated.
+ If stack grows up, this is the address for the next slot. */
+ poly_int64_pod x_frame_offset;
+
+ /* Insn after which register parms and SAVE_EXPRs are born, if nonopt. */
+ rtx_insn *x_parm_birth_insn;
+
+ /* List of all used temporaries allocated, by level. */
+ vec<temp_slot_p, va_gc> *x_used_temp_slots;
+
+ /* List of available temp slots. */
+ class temp_slot *x_avail_temp_slots;
+
+ /* Current nesting level for temporaries. */
+ int x_temp_slot_level;
+
+ /* The largest alignment needed on the stack, including requirement
+ for outgoing stack alignment. */
+ unsigned int stack_alignment_needed;
+
+ /* Preferred alignment of the end of stack frame, which is preferred
+ to call other functions. */
+ unsigned int preferred_stack_boundary;
+
+ /* The minimum alignment of parameter stack. */
+ unsigned int parm_stack_boundary;
+
+ /* The largest alignment of slot allocated on the stack. */
+ unsigned int max_used_stack_slot_alignment;
+
+ /* The stack alignment estimated before reload, with consideration of
+ following factors:
+ 1. Alignment of local stack variables (max_used_stack_slot_alignment)
+ 2. Alignment requirement to call other functions
+ (preferred_stack_boundary)
+ 3. Alignment of non-local stack variables but might be spilled in
+ local stack. */
+ unsigned int stack_alignment_estimated;
+
+ /* How many NOP insns to place at each function entry by default. */
+ unsigned short patch_area_size;
+
+ /* How far the real asm entry point is into this area. */
+ unsigned short patch_area_entry;
+
+ /* For reorg. */
+
+ /* Nonzero if function being compiled called builtin_return_addr or
+ builtin_frame_address with nonzero count. */
+ bool accesses_prior_frames;
+
+ /* Nonzero if the function calls __builtin_eh_return. */
+ bool calls_eh_return;
+
+ /* Nonzero if function saves all registers, e.g. if it has a nonlocal
+ label that can reach the exit block via non-exceptional paths. */
+ bool saves_all_registers;
+
+ /* Nonzero if function being compiled has nonlocal gotos to parent
+ function. */
+ bool has_nonlocal_goto;
+
+ /* Nonzero if function being compiled has an asm statement. */
+ bool has_asm_statement;
+
+ /* This bit is used by the exception handling logic. It is set if all
+ calls (if any) are sibling calls. Such functions do not have to
+ have EH tables generated, as they cannot throw. A call to such a
+ function, however, should be treated as throwing if any of its callees
+ can throw. */
+ bool all_throwers_are_sibcalls;
+
+ /* Nonzero if stack limit checking should be enabled in the current
+ function. */
+ bool limit_stack;
+
+ /* Nonzero if profiling code should be generated. */
+ bool profile;
+
+ /* Nonzero if the current function uses the constant pool. */
+ bool uses_const_pool;
+
+ /* Nonzero if the current function uses pic_offset_table_rtx. */
+ bool uses_pic_offset_table;
+
+ /* Nonzero if the current function needs an lsda for exception handling. */
+ bool uses_eh_lsda;
+
+ /* Set when the tail call has been produced. */
+ bool tail_call_emit;
+
+ /* Nonzero if code to initialize arg_pointer_save_area has been emitted. */
+ bool arg_pointer_save_area_init;
+
+ /* Nonzero if current function must be given a frame pointer.
+ Set in reload1.cc or lra-eliminations.cc if anything is allocated
+ on the stack there. */
+ bool frame_pointer_needed;
+
+ /* When set, expand should optimize for speed. */
+ bool maybe_hot_insn_p;
+
+ /* Nonzero if function stack realignment is needed. This flag may be
+ set twice: before and after reload. It is set before reload wrt
+ stack alignment estimation before reload. It will be changed after
+ reload if by then criteria of stack realignment is different.
+ The value set after reload is the accurate one and is finalized. */
+ bool stack_realign_needed;
+
+ /* Nonzero if function stack realignment is tried. This flag is set
+ only once before reload. It affects register elimination. This
+ is used to generate DWARF debug info for stack variables. */
+ bool stack_realign_tried;
+
+ /* Nonzero if function being compiled needs dynamic realigned
+ argument pointer (drap) if stack needs realigning. */
+ bool need_drap;
+
+ /* Nonzero if function stack realignment estimation is done, namely
+ stack_realign_needed flag has been set before reload wrt estimated
+ stack alignment info. */
+ bool stack_realign_processed;
+
+ /* Nonzero if function stack realignment has been finalized, namely
+ stack_realign_needed flag has been set and finalized after reload. */
+ bool stack_realign_finalized;
+
+ /* True if dbr_schedule has already been called for this function. */
+ bool dbr_scheduled_p;
+
+ /* True if current function cannot throw. Unlike
+ TREE_NOTHROW (current_function_decl) it is set even for overwritable
+ function where currently compiled version of it is nothrow. */
+ bool nothrow;
+
+ /* True if we performed shrink-wrapping for the current function. */
+ bool shrink_wrapped;
+
+ /* True if we performed shrink-wrapping for separate components for
+ the current function. */
+ bool shrink_wrapped_separate;
+
+ /* Nonzero if function being compiled doesn't modify the stack pointer
+ (ignoring the prologue and epilogue). This is only valid after
+ pass_stack_ptr_mod has run. */
+ bool sp_is_unchanging;
+
+ /* True if the stack pointer is clobbered by asm statement. */
+ bool sp_is_clobbered_by_asm;
+
+ /* Nonzero if function being compiled doesn't contain any calls
+ (ignoring the prologue and epilogue). This is set prior to
+ register allocation in IRA and is valid for the remaining
+ compiler passes. */
+ bool is_leaf;
+
+ /* Nonzero if the function being compiled is a leaf function which only
+ uses leaf registers. This is valid after reload (specifically after
+ sched2) and is useful only if the port defines LEAF_REGISTERS. */
+ bool uses_only_leaf_regs;
+
+ /* Nonzero if the function being compiled has undergone hot/cold partitioning
+ (under flag_reorder_blocks_and_partition) and has at least one cold
+ block. */
+ bool has_bb_partition;
+
+ /* Nonzero if the function being compiled has completed the bb reordering
+ pass. */
+ bool bb_reorder_complete;
+
+ /* Like regs_ever_live, but 1 if a reg is set or clobbered from an
+ asm. Unlike regs_ever_live, elements of this array corresponding
+ to eliminable regs (like the frame pointer) are set if an asm
+ sets them. */
+ HARD_REG_SET asm_clobbers;
+
+ /* All hard registers that need to be zeroed at the return of the routine. */
+ HARD_REG_SET must_be_zero_on_return;
+
+ /* The highest address seen during shorten_branches. */
+ int max_insn_address;
+};
+
+#define return_label (crtl->x_return_label)
+#define naked_return_label (crtl->x_naked_return_label)
+#define stack_slot_list (crtl->x_stack_slot_list)
+#define parm_birth_insn (crtl->x_parm_birth_insn)
+#define frame_offset (crtl->x_frame_offset)
+#define stack_check_probe_note (crtl->x_stack_check_probe_note)
+#define arg_pointer_save_area (crtl->x_arg_pointer_save_area)
+#define used_temp_slots (crtl->x_used_temp_slots)
+#define avail_temp_slots (crtl->x_avail_temp_slots)
+#define temp_slot_level (crtl->x_temp_slot_level)
+#define nonlocal_goto_handler_labels (crtl->x_nonlocal_goto_handler_labels)
+#define frame_pointer_needed (crtl->frame_pointer_needed)
+#define stack_realign_fp (crtl->stack_realign_needed && !crtl->need_drap)
+#define stack_realign_drap (crtl->stack_realign_needed && crtl->need_drap)
+
+extern GTY(()) struct rtl_data x_rtl;
+
+/* Accessor to RTL datastructures. We keep them statically allocated now since
+ we never keep multiple functions. For threaded compiler we might however
+ want to do differently. */
+#define crtl (&x_rtl)
+
+/* Return whether two MEM_ATTRs are equal. */
+bool mem_attrs_eq_p (const class mem_attrs *, const class mem_attrs *);
+
+/* Set the alias set of MEM to SET. */
+extern void set_mem_alias_set (rtx, alias_set_type);
+
+/* Set the alignment of MEM to ALIGN bits. */
+extern void set_mem_align (rtx, unsigned int);
+
+/* Set the address space of MEM to ADDRSPACE. */
+extern void set_mem_addr_space (rtx, addr_space_t);
+
+/* Set the expr for MEM to EXPR. */
+extern void set_mem_expr (rtx, tree);
+
+/* Set the offset for MEM to OFFSET. */
+extern void set_mem_offset (rtx, poly_int64);
+
+/* Clear the offset recorded for MEM. */
+extern void clear_mem_offset (rtx);
+
+/* Set the size for MEM to SIZE. */
+extern void set_mem_size (rtx, poly_int64);
+
+/* Clear the size recorded for MEM. */
+extern void clear_mem_size (rtx);
+
+/* Set the attributes for MEM appropriate for a spill slot. */
+extern void set_mem_attrs_for_spill (rtx);
+extern tree get_spill_slot_decl (bool);
+
+/* Return a memory reference like MEMREF, but with its address changed to
+ ADDR. The caller is asserting that the actual piece of memory pointed
+ to is the same, just the form of the address is being changed, such as
+ by putting something into a register. */
+extern rtx replace_equiv_address (rtx, rtx, bool = false);
+
+/* Likewise, but the reference is not required to be valid. */
+extern rtx replace_equiv_address_nv (rtx, rtx, bool = false);
+
+extern rtx gen_blockage (void);
+extern rtvec gen_rtvec (int, ...);
+extern rtx copy_insn_1 (rtx);
+extern rtx copy_insn (rtx);
+extern rtx_insn *copy_delay_slot_insn (rtx_insn *);
+extern rtx gen_int_mode (poly_int64, machine_mode);
+extern rtx_insn *emit_copy_of_insn_after (rtx_insn *, rtx_insn *);
+extern void set_reg_attrs_from_value (rtx, rtx);
+extern void set_reg_attrs_for_parm (rtx, rtx);
+extern void set_reg_attrs_for_decl_rtl (tree t, rtx x);
+extern void adjust_reg_mode (rtx, machine_mode);
+extern int mem_expr_equal_p (const_tree, const_tree);
+extern rtx gen_int_shift_amount (machine_mode, poly_int64);
+
+extern bool need_atomic_barrier_p (enum memmodel, bool);
+
+/* Return the current sequence. */
+
+static inline struct sequence_stack *
+get_current_sequence (void)
+{
+ return &crtl->emit.seq;
+}
+
+/* Return the outermost sequence. */
+
+static inline struct sequence_stack *
+get_topmost_sequence (void)
+{
+ struct sequence_stack *seq, *top;
+
+ seq = get_current_sequence ();
+ do
+ {
+ top = seq;
+ seq = seq->next;
+ } while (seq);
+ return top;
+}
+
+/* Return the first insn of the current sequence or current function. */
+
+static inline rtx_insn *
+get_insns (void)
+{
+ return get_current_sequence ()->first;
+}
+
+/* Specify a new insn as the first in the chain. */
+
+static inline void
+set_first_insn (rtx_insn *insn)
+{
+ gcc_checking_assert (!insn || !PREV_INSN (insn));
+ get_current_sequence ()->first = insn;
+}
+
+/* Return the last insn emitted in current sequence or current function. */
+
+static inline rtx_insn *
+get_last_insn (void)
+{
+ return get_current_sequence ()->last;
+}
+
+/* Specify a new insn as the last in the chain. */
+
+static inline void
+set_last_insn (rtx_insn *insn)
+{
+ gcc_checking_assert (!insn || !NEXT_INSN (insn));
+ get_current_sequence ()->last = insn;
+}
+
+/* Return a number larger than any instruction's uid in this function. */
+
+static inline int
+get_max_uid (void)
+{
+ return crtl->emit.x_cur_insn_uid;
+}
+
+extern bool valid_for_const_vector_p (machine_mode, rtx);
+extern rtx gen_const_vec_duplicate (machine_mode, rtx);
+extern rtx gen_vec_duplicate (machine_mode, rtx);
+
+extern rtx gen_const_vec_series (machine_mode, rtx, rtx);
+extern rtx gen_vec_series (machine_mode, rtx, rtx);
+
+extern void set_decl_incoming_rtl (tree, rtx, bool);
+
+/* Return a memory reference like MEMREF, but with its mode changed
+ to MODE and its address changed to ADDR.
+ (VOIDmode means don't change the mode.
+ NULL for ADDR means don't change the address.) */
+extern rtx change_address (rtx, machine_mode, rtx);
+
+/* Return a memory reference like MEMREF, but with its mode changed
+ to MODE and its address offset by OFFSET bytes. */
+#define adjust_address(MEMREF, MODE, OFFSET) \
+ adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 0, 0)
+
+/* Likewise, but the reference is not required to be valid. */
+#define adjust_address_nv(MEMREF, MODE, OFFSET) \
+ adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1, 0, 0)
+
+/* Return a memory reference like MEMREF, but with its mode changed
+ to MODE and its address offset by OFFSET bytes. Assume that it's
+ for a bitfield and conservatively drop the underlying object if we
+ cannot be sure to stay within its bounds. */
+#define adjust_bitfield_address(MEMREF, MODE, OFFSET) \
+ adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 1, 0)
+
+/* As for adjust_bitfield_address, but specify that the width of
+ BLKmode accesses is SIZE bytes. */
+#define adjust_bitfield_address_size(MEMREF, MODE, OFFSET, SIZE) \
+ adjust_address_1 (MEMREF, MODE, OFFSET, 1, 1, 1, SIZE)
+
+/* Likewise, but the reference is not required to be valid. */
+#define adjust_bitfield_address_nv(MEMREF, MODE, OFFSET) \
+ adjust_address_1 (MEMREF, MODE, OFFSET, 0, 1, 1, 0)
+
+/* Return a memory reference like MEMREF, but with its mode changed
+ to MODE and its address changed to ADDR, which is assumed to be
+ increased by OFFSET bytes from MEMREF. */
+#define adjust_automodify_address(MEMREF, MODE, ADDR, OFFSET) \
+ adjust_automodify_address_1 (MEMREF, MODE, ADDR, OFFSET, 1)
+
+/* Likewise, but the reference is not required to be valid. */
+#define adjust_automodify_address_nv(MEMREF, MODE, ADDR, OFFSET) \
+ adjust_automodify_address_1 (MEMREF, MODE, ADDR, OFFSET, 0)
+
+extern rtx adjust_address_1 (rtx, machine_mode, poly_int64, int, int,
+ int, poly_int64);
+extern rtx adjust_automodify_address_1 (rtx, machine_mode, rtx,
+ poly_int64, int);
+
+/* Return a memory reference like MEMREF, but whose address is changed by
+ adding OFFSET, an RTX, to it. POW2 is the highest power of two factor
+ known to be in OFFSET (possibly 1). */
+extern rtx offset_address (rtx, rtx, unsigned HOST_WIDE_INT);
+
+/* Given REF, a MEM, and T, either the type of X or the expression
+ corresponding to REF, set the memory attributes. OBJECTP is nonzero
+ if we are making a new object of this type. */
+extern void set_mem_attributes (rtx, tree, int);
+
+/* Similar, except that BITPOS has not yet been applied to REF, so if
+ we alter MEM_OFFSET according to T then we should subtract BITPOS
+ expecting that it'll be added back in later. */
+extern void set_mem_attributes_minus_bitpos (rtx, tree, int, poly_int64);
+
+/* Return OFFSET if XEXP (MEM, 0) - OFFSET is known to be ALIGN
+ bits aligned for 0 <= OFFSET < ALIGN / BITS_PER_UNIT, or
+ -1 if not known. */
+extern int get_mem_align_offset (rtx, unsigned int);
+
+/* Return a memory reference like MEMREF, but with its mode widened to
+ MODE and adjusted by OFFSET. */
+extern rtx widen_memory_access (rtx, machine_mode, poly_int64);
+
+extern void maybe_set_max_label_num (rtx_code_label *x);
+
+#endif /* GCC_EMIT_RTL_H */
diff --git a/support/cpp/gcc/errors.cc b/support/cpp/gcc/errors.cc
new file mode 100644
index 000000000..766e12e60
--- /dev/null
+++ b/support/cpp/gcc/errors.cc
@@ -0,0 +1,134 @@
+/* Basic error reporting routines.
+ 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.
+
+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/>. */
+
+/* warning, error, and fatal. These definitions are suitable for use
+ in the generator programs; the compiler has a more elaborate suite
+ of diagnostic printers, found in diagnostic.cc. */
+
+#ifdef HOST_GENERATOR_FILE
+#include "config.h"
+#define GENERATOR_FILE 1
+#else
+#include "bconfig.h"
+#endif
+#include "system.h"
+#include "errors.h"
+
+/* Set this to argv[0] at the beginning of main. */
+
+const char *progname;
+
+/* Starts out 0, set to 1 if error is called. */
+
+int have_error = 0;
+
+/* Print a warning message - output produced, but there may be problems. */
+
+void
+warning (const char *format, ...)
+{
+ va_list ap;
+
+ va_start (ap, format);
+ fprintf (stderr, "%s: warning: ", progname);
+ vfprintf (stderr, format, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+}
+
+
+/* Print an error message - we keep going but the output is unusable. */
+
+void
+error (const char *format, ...)
+{
+ va_list ap;
+
+ va_start (ap, format);
+ fprintf (stderr, "%s: ", progname);
+ vfprintf (stderr, format, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+
+ have_error = 1;
+}
+
+
+/* Fatal error - terminate execution immediately. Does not return. */
+
+void
+fatal (const char *format, ...)
+{
+ va_list ap;
+
+ va_start (ap, format);
+ fprintf (stderr, "%s: ", progname);
+ vfprintf (stderr, format, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+ exit (FATAL_EXIT_CODE);
+}
+
+/* Similar, but say we got an internal error. */
+
+void
+internal_error (const char *format, ...)
+{
+ va_list ap;
+
+ va_start (ap, format);
+ fprintf (stderr, "%s: Internal error: ", progname);
+ vfprintf (stderr, format, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+ exit (FATAL_EXIT_CODE);
+}
+
+/* Given a partial pathname as input, return another pathname that
+ shares no directory elements with the pathname of __FILE__. This
+ is used by fancy_abort() to print `Internal compiler error in expr.cc'
+ instead of `Internal compiler error in ../../GCC/gcc/expr.cc'. This
+ version is meant to be used for the gen* programs and therefor need not
+ handle subdirectories. */
+
+const char *
+trim_filename (const char *name)
+{
+ static const char this_file[] = __FILE__;
+ const char *p = name, *q = this_file;
+
+ /* Skip any parts the two filenames have in common. */
+ while (*p == *q && *p != 0 && *q != 0)
+ p++, q++;
+
+ /* Now go backwards until the previous directory separator. */
+ while (p > name && !IS_DIR_SEPARATOR (p[-1]))
+ p--;
+
+ return p;
+}
+
+/* "Fancy" abort. Reports where in the compiler someone gave up.
+ This file is used only by build programs, so we're not as polite as
+ the version in diagnostic.cc. */
+void
+fancy_abort (const char *file, int line, const char *func)
+{
+ internal_error ("abort in %s, at %s:%d", func, trim_filename (file), line);
+}
diff --git a/support/cpp/gcc/errors.h b/support/cpp/gcc/errors.h
new file mode 100644
index 000000000..994d9c20b
--- /dev/null
+++ b/support/cpp/gcc/errors.h
@@ -0,0 +1,40 @@
+/* Basic error reporting routines.
+ 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.
+
+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/>. */
+
+/* warning, error, and fatal. These definitions are suitable for use
+ in the generator programs; eventually we would like to use them in
+ cc1 too, but that's a longer term project.
+
+ N.B. We cannot presently use ATTRIBUTE_PRINTF with these functions,
+ because they can be extended with additional format specifiers which
+ GCC does not know about. */
+
+#ifndef GCC_ERRORS_H
+#define GCC_ERRORS_H
+
+extern void warning (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
+extern void error (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
+extern void fatal (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
+extern void internal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF_1 ATTRIBUTE_COLD;
+extern const char *trim_filename (const char *);
+
+extern int have_error;
+extern const char *progname;
+
+#endif /* ! GCC_ERRORS_H */
diff --git a/support/cpp/gcc/escaped_string.h b/support/cpp/gcc/escaped_string.h
new file mode 100644
index 000000000..fd9a6fc29
--- /dev/null
+++ b/support/cpp/gcc/escaped_string.h
@@ -0,0 +1,43 @@
+/* Shared escaped string class.
+ 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.
+
+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_ESCAPED_STRING_H
+#define GCC_ESCAPED_STRING_H
+
+#include <cstdlib>
+
+/* A class to handle converting a string that might contain
+ control characters, (eg newline, form-feed, etc), into one
+ in which contains escape sequences instead. */
+
+class escaped_string
+{
+ public:
+ escaped_string () { m_owned = false; m_str = NULL; };
+ ~escaped_string () { if (m_owned) free (m_str); }
+ operator const char *() const { return m_str; }
+ void escape (const char *);
+ private:
+ escaped_string(const escaped_string&) {}
+ escaped_string& operator=(const escaped_string&) { return *this; }
+ char *m_str;
+ bool m_owned;
+};
+
+#endif /* ! GCC_ESCAPED_STRING_H */
diff --git a/support/cpp/gcc/except.h b/support/cpp/gcc/except.h
new file mode 100644
index 000000000..b7fd0f419
--- /dev/null
+++ b/support/cpp/gcc/except.h
@@ -0,0 +1,334 @@
+/* Exception Handling interface routines.
+ Copyright (C) 1996-2022 Free Software Foundation, Inc.
+ Contributed by Mike Stump <mrs@cygnus.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.
+
+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/>. */
+
+/* No include guards here, but define an include file marker anyway, so
+ that the compiler can keep track of where this file is included. This
+ is e.g. used to avoid including this file in front-end specific files. */
+#ifndef GCC_EXCEPT_H
+#define GCC_EXCEPT_H
+
+
+struct function;
+struct eh_region_d;
+
+/* The type of an exception region. */
+enum eh_region_type
+{
+ /* CLEANUP regions implement e.g. destructors run when exiting a block.
+ They can be generated from both GIMPLE_TRY_FINALLY and GIMPLE_TRY_CATCH
+ nodes. It is expected by the runtime that cleanup regions will *not*
+ resume normal program flow, but will continue propagation of the
+ exception. */
+ ERT_CLEANUP,
+
+ /* TRY regions implement catching an exception. The list of types associated
+ with the attached catch handlers is examined in order by the runtime and
+ control is transferred to the appropriate handler. Note that a NULL type
+ list is a catch-all handler, and that it will catch *all* exceptions
+ including those originating from a different language. */
+ ERT_TRY,
+
+ /* ALLOWED_EXCEPTIONS regions implement exception filtering, e.g. the
+ throw(type-list) specification that can be added to C++ functions.
+ The runtime examines the thrown exception vs the type list, and if
+ the exception does not match, transfers control to the handler. The
+ normal handler for C++ calls __cxa_call_unexpected. */
+ ERT_ALLOWED_EXCEPTIONS,
+
+ /* MUST_NOT_THROW regions prevent all exceptions from propagating. This
+ region type is used in C++ to surround destructors being run inside a
+ CLEANUP region. This differs from an ALLOWED_EXCEPTIONS region with
+ an empty type list in that the runtime is prepared to terminate the
+ program directly. We only generate code for MUST_NOT_THROW regions
+ along control paths that are already handling an exception within the
+ current function. */
+ ERT_MUST_NOT_THROW
+};
+
+
+/* A landing pad for a given exception region. Any transfer of control
+ from the EH runtime to the function happens at a landing pad. */
+
+struct GTY(()) eh_landing_pad_d
+{
+ /* The linked list of all landing pads associated with the region. */
+ struct eh_landing_pad_d *next_lp;
+
+ /* The region with which this landing pad is associated. */
+ struct eh_region_d *region;
+
+ /* At the gimple level, the location to which control will be transferred
+ for this landing pad. There can be both EH and normal edges into the
+ block containing the post-landing-pad label. */
+ tree post_landing_pad;
+
+ /* At the rtl level, the location to which the runtime will transfer
+ control. This differs from the post-landing-pad in that the target's
+ EXCEPTION_RECEIVER pattern will be expanded here, as well as other
+ bookkeeping specific to exceptions. There must not be normal edges
+ into the block containing the landing-pad label. */
+ rtx_code_label *landing_pad;
+
+ /* The index of this landing pad within fun->eh->lp_array. */
+ int index;
+};
+
+/* A catch handler associated with an ERT_TRY region. */
+
+struct GTY(()) eh_catch_d
+{
+ /* The double-linked list of all catch handlers for the region. */
+ struct eh_catch_d *next_catch;
+ struct eh_catch_d *prev_catch;
+
+ /* A TREE_LIST of runtime type objects that this catch handler
+ will catch, or NULL if all exceptions are caught. */
+ tree type_list;
+
+ /* A TREE_LIST of INTEGER_CSTs that correspond to the type_list entries,
+ having been mapped by assign_filter_values. These integers are to be
+ compared against the __builtin_eh_filter value. */
+ tree filter_list;
+
+ /* The code that should be executed if this catch handler matches the
+ thrown exception. This label is only maintained until
+ pass_lower_eh_dispatch, at which point it is cleared. */
+ tree label;
+};
+
+/* Describes one exception region. */
+
+struct GTY(()) eh_region_d
+{
+ /* The immediately surrounding region. */
+ struct eh_region_d *outer;
+
+ /* The list of immediately contained regions. */
+ struct eh_region_d *inner;
+ struct eh_region_d *next_peer;
+
+ /* The index of this region within fun->eh->region_array. */
+ int index;
+
+ /* Each region does exactly one thing. */
+ enum eh_region_type type;
+
+ /* Holds the action to perform based on the preceding type. */
+ union eh_region_u {
+ struct eh_region_u_try {
+ /* The double-linked list of all catch handlers for this region. */
+ struct eh_catch_d *first_catch;
+ struct eh_catch_d *last_catch;
+ } GTY ((tag ("ERT_TRY"))) eh_try;
+
+ struct eh_region_u_allowed {
+ /* A TREE_LIST of runtime type objects allowed to pass. */
+ tree type_list;
+ /* The code that should be executed if the thrown exception does
+ not match the type list. This label is only maintained until
+ pass_lower_eh_dispatch, at which point it is cleared. */
+ tree label;
+ /* The integer that will be passed by the runtime to signal that
+ we should execute the code at LABEL. This integer is assigned
+ by assign_filter_values and is to be compared against the
+ __builtin_eh_filter value. */
+ int filter;
+ } GTY ((tag ("ERT_ALLOWED_EXCEPTIONS"))) allowed;
+
+ struct eh_region_u_must_not_throw {
+ /* A function decl to be invoked if this region is actually reachable
+ from within the function, rather than implementable from the runtime.
+ The normal way for this to happen is for there to be a CLEANUP region
+ contained within this MUST_NOT_THROW region. Note that if the
+ runtime handles the MUST_NOT_THROW region, we have no control over
+ what termination function is called; it will be decided by the
+ personality function in effect for this CIE. */
+ tree failure_decl;
+ /* The location assigned to the call of FAILURE_DECL, if expanded. */
+ location_t failure_loc;
+ } GTY ((tag ("ERT_MUST_NOT_THROW"))) must_not_throw;
+ } GTY ((desc ("%0.type"))) u;
+
+ /* The list of landing pads associated with this region. */
+ struct eh_landing_pad_d *landing_pads;
+
+ /* EXC_PTR and FILTER values copied from the runtime for this region.
+ Each region gets its own psuedos so that if there are nested exceptions
+ we do not overwrite the values of the first exception. */
+ rtx exc_ptr_reg, filter_reg;
+
+ /* True if this region should use __cxa_end_cleanup instead
+ of _Unwind_Resume. */
+ bool use_cxa_end_cleanup;
+};
+
+typedef struct eh_landing_pad_d *eh_landing_pad;
+typedef struct eh_catch_d *eh_catch;
+typedef struct eh_region_d *eh_region;
+
+
+
+
+/* The exception status for each function. */
+
+struct GTY(()) eh_status
+{
+ /* The tree of all regions for this function. */
+ eh_region region_tree;
+
+ /* The same information as an indexable array. */
+ vec<eh_region, va_gc> *region_array;
+
+ /* The landing pads as an indexable array. */
+ vec<eh_landing_pad, va_gc> *lp_array;
+
+ /* At the gimple level, a mapping from gimple statement to landing pad
+ or must-not-throw region. See record_stmt_eh_region. */
+ hash_map<gimple *, int> *GTY(()) throw_stmt_table;
+
+ /* All of the runtime type data used by the function. These objects
+ are emitted to the lang-specific-data-area for the function. */
+ vec<tree, va_gc> *ttype_data;
+
+ /* The table of all action chains. These encode the eh_region tree in
+ a compact form for use by the runtime, and is also emitted to the
+ lang-specific-data-area. Note that the ARM EABI uses a different
+ format for the encoding than all other ports. */
+ union eh_status_u {
+ vec<tree, va_gc> *GTY((tag ("1"))) arm_eabi;
+ vec<uchar, va_gc> *GTY((tag ("0"))) other;
+ } GTY ((desc ("targetm.arm_eabi_unwinder"))) ehspec_data;
+};
+
+
+/* Invokes CALLBACK for every exception handler label. Only used by old
+ loop hackery; should not be used by new code. */
+extern void for_each_eh_label (void (*) (rtx));
+
+extern void init_eh_for_function (void);
+
+extern void remove_eh_landing_pad (eh_landing_pad);
+extern void remove_eh_handler (eh_region);
+extern void remove_unreachable_eh_regions (sbitmap);
+
+extern bool current_function_has_exception_handlers (void);
+extern void output_function_exception_table (int);
+
+extern rtx expand_builtin_eh_pointer (tree);
+extern rtx expand_builtin_eh_filter (tree);
+extern rtx expand_builtin_eh_copy_values (tree);
+extern void expand_builtin_unwind_init (void);
+extern rtx expand_builtin_eh_return_data_regno (tree);
+extern rtx expand_builtin_extract_return_addr (tree);
+extern void expand_builtin_init_dwarf_reg_sizes (tree);
+extern rtx expand_builtin_frob_return_addr (tree);
+extern rtx expand_builtin_dwarf_sp_column (void);
+extern void expand_builtin_eh_return (tree, tree);
+extern void expand_eh_return (void);
+extern rtx expand_builtin_extend_pointer (tree);
+
+typedef tree (*duplicate_eh_regions_map) (tree, void *);
+extern hash_map<void *, void *> *duplicate_eh_regions
+ (struct function *, eh_region, int, duplicate_eh_regions_map, void *);
+
+extern void sjlj_emit_function_exit_after (rtx_insn *);
+extern void update_sjlj_context (void);
+
+extern eh_region gen_eh_region_cleanup (eh_region);
+extern eh_region gen_eh_region_try (eh_region);
+extern eh_region gen_eh_region_allowed (eh_region, tree);
+extern eh_region gen_eh_region_must_not_throw (eh_region);
+
+extern eh_catch gen_eh_region_catch (eh_region, tree);
+extern eh_landing_pad gen_eh_landing_pad (eh_region);
+
+extern eh_region get_eh_region_from_number_fn (struct function *, int);
+extern eh_region get_eh_region_from_number (int);
+extern eh_landing_pad get_eh_landing_pad_from_number_fn (struct function*,int);
+extern eh_landing_pad get_eh_landing_pad_from_number (int);
+extern eh_region get_eh_region_from_lp_number_fn (struct function *, int);
+extern eh_region get_eh_region_from_lp_number (int);
+
+extern eh_region eh_region_outermost (struct function *, eh_region, eh_region);
+
+extern void make_reg_eh_region_note (rtx_insn *insn, int ecf_flags, int lp_nr);
+extern void make_reg_eh_region_note_nothrow_nononlocal (rtx_insn *);
+
+extern void verify_eh_tree (struct function *);
+extern void dump_eh_tree (FILE *, struct function *);
+void debug_eh_tree (struct function *);
+extern void add_type_for_runtime (tree);
+extern tree lookup_type_for_runtime (tree);
+extern void assign_filter_values (void);
+
+extern eh_region get_eh_region_from_rtx (const_rtx);
+extern eh_landing_pad get_eh_landing_pad_from_rtx (const_rtx);
+
+extern void finish_eh_generation (void);
+
+struct GTY(()) throw_stmt_node {
+ gimple *stmt;
+ int lp_nr;
+};
+
+extern hash_map<gimple *, int> *get_eh_throw_stmt_table (struct function *);
+extern void set_eh_throw_stmt_table (function *, hash_map<gimple *, int> *);
+
+enum eh_personality_kind {
+ eh_personality_none,
+ eh_personality_any,
+ eh_personality_lang
+};
+
+extern enum eh_personality_kind
+function_needs_eh_personality (struct function *);
+
+/* Pre-order iteration within the eh_region tree. */
+
+static inline eh_region
+ehr_next (eh_region r, eh_region start)
+{
+ if (r->inner)
+ r = r->inner;
+ else if (r->next_peer && r != start)
+ r = r->next_peer;
+ else
+ {
+ do
+ {
+ r = r->outer;
+ if (r == start)
+ return NULL;
+ }
+ while (r->next_peer == NULL);
+ r = r->next_peer;
+ }
+ return r;
+}
+
+#define FOR_ALL_EH_REGION_AT(R, START) \
+ for ((R) = (START); (R) != NULL; (R) = ehr_next (R, START))
+
+#define FOR_ALL_EH_REGION_FN(R, FN) \
+ for ((R) = (FN)->eh->region_tree; (R) != NULL; (R) = ehr_next (R, NULL))
+
+#define FOR_ALL_EH_REGION(R) FOR_ALL_EH_REGION_FN (R, cfun)
+
+#endif
diff --git a/support/cpp/gcc/exec-tool.in b/support/cpp/gcc/exec-tool.in
new file mode 100644
index 000000000..cf7222745
--- /dev/null
+++ b/support/cpp/gcc/exec-tool.in
@@ -0,0 +1,116 @@
+#! /bin/sh
+
+# Copyright (C) 2007-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/>.
+
+# Invoke as, ld or nm from the build tree.
+
+ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@"
+ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@"
+ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@"
+ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@"
+ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@"
+ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@"
+ORIGINAL_DSYMUTIL_FOR_TARGET="@ORIGINAL_DSYMUTIL_FOR_TARGET@"
+exeext=@host_exeext@
+fast_install=@enable_fast_install@
+objdir=@objdir@
+
+invoked=`basename "$0"`
+id=$invoked
+case "$invoked" in
+ as)
+ original=$ORIGINAL_AS_FOR_TARGET
+ prog=as-new$exeext
+ dir=gas
+ ;;
+ collect-ld)
+ # Check -fuse-ld=bfd and -fuse-ld=gold
+ case " $* " in
+ *\ -fuse-ld=bfd\ *)
+ original=$ORIGINAL_LD_BFD_FOR_TARGET
+ ;;
+ *\ -fuse-ld=gold\ *)
+ original=$ORIGINAL_LD_GOLD_FOR_TARGET
+ ;;
+ *)
+ # when using a linker plugin, gcc will always pass '-plugin' as the
+ # first or second option to the linker.
+ if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then
+ original=$ORIGINAL_PLUGIN_LD_FOR_TARGET
+ else
+ original=$ORIGINAL_LD_FOR_TARGET
+ fi
+ ;;
+ esac
+ prog=ld-new$exeext
+ if test "$original" = ../gold/ld-new$exeext; then
+ dir=gold
+ # No need to handle relink since gold doesn't use libtool.
+ fast_install=yes
+ else
+ dir=ld
+ fi
+ id=ld
+ ;;
+ nm)
+ original=$ORIGINAL_NM_FOR_TARGET
+ prog=nm-new$exeext
+ dir=binutils
+ ;;
+ dsymutil)
+ original=$ORIGINAL_DSYMUTIL_FOR_TARGET
+ # We do not build this in tree - but still want to be able to execute
+ # a configured version from the build dir.
+ prog=
+ dir=
+ ;;
+esac
+
+case "$original" in
+ ../*)
+ # compute absolute path of the location of this script
+ tdir=`dirname "$0"`
+ scriptdir=`cd "$tdir" && pwd`
+
+ if test -x $scriptdir/../$dir/$prog; then
+ test "$fast_install" = yes || exec $scriptdir/../$dir/$prog ${1+"$@"}
+
+ # if libtool did everything it needs to do, there's a fast path
+ lt_prog=$scriptdir/../$dir/$objdir/lt-$prog
+ test -x $lt_prog && exec $lt_prog ${1+"$@"}
+
+ # libtool has not relinked ld-new yet, but we cannot just use the
+ # previous stage (because then the relinking would just never happen!).
+ # So we take extra care to use prev-ld/ld-new *on recursive calls*.
+ eval LT_RCU="\${LT_RCU_$id}"
+ test x"$LT_RCU" = x"1" && exec $scriptdir/../prev-$dir/$prog ${1+"$@"}
+
+ eval LT_RCU_$id=1
+ export LT_RCU_$id
+ $scriptdir/../$dir/$prog ${1+"$@"}
+ result=$?
+ exit $result
+
+ else
+ exec $scriptdir/../prev-$dir/$prog ${1+"$@"}
+ fi
+ ;;
+ *)
+ exec $original ${1+"$@"}
+ ;;
+esac
diff --git a/support/cpp/gcc/explow.h b/support/cpp/gcc/explow.h
new file mode 100644
index 000000000..2b9f7e432
--- /dev/null
+++ b/support/cpp/gcc/explow.h
@@ -0,0 +1,143 @@
+/* Export function prototypes from explow.cc.
+ Copyright (C) 2015-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_EXPLOW_H
+#define GCC_EXPLOW_H
+
+/* Return a memory reference like MEMREF, but which is known to have a
+ valid address. */
+extern rtx validize_mem (rtx);
+
+extern rtx use_anchored_address (rtx);
+
+/* Copy given rtx to a new temp reg and return that. */
+extern rtx copy_to_reg (rtx);
+
+/* Like copy_to_reg but always make the reg Pmode. */
+extern rtx copy_addr_to_reg (rtx);
+
+/* Like copy_to_reg but always make the reg the specified mode MODE. */
+extern rtx copy_to_mode_reg (machine_mode, rtx);
+
+/* Copy given rtx to given temp reg and return that. */
+extern rtx copy_to_suggested_reg (rtx, rtx, machine_mode);
+
+/* Copy a value to a register if it isn't already a register.
+ Args are mode (in case value is a constant) and the value. */
+extern rtx force_reg (machine_mode, rtx);
+
+/* Return given rtx, copied into a new temp reg if it was in memory. */
+extern rtx force_not_mem (rtx);
+
+/* Return mode and signedness to use when an argument or result in the
+ given mode is promoted. */
+extern machine_mode promote_function_mode (const_tree, machine_mode, int *,
+ const_tree, int);
+
+/* Return mode and signedness to use when an object in the given mode
+ is promoted. */
+extern machine_mode promote_mode (const_tree, machine_mode, int *);
+
+/* Return mode and signedness to use when object is promoted. */
+machine_mode promote_decl_mode (const_tree, int *);
+
+/* Return mode and signedness to use when object is promoted. */
+machine_mode promote_ssa_mode (const_tree, int *);
+
+/* Remove some bytes from the stack. An rtx says how many. */
+extern void adjust_stack (rtx);
+
+/* Add some bytes to the stack. An rtx says how many. */
+extern void anti_adjust_stack (rtx);
+
+/* Add some bytes to the stack while probing it. An rtx says how many. */
+extern void anti_adjust_stack_and_probe (rtx, bool);
+
+/* Add some bytes to the stack while probing it. An rtx says how
+ many. Add additional probes to prevent stack clashing attacks. */
+extern void anti_adjust_stack_and_probe_stack_clash (rtx);
+
+/* Support for building allocation/probing loops for stack-clash
+ protection of dyamically allocated stack space. */
+extern void compute_stack_clash_protection_loop_data (rtx *, rtx *, rtx *,
+ HOST_WIDE_INT *, rtx);
+extern void emit_stack_clash_protection_probe_loop_start (rtx *, rtx *,
+ rtx, bool);
+extern void emit_stack_clash_protection_probe_loop_end (rtx, rtx,
+ rtx, bool);
+
+/* This enum is used for the following two functions. */
+enum save_level {SAVE_BLOCK, SAVE_FUNCTION, SAVE_NONLOCAL};
+
+/* Save the stack pointer at the specified level. */
+extern void emit_stack_save (enum save_level, rtx *);
+
+/* Restore the stack pointer from a save area of the specified level. */
+extern void emit_stack_restore (enum save_level, rtx);
+
+/* Invoke emit_stack_save for the nonlocal_goto_save_area. */
+extern void update_nonlocal_goto_save_area (void);
+
+/* Record a new stack level. */
+extern void record_new_stack_level (void);
+
+/* Allocate some space on the stack dynamically and return its address. */
+extern rtx allocate_dynamic_stack_space (rtx, unsigned, unsigned,
+ HOST_WIDE_INT, bool);
+
+/* Calculate the necessary size of a constant dynamic stack allocation from the
+ size of the variable area. */
+extern void get_dynamic_stack_size (rtx *, unsigned, unsigned, HOST_WIDE_INT *);
+
+/* Returns the address of the dynamic stack space without allocating it. */
+extern rtx get_dynamic_stack_base (poly_int64, unsigned, rtx);
+
+/* Return an rtx doing runtime alignment to REQUIRED_ALIGN on TARGET. */
+extern rtx align_dynamic_address (rtx, unsigned);
+
+/* Emit one stack probe at ADDRESS, an address within the stack. */
+extern void emit_stack_probe (rtx);
+
+/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
+ FIRST is a constant and size is a Pmode RTX. These are offsets from
+ the current stack pointer. STACK_GROWS_DOWNWARD says whether to add
+ or subtract them from the stack pointer. */
+extern void probe_stack_range (HOST_WIDE_INT, rtx);
+
+/* Return an rtx that refers to the value returned by a library call
+ in its original home. This becomes invalid if any more code is emitted. */
+extern rtx hard_libcall_value (machine_mode, rtx);
+
+/* Return an rtx that refers to the value returned by a function
+ in its original home. This becomes invalid if any more code is emitted. */
+extern rtx hard_function_value (const_tree, const_tree, const_tree, int);
+
+/* Convert arg to a valid memory address for specified machine mode that points
+ to a specific named address space, by emitting insns to perform arithmetic
+ if necessary. */
+extern rtx memory_address_addr_space (machine_mode, rtx, addr_space_t);
+
+extern rtx eliminate_constant_term (rtx, rtx *);
+
+/* Like memory_address_addr_space, except assume the memory address points to
+ the generic named address space. */
+#define memory_address(MODE,RTX) \
+ memory_address_addr_space ((MODE), (RTX), ADDR_SPACE_GENERIC)
+
+#endif /* GCC_EXPLOW_H */
diff --git a/support/cpp/gcc/expmed.h b/support/cpp/gcc/expmed.h
new file mode 100644
index 000000000..ee1ddc82b
--- /dev/null
+++ b/support/cpp/gcc/expmed.h
@@ -0,0 +1,726 @@
+/* Target-dependent costs for expmed.cc.
+ 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/>. */
+
+#ifndef EXPMED_H
+#define EXPMED_H 1
+
+#include "insn-codes.h"
+
+enum alg_code {
+ alg_unknown,
+ alg_zero,
+ alg_m, alg_shift,
+ alg_add_t_m2,
+ alg_sub_t_m2,
+ alg_add_factor,
+ alg_sub_factor,
+ alg_add_t2_m,
+ alg_sub_t2_m,
+ alg_impossible
+};
+
+/* Indicates the type of fixup needed after a constant multiplication.
+ BASIC_VARIANT means no fixup is needed, NEGATE_VARIANT means that
+ the result should be negated, and ADD_VARIANT means that the
+ multiplicand should be added to the result. */
+enum mult_variant {basic_variant, negate_variant, add_variant};
+
+bool choose_mult_variant (machine_mode, HOST_WIDE_INT,
+ struct algorithm *, enum mult_variant *, int);
+
+/* This structure holds the "cost" of a multiply sequence. The
+ "cost" field holds the total rtx_cost of every operator in the
+ synthetic multiplication sequence, hence cost(a op b) is defined
+ as rtx_cost(op) + cost(a) + cost(b), where cost(leaf) is zero.
+ The "latency" field holds the minimum possible latency of the
+ synthetic multiply, on a hypothetical infinitely parallel CPU.
+ This is the critical path, or the maximum height, of the expression
+ tree which is the sum of rtx_costs on the most expensive path from
+ any leaf to the root. Hence latency(a op b) is defined as zero for
+ leaves and rtx_cost(op) + max(latency(a), latency(b)) otherwise. */
+
+struct mult_cost {
+ short cost; /* Total rtx_cost of the multiplication sequence. */
+ short latency; /* The latency of the multiplication sequence. */
+};
+
+/* This macro is used to compare a pointer to a mult_cost against an
+ single integer "rtx_cost" value. This is equivalent to the macro
+ CHEAPER_MULT_COST(X,Z) where Z = {Y,Y}. */
+#define MULT_COST_LESS(X,Y) ((X)->cost < (Y) \
+ || ((X)->cost == (Y) && (X)->latency < (Y)))
+
+/* This macro is used to compare two pointers to mult_costs against
+ each other. The macro returns true if X is cheaper than Y.
+ Currently, the cheaper of two mult_costs is the one with the
+ lower "cost". If "cost"s are tied, the lower latency is cheaper. */
+#define CHEAPER_MULT_COST(X,Y) ((X)->cost < (Y)->cost \
+ || ((X)->cost == (Y)->cost \
+ && (X)->latency < (Y)->latency))
+
+/* This structure records a sequence of operations.
+ `ops' is the number of operations recorded.
+ `cost' is their total cost.
+ The operations are stored in `op' and the corresponding
+ logarithms of the integer coefficients in `log'.
+
+ These are the operations:
+ alg_zero total := 0;
+ alg_m total := multiplicand;
+ alg_shift total := total * coeff
+ alg_add_t_m2 total := total + multiplicand * coeff;
+ alg_sub_t_m2 total := total - multiplicand * coeff;
+ alg_add_factor total := total * coeff + total;
+ alg_sub_factor total := total * coeff - total;
+ alg_add_t2_m total := total * coeff + multiplicand;
+ alg_sub_t2_m total := total * coeff - multiplicand;
+
+ The first operand must be either alg_zero or alg_m. */
+
+struct algorithm
+{
+ struct mult_cost cost;
+ short ops;
+ /* The size of the OP and LOG fields are not directly related to the
+ word size, but the worst-case algorithms will be if we have few
+ consecutive ones or zeros, i.e., a multiplicand like 10101010101...
+ In that case we will generate shift-by-2, add, shift-by-2, add,...,
+ in total wordsize operations. */
+ enum alg_code op[MAX_BITS_PER_WORD];
+ char log[MAX_BITS_PER_WORD];
+};
+
+/* The entry for our multiplication cache/hash table. */
+struct alg_hash_entry {
+ /* The number we are multiplying by. */
+ unsigned HOST_WIDE_INT t;
+
+ /* The mode in which we are multiplying something by T. */
+ machine_mode mode;
+
+ /* The best multiplication algorithm for t. */
+ enum alg_code alg;
+
+ /* The cost of multiplication if ALG_CODE is not alg_impossible.
+ Otherwise, the cost within which multiplication by T is
+ impossible. */
+ struct mult_cost cost;
+
+ /* Optimized for speed? */
+ bool speed;
+};
+
+/* The number of cache/hash entries. */
+#if HOST_BITS_PER_WIDE_INT == 64
+#define NUM_ALG_HASH_ENTRIES 1031
+#else
+#define NUM_ALG_HASH_ENTRIES 307
+#endif
+
+#define NUM_MODE_IP_INT (NUM_MODE_INT + NUM_MODE_PARTIAL_INT)
+#define NUM_MODE_IPV_INT (NUM_MODE_IP_INT + NUM_MODE_VECTOR_INT)
+
+struct expmed_op_cheap {
+ bool cheap[2][NUM_MODE_IPV_INT];
+};
+
+struct expmed_op_costs {
+ int cost[2][NUM_MODE_IPV_INT];
+};
+
+/* Target-dependent globals. */
+struct target_expmed {
+ /* Each entry of ALG_HASH caches alg_code for some integer. This is
+ actually a hash table. If we have a collision, that the older
+ entry is kicked out. */
+ struct alg_hash_entry x_alg_hash[NUM_ALG_HASH_ENTRIES];
+
+ /* True if x_alg_hash might already have been used. */
+ bool x_alg_hash_used_p;
+
+ /* Nonzero means divides or modulus operations are relatively cheap for
+ powers of two, so don't use branches; emit the operation instead.
+ Usually, this will mean that the MD file will emit non-branch
+ sequences. */
+ struct expmed_op_cheap x_sdiv_pow2_cheap;
+ struct expmed_op_cheap x_smod_pow2_cheap;
+
+ /* Cost of various pieces of RTL. Note that some of these are indexed by
+ shift count and some by mode. */
+ int x_zero_cost[2];
+ struct expmed_op_costs x_add_cost;
+ struct expmed_op_costs x_neg_cost;
+ struct expmed_op_costs x_shift_cost[MAX_BITS_PER_WORD];
+ struct expmed_op_costs x_shiftadd_cost[MAX_BITS_PER_WORD];
+ struct expmed_op_costs x_shiftsub0_cost[MAX_BITS_PER_WORD];
+ struct expmed_op_costs x_shiftsub1_cost[MAX_BITS_PER_WORD];
+ struct expmed_op_costs x_mul_cost;
+ struct expmed_op_costs x_sdiv_cost;
+ struct expmed_op_costs x_udiv_cost;
+ int x_mul_widen_cost[2][NUM_MODE_INT];
+ int x_mul_highpart_cost[2][NUM_MODE_INT];
+
+ /* Conversion costs are only defined between two scalar integer modes
+ of different sizes. The first machine mode is the destination mode,
+ and the second is the source mode. */
+ int x_convert_cost[2][NUM_MODE_IP_INT][NUM_MODE_IP_INT];
+};
+
+extern struct target_expmed default_target_expmed;
+#if SWITCHABLE_TARGET
+extern struct target_expmed *this_target_expmed;
+#else
+#define this_target_expmed (&default_target_expmed)
+#endif
+
+/* Return a pointer to the alg_hash_entry at IDX. */
+
+static inline struct alg_hash_entry *
+alg_hash_entry_ptr (int idx)
+{
+ return &this_target_expmed->x_alg_hash[idx];
+}
+
+/* Return true if the x_alg_hash field might have been used. */
+
+static inline bool
+alg_hash_used_p (void)
+{
+ return this_target_expmed->x_alg_hash_used_p;
+}
+
+/* Set whether the x_alg_hash field might have been used. */
+
+static inline void
+set_alg_hash_used_p (bool usedp)
+{
+ this_target_expmed->x_alg_hash_used_p = usedp;
+}
+
+/* Compute an index into the cost arrays by mode class. */
+
+static inline int
+expmed_mode_index (machine_mode mode)
+{
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ return mode - MIN_MODE_INT;
+ case MODE_PARTIAL_INT:
+ /* If there are no partial integer modes, help the compiler
+ to figure out this will never happen. See PR59934. */
+ if (MIN_MODE_PARTIAL_INT != VOIDmode)
+ return mode - MIN_MODE_PARTIAL_INT + NUM_MODE_INT;
+ break;
+ case MODE_VECTOR_INT:
+ /* If there are no vector integer modes, help the compiler
+ to figure out this will never happen. See PR59934. */
+ if (MIN_MODE_VECTOR_INT != VOIDmode)
+ return mode - MIN_MODE_VECTOR_INT + NUM_MODE_IP_INT;
+ break;
+ default:
+ break;
+ }
+ gcc_unreachable ();
+}
+
+/* Return a pointer to a boolean contained in EOC indicating whether
+ a particular operation performed in MODE is cheap when optimizing
+ for SPEED. */
+
+static inline bool *
+expmed_op_cheap_ptr (struct expmed_op_cheap *eoc, bool speed,
+ machine_mode mode)
+{
+ int idx = expmed_mode_index (mode);
+ return &eoc->cheap[speed][idx];
+}
+
+/* Return a pointer to a cost contained in COSTS when a particular
+ operation is performed in MODE when optimizing for SPEED. */
+
+static inline int *
+expmed_op_cost_ptr (struct expmed_op_costs *costs, bool speed,
+ machine_mode mode)
+{
+ int idx = expmed_mode_index (mode);
+ return &costs->cost[speed][idx];
+}
+
+/* Subroutine of {set_,}sdiv_pow2_cheap. Not to be used otherwise. */
+
+static inline bool *
+sdiv_pow2_cheap_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cheap_ptr (&this_target_expmed->x_sdiv_pow2_cheap,
+ speed, mode);
+}
+
+/* Set whether a signed division by a power of 2 is cheap in MODE
+ when optimizing for SPEED. */
+
+static inline void
+set_sdiv_pow2_cheap (bool speed, machine_mode mode, bool cheap_p)
+{
+ *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p;
+}
+
+/* Return whether a signed division by a power of 2 is cheap in MODE
+ when optimizing for SPEED. */
+
+static inline bool
+sdiv_pow2_cheap (bool speed, machine_mode mode)
+{
+ return *sdiv_pow2_cheap_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}smod_pow2_cheap. Not to be used otherwise. */
+
+static inline bool *
+smod_pow2_cheap_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cheap_ptr (&this_target_expmed->x_smod_pow2_cheap,
+ speed, mode);
+}
+
+/* Set whether a signed modulo by a power of 2 is CHEAP in MODE when
+ optimizing for SPEED. */
+
+static inline void
+set_smod_pow2_cheap (bool speed, machine_mode mode, bool cheap)
+{
+ *smod_pow2_cheap_ptr (speed, mode) = cheap;
+}
+
+/* Return whether a signed modulo by a power of 2 is cheap in MODE
+ when optimizing for SPEED. */
+
+static inline bool
+smod_pow2_cheap (bool speed, machine_mode mode)
+{
+ return *smod_pow2_cheap_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}zero_cost. Not to be used otherwise. */
+
+static inline int *
+zero_cost_ptr (bool speed)
+{
+ return &this_target_expmed->x_zero_cost[speed];
+}
+
+/* Set the COST of loading zero when optimizing for SPEED. */
+
+static inline void
+set_zero_cost (bool speed, int cost)
+{
+ *zero_cost_ptr (speed) = cost;
+}
+
+/* Return the COST of loading zero when optimizing for SPEED. */
+
+static inline int
+zero_cost (bool speed)
+{
+ return *zero_cost_ptr (speed);
+}
+
+/* Subroutine of {set_,}add_cost. Not to be used otherwise. */
+
+static inline int *
+add_cost_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_add_cost, speed, mode);
+}
+
+/* Set the COST of computing an add in MODE when optimizing for SPEED. */
+
+static inline void
+set_add_cost (bool speed, machine_mode mode, int cost)
+{
+ *add_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost of computing an add in MODE when optimizing for SPEED. */
+
+static inline int
+add_cost (bool speed, machine_mode mode)
+{
+ return *add_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}neg_cost. Not to be used otherwise. */
+
+static inline int *
+neg_cost_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_neg_cost, speed, mode);
+}
+
+/* Set the COST of computing a negation in MODE when optimizing for SPEED. */
+
+static inline void
+set_neg_cost (bool speed, machine_mode mode, int cost)
+{
+ *neg_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost of computing a negation in MODE when optimizing for
+ SPEED. */
+
+static inline int
+neg_cost (bool speed, machine_mode mode)
+{
+ return *neg_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}shift_cost. Not to be used otherwise. */
+
+static inline int *
+shift_cost_ptr (bool speed, machine_mode mode, int bits)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_shift_cost[bits],
+ speed, mode);
+}
+
+/* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED. */
+
+static inline void
+set_shift_cost (bool speed, machine_mode mode, int bits, int cost)
+{
+ *shift_cost_ptr (speed, mode, bits) = cost;
+}
+
+/* Return the cost of doing a shift in MODE by BITS when optimizing for
+ SPEED. */
+
+static inline int
+shift_cost (bool speed, machine_mode mode, int bits)
+{
+ return *shift_cost_ptr (speed, mode, bits);
+}
+
+/* Subroutine of {set_,}shiftadd_cost. Not to be used otherwise. */
+
+static inline int *
+shiftadd_cost_ptr (bool speed, machine_mode mode, int bits)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_shiftadd_cost[bits],
+ speed, mode);
+}
+
+/* Set the COST of doing a shift in MODE by BITS followed by an add when
+ optimizing for SPEED. */
+
+static inline void
+set_shiftadd_cost (bool speed, machine_mode mode, int bits, int cost)
+{
+ *shiftadd_cost_ptr (speed, mode, bits) = cost;
+}
+
+/* Return the cost of doing a shift in MODE by BITS followed by an add
+ when optimizing for SPEED. */
+
+static inline int
+shiftadd_cost (bool speed, machine_mode mode, int bits)
+{
+ return *shiftadd_cost_ptr (speed, mode, bits);
+}
+
+/* Subroutine of {set_,}shiftsub0_cost. Not to be used otherwise. */
+
+static inline int *
+shiftsub0_cost_ptr (bool speed, machine_mode mode, int bits)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub0_cost[bits],
+ speed, mode);
+}
+
+/* Set the COST of doing a shift in MODE by BITS and then subtracting a
+ value when optimizing for SPEED. */
+
+static inline void
+set_shiftsub0_cost (bool speed, machine_mode mode, int bits, int cost)
+{
+ *shiftsub0_cost_ptr (speed, mode, bits) = cost;
+}
+
+/* Return the cost of doing a shift in MODE by BITS and then subtracting
+ a value when optimizing for SPEED. */
+
+static inline int
+shiftsub0_cost (bool speed, machine_mode mode, int bits)
+{
+ return *shiftsub0_cost_ptr (speed, mode, bits);
+}
+
+/* Subroutine of {set_,}shiftsub1_cost. Not to be used otherwise. */
+
+static inline int *
+shiftsub1_cost_ptr (bool speed, machine_mode mode, int bits)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_shiftsub1_cost[bits],
+ speed, mode);
+}
+
+/* Set the COST of subtracting a shift in MODE by BITS from a value when
+ optimizing for SPEED. */
+
+static inline void
+set_shiftsub1_cost (bool speed, machine_mode mode, int bits, int cost)
+{
+ *shiftsub1_cost_ptr (speed, mode, bits) = cost;
+}
+
+/* Return the cost of subtracting a shift in MODE by BITS from a value
+ when optimizing for SPEED. */
+
+static inline int
+shiftsub1_cost (bool speed, machine_mode mode, int bits)
+{
+ return *shiftsub1_cost_ptr (speed, mode, bits);
+}
+
+/* Subroutine of {set_,}mul_cost. Not to be used otherwise. */
+
+static inline int *
+mul_cost_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_mul_cost, speed, mode);
+}
+
+/* Set the COST of doing a multiplication in MODE when optimizing for
+ SPEED. */
+
+static inline void
+set_mul_cost (bool speed, machine_mode mode, int cost)
+{
+ *mul_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost of doing a multiplication in MODE when optimizing
+ for SPEED. */
+
+static inline int
+mul_cost (bool speed, machine_mode mode)
+{
+ return *mul_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}sdiv_cost. Not to be used otherwise. */
+
+static inline int *
+sdiv_cost_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_sdiv_cost, speed, mode);
+}
+
+/* Set the COST of doing a signed division in MODE when optimizing
+ for SPEED. */
+
+static inline void
+set_sdiv_cost (bool speed, machine_mode mode, int cost)
+{
+ *sdiv_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost of doing a signed division in MODE when optimizing
+ for SPEED. */
+
+static inline int
+sdiv_cost (bool speed, machine_mode mode)
+{
+ return *sdiv_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}udiv_cost. Not to be used otherwise. */
+
+static inline int *
+udiv_cost_ptr (bool speed, machine_mode mode)
+{
+ return expmed_op_cost_ptr (&this_target_expmed->x_udiv_cost, speed, mode);
+}
+
+/* Set the COST of doing an unsigned division in MODE when optimizing
+ for SPEED. */
+
+static inline void
+set_udiv_cost (bool speed, machine_mode mode, int cost)
+{
+ *udiv_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost of doing an unsigned division in MODE when
+ optimizing for SPEED. */
+
+static inline int
+udiv_cost (bool speed, machine_mode mode)
+{
+ return *udiv_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}mul_widen_cost. Not to be used otherwise. */
+
+static inline int *
+mul_widen_cost_ptr (bool speed, machine_mode mode)
+{
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+
+ return &this_target_expmed->x_mul_widen_cost[speed][mode - MIN_MODE_INT];
+}
+
+/* Set the COST for computing a widening multiplication in MODE when
+ optimizing for SPEED. */
+
+static inline void
+set_mul_widen_cost (bool speed, machine_mode mode, int cost)
+{
+ *mul_widen_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost for computing a widening multiplication in MODE when
+ optimizing for SPEED. */
+
+static inline int
+mul_widen_cost (bool speed, machine_mode mode)
+{
+ return *mul_widen_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}mul_highpart_cost. Not to be used otherwise. */
+
+static inline int *
+mul_highpart_cost_ptr (bool speed, machine_mode mode)
+{
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_INT);
+ int m = mode - MIN_MODE_INT;
+ gcc_assert (m < NUM_MODE_INT);
+
+ return &this_target_expmed->x_mul_highpart_cost[speed][m];
+}
+
+/* Set the COST for computing the high part of a multiplication in MODE
+ when optimizing for SPEED. */
+
+static inline void
+set_mul_highpart_cost (bool speed, machine_mode mode, int cost)
+{
+ *mul_highpart_cost_ptr (speed, mode) = cost;
+}
+
+/* Return the cost for computing the high part of a multiplication in MODE
+ when optimizing for SPEED. */
+
+static inline int
+mul_highpart_cost (bool speed, machine_mode mode)
+{
+ return *mul_highpart_cost_ptr (speed, mode);
+}
+
+/* Subroutine of {set_,}convert_cost. Not to be used otherwise. */
+
+static inline int *
+convert_cost_ptr (machine_mode to_mode, machine_mode from_mode,
+ bool speed)
+{
+ int to_idx = expmed_mode_index (to_mode);
+ int from_idx = expmed_mode_index (from_mode);
+
+ gcc_assert (IN_RANGE (to_idx, 0, NUM_MODE_IP_INT - 1));
+ gcc_assert (IN_RANGE (from_idx, 0, NUM_MODE_IP_INT - 1));
+
+ return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx];
+}
+
+/* Set the COST for converting from FROM_MODE to TO_MODE when optimizing
+ for SPEED. */
+
+static inline void
+set_convert_cost (machine_mode to_mode, machine_mode from_mode,
+ bool speed, int cost)
+{
+ *convert_cost_ptr (to_mode, from_mode, speed) = cost;
+}
+
+/* Return the cost for converting from FROM_MODE to TO_MODE when optimizing
+ for SPEED. */
+
+static inline int
+convert_cost (machine_mode to_mode, machine_mode from_mode,
+ bool speed)
+{
+ return *convert_cost_ptr (to_mode, from_mode, speed);
+}
+
+extern int mult_by_coeff_cost (HOST_WIDE_INT, machine_mode, bool);
+extern rtx emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
+ machine_mode mode, machine_mode compare_mode,
+ int unsignedp, rtx x, rtx y, int normalizep,
+ machine_mode target_mode);
+
+/* Arguments MODE, RTX: return an rtx for the negation of that value.
+ May emit insns. */
+extern rtx negate_rtx (machine_mode, rtx);
+
+/* Arguments MODE, RTX: return an rtx for the flipping of that value.
+ May emit insns. */
+extern rtx flip_storage_order (machine_mode, rtx);
+
+/* Expand a logical AND operation. */
+extern rtx expand_and (machine_mode, rtx, rtx, rtx);
+
+/* Emit a store-flag operation. */
+extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, machine_mode,
+ int, int);
+
+/* Like emit_store_flag, but always succeeds. */
+extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx,
+ machine_mode, int, int);
+
+extern void canonicalize_comparison (machine_mode, enum rtx_code *, rtx *);
+
+/* Choose a minimal N + 1 bit approximation to 1/D that can be used to
+ replace division by D, and put the least significant N bits of the result
+ in *MULTIPLIER_PTR and return the most significant bit. */
+extern unsigned HOST_WIDE_INT choose_multiplier (unsigned HOST_WIDE_INT, int,
+ int, unsigned HOST_WIDE_INT *,
+ int *, int *);
+
+#ifdef TREE_CODE
+extern rtx expand_variable_shift (enum tree_code, machine_mode,
+ rtx, tree, rtx, int);
+extern rtx expand_shift (enum tree_code, machine_mode, rtx, poly_int64, rtx,
+ int);
+#ifdef GCC_OPTABS_H
+extern rtx expand_divmod (int, enum tree_code, machine_mode, rtx, rtx,
+ rtx, int, enum optab_methods = OPTAB_LIB_WIDEN);
+#endif
+#endif
+
+extern void store_bit_field (rtx, poly_uint64, poly_uint64,
+ poly_uint64, poly_uint64,
+ machine_mode, rtx, bool);
+extern rtx extract_bit_field (rtx, poly_uint64, poly_uint64, int, rtx,
+ machine_mode, machine_mode, bool, rtx *);
+extern rtx extract_low_bits (machine_mode, machine_mode, rtx);
+extern rtx expand_mult (machine_mode, rtx, rtx, rtx, int, bool = false);
+extern rtx expand_mult_highpart_adjust (scalar_int_mode, rtx, rtx, rtx,
+ rtx, int);
+
+#endif // EXPMED_H
diff --git a/support/cpp/gcc/expr.h b/support/cpp/gcc/expr.h
new file mode 100644
index 000000000..311d0e79b
--- /dev/null
+++ b/support/cpp/gcc/expr.h
@@ -0,0 +1,352 @@
+/* Definitions for code generation pass of 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/>. */
+
+#if 0 // sdcpp ndef GCC_EXPR_H
+#define GCC_EXPR_H
+
+/* This is the 4th arg to `expand_expr'.
+ EXPAND_STACK_PARM means we are possibly expanding a call param onto
+ the stack.
+ EXPAND_SUM means it is ok to return a PLUS rtx or MULT rtx.
+ EXPAND_INITIALIZER is similar but also record any labels on forced_labels.
+ EXPAND_CONST_ADDRESS means it is ok to return a MEM whose address
+ is a constant that is not a legitimate address.
+ EXPAND_WRITE means we are only going to write to the resulting rtx.
+ EXPAND_MEMORY means we are interested in a memory result, even if
+ the memory is constant and we could have propagated a constant value,
+ or the memory is unaligned on a STRICT_ALIGNMENT target. */
+enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM,
+ EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE,
+ EXPAND_MEMORY};
+
+/* Prevent the compiler from deferring stack pops. See
+ inhibit_defer_pop for more information. */
+#define NO_DEFER_POP (inhibit_defer_pop += 1)
+
+/* Allow the compiler to defer stack pops. See inhibit_defer_pop for
+ more information. */
+#define OK_DEFER_POP (inhibit_defer_pop -= 1)
+
+/* This structure is used to pass around information about exploded
+ unary, binary and trinary expressions between expand_expr_real_1 and
+ friends. */
+typedef struct separate_ops
+{
+ enum tree_code code;
+ location_t location;
+ tree type;
+ tree op0, op1, op2;
+} *sepops;
+
+/* This is run during target initialization to set up which modes can be
+ used directly in memory and to initialize the block move optab. */
+extern void init_expr_target (void);
+
+/* This is run at the start of compiling a function. */
+extern void init_expr (void);
+
+/* Emit some rtl insns to move data between rtx's, converting machine modes.
+ Both modes must be floating or both fixed. */
+extern void convert_move (rtx, rtx, int);
+
+/* Convert an rtx to specified machine mode and return the result. */
+extern rtx convert_to_mode (machine_mode, rtx, int);
+
+/* Convert an rtx to MODE from OLDMODE and return the result. */
+extern rtx convert_modes (machine_mode, machine_mode, rtx, int);
+
+/* Expand a call to memcpy or memmove or memcmp, and return the result. */
+extern rtx emit_block_op_via_libcall (enum built_in_function, rtx, rtx, rtx,
+ bool);
+
+static inline rtx
+emit_block_copy_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
+{
+ return emit_block_op_via_libcall (BUILT_IN_MEMCPY, dst, src, size, tailcall);
+}
+
+static inline rtx
+emit_block_move_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
+{
+ return emit_block_op_via_libcall (BUILT_IN_MEMMOVE, dst, src, size, tailcall);
+}
+
+static inline rtx
+emit_block_comp_via_libcall (rtx dst, rtx src, rtx size, bool tailcall = false)
+{
+ return emit_block_op_via_libcall (BUILT_IN_MEMCMP, dst, src, size, tailcall);
+}
+
+/* Emit code to move a block Y to a block X. */
+enum block_op_methods
+{
+ BLOCK_OP_NORMAL,
+ BLOCK_OP_NO_LIBCALL,
+ BLOCK_OP_CALL_PARM,
+ /* Like BLOCK_OP_NORMAL, but the libcall can be tail call optimized. */
+ BLOCK_OP_TAILCALL,
+ /* Like BLOCK_OP_NO_LIBCALL, but instead of emitting a libcall return
+ pc_rtx to indicate nothing has been emitted and let the caller handle
+ it. */
+ BLOCK_OP_NO_LIBCALL_RET
+};
+
+typedef rtx (*by_pieces_constfn) (void *, void *, HOST_WIDE_INT,
+ fixed_size_mode);
+
+/* The second pointer passed to by_pieces_constfn. */
+struct by_pieces_prev
+{
+ rtx data;
+ fixed_size_mode mode;
+};
+
+extern rtx emit_block_move (rtx, rtx, rtx, enum block_op_methods);
+extern rtx emit_block_move_hints (rtx, rtx, rtx, enum block_op_methods,
+ unsigned int, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ bool bail_out_libcall = false,
+ bool *is_move_done = NULL,
+ bool might_overlap = false);
+extern rtx emit_block_cmp_hints (rtx, rtx, rtx, tree, rtx, bool,
+ by_pieces_constfn, void *);
+extern bool emit_storent_insn (rtx to, rtx from);
+
+/* Copy all or part of a value X into registers starting at REGNO.
+ The number of registers to be filled is NREGS. */
+extern void move_block_to_reg (int, rtx, int, machine_mode);
+
+/* Copy all or part of a BLKmode value X out of registers starting at REGNO.
+ The number of registers to be filled is NREGS. */
+extern void move_block_from_reg (int, rtx, int);
+
+/* Generate a non-consecutive group of registers represented by a PARALLEL. */
+extern rtx gen_group_rtx (rtx);
+
+/* Load a BLKmode value into non-consecutive registers represented by a
+ PARALLEL. */
+extern void emit_group_load (rtx, rtx, tree, poly_int64);
+
+/* Similarly, but load into new temporaries. */
+extern rtx emit_group_load_into_temps (rtx, rtx, tree, poly_int64);
+
+/* Move a non-consecutive group of registers represented by a PARALLEL into
+ a non-consecutive group of registers represented by a PARALLEL. */
+extern void emit_group_move (rtx, rtx);
+
+/* Move a group of registers represented by a PARALLEL into pseudos. */
+extern rtx emit_group_move_into_temps (rtx);
+
+/* Store a BLKmode value from non-consecutive registers represented by a
+ PARALLEL. */
+extern void emit_group_store (rtx, rtx, tree, poly_int64);
+
+extern rtx maybe_emit_group_store (rtx, tree);
+
+/* Mark REG as holding a parameter for the next CALL_INSN.
+ Mode is TYPE_MODE of the non-promoted parameter, or VOIDmode. */
+extern void use_reg_mode (rtx *, rtx, machine_mode);
+extern void clobber_reg_mode (rtx *, rtx, machine_mode);
+
+extern rtx copy_blkmode_to_reg (machine_mode, tree);
+
+/* Mark REG as holding a parameter for the next CALL_INSN. */
+static inline void
+use_reg (rtx *fusage, rtx reg)
+{
+ use_reg_mode (fusage, reg, VOIDmode);
+}
+
+/* Mark REG as clobbered by the call with FUSAGE as CALL_INSN_FUNCTION_USAGE. */
+static inline void
+clobber_reg (rtx *fusage, rtx reg)
+{
+ clobber_reg_mode (fusage, reg, VOIDmode);
+}
+
+/* Mark NREGS consecutive regs, starting at REGNO, as holding parameters
+ for the next CALL_INSN. */
+extern void use_regs (rtx *, int, int);
+
+/* Mark a PARALLEL as holding a parameter for the next CALL_INSN. */
+extern void use_group_regs (rtx *, rtx);
+
+#ifdef GCC_INSN_CODES_H
+extern rtx expand_cmpstrn_or_cmpmem (insn_code, rtx, rtx, rtx, tree, rtx,
+ HOST_WIDE_INT);
+#endif
+
+/* Write zeros through the storage of OBJECT.
+ If OBJECT has BLKmode, SIZE is its length in bytes. */
+extern rtx clear_storage (rtx, rtx, enum block_op_methods);
+extern rtx clear_storage_hints (rtx, rtx, enum block_op_methods,
+ unsigned int, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned);
+/* The same, but always output an library call. */
+extern rtx set_storage_via_libcall (rtx, rtx, rtx, bool = false);
+
+/* Expand a setmem pattern; return true if successful. */
+extern bool set_storage_via_setmem (rtx, rtx, rtx, unsigned int,
+ unsigned int, HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT);
+
+/* Return nonzero if it is desirable to store LEN bytes generated by
+ CONSTFUN with several move instructions by store_by_pieces
+ function. CONSTFUNDATA is a pointer which will be passed as argument
+ in every CONSTFUN call.
+ ALIGN is maximum alignment we can assume.
+ MEMSETP is true if this is a real memset/bzero, not a copy
+ of a const string. */
+extern int can_store_by_pieces (unsigned HOST_WIDE_INT,
+ by_pieces_constfn,
+ void *, unsigned int, bool);
+
+/* Generate several move instructions to store LEN bytes generated by
+ CONSTFUN to block TO. (A MEM rtx with BLKmode). CONSTFUNDATA is a
+ pointer which will be passed as argument in every CONSTFUN call.
+ ALIGN is maximum alignment we can assume.
+ MEMSETP is true if this is a real memset/bzero, not a copy.
+ Returns TO + LEN. */
+extern rtx store_by_pieces (rtx, unsigned HOST_WIDE_INT, by_pieces_constfn,
+ void *, unsigned int, bool, memop_ret);
+
+/* If can_store_by_pieces passes for worst-case values near MAX_LEN, call
+ store_by_pieces within conditionals so as to handle variable LEN efficiently,
+ storing VAL, if non-NULL_RTX, or valc instead. */
+extern bool try_store_by_multiple_pieces (rtx to, rtx len,
+ unsigned int ctz_len,
+ unsigned HOST_WIDE_INT min_len,
+ unsigned HOST_WIDE_INT max_len,
+ rtx val, char valc,
+ unsigned int align);
+
+/* Emit insns to set X from Y. */
+extern rtx_insn *emit_move_insn (rtx, rtx);
+extern rtx_insn *gen_move_insn (rtx, rtx);
+
+/* Emit insns to set X from Y, with no frills. */
+extern rtx_insn *emit_move_insn_1 (rtx, rtx);
+
+extern rtx_insn *emit_move_complex_push (machine_mode, rtx, rtx);
+extern rtx_insn *emit_move_complex_parts (rtx, rtx);
+extern rtx read_complex_part (rtx, bool);
+extern void write_complex_part (rtx, rtx, bool);
+extern rtx read_complex_part (rtx, bool);
+extern rtx emit_move_resolve_push (machine_mode, rtx);
+
+/* Push a block of length SIZE (perhaps variable)
+ and return an rtx to address the beginning of the block. */
+extern rtx push_block (rtx, poly_int64, int);
+
+/* Generate code to push something onto the stack, given its mode and type. */
+extern bool emit_push_insn (rtx, machine_mode, tree, rtx, unsigned int,
+ int, rtx, poly_int64, rtx, rtx, int, rtx, bool);
+
+/* Extract the accessible bit-range from a COMPONENT_REF. */
+extern void get_bit_range (poly_uint64_pod *, poly_uint64_pod *, tree,
+ poly_int64_pod *, tree *);
+
+/* Expand an assignment that stores the value of FROM into TO. */
+extern void expand_assignment (tree, tree, bool);
+
+/* Generate code for computing expression EXP,
+ and storing the value into TARGET.
+ If SUGGEST_REG is nonzero, copy the value through a register
+ and return that register, if that is possible. */
+extern rtx store_expr (tree, rtx, int, bool, bool);
+
+/* Given an rtx that may include add and multiply operations,
+ generate them as insns and return a pseudo-reg containing the value.
+ Useful after calling expand_expr with 1 as sum_ok. */
+extern rtx force_operand (rtx, rtx);
+
+/* Work horses for expand_expr. */
+extern rtx expand_expr_real (tree, rtx, machine_mode,
+ enum expand_modifier, rtx *, bool);
+extern rtx expand_expr_real_1 (tree, rtx, machine_mode,
+ enum expand_modifier, rtx *, bool);
+extern rtx expand_expr_real_2 (sepops, rtx, machine_mode,
+ enum expand_modifier);
+
+/* Generate code for computing expression EXP.
+ An rtx for the computed value is returned. The value is never null.
+ In the case of a void EXP, const0_rtx is returned. */
+static inline rtx
+expand_expr (tree exp, rtx target, machine_mode mode,
+ enum expand_modifier modifier)
+{
+ return expand_expr_real (exp, target, mode, modifier, NULL, false);
+}
+
+static inline rtx
+expand_normal (tree exp)
+{
+ return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false);
+}
+
+
+/* Return STRING_CST and set offset, size and decl, if the first
+ argument corresponds to a string constant. */
+extern tree string_constant (tree, tree *, tree *, tree *);
+/* Similar to string_constant, return a STRING_CST corresponding
+ to the value representation of the first argument if it's
+ a constant. */
+extern tree byte_representation (tree, tree *, tree *, tree *);
+
+extern enum tree_code maybe_optimize_mod_cmp (enum tree_code, tree *, tree *);
+extern void maybe_optimize_sub_cmp_0 (enum tree_code, tree *, tree *);
+
+/* Two different ways of generating switch statements. */
+extern int try_casesi (tree, tree, tree, tree, rtx, rtx, rtx, profile_probability);
+extern int try_tablejump (tree, tree, tree, tree, rtx, rtx, profile_probability);
+
+extern int safe_from_p (const_rtx, tree, int);
+
+/* Get the personality libfunc for a function decl. */
+rtx get_personality_function (tree);
+
+/* Determine whether the LEN bytes can be moved by using several move
+ instructions. Return nonzero if a call to move_by_pieces should
+ succeed. */
+extern bool can_move_by_pieces (unsigned HOST_WIDE_INT, unsigned int);
+
+extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
+
+extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *,
+ HOST_WIDE_INT *, HOST_WIDE_INT *,
+ bool *);
+
+extern void expand_operands (tree, tree, rtx, rtx*, rtx*,
+ enum expand_modifier);
+
+/* rtl.h and tree.h were included. */
+/* Return an rtx for the size in bytes of the value of an expr. */
+extern rtx expr_size (tree);
+
+extern bool mem_ref_refers_to_non_mem_p (tree);
+extern bool non_mem_decl_p (tree);
+
+#endif /* GCC_EXPR_H */
diff --git a/support/cpp/gcc/file-find.cc b/support/cpp/gcc/file-find.cc
new file mode 100644
index 000000000..f4caea50d
--- /dev/null
+++ b/support/cpp/gcc/file-find.cc
@@ -0,0 +1,210 @@
+/* Utility functions for finding files relative to GCC binaries.
+ 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "filenames.h"
+#include "file-find.h"
+
+static bool debug = false;
+
+void
+find_file_set_debug (bool debug_state)
+{
+ debug = debug_state;
+}
+
+char *
+find_a_file (struct path_prefix *pprefix, const char *name, int mode)
+{
+ char *temp;
+ struct prefix_list *pl;
+ int len = pprefix->max_len + strlen (name) + 1;
+
+ if (debug)
+ fprintf (stderr, "Looking for '%s'\n", name);
+
+#ifdef HOST_EXECUTABLE_SUFFIX
+ len += strlen (HOST_EXECUTABLE_SUFFIX);
+#endif
+
+ temp = XNEWVEC (char, len);
+
+ /* Determine the filename to execute (special case for absolute paths). */
+
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ if (access (name, mode) == 0)
+ {
+ strcpy (temp, name);
+
+ if (debug)
+ fprintf (stderr, " - found: absolute path\n");
+
+ return temp;
+ }
+
+#ifdef HOST_EXECUTABLE_SUFFIX
+ /* Some systems have a suffix for executable files.
+ So try appending that. */
+ strcpy (temp, name);
+ strcat (temp, HOST_EXECUTABLE_SUFFIX);
+
+ if (access (temp, mode) == 0)
+ return temp;
+#endif
+
+ if (debug)
+ fprintf (stderr, " - failed to locate using absolute path\n");
+ }
+ else
+ for (pl = pprefix->plist; pl; pl = pl->next)
+ {
+ struct stat st;
+
+ strcpy (temp, pl->prefix);
+ strcat (temp, name);
+
+ if (stat (temp, &st) >= 0
+ && ! S_ISDIR (st.st_mode)
+ && access (temp, mode) == 0)
+ return temp;
+
+#ifdef HOST_EXECUTABLE_SUFFIX
+ /* Some systems have a suffix for executable files.
+ So try appending that. */
+ strcat (temp, HOST_EXECUTABLE_SUFFIX);
+
+ if (stat (temp, &st) >= 0
+ && ! S_ISDIR (st.st_mode)
+ && access (temp, mode) == 0)
+ return temp;
+#endif
+ }
+
+ if (debug && pprefix->plist == NULL)
+ fprintf (stderr, " - failed: no entries in prefix list\n");
+
+ free (temp);
+ return 0;
+}
+
+/* Add an entry for PREFIX to prefix list PREFIX.
+ Add at beginning if FIRST is true. */
+
+void
+do_add_prefix (struct path_prefix *pprefix, const char *prefix, bool first)
+{
+ struct prefix_list *pl, **prev;
+ int len;
+
+ if (pprefix->plist && !first)
+ {
+ for (pl = pprefix->plist; pl->next; pl = pl->next)
+ ;
+ prev = &pl->next;
+ }
+ else
+ prev = &pprefix->plist;
+
+ /* Keep track of the longest prefix. */
+
+ len = strlen (prefix);
+ if (len > pprefix->max_len)
+ pprefix->max_len = len;
+
+ pl = XNEW (struct prefix_list);
+ pl->prefix = xstrdup (prefix);
+
+ if (*prev)
+ pl->next = *prev;
+ else
+ pl->next = (struct prefix_list *) 0;
+ *prev = pl;
+}
+
+/* Add an entry for PREFIX at the end of prefix list PREFIX. */
+
+void
+add_prefix (struct path_prefix *pprefix, const char *prefix)
+{
+ do_add_prefix (pprefix, prefix, false);
+}
+
+/* Add an entry for PREFIX at the begin of prefix list PREFIX. */
+
+void
+add_prefix_begin (struct path_prefix *pprefix, const char *prefix)
+{
+ do_add_prefix (pprefix, prefix, true);
+}
+
+/* Take the value of the environment variable ENV, break it into a path, and
+ add of the entries to PPREFIX. */
+
+void
+prefix_from_env (const char *env, struct path_prefix *pprefix)
+{
+ const char *p;
+ p = getenv (env);
+
+ if (p)
+ prefix_from_string (p, pprefix);
+}
+
+void
+prefix_from_string (const char *p, struct path_prefix *pprefix)
+{
+ const char *startp, *endp;
+ char *nstore = XNEWVEC (char, strlen (p) + 3);
+
+ if (debug)
+ fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
+
+ startp = endp = p;
+ while (1)
+ {
+ if (*endp == PATH_SEPARATOR || *endp == 0)
+ {
+ strncpy (nstore, startp, endp-startp);
+ if (endp == startp)
+ {
+ strcpy (nstore, "./");
+ }
+ else if (! IS_DIR_SEPARATOR (endp[-1]))
+ {
+ nstore[endp-startp] = DIR_SEPARATOR;
+ nstore[endp-startp+1] = 0;
+ }
+ else
+ nstore[endp-startp] = 0;
+
+ if (debug)
+ fprintf (stderr, " - add prefix: %s\n", nstore);
+
+ add_prefix (pprefix, nstore);
+ if (*endp == 0)
+ break;
+ endp = startp = endp + 1;
+ }
+ else
+ endp++;
+ }
+ free (nstore);
+}
diff --git a/support/cpp/gcc/file-find.h b/support/cpp/gcc/file-find.h
new file mode 100644
index 000000000..54a276c72
--- /dev/null
+++ b/support/cpp/gcc/file-find.h
@@ -0,0 +1,47 @@
+/* Prototypes and data structures used for implementing functions for
+ finding files relative to GCC binaries.
+ 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/>. */
+
+#ifndef GCC_FILE_FIND_H
+#define GCC_FILE_FIND_H
+
+/* Structure to hold all the directories in which to search for files to
+ execute. */
+
+struct prefix_list
+{
+ const char *prefix; /* String to prepend to the path. */
+ struct prefix_list *next; /* Next in linked list. */
+};
+
+struct path_prefix
+{
+ struct prefix_list *plist; /* List of prefixes to try */
+ int max_len; /* Max length of a prefix in PLIST */
+ const char *name; /* Name of this list (used in config stuff) */
+};
+
+extern void find_file_set_debug (bool);
+extern char *find_a_file (struct path_prefix *, const char *, int);
+extern void add_prefix (struct path_prefix *, const char *);
+extern void add_prefix_begin (struct path_prefix *, const char *);
+extern void prefix_from_env (const char *, struct path_prefix *);
+extern void prefix_from_string (const char *, struct path_prefix *);
+
+#endif /* GCC_FILE_FIND_H */
diff --git a/support/cpp/gcc/file-prefix-map.cc b/support/cpp/gcc/file-prefix-map.cc
new file mode 100644
index 000000000..24733f831
--- /dev/null
+++ b/support/cpp/gcc/file-prefix-map.cc
@@ -0,0 +1,149 @@
+/* Implementation of file prefix remapping support (-f*-prefix-map options).
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "diagnostic.h"
+#include "file-prefix-map.h"
+
+/* Structure recording the mapping from source file and directory names at
+ compile time to those to be embedded in the compilation result (debug
+ information, the __FILE__ macro expansion, etc). */
+struct file_prefix_map
+{
+ const char *old_prefix;
+ const char *new_prefix;
+ size_t old_len;
+ size_t new_len;
+ struct file_prefix_map *next;
+};
+
+/* Record a file prefix mapping in the specified map. ARG is the argument to
+ -f*-prefix-map and must be of the form OLD=NEW. OPT is the option name
+ for diagnostics. */
+static void
+add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
+{
+ file_prefix_map *map;
+ const char *p;
+
+ /* Note: looking for the last '='. The thinking is we can control the paths
+ inside our projects but not where the users build them. */
+ p = strrchr (arg, '=');
+ if (!p)
+ {
+ error ("invalid argument %qs to %qs", arg, opt);
+ return;
+ }
+ map = XNEW (file_prefix_map);
+ map->old_prefix = xstrndup (arg, p - arg);
+ map->old_len = p - arg;
+ p++;
+ map->new_prefix = xstrdup (p);
+ map->new_len = strlen (p);
+ map->next = maps;
+ maps = map;
+}
+
+/* Perform user-specified mapping of filename prefixes. Return the
+ GC-allocated new name corresponding to FILENAME or FILENAME if no
+ remapping was performed. */
+
+static const char *
+remap_filename (file_prefix_map *maps, const char *filename)
+{
+ file_prefix_map *map;
+ char *s;
+ const char *name;
+ size_t name_len;
+
+ for (map = maps; map; map = map->next)
+ if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
+ break;
+ if (!map)
+ return filename;
+ name = filename + map->old_len;
+ name_len = strlen (name) + 1;
+
+ s = (char *) ggc_alloc_atomic (name_len + map->new_len);
+ memcpy (s, map->new_prefix, map->new_len);
+ memcpy (s + map->new_len, name, name_len);
+ return s;
+}
+
+/* NOTE: if adding another -f*-prefix-map option then don't forget to
+ ignore it in DW_AT_producer (dwarf2out.cc). */
+
+/* Linked lists of file_prefix_map structures. */
+static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map */
+static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map */
+static file_prefix_map *profile_prefix_maps; /* -fprofile-prefix-map */
+
+/* Record a file prefix mapping for -fmacro-prefix-map. */
+void
+add_macro_prefix_map (const char *arg)
+{
+ add_prefix_map (macro_prefix_maps, arg, "-fmacro-prefix-map");
+}
+
+/* Record a file prefix mapping for -fdebug-prefix-map. */
+void
+add_debug_prefix_map (const char *arg)
+{
+ add_prefix_map (debug_prefix_maps, arg, "-fdebug-prefix-map");
+}
+
+/* Record a file prefix mapping for all -f*-prefix-map. */
+void
+add_file_prefix_map (const char *arg)
+{
+ add_prefix_map (macro_prefix_maps, arg, "-ffile-prefix-map");
+ add_prefix_map (debug_prefix_maps, arg, "-ffile-prefix-map");
+ add_prefix_map (profile_prefix_maps, arg, "-ffile-prefix-map");
+}
+
+/* Record a file prefix mapping for -fprofile-prefix-map. */
+void
+add_profile_prefix_map (const char *arg)
+{
+ add_prefix_map (profile_prefix_maps, arg, "-fprofile-prefix-map");
+}
+
+/* Remap using -fmacro-prefix-map. Return the GC-allocated new name
+ corresponding to FILENAME or FILENAME if no remapping was performed. */
+const char *
+remap_macro_filename (const char *filename)
+{
+ return remap_filename (macro_prefix_maps, filename);
+}
+
+/* Remap using -fdebug-prefix-map. Return the GC-allocated new name
+ corresponding to FILENAME or FILENAME if no remapping was performed. */
+const char *
+remap_debug_filename (const char *filename)
+{
+ return remap_filename (debug_prefix_maps, filename);
+}
+
+/* Remap using -fprofile-prefix-map. Return the GC-allocated new name
+ corresponding to FILENAME or FILENAME if no remapping was performed. */
+const char *
+remap_profile_filename (const char *filename)
+{
+ return remap_filename (profile_prefix_maps, filename);
+}
diff --git a/support/cpp/gcc/file-prefix-map.h b/support/cpp/gcc/file-prefix-map.h
new file mode 100644
index 000000000..d97584096
--- /dev/null
+++ b/support/cpp/gcc/file-prefix-map.h
@@ -0,0 +1,30 @@
+/* Declarations for file prefix remapping support (-f*-prefix-map options).
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_FILE_PREFIX_MAP_H
+#define GCC_FILE_PREFIX_MAP_H
+
+void add_macro_prefix_map (const char *);
+void add_debug_prefix_map (const char *);
+void add_file_prefix_map (const char *);
+void add_profile_prefix_map (const char *);
+
+const char *remap_macro_filename (const char *);
+const char *remap_debug_filename (const char *);
+const char *remap_profile_filename (const char *);
+
+#endif /* !GCC_FILE_PREFIX_MAP_H */
diff --git a/support/cpp/gcc/fixed-value.h b/support/cpp/gcc/fixed-value.h
new file mode 100644
index 000000000..722b26ce5
--- /dev/null
+++ b/support/cpp/gcc/fixed-value.h
@@ -0,0 +1,111 @@
+/* Fixed-point arithmetic support.
+ Copyright (C) 2006-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_FIXED_VALUE_H
+#define GCC_FIXED_VALUE_H
+
+struct GTY(()) fixed_value
+{
+ double_int data; /* Store data up to 2 wide integers. */
+ scalar_mode_pod mode; /* Use machine mode to know IBIT and FBIT. */
+};
+
+#define FIXED_VALUE_TYPE struct fixed_value
+
+#define MAX_FCONST0 18 /* For storing 18 fixed-point zeros per
+ fract, ufract, accum, and uaccum modes . */
+#define MAX_FCONST1 8 /* For storing 8 fixed-point ones per accum
+ and uaccum modes. */
+/* Constant fixed-point values 0 and 1. */
+extern FIXED_VALUE_TYPE fconst0[MAX_FCONST0];
+extern FIXED_VALUE_TYPE fconst1[MAX_FCONST1];
+
+/* Macros to access fconst0 and fconst1 via machine modes. */
+#define FCONST0(mode) fconst0[mode - QQmode]
+#define FCONST1(mode) fconst1[mode - HAmode]
+
+/* Return a CONST_FIXED with value R and mode M. */
+#define CONST_FIXED_FROM_FIXED_VALUE(r, m) \
+ const_fixed_from_fixed_value (r, m)
+extern rtx const_fixed_from_fixed_value (FIXED_VALUE_TYPE, machine_mode);
+
+/* Construct a FIXED_VALUE from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are sign-extended/zero-extended according to MODE. */
+extern FIXED_VALUE_TYPE fixed_from_double_int (double_int, scalar_mode);
+
+/* Return a CONST_FIXED from a bit payload and machine mode MODE.
+ The bits in PAYLOAD are sign-extended/zero-extended according to MODE. */
+static inline rtx
+const_fixed_from_double_int (double_int payload,
+ scalar_mode mode)
+{
+ return
+ const_fixed_from_fixed_value (fixed_from_double_int (payload, mode),
+ mode);
+}
+
+/* Initialize from a decimal or hexadecimal string. */
+extern void fixed_from_string (FIXED_VALUE_TYPE *, const char *,
+ scalar_mode);
+
+/* In tree.cc: wrap up a FIXED_VALUE_TYPE in a tree node. */
+extern tree build_fixed (tree, FIXED_VALUE_TYPE);
+
+/* Extend or truncate to a new mode. */
+extern bool fixed_convert (FIXED_VALUE_TYPE *, scalar_mode,
+ const FIXED_VALUE_TYPE *, bool);
+
+/* Convert to a fixed-point mode from an integer. */
+extern bool fixed_convert_from_int (FIXED_VALUE_TYPE *, scalar_mode,
+ double_int, bool, bool);
+
+/* Convert to a fixed-point mode from a real. */
+extern bool fixed_convert_from_real (FIXED_VALUE_TYPE *, scalar_mode,
+ const REAL_VALUE_TYPE *, bool);
+
+/* Convert to a real mode from a fixed-point. */
+extern void real_convert_from_fixed (REAL_VALUE_TYPE *, scalar_mode,
+ const FIXED_VALUE_TYPE *);
+
+/* Compare two fixed-point objects for bitwise identity. */
+extern bool fixed_identical (const FIXED_VALUE_TYPE *, const FIXED_VALUE_TYPE *);
+
+/* Calculate a hash value. */
+extern unsigned int fixed_hash (const FIXED_VALUE_TYPE *);
+
+#define FIXED_VALUES_IDENTICAL(x, y) fixed_identical (&(x), &(y))
+
+/* Determine whether a fixed-point value X is negative. */
+#define FIXED_VALUE_NEGATIVE(x) fixed_isneg (&(x))
+
+/* Render F as a decimal floating point constant. */
+extern void fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *, size_t);
+
+/* Binary or unary arithmetic on tree_code. */
+extern bool fixed_arithmetic (FIXED_VALUE_TYPE *, int, const FIXED_VALUE_TYPE *,
+ const FIXED_VALUE_TYPE *, bool);
+
+/* Compare fixed-point values by tree_code. */
+extern bool fixed_compare (int, const FIXED_VALUE_TYPE *,
+ const FIXED_VALUE_TYPE *);
+
+/* Determine whether a fixed-point value X is negative. */
+extern bool fixed_isneg (const FIXED_VALUE_TYPE *);
+
+#endif /* GCC_FIXED_VALUE_H */
diff --git a/support/cpp/gcc/flag-types.h b/support/cpp/gcc/flag-types.h
new file mode 100644
index 000000000..2c8498169
--- /dev/null
+++ b/support/cpp/gcc/flag-types.h
@@ -0,0 +1,514 @@
+/* Compilation switch flag type definitions for GCC.
+ 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/>. */
+
+#ifndef GCC_FLAG_TYPES_H
+#define GCC_FLAG_TYPES_H
+
+#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
+
+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_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). */
+#define CTF_DEBUG (1U << DINFO_TYPE_CTF)
+/* Write BTF debug info (using btfout.cc). */
+#define BTF_DEBUG (1U << DINFO_TYPE_BTF)
+/* Write BTF debug info for BPF CO-RE usecase (using btfout.cc). */
+#define BTF_WITH_CORE_DEBUG (1U << DINFO_TYPE_BTF_WITH_CORE)
+
+/* Note: Adding new definitions to handle -combination- of debug formats,
+ like VMS_AND_DWARF2_DEBUG is not recommended. This definition remains
+ here for historical reasons. */
+/* Write VMS debug info (using vmsdbgout.cc) and DWARF v2 debug info (using
+ dwarf2out.cc). */
+#define VMS_AND_DWARF2_DEBUG ((VMS_DEBUG | DWARF2_DEBUG))
+
+enum debug_info_levels
+{
+ DINFO_LEVEL_NONE, /* Write no debugging info. */
+ DINFO_LEVEL_TERSE, /* Write minimal info to support tracebacks only. */
+ DINFO_LEVEL_NORMAL, /* Write info for all declarations (and line table). */
+ DINFO_LEVEL_VERBOSE /* Write normal info plus #define/#undef info. */
+};
+
+/* CTF debug info levels.
+ CTF debug info levels are untied with DWARF debug info levels because CTF
+ may co-exist with DWARF. */
+enum ctf_debug_info_levels
+{
+ CTFINFO_LEVEL_NONE = 0, /* Write no CTF debug info. */
+ CTFINFO_LEVEL_TERSE = 1, /* Write CTF information to support tracebacks
+ only. Not Implemented. */
+ CTFINFO_LEVEL_NORMAL = 2 /* Write CTF type information for all entities
+ (functions, data objects, variables etc.)
+ at file-scope or global-scope only. */
+};
+
+/* A major contribution to object and executable size is debug
+ information size. A major contribution to debug information
+ size is struct descriptions replicated in several object files.
+ The following function determines whether or not debug information
+ should be generated for a given struct. The indirect parameter
+ indicates that the struct is being handled indirectly, via
+ a pointer. See opts.cc for the implementation. */
+
+enum debug_info_usage
+{
+ DINFO_USAGE_DFN, /* A struct definition. */
+ DINFO_USAGE_DIR_USE, /* A direct use, such as the type of a variable. */
+ DINFO_USAGE_IND_USE, /* An indirect use, such as through a pointer. */
+ DINFO_USAGE_NUM_ENUMS /* The number of enumerators. */
+};
+
+/* A major contribution to object and executable size is debug
+ information size. A major contribution to debug information size
+ is struct descriptions replicated in several object files. The
+ following flags attempt to reduce this information. The basic
+ idea is to not emit struct debugging information in the current
+ compilation unit when that information will be generated by
+ another compilation unit.
+
+ Debug information for a struct defined in the current source
+ file should be generated in the object file. Likewise the
+ debug information for a struct defined in a header should be
+ generated in the object file of the corresponding source file.
+ Both of these case are handled when the base name of the file of
+ the struct definition matches the base name of the source file
+ of the current compilation unit. This matching emits minimal
+ struct debugging information.
+
+ The base file name matching rule above will fail to emit debug
+ information for structs defined in system headers. So a second
+ category of files includes system headers in addition to files
+ with matching bases.
+
+ The remaining types of files are library headers and application
+ headers. We cannot currently distinguish these two types. */
+
+enum debug_struct_file
+{
+ DINFO_STRUCT_FILE_NONE, /* Debug no structs. */
+ DINFO_STRUCT_FILE_BASE, /* Debug structs defined in files with the
+ same base name as the compilation unit. */
+ DINFO_STRUCT_FILE_SYS, /* Also debug structs defined in system
+ header files. */
+ DINFO_STRUCT_FILE_ANY /* Debug structs defined in all files. */
+};
+
+/* Balance between GNAT encodings and standard DWARF to emit. */
+
+enum dwarf_gnat_encodings
+{
+ DWARF_GNAT_ENCODINGS_ALL = 0, /* Emit all GNAT encodings, then emit as
+ much standard DWARF as possible so it
+ does not conflict with GNAT
+ encodings. */
+ DWARF_GNAT_ENCODINGS_GDB = 1, /* Emit as much standard DWARF as possible
+ as long as GDB handles them. Emit GNAT
+ encodings for the rest. */
+ DWARF_GNAT_ENCODINGS_MINIMAL = 2 /* Emit all the standard DWARF we can.
+ Emit GNAT encodings for the rest. */
+};
+
+/* Enumerate Objective-c instance variable visibility settings. */
+
+enum ivar_visibility
+{
+ IVAR_VISIBILITY_PRIVATE,
+ IVAR_VISIBILITY_PROTECTED,
+ IVAR_VISIBILITY_PUBLIC,
+ IVAR_VISIBILITY_PACKAGE
+};
+
+/* The stack reuse level. */
+enum stack_reuse_level
+{
+ SR_NONE,
+ SR_NAMED_VARS,
+ SR_ALL
+};
+
+/* The live patching level. */
+enum live_patching_level
+{
+ LIVE_PATCHING_NONE = 0,
+ LIVE_PATCHING_INLINE_ONLY_STATIC,
+ LIVE_PATCHING_INLINE_CLONE
+};
+
+/* The algorithm used for basic block reordering. */
+enum reorder_blocks_algorithm
+{
+ REORDER_BLOCKS_ALGORITHM_SIMPLE,
+ REORDER_BLOCKS_ALGORITHM_STC
+};
+
+/* The algorithm used for the integrated register allocator (IRA). */
+enum ira_algorithm
+{
+ IRA_ALGORITHM_CB,
+ IRA_ALGORITHM_PRIORITY
+};
+
+/* The regions used for the integrated register allocator (IRA). */
+enum ira_region
+{
+ IRA_REGION_ONE,
+ IRA_REGION_ALL,
+ IRA_REGION_MIXED,
+};
+
+/* The options for excess precision. */
+enum excess_precision
+{
+ EXCESS_PRECISION_DEFAULT,
+ EXCESS_PRECISION_FAST,
+ EXCESS_PRECISION_STANDARD,
+ EXCESS_PRECISION_FLOAT16
+};
+
+/* The options for which values of FLT_EVAL_METHOD are permissible. */
+enum permitted_flt_eval_methods
+{
+ PERMITTED_FLT_EVAL_METHODS_DEFAULT,
+ PERMITTED_FLT_EVAL_METHODS_TS_18661,
+ PERMITTED_FLT_EVAL_METHODS_C11
+};
+
+/* Type of stack check.
+
+ Stack checking is designed to detect infinite recursion and stack
+ overflows for Ada programs. Furthermore stack checking tries to ensure
+ in that scenario that enough stack space is left to run a signal handler.
+
+ -fstack-check= does not prevent stack-clash style attacks. For that
+ you want -fstack-clash-protection. */
+enum stack_check_type
+{
+ /* Do not check the stack. */
+ NO_STACK_CHECK = 0,
+
+ /* Check the stack generically, i.e. assume no specific support
+ from the target configuration files. */
+ GENERIC_STACK_CHECK,
+
+ /* Check the stack and rely on the target configuration files to
+ check the static frame of functions, i.e. use the generic
+ mechanism only for dynamic stack allocations. */
+ STATIC_BUILTIN_STACK_CHECK,
+
+ /* Check the stack and entirely rely on the target configuration
+ files, i.e. do not use the generic mechanism at all. */
+ FULL_BUILTIN_STACK_CHECK
+};
+
+/* Type of callgraph information. */
+enum callgraph_info_type
+{
+ /* No information. */
+ NO_CALLGRAPH_INFO = 0,
+
+ /* Naked callgraph. */
+ CALLGRAPH_INFO_NAKED = 1,
+
+ /* Callgraph decorated with stack usage information. */
+ CALLGRAPH_INFO_STACK_USAGE = 2,
+
+ /* Callgraph decoration with dynamic allocation information. */
+ CALLGRAPH_INFO_DYNAMIC_ALLOC = 4
+};
+
+/* Floating-point contraction mode. */
+enum fp_contract_mode {
+ FP_CONTRACT_OFF = 0,
+ FP_CONTRACT_ON = 1,
+ FP_CONTRACT_FAST = 2
+};
+
+/* Scalar storage order kind. */
+enum scalar_storage_order_kind {
+ SSO_NATIVE = 0,
+ SSO_BIG_ENDIAN,
+ SSO_LITTLE_ENDIAN
+};
+
+/* Vectorizer cost-model. Except for DEFAULT, the values are ordered from
+ the most conservative to the least conservative. */
+enum vect_cost_model {
+ VECT_COST_MODEL_VERY_CHEAP = -3,
+ VECT_COST_MODEL_CHEAP = -2,
+ VECT_COST_MODEL_DYNAMIC = -1,
+ VECT_COST_MODEL_UNLIMITED = 0,
+ VECT_COST_MODEL_DEFAULT = 1
+};
+
+/* Automatic variable initialization type. */
+enum auto_init_type {
+ AUTO_INIT_UNINITIALIZED = 0,
+ AUTO_INIT_PATTERN = 1,
+ AUTO_INIT_ZERO = 2
+};
+
+/* Different instrumentation modes. */
+enum sanitize_code {
+ /* AddressSanitizer. */
+ SANITIZE_ADDRESS = 1UL << 0,
+ SANITIZE_USER_ADDRESS = 1UL << 1,
+ SANITIZE_KERNEL_ADDRESS = 1UL << 2,
+ /* ThreadSanitizer. */
+ SANITIZE_THREAD = 1UL << 3,
+ /* LeakSanitizer. */
+ SANITIZE_LEAK = 1UL << 4,
+ /* UndefinedBehaviorSanitizer. */
+ SANITIZE_SHIFT_BASE = 1UL << 5,
+ SANITIZE_SHIFT_EXPONENT = 1UL << 6,
+ SANITIZE_DIVIDE = 1UL << 7,
+ SANITIZE_UNREACHABLE = 1UL << 8,
+ SANITIZE_VLA = 1UL << 9,
+ SANITIZE_NULL = 1UL << 10,
+ SANITIZE_RETURN = 1UL << 11,
+ SANITIZE_SI_OVERFLOW = 1UL << 12,
+ SANITIZE_BOOL = 1UL << 13,
+ SANITIZE_ENUM = 1UL << 14,
+ SANITIZE_FLOAT_DIVIDE = 1UL << 15,
+ SANITIZE_FLOAT_CAST = 1UL << 16,
+ SANITIZE_BOUNDS = 1UL << 17,
+ SANITIZE_ALIGNMENT = 1UL << 18,
+ SANITIZE_NONNULL_ATTRIBUTE = 1UL << 19,
+ SANITIZE_RETURNS_NONNULL_ATTRIBUTE = 1UL << 20,
+ SANITIZE_OBJECT_SIZE = 1UL << 21,
+ SANITIZE_VPTR = 1UL << 22,
+ SANITIZE_BOUNDS_STRICT = 1UL << 23,
+ SANITIZE_POINTER_OVERFLOW = 1UL << 24,
+ SANITIZE_BUILTIN = 1UL << 25,
+ SANITIZE_POINTER_COMPARE = 1UL << 26,
+ SANITIZE_POINTER_SUBTRACT = 1UL << 27,
+ SANITIZE_HWADDRESS = 1UL << 28,
+ SANITIZE_USER_HWADDRESS = 1UL << 29,
+ SANITIZE_KERNEL_HWADDRESS = 1UL << 30,
+ /* Shadow Call Stack. */
+ SANITIZE_SHADOW_CALL_STACK = 1UL << 31,
+ SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
+ SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
+ | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
+ | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM
+ | SANITIZE_BOUNDS | SANITIZE_ALIGNMENT
+ | SANITIZE_NONNULL_ATTRIBUTE
+ | SANITIZE_RETURNS_NONNULL_ATTRIBUTE
+ | SANITIZE_OBJECT_SIZE | SANITIZE_VPTR
+ | SANITIZE_POINTER_OVERFLOW | SANITIZE_BUILTIN,
+ SANITIZE_UNDEFINED_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST
+ | SANITIZE_BOUNDS_STRICT
+};
+
+/* Different settings for zeroing subset of registers. */
+namespace zero_regs_flags {
+ const unsigned int UNSET = 0;
+ const unsigned int SKIP = 1UL << 0;
+ const unsigned int ONLY_USED = 1UL << 1;
+ const unsigned int ONLY_GPR = 1UL << 2;
+ const unsigned int ONLY_ARG = 1UL << 3;
+ const unsigned int ENABLED = 1UL << 4;
+ const unsigned int USED_GPR_ARG = ENABLED | ONLY_USED | ONLY_GPR | ONLY_ARG;
+ const unsigned int USED_GPR = ENABLED | ONLY_USED | ONLY_GPR;
+ const unsigned int USED_ARG = ENABLED | ONLY_USED | ONLY_ARG;
+ const unsigned int USED = ENABLED | ONLY_USED;
+ const unsigned int ALL_GPR_ARG = ENABLED | ONLY_GPR | ONLY_ARG;
+ const unsigned int ALL_GPR = ENABLED | ONLY_GPR;
+ const unsigned int ALL_ARG = ENABLED | ONLY_ARG;
+ const unsigned int ALL = ENABLED;
+}
+
+/* Settings of flag_incremental_link. */
+enum incremental_link {
+ INCREMENTAL_LINK_NONE,
+ /* Do incremental linking and produce binary. */
+ INCREMENTAL_LINK_NOLTO,
+ /* Do incremental linking and produce IL. */
+ INCREMENTAL_LINK_LTO
+};
+
+/* Different trace modes. */
+enum sanitize_coverage_code {
+ /* Trace PC. */
+ SANITIZE_COV_TRACE_PC = 1 << 0,
+ /* Trace Comparison. */
+ SANITIZE_COV_TRACE_CMP = 1 << 1
+};
+
+/* flag_vtable_verify initialization levels. */
+enum vtv_priority {
+ VTV_NO_PRIORITY = 0, /* i.E. Do NOT do vtable verification. */
+ VTV_STANDARD_PRIORITY = 1,
+ VTV_PREINIT_PRIORITY = 2
+};
+
+/* flag_lto_partition initialization values. */
+enum lto_partition_model {
+ LTO_PARTITION_NONE = 0,
+ LTO_PARTITION_ONE = 1,
+ LTO_PARTITION_BALANCED = 2,
+ LTO_PARTITION_1TO1 = 3,
+ LTO_PARTITION_MAX = 4
+};
+
+/* flag_lto_linker_output initialization values. */
+enum lto_linker_output {
+ LTO_LINKER_OUTPUT_UNKNOWN,
+ LTO_LINKER_OUTPUT_REL,
+ LTO_LINKER_OUTPUT_NOLTOREL,
+ LTO_LINKER_OUTPUT_DYN,
+ LTO_LINKER_OUTPUT_PIE,
+ LTO_LINKER_OUTPUT_EXEC
+};
+
+/* gfortran -finit-real= values. */
+
+enum gfc_init_local_real
+{
+ GFC_INIT_REAL_OFF = 0,
+ GFC_INIT_REAL_ZERO,
+ GFC_INIT_REAL_NAN,
+ GFC_INIT_REAL_SNAN,
+ GFC_INIT_REAL_INF,
+ GFC_INIT_REAL_NEG_INF
+};
+
+/* gfortran -fcoarray= values. */
+
+enum gfc_fcoarray
+{
+ GFC_FCOARRAY_NONE = 0,
+ GFC_FCOARRAY_SINGLE,
+ GFC_FCOARRAY_LIB
+};
+
+
+/* gfortran -fconvert= values; used for unformatted I/O.
+ Keep in sync with GFC_CONVERT_* in gcc/fortran/libgfortran.h. */
+enum gfc_convert
+{
+ GFC_FLAG_CONVERT_NATIVE = 0,
+ GFC_FLAG_CONVERT_SWAP,
+ GFC_FLAG_CONVERT_BIG,
+ GFC_FLAG_CONVERT_LITTLE,
+ GFC_FLAG_CONVERT_R16_IEEE = 4,
+ GFC_FLAG_CONVERT_R16_IEEE_SWAP,
+ GFC_FLAG_CONVERT_R16_IEEE_BIG,
+ GFC_FLAG_CONVERT_R16_IEEE_LITTLE,
+ GFC_FLAG_CONVERT_R16_IBM = 8,
+ GFC_FLAG_CONVERT_R16_IBM_SWAP,
+ GFC_FLAG_CONVERT_R16_IBM_BIG,
+ GFC_FLAG_CONVERT_R16_IBM_LITTLE,
+};
+
+
+/* Control-Flow Protection values. */
+enum cf_protection_level
+{
+ CF_NONE = 0,
+ CF_BRANCH = 1 << 0,
+ CF_RETURN = 1 << 1,
+ CF_FULL = CF_BRANCH | CF_RETURN,
+ CF_SET = 1 << 2,
+ CF_CHECK = 1 << 3
+};
+
+/* Parloops schedule type. */
+enum parloops_schedule_type
+{
+ PARLOOPS_SCHEDULE_STATIC = 0,
+ PARLOOPS_SCHEDULE_DYNAMIC,
+ PARLOOPS_SCHEDULE_GUIDED,
+ PARLOOPS_SCHEDULE_AUTO,
+ PARLOOPS_SCHEDULE_RUNTIME
+};
+
+/* Ranger debug mode. */
+enum ranger_debug
+{
+ RANGER_DEBUG_NONE = 0,
+ RANGER_DEBUG_TRACE = 1,
+ RANGER_DEBUG_CACHE = 2,
+ RANGER_DEBUG_GORI = 4,
+ RANGER_DEBUG_TRACE_GORI = (RANGER_DEBUG_TRACE | RANGER_DEBUG_GORI),
+ RANGER_DEBUG_TRACE_CACHE = (RANGER_DEBUG_TRACE | RANGER_DEBUG_CACHE),
+ RANGER_DEBUG_ALL = (RANGER_DEBUG_GORI | RANGER_DEBUG_CACHE
+ | RANGER_DEBUG_TRACE)
+};
+
+/* Jump threader verbose dumps. */
+enum threader_debug
+{
+ THREADER_DEBUG_NONE = 0,
+ THREADER_DEBUG_ALL = 1
+};
+
+/* EVRP mode. */
+enum evrp_mode
+{
+ EVRP_MODE_RVRP_ONLY,
+ EVRP_MODE_EVRP_ONLY,
+ EVRP_MODE_EVRP_FIRST,
+ EVRP_MODE_RVRP_FIRST
+};
+
+/* VRP modes. */
+enum vrp_mode
+{
+ VRP_MODE_VRP,
+ VRP_MODE_RANGER
+};
+
+/* Modes of OpenACC 'kernels' constructs handling. */
+enum openacc_kernels
+{
+ OPENACC_KERNELS_DECOMPOSE,
+ OPENACC_KERNELS_PARLOOPS
+};
+
+/* Modes of OpenACC privatization diagnostics. */
+enum openacc_privatization
+{
+ OPENACC_PRIVATIZATION_QUIET,
+ OPENACC_PRIVATIZATION_NOISY
+};
+
+#endif
+
+#endif /* ! GCC_FLAG_TYPES_H */
diff --git a/support/cpp/gcc/flags.h b/support/cpp/gcc/flags.h
new file mode 100644
index 000000000..a9381cf93
--- /dev/null
+++ b/support/cpp/gcc/flags.h
@@ -0,0 +1,115 @@
+/* Compilation switch flag definitions for GCC.
+ 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/>. */
+
+#ifndef GCC_FLAGS_H
+#define GCC_FLAGS_H
+
+#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
+
+/* Names of fundamental debug info formats indexed by enum
+ debug_info_type. */
+
+extern const char *const debug_type_names[];
+
+/* Get enum debug_info_type of the specified debug format, for error messages.
+ Can be used only for individual debug format types. */
+
+extern enum debug_info_type debug_set_to_format (uint32_t debug_info_set);
+
+/* Get the number of debug formats enabled for output. */
+
+unsigned int debug_set_count (uint32_t w_symbols);
+
+/* Get the names of the debug formats enabled for output. */
+
+const char * debug_set_names (uint32_t w_symbols);
+
+/* Return true iff BTF debug info is enabled. */
+
+extern bool btf_debuginfo_p ();
+
+/* Return true iff BTF with CO-RE debug info is enabled. */
+
+extern bool btf_with_core_debuginfo_p ();
+
+/* Return true iff CTF debug info is enabled. */
+
+extern bool ctf_debuginfo_p ();
+
+/* Return true iff DWARF2 debug info is enabled. */
+
+extern bool dwarf_debuginfo_p ();
+
+/* Return true iff the debug info format is to be generated based on DWARF
+ DIEs (like CTF and BTF debug info formats). */
+
+extern bool dwarf_based_debuginfo_p ();
+
+extern void strip_off_ending (char *, int);
+extern int base_of_path (const char *path, const char **base_out);
+
+/* Return true iff flags are set as if -ffast-math. */
+extern bool fast_math_flags_set_p (const struct gcc_options *);
+extern bool fast_math_flags_struct_set_p (struct cl_optimization *);
+
+
+/* Now the symbols that are set with `-f' switches. */
+
+/* True if printing into -fdump-final-insns= dump. */
+
+extern bool final_insns_dump_p;
+
+
+/* Other basic status info about current function. */
+
+class target_flag_state
+{
+public:
+ /* Each falign-foo can generate up to two levels of alignment:
+ -falign-foo=N:M[:N2:M2] */
+ align_flags x_align_loops;
+ align_flags x_align_jumps;
+ align_flags x_align_labels;
+ align_flags x_align_functions;
+};
+
+extern class target_flag_state default_target_flag_state;
+#if SWITCHABLE_TARGET
+extern class target_flag_state *this_target_flag_state;
+#else
+#define this_target_flag_state (&default_target_flag_state)
+#endif
+
+#define align_loops (this_target_flag_state->x_align_loops)
+#define align_jumps (this_target_flag_state->x_align_jumps)
+#define align_labels (this_target_flag_state->x_align_labels)
+#define align_functions (this_target_flag_state->x_align_functions)
+
+/* Returns TRUE if generated code should match ABI version N or
+ greater is in use. */
+
+#define abi_version_at_least(N) \
+ (flag_abi_version == 0 || flag_abi_version >= (N))
+
+/* Whether to emit an overflow warning whose code is C. */
+#define issue_strict_overflow_warning(c) (warn_strict_overflow >= (int) (c))
+
+#endif
+
+#endif /* ! GCC_FLAGS_H */
diff --git a/support/cpp/gcc/fold-const.h b/support/cpp/gcc/fold-const.h
new file mode 100644
index 000000000..ffc4f386a
--- /dev/null
+++ b/support/cpp/gcc/fold-const.h
@@ -0,0 +1,270 @@
+/* Fold a constant sub-tree into a single node for C-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/>. */
+
+#if 0 // sdcpp ndef GCC_FOLD_CONST_H
+#define GCC_FOLD_CONST_H
+
+/* Nonzero if we are folding constants inside an initializer or a C++
+ manifestly-constant-evaluated context; zero otherwise.
+ Should be used when folding in initializer enables additional
+ optimizations. */
+extern int folding_initializer;
+/* Nonzero if we are folding C++ manifestly-constant-evaluated context; zero
+ otherwise.
+ Should be used when certain constructs shouldn't be optimized
+ during folding in that context. */
+extern bool folding_cxx_constexpr;
+
+/* Convert between trees and native memory representation. */
+extern int native_encode_expr (const_tree, unsigned char *, int, int off = -1);
+extern int native_encode_initializer (tree, unsigned char *, int,
+ int off = -1, unsigned char * = nullptr);
+extern tree native_interpret_expr (tree, const unsigned char *, int);
+extern tree native_interpret_real (tree, const unsigned char *, int);
+extern bool can_native_interpret_type_p (tree);
+extern tree native_interpret_aggregate (tree, const unsigned char *, int, int);
+extern tree find_bitfield_repr_type (int, int);
+extern void shift_bytes_in_array_left (unsigned char *, unsigned int,
+ unsigned int);
+extern void shift_bytes_in_array_right (unsigned char *, unsigned int,
+ unsigned int);
+
+/* Fold constants as much as possible in an expression.
+ Returns the simplified expression.
+ Acts only on the top level of the expression;
+ if the argument itself cannot be simplified, its
+ subexpressions are not changed. */
+
+extern tree fold (tree);
+extern tree fold_init (tree);
+#define fold_unary(CODE,T1,T2)\
+ fold_unary_loc (UNKNOWN_LOCATION, CODE, T1, T2)
+extern tree fold_unary_loc (location_t, enum tree_code, tree, tree);
+#define fold_unary_ignore_overflow(CODE,T1,T2)\
+ fold_unary_ignore_overflow_loc (UNKNOWN_LOCATION, CODE, T1, T2)
+extern tree fold_unary_ignore_overflow_loc (location_t, enum tree_code, tree, tree);
+#define fold_binary(CODE,T1,T2,T3)\
+ fold_binary_loc (UNKNOWN_LOCATION, CODE, T1, T2, T3)
+extern tree fold_binary_loc (location_t, enum tree_code, tree, tree, tree);
+#define fold_ternary(CODE,T1,T2,T3,T4)\
+ fold_ternary_loc (UNKNOWN_LOCATION, CODE, T1, T2, T3, T4)
+extern tree fold_ternary_loc (location_t, enum tree_code, tree, tree, tree, tree);
+#define fold_build1(c,t1,t2)\
+ fold_build1_loc (UNKNOWN_LOCATION, c, t1, t2 MEM_STAT_INFO)
+extern tree fold_build1_loc (location_t, enum tree_code, tree,
+ tree CXX_MEM_STAT_INFO);
+#define fold_build2(c,t1,t2,t3)\
+ fold_build2_loc (UNKNOWN_LOCATION, c, t1, t2, t3 MEM_STAT_INFO)
+extern tree fold_build2_loc (location_t, enum tree_code, tree, tree,
+ tree CXX_MEM_STAT_INFO);
+#define fold_build3(c,t1,t2,t3,t4)\
+ fold_build3_loc (UNKNOWN_LOCATION, c, t1, t2, t3, t4 MEM_STAT_INFO)
+extern tree fold_build3_loc (location_t, enum tree_code, tree, tree, tree,
+ tree CXX_MEM_STAT_INFO);
+extern tree fold_build1_initializer_loc (location_t, enum tree_code, tree, tree);
+extern tree fold_build2_initializer_loc (location_t, enum tree_code, tree, tree, tree);
+#define fold_build_call_array(T1,T2,N,T4)\
+ fold_build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
+extern tree fold_build_call_array_loc (location_t, tree, tree, int, tree *);
+#define fold_build_call_array_initializer(T1,T2,N,T4)\
+ fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
+extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
+extern tree fold_binary_initializer_loc (location_t, tree_code, tree, tree, tree);
+extern tree get_array_ctor_element_at_index (tree, offset_int,
+ unsigned * = NULL);
+extern bool fold_convertible_p (const_tree, const_tree);
+#define fold_convert(T1,T2)\
+ fold_convert_loc (UNKNOWN_LOCATION, T1, T2)
+extern tree fold_convert_loc (location_t, tree, tree);
+extern tree fold_single_bit_test (location_t, enum tree_code, tree, tree, tree);
+extern tree fold_ignored_result (tree);
+extern tree fold_abs_const (tree, tree);
+extern tree fold_indirect_ref_1 (location_t, tree, tree);
+extern void fold_defer_overflow_warnings (void);
+extern void fold_undefer_overflow_warnings (bool, const gimple *, int);
+extern void fold_undefer_and_ignore_overflow_warnings (void);
+extern bool fold_deferring_overflow_warnings_p (void);
+extern void fold_overflow_warning (const char*, enum warn_strict_overflow_code);
+extern enum tree_code fold_div_compare (enum tree_code, tree, tree,
+ tree *, tree *, bool *);
+extern bool operand_equal_p (const_tree, const_tree, unsigned int flags = 0);
+extern int multiple_of_p (tree, const_tree, const_tree, bool = true);
+#define omit_one_operand(T1,T2,T3)\
+ omit_one_operand_loc (UNKNOWN_LOCATION, T1, T2, T3)
+extern tree omit_one_operand_loc (location_t, tree, tree, tree);
+#define omit_two_operands(T1,T2,T3,T4)\
+ omit_two_operands_loc (UNKNOWN_LOCATION, T1, T2, T3, T4)
+extern tree omit_two_operands_loc (location_t, tree, tree, tree, tree);
+#define invert_truthvalue(T)\
+ invert_truthvalue_loc (UNKNOWN_LOCATION, T)
+extern tree invert_truthvalue_loc (location_t, tree);
+extern tree fold_unary_to_constant (enum tree_code, tree, tree);
+extern tree fold_binary_to_constant (enum tree_code, tree, tree, tree);
+extern tree fold_bit_and_mask (tree, tree, enum tree_code,
+ tree, enum tree_code, tree, tree,
+ tree, enum tree_code, tree, tree, tree *);
+extern tree fold_read_from_constant_string (tree);
+// sdcpp extern tree fold_read_from_vector (tree, poly_uint64);
+#if GCC_VEC_PERN_INDICES_H
+extern tree fold_vec_perm (tree, tree, tree, const vec_perm_indices &);
+#endif
+extern bool wide_int_binop (wide_int &res, enum tree_code,
+ const wide_int &arg1, const wide_int &arg2,
+ signop, wi::overflow_type *);
+extern tree int_const_binop (enum tree_code, const_tree, const_tree, int = 1);
+#define build_fold_addr_expr(T)\
+ build_fold_addr_expr_loc (UNKNOWN_LOCATION, (T))
+extern tree build_fold_addr_expr_loc (location_t, tree);
+#define build_fold_addr_expr_with_type(T,TYPE)\
+ build_fold_addr_expr_with_type_loc (UNKNOWN_LOCATION, (T), TYPE)
+extern tree build_fold_addr_expr_with_type_loc (location_t, tree, tree);
+extern tree fold_build_cleanup_point_expr (tree type, tree expr);
+#define build_fold_indirect_ref(T)\
+ build_fold_indirect_ref_loc (UNKNOWN_LOCATION, T)
+extern tree build_fold_indirect_ref_loc (location_t, tree);
+#define fold_indirect_ref(T)\
+ fold_indirect_ref_loc (UNKNOWN_LOCATION, T)
+extern tree fold_indirect_ref_loc (location_t, tree);
+extern tree build_simple_mem_ref_loc (location_t, tree);
+#define build_simple_mem_ref(T)\
+ build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
+// sdcpp extern poly_offset_int mem_ref_offset (const_tree);
+// sdcpp extern tree build_invariant_address (tree, tree, poly_int64);
+extern tree constant_boolean_node (bool, tree);
+extern tree div_if_zero_remainder (const_tree, const_tree);
+
+extern bool tree_swap_operands_p (const_tree, const_tree);
+extern enum tree_code swap_tree_comparison (enum tree_code);
+
+// sdcpp extern bool ptr_difference_const (tree, tree, poly_int64_pod *);
+extern enum tree_code invert_tree_comparison (enum tree_code, bool);
+extern bool inverse_conditions_p (const_tree, const_tree);
+
+extern bool tree_unary_nonzero_warnv_p (enum tree_code, tree, tree, bool *);
+extern bool tree_binary_nonzero_warnv_p (enum tree_code, tree, tree, tree op1,
+ bool *);
+extern bool tree_single_nonzero_warnv_p (tree, bool *);
+extern bool tree_unary_nonnegative_warnv_p (enum tree_code, tree, tree,
+ bool *, int);
+extern bool tree_binary_nonnegative_warnv_p (enum tree_code, tree, tree, tree,
+ bool *, int);
+extern bool tree_single_nonnegative_warnv_p (tree, bool *, int);
+extern bool tree_call_nonnegative_warnv_p (tree, combined_fn, tree, tree,
+ bool *, int);
+
+extern bool integer_valued_real_unary_p (tree_code, tree, int);
+extern bool integer_valued_real_binary_p (tree_code, tree, tree, int);
+extern bool integer_valued_real_call_p (combined_fn, tree, tree, int);
+extern bool integer_valued_real_single_p (tree, int);
+extern bool integer_valued_real_p (tree, int = 0);
+
+extern bool fold_real_zero_addition_p (const_tree, const_tree, const_tree,
+ int);
+extern tree combine_comparisons (location_t, enum tree_code, enum tree_code,
+ enum tree_code, tree, tree, tree);
+extern void debug_fold_checksum (const_tree);
+extern bool may_negate_without_overflow_p (const_tree);
+#define round_up(T,N) round_up_loc (UNKNOWN_LOCATION, T, N)
+extern tree round_up_loc (location_t, tree, unsigned int);
+#define round_down(T,N) round_down_loc (UNKNOWN_LOCATION, T, N)
+extern tree round_down_loc (location_t, tree, int);
+// sdcpp extern tree size_int_kind (poly_int64, enum size_type_kind);
+#define size_binop(CODE,T1,T2)\
+ size_binop_loc (UNKNOWN_LOCATION, CODE, T1, T2)
+extern tree size_binop_loc (location_t, enum tree_code, tree, tree);
+#define size_diffop(T1,T2)\
+ size_diffop_loc (UNKNOWN_LOCATION, T1, T2)
+extern tree size_diffop_loc (location_t, tree, tree);
+
+/* Return an expr equal to X but certainly not valid as an lvalue. */
+#define non_lvalue(T) non_lvalue_loc (UNKNOWN_LOCATION, T)
+extern tree non_lvalue_loc (location_t, tree);
+
+extern bool tree_expr_nonzero_p (tree);
+extern bool tree_expr_nonnegative_p (tree);
+extern bool tree_expr_nonnegative_warnv_p (tree, bool *, int = 0);
+extern bool tree_expr_finite_p (const_tree);
+extern bool tree_expr_infinite_p (const_tree);
+extern bool tree_expr_maybe_infinite_p (const_tree);
+extern bool tree_expr_signaling_nan_p (const_tree);
+extern bool tree_expr_maybe_signaling_nan_p (const_tree);
+extern bool tree_expr_nan_p (const_tree);
+extern bool tree_expr_maybe_nan_p (const_tree);
+extern bool tree_expr_maybe_real_minus_zero_p (const_tree);
+extern tree make_range (tree, int *, tree *, tree *, bool *);
+extern tree make_range_step (location_t, enum tree_code, tree, tree, tree,
+ tree *, tree *, int *, bool *);
+extern tree range_check_type (tree);
+extern tree build_range_check (location_t, tree, tree, int, tree, tree);
+extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
+ tree, tree);
+extern tree sign_bit_p (tree, const_tree);
+extern tree exact_inverse (tree, tree);
+extern bool expr_not_equal_to (tree t, const wide_int &);
+extern tree const_unop (enum tree_code, tree, tree);
+extern tree const_binop (enum tree_code, tree, tree, tree);
+extern bool negate_mathfn_p (combined_fn);
+extern const char *getbyterep (tree, unsigned HOST_WIDE_INT *);
+extern const char *c_getstr (tree);
+extern wide_int tree_nonzero_bits (const_tree);
+// sdcpp extern int address_compare (tree_code, tree, tree, tree, tree &, tree &,
+// sdcpp poly_int64 &, poly_int64 &, bool);
+extern tree ctor_single_nonzero_element (const_tree);
+
+/* Return OFF converted to a pointer offset type suitable as offset for
+ POINTER_PLUS_EXPR. Use location LOC for this conversion. */
+extern tree convert_to_ptrofftype_loc (location_t loc, tree off);
+
+#define convert_to_ptrofftype(t) convert_to_ptrofftype_loc (UNKNOWN_LOCATION, t)
+
+/* Build and fold a POINTER_PLUS_EXPR at LOC offsetting PTR by OFF. */
+extern tree fold_build_pointer_plus_loc (location_t loc, tree ptr, tree off);
+
+#define fold_build_pointer_plus(p,o) \
+ fold_build_pointer_plus_loc (UNKNOWN_LOCATION, p, o)
+
+/* Build and fold a POINTER_PLUS_EXPR at LOC offsetting PTR by OFF. */
+extern tree fold_build_pointer_plus_hwi_loc (location_t loc, tree ptr, HOST_WIDE_INT off);
+
+#define fold_build_pointer_plus_hwi(p,o) \
+ fold_build_pointer_plus_hwi_loc (UNKNOWN_LOCATION, p, o)
+
+
+/* Class used to compare gimple operands. */
+
+class operand_compare
+{
+public:
+ /* Return true if two operands are equal. The flags fields can be used
+ to specify OEP flags described in tree-core.h. */
+ virtual bool operand_equal_p (const_tree, const_tree, unsigned int flags);
+
+ /* Generate a hash value for an expression. This can be used iteratively
+ by passing a previous result as the HSTATE argument. */
+ virtual void hash_operand (const_tree, inchash::hash &, unsigned flags);
+
+protected:
+ /* Verify that when arguments (ARG0 and ARG1) are equal, then they have
+ an equal hash value. When the function knowns comparison return,
+ true is returned. Then RET is set to corresponding comparsion result. */
+ bool verify_hash_value (const_tree arg0, const_tree arg1, unsigned int flags,
+ bool *ret);
+};
+
+#endif // GCC_FOLD_CONST_H
diff --git a/support/cpp/gcc/function-abi.h b/support/cpp/gcc/function-abi.h
new file mode 100644
index 000000000..388f5d852
--- /dev/null
+++ b/support/cpp/gcc/function-abi.h
@@ -0,0 +1,320 @@
+/* Information about function binary interfaces.
+ Copyright (C) 2019-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_FUNCTION_ABI_H
+#define GCC_FUNCTION_ABI_H
+
+/* Most targets use the same ABI for all functions in a translation
+ unit, but some targets support interoperability between several ABIs.
+ Each such ABI has a unique 0-based identifier, with 0 always being
+ the default choice of ABI.
+
+ NUM_ABI_IDS is the maximum number of such ABIs that GCC can handle at once.
+ A bitfield with this number of bits can represent any combinaion of the
+ supported ABIs. */
+const size_t NUM_ABI_IDS = 8;
+
+/* Information about one of the target's predefined ABIs. */
+class predefined_function_abi
+{
+public:
+ /* A target-specific identifier for this ABI. The value must be in
+ the range [0, NUM_ABI_IDS - 1]. */
+ unsigned int id () const { return m_id; }
+
+ /* True if this ABI has been initialized. */
+ bool initialized_p () const { return m_initialized; }
+
+ /* Return true if a function call is allowed to alter every bit of
+ register REGNO, so that the register contains an arbitrary value
+ on return. If so, the register cannot hold any part of a value
+ that is live across a call. */
+ bool
+ clobbers_full_reg_p (unsigned int regno) const
+ {
+ return TEST_HARD_REG_BIT (m_full_reg_clobbers, regno);
+ }
+
+ /* Return true if a function call is allowed to alter some or all bits
+ of register REGNO.
+
+ This is true whenever clobbers_full_reg_p (REGNO) is true. It is
+ also true if, for example, the ABI says that a call must preserve the
+ low 32 or 64 bits of REGNO, but can clobber the upper bits of REGNO.
+ In the latter case, it is possible for REGNO to hold values that
+ are live across a call, provided that the value occupies only the
+ call-preserved part of the register. */
+ bool
+ clobbers_at_least_part_of_reg_p (unsigned int regno) const
+ {
+ return TEST_HARD_REG_BIT (m_full_and_partial_reg_clobbers, regno);
+ }
+
+ /* Return true if a function call is allowed to clobber at least part
+ of (reg:MODE REGNO). If so, it is not possible for the register
+ as a whole to be live across a call. */
+ bool
+ clobbers_reg_p (machine_mode mode, unsigned int regno) const
+ {
+ return overlaps_hard_reg_set_p (m_mode_clobbers[mode], mode, regno);
+ }
+
+ /* Return the set of registers that a function call is allowed to
+ alter completely, so that the registers contain arbitrary values
+ on return. This doesn't include registers that a call can only
+ partly clobber (as per TARGET_HARD_REGNO_CALL_PART_CLOBBERED).
+
+ These registers cannot hold any part of a value that is live across
+ a call. */
+ HARD_REG_SET full_reg_clobbers () const { return m_full_reg_clobbers; }
+
+ /* Return the set of registers that a function call is allowed to alter
+ to some degree. For example, if an ABI says that a call must preserve
+ the low 32 or 64 bits of a register R, but can clobber the upper bits
+ of R, R would be in this set but not in full_reg_clobbers ().
+
+ This set is a superset of full_reg_clobbers (). It is possible for a
+ register in full_and_partial_reg_clobbers () & ~full_reg_clobbers ()
+ to contain values that are live across a call, provided that the live
+ value only occupies the call-preserved part of the register. */
+ HARD_REG_SET
+ full_and_partial_reg_clobbers () const
+ {
+ return m_full_and_partial_reg_clobbers;
+ }
+
+ /* Return the set of registers that cannot be used to hold a value of
+ mode MODE across a function call. That is:
+
+ (reg:REGNO MODE)
+
+ might be clobbered by a call whenever:
+
+ overlaps_hard_reg_set (mode_clobbers (MODE), MODE, REGNO)
+
+ In allocation terms, the registers in the returned set conflict
+ with any value of mode MODE that is live across a call. */
+ HARD_REG_SET
+ mode_clobbers (machine_mode mode) const
+ {
+ return m_mode_clobbers[mode];
+ }
+
+ void initialize (unsigned int, const_hard_reg_set);
+ void add_full_reg_clobber (unsigned int);
+
+private:
+ unsigned int m_id : NUM_ABI_IDS;
+ unsigned int m_initialized : 1;
+ HARD_REG_SET m_full_reg_clobbers;
+ HARD_REG_SET m_full_and_partial_reg_clobbers;
+ HARD_REG_SET m_mode_clobbers[NUM_MACHINE_MODES];
+};
+
+/* Describes either a predefined ABI or the ABI of a particular function.
+ In the latter case, the ABI might make use of extra function-specific
+ information, such as for -fipa-ra. */
+class function_abi
+{
+public:
+ /* Initialize the structure for a general function with the given ABI. */
+ function_abi (const predefined_function_abi &base_abi)
+ : m_base_abi (&base_abi),
+ m_mask (base_abi.full_and_partial_reg_clobbers ()) {}
+
+ /* Initialize the structure for a function that has the given ABI and
+ that is known not to clobber registers outside MASK. */
+ function_abi (const predefined_function_abi &base_abi,
+ const_hard_reg_set mask)
+ : m_base_abi (&base_abi), m_mask (mask) {}
+
+ /* The predefined ABI from which this ABI is derived. */
+ const predefined_function_abi &base_abi () const { return *m_base_abi; }
+
+ /* The target-specific identifier of the predefined ABI. */
+ unsigned int id () const { return m_base_abi->id (); }
+
+ /* See the corresponding predefined_function_abi functions for
+ details about the following functions. */
+
+ HARD_REG_SET
+ full_reg_clobbers () const
+ {
+ return m_mask & m_base_abi->full_reg_clobbers ();
+ }
+
+ HARD_REG_SET
+ full_and_partial_reg_clobbers () const
+ {
+ return m_mask & m_base_abi->full_and_partial_reg_clobbers ();
+ }
+
+ HARD_REG_SET
+ mode_clobbers (machine_mode mode) const
+ {
+ return m_mask & m_base_abi->mode_clobbers (mode);
+ }
+
+ bool
+ clobbers_full_reg_p (unsigned int regno) const
+ {
+ return (TEST_HARD_REG_BIT (m_mask, regno)
+ & m_base_abi->clobbers_full_reg_p (regno));
+ }
+
+ bool
+ clobbers_at_least_part_of_reg_p (unsigned int regno) const
+ {
+ return (TEST_HARD_REG_BIT (m_mask, regno)
+ & m_base_abi->clobbers_at_least_part_of_reg_p (regno));
+ }
+
+ bool
+ clobbers_reg_p (machine_mode mode, unsigned int regno) const
+ {
+ return overlaps_hard_reg_set_p (mode_clobbers (mode), mode, regno);
+ }
+
+ bool
+ operator== (const function_abi &other) const
+ {
+ return m_base_abi == other.m_base_abi && m_mask == other.m_mask;
+ }
+
+ bool
+ operator!= (const function_abi &other) const
+ {
+ return !operator== (other);
+ }
+
+protected:
+ const predefined_function_abi *m_base_abi;
+ HARD_REG_SET m_mask;
+};
+
+/* This class collects information about the ABIs of functions that are
+ called in a particular region of code. It is mostly intended to be
+ used as a local variable during an IR walk. */
+class function_abi_aggregator
+{
+public:
+ function_abi_aggregator () : m_abi_clobbers () {}
+
+ /* Record that the code region calls a function with the given ABI. */
+ void
+ note_callee_abi (const function_abi &abi)
+ {
+ m_abi_clobbers[abi.id ()] |= abi.full_and_partial_reg_clobbers ();
+ }
+
+ HARD_REG_SET caller_save_regs (const function_abi &) const;
+
+private:
+ HARD_REG_SET m_abi_clobbers[NUM_ABI_IDS];
+};
+
+struct target_function_abi_info
+{
+ /* An array of all the target ABIs that are available in this
+ translation unit. Not all entries are used for all targets,
+ but the structures are relatively small, and using a fixed-size
+ array avoids extra indirection.
+
+ There are various ways of getting an ABI descriptor:
+
+ * fndecl_abi (FNDECL) is the ABI of function FNDECL.
+
+ * fntype_abi (FNTYPE) is the ABI of a function with type FNTYPE.
+
+ * crtl->abi is the ABI of the function that we are currently
+ compiling to rtl.
+
+ * insn_callee_abi (INSN) is the ABI used by the target of call insn INSN.
+
+ * eh_edge_abi is the "ABI" used when taking an EH edge from an
+ exception-throwing statement to an exception handler. Catching
+ exceptions from calls can be treated as an abnormal return from
+ those calls, and this ABI therefore describes the ABI of functions
+ on such an abnormal return. Statements that throw non-call
+ exceptions can be treated as being implicitly wrapped in a call
+ that has such an abnormal return.
+
+ At present, no target needs to support more than one EH ABI.
+
+ * function_abis[N] is the ABI with identifier N. This can be useful
+ when referring back to ABIs that have been collected by number in
+ a bitmask, such as after walking function calls in a particular
+ region of code.
+
+ * default_function_abi refers specifically to the target's default
+ choice of ABI, regardless of which (if any) functions actually
+ use it. This ABI and data derived from it do *not* provide
+ globally conservatively-correct information, so it is only
+ useful in very specific circumstances. */
+ predefined_function_abi x_function_abis[NUM_ABI_IDS];
+};
+
+extern target_function_abi_info default_target_function_abi_info;
+#if SWITCHABLE_TARGET
+extern target_function_abi_info *this_target_function_abi_info;
+#else
+#define this_target_function_abi_info (&default_target_function_abi_info)
+#endif
+
+/* See the comment above x_function_abis for when these macros should be used.
+ At present, eh_edge_abi is always the default ABI, but that could change
+ in future if a target needs it to. */
+#define function_abis \
+ (this_target_function_abi_info->x_function_abis)
+#define default_function_abi \
+ (this_target_function_abi_info->x_function_abis[0])
+#define eh_edge_abi default_function_abi
+
+extern HARD_REG_SET call_clobbers_in_region (unsigned int, const_hard_reg_set,
+ machine_mode mode);
+
+/* Return true if (reg:MODE REGNO) might be clobbered by one of the
+ calls in a region described by ABIS and MASK, where:
+
+ * Bit ID of ABIS is set if the region contains a call with
+ function_abi identifier ID.
+
+ * MASK contains all the registers that are fully or partially
+ clobbered by calls in the region.
+
+ This is not quite as accurate as testing each individual call,
+ but it's a close and conservatively-correct approximation.
+ It's much better for some targets than:
+
+ overlaps_hard_reg_set_p (MASK, MODE, REGNO). */
+
+inline bool
+call_clobbered_in_region_p (unsigned int abis, const_hard_reg_set mask,
+ machine_mode mode, unsigned int regno)
+{
+ HARD_REG_SET clobbers = call_clobbers_in_region (abis, mask, mode);
+ return overlaps_hard_reg_set_p (clobbers, mode, regno);
+}
+
+extern const predefined_function_abi &fntype_abi (const_tree);
+extern function_abi fndecl_abi (const_tree);
+extern function_abi insn_callee_abi (const rtx_insn *);
+extern function_abi expr_callee_abi (const_tree);
+
+#endif
diff --git a/support/cpp/gcc/function.h b/support/cpp/gcc/function.h
new file mode 100644
index 000000000..09ac49528
--- /dev/null
+++ b/support/cpp/gcc/function.h
@@ -0,0 +1,733 @@
+/* Structure for saving state for a nested function.
+ Copyright (C) 1989-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_FUNCTION_H
+#define GCC_FUNCTION_H
+
+
+/* Stack of pending (incomplete) sequences saved by `start_sequence'.
+ Each element describes one pending sequence.
+ The main insn-chain is saved in the last element of the chain,
+ unless the chain is empty. */
+
+struct GTY(()) sequence_stack {
+ /* First and last insns in the chain of the saved sequence. */
+ rtx_insn *first;
+ rtx_insn *last;
+ struct sequence_stack *next;
+};
+
+struct GTY(()) emit_status {
+ void ensure_regno_capacity ();
+
+ /* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
+ After rtl generation, it is 1 plus the largest register number used. */
+ int x_reg_rtx_no;
+
+ /* Lowest label number in current function. */
+ int x_first_label_num;
+
+ /* seq.first and seq.last are the ends of the doubly-linked chain of
+ rtl for the current function. Both are reset to null at the
+ start of rtl generation for the function.
+
+ start_sequence saves both of these on seq.next and then starts
+ a new, nested sequence of insns.
+
+ seq.next is a stack of pending (incomplete) sequences saved by
+ start_sequence. Each element describes one pending sequence.
+ The main insn-chain is the last element of the chain. */
+ struct sequence_stack seq;
+
+ /* INSN_UID for next insn emitted.
+ Reset to 1 for each function compiled. */
+ int x_cur_insn_uid;
+
+ /* INSN_UID for next debug insn emitted. Only used if
+ --param min-nondebug-insn-uid=<value> is given with nonzero value. */
+ int x_cur_debug_insn_uid;
+
+ /* The length of the regno_pointer_align, regno_decl, and x_regno_reg_rtx
+ vectors. Since these vectors are needed during the expansion phase when
+ the total number of registers in the function is not yet known, the
+ vectors are copied and made bigger when necessary. */
+ int regno_pointer_align_length;
+
+ /* Indexed by pseudo register number, if nonzero gives the known alignment
+ for that pseudo (if REG_POINTER is set in x_regno_reg_rtx).
+ Allocated in parallel with x_regno_reg_rtx. */
+ unsigned char * GTY((skip)) regno_pointer_align;
+};
+
+
+/* Indexed by register number, gives an rtx for that register (and only
+ that register). For pseudo registers, it is the unique rtx for
+ that pseudo. For hard registers, it is an rtx of the mode specified
+ by reg_raw_mode.
+
+ FIXME: We could put it into emit_status struct, but gengtype is not
+ able to deal with length attribute nested in top level structures. */
+
+extern GTY ((length ("crtl->emit.x_reg_rtx_no"))) rtx * regno_reg_rtx;
+
+/* For backward compatibility... eventually these should all go away. */
+#define reg_rtx_no (crtl->emit.x_reg_rtx_no)
+
+#define REGNO_POINTER_ALIGN(REGNO) (crtl->emit.regno_pointer_align[REGNO])
+
+#if 0 // sdcpp
+struct GTY(()) expr_status {
+ /* Number of units that we should eventually pop off the stack.
+ These are the arguments to function calls that have already returned. */
+ poly_int64_pod x_pending_stack_adjust;
+
+ /* Under some ABIs, it is the caller's responsibility to pop arguments
+ pushed for function calls. A naive implementation would simply pop
+ the arguments immediately after each call. However, if several
+ function calls are made in a row, it is typically cheaper to pop
+ all the arguments after all of the calls are complete since a
+ single pop instruction can be used. Therefore, GCC attempts to
+ defer popping the arguments until absolutely necessary. (For
+ example, at the end of a conditional, the arguments must be popped,
+ since code outside the conditional won't know whether or not the
+ arguments need to be popped.)
+
+ When INHIBIT_DEFER_POP is nonzero, however, the compiler does not
+ attempt to defer pops. Instead, the stack is popped immediately
+ after each call. Rather then setting this variable directly, use
+ NO_DEFER_POP and OK_DEFER_POP. */
+ int x_inhibit_defer_pop;
+
+ /* If PREFERRED_STACK_BOUNDARY and PUSH_ROUNDING are defined, the stack
+ boundary can be momentarily unaligned while pushing the arguments.
+ Record the delta since last aligned boundary here in order to get
+ stack alignment in the nested function calls working right. */
+ poly_int64_pod x_stack_pointer_delta;
+
+ /* Nonzero means __builtin_saveregs has already been done in this function.
+ The value is the pseudoreg containing the value __builtin_saveregs
+ returned. */
+ rtx x_saveregs_value;
+
+ /* Similarly for __builtin_apply_args. */
+ rtx x_apply_args_value;
+
+ /* List of labels that must never be deleted. */
+ vec<rtx_insn *, va_gc> *x_forced_labels;
+};
+#endif // sdcpp
+
+typedef struct call_site_record_d *call_site_record;
+
+/* RTL representation of exception handling. */
+struct GTY(()) rtl_eh {
+ rtx ehr_stackadj;
+ rtx ehr_handler;
+ rtx_code_label *ehr_label;
+
+ rtx sjlj_fc;
+ rtx_insn *sjlj_exit_after;
+
+ vec<uchar, va_gc> *action_record_data;
+
+ vec<call_site_record, va_gc> *call_site_record_v[2];
+};
+
+#define pending_stack_adjust (crtl->expr.x_pending_stack_adjust)
+#define inhibit_defer_pop (crtl->expr.x_inhibit_defer_pop)
+#define saveregs_value (crtl->expr.x_saveregs_value)
+#define apply_args_value (crtl->expr.x_apply_args_value)
+#define forced_labels (crtl->expr.x_forced_labels)
+#define stack_pointer_delta (crtl->expr.x_stack_pointer_delta)
+
+struct gimple_df;
+struct call_site_record_d;
+struct dw_fde_node;
+class range_query;
+
+struct GTY(()) varasm_status {
+ /* If we're using a per-function constant pool, this is it. */
+ struct rtx_constant_pool *pool;
+
+ /* Number of tree-constants deferred during the expansion of this
+ function. */
+ unsigned int deferred_constants;
+};
+
+
+/* Data for function partitioning. */
+struct GTY(()) function_subsections {
+ /* Assembly labels for the hot and cold text sections, to
+ be used by debugger functions for determining the size of text
+ sections. */
+
+ const char *hot_section_label;
+ const char *cold_section_label;
+ const char *hot_section_end_label;
+ const char *cold_section_end_label;
+};
+
+/* Describe an empty area of space in the stack frame. These can be chained
+ into a list; this is used to keep track of space wasted for alignment
+ reasons. */
+#if 0 // sdcpp
+class GTY(()) frame_space
+{
+public:
+ class frame_space *next;
+
+ poly_int64 start;
+ poly_int64 length;
+};
+#endif // sdcpp
+
+/* Describe emitted calls for -fcallgraph-info. */
+struct GTY(()) callinfo_callee
+{
+ location_t location;
+ tree decl;
+};
+
+/* Describe dynamic allocation for -fcallgraph-info=da. */
+struct GTY(()) callinfo_dalloc
+{
+ location_t location;
+ char const *name;
+};
+
+#if 0 // sdcpp
+class GTY(()) stack_usage
+{
+public:
+ /* # of bytes of static stack space allocated by the function. */
+ HOST_WIDE_INT static_stack_size;
+
+ /* # of bytes of dynamic stack space allocated by the function. This is
+ meaningful only if has_unbounded_dynamic_stack_size is zero. */
+ HOST_WIDE_INT dynamic_stack_size;
+
+ /* Upper bound on the number of bytes pushed onto the stack after the
+ prologue. If !ACCUMULATE_OUTGOING_ARGS, it contains the outgoing
+ arguments. */
+ poly_int64 pushed_stack_size;
+
+ /* Nonzero if the amount of stack space allocated dynamically cannot
+ be bounded at compile-time. */
+ unsigned int has_unbounded_dynamic_stack_size : 1;
+
+ /* Functions called within the function, if callgraph is enabled. */
+ vec<callinfo_callee, va_gc> *callees;
+
+ /* Dynamic allocations encountered within the function, if callgraph
+ da is enabled. */
+ vec<callinfo_dalloc, va_gc> *dallocs;
+};
+
+#define current_function_static_stack_size (cfun->su->static_stack_size)
+#define current_function_dynamic_stack_size (cfun->su->dynamic_stack_size)
+#define current_function_pushed_stack_size (cfun->su->pushed_stack_size)
+#endif // sdcpp
+#define current_function_has_unbounded_dynamic_stack_size \
+ (cfun->su->has_unbounded_dynamic_stack_size)
+#define current_function_allocates_dynamic_stack_space \
+ (current_function_dynamic_stack_size != 0 \
+ || current_function_has_unbounded_dynamic_stack_size)
+
+/* This structure can save all the important global and static variables
+ describing the status of the current function. */
+
+struct GTY(()) function {
+ struct eh_status *eh;
+
+ /* The control flow graph for this function. */
+ struct control_flow_graph *cfg;
+
+ /* GIMPLE body for this function. */
+ gimple_seq gimple_body;
+
+ /* SSA and dataflow information. */
+ struct gimple_df *gimple_df;
+
+ /* The loops in this function. */
+ struct loops *x_current_loops;
+
+ /* Filled by the GIMPLE and RTL FEs, pass to start compilation with. */
+ char *pass_startwith;
+
+ /* The stack usage of this function. */
+ class stack_usage *su;
+
+ /* Value histograms attached to particular statements. */
+ htab_t GTY((skip)) value_histograms;
+
+ /* For function.cc. */
+
+ /* Points to the FUNCTION_DECL of this function. */
+ tree decl;
+
+ /* A PARM_DECL that should contain the static chain for this function.
+ It will be initialized at the beginning of the function. */
+ tree static_chain_decl;
+
+ /* An expression that contains the non-local goto save area. The first
+ word is the saved frame pointer and the second is the saved stack
+ pointer. */
+ tree nonlocal_goto_save_area;
+
+ /* Vector of function local variables, functions, types and constants. */
+ vec<tree, va_gc> *local_decls;
+
+ /* For md files. */
+
+ /* tm.h can use this to store whatever it likes. */
+ struct machine_function * GTY ((maybe_undef)) machine;
+
+ /* Language-specific code can use this to store whatever it likes. */
+ struct language_function * language;
+
+ /* Used types hash table. */
+ hash_set<tree> *GTY (()) used_types_hash;
+
+ /* Dwarf2 Frame Description Entry, containing the Call Frame Instructions
+ used for unwinding. Only set when either dwarf2 unwinding or dwarf2
+ debugging is enabled. */
+ struct dw_fde_node *fde;
+
+ /* Range query mechanism for functions. The default is to pick up
+ global ranges. If a pass wants on-demand ranges OTOH, it must
+ call enable/disable_ranger(). The pointer is never null. It
+ should be queried by calling get_range_query(). */
+ range_query * GTY ((skip)) x_range_query;
+
+ /* Last statement uid. */
+ int last_stmt_uid;
+
+ /* Debug marker counter. Count begin stmt markers. We don't have
+ to keep it exact, it's more of a rough estimate to enable us to
+ decide whether they are too many to copy during inlining, or when
+ expanding to RTL. */
+ int debug_marker_count;
+
+ /* Function sequence number for profiling, debugging, etc. */
+ int funcdef_no;
+
+ /* Line number of the start of the function for debugging purposes. */
+ location_t function_start_locus;
+
+ /* Line number of the end of the function. */
+ location_t function_end_locus;
+
+ /* Properties used by the pass manager. */
+ unsigned int curr_properties;
+ unsigned int last_verified;
+
+ /* Different from normal TODO_flags which are handled right at the
+ beginning or the end of one pass execution, the pending_TODOs
+ are passed down in the pipeline until one of its consumers can
+ perform the requested action. Consumers should then clear the
+ flags for the actions that they have taken. */
+ unsigned int pending_TODOs;
+
+ /* Non-null if the function does something that would prevent it from
+ being copied; this applies to both versioning and inlining. Set to
+ a string describing the reason for failure. */
+ const char * GTY((skip)) cannot_be_copied_reason;
+
+ /* Last assigned dependence info clique. */
+ unsigned short last_clique;
+
+ /* Collected bit flags. */
+
+ /* Number of units of general registers that need saving in stdarg
+ function. What unit is depends on the backend, either it is number
+ of bytes, or it can be number of registers. */
+ unsigned int va_list_gpr_size : 8;
+
+ /* Number of units of floating point registers that need saving in stdarg
+ function. */
+ unsigned int va_list_fpr_size : 8;
+
+ /* Nonzero if function being compiled can call setjmp. */
+ unsigned int calls_setjmp : 1;
+
+ /* Nonzero if function being compiled can call alloca,
+ either as a subroutine or builtin. */
+ unsigned int calls_alloca : 1;
+
+ /* Nonzero if function being compiled can call __builtin_eh_return. */
+ unsigned int calls_eh_return : 1;
+
+ /* Nonzero if function being compiled receives nonlocal gotos
+ from nested functions. */
+ unsigned int has_nonlocal_label : 1;
+
+ /* Nonzero if function being compiled has a forced label
+ placed into static storage. */
+ unsigned int has_forced_label_in_static : 1;
+
+ /* Nonzero if we've set cannot_be_copied_reason. I.e. if
+ (cannot_be_copied_set && !cannot_be_copied_reason), the function
+ can in fact be copied. */
+ unsigned int cannot_be_copied_set : 1;
+
+ /* Nonzero if current function uses stdarg.h or equivalent. */
+ unsigned int stdarg : 1;
+
+ unsigned int after_inlining : 1;
+ unsigned int always_inline_functions_inlined : 1;
+
+ /* Nonzero if function being compiled can throw synchronous non-call
+ exceptions. */
+ unsigned int can_throw_non_call_exceptions : 1;
+
+ /* Nonzero if instructions that may throw exceptions but don't otherwise
+ contribute to the execution of the program can be deleted. */
+ unsigned int can_delete_dead_exceptions : 1;
+
+ /* Fields below this point are not set for abstract functions; see
+ allocate_struct_function. */
+
+ /* Nonzero if function being compiled needs to be given an address
+ where the value should be stored. */
+ unsigned int returns_struct : 1;
+
+ /* Nonzero if function being compiled needs to
+ return the address of where it has put a structure value. */
+ unsigned int returns_pcc_struct : 1;
+
+ /* Nonzero if this function has local DECL_HARD_REGISTER variables.
+ In this case code motion has to be done more carefully. */
+ unsigned int has_local_explicit_reg_vars : 1;
+
+ /* Nonzero if the current function is a thunk, i.e., a lightweight
+ function implemented by the output_mi_thunk hook) that just
+ adjusts one of its arguments and forwards to another
+ function. */
+ unsigned int is_thunk : 1;
+
+ /* Nonzero if the current function contains any loops with
+ loop->force_vectorize set. */
+ unsigned int has_force_vectorize_loops : 1;
+
+ /* Nonzero if the current function contains any loops with
+ nonzero value in loop->simduid. */
+ unsigned int has_simduid_loops : 1;
+
+ /* Nonzero when the tail call has been identified. */
+ unsigned int tail_call_marked : 1;
+
+ /* Nonzero if the current function contains a #pragma GCC unroll. */
+ unsigned int has_unroll : 1;
+
+ /* Set when the function was compiled with generation of debug
+ (begin stmt, inline entry, ...) markers enabled. */
+ unsigned int debug_nonbind_markers : 1;
+
+ /* Set if this is a coroutine-related function. */
+ unsigned int coroutine_component : 1;
+
+ /* Set if there are any OMP_TARGET regions in the function. */
+ unsigned int has_omp_target : 1;
+};
+
+/* Add the decl D to the local_decls list of FUN. */
+
+void add_local_decl (struct function *fun, tree d);
+
+#define FOR_EACH_LOCAL_DECL(FUN, I, D) \
+ FOR_EACH_VEC_SAFE_ELT_REVERSE ((FUN)->local_decls, I, D)
+
+/* Record a final call to CALLEE at LOCATION. */
+void record_final_call (tree callee, location_t location);
+
+/* Record a dynamic allocation made for DECL_OR_EXP. */
+void record_dynamic_alloc (tree decl_or_exp);
+
+/* If va_list_[gf]pr_size is set to this, it means we don't know how
+ many units need to be saved. */
+#define VA_LIST_MAX_GPR_SIZE 255
+#define VA_LIST_MAX_FPR_SIZE 255
+
+/* The function currently being compiled. */
+extern GTY(()) struct function *cfun;
+
+#if 0 // sdcpp
+
+/* In order to ensure that cfun is not set directly, we redefine it so
+ that it is not an lvalue. Rather than assign to cfun, use
+ push_cfun or set_cfun. */
+#define cfun (cfun + 0)
+
+/* Nonzero if we've already converted virtual regs to hard regs. */
+extern int virtuals_instantiated;
+
+/* Nonzero if at least one trampoline has been created. */
+extern int trampolines_created;
+
+struct GTY((for_user)) types_used_by_vars_entry {
+ tree type;
+ tree var_decl;
+};
+
+struct used_type_hasher : ggc_ptr_hash<types_used_by_vars_entry>
+{
+ static hashval_t hash (types_used_by_vars_entry *);
+ static bool equal (types_used_by_vars_entry *, types_used_by_vars_entry *);
+};
+
+/* Hash table making the relationship between a global variable
+ and the types it references in its initializer. The key of the
+ entry is a referenced type, and the value is the DECL of the global
+ variable. types_use_by_vars_do_hash and types_used_by_vars_eq below are
+ the hash and equality functions to use for this hash table. */
+extern GTY(()) hash_table<used_type_hasher> *types_used_by_vars_hash;
+
+void types_used_by_var_decl_insert (tree type, tree var_decl);
+
+/* During parsing of a global variable, this vector contains the types
+ referenced by the global variable. */
+extern GTY(()) vec<tree, va_gc> *types_used_by_cur_var_decl;
+#endif // sdcpp
+
+
+/* Return the loop tree of FN. */
+
+inline struct loops *
+loops_for_fn (struct function *fn)
+{
+ return fn->x_current_loops;
+}
+#if 0 // sdcpp
+
+/* Set the loop tree of FN to LOOPS. */
+
+inline void
+set_loops_for_fn (struct function *fn, struct loops *loops)
+{
+ gcc_checking_assert (fn->x_current_loops == NULL || loops == NULL);
+ fn->x_current_loops = loops;
+}
+
+/* For backward compatibility... eventually these should all go away. */
+#define current_function_funcdef_no (cfun->funcdef_no)
+
+#define current_loops (cfun->x_current_loops)
+#define dom_computed (cfun->cfg->x_dom_computed)
+#define n_bbs_in_dom_tree (cfun->cfg->x_n_bbs_in_dom_tree)
+#define VALUE_HISTOGRAMS(fun) (fun)->value_histograms
+
+/* A pointer to a function to create target specific, per-function
+ data structures. */
+extern struct machine_function * (*init_machine_status) (void);
+
+/* Structure to record the size of a sequence of arguments
+ as the sum of a tree-expression and a constant. This structure is
+ also used to store offsets from the stack, which might be negative,
+ so the variable part must be ssizetype, not sizetype. */
+
+struct args_size
+{
+ poly_int64_pod constant;
+ tree var;
+};
+
+/* Package up various arg related fields of struct args for
+ locate_and_pad_parm. */
+struct locate_and_pad_arg_data
+{
+ /* Size of this argument on the stack, rounded up for any padding it
+ gets. If REG_PARM_STACK_SPACE is defined, then register parms are
+ counted here, otherwise they aren't. */
+ struct args_size size;
+ /* Offset of this argument from beginning of stack-args. */
+ struct args_size offset;
+ /* Offset to the start of the stack slot. Different from OFFSET
+ if this arg pads downward. */
+ struct args_size slot_offset;
+ /* The amount that the stack pointer needs to be adjusted to
+ force alignment for the next argument. */
+ struct args_size alignment_pad;
+ /* Which way we should pad this arg. */
+ pad_direction where_pad;
+ /* slot_offset is at least this aligned. */
+ unsigned int boundary;
+};
+
+/* Add the value of the tree INC to the `struct args_size' TO. */
+
+#define ADD_PARM_SIZE(TO, INC) \
+do { \
+ tree inc = (INC); \
+ if (tree_fits_shwi_p (inc)) \
+ (TO).constant += tree_to_shwi (inc); \
+ else if ((TO).var == 0) \
+ (TO).var = fold_convert (ssizetype, inc); \
+ else \
+ (TO).var = size_binop (PLUS_EXPR, (TO).var, \
+ fold_convert (ssizetype, inc)); \
+} while (0)
+
+#define SUB_PARM_SIZE(TO, DEC) \
+do { \
+ tree dec = (DEC); \
+ if (tree_fits_shwi_p (dec)) \
+ (TO).constant -= tree_to_shwi (dec); \
+ else if ((TO).var == 0) \
+ (TO).var = size_binop (MINUS_EXPR, ssize_int (0), \
+ fold_convert (ssizetype, dec)); \
+ else \
+ (TO).var = size_binop (MINUS_EXPR, (TO).var, \
+ fold_convert (ssizetype, dec)); \
+} while (0)
+
+/* Convert the implicit sum in a `struct args_size' into a tree
+ of type ssizetype. */
+#define ARGS_SIZE_TREE(SIZE) \
+((SIZE).var == 0 ? ssize_int ((SIZE).constant) \
+ : size_binop (PLUS_EXPR, fold_convert (ssizetype, (SIZE).var), \
+ ssize_int ((SIZE).constant)))
+
+/* Convert the implicit sum in a `struct args_size' into an rtx. */
+#define ARGS_SIZE_RTX(SIZE) \
+((SIZE).var == 0 ? gen_int_mode ((SIZE).constant, Pmode) \
+ : expand_normal (ARGS_SIZE_TREE (SIZE)))
+
+#define ASLK_REDUCE_ALIGN 1
+#define ASLK_RECORD_PAD 2
+
+/* If pointers to member functions use the least significant bit to
+ indicate whether a function is virtual, ensure a pointer
+ to this function will have that bit clear. */
+#define MINIMUM_METHOD_BOUNDARY \
+ ((TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn) \
+ ? MAX (FUNCTION_BOUNDARY, 2 * BITS_PER_UNIT) : FUNCTION_BOUNDARY)
+
+enum stack_clash_probes {
+ NO_PROBE_NO_FRAME,
+ NO_PROBE_SMALL_FRAME,
+ PROBE_INLINE,
+ PROBE_LOOP
+};
+
+extern void dump_stack_clash_frame_info (enum stack_clash_probes, bool);
+
+
+extern void push_function_context (void);
+extern void pop_function_context (void);
+
+/* Save and restore status information for a nested function. */
+extern void free_after_parsing (struct function *);
+extern void free_after_compilation (struct function *);
+
+/* Return size needed for stack frame based on slots so far allocated.
+ This size counts from zero. It is not rounded to STACK_BOUNDARY;
+ the caller may have to do that. */
+extern poly_int64 get_frame_size (void);
+
+/* Issue an error message and return TRUE if frame OFFSET overflows in
+ the signed target pointer arithmetics for function FUNC. Otherwise
+ return FALSE. */
+extern bool frame_offset_overflow (poly_int64, tree);
+
+extern unsigned int spill_slot_alignment (machine_mode);
+
+extern rtx assign_stack_local_1 (machine_mode, poly_int64, int, int);
+extern rtx assign_stack_local (machine_mode, poly_int64, int);
+extern rtx assign_stack_temp_for_type (machine_mode, poly_int64, tree);
+extern rtx assign_stack_temp (machine_mode, poly_int64);
+extern rtx assign_temp (tree, int, int);
+extern void update_temp_slot_address (rtx, rtx);
+extern void preserve_temp_slots (rtx);
+extern void free_temp_slots (void);
+extern void push_temp_slots (void);
+extern void pop_temp_slots (void);
+extern void init_temp_slots (void);
+extern rtx get_hard_reg_initial_reg (rtx);
+extern rtx get_hard_reg_initial_val (machine_mode, unsigned int);
+extern rtx has_hard_reg_initial_val (machine_mode, unsigned int);
+
+/* Called from gimple_expand_cfg. */
+extern unsigned int emit_initial_value_sets (void);
+
+extern bool initial_value_entry (int i, rtx *, rtx *);
+extern void instantiate_decl_rtl (rtx x);
+extern int aggregate_value_p (const_tree, const_tree);
+extern bool use_register_for_decl (const_tree);
+extern gimple_seq gimplify_parameters (gimple_seq *);
+extern void locate_and_pad_parm (machine_mode, tree, int, int, int,
+ tree, struct args_size *,
+ struct locate_and_pad_arg_data *);
+extern void generate_setjmp_warnings (void);
+
+/* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
+ and create duplicate blocks. */
+extern void reorder_blocks (void);
+extern void clear_block_marks (tree);
+extern tree blocks_nreverse (tree);
+extern tree block_chainon (tree, tree);
+
+/* Set BLOCK_NUMBER for all the blocks in FN. */
+extern void number_blocks (tree);
+
+/* cfun shouldn't be set directly; use one of these functions instead. */
+extern void set_cfun (struct function *new_cfun, bool force = false);
+extern void push_cfun (struct function *new_cfun);
+extern void pop_cfun (void);
+
+extern int get_next_funcdef_no (void);
+extern int get_last_funcdef_no (void);
+extern void allocate_struct_function (tree, bool);
+extern void push_struct_function (tree fndecl);
+extern void push_dummy_function (bool);
+extern void pop_dummy_function (void);
+extern void init_dummy_function_start (void);
+extern void init_function_start (tree);
+extern void stack_protect_epilogue (void);
+extern void expand_function_start (tree);
+extern void expand_dummy_function_end (void);
+
+extern void thread_prologue_and_epilogue_insns (void);
+extern void diddle_return_value (void (*)(rtx, void*), void*);
+extern void clobber_return_register (void);
+extern void expand_function_end (void);
+extern rtx get_arg_pointer_save_area (void);
+extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
+extern int prologue_contains (const rtx_insn *);
+extern int epilogue_contains (const rtx_insn *);
+extern int prologue_epilogue_contains (const rtx_insn *);
+extern void record_prologue_seq (rtx_insn *);
+extern void record_epilogue_seq (rtx_insn *);
+extern void emit_return_into_block (bool simple_p, basic_block bb);
+extern void set_return_jump_label (rtx_insn *);
+extern bool active_insn_between (rtx_insn *head, rtx_insn *tail);
+extern vec<edge> convert_jumps_to_returns (basic_block last_bb, bool simple_p,
+ vec<edge> unconverted);
+extern basic_block emit_return_for_exit (edge exit_fallthru_edge,
+ bool simple_p);
+extern void reposition_prologue_and_epilogue_notes (void);
+
+/* Returns the name of the current function. */
+extern const char *fndecl_name (tree);
+extern const char *function_name (struct function *);
+extern const char *current_function_name (void);
+
+extern void used_types_insert (tree);
+#endif // sdcpp
+
+#endif /* GCC_FUNCTION_H */
diff --git a/support/cpp/gcc/gcc-main.cc b/support/cpp/gcc/gcc-main.cc
new file mode 100644
index 000000000..2d0ef4d99
--- /dev/null
+++ b/support/cpp/gcc/gcc-main.cc
@@ -0,0 +1,48 @@
+/* "main" for the compiler driver.
+ 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/>. */
+
+/* This source file contains "main" for the compiler driver.
+ All of the real work is done within gcc.cc; we implement "main"
+ in here for the "gcc" binary so that gcc.o can be used in
+ libgccjit.so. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "xregex.h"
+#include "obstack.h"
+#include "intl.h"
+#include "prefix.h"
+#include "opt-suggestions.h"
+#include "gcc.h"
+
+/* Implement the top-level "main" within the driver in terms of
+ driver::main (implemented in gcc.cc). */
+
+extern int main (int, char **);
+
+int
+main (int argc, char **argv)
+{
+ driver d (false, /* can_finalize */
+ false); /* debug */
+
+ return d.main (argc, argv);
+}
diff --git a/support/cpp/gcc/gcc-rich-location.h b/support/cpp/gcc/gcc-rich-location.h
new file mode 100644
index 000000000..a43fe3899
--- /dev/null
+++ b/support/cpp/gcc/gcc-rich-location.h
@@ -0,0 +1,226 @@
+/* Declarations relating to class gcc_rich_location
+ Copyright (C) 2014-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_RICH_LOCATION_H
+#define GCC_RICH_LOCATION_H
+
+/* A gcc_rich_location is libcpp's rich_location with additional
+ helper methods for working with gcc's types. The class is not
+ copyable or assignable because rich_location isn't. */
+
+class gcc_rich_location : public rich_location
+{
+ public:
+ /* Constructors. */
+
+ /* Constructing from a location. */
+ explicit gcc_rich_location (location_t loc, const range_label *label = NULL)
+ : rich_location (line_table, loc, label)
+ {
+ }
+
+ /* Methods for adding ranges via gcc entities. */
+ void
+ add_expr (tree expr, range_label *label);
+
+ void
+ maybe_add_expr (tree t, range_label *label);
+
+ void add_fixit_misspelled_id (location_t misspelled_token_loc,
+ tree hint_id);
+
+ /* If LOC is within the spans of lines that will already be printed for
+ this gcc_rich_location, then add it as a secondary location
+ and return true.
+
+ Otherwise return false.
+
+ This allows for a diagnostic to compactly print secondary locations
+ in one diagnostic when these are near enough the primary locations for
+ diagnostics-show-locus.c to cope with them, and to fall back to
+ printing them via a note otherwise e.g.:
+
+ gcc_rich_location richloc (primary_loc);
+ bool added secondary = richloc.add_location_if_nearby (secondary_loc);
+ error_at (&richloc, "main message");
+ if (!added secondary)
+ inform (secondary_loc, "message for secondary");
+
+ Implemented in diagnostic-show-locus.cc. */
+
+ bool add_location_if_nearby (location_t loc,
+ bool restrict_to_current_line_spans = true,
+ const range_label *label = NULL);
+
+ /* Add a fix-it hint suggesting the insertion of CONTENT before
+ INSERTION_POINT.
+
+ Attempt to handle formatting: if INSERTION_POINT is the first thing on
+ its line, and INDENT is sufficiently sane, then add CONTENT on its own
+ line, using the indentation of INDENT.
+ Otherwise, add CONTENT directly before INSERTION_POINT.
+
+ For example, adding "CONTENT;" with the closing brace as the insertion
+ point and using "INDENT;" for indentation:
+
+ if ()
+ {
+ INDENT;
+ }
+
+ would lead to:
+
+ if ()
+ {
+ INDENT;
+ CONTENT;
+ }
+
+ but adding it to:
+
+ if () {INDENT;}
+
+ would lead to:
+
+ if () {INDENT;CONTENT;}
+ */
+ void add_fixit_insert_formatted (const char *content,
+ location_t insertion_point,
+ location_t indent);
+};
+
+/* Concrete subclass of libcpp's range_label.
+ Simple implementation using a string literal. */
+
+class text_range_label : public range_label
+{
+ public:
+ text_range_label (const char *text) : m_text (text) {}
+
+ label_text get_text (unsigned /*range_idx*/) const FINAL OVERRIDE
+ {
+ return label_text::borrow (m_text);
+ }
+
+ private:
+ const char *m_text;
+};
+
+/* Concrete subclass of libcpp's range_label for use in
+ diagnostics involving mismatched types.
+
+ Each frontend that uses this should supply its own implementation.
+
+ Generate a label describing LABELLED_TYPE. The frontend may use
+ OTHER_TYPE where appropriate for highlighting the differences between
+ the two types (analogous to C++'s use of %H and %I with
+ template types).
+
+ Either or both of LABELLED_TYPE and OTHER_TYPE may be NULL_TREE.
+ If LABELLED_TYPE is NULL_TREE, then there is no label.
+
+ For example, this rich_location could use two instances of
+ range_label_for_type_mismatch:
+
+ printf ("arg0: %i arg1: %s arg2: %i",
+ ^~
+ |
+ const char *
+ 100, 101, 102);
+ ~~~
+ |
+ int
+
+ (a) the label for "%s" with LABELLED_TYPE for "const char*" and
+ (b) the label for "101" with LABELLED TYPE for "int"
+ where each one uses the other's type as OTHER_TYPE. */
+
+class range_label_for_type_mismatch : public range_label
+{
+ public:
+ range_label_for_type_mismatch (tree labelled_type, tree other_type)
+ : m_labelled_type (labelled_type), m_other_type (other_type)
+ {
+ }
+
+ label_text get_text (unsigned range_idx) const OVERRIDE;
+
+ protected:
+ tree m_labelled_type;
+ tree m_other_type;
+};
+
+/* Subclass of range_label for labelling the type of EXPR when reporting
+ a type mismatch between EXPR and OTHER_EXPR.
+ Either or both of EXPR and OTHER_EXPR could be NULL. */
+
+class maybe_range_label_for_tree_type_mismatch : public range_label
+{
+ public:
+ maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr)
+ : m_expr (expr), m_other_expr (other_expr)
+ {
+ }
+
+ label_text get_text (unsigned range_idx) const FINAL OVERRIDE;
+
+ private:
+ tree m_expr;
+ tree m_other_expr;
+};
+
+class op_location_t;
+
+/* A subclass of rich_location for showing problems with binary operations.
+
+ If enough location information is available, the ctor will make a
+ 3-location rich_location of the form:
+
+ arg_0 op arg_1
+ ~~~~~ ^~ ~~~~~
+ | |
+ | arg1 type
+ arg0 type
+
+ labelling the types of the arguments if SHOW_TYPES is true.
+
+ Otherwise, it will fall back to a 1-location rich_location using the
+ compound location within LOC:
+
+ arg_0 op arg_1
+ ~~~~~~^~~~~~~~
+
+ for which we can't label the types. */
+
+class binary_op_rich_location : public gcc_rich_location
+{
+ public:
+ binary_op_rich_location (const op_location_t &loc,
+ tree arg0, tree arg1,
+ bool show_types);
+
+ private:
+ static bool use_operator_loc_p (const op_location_t &loc,
+ tree arg0, tree arg1);
+
+ maybe_range_label_for_tree_type_mismatch m_label_for_arg0;
+ maybe_range_label_for_tree_type_mismatch m_label_for_arg1;
+};
+
+#endif /* GCC_RICH_LOCATION_H */
diff --git a/support/cpp/gcc/gcc.cc b/support/cpp/gcc/gcc.cc
new file mode 100644
index 000000000..3b27f49cc
--- /dev/null
+++ b/support/cpp/gcc/gcc.cc
@@ -0,0 +1,11295 @@
+/* Compiler driver program that can handle many languages.
+ 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/>. */
+
+/* This program is the user interface to the C compiler and possibly to
+other compilers. It is used because compilation is a complicated procedure
+which involves running several programs and passing temporary files between
+them, forwarding the users switches to those programs selectively,
+and deleting the temporary files at the end.
+
+CC recognizes how to compile each input file by suffixes in the file names.
+Once it knows which kind of compilation to perform, the procedure for
+compilation is specified by a string called a "spec". */
+
+#include <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ \
+ <<":" << __func__ << "\n" )
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "multilib.h" /* before tm.h */
+#include "tm.h"
+#include "xregex.h"
+#include "obstack.h"
+#include "intl.h"
+#include "prefix.h"
+#include "opt-suggestions.h"
+#include "gcc.h"
+#include "diagnostic.h"
+#include "flags.h"
+#include "opts.h"
+#include "filenames.h"
+#include "spellcheck.h"
+
+#include <cassert>
+
+// sdcpp
+extern bool flag_wpa;
+bool flag_wpa;
+
+/* Manage the manipulation of env vars.
+
+ We poison "getenv" and "putenv", so that all enviroment-handling is
+ done through this class. Note that poisoning happens in the
+ preprocessor at the identifier level, and doesn't distinguish between
+ env.getenv ();
+ and
+ getenv ();
+ Hence we need to use "get" for the accessor method, not "getenv". */
+
+struct env_manager
+{
+ public:
+ void init (bool can_restore, bool debug);
+ const char *get (const char *name);
+ void xput (const char *string);
+ void restore ();
+
+ private:
+ bool m_can_restore;
+ bool m_debug;
+ struct kv
+ {
+ char *m_key;
+ char *m_value;
+ };
+ vec<kv> m_keys;
+
+};
+
+/* The singleton instance of class env_manager. */
+
+static env_manager env;
+
+/* Initializer for class env_manager.
+
+ We can't do this as a constructor since we have a statically
+ allocated instance ("env" above). */
+
+void
+env_manager::init (bool can_restore, bool debug)
+{
+ m_can_restore = can_restore;
+ m_debug = debug;
+}
+
+/* Get the value of NAME within the environment. Essentially
+ a wrapper for ::getenv, but adding logging, and the possibility
+ of caching results. */
+
+const char *
+env_manager::get (const char *name)
+{
+ const char *result = ::getenv (name);
+ if (m_debug)
+ fprintf (stderr, "env_manager::getenv (%s) -> %s\n", name, result);
+ return result;
+}
+
+/* Put the given KEY=VALUE entry STRING into the environment.
+ If the env_manager was initialized with CAN_RESTORE set, then
+ also record the old value of KEY within the environment, so that it
+ can be later restored. */
+
+void
+env_manager::xput (const char *string)
+{
+ if (m_debug)
+ fprintf (stderr, "env_manager::xput (%s)\n", string);
+ if (verbose_flag)
+ fnotice (stderr, "%s\n", string);
+
+ if (m_can_restore)
+ {
+ char *equals = strchr (const_cast <char *> (string), '=');
+ gcc_assert (equals);
+
+ struct kv kv;
+ kv.m_key = xstrndup (string, equals - string);
+ const char *cur_value = ::getenv (kv.m_key);
+ if (m_debug)
+ fprintf (stderr, "saving old value: %s\n",cur_value);
+ kv.m_value = cur_value ? xstrdup (cur_value) : NULL;
+ m_keys.safe_push (kv);
+ }
+
+ ::putenv (CONST_CAST (char *, string));
+}
+
+/* Undo any xputenv changes made since last restore.
+ Can only be called if the env_manager was initialized with
+ CAN_RESTORE enabled. */
+
+void
+env_manager::restore ()
+{
+ unsigned int i;
+ struct kv *item;
+
+ gcc_assert (m_can_restore);
+
+ FOR_EACH_VEC_ELT_REVERSE (m_keys, i, item)
+ {
+ if (m_debug)
+ printf ("restoring saved key: %s value: %s\n", item->m_key, item->m_value);
+ if (item->m_value)
+ ::setenv (item->m_key, item->m_value, 1);
+ else
+ ::unsetenv (item->m_key);
+ free (item->m_key);
+ free (item->m_value);
+ }
+
+ m_keys.truncate (0);
+}
+
+/* Forbid other uses of getenv and putenv. */
+#if (GCC_VERSION >= 3000)
+#pragma GCC poison getenv putenv
+#endif
+
+
+
+/* By default there is no special suffix for target executables. */
+#ifdef TARGET_EXECUTABLE_SUFFIX
+#define HAVE_TARGET_EXECUTABLE_SUFFIX
+#else
+#define TARGET_EXECUTABLE_SUFFIX ""
+#endif
+
+/* By default there is no special suffix for host executables. */
+#ifdef HOST_EXECUTABLE_SUFFIX
+#define HAVE_HOST_EXECUTABLE_SUFFIX
+#else
+#define HOST_EXECUTABLE_SUFFIX ""
+#endif
+
+/* By default, the suffix for target object files is ".o". */
+#ifdef TARGET_OBJECT_SUFFIX
+#define HAVE_TARGET_OBJECT_SUFFIX
+#else
+#define TARGET_OBJECT_SUFFIX ".o"
+#endif
+
+static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
+
+/* Most every one is fine with LIBRARY_PATH. For some, it conflicts. */
+#ifndef LIBRARY_PATH_ENV
+#define LIBRARY_PATH_ENV "LIBRARY_PATH"
+#endif
+
+/* If a stage of compilation returns an exit status >= 1,
+ compilation of that file ceases. */
+
+#define MIN_FATAL_STATUS 1
+
+/* Flag set by cppspec.cc to 1. */
+int is_cpp_driver;
+
+/* Flag set to nonzero if an @file argument has been supplied to gcc. */
+static bool at_file_supplied;
+
+/* Definition of string containing the arguments given to configure. */
+#include "configargs.h"
+
+/* Flag saying to print the command line options understood by gcc and its
+ sub-processes. */
+
+static int print_help_list;
+
+/* Flag saying to print the version of gcc and its sub-processes. */
+
+static int print_version;
+
+/* Flag that stores string prefix for which we provide bash completion. */
+
+static const char *completion = NULL;
+
+/* Flag indicating whether we should ONLY print the command and
+ arguments (like verbose_flag) without executing the command.
+ Displayed arguments are quoted so that the generated command
+ line is suitable for execution. This is intended for use in
+ shell scripts to capture the driver-generated command line. */
+static int verbose_only_flag;
+
+/* Flag indicating how to print command line options of sub-processes. */
+
+static int print_subprocess_help;
+
+/* Linker suffix passed to -fuse-ld=... */
+static const char *use_ld;
+
+/* Whether we should report subprocess execution times to a file. */
+
+FILE *report_times_to_file = NULL;
+
+/* Nonzero means place this string before uses of /, so that include
+ and library files can be found in an alternate location. */
+
+#ifdef TARGET_SYSTEM_ROOT
+#define DEFAULT_TARGET_SYSTEM_ROOT (TARGET_SYSTEM_ROOT)
+#else
+#define DEFAULT_TARGET_SYSTEM_ROOT (0)
+#endif
+static const char *target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
+
+/* Nonzero means pass the updated target_system_root to the compiler. */
+
+static int target_system_root_changed;
+
+/* Nonzero means append this string to target_system_root. */
+
+static const char *target_sysroot_suffix = 0;
+
+/* Nonzero means append this string to target_system_root for headers. */
+
+static const char *target_sysroot_hdrs_suffix = 0;
+
+/* Nonzero means write "temp" files in source directory
+ and use the source file's name in them, and don't delete them. */
+
+static enum save_temps {
+ SAVE_TEMPS_NONE, /* no -save-temps */
+ SAVE_TEMPS_CWD, /* -save-temps in current directory */
+ SAVE_TEMPS_DUMP, /* -save-temps in dumpdir */
+ SAVE_TEMPS_OBJ /* -save-temps in object directory */
+} save_temps_flag;
+
+/* Set this iff the dumppfx implied by a -save-temps=* option is to
+ override a -dumpdir option, if any. */
+static bool save_temps_overrides_dumpdir = false;
+
+/* -dumpdir, -dumpbase and -dumpbase-ext flags passed in, possibly
+ rearranged as they are to be passed down, e.g., dumpbase and
+ dumpbase_ext may be cleared if integrated with dumpdir or
+ dropped. */
+static char *dumpdir, *dumpbase, *dumpbase_ext;
+
+/* Usually the length of the string in dumpdir. However, during
+ linking, it may be shortened to omit a driver-added trailing dash,
+ by then replaced with a trailing period, that is still to be passed
+ to sub-processes in -dumpdir, but not to be generally used in spec
+ filename expansions. See maybe_run_linker. */
+static size_t dumpdir_length = 0;
+
+/* Set if the last character in dumpdir is (or was) a dash that the
+ driver added to dumpdir after dumpbase or linker output name. */
+static bool dumpdir_trailing_dash_added = false;
+
+/* Basename of dump and aux outputs, computed from dumpbase (given or
+ derived from output name), to override input_basename in non-%w %b
+ et al. */
+static char *outbase;
+static size_t outbase_length = 0;
+
+/* The compiler version. */
+
+static const char *compiler_version;
+
+/* The target version. */
+
+static const char *const spec_version = DEFAULT_TARGET_VERSION;
+
+/* The target machine. */
+
+static const char *spec_machine = DEFAULT_TARGET_MACHINE;
+static const char *spec_host_machine = DEFAULT_REAL_TARGET_MACHINE;
+
+/* List of offload targets. Separated by colon. Empty string for
+ -foffload=disable. */
+
+static char *offload_targets = NULL;
+
+#if OFFLOAD_DEFAULTED
+/* Set to true if -foffload has not been used and offload_targets
+ is set to the configured in default. */
+static bool offload_targets_default;
+#endif
+
+/* Nonzero if cross-compiling.
+ When -b is used, the value comes from the `specs' file. */
+
+#ifdef CROSS_DIRECTORY_STRUCTURE
+static const char *cross_compile = "1";
+#else
+static const char *cross_compile = "0";
+#endif
+
+/* Greatest exit code of sub-processes that has been encountered up to
+ now. */
+static int greatest_status = 1;
+
+/* This is the obstack which we use to allocate many strings. */
+
+static struct obstack obstack;
+
+/* This is the obstack to build an environment variable to pass to
+ collect2 that describes all of the relevant switches of what to
+ pass the compiler in building the list of pointers to constructors
+ and destructors. */
+
+static struct obstack collect_obstack;
+
+/* Forward declaration for prototypes. */
+struct path_prefix;
+struct prefix_list;
+
+static void init_spec (void);
+static void store_arg (const char *, int, int);
+static void insert_wrapper (const char *);
+static char *load_specs (const char *);
+static void read_specs (const char *, bool, bool);
+static void set_spec (const char *, const char *, bool);
+static struct compiler *lookup_compiler (const char *, size_t, const char *);
+static char *build_search_list (const struct path_prefix *, const char *,
+ bool, bool);
+static void xputenv (const char *);
+static void putenv_from_prefixes (const struct path_prefix *, const char *,
+ bool);
+static int access_check (const char *, int);
+static char *find_a_file (const struct path_prefix *, const char *, int, bool);
+static char *find_a_program (const char *);
+static void add_prefix (struct path_prefix *, const char *, const char *,
+ int, int, int);
+static void add_sysrooted_prefix (struct path_prefix *, const char *,
+ const char *, int, int, int);
+static char *skip_whitespace (char *);
+static void delete_if_ordinary (const char *);
+static void delete_temp_files (void);
+static void delete_failure_queue (void);
+static void clear_failure_queue (void);
+static int check_live_switch (int, int);
+static const char *handle_braces (const char *);
+static inline bool input_suffix_matches (const char *, const char *);
+static inline bool switch_matches (const char *, const char *, int);
+static inline void mark_matching_switches (const char *, const char *, int);
+static inline void process_marked_switches (void);
+static const char *process_brace_body (const char *, const char *, const char *, int, int);
+static const struct spec_function *lookup_spec_function (const char *);
+static const char *eval_spec_function (const char *, const char *, const char *);
+static const char *handle_spec_function (const char *, bool *, const char *);
+static char *save_string (const char *, int);
+static void set_collect_gcc_options (void);
+static int do_spec_1 (const char *, int, const char *);
+static int do_spec_2 (const char *, const char *);
+static void do_option_spec (const char *, const char *);
+static void do_self_spec (const char *);
+static const char *find_file (const char *);
+static int is_directory (const char *, bool);
+static const char *validate_switches (const char *, bool, bool);
+static void validate_all_switches (void);
+static inline void validate_switches_from_spec (const char *, bool);
+static void give_switch (int, int);
+static int default_arg (const char *, int);
+static void set_multilib_dir (void);
+static void print_multilib_info (void);
+static void display_help (void);
+static void add_preprocessor_option (const char *, int);
+static void add_assembler_option (const char *, int);
+static void add_linker_option (const char *, int);
+static void process_command (unsigned int, struct cl_decoded_option *);
+static int execute (void);
+static void alloc_args (void);
+static void clear_args (void);
+static void fatal_signal (int);
+#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
+static void init_gcc_specs (struct obstack *, const char *, const char *,
+ const char *);
+#endif
+#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+static const char *convert_filename (const char *, int, int);
+#endif
+
+static void try_generate_repro (const char **argv);
+static const char *getenv_spec_function (int, const char **);
+static const char *if_exists_spec_function (int, const char **);
+static const char *if_exists_else_spec_function (int, const char **);
+static const char *if_exists_then_else_spec_function (int, const char **);
+static const char *sanitize_spec_function (int, const char **);
+static const char *replace_outfile_spec_function (int, const char **);
+static const char *remove_outfile_spec_function (int, const char **);
+static const char *version_compare_spec_function (int, const char **);
+static const char *include_spec_function (int, const char **);
+static const char *find_file_spec_function (int, const char **);
+static const char *find_plugindir_spec_function (int, const char **);
+static const char *print_asm_header_spec_function (int, const char **);
+static const char *compare_debug_dump_opt_spec_function (int, const char **);
+static const char *compare_debug_self_opt_spec_function (int, const char **);
+static const char *pass_through_libs_spec_func (int, const char **);
+static const char *dumps_spec_func (int, const char **);
+static const char *greater_than_spec_func (int, const char **);
+static const char *debug_level_greater_than_spec_func (int, const char **);
+static const char *dwarf_version_greater_than_spec_func (int, const char **);
+static const char *find_fortran_preinclude_file (int, const char **);
+static char *convert_white_space (char *);
+static char *quote_spec (char *);
+static char *quote_spec_arg (char *);
+static bool not_actual_file_p (const char *);
+
+
+/* The Specs Language
+
+Specs are strings containing lines, each of which (if not blank)
+is made up of a program name, and arguments separated by spaces.
+The program name must be exact and start from root, since no path
+is searched and it is unreliable to depend on the current working directory.
+Redirection of input or output is not supported; the subprograms must
+accept filenames saying what files to read and write.
+
+In addition, the specs can contain %-sequences to substitute variable text
+or for conditional text. Here is a table of all defined %-sequences.
+Note that spaces are not generated automatically around the results of
+expanding these sequences; therefore, you can concatenate them together
+or with constant text in a single argument.
+
+ %% substitute one % into the program name or argument.
+ %" substitute an empty argument.
+ %i substitute the name of the input file being processed.
+ %b substitute the basename for outputs related with the input file
+ being processed. This is often a substring of the input file name,
+ up to (and not including) the last period but, unless %w is active,
+ it is affected by the directory selected by -save-temps=*, by
+ -dumpdir, and, in case of multiple compilations, even by -dumpbase
+ and -dumpbase-ext and, in case of linking, by the linker output
+ name. When %w is active, it derives the main output name only from
+ the input file base name; when it is not, it names aux/dump output
+ file.
+ %B same as %b, but include the input file suffix (text after the last
+ period).
+ %gSUFFIX
+ substitute a file name that has suffix SUFFIX and is chosen
+ once per compilation, and mark the argument a la %d. To reduce
+ exposure to denial-of-service attacks, the file name is now
+ chosen in a way that is hard to predict even when previously
+ chosen file names are known. For example, `%g.s ... %g.o ... %g.s'
+ might turn into `ccUVUUAU.s ccXYAXZ12.o ccUVUUAU.s'. SUFFIX matches
+ the regexp "[.0-9A-Za-z]*%O"; "%O" is treated exactly as if it
+ had been pre-processed. Previously, %g was simply substituted
+ with a file name chosen once per compilation, without regard
+ to any appended suffix (which was therefore treated just like
+ ordinary text), making such attacks more likely to succeed.
+ %|SUFFIX
+ like %g, but if -pipe is in effect, expands simply to "-".
+ %mSUFFIX
+ like %g, but if -pipe is in effect, expands to nothing. (We have both
+ %| and %m to accommodate differences between system assemblers; see
+ the AS_NEEDS_DASH_FOR_PIPED_INPUT target macro.)
+ %uSUFFIX
+ like %g, but generates a new temporary file name even if %uSUFFIX
+ was already seen.
+ %USUFFIX
+ substitutes the last file name generated with %uSUFFIX, generating a
+ new one if there is no such last file name. In the absence of any
+ %uSUFFIX, this is just like %gSUFFIX, except they don't share
+ the same suffix "space", so `%g.s ... %U.s ... %g.s ... %U.s'
+ would involve the generation of two distinct file names, one
+ for each `%g.s' and another for each `%U.s'. Previously, %U was
+ simply substituted with a file name chosen for the previous %u,
+ without regard to any appended suffix.
+ %jSUFFIX
+ substitutes the name of the HOST_BIT_BUCKET, if any, and if it is
+ writable, and if save-temps is off; otherwise, substitute the name
+ of a temporary file, just like %u. This temporary file is not
+ meant for communication between processes, but rather as a junk
+ disposal mechanism.
+ %.SUFFIX
+ substitutes .SUFFIX for the suffixes of a matched switch's args when
+ it is subsequently output with %*. SUFFIX is terminated by the next
+ space or %.
+ %d marks the argument containing or following the %d as a
+ temporary file name, so that file will be deleted if GCC exits
+ successfully. Unlike %g, this contributes no text to the argument.
+ %w marks the argument containing or following the %w as the
+ "output file" of this compilation. This puts the argument
+ into the sequence of arguments that %o will substitute later.
+ %V indicates that this compilation produces no "output file".
+ %W{...}
+ like %{...} but marks the last argument supplied within as a file
+ to be deleted on failure.
+ %@{...}
+ like %{...} but puts the result into a FILE and substitutes @FILE
+ if an @file argument has been supplied.
+ %o substitutes the names of all the output files, with spaces
+ automatically placed around them. You should write spaces
+ around the %o as well or the results are undefined.
+ %o is for use in the specs for running the linker.
+ Input files whose names have no recognized suffix are not compiled
+ at all, but they are included among the output files, so they will
+ be linked.
+ %O substitutes the suffix for object files. Note that this is
+ handled specially when it immediately follows %g, %u, or %U
+ (with or without a suffix argument) because of the need for
+ those to form complete file names. The handling is such that
+ %O is treated exactly as if it had already been substituted,
+ except that %g, %u, and %U do not currently support additional
+ SUFFIX characters following %O as they would following, for
+ example, `.o'.
+ %I Substitute any of -iprefix (made from GCC_EXEC_PREFIX), -isysroot
+ (made from TARGET_SYSTEM_ROOT), -isystem (made from COMPILER_PATH
+ and -B options) and -imultilib as necessary.
+ %s current argument is the name of a library or startup file of some sort.
+ Search for that file in a standard list of directories
+ and substitute the full name found.
+ %T current argument is the name of a linker script.
+ Search for that file in the current list of directories to scan for
+ libraries. If the file is located, insert a --script option into the
+ command line followed by the full path name found. If the file is
+ not found then generate an error message.
+ Note: the current working directory is not searched.
+ %eSTR Print STR as an error message. STR is terminated by a newline.
+ Use this when inconsistent options are detected.
+ %nSTR Print STR as a notice. STR is terminated by a newline.
+ %x{OPTION} Accumulate an option for %X.
+ %X Output the accumulated linker options specified by compilations.
+ %Y Output the accumulated assembler options specified by compilations.
+ %Z Output the accumulated preprocessor options specified by compilations.
+ %a process ASM_SPEC as a spec.
+ This allows config.h to specify part of the spec for running as.
+ %A process ASM_FINAL_SPEC as a spec. A capital A is actually
+ used here. This can be used to run a post-processor after the
+ assembler has done its job.
+ %D Dump out a -L option for each directory in startfile_prefixes.
+ If multilib_dir is set, extra entries are generated with it affixed.
+ %l process LINK_SPEC as a spec.
+ %L process LIB_SPEC as a spec.
+ %M Output multilib_os_dir.
+ %G process LIBGCC_SPEC as a spec.
+ %R Output the concatenation of target_system_root and
+ target_sysroot_suffix.
+ %S process STARTFILE_SPEC as a spec. A capital S is actually used here.
+ %E process ENDFILE_SPEC as a spec. A capital E is actually used here.
+ %C process CPP_SPEC as a spec.
+ %1 process CC1_SPEC as a spec.
+ %2 process CC1PLUS_SPEC as a spec.
+ %* substitute the variable part of a matched option. (See below.)
+ Note that each comma in the substituted string is replaced by
+ a single space. A space is appended after the last substition
+ unless there is more text in current sequence.
+ %<S remove all occurrences of -S from the command line.
+ Note - this command is position dependent. % commands in the
+ spec string before this one will see -S, % commands in the
+ spec string after this one will not.
+ %>S Similar to "%<S", but keep it in the GCC command line.
+ %<S* remove all occurrences of all switches beginning with -S from the
+ command line.
+ %:function(args)
+ Call the named function FUNCTION, passing it ARGS. ARGS is
+ first processed as a nested spec string, then split into an
+ argument vector in the usual fashion. The function returns
+ a string which is processed as if it had appeared literally
+ as part of the current spec.
+ %{S} substitutes the -S switch, if that switch was given to GCC.
+ If that switch was not specified, this substitutes nothing.
+ Here S is a metasyntactic variable.
+ %{S*} substitutes all the switches specified to GCC whose names start
+ with -S. This is used for -o, -I, etc; switches that take
+ arguments. GCC considers `-o foo' as being one switch whose
+ name starts with `o'. %{o*} would substitute this text,
+ including the space; thus, two arguments would be generated.
+ %{S*&T*} likewise, but preserve order of S and T options (the order
+ of S and T in the spec is not significant). Can be any number
+ of ampersand-separated variables; for each the wild card is
+ optional. Useful for CPP as %{D*&U*&A*}.
+
+ %{S:X} substitutes X, if the -S switch was given to GCC.
+ %{!S:X} substitutes X, if the -S switch was NOT given to GCC.
+ %{S*:X} substitutes X if one or more switches whose names start
+ with -S was given to GCC. Normally X is substituted only
+ once, no matter how many such switches appeared. However,
+ if %* appears somewhere in X, then X will be substituted
+ once for each matching switch, with the %* replaced by the
+ part of that switch that matched the '*'. A space will be
+ appended after the last substition unless there is more
+ text in current sequence.
+ %{.S:X} substitutes X, if processing a file with suffix S.
+ %{!.S:X} substitutes X, if NOT processing a file with suffix S.
+ %{,S:X} substitutes X, if processing a file which will use spec S.
+ %{!,S:X} substitutes X, if NOT processing a file which will use spec S.
+
+ %{S|T:X} substitutes X if either -S or -T was given to GCC. This may be
+ combined with '!', '.', ',', and '*' as above binding stronger
+ than the OR.
+ If %* appears in X, all of the alternatives must be starred, and
+ only the first matching alternative is substituted.
+ %{%:function(args):X}
+ Call function named FUNCTION with args ARGS. If the function
+ returns non-NULL, then X is substituted, if it returns
+ NULL, it isn't substituted.
+ %{S:X; if S was given to GCC, substitutes X;
+ T:Y; else if T was given to GCC, substitutes Y;
+ :D} else substitutes D. There can be as many clauses as you need.
+ This may be combined with '.', '!', ',', '|', and '*' as above.
+
+ %(Spec) processes a specification defined in a specs file as *Spec:
+
+The switch matching text S in a %{S}, %{S:X}, or similar construct can use
+a backslash to ignore the special meaning of the character following it,
+thus allowing literal matching of a character that is otherwise specially
+treated. For example, %{std=iso9899\:1999:X} substitutes X if the
+-std=iso9899:1999 option is given.
+
+The conditional text X in a %{S:X} or similar construct may contain
+other nested % constructs or spaces, or even newlines. They are
+processed as usual, as described above. Trailing white space in X is
+ignored. White space may also appear anywhere on the left side of the
+colon in these constructs, except between . or * and the corresponding
+word.
+
+The -O, -f, -g, -m, and -W switches are handled specifically in these
+constructs. If another value of -O or the negated form of a -f, -m, or
+-W switch is found later in the command line, the earlier switch
+value is ignored, except with {S*} where S is just one letter; this
+passes all matching options.
+
+The character | at the beginning of the predicate text is used to indicate
+that a command should be piped to the following command, but only if -pipe
+is specified.
+
+Note that it is built into GCC which switches take arguments and which
+do not. You might think it would be useful to generalize this to
+allow each compiler's spec to say which switches take arguments. But
+this cannot be done in a consistent fashion. GCC cannot even decide
+which input files have been specified without knowing which switches
+take arguments, and it must know which input files to compile in order
+to tell which compilers to run.
+
+GCC also knows implicitly that arguments starting in `-l' are to be
+treated as compiler output files, and passed to the linker in their
+proper position among the other output files. */
+
+/* Define the macros used for specs %a, %l, %L, %S, %C, %1. */
+
+/* config.h can define ASM_SPEC to provide extra args to the assembler
+ or extra switch-translations. */
+#ifndef ASM_SPEC
+#define ASM_SPEC ""
+#endif
+
+/* config.h can define ASM_FINAL_SPEC to run a post processor after
+ the assembler has run. */
+#ifndef ASM_FINAL_SPEC
+#define ASM_FINAL_SPEC \
+ "%{gsplit-dwarf: \n\
+ objcopy --extract-dwo \
+ %{c:%{o*:%*}%{!o*:%w%b%O}}%{!c:%U%O} \
+ %b.dwo \n\
+ objcopy --strip-dwo \
+ %{c:%{o*:%*}%{!o*:%w%b%O}}%{!c:%U%O} \
+ }"
+#endif
+
+/* config.h can define CPP_SPEC to provide extra args to the C preprocessor
+ or extra switch-translations. */
+#ifndef CPP_SPEC
+#define CPP_SPEC ""
+#endif
+
+/* config.h can define CC1_SPEC to provide extra args to cc1 and cc1plus
+ or extra switch-translations. */
+#ifndef CC1_SPEC
+#define CC1_SPEC ""
+#endif
+
+/* config.h can define CC1PLUS_SPEC to provide extra args to cc1plus
+ or extra switch-translations. */
+#ifndef CC1PLUS_SPEC
+#define CC1PLUS_SPEC ""
+#endif
+
+/* config.h can define LINK_SPEC to provide extra args to the linker
+ or extra switch-translations. */
+#ifndef LINK_SPEC
+#define LINK_SPEC ""
+#endif
+
+/* config.h can define LIB_SPEC to override the default libraries. */
+#ifndef LIB_SPEC
+#define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
+#endif
+
+/* When using -fsplit-stack we need to wrap pthread_create, in order
+ to initialize the stack guard. We always use wrapping, rather than
+ shared library ordering, and we keep the wrapper function in
+ libgcc. This is not yet a real spec, though it could become one;
+ it is currently just stuffed into LINK_SPEC. FIXME: This wrapping
+ only works with GNU ld and gold. */
+#ifdef HAVE_GOLD_NON_DEFAULT_SPLIT_STACK
+#define STACK_SPLIT_SPEC " %{fsplit-stack: -fuse-ld=gold --wrap=pthread_create}"
+#else
+#define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}"
+#endif
+
+#ifndef LIBASAN_SPEC
+#define STATIC_LIBASAN_LIBS \
+ " %{static-libasan|static:%:include(libsanitizer.spec)%(link_libasan)}"
+#ifdef LIBASAN_EARLY_SPEC
+#define LIBASAN_SPEC STATIC_LIBASAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBASAN_SPEC "%{static-libasan:" LD_STATIC_OPTION \
+ "} -lasan %{static-libasan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBASAN_LIBS
+#else
+#define LIBASAN_SPEC "-lasan" STATIC_LIBASAN_LIBS
+#endif
+#endif
+
+#ifndef LIBASAN_EARLY_SPEC
+#define LIBASAN_EARLY_SPEC ""
+#endif
+
+#ifndef LIBHWASAN_SPEC
+#define STATIC_LIBHWASAN_LIBS \
+ " %{static-libhwasan|static:%:include(libsanitizer.spec)%(link_libhwasan)}"
+#ifdef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_SPEC STATIC_LIBHWASAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBHWASAN_SPEC "%{static-libhwasan:" LD_STATIC_OPTION \
+ "} -lhwasan %{static-libhwasan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBHWASAN_LIBS
+#else
+#define LIBHWASAN_SPEC "-lhwasan" STATIC_LIBHWASAN_LIBS
+#endif
+#endif
+
+#ifndef LIBHWASAN_EARLY_SPEC
+#define LIBHWASAN_EARLY_SPEC ""
+#endif
+
+#ifndef LIBTSAN_SPEC
+#define STATIC_LIBTSAN_LIBS \
+ " %{static-libtsan|static:%:include(libsanitizer.spec)%(link_libtsan)}"
+#ifdef LIBTSAN_EARLY_SPEC
+#define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \
+ "} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBTSAN_LIBS
+#else
+#define LIBTSAN_SPEC "-ltsan" STATIC_LIBTSAN_LIBS
+#endif
+#endif
+
+#ifndef LIBTSAN_EARLY_SPEC
+#define LIBTSAN_EARLY_SPEC ""
+#endif
+
+#ifndef LIBLSAN_SPEC
+#define STATIC_LIBLSAN_LIBS \
+ " %{static-liblsan|static:%:include(libsanitizer.spec)%(link_liblsan)}"
+#ifdef LIBLSAN_EARLY_SPEC
+#define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS
+#elif defined(HAVE_LD_STATIC_DYNAMIC)
+#define LIBLSAN_SPEC "%{static-liblsan:" LD_STATIC_OPTION \
+ "} -llsan %{static-liblsan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBLSAN_LIBS
+#else
+#define LIBLSAN_SPEC "-llsan" STATIC_LIBLSAN_LIBS
+#endif
+#endif
+
+#ifndef LIBLSAN_EARLY_SPEC
+#define LIBLSAN_EARLY_SPEC ""
+#endif
+
+#ifndef LIBUBSAN_SPEC
+#define STATIC_LIBUBSAN_LIBS \
+ " %{static-libubsan|static:%:include(libsanitizer.spec)%(link_libubsan)}"
+#ifdef HAVE_LD_STATIC_DYNAMIC
+#define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \
+ "} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \
+ STATIC_LIBUBSAN_LIBS
+#else
+#define LIBUBSAN_SPEC "-lubsan" STATIC_LIBUBSAN_LIBS
+#endif
+#endif
+
+/* Linker options for compressed debug sections. */
+#if HAVE_LD_COMPRESS_DEBUG == 0
+/* No linker support. */
+#define LINK_COMPRESS_DEBUG_SPEC \
+ " %{gz*:%e-gz is not supported in this configuration} "
+#elif HAVE_LD_COMPRESS_DEBUG == 1
+/* GNU style on input, GNU ld options. Reject, not useful. */
+#define LINK_COMPRESS_DEBUG_SPEC \
+ " %{gz*:%e-gz is not supported in this configuration} "
+#elif HAVE_LD_COMPRESS_DEBUG == 2
+/* GNU style, GNU gold options. */
+#define LINK_COMPRESS_DEBUG_SPEC \
+ " %{gz|gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
+ " %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \
+ " %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
+#elif HAVE_LD_COMPRESS_DEBUG == 3
+/* ELF gABI style. */
+#define LINK_COMPRESS_DEBUG_SPEC \
+ " %{gz|gz=zlib:" LD_COMPRESS_DEBUG_OPTION "=zlib}" \
+ " %{gz=none:" LD_COMPRESS_DEBUG_OPTION "=none}" \
+ " %{gz=zlib-gnu:" LD_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
+#else
+#error Unknown value for HAVE_LD_COMPRESS_DEBUG.
+#endif
+
+/* config.h can define LIBGCC_SPEC to override how and when libgcc.a is
+ included. */
+#ifndef LIBGCC_SPEC
+#if defined(REAL_LIBGCC_SPEC)
+#define LIBGCC_SPEC REAL_LIBGCC_SPEC
+#elif defined(LINK_LIBGCC_SPECIAL_1)
+/* Have gcc do the search for libgcc.a. */
+#define LIBGCC_SPEC "libgcc.a%s"
+#else
+#define LIBGCC_SPEC "-lgcc"
+#endif
+#endif
+
+/* config.h can define STARTFILE_SPEC to override the default crt0 files. */
+#ifndef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}"
+#endif
+
+/* config.h can define ENDFILE_SPEC to override the default crtn files. */
+#ifndef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
+#endif
+
+#ifndef LINKER_NAME
+#define LINKER_NAME "collect2"
+#endif
+
+#ifdef HAVE_AS_DEBUG_PREFIX_MAP
+#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
+#else
+#define ASM_MAP ""
+#endif
+
+/* Assembler options for compressed debug sections. */
+#if HAVE_LD_COMPRESS_DEBUG < 2
+/* Reject if the linker cannot write compressed debug sections. */
+#define ASM_COMPRESS_DEBUG_SPEC \
+ " %{gz*:%e-gz is not supported in this configuration} "
+#else /* HAVE_LD_COMPRESS_DEBUG >= 2 */
+#if HAVE_AS_COMPRESS_DEBUG == 0
+/* No assembler support. Ignore silently. */
+#define ASM_COMPRESS_DEBUG_SPEC \
+ " %{gz*:} "
+#elif HAVE_AS_COMPRESS_DEBUG == 1
+/* GNU style, GNU as options. */
+#define ASM_COMPRESS_DEBUG_SPEC \
+ " %{gz|gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "}" \
+ " %{gz=none:" AS_NO_COMPRESS_DEBUG_OPTION "}" \
+ " %{gz=zlib:%e-gz=zlib is not supported in this configuration} "
+#elif HAVE_AS_COMPRESS_DEBUG == 2
+/* ELF gABI style. */
+#define ASM_COMPRESS_DEBUG_SPEC \
+ " %{gz|gz=zlib:" AS_COMPRESS_DEBUG_OPTION "=zlib}" \
+ " %{gz=none:" AS_COMPRESS_DEBUG_OPTION "=none}" \
+ " %{gz=zlib-gnu:" AS_COMPRESS_DEBUG_OPTION "=zlib-gnu} "
+#else
+#error Unknown value for HAVE_AS_COMPRESS_DEBUG.
+#endif
+#endif /* HAVE_LD_COMPRESS_DEBUG >= 2 */
+
+/* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
+ to the assembler, when compiling assembly sources only. */
+#ifndef ASM_DEBUG_SPEC
+# if defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) && defined(HAVE_AS_WORKING_DWARF_N_FLAG)
+/* If --gdwarf-N is supported and as can handle even compiler generated
+ .debug_line with it, supply --gdwarf-N in ASM_DEBUG_OPTION_SPEC rather
+ than in ASM_DEBUG_SPEC, so that it applies to both .s and .c etc.
+ compilations. */
+# define ASM_DEBUG_DWARF_OPTION ""
+# elif defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) && !defined(HAVE_LD_BROKEN_PE_DWARF5)
+# define ASM_DEBUG_DWARF_OPTION "%{%:dwarf-version-gt(4):--gdwarf-5;" \
+ "%:dwarf-version-gt(3):--gdwarf-4;" \
+ "%:dwarf-version-gt(2):--gdwarf-3;" \
+ ":--gdwarf2}"
+# 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
+
+/* Define ASM_DEBUG_OPTION_SPEC to be a spec suitable for translating '-g'
+ to the assembler when compiling all sources. */
+#ifndef ASM_DEBUG_OPTION_SPEC
+# if defined(HAVE_AS_GDWARF_5_DEBUG_FLAG) && defined(HAVE_AS_WORKING_DWARF_N_FLAG)
+# define ASM_DEBUG_OPTION_DWARF_OPT \
+ "%{%:dwarf-version-gt(4):--gdwarf-5 ;" \
+ "%: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)
+# define ASM_DEBUG_OPTION_SPEC "%{g*:%{%:debug-level-gt(0):" \
+ ASM_DEBUG_OPTION_DWARF_OPT "}}"
+# endif
+# endif
+#endif
+#ifndef ASM_DEBUG_OPTION_SPEC
+# define ASM_DEBUG_OPTION_SPEC ""
+#endif
+
+/* Here is the spec for running the linker, after compiling all files. */
+
+/* This is overridable by the target in case they need to specify the
+ -lgcc and -lc order specially, yet not require them to override all
+ of LINK_COMMAND_SPEC. */
+#ifndef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC "%G %{!nolibc:%L %G}"
+#endif
+
+#ifndef LINK_SSP_SPEC
+#ifdef TARGET_LIBC_PROVIDES_SSP
+#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ "|fstack-protector-strong|fstack-protector-explicit:}"
+#else
+#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ "|fstack-protector-strong|fstack-protector-explicit" \
+ ":-lssp_nonshared -lssp}"
+#endif
+#endif
+
+#ifdef ENABLE_DEFAULT_PIE
+#define PIE_SPEC "!no-pie"
+#define NO_FPIE1_SPEC "fno-pie"
+#define FPIE1_SPEC NO_FPIE1_SPEC ":;"
+#define NO_FPIE2_SPEC "fno-PIE"
+#define FPIE2_SPEC NO_FPIE2_SPEC ":;"
+#define NO_FPIE_SPEC NO_FPIE1_SPEC "|" NO_FPIE2_SPEC
+#define FPIE_SPEC NO_FPIE_SPEC ":;"
+#define NO_FPIC1_SPEC "fno-pic"
+#define FPIC1_SPEC NO_FPIC1_SPEC ":;"
+#define NO_FPIC2_SPEC "fno-PIC"
+#define FPIC2_SPEC NO_FPIC2_SPEC ":;"
+#define NO_FPIC_SPEC NO_FPIC1_SPEC "|" NO_FPIC2_SPEC
+#define FPIC_SPEC NO_FPIC_SPEC ":;"
+#define NO_FPIE1_AND_FPIC1_SPEC NO_FPIE1_SPEC "|" NO_FPIC1_SPEC
+#define FPIE1_OR_FPIC1_SPEC NO_FPIE1_AND_FPIC1_SPEC ":;"
+#define NO_FPIE2_AND_FPIC2_SPEC NO_FPIE2_SPEC "|" NO_FPIC2_SPEC
+#define FPIE2_OR_FPIC2_SPEC NO_FPIE2_AND_FPIC2_SPEC ":;"
+#define NO_FPIE_AND_FPIC_SPEC NO_FPIE_SPEC "|" NO_FPIC_SPEC
+#define FPIE_OR_FPIC_SPEC NO_FPIE_AND_FPIC_SPEC ":;"
+#else
+#define PIE_SPEC "pie"
+#define FPIE1_SPEC "fpie"
+#define NO_FPIE1_SPEC FPIE1_SPEC ":;"
+#define FPIE2_SPEC "fPIE"
+#define NO_FPIE2_SPEC FPIE2_SPEC ":;"
+#define FPIE_SPEC FPIE1_SPEC "|" FPIE2_SPEC
+#define NO_FPIE_SPEC FPIE_SPEC ":;"
+#define FPIC1_SPEC "fpic"
+#define NO_FPIC1_SPEC FPIC1_SPEC ":;"
+#define FPIC2_SPEC "fPIC"
+#define NO_FPIC2_SPEC FPIC2_SPEC ":;"
+#define FPIC_SPEC FPIC1_SPEC "|" FPIC2_SPEC
+#define NO_FPIC_SPEC FPIC_SPEC ":;"
+#define FPIE1_OR_FPIC1_SPEC FPIE1_SPEC "|" FPIC1_SPEC
+#define NO_FPIE1_AND_FPIC1_SPEC FPIE1_OR_FPIC1_SPEC ":;"
+#define FPIE2_OR_FPIC2_SPEC FPIE2_SPEC "|" FPIC2_SPEC
+#define NO_FPIE2_AND_FPIC2_SPEC FPIE1_OR_FPIC2_SPEC ":;"
+#define FPIE_OR_FPIC_SPEC FPIE_SPEC "|" FPIC_SPEC
+#define NO_FPIE_AND_FPIC_SPEC FPIE_OR_FPIC_SPEC ":;"
+#endif
+
+#ifndef LINK_PIE_SPEC
+#ifdef HAVE_LD_PIE
+#ifndef LD_PIE_SPEC
+#define LD_PIE_SPEC "-pie"
+#endif
+#else
+#define LD_PIE_SPEC ""
+#endif
+#define LINK_PIE_SPEC "%{static|shared|r:;" PIE_SPEC ":" LD_PIE_SPEC "} "
+#endif
+
+#ifndef LINK_BUILDID_SPEC
+# if defined(HAVE_LD_BUILDID) && defined(ENABLE_LD_BUILDID)
+# define LINK_BUILDID_SPEC "%{!r:--build-id} "
+# endif
+#endif
+
+#ifndef LTO_PLUGIN_SPEC
+#define LTO_PLUGIN_SPEC ""
+#endif
+
+/* Conditional to test whether the LTO plugin is used or not.
+ FIXME: For slim LTO we will need to enable plugin unconditionally. This
+ still cause problems with PLUGIN_LD != LD and when plugin is built but
+ not useable. For GCC 4.6 we don't support slim LTO and thus we can enable
+ plugin only when LTO is enabled. We still honor explicit
+ -fuse-linker-plugin if the linker used understands -plugin. */
+
+/* The linker has some plugin support. */
+#if HAVE_LTO_PLUGIN > 0
+/* The linker used has full plugin support, use LTO plugin by default. */
+#if HAVE_LTO_PLUGIN == 2
+#define PLUGIN_COND "!fno-use-linker-plugin:%{!fno-lto"
+#define PLUGIN_COND_CLOSE "}"
+#else
+/* The linker used has limited plugin support, use LTO plugin with explicit
+ -fuse-linker-plugin. */
+#define PLUGIN_COND "fuse-linker-plugin"
+#define PLUGIN_COND_CLOSE ""
+#endif
+#define LINK_PLUGIN_SPEC \
+ "%{" PLUGIN_COND": \
+ -plugin %(linker_plugin_file) \
+ -plugin-opt=%(lto_wrapper) \
+ -plugin-opt=-fresolution=%u.res \
+ " LTO_PLUGIN_SPEC "\
+ %{flinker-output=*:-plugin-opt=-linker-output-known} \
+ %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
+ }" PLUGIN_COND_CLOSE
+#else
+/* The linker used doesn't support -plugin, reject -fuse-linker-plugin. */
+#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
+ %e-fuse-linker-plugin is not supported in this configuration}"
+#endif
+
+/* Linker command line options for -fsanitize= early on the command line. */
+#ifndef SANITIZER_EARLY_SPEC
+#define SANITIZER_EARLY_SPEC "\
+%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \
+ %{%:sanitize(hwaddress):" LIBHWASAN_EARLY_SPEC "} \
+ %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \
+ %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}}"
+#endif
+
+/* Linker command line options for -fsanitize= late on the command line. */
+#ifndef SANITIZER_SPEC
+#define SANITIZER_SPEC "\
+%{!nostdlib:%{!r:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\
+ %{static:%ecannot specify -static with -fsanitize=address}}\
+ %{%:sanitize(hwaddress):" LIBHWASAN_SPEC "\
+ %{static:%ecannot specify -static with -fsanitize=hwaddress}}\
+ %{%:sanitize(thread):" LIBTSAN_SPEC "\
+ %{static:%ecannot specify -static with -fsanitize=thread}}\
+ %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\
+ %{%:sanitize(leak):" LIBLSAN_SPEC "}}}}"
+#endif
+
+#ifndef POST_LINK_SPEC
+#define POST_LINK_SPEC ""
+#endif
+
+/* This is the spec to use, once the code for creating the vtable
+ verification runtime library, libvtv.so, has been created. Currently
+ the vtable verification runtime functions are in libstdc++, so we use
+ the spec just below this one. */
+#ifndef VTABLE_VERIFICATION_SPEC
+#if ENABLE_VTABLE_VERIFY
+#define VTABLE_VERIFICATION_SPEC "\
+%{!nostdlib:%{!r:%{fvtable-verify=std: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}\
+ %{fvtable-verify=preinit: -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end}}}"
+#else
+#define VTABLE_VERIFICATION_SPEC "\
+%{fvtable-verify=none:} \
+%{fvtable-verify=std: \
+ %e-fvtable-verify=std is not supported in this configuration} \
+%{fvtable-verify=preinit: \
+ %e-fvtable-verify=preinit is not supported in this configuration}"
+#endif
+#endif
+
+/* -u* was put back because both BSD and SysV seem to support it. */
+/* %{static|no-pie|static-pie:} simply prevents an error message:
+ 1. If the target machine doesn't handle -static.
+ 2. If PIE isn't enabled by default.
+ 3. If the target machine doesn't handle -static-pie.
+ */
+/* We want %{T*} after %{L*} and %D so that it can be used to specify linker
+ scripts which exist in user specified directories, or in standard
+ directories. */
+/* We pass any -flto flags on to the linker, which is expected
+ to understand them. In practice, this means it had better be collect2. */
+/* %{e*} includes -export-dynamic; see comment in common.opt. */
+#ifndef LINK_COMMAND_SPEC
+#define LINK_COMMAND_SPEC "\
+%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
+ %(linker) " \
+ LINK_PLUGIN_SPEC \
+ "%{flto|flto=*:%<fcompare-debug*} \
+ %{flto} %{fno-lto} %{flto=*} %l " LINK_PIE_SPEC \
+ "%{fuse-ld=*:-fuse-ld=%*} " LINK_COMPRESS_DEBUG_SPEC \
+ "%X %{o*} %{e*} %{N} %{n} %{r}\
+ %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!r:%{!nostartfiles:%S}}} \
+ %{static|no-pie|static-pie:} %@{L*} %(mfwrap) %(link_libgcc) " \
+ VTABLE_VERIFICATION_SPEC " " SANITIZER_EARLY_SPEC " %o "" \
+ %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\
+ %:include(libgomp.spec)%(link_gomp)}\
+ %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
+ %(mflib) " STACK_SPLIT_SPEC "\
+ %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} " SANITIZER_SPEC " \
+ %{!nostdlib:%{!r:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}}\
+ %{!nostdlib:%{!r:%{!nostartfiles:%E}}} %{T*} \n%(post_link) }}}}}}"
+#endif
+
+#ifndef LINK_LIBGCC_SPEC
+/* Generate -L options for startfile prefix list. */
+# define LINK_LIBGCC_SPEC "%D"
+#endif
+
+#ifndef STARTFILE_PREFIX_SPEC
+# define STARTFILE_PREFIX_SPEC ""
+#endif
+
+#ifndef SYSROOT_SPEC
+# define SYSROOT_SPEC "--sysroot=%R"
+#endif
+
+#ifndef SYSROOT_SUFFIX_SPEC
+# define SYSROOT_SUFFIX_SPEC ""
+#endif
+
+#ifndef SYSROOT_HEADERS_SUFFIX_SPEC
+# define SYSROOT_HEADERS_SUFFIX_SPEC ""
+#endif
+
+static const char *asm_debug = ASM_DEBUG_SPEC;
+static const char *asm_debug_option = ASM_DEBUG_OPTION_SPEC;
+static const char *cpp_spec = CPP_SPEC;
+static const char *cc1_spec = CC1_SPEC;
+static const char *cc1plus_spec = CC1PLUS_SPEC;
+static const char *link_gcc_c_sequence_spec = LINK_GCC_C_SEQUENCE_SPEC;
+static const char *link_ssp_spec = LINK_SSP_SPEC;
+static const char *asm_spec = ASM_SPEC;
+static const char *asm_final_spec = ASM_FINAL_SPEC;
+static const char *link_spec = LINK_SPEC;
+static const char *lib_spec = LIB_SPEC;
+static const char *link_gomp_spec = "";
+static const char *libgcc_spec = LIBGCC_SPEC;
+static const char *endfile_spec = ENDFILE_SPEC;
+static const char *startfile_spec = STARTFILE_SPEC;
+static const char *linker_name_spec = LINKER_NAME;
+static const char *linker_plugin_file_spec = "";
+static const char *lto_wrapper_spec = "";
+static const char *lto_gcc_spec = "";
+static const char *post_link_spec = POST_LINK_SPEC;
+static const char *link_command_spec = LINK_COMMAND_SPEC;
+static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
+static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
+static const char *sysroot_spec = SYSROOT_SPEC;
+static const char *sysroot_suffix_spec = SYSROOT_SUFFIX_SPEC;
+static const char *sysroot_hdrs_suffix_spec = SYSROOT_HEADERS_SUFFIX_SPEC;
+static const char *self_spec = "";
+
+/* Standard options to cpp, cc1, and as, to reduce duplication in specs.
+ There should be no need to override these in target dependent files,
+ but we need to copy them to the specs file so that newer versions
+ of the GCC driver can correctly drive older tool chains with the
+ appropriate -B options. */
+
+/* When cpplib handles traditional preprocessing, get rid of this, and
+ call cc1 (or cc1obj in objc/lang-specs.h) from the main specs so
+ that we default the front end language better. */
+static const char *trad_capable_cpp =
+"cc1 -E %{traditional|traditional-cpp:-traditional-cpp}";
+
+/* We don't wrap .d files in %W{} since a missing .d file, and
+ therefore no dependency entry, confuses make into thinking a .o
+ file that happens to exist is up-to-date. */
+static const char *cpp_unique_options =
+"%{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %@{I*&F*} %{P} %I\
+ %{MD:-MD %{!o:%b.d}%{o*:%.d%*}}\
+ %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}}\
+ %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*}\
+ %{Mmodules} %{Mno-modules}\
+ %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}}\
+ %{remap} %{%:debug-level-gt(2):-dD}\
+ %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
+ %{H} %C %{D*&U*&A*} %{i*} %Z %i\
+ %{E|M|MM:%W{o*}}";
+
+/* This contains cpp options which are common with cc1_options and are passed
+ only when preprocessing only to avoid duplication. We pass the cc1 spec
+ options to the preprocessor so that it the cc1 spec may manipulate
+ options used to set target flags. Those special target flags settings may
+ in turn cause preprocessor symbols to be defined specially. */
+static const char *cpp_options =
+"%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
+ %{f*} %{g*:%{%:debug-level-gt(0):%{g*}\
+ %{!fno-working-directory:-fworking-directory}}} %{O*}\
+ %{undef} %{save-temps*:-fpch-preprocess}";
+
+/* Pass -d* flags, possibly modifying -dumpdir, -dumpbase et al.
+
+ Make it easy for a language to override the argument for the
+ %:dumps specs function call. */
+#define DUMPS_OPTIONS(EXTS) \
+ "%<dumpdir %<dumpbase %<dumpbase-ext %{d*} %:dumps(" EXTS ")"
+
+/* This contains cpp options which are not passed when the preprocessor
+ output will be used by another program. */
+static const char *cpp_debug_options = DUMPS_OPTIONS ("");
+
+/* NB: This is shared amongst all front-ends, except for Ada. */
+static const char *cc1_options =
+"%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
+ %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\
+ %1 %{!Q:-quiet} %(cpp_debug_options) %{m*} %{aux-info*}\
+ %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs}\
+ %{v:-version} %{pg:-p} %{p} %{f*} %{undef}\
+ %{Qn:-fno-ident} %{Qy:} %{-help:--help}\
+ %{-target-help:--target-help}\
+ %{-version:--version}\
+ %{-help=*:--help=%*}\
+ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}}\
+ %{fsyntax-only:-o %j} %{-param*}\
+ %{coverage:-fprofile-arcs -ftest-coverage}\
+ %{fprofile-arcs|fprofile-generate*|coverage:\
+ %{!fprofile-update=single:\
+ %{pthread:-fprofile-update=prefer-atomic}}}";
+
+static const char *asm_options =
+"%{-target-help:%:print-asm-header()} "
+#if HAVE_GNU_AS
+/* If GNU AS is used, then convert -w (no warnings), -I, and -v
+ to the assembler equivalents. */
+"%{v} %{w:-W} %{I*} "
+#endif
+"%(asm_debug_option)"
+ASM_COMPRESS_DEBUG_SPEC
+"%a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}";
+
+static const char *invoke_as =
+#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
+"%{!fwpa*:\
+ %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
+ %{!S:-o %|.s |\n as %(asm_options) %|.s %A }\
+ }";
+#else
+"%{!fwpa*:\
+ %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()}\
+ %{!S:-o %|.s |\n as %(asm_options) %m.s %A }\
+ }";
+#endif
+
+/* Some compilers have limits on line lengths, and the multilib_select
+ and/or multilib_matches strings can be very long, so we build them at
+ run time. */
+static struct obstack multilib_obstack;
+static const char *multilib_select;
+static const char *multilib_matches;
+static const char *multilib_defaults;
+static const char *multilib_exclusions;
+static const char *multilib_reuse;
+
+/* Check whether a particular argument is a default argument. */
+
+#ifndef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "" }
+#endif
+
+static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
+
+#ifndef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS ""
+#endif
+
+/* Linking to libgomp implies pthreads. This is particularly important
+ for targets that use different start files and suchlike. */
+#ifndef GOMP_SELF_SPECS
+#define GOMP_SELF_SPECS \
+ "%{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1): " \
+ "-pthread}"
+#endif
+
+/* Likewise for -fgnu-tm. */
+#ifndef GTM_SELF_SPECS
+#define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
+#endif
+
+static const char *const driver_self_specs[] = {
+ "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
+ DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
+};
+
+#ifndef OPTION_DEFAULT_SPECS
+#define OPTION_DEFAULT_SPECS { "", "" }
+#endif
+
+struct default_spec
+{
+ const char *name;
+ const char *spec;
+};
+
+static const struct default_spec
+ option_default_specs[] = { OPTION_DEFAULT_SPECS };
+
+struct user_specs
+{
+ struct user_specs *next;
+ const char *filename;
+};
+
+static struct user_specs *user_specs_head, *user_specs_tail;
+
+
+/* Record the mapping from file suffixes for compilation specs. */
+
+struct compiler
+{
+ const char *suffix; /* Use this compiler for input files
+ whose names end in this suffix. */
+
+ const char *spec; /* To use this compiler, run this spec. */
+
+ const char *cpp_spec; /* If non-NULL, substitute this spec
+ for `%C', rather than the usual
+ cpp_spec. */
+ int combinable; /* If nonzero, compiler can deal with
+ multiple source files at once (IMA). */
+ int needs_preprocessing; /* If nonzero, source files need to
+ be run through a preprocessor. */
+};
+
+/* Pointer to a vector of `struct compiler' that gives the spec for
+ compiling a file, based on its suffix.
+ A file that does not end in any of these suffixes will be passed
+ unchanged to the loader and nothing else will be done to it.
+
+ An entry containing two 0s is used to terminate the vector.
+
+ If multiple entries match a file, the last matching one is used. */
+
+static struct compiler *compilers;
+
+/* Number of entries in `compilers', not counting the null terminator. */
+
+static int n_compilers;
+
+/* The default list of file name suffixes and their compilation specs. */
+
+static const struct compiler default_compilers[] =
+{
+ /* Add lists of suffixes of known languages here. If those languages
+ were not present when we built the driver, we will hit these copies
+ and be given a more meaningful error than "file not used since
+ linking is not done". */
+ {".m", "#Objective-C", 0, 0, 0}, {".mi", "#Objective-C", 0, 0, 0},
+ {".mm", "#Objective-C++", 0, 0, 0}, {".M", "#Objective-C++", 0, 0, 0},
+ {".mii", "#Objective-C++", 0, 0, 0},
+ {".cc", "#C++", 0, 0, 0}, {".cxx", "#C++", 0, 0, 0},
+ {".cpp", "#C++", 0, 0, 0}, {".cp", "#C++", 0, 0, 0},
+ {".c++", "#C++", 0, 0, 0}, {".C", "#C++", 0, 0, 0},
+ {".CPP", "#C++", 0, 0, 0}, {".ii", "#C++", 0, 0, 0},
+ {".ads", "#Ada", 0, 0, 0}, {".adb", "#Ada", 0, 0, 0},
+ {".f", "#Fortran", 0, 0, 0}, {".F", "#Fortran", 0, 0, 0},
+ {".for", "#Fortran", 0, 0, 0}, {".FOR", "#Fortran", 0, 0, 0},
+ {".ftn", "#Fortran", 0, 0, 0}, {".FTN", "#Fortran", 0, 0, 0},
+ {".fpp", "#Fortran", 0, 0, 0}, {".FPP", "#Fortran", 0, 0, 0},
+ {".f90", "#Fortran", 0, 0, 0}, {".F90", "#Fortran", 0, 0, 0},
+ {".f95", "#Fortran", 0, 0, 0}, {".F95", "#Fortran", 0, 0, 0},
+ {".f03", "#Fortran", 0, 0, 0}, {".F03", "#Fortran", 0, 0, 0},
+ {".f08", "#Fortran", 0, 0, 0}, {".F08", "#Fortran", 0, 0, 0},
+ {".r", "#Ratfor", 0, 0, 0},
+ {".go", "#Go", 0, 1, 0},
+ {".d", "#D", 0, 1, 0}, {".dd", "#D", 0, 1, 0}, {".di", "#D", 0, 1, 0},
+ /* Next come the entries for C. */
+ {".c", "@c", 0, 0, 1},
+ {"@c",
+ /* cc1 has an integrated ISO C preprocessor. We should invoke the
+ external preprocessor if -save-temps is given. */
+ "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{traditional:\
+%eGNU C no longer supports -traditional without -E}\
+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+ cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
+ %(cc1_options)}\
+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
+ cc1 %(cpp_unique_options) %(cc1_options)}}}\
+ %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 1},
+ {"-",
+ "%{!E:%e-E or -x required when input is from standard input}\
+ %(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)", 0, 0, 0},
+ {".h", "@c-header", 0, 0, 0},
+ {"@c-header",
+ /* cc1 has an integrated ISO C preprocessor. We should invoke the
+ external preprocessor if -save-temps is given. */
+ "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_options)}\
+ %{!E:%{!M:%{!MM:\
+ %{save-temps*|traditional-cpp|no-integrated-cpp:%(trad_capable_cpp) \
+ %(cpp_options) -o %{save-temps*:%b.i} %{!save-temps*:%g.i} \n\
+ cc1 -fpreprocessed %{save-temps*:%b.i} %{!save-temps*:%g.i} \
+ %(cc1_options)\
+ %{!fsyntax-only:%{!S:-o %g.s} \
+ %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\
+ %W{o*:--output-pch=%*}}%V}}\
+ %{!save-temps*:%{!traditional-cpp:%{!no-integrated-cpp:\
+ cc1 %(cpp_unique_options) %(cc1_options)\
+ %{!fsyntax-only:%{!S:-o %g.s} \
+ %{!fdump-ada-spec*:%{!o*:--output-pch=%i.gch}\
+ %W{o*:--output-pch=%*}}%V}}}}}}}", 0, 0, 0},
+ {".i", "@cpp-output", 0, 0, 0},
+ {"@cpp-output",
+ "%{!M:%{!MM:%{!E:cc1 -fpreprocessed %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0},
+ {".s", "@assembler", 0, 0, 0},
+ {"@assembler",
+ "%{!M:%{!MM:%{!E:%{!S:as %(asm_debug) %(asm_options) %i %A }}}}", 0, 0, 0},
+ {".sx", "@assembler-with-cpp", 0, 0, 0},
+ {".S", "@assembler-with-cpp", 0, 0, 0},
+ {"@assembler-with-cpp",
+#ifdef AS_NEEDS_DASH_FOR_PIPED_INPUT
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
+ %{E|M|MM:%(cpp_debug_options)}\
+ %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
+ as %(asm_debug) %(asm_options) %|.s %A }}}}"
+#else
+ "%(trad_capable_cpp) -lang-asm %(cpp_options) -fno-directives-only\
+ %{E|M|MM:%(cpp_debug_options)}\
+ %{!M:%{!MM:%{!E:%{!S:-o %|.s |\n\
+ as %(asm_debug) %(asm_options) %m.s %A }}}}"
+#endif
+ , 0, 0, 0},
+
+#include "specs.h"
+ /* Mark end of table. */
+ {0, 0, 0, 0, 0}
+};
+
+/* Number of elements in default_compilers, not counting the terminator. */
+
+static const int n_default_compilers = ARRAY_SIZE (default_compilers) - 1;
+
+typedef char *char_p; /* For DEF_VEC_P. */
+
+/* A vector of options to give to the linker.
+ These options are accumulated by %x,
+ and substituted into the linker command with %X. */
+static vec<char_p> linker_options;
+
+/* A vector of options to give to the assembler.
+ These options are accumulated by -Wa,
+ and substituted into the assembler command with %Y. */
+static vec<char_p> assembler_options;
+
+/* A vector of options to give to the preprocessor.
+ These options are accumulated by -Wp,
+ and substituted into the preprocessor command with %Z. */
+static vec<char_p> preprocessor_options;
+
+static char *
+skip_whitespace (char *p)
+{
+ while (1)
+ {
+ /* A fully-blank line is a delimiter in the SPEC file and shouldn't
+ be considered whitespace. */
+ if (p[0] == '\n' && p[1] == '\n' && p[2] == '\n')
+ return p + 1;
+ else if (*p == '\n' || *p == ' ' || *p == '\t')
+ p++;
+ else if (*p == '#')
+ {
+ while (*p != '\n')
+ p++;
+ p++;
+ }
+ else
+ break;
+ }
+
+ return p;
+}
+/* Structures to keep track of prefixes to try when looking for files. */
+
+struct prefix_list
+{
+ const char *prefix; /* String to prepend to the path. */
+ struct prefix_list *next; /* Next in linked list. */
+ int require_machine_suffix; /* Don't use without machine_suffix. */
+ /* 2 means try both machine_suffix and just_machine_suffix. */
+ int priority; /* Sort key - priority within list. */
+ int os_multilib; /* 1 if OS multilib scheme should be used,
+ 0 for GCC multilib scheme. */
+};
+
+struct path_prefix
+{
+ struct prefix_list *plist; /* List of prefixes to try */
+ int max_len; /* Max length of a prefix in PLIST */
+ const char *name; /* Name of this list (used in config stuff) */
+};
+
+/* List of prefixes to try when looking for executables. */
+
+static struct path_prefix exec_prefixes = { 0, 0, "exec" };
+
+/* List of prefixes to try when looking for startup (crt0) files. */
+
+static struct path_prefix startfile_prefixes = { 0, 0, "startfile" };
+
+/* List of prefixes to try when looking for include files. */
+
+static struct path_prefix include_prefixes = { 0, 0, "include" };
+
+/* Suffix to attach to directories searched for commands.
+ This looks like `MACHINE/VERSION/'. */
+
+static const char *machine_suffix = 0;
+
+/* Suffix to attach to directories searched for commands.
+ This is just `MACHINE/'. */
+
+static const char *just_machine_suffix = 0;
+
+/* Adjusted value of GCC_EXEC_PREFIX envvar. */
+
+static const char *gcc_exec_prefix;
+
+/* Adjusted value of standard_libexec_prefix. */
+
+static const char *gcc_libexec_prefix;
+
+/* Default prefixes to attach to command names. */
+
+#ifndef STANDARD_STARTFILE_PREFIX_1
+#define STANDARD_STARTFILE_PREFIX_1 "/lib/"
+#endif
+#ifndef STANDARD_STARTFILE_PREFIX_2
+#define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
+#endif
+
+#ifdef CROSS_DIRECTORY_STRUCTURE /* Don't use these prefixes for a cross compiler. */
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+#undef MD_STARTFILE_PREFIX_1
+#endif
+
+/* If no prefixes defined, use the null string, which will disable them. */
+#ifndef MD_EXEC_PREFIX
+#define MD_EXEC_PREFIX ""
+#endif
+#ifndef MD_STARTFILE_PREFIX
+#define MD_STARTFILE_PREFIX ""
+#endif
+#ifndef MD_STARTFILE_PREFIX_1
+#define MD_STARTFILE_PREFIX_1 ""
+#endif
+
+/* These directories are locations set at configure-time based on the
+ --prefix option provided to configure. Their initializers are
+ defined in Makefile.in. These paths are not *directly* used when
+ gcc_exec_prefix is set because, in that case, we know where the
+ compiler has been installed, and use paths relative to that
+ location instead. */
+static const char *const standard_exec_prefix = STANDARD_EXEC_PREFIX;
+static const char *const standard_libexec_prefix = STANDARD_LIBEXEC_PREFIX;
+static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
+static const char *const standard_startfile_prefix = STANDARD_STARTFILE_PREFIX;
+
+/* For native compilers, these are well-known paths containing
+ components that may be provided by the system. For cross
+ compilers, these paths are not used. */
+static const char *md_exec_prefix = MD_EXEC_PREFIX;
+static const char *md_startfile_prefix = MD_STARTFILE_PREFIX;
+static const char *md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1;
+static const char *const standard_startfile_prefix_1
+ = STANDARD_STARTFILE_PREFIX_1;
+static const char *const standard_startfile_prefix_2
+ = STANDARD_STARTFILE_PREFIX_2;
+
+/* A relative path to be used in finding the location of tools
+ relative to the driver. */
+static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+
+/* A prefix to be used when this is an accelerator compiler. */
+static const char *const accel_dir_suffix = ACCEL_DIR_SUFFIX;
+
+/* Subdirectory to use for locating libraries. Set by
+ set_multilib_dir based on the compilation options. */
+
+static const char *multilib_dir;
+
+/* Subdirectory to use for locating libraries in OS conventions. Set by
+ set_multilib_dir based on the compilation options. */
+
+static const char *multilib_os_dir;
+
+/* Subdirectory to use for locating libraries in multiarch conventions. Set by
+ set_multilib_dir based on the compilation options. */
+
+static const char *multiarch_dir;
+
+/* Structure to keep track of the specs that have been defined so far.
+ These are accessed using %(specname) in a compiler or link
+ spec. */
+
+struct spec_list
+{
+ /* The following 2 fields must be first */
+ /* to allow EXTRA_SPECS to be initialized */
+ const char *name; /* name of the spec. */
+ const char *ptr; /* available ptr if no static pointer */
+
+ /* The following fields are not initialized */
+ /* by EXTRA_SPECS */
+ const char **ptr_spec; /* pointer to the spec itself. */
+ struct spec_list *next; /* Next spec in linked list. */
+ int name_len; /* length of the name */
+ bool user_p; /* whether string come from file spec. */
+ bool alloc_p; /* whether string was allocated */
+ const char *default_ptr; /* The default value of *ptr_spec. */
+};
+
+#define INIT_STATIC_SPEC(NAME,PTR) \
+ { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false, \
+ *PTR }
+
+/* List of statically defined specs. */
+static struct spec_list static_specs[] =
+{
+ INIT_STATIC_SPEC ("asm", &asm_spec),
+ INIT_STATIC_SPEC ("asm_debug", &asm_debug),
+ INIT_STATIC_SPEC ("asm_debug_option", &asm_debug_option),
+ INIT_STATIC_SPEC ("asm_final", &asm_final_spec),
+ INIT_STATIC_SPEC ("asm_options", &asm_options),
+ INIT_STATIC_SPEC ("invoke_as", &invoke_as),
+ INIT_STATIC_SPEC ("cpp", &cpp_spec),
+ INIT_STATIC_SPEC ("cpp_options", &cpp_options),
+ INIT_STATIC_SPEC ("cpp_debug_options", &cpp_debug_options),
+ INIT_STATIC_SPEC ("cpp_unique_options", &cpp_unique_options),
+ INIT_STATIC_SPEC ("trad_capable_cpp", &trad_capable_cpp),
+ INIT_STATIC_SPEC ("cc1", &cc1_spec),
+ INIT_STATIC_SPEC ("cc1_options", &cc1_options),
+ INIT_STATIC_SPEC ("cc1plus", &cc1plus_spec),
+ INIT_STATIC_SPEC ("link_gcc_c_sequence", &link_gcc_c_sequence_spec),
+ INIT_STATIC_SPEC ("link_ssp", &link_ssp_spec),
+ INIT_STATIC_SPEC ("endfile", &endfile_spec),
+ INIT_STATIC_SPEC ("link", &link_spec),
+ INIT_STATIC_SPEC ("lib", &lib_spec),
+ INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec),
+ INIT_STATIC_SPEC ("libgcc", &libgcc_spec),
+ INIT_STATIC_SPEC ("startfile", &startfile_spec),
+ INIT_STATIC_SPEC ("cross_compile", &cross_compile),
+ INIT_STATIC_SPEC ("version", &compiler_version),
+ INIT_STATIC_SPEC ("multilib", &multilib_select),
+ INIT_STATIC_SPEC ("multilib_defaults", &multilib_defaults),
+ INIT_STATIC_SPEC ("multilib_extra", &multilib_extra),
+ INIT_STATIC_SPEC ("multilib_matches", &multilib_matches),
+ INIT_STATIC_SPEC ("multilib_exclusions", &multilib_exclusions),
+ INIT_STATIC_SPEC ("multilib_options", &multilib_options),
+ INIT_STATIC_SPEC ("multilib_reuse", &multilib_reuse),
+ INIT_STATIC_SPEC ("linker", &linker_name_spec),
+ INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec),
+ INIT_STATIC_SPEC ("lto_wrapper", &lto_wrapper_spec),
+ INIT_STATIC_SPEC ("lto_gcc", &lto_gcc_spec),
+ INIT_STATIC_SPEC ("post_link", &post_link_spec),
+ INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
+ INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
+ INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
+ INIT_STATIC_SPEC ("md_startfile_prefix_1", &md_startfile_prefix_1),
+ INIT_STATIC_SPEC ("startfile_prefix_spec", &startfile_prefix_spec),
+ INIT_STATIC_SPEC ("sysroot_spec", &sysroot_spec),
+ INIT_STATIC_SPEC ("sysroot_suffix_spec", &sysroot_suffix_spec),
+ INIT_STATIC_SPEC ("sysroot_hdrs_suffix_spec", &sysroot_hdrs_suffix_spec),
+ INIT_STATIC_SPEC ("self_spec", &self_spec),
+};
+
+#ifdef EXTRA_SPECS /* additional specs needed */
+/* Structure to keep track of just the first two args of a spec_list.
+ That is all that the EXTRA_SPECS macro gives us. */
+struct spec_list_1
+{
+ const char *const name;
+ const char *const ptr;
+};
+
+static const struct spec_list_1 extra_specs_1[] = { EXTRA_SPECS };
+static struct spec_list *extra_specs = (struct spec_list *) 0;
+#endif
+
+/* List of dynamically allocates specs that have been defined so far. */
+
+static struct spec_list *specs = (struct spec_list *) 0;
+
+/* List of static spec functions. */
+
+static const struct spec_function static_spec_functions[] =
+{
+ { "getenv", getenv_spec_function },
+ { "if-exists", if_exists_spec_function },
+ { "if-exists-else", if_exists_else_spec_function },
+ { "if-exists-then-else", if_exists_then_else_spec_function },
+ { "sanitize", sanitize_spec_function },
+ { "replace-outfile", replace_outfile_spec_function },
+ { "remove-outfile", remove_outfile_spec_function },
+ { "version-compare", version_compare_spec_function },
+ { "include", include_spec_function },
+ { "find-file", find_file_spec_function },
+ { "find-plugindir", find_plugindir_spec_function },
+ { "print-asm-header", print_asm_header_spec_function },
+ { "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
+ { "compare-debug-self-opt", compare_debug_self_opt_spec_function },
+ { "pass-through-libs", pass_through_libs_spec_func },
+ { "dumps", dumps_spec_func },
+ { "gt", greater_than_spec_func },
+ { "debug-level-gt", debug_level_greater_than_spec_func },
+ { "dwarf-version-gt", dwarf_version_greater_than_spec_func },
+ { "fortran-preinclude-file", find_fortran_preinclude_file},
+#ifdef EXTRA_SPEC_FUNCTIONS
+ EXTRA_SPEC_FUNCTIONS
+#endif
+ { 0, 0 }
+};
+
+static int processing_spec_function;
+
+/* Add appropriate libgcc specs to OBSTACK, taking into account
+ various permutations of -shared-libgcc, -shared, and such. */
+
+#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
+
+#ifndef USE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 0
+#endif
+
+static void
+init_gcc_specs (struct obstack *obstack, const char *shared_name,
+ const char *static_name, const char *eh_name)
+{
+ char *buf;
+
+#if USE_LD_AS_NEEDED
+ buf = concat ("%{static|static-libgcc|static-pie:", static_name, " ", eh_name, "}"
+ "%{!static:%{!static-libgcc:%{!static-pie:"
+ "%{!shared-libgcc:",
+ static_name, " " LD_AS_NEEDED_OPTION " ",
+ shared_name, " " LD_NO_AS_NEEDED_OPTION
+ "}"
+ "%{shared-libgcc:",
+ shared_name, "%{!shared: ", static_name, "}"
+ "}}"
+#else
+ buf = concat ("%{static|static-libgcc:", static_name, " ", eh_name, "}"
+ "%{!static:%{!static-libgcc:"
+ "%{!shared:"
+ "%{!shared-libgcc:", static_name, " ", eh_name, "}"
+ "%{shared-libgcc:", shared_name, " ", static_name, "}"
+ "}"
+#ifdef LINK_EH_SPEC
+ "%{shared:"
+ "%{shared-libgcc:", shared_name, "}"
+ "%{!shared-libgcc:", static_name, "}"
+ "}"
+#else
+ "%{shared:", shared_name, "}"
+#endif
+#endif
+ "}}", NULL);
+
+ obstack_grow (obstack, buf, strlen (buf));
+ free (buf);
+}
+#endif /* ENABLE_SHARED_LIBGCC */
+
+/* Initialize the specs lookup routines. */
+
+static void
+init_spec (void)
+{
+ struct spec_list *next = (struct spec_list *) 0;
+ struct spec_list *sl = (struct spec_list *) 0;
+ int i;
+
+ if (specs)
+ return; /* Already initialized. */
+
+ if (verbose_flag)
+ fnotice (stderr, "Using built-in specs.\n");
+
+#ifdef EXTRA_SPECS
+ extra_specs = XCNEWVEC (struct spec_list, ARRAY_SIZE (extra_specs_1));
+
+ for (i = ARRAY_SIZE (extra_specs_1) - 1; i >= 0; i--)
+ {
+ sl = &extra_specs[i];
+ sl->name = extra_specs_1[i].name;
+ sl->ptr = extra_specs_1[i].ptr;
+ sl->next = next;
+ sl->name_len = strlen (sl->name);
+ sl->ptr_spec = &sl->ptr;
+ gcc_assert (sl->ptr_spec != NULL);
+ sl->default_ptr = sl->ptr;
+ next = sl;
+ }
+#endif
+
+ for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
+ {
+ sl = &static_specs[i];
+ sl->next = next;
+ next = sl;
+ }
+
+#if defined(ENABLE_SHARED_LIBGCC) && !defined(REAL_LIBGCC_SPEC)
+ /* ??? If neither -shared-libgcc nor --static-libgcc was
+ seen, then we should be making an educated guess. Some proposed
+ heuristics for ELF include:
+
+ (1) If "-Wl,--export-dynamic", then it's a fair bet that the
+ program will be doing dynamic loading, which will likely
+ need the shared libgcc.
+
+ (2) If "-ldl", then it's also a fair bet that we're doing
+ dynamic loading.
+
+ (3) For each ET_DYN we're linking against (either through -lfoo
+ or /some/path/foo.so), check to see whether it or one of
+ its dependencies depends on a shared libgcc.
+
+ (4) If "-shared"
+
+ If the runtime is fixed to look for program headers instead
+ of calling __register_frame_info at all, for each object,
+ use the shared libgcc if any EH symbol referenced.
+
+ If crtstuff is fixed to not invoke __register_frame_info
+ automatically, for each object, use the shared libgcc if
+ any non-empty unwind section found.
+
+ Doing any of this probably requires invoking an external program to
+ do the actual object file scanning. */
+ {
+ const char *p = libgcc_spec;
+ int in_sep = 1;
+
+ /* Transform the extant libgcc_spec into one that uses the shared libgcc
+ when given the proper command line arguments. */
+ while (*p)
+ {
+ if (in_sep && *p == '-' && startswith (p, "-lgcc"))
+ {
+ init_gcc_specs (&obstack,
+ "-lgcc_s"
+#ifdef USE_LIBUNWIND_EXCEPTIONS
+ " -lunwind"
+#endif
+ ,
+ "-lgcc",
+ "-lgcc_eh"
+#ifdef USE_LIBUNWIND_EXCEPTIONS
+# ifdef HAVE_LD_STATIC_DYNAMIC
+ " %{!static:%{!static-pie:" LD_STATIC_OPTION "}} -lunwind"
+ " %{!static:%{!static-pie:" LD_DYNAMIC_OPTION "}}"
+# else
+ " -lunwind"
+# endif
+#endif
+ );
+
+ p += 5;
+ in_sep = 0;
+ }
+ else if (in_sep && *p == 'l' && startswith (p, "libgcc.a%s"))
+ {
+ /* Ug. We don't know shared library extensions. Hope that
+ systems that use this form don't do shared libraries. */
+ init_gcc_specs (&obstack,
+ "-lgcc_s",
+ "libgcc.a%s",
+ "libgcc_eh.a%s"
+#ifdef USE_LIBUNWIND_EXCEPTIONS
+ " -lunwind"
+#endif
+ );
+ p += 10;
+ in_sep = 0;
+ }
+ else
+ {
+ obstack_1grow (&obstack, *p);
+ in_sep = (*p == ' ');
+ p += 1;
+ }
+ }
+
+ obstack_1grow (&obstack, '\0');
+ libgcc_spec = XOBFINISH (&obstack, const char *);
+ }
+#endif
+#ifdef USE_AS_TRADITIONAL_FORMAT
+ /* Prepend "--traditional-format" to whatever asm_spec we had before. */
+ {
+ static const char tf[] = "--traditional-format ";
+ obstack_grow (&obstack, tf, sizeof (tf) - 1);
+ obstack_grow0 (&obstack, asm_spec, strlen (asm_spec));
+ asm_spec = XOBFINISH (&obstack, const char *);
+ }
+#endif
+
+#if defined LINK_EH_SPEC || defined LINK_BUILDID_SPEC || \
+ defined LINKER_HASH_STYLE
+# ifdef LINK_BUILDID_SPEC
+ /* Prepend LINK_BUILDID_SPEC to whatever link_spec we had before. */
+ obstack_grow (&obstack, LINK_BUILDID_SPEC, sizeof (LINK_BUILDID_SPEC) - 1);
+# endif
+# ifdef LINK_EH_SPEC
+ /* Prepend LINK_EH_SPEC to whatever link_spec we had before. */
+ obstack_grow (&obstack, LINK_EH_SPEC, sizeof (LINK_EH_SPEC) - 1);
+# endif
+# ifdef LINKER_HASH_STYLE
+ /* Prepend --hash-style=LINKER_HASH_STYLE to whatever link_spec we had
+ before. */
+ {
+ static const char hash_style[] = "--hash-style=";
+ obstack_grow (&obstack, hash_style, sizeof (hash_style) - 1);
+ obstack_grow (&obstack, LINKER_HASH_STYLE, sizeof (LINKER_HASH_STYLE) - 1);
+ obstack_1grow (&obstack, ' ');
+ }
+# endif
+ obstack_grow0 (&obstack, link_spec, strlen (link_spec));
+ link_spec = XOBFINISH (&obstack, const char *);
+#endif
+
+ specs = sl;
+}
+
+/* Update the entry for SPEC in the static_specs table to point to VALUE,
+ ensuring that we free the previous value if necessary. Set alloc_p for the
+ entry to ALLOC_P: this determines whether we take ownership of VALUE (i.e.
+ whether we need to free it later on). */
+static void
+set_static_spec (const char **spec, const char *value, bool alloc_p)
+{
+ struct spec_list *sl = NULL;
+
+ for (unsigned i = 0; i < ARRAY_SIZE (static_specs); i++)
+ {
+ if (static_specs[i].ptr_spec == spec)
+ {
+ sl = static_specs + i;
+ break;
+ }
+ }
+
+ gcc_assert (sl);
+
+ if (sl->alloc_p)
+ {
+ const char *old = *spec;
+ free (const_cast <char *> (old));
+ }
+
+ *spec = value;
+ sl->alloc_p = alloc_p;
+}
+
+/* Update a static spec to a new string, taking ownership of that
+ string's memory. */
+static void set_static_spec_owned (const char **spec, const char *val)
+{
+ return set_static_spec (spec, val, true);
+}
+
+/* Update a static spec to point to a new value, but don't take
+ ownership of (i.e. don't free) that string. */
+static void set_static_spec_shared (const char **spec, const char *val)
+{
+ return set_static_spec (spec, val, false);
+}
+
+
+/* Change the value of spec NAME to SPEC. If SPEC is empty, then the spec is
+ removed; If the spec starts with a + then SPEC is added to the end of the
+ current spec. */
+
+static void
+set_spec (const char *name, const char *spec, bool user_p)
+{
+ struct spec_list *sl;
+ const char *old_spec;
+ int name_len = strlen (name);
+ int i;
+
+ /* If this is the first call, initialize the statically allocated specs. */
+ if (!specs)
+ {
+ struct spec_list *next = (struct spec_list *) 0;
+ for (i = ARRAY_SIZE (static_specs) - 1; i >= 0; i--)
+ {
+ sl = &static_specs[i];
+ sl->next = next;
+ next = sl;
+ }
+ specs = sl;
+ }
+
+ /* See if the spec already exists. */
+ for (sl = specs; sl; sl = sl->next)
+ if (name_len == sl->name_len && !strcmp (sl->name, name))
+ break;
+
+ if (!sl)
+ {
+ /* Not found - make it. */
+ sl = XNEW (struct spec_list);
+ sl->name = xstrdup (name);
+ sl->name_len = name_len;
+ sl->ptr_spec = &sl->ptr;
+ sl->alloc_p = 0;
+ *(sl->ptr_spec) = "";
+ sl->next = specs;
+ sl->default_ptr = NULL;
+ specs = sl;
+ }
+
+ old_spec = *(sl->ptr_spec);
+ *(sl->ptr_spec) = ((spec[0] == '+' && ISSPACE ((unsigned char)spec[1]))
+ ? concat (old_spec, spec + 1, NULL)
+ : xstrdup (spec));
+
+#ifdef DEBUG_SPECS
+ if (verbose_flag)
+ fnotice (stderr, "Setting spec %s to '%s'\n\n", name, *(sl->ptr_spec));
+#endif
+
+ /* Free the old spec. */
+ if (old_spec && sl->alloc_p)
+ free (CONST_CAST (char *, old_spec));
+
+ sl->user_p = user_p;
+ sl->alloc_p = true;
+}
+
+/* Accumulate a command (program name and args), and run it. */
+
+typedef const char *const_char_p; /* For DEF_VEC_P. */
+
+/* Vector of pointers to arguments in the current line of specifications. */
+static vec<const_char_p> argbuf;
+
+/* Likewise, but for the current @file. */
+static vec<const_char_p> at_file_argbuf;
+
+/* Whether an @file is currently open. */
+static bool in_at_file = false;
+
+/* Were the options -c, -S or -E passed. */
+static int have_c = 0;
+
+/* Was the option -o passed. */
+static int have_o = 0;
+
+/* Was the option -E passed. */
+static int have_E = 0;
+
+/* Pointer to output file name passed in with -o. */
+static const char *output_file = 0;
+
+/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
+ temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for
+ it here. */
+
+static struct temp_name {
+ const char *suffix; /* suffix associated with the code. */
+ int length; /* strlen (suffix). */
+ int unique; /* Indicates whether %g or %u/%U was used. */
+ const char *filename; /* associated filename. */
+ int filename_length; /* strlen (filename). */
+ struct temp_name *next;
+} *temp_names;
+
+/* Number of commands executed so far. */
+
+static int execution_count;
+
+/* Number of commands that exited with a signal. */
+
+static int signal_count;
+
+/* Allocate the argument vector. */
+
+static void
+alloc_args (void)
+{
+ argbuf.create (10);
+ at_file_argbuf.create (10);
+}
+
+/* Clear out the vector of arguments (after a command is executed). */
+
+static void
+clear_args (void)
+{
+ argbuf.truncate (0);
+ at_file_argbuf.truncate (0);
+}
+
+/* Add one argument to the vector at the end.
+ This is done when a space is seen or at the end of the line.
+ If DELETE_ALWAYS is nonzero, the arg is a filename
+ and the file should be deleted eventually.
+ If DELETE_FAILURE is nonzero, the arg is a filename
+ and the file should be deleted if this compilation fails. */
+
+static void
+store_arg (const char *arg, int delete_always, int delete_failure)
+{
+ if (in_at_file)
+ at_file_argbuf.safe_push (arg);
+ else
+ argbuf.safe_push (arg);
+
+ if (delete_always || delete_failure)
+ {
+ const char *p;
+ /* If the temporary file we should delete is specified as
+ part of a joined argument extract the filename. */
+ if (arg[0] == '-'
+ && (p = strrchr (arg, '=')))
+ arg = p + 1;
+ record_temp_file (arg, delete_always, delete_failure);
+ }
+}
+
+/* Open a temporary @file into which subsequent arguments will be stored. */
+
+static void
+open_at_file (void)
+{
+ if (in_at_file)
+ fatal_error (input_location, "cannot open nested response file");
+ else
+ in_at_file = true;
+}
+
+/* Create a temporary @file name. */
+
+static char *make_at_file (void)
+{
+ static int fileno = 0;
+ char filename[20];
+ const char *base, *ext;
+
+ if (!save_temps_flag)
+ return make_temp_file ("");
+
+ base = dumpbase;
+ if (!(base && *base))
+ base = dumpdir;
+ if (!(base && *base))
+ base = "a";
+
+ sprintf (filename, ".args.%d", fileno++);
+ ext = filename;
+
+ if (base == dumpdir && dumpdir_trailing_dash_added)
+ ext++;
+
+ return concat (base, ext, NULL);
+}
+
+/* Close the temporary @file and add @file to the argument list. */
+
+static void
+close_at_file (void)
+{
+ if (!in_at_file)
+ fatal_error (input_location, "cannot close nonexistent response file");
+
+ in_at_file = false;
+
+ const unsigned int n_args = at_file_argbuf.length ();
+ if (n_args == 0)
+ return;
+
+ char **argv = XALLOCAVEC (char *, n_args + 1);
+ char *temp_file = make_at_file ();
+ char *at_argument = concat ("@", temp_file, NULL);
+ FILE *f = fopen (temp_file, "w");
+ int status;
+ unsigned int i;
+
+ /* Copy the strings over. */
+ for (i = 0; i < n_args; i++)
+ argv[i] = CONST_CAST (char *, at_file_argbuf[i]);
+ argv[i] = NULL;
+
+ at_file_argbuf.truncate (0);
+
+ if (f == NULL)
+ fatal_error (input_location, "could not open temporary response file %s",
+ temp_file);
+
+ status = writeargv (argv, f);
+
+ if (status)
+ fatal_error (input_location,
+ "could not write to temporary response file %s",
+ temp_file);
+
+ status = fclose (f);
+
+ if (status == EOF)
+ fatal_error (input_location, "could not close temporary response file %s",
+ temp_file);
+
+ store_arg (at_argument, 0, 0);
+
+ record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
+}
+
+/* Load specs from a file name named FILENAME, replacing occurrences of
+ various different types of line-endings, \r\n, \n\r and just \r, with
+ a single \n. */
+
+static char *
+load_specs (const char *filename)
+{
+ int desc;
+ int readlen;
+ struct stat statbuf;
+ char *buffer;
+ char *buffer_p;
+ char *specs;
+ char *specs_p;
+
+ if (verbose_flag)
+ fnotice (stderr, "Reading specs from %s\n", filename);
+
+ /* Open and stat the file. */
+ desc = open (filename, O_RDONLY, 0);
+ if (desc < 0)
+ {
+ failed:
+ /* This leaves DESC open, but the OS will save us. */
+ fatal_error (input_location, "cannot read spec file %qs: %m", filename);
+ }
+
+ if (stat (filename, &statbuf) < 0)
+ goto failed;
+
+ /* Read contents of file into BUFFER. */
+ buffer = XNEWVEC (char, statbuf.st_size + 1);
+ readlen = read (desc, buffer, (unsigned) statbuf.st_size);
+ if (readlen < 0)
+ goto failed;
+ buffer[readlen] = 0;
+ close (desc);
+
+ specs = XNEWVEC (char, readlen + 1);
+ specs_p = specs;
+ for (buffer_p = buffer; buffer_p && *buffer_p; buffer_p++)
+ {
+ int skip = 0;
+ char c = *buffer_p;
+ if (c == '\r')
+ {
+ if (buffer_p > buffer && *(buffer_p - 1) == '\n') /* \n\r */
+ skip = 1;
+ else if (*(buffer_p + 1) == '\n') /* \r\n */
+ skip = 1;
+ else /* \r */
+ c = '\n';
+ }
+ if (! skip)
+ *specs_p++ = c;
+ }
+ *specs_p = '\0';
+
+ free (buffer);
+ return (specs);
+}
+
+/* Read compilation specs from a file named FILENAME,
+ replacing the default ones.
+
+ A suffix which starts with `*' is a definition for
+ one of the machine-specific sub-specs. The "suffix" should be
+ *asm, *cc1, *cpp, *link, *startfile, etc.
+ The corresponding spec is stored in asm_spec, etc.,
+ rather than in the `compilers' vector.
+
+ Anything invalid in the file is a fatal error. */
+
+static void
+read_specs (const char *filename, bool main_p, bool user_p)
+{
+ char *buffer;
+ char *p;
+
+ buffer = load_specs (filename);
+
+ /* Scan BUFFER for specs, putting them in the vector. */
+ p = buffer;
+ while (1)
+ {
+ char *suffix;
+ char *spec;
+ char *in, *out, *p1, *p2, *p3;
+
+ /* Advance P in BUFFER to the next nonblank nocomment line. */
+ p = skip_whitespace (p);
+ if (*p == 0)
+ break;
+
+ /* Is this a special command that starts with '%'? */
+ /* Don't allow this for the main specs file, since it would
+ encourage people to overwrite it. */
+ if (*p == '%' && !main_p)
+ {
+ p1 = p;
+ while (*p && *p != '\n')
+ p++;
+
+ /* Skip '\n'. */
+ p++;
+
+ if (startswith (p1, "%include")
+ && (p1[sizeof "%include" - 1] == ' '
+ || p1[sizeof "%include" - 1] == '\t'))
+ {
+ char *new_filename;
+
+ p1 += sizeof ("%include");
+ while (*p1 == ' ' || *p1 == '\t')
+ p1++;
+
+ if (*p1++ != '<' || p[-2] != '>')
+ fatal_error (input_location,
+ "specs %%include syntax malformed after "
+ "%ld characters",
+ (long) (p1 - buffer + 1));
+
+ p[-2] = '\0';
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
+ read_specs (new_filename ? new_filename : p1, false, user_p);
+ continue;
+ }
+ else if (startswith (p1, "%include_noerr")
+ && (p1[sizeof "%include_noerr" - 1] == ' '
+ || p1[sizeof "%include_noerr" - 1] == '\t'))
+ {
+ char *new_filename;
+
+ p1 += sizeof "%include_noerr";
+ while (*p1 == ' ' || *p1 == '\t')
+ p1++;
+
+ if (*p1++ != '<' || p[-2] != '>')
+ fatal_error (input_location,
+ "specs %%include syntax malformed after "
+ "%ld characters",
+ (long) (p1 - buffer + 1));
+
+ p[-2] = '\0';
+ new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
+ if (new_filename)
+ read_specs (new_filename, false, user_p);
+ else if (verbose_flag)
+ fnotice (stderr, "could not find specs file %s\n", p1);
+ continue;
+ }
+ else if (startswith (p1, "%rename")
+ && (p1[sizeof "%rename" - 1] == ' '
+ || p1[sizeof "%rename" - 1] == '\t'))
+ {
+ int name_len;
+ struct spec_list *sl;
+ struct spec_list *newsl;
+
+ /* Get original name. */
+ p1 += sizeof "%rename";
+ while (*p1 == ' ' || *p1 == '\t')
+ p1++;
+
+ if (! ISALPHA ((unsigned char) *p1))
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p1 - buffer));
+
+ p2 = p1;
+ while (*p2 && !ISSPACE ((unsigned char) *p2))
+ p2++;
+
+ if (*p2 != ' ' && *p2 != '\t')
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p2 - buffer));
+
+ name_len = p2 - p1;
+ *p2++ = '\0';
+ while (*p2 == ' ' || *p2 == '\t')
+ p2++;
+
+ if (! ISALPHA ((unsigned char) *p2))
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p2 - buffer));
+
+ /* Get new spec name. */
+ p3 = p2;
+ while (*p3 && !ISSPACE ((unsigned char) *p3))
+ p3++;
+
+ if (p3 != p - 1)
+ fatal_error (input_location,
+ "specs %%rename syntax malformed after "
+ "%ld characters",
+ (long) (p3 - buffer));
+ *p3 = '\0';
+
+ for (sl = specs; sl; sl = sl->next)
+ if (name_len == sl->name_len && !strcmp (sl->name, p1))
+ break;
+
+ if (!sl)
+ fatal_error (input_location,
+ "specs %s spec was not found to be renamed", p1);
+
+ if (strcmp (p1, p2) == 0)
+ continue;
+
+ for (newsl = specs; newsl; newsl = newsl->next)
+ if (strcmp (newsl->name, p2) == 0)
+ fatal_error (input_location,
+ "%s: attempt to rename spec %qs to "
+ "already defined spec %qs",
+ filename, p1, p2);
+
+ if (verbose_flag)
+ {
+ fnotice (stderr, "rename spec %s to %s\n", p1, p2);
+#ifdef DEBUG_SPECS
+ fnotice (stderr, "spec is '%s'\n\n", *(sl->ptr_spec));
+#endif
+ }
+
+ set_spec (p2, *(sl->ptr_spec), user_p);
+ if (sl->alloc_p)
+ free (CONST_CAST (char *, *(sl->ptr_spec)));
+
+ *(sl->ptr_spec) = "";
+ sl->alloc_p = 0;
+ continue;
+ }
+ else
+ fatal_error (input_location,
+ "specs unknown %% command after %ld characters",
+ (long) (p1 - buffer));
+ }
+
+ /* Find the colon that should end the suffix. */
+ p1 = p;
+ while (*p1 && *p1 != ':' && *p1 != '\n')
+ p1++;
+
+ /* The colon shouldn't be missing. */
+ if (*p1 != ':')
+ fatal_error (input_location,
+ "specs file malformed after %ld characters",
+ (long) (p1 - buffer));
+
+ /* Skip back over trailing whitespace. */
+ p2 = p1;
+ while (p2 > buffer && (p2[-1] == ' ' || p2[-1] == '\t'))
+ p2--;
+
+ /* Copy the suffix to a string. */
+ suffix = save_string (p, p2 - p);
+ /* Find the next line. */
+ p = skip_whitespace (p1 + 1);
+ if (p[1] == 0)
+ fatal_error (input_location,
+ "specs file malformed after %ld characters",
+ (long) (p - buffer));
+
+ p1 = p;
+ /* Find next blank line or end of string. */
+ while (*p1 && !(*p1 == '\n' && (p1[1] == '\n' || p1[1] == '\0')))
+ p1++;
+
+ /* Specs end at the blank line and do not include the newline. */
+ spec = save_string (p, p1 - p);
+ p = p1;
+
+ /* Delete backslash-newline sequences from the spec. */
+ in = spec;
+ out = spec;
+ while (*in != 0)
+ {
+ if (in[0] == '\\' && in[1] == '\n')
+ in += 2;
+ else if (in[0] == '#')
+ while (*in && *in != '\n')
+ in++;
+
+ else
+ *out++ = *in++;
+ }
+ *out = 0;
+
+ if (suffix[0] == '*')
+ {
+ if (! strcmp (suffix, "*link_command"))
+ link_command_spec = spec;
+ else
+ {
+ set_spec (suffix + 1, spec, user_p);
+ free (spec);
+ }
+ }
+ else
+ {
+ /* Add this pair to the vector. */
+ compilers
+ = XRESIZEVEC (struct compiler, compilers, n_compilers + 2);
+
+ compilers[n_compilers].suffix = suffix;
+ compilers[n_compilers].spec = spec;
+ n_compilers++;
+ memset (&compilers[n_compilers], 0, sizeof compilers[n_compilers]);
+ }
+
+ if (*suffix == 0)
+ link_command_spec = spec;
+ }
+
+ if (link_command_spec == 0)
+ fatal_error (input_location, "spec file has no spec for linking");
+
+ XDELETEVEC (buffer);
+}
+
+/* Record the names of temporary files we tell compilers to write,
+ and delete them at the end of the run. */
+
+/* This is the common prefix we use to make temp file names.
+ It is chosen once for each run of this program.
+ It is substituted into a spec by %g or %j.
+ Thus, all temp file names contain this prefix.
+ In practice, all temp file names start with this prefix.
+
+ This prefix comes from the envvar TMPDIR if it is defined;
+ otherwise, from the P_tmpdir macro if that is defined;
+ otherwise, in /usr/tmp or /tmp;
+ or finally the current directory if all else fails. */
+
+static const char *temp_filename;
+
+/* Length of the prefix. */
+
+static int temp_filename_length;
+
+/* Define the list of temporary files to delete. */
+
+struct temp_file
+{
+ const char *name;
+ struct temp_file *next;
+};
+
+/* Queue of files to delete on success or failure of compilation. */
+static struct temp_file *always_delete_queue;
+/* Queue of files to delete on failure of compilation. */
+static struct temp_file *failure_delete_queue;
+
+/* Record FILENAME as a file to be deleted automatically.
+ ALWAYS_DELETE nonzero means delete it if all compilation succeeds;
+ otherwise delete it in any case.
+ FAIL_DELETE nonzero means delete it if a compilation step fails;
+ otherwise delete it in any case. */
+
+void
+record_temp_file (const char *filename, int always_delete, int fail_delete)
+{
+ char *const name = xstrdup (filename);
+
+ if (always_delete)
+ {
+ struct temp_file *temp;
+ for (temp = always_delete_queue; temp; temp = temp->next)
+ if (! filename_cmp (name, temp->name))
+ {
+ free (name);
+ goto already1;
+ }
+
+ temp = XNEW (struct temp_file);
+ temp->next = always_delete_queue;
+ temp->name = name;
+ always_delete_queue = temp;
+
+ already1:;
+ }
+
+ if (fail_delete)
+ {
+ struct temp_file *temp;
+ for (temp = failure_delete_queue; temp; temp = temp->next)
+ if (! filename_cmp (name, temp->name))
+ {
+ free (name);
+ goto already2;
+ }
+
+ temp = XNEW (struct temp_file);
+ temp->next = failure_delete_queue;
+ temp->name = name;
+ failure_delete_queue = temp;
+
+ already2:;
+ }
+}
+
+/* Delete all the temporary files whose names we previously recorded. */
+
+#ifndef DELETE_IF_ORDINARY
+#define DELETE_IF_ORDINARY(NAME,ST,VERBOSE_FLAG) \
+do \
+ { \
+ if (stat (NAME, &ST) >= 0 && S_ISREG (ST.st_mode)) \
+ if (unlink (NAME) < 0) \
+ if (VERBOSE_FLAG) \
+ error ("%s: %m", (NAME)); \
+ } while (0)
+#endif
+
+static void
+delete_if_ordinary (const char *name)
+{
+ struct stat st;
+#ifdef DEBUG
+ int i, c;
+
+ printf ("Delete %s? (y or n) ", name);
+ fflush (stdout);
+ i = getchar ();
+ if (i != '\n')
+ while ((c = getchar ()) != '\n' && c != EOF)
+ ;
+
+ if (i == 'y' || i == 'Y')
+#endif /* DEBUG */
+ DELETE_IF_ORDINARY (name, st, verbose_flag);
+}
+
+static void
+delete_temp_files (void)
+{
+ struct temp_file *temp;
+
+ for (temp = always_delete_queue; temp; temp = temp->next)
+ delete_if_ordinary (temp->name);
+ always_delete_queue = 0;
+}
+
+/* Delete all the files to be deleted on error. */
+
+static void
+delete_failure_queue (void)
+{
+ struct temp_file *temp;
+
+ for (temp = failure_delete_queue; temp; temp = temp->next)
+ delete_if_ordinary (temp->name);
+}
+
+static void
+clear_failure_queue (void)
+{
+ failure_delete_queue = 0;
+}
+
+/* Call CALLBACK for each path in PATHS, breaking out early if CALLBACK
+ returns non-NULL.
+ If DO_MULTI is true iterate over the paths twice, first with multilib
+ suffix then without, otherwise iterate over the paths once without
+ adding a multilib suffix. When DO_MULTI is true, some attempt is made
+ to avoid visiting the same path twice, but we could do better. For
+ instance, /usr/lib/../lib is considered different from /usr/lib.
+ At least EXTRA_SPACE chars past the end of the path passed to
+ CALLBACK are available for use by the callback.
+ CALLBACK_INFO allows extra parameters to be passed to CALLBACK.
+
+ Returns the value returned by CALLBACK. */
+
+static void *
+for_each_path (const struct path_prefix *paths,
+ bool do_multi,
+ size_t extra_space,
+ void *(*callback) (char *, void *),
+ void *callback_info)
+{
+ struct prefix_list *pl;
+ const char *multi_dir = NULL;
+ const char *multi_os_dir = NULL;
+ const char *multiarch_suffix = NULL;
+ const char *multi_suffix;
+ const char *just_multi_suffix;
+ char *path = NULL;
+ void *ret = NULL;
+ bool skip_multi_dir = false;
+ bool skip_multi_os_dir = false;
+
+ multi_suffix = machine_suffix;
+ just_multi_suffix = just_machine_suffix;
+ if (do_multi && multilib_dir && strcmp (multilib_dir, ".") != 0)
+ {
+ multi_dir = concat (multilib_dir, dir_separator_str, NULL);
+ multi_suffix = concat (multi_suffix, multi_dir, NULL);
+ just_multi_suffix = concat (just_multi_suffix, multi_dir, NULL);
+ }
+ if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
+ multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+ if (multiarch_dir)
+ multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
+
+ while (1)
+ {
+ size_t multi_dir_len = 0;
+ size_t multi_os_dir_len = 0;
+ size_t multiarch_len = 0;
+ size_t suffix_len;
+ size_t just_suffix_len;
+ size_t len;
+
+ if (multi_dir)
+ multi_dir_len = strlen (multi_dir);
+ if (multi_os_dir)
+ multi_os_dir_len = strlen (multi_os_dir);
+ if (multiarch_suffix)
+ multiarch_len = strlen (multiarch_suffix);
+ suffix_len = strlen (multi_suffix);
+ just_suffix_len = strlen (just_multi_suffix);
+
+ if (path == NULL)
+ {
+ len = paths->max_len + extra_space + 1;
+ len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
+ path = XNEWVEC (char, len);
+ }
+
+ for (pl = paths->plist; pl != 0; pl = pl->next)
+ {
+ len = strlen (pl->prefix);
+ memcpy (path, pl->prefix, len);
+
+ /* Look first in MACHINE/VERSION subdirectory. */
+ if (!skip_multi_dir)
+ {
+ memcpy (path + len, multi_suffix, suffix_len + 1);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+
+ /* Some paths are tried with just the machine (ie. target)
+ subdir. This is used for finding as, ld, etc. */
+ if (!skip_multi_dir
+ && pl->require_machine_suffix == 2)
+ {
+ memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+
+ /* Now try the multiarch path. */
+ if (!skip_multi_dir
+ && !pl->require_machine_suffix && multiarch_dir)
+ {
+ memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+
+ /* Now try the base path. */
+ if (!pl->require_machine_suffix
+ && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
+ {
+ const char *this_multi;
+ size_t this_multi_len;
+
+ if (pl->os_multilib)
+ {
+ this_multi = multi_os_dir;
+ this_multi_len = multi_os_dir_len;
+ }
+ else
+ {
+ this_multi = multi_dir;
+ this_multi_len = multi_dir_len;
+ }
+
+ if (this_multi_len)
+ memcpy (path + len, this_multi, this_multi_len + 1);
+ else
+ path[len] = '\0';
+
+ ret = callback (path, callback_info);
+ if (ret)
+ break;
+ }
+ }
+ if (pl)
+ break;
+
+ if (multi_dir == NULL && multi_os_dir == NULL)
+ break;
+
+ /* Run through the paths again, this time without multilibs.
+ Don't repeat any we have already seen. */
+ if (multi_dir)
+ {
+ free (CONST_CAST (char *, multi_dir));
+ multi_dir = NULL;
+ free (CONST_CAST (char *, multi_suffix));
+ multi_suffix = machine_suffix;
+ free (CONST_CAST (char *, just_multi_suffix));
+ just_multi_suffix = just_machine_suffix;
+ }
+ else
+ skip_multi_dir = true;
+ if (multi_os_dir)
+ {
+ free (CONST_CAST (char *, multi_os_dir));
+ multi_os_dir = NULL;
+ }
+ else
+ skip_multi_os_dir = true;
+ }
+
+ if (multi_dir)
+ {
+ free (CONST_CAST (char *, multi_dir));
+ free (CONST_CAST (char *, multi_suffix));
+ free (CONST_CAST (char *, just_multi_suffix));
+ }
+ if (multi_os_dir)
+ free (CONST_CAST (char *, multi_os_dir));
+ if (ret != path)
+ free (path);
+ return ret;
+}
+
+/* Callback for build_search_list. Adds path to obstack being built. */
+
+struct add_to_obstack_info {
+ struct obstack *ob;
+ bool check_dir;
+ bool first_time;
+};
+
+static void *
+add_to_obstack (char *path, void *data)
+{
+ struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
+
+ if (info->check_dir && !is_directory (path, false))
+ return NULL;
+
+ if (!info->first_time)
+ obstack_1grow (info->ob, PATH_SEPARATOR);
+
+ obstack_grow (info->ob, path, strlen (path));
+
+ info->first_time = false;
+ return NULL;
+}
+
+/* Add or change the value of an environment variable, outputting the
+ change to standard error if in verbose mode. */
+static void
+xputenv (const char *string)
+{
+ env.xput (string);
+}
+
+/* Build a list of search directories from PATHS.
+ PREFIX is a string to prepend to the list.
+ If CHECK_DIR_P is true we ensure the directory exists.
+ If DO_MULTI is true, multilib paths are output first, then
+ non-multilib paths.
+ This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
+ It is also used by the --print-search-dirs flag. */
+
+static char *
+build_search_list (const struct path_prefix *paths, const char *prefix,
+ bool check_dir, bool do_multi)
+{
+ struct add_to_obstack_info info;
+
+ info.ob = &collect_obstack;
+ info.check_dir = check_dir;
+ info.first_time = true;
+
+ obstack_grow (&collect_obstack, prefix, strlen (prefix));
+ obstack_1grow (&collect_obstack, '=');
+
+ for_each_path (paths, do_multi, 0, add_to_obstack, &info);
+
+ obstack_1grow (&collect_obstack, '\0');
+ return XOBFINISH (&collect_obstack, char *);
+}
+
+/* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
+ for collect. */
+
+static void
+putenv_from_prefixes (const struct path_prefix *paths, const char *env_var,
+ bool do_multi)
+{
+ xputenv (build_search_list (paths, env_var, true, do_multi));
+}
+
+/* Check whether NAME can be accessed in MODE. This is like access,
+ except that it never considers directories to be executable. */
+
+static int
+access_check (const char *name, int mode)
+{
+ if (mode == X_OK)
+ {
+ struct stat st;
+
+ if (stat (name, &st) < 0
+ || S_ISDIR (st.st_mode))
+ return -1;
+ }
+
+ return access (name, mode);
+}
+
+/* Callback for find_a_file. Appends the file name to the directory
+ path. If the resulting file exists in the right mode, return the
+ full pathname to the file. */
+
+struct file_at_path_info {
+ const char *name;
+ const char *suffix;
+ int name_len;
+ int suffix_len;
+ int mode;
+};
+
+static void *
+file_at_path (char *path, void *data)
+{
+ struct file_at_path_info *info = (struct file_at_path_info *) data;
+ size_t len = strlen (path);
+
+ memcpy (path + len, info->name, info->name_len);
+ len += info->name_len;
+
+ /* Some systems have a suffix for executable files.
+ So try appending that first. */
+ if (info->suffix_len)
+ {
+ memcpy (path + len, info->suffix, info->suffix_len + 1);
+ if (access_check (path, info->mode) == 0)
+ return path;
+ }
+
+ path[len] = '\0';
+ if (access_check (path, info->mode) == 0)
+ return path;
+
+ return NULL;
+}
+
+/* Search for NAME using the prefix list PREFIXES. MODE is passed to
+ access to check permissions. If DO_MULTI is true, search multilib
+ paths then non-multilib paths, otherwise do not search multilib paths.
+ Return 0 if not found, otherwise return its name, allocated with malloc. */
+
+static char *
+find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
+ bool do_multi)
+{
+ struct file_at_path_info info;
+
+ /* Find the filename in question (special case for absolute paths). */
+
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ if (access (name, mode) == 0)
+ return xstrdup (name);
+
+ return NULL;
+ }
+
+ info.name = name;
+ info.suffix = (mode & X_OK) != 0 ? HOST_EXECUTABLE_SUFFIX : "";
+ info.name_len = strlen (info.name);
+ info.suffix_len = strlen (info.suffix);
+ info.mode = mode;
+
+ return (char*) for_each_path (pprefix, do_multi,
+ info.name_len + info.suffix_len,
+ file_at_path, &info);
+}
+
+/* Specialization of find_a_file for programs that also takes into account
+ configure-specified default programs. */
+
+static char*
+find_a_program (const char *name)
+{
+ /* Do not search if default matches query. */
+
+#ifdef DEFAULT_ASSEMBLER
+ if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, X_OK) == 0)
+ return xstrdup (DEFAULT_ASSEMBLER);
+#endif
+
+#ifdef DEFAULT_LINKER
+ if (! strcmp (name, "ld") && access (DEFAULT_LINKER, X_OK) == 0)
+ return xstrdup (DEFAULT_LINKER);
+#endif
+
+#ifdef DEFAULT_DSYMUTIL
+ if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, X_OK) == 0)
+ return xstrdup (DEFAULT_DSYMUTIL);
+#endif
+
+ return find_a_file (&exec_prefixes, name, X_OK, false);
+}
+
+/* Ranking of prefixes in the sort list. -B prefixes are put before
+ all others. */
+
+enum path_prefix_priority
+{
+ PREFIX_PRIORITY_B_OPT,
+ PREFIX_PRIORITY_LAST
+};
+
+/* Add an entry for PREFIX in PLIST. The PLIST is kept in ascending
+ order according to PRIORITY. Within each PRIORITY, new entries are
+ appended.
+
+ If WARN is nonzero, we will warn if no file is found
+ through this prefix. WARN should point to an int
+ which will be set to 1 if this entry is used.
+
+ COMPONENT is the value to be passed to update_path.
+
+ REQUIRE_MACHINE_SUFFIX is 1 if this prefix can't be used without
+ the complete value of machine_suffix.
+ 2 means try both machine_suffix and just_machine_suffix. */
+
+static void
+add_prefix (struct path_prefix *pprefix, const char *prefix,
+ const char *component, /* enum prefix_priority */ int priority,
+ int require_machine_suffix, int os_multilib)
+{
+ struct prefix_list *pl, **prev;
+ int len;
+
+ for (prev = &pprefix->plist;
+ (*prev) != NULL && (*prev)->priority <= priority;
+ prev = &(*prev)->next)
+ ;
+
+ /* Keep track of the longest prefix. */
+
+ prefix = update_path (prefix, component);
+ len = strlen (prefix);
+ if (len > pprefix->max_len)
+ pprefix->max_len = len;
+
+ pl = XNEW (struct prefix_list);
+ pl->prefix = prefix;
+ pl->require_machine_suffix = require_machine_suffix;
+ pl->priority = priority;
+ pl->os_multilib = os_multilib;
+
+ /* Insert after PREV. */
+ pl->next = (*prev);
+ (*prev) = pl;
+}
+
+/* Same as add_prefix, but prepending target_system_root to prefix. */
+/* The target_system_root prefix has been relocated by gcc_exec_prefix. */
+static void
+add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
+ const char *component,
+ /* enum prefix_priority */ int priority,
+ int require_machine_suffix, int os_multilib)
+{
+ if (!IS_ABSOLUTE_PATH (prefix))
+ fatal_error (input_location, "system path %qs is not absolute", prefix);
+
+ if (target_system_root)
+ {
+ char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
+ size_t sysroot_len = strlen (target_system_root);
+
+ if (sysroot_len > 0
+ && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
+ sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+
+ if (target_sysroot_suffix)
+ prefix = concat (sysroot_no_trailing_dir_separator,
+ target_sysroot_suffix, prefix, NULL);
+ else
+ prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
+
+ free (sysroot_no_trailing_dir_separator);
+
+ /* We have to override this because GCC's notion of sysroot
+ moves along with GCC. */
+ component = "GCC";
+ }
+
+ add_prefix (pprefix, prefix, component, priority,
+ require_machine_suffix, os_multilib);
+}
+
+/* Same as add_prefix, but prepending target_sysroot_hdrs_suffix to prefix. */
+
+static void
+add_sysrooted_hdrs_prefix (struct path_prefix *pprefix, const char *prefix,
+ const char *component,
+ /* enum prefix_priority */ int priority,
+ int require_machine_suffix, int os_multilib)
+{
+ if (!IS_ABSOLUTE_PATH (prefix))
+ fatal_error (input_location, "system path %qs is not absolute", prefix);
+
+ if (target_system_root)
+ {
+ char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
+ size_t sysroot_len = strlen (target_system_root);
+
+ if (sysroot_len > 0
+ && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
+ sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+
+ if (target_sysroot_hdrs_suffix)
+ prefix = concat (sysroot_no_trailing_dir_separator,
+ target_sysroot_hdrs_suffix, prefix, NULL);
+ else
+ prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
+
+ free (sysroot_no_trailing_dir_separator);
+
+ /* We have to override this because GCC's notion of sysroot
+ moves along with GCC. */
+ component = "GCC";
+ }
+
+ add_prefix (pprefix, prefix, component, priority,
+ require_machine_suffix, os_multilib);
+}
+
+
+/* Execute the command specified by the arguments on the current line of spec.
+ When using pipes, this includes several piped-together commands
+ with `|' between them.
+
+ Return 0 if successful, -1 if failed. */
+
+static int
+execute (void)
+{
+ int i;
+ int n_commands; /* # of command. */
+ char *string;
+ struct pex_obj *pex;
+ struct command
+ {
+ const char *prog; /* program name. */
+ const char **argv; /* vector of args. */
+ };
+ const char *arg;
+
+ struct command *commands; /* each command buffer with above info. */
+
+ gcc_assert (!processing_spec_function);
+
+ if (wrapper_string)
+ {
+ string = find_a_program (argbuf[0]);
+ if (string)
+ argbuf[0] = string;
+ insert_wrapper (wrapper_string);
+ }
+
+ /* Count # of piped commands. */
+ for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
+ if (strcmp (arg, "|") == 0)
+ n_commands++;
+
+ /* Get storage for each command. */
+ commands = XALLOCAVEC (struct command, n_commands);
+
+ /* Split argbuf into its separate piped processes,
+ and record info about each one.
+ Also search for the programs that are to be run. */
+
+ argbuf.safe_push (0);
+
+ commands[0].prog = argbuf[0]; /* first command. */
+ commands[0].argv = argbuf.address ();
+
+ if (!wrapper_string)
+ {
+ string = find_a_program(commands[0].prog);
+ if (string)
+ commands[0].argv[0] = string;
+ }
+
+ for (n_commands = 1, i = 0; argbuf.iterate (i, &arg); i++)
+ if (arg && strcmp (arg, "|") == 0)
+ { /* each command. */
+#if defined (__MSDOS__) || defined (OS2) || defined (VMS)
+ fatal_error (input_location, "%<-pipe%> not supported");
+#endif
+ argbuf[i] = 0; /* Termination of command args. */
+ commands[n_commands].prog = argbuf[i + 1];
+ commands[n_commands].argv
+ = &(argbuf.address ())[i + 1];
+ string = find_a_program(commands[n_commands].prog);
+ if (string)
+ commands[n_commands].argv[0] = string;
+ n_commands++;
+ }
+
+ /* If -v, print what we are about to do, and maybe query. */
+
+ if (verbose_flag)
+ {
+ /* For help listings, put a blank line between sub-processes. */
+ if (print_help_list)
+ fputc ('\n', stderr);
+
+ /* Print each piped command as a separate line. */
+ for (i = 0; i < n_commands; i++)
+ {
+ const char *const *j;
+
+ if (verbose_only_flag)
+ {
+ for (j = commands[i].argv; *j; j++)
+ {
+ const char *p;
+ for (p = *j; *p; ++p)
+ if (!ISALNUM ((unsigned char) *p)
+ && *p != '_' && *p != '/' && *p != '-' && *p != '.')
+ break;
+ if (*p || !*j)
+ {
+ fprintf (stderr, " \"");
+ for (p = *j; *p; ++p)
+ {
+ if (*p == '"' || *p == '\\' || *p == '$')
+ fputc ('\\', stderr);
+ fputc (*p, stderr);
+ }
+ fputc ('"', stderr);
+ }
+ /* If it's empty, print "". */
+ else if (!**j)
+ fprintf (stderr, " \"\"");
+ else
+ fprintf (stderr, " %s", *j);
+ }
+ }
+ else
+ for (j = commands[i].argv; *j; j++)
+ /* If it's empty, print "". */
+ if (!**j)
+ fprintf (stderr, " \"\"");
+ else
+ fprintf (stderr, " %s", *j);
+
+ /* Print a pipe symbol after all but the last command. */
+ if (i + 1 != n_commands)
+ fprintf (stderr, " |");
+ fprintf (stderr, "\n");
+ }
+ fflush (stderr);
+ if (verbose_only_flag != 0)
+ {
+ /* verbose_only_flag should act as if the spec was
+ executed, so increment execution_count before
+ returning. This prevents spurious warnings about
+ unused linker input files, etc. */
+ execution_count++;
+ return 0;
+ }
+#ifdef DEBUG
+ fnotice (stderr, "\nGo ahead? (y or n) ");
+ fflush (stderr);
+ i = getchar ();
+ if (i != '\n')
+ while (getchar () != '\n')
+ ;
+
+ if (i != 'y' && i != 'Y')
+ return 0;
+#endif /* DEBUG */
+ }
+
+#ifdef ENABLE_VALGRIND_CHECKING
+ /* Run the each command through valgrind. To simplify prepending the
+ path to valgrind and the option "-q" (for quiet operation unless
+ something triggers), we allocate a separate argv array. */
+
+ for (i = 0; i < n_commands; i++)
+ {
+ const char **argv;
+ int argc;
+ int j;
+
+ for (argc = 0; commands[i].argv[argc] != NULL; argc++)
+ ;
+
+ argv = XALLOCAVEC (const char *, argc + 3);
+
+ argv[0] = VALGRIND_PATH;
+ argv[1] = "-q";
+ for (j = 2; j < argc + 2; j++)
+ argv[j] = commands[i].argv[j - 2];
+ argv[j] = NULL;
+
+ commands[i].argv = argv;
+ commands[i].prog = argv[0];
+ }
+#endif
+
+ /* Run each piped subprocess. */
+
+ pex = pex_init (PEX_USE_PIPES | ((report_times || report_times_to_file)
+ ? PEX_RECORD_TIMES : 0),
+ progname, temp_filename);
+ if (pex == NULL)
+ fatal_error (input_location, "%<pex_init%> failed: %m");
+
+ for (i = 0; i < n_commands; i++)
+ {
+ const char *errmsg;
+ int err;
+ const char *string = commands[i].argv[0];
+
+ errmsg = pex_run (pex,
+ ((i + 1 == n_commands ? PEX_LAST : 0)
+ | (string == commands[i].prog ? PEX_SEARCH : 0)),
+ string, CONST_CAST (char **, commands[i].argv),
+ NULL, NULL, &err);
+ if (errmsg != NULL)
+ {
+ errno = err;
+ fatal_error (input_location,
+ err ? G_("cannot execute %qs: %s: %m")
+ : G_("cannot execute %qs: %s"),
+ string, errmsg);
+ }
+
+ if (i && string != commands[i].prog)
+ free (CONST_CAST (char *, string));
+ }
+
+ execution_count++;
+
+ /* Wait for all the subprocesses to finish. */
+
+ {
+ int *statuses;
+ struct pex_time *times = NULL;
+ int ret_code = 0;
+
+ statuses = XALLOCAVEC (int, n_commands);
+ if (!pex_get_status (pex, n_commands, statuses))
+ fatal_error (input_location, "failed to get exit status: %m");
+
+ if (report_times || report_times_to_file)
+ {
+ times = XALLOCAVEC (struct pex_time, n_commands);
+ if (!pex_get_times (pex, n_commands, times))
+ fatal_error (input_location, "failed to get process times: %m");
+ }
+
+ pex_free (pex);
+
+ for (i = 0; i < n_commands; ++i)
+ {
+ int status = statuses[i];
+
+ if (WIFSIGNALED (status))
+ switch (WTERMSIG (status))
+ {
+ case SIGINT:
+ case SIGTERM:
+ /* SIGQUIT and SIGKILL are not available on MinGW. */
+#ifdef SIGQUIT
+ case SIGQUIT:
+#endif
+#ifdef SIGKILL
+ case SIGKILL:
+#endif
+ /* The user (or environment) did something to the
+ inferior. Making this an ICE confuses the user into
+ thinking there's a compiler bug. Much more likely is
+ the user or OOM killer nuked it. */
+ fatal_error (input_location,
+ "%s signal terminated program %s",
+ strsignal (WTERMSIG (status)),
+ commands[i].prog);
+ break;
+
+#ifdef SIGPIPE
+ case SIGPIPE:
+ /* SIGPIPE is a special case. It happens in -pipe mode
+ when the compiler dies before the preprocessor is
+ done, or the assembler dies before the compiler is
+ done. There's generally been an error already, and
+ this is just fallout. So don't generate another
+ error unless we would otherwise have succeeded. */
+ if (signal_count || greatest_status >= MIN_FATAL_STATUS)
+ {
+ signal_count++;
+ ret_code = -1;
+ break;
+ }
+#endif
+ /* FALLTHROUGH */
+
+ default:
+ /* The inferior failed to catch the signal. */
+ internal_error_no_backtrace ("%s signal terminated program %s",
+ strsignal (WTERMSIG (status)),
+ commands[i].prog);
+ }
+ else if (WIFEXITED (status)
+ && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
+ {
+ /* For ICEs in cc1, cc1obj, cc1plus see if it is
+ reproducible or not. */
+ const char *p;
+ if (flag_report_bug
+ && WEXITSTATUS (status) == ICE_EXIT_CODE
+ && i == 0
+ && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+ && startswith (p + 1, "cc1"))
+ try_generate_repro (commands[0].argv);
+ if (WEXITSTATUS (status) > greatest_status)
+ greatest_status = WEXITSTATUS (status);
+ ret_code = -1;
+ }
+
+ if (report_times || report_times_to_file)
+ {
+ struct pex_time *pt = &times[i];
+ double ut, st;
+
+ ut = ((double) pt->user_seconds
+ + (double) pt->user_microseconds / 1.0e6);
+ st = ((double) pt->system_seconds
+ + (double) pt->system_microseconds / 1.0e6);
+
+ if (ut + st != 0)
+ {
+ if (report_times)
+ fnotice (stderr, "# %s %.2f %.2f\n",
+ commands[i].prog, ut, st);
+
+ if (report_times_to_file)
+ {
+ int c = 0;
+ const char *const *j;
+
+ fprintf (report_times_to_file, "%g %g", ut, st);
+
+ for (j = &commands[i].prog; *j; j = &commands[i].argv[++c])
+ {
+ const char *p;
+ for (p = *j; *p; ++p)
+ if (*p == '"' || *p == '\\' || *p == '$'
+ || ISSPACE (*p))
+ break;
+
+ if (*p)
+ {
+ fprintf (report_times_to_file, " \"");
+ for (p = *j; *p; ++p)
+ {
+ if (*p == '"' || *p == '\\' || *p == '$')
+ fputc ('\\', report_times_to_file);
+ fputc (*p, report_times_to_file);
+ }
+ fputc ('"', report_times_to_file);
+ }
+ else
+ fprintf (report_times_to_file, " %s", *j);
+ }
+
+ fputc ('\n', report_times_to_file);
+ }
+ }
+ }
+ }
+
+ if (commands[0].argv[0] != commands[0].prog)
+ free (CONST_CAST (char *, commands[0].argv[0]));
+
+ return ret_code;
+ }
+}
+
+/* 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;
+
+static int n_switches_alloc;
+
+/* Set to zero if -fcompare-debug is disabled, positive if it's
+ enabled and we're running the first compilation, negative if it's
+ enabled and we're running the second compilation. For most of the
+ time, it's in the range -1..1, but it can be temporarily set to 2
+ or 3 to indicate that the -fcompare-debug flags didn't come from
+ the command-line, but rather from the GCC_COMPARE_DEBUG environment
+ variable, until a synthesized -fcompare-debug flag is added to the
+ command line. */
+int compare_debug;
+
+/* Set to nonzero if we've seen the -fcompare-debug-second flag. */
+int compare_debug_second;
+
+/* Set to the flags that should be passed to the second compilation in
+ a -fcompare-debug compilation. */
+const char *compare_debug_opt;
+
+static struct switchstr *switches_debug_check[2];
+
+static int n_switches_debug_check[2];
+
+static int n_switches_alloc_debug_check[2];
+
+static char *debug_check_temp_file[2];
+
+/* Language is one of three things:
+
+ 1) The name of a real programming language.
+ 2) NULL, indicating that no one has figured out
+ what it is yet.
+ 3) '*', indicating that the file should be passed
+ to the linker. */
+struct infile
+{
+ const char *name;
+ const char *language;
+ struct compiler *incompiler;
+ bool compiled;
+ bool preprocessed;
+};
+
+/* Also a vector of input files specified. */
+
+static struct infile *infiles;
+
+int n_infiles;
+
+static int n_infiles_alloc;
+
+/* True if undefined environment variables encountered during spec processing
+ are ok to ignore, typically when we're running for --help or --version. */
+
+static bool spec_undefvar_allowed;
+
+/* True if multiple input files are being compiled to a single
+ assembly file. */
+
+static bool combine_inputs;
+
+/* This counts the number of libraries added by lang_specific_driver, so that
+ we can tell if there were any user supplied any files or libraries. */
+
+static int added_libraries;
+
+/* And a vector of corresponding output files is made up later. */
+
+const char **outfiles;
+
+#if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+
+/* Convert NAME to a new name if it is the standard suffix. DO_EXE
+ is true if we should look for an executable suffix. DO_OBJ
+ is true if we should look for an object suffix. */
+
+static const char *
+convert_filename (const char *name, int do_exe ATTRIBUTE_UNUSED,
+ int do_obj ATTRIBUTE_UNUSED)
+{
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+ int i;
+#endif
+ int len;
+
+ if (name == NULL)
+ return NULL;
+
+ len = strlen (name);
+
+#ifdef HAVE_TARGET_OBJECT_SUFFIX
+ /* Convert x.o to x.obj if TARGET_OBJECT_SUFFIX is ".obj". */
+ if (do_obj && len > 2
+ && name[len - 2] == '.'
+ && name[len - 1] == 'o')
+ {
+ obstack_grow (&obstack, name, len - 2);
+ obstack_grow0 (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
+ name = XOBFINISH (&obstack, const char *);
+ }
+#endif
+
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+ /* If there is no filetype, make it the executable suffix (which includes
+ the "."). But don't get confused if we have just "-o". */
+ if (! do_exe || TARGET_EXECUTABLE_SUFFIX[0] == 0 || not_actual_file_p (name))
+ return name;
+
+ for (i = len - 1; i >= 0; i--)
+ if (IS_DIR_SEPARATOR (name[i]))
+ break;
+
+ for (i++; i < len; i++)
+ if (name[i] == '.')
+ return name;
+
+ obstack_grow (&obstack, name, len);
+ obstack_grow0 (&obstack, TARGET_EXECUTABLE_SUFFIX,
+ strlen (TARGET_EXECUTABLE_SUFFIX));
+ name = XOBFINISH (&obstack, const char *);
+#endif
+
+ return name;
+}
+#endif
+
+/* Display the command line switches accepted by gcc. */
+static void
+display_help (void)
+{
+ printf (_("Usage: %s [options] file...\n"), progname);
+ fputs (_("Options:\n"), stdout);
+
+ fputs (_(" -pass-exit-codes Exit with highest error code from a phase.\n"), stdout);
+ fputs (_(" --help Display this information.\n"), stdout);
+ fputs (_(" --target-help Display target specific command line options "
+ "(including assembler and linker options).\n"), stdout);
+ fputs (_(" --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].\n"), stdout);
+ fputs (_(" Display specific types of command line options.\n"), stdout);
+ if (! verbose_flag)
+ fputs (_(" (Use '-v --help' to display command line options of sub-processes).\n"), stdout);
+ fputs (_(" --version Display compiler version information.\n"), stdout);
+ fputs (_(" -dumpspecs Display all of the built in spec strings.\n"), stdout);
+ fputs (_(" -dumpversion Display the version of the compiler.\n"), stdout);
+ fputs (_(" -dumpmachine Display the compiler's target processor.\n"), stdout);
+ fputs (_(" -foffload=<targets> Specify offloading targets.\n"), stdout);
+ fputs (_(" -print-search-dirs Display the directories in the compiler's search path.\n"), stdout);
+ fputs (_(" -print-libgcc-file-name Display the name of the compiler's companion library.\n"), stdout);
+ fputs (_(" -print-file-name=<lib> Display the full path to library <lib>.\n"), stdout);
+ fputs (_(" -print-prog-name=<prog> Display the full path to compiler component <prog>.\n"), stdout);
+ fputs (_("\
+ -print-multiarch Display the target's normalized GNU triplet, used as\n\
+ a component in the library path.\n"), stdout);
+ fputs (_(" -print-multi-directory Display the root directory for versions of libgcc.\n"), stdout);
+ fputs (_("\
+ -print-multi-lib Display the mapping between command line options and\n\
+ multiple library search directories.\n"), stdout);
+ fputs (_(" -print-multi-os-directory Display the relative path to OS libraries.\n"), stdout);
+ fputs (_(" -print-sysroot Display the target libraries directory.\n"), stdout);
+ fputs (_(" -print-sysroot-headers-suffix Display the sysroot suffix used to find headers.\n"), stdout);
+ fputs (_(" -Wa,<options> Pass comma-separated <options> on to the assembler.\n"), stdout);
+ fputs (_(" -Wp,<options> Pass comma-separated <options> on to the preprocessor.\n"), stdout);
+ fputs (_(" -Wl,<options> Pass comma-separated <options> on to the linker.\n"), stdout);
+ fputs (_(" -Xassembler <arg> Pass <arg> on to the assembler.\n"), stdout);
+ fputs (_(" -Xpreprocessor <arg> Pass <arg> on to the preprocessor.\n"), stdout);
+ fputs (_(" -Xlinker <arg> Pass <arg> on to the linker.\n"), stdout);
+ fputs (_(" -save-temps Do not delete intermediate files.\n"), stdout);
+ fputs (_(" -save-temps=<arg> Do not delete intermediate files.\n"), stdout);
+ fputs (_("\
+ -no-canonical-prefixes Do not canonicalize paths when building relative\n\
+ prefixes to other gcc components.\n"), stdout);
+ fputs (_(" -pipe Use pipes rather than intermediate files.\n"), stdout);
+ fputs (_(" -time Time the execution of each subprocess.\n"), stdout);
+ fputs (_(" -specs=<file> Override built-in specs with the contents of <file>.\n"), stdout);
+ fputs (_(" -std=<standard> Assume that the input sources are for <standard>.\n"), stdout);
+ fputs (_("\
+ --sysroot=<directory> Use <directory> as the root directory for headers\n\
+ and libraries.\n"), stdout);
+ fputs (_(" -B <directory> Add <directory> to the compiler's search paths.\n"), stdout);
+ fputs (_(" -v Display the programs invoked by the compiler.\n"), stdout);
+ fputs (_(" -### Like -v but options quoted and commands not executed.\n"), stdout);
+ fputs (_(" -E Preprocess only; do not compile, assemble or link.\n"), stdout);
+ fputs (_(" -S Compile only; do not assemble or link.\n"), stdout);
+ fputs (_(" -c Compile and assemble, but do not link.\n"), stdout);
+ fputs (_(" -o <file> Place the output into <file>.\n"), stdout);
+ fputs (_(" -pie Create a dynamically linked position independent\n\
+ executable.\n"), stdout);
+ fputs (_(" -shared Create a shared library.\n"), stdout);
+ fputs (_("\
+ -x <language> Specify the language of the following input files.\n\
+ Permissible languages include: c c++ assembler none\n\
+ 'none' means revert to the default behavior of\n\
+ guessing the language based on the file's extension.\n\
+"), stdout);
+
+ printf (_("\
+\nOptions starting with -g, -f, -m, -O, -W, or --param are automatically\n\
+ passed on to the various sub-processes invoked by %s. In order to pass\n\
+ other options on to these processes the -W<letter> options must be used.\n\
+"), progname);
+
+ /* The rest of the options are displayed by invocations of the various
+ sub-processes. */
+}
+
+static void
+add_preprocessor_option (const char *option, int len)
+{
+ preprocessor_options.safe_push (save_string (option, len));
+}
+
+static void
+add_assembler_option (const char *option, int len)
+{
+ assembler_options.safe_push (save_string (option, len));
+}
+
+static void
+add_linker_option (const char *option, int len)
+{
+ linker_options.safe_push (save_string (option, len));
+}
+
+/* Allocate space for an input file in infiles. */
+
+static void
+alloc_infile (void)
+{
+ if (n_infiles_alloc == 0)
+ {
+ n_infiles_alloc = 16;
+ infiles = XNEWVEC (struct infile, n_infiles_alloc);
+ }
+ else if (n_infiles_alloc == n_infiles)
+ {
+ n_infiles_alloc *= 2;
+ infiles = XRESIZEVEC (struct infile, infiles, n_infiles_alloc);
+ }
+}
+
+/* Store an input file with the given NAME and LANGUAGE in
+ infiles. */
+
+static void
+add_infile (const char *name, const char *language)
+{
+ alloc_infile ();
+ infiles[n_infiles].name = name;
+ infiles[n_infiles++].language = language;
+}
+
+/* Allocate space for a switch in switches. */
+
+static void
+alloc_switch (void)
+{
+ if (n_switches_alloc == 0)
+ {
+ n_switches_alloc = 16;
+ switches = XNEWVEC (struct switchstr, n_switches_alloc);
+ }
+ else if (n_switches_alloc == n_switches)
+ {
+ n_switches_alloc *= 2;
+ switches = XRESIZEVEC (struct switchstr, switches, n_switches_alloc);
+ }
+}
+
+/* Save an option OPT with N_ARGS arguments in array ARGS, marking it
+ as validated if VALIDATED and KNOWN if it is an internal switch. */
+
+static void
+save_switch (const char *opt, size_t n_args, const char *const *args,
+ bool validated, bool known)
+{
+ alloc_switch ();
+ switches[n_switches].part1 = opt + 1;
+ if (n_args == 0)
+ switches[n_switches].args = 0;
+ else
+ {
+ switches[n_switches].args = XNEWVEC (const char *, n_args + 1);
+ memcpy (switches[n_switches].args, args, n_args * sizeof (const char *));
+ switches[n_switches].args[n_args] = NULL;
+ }
+
+ switches[n_switches].live_cond = 0;
+ switches[n_switches].validated = validated;
+ switches[n_switches].known = known;
+ switches[n_switches].ordering = 0;
+ n_switches++;
+}
+
+/* Set the SOURCE_DATE_EPOCH environment variable to the current time if it is
+ not set already. */
+
+static void
+set_source_date_epoch_envvar ()
+{
+ /* Array size is 21 = ceil(log_10(2^64)) + 1 to hold string representations
+ of 64 bit integers. */
+ char source_date_epoch[21];
+ time_t tt;
+
+ errno = 0;
+ tt = time (NULL);
+ if (tt < (time_t) 0 || errno != 0)
+ tt = (time_t) 0;
+
+ snprintf (source_date_epoch, 21, "%llu", (unsigned long long) tt);
+ /* Using setenv instead of xputenv because we want the variable to remain
+ after finalizing so that it's still set in the second run when using
+ -fcompare-debug. */
+ setenv ("SOURCE_DATE_EPOCH", source_date_epoch, 0);
+}
+
+/* Handle an option DECODED that is unknown to the option-processing
+ machinery. */
+
+static bool
+driver_unknown_option_callback (const struct cl_decoded_option *decoded)
+{
+ const char *opt = decoded->arg;
+ if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
+ && !(decoded->errors & CL_ERR_NEGATIVE))
+ {
+ /* Leave unknown -Wno-* options for the compiler proper, to be
+ diagnosed only if there are warnings. */
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], false, true);
+ return false;
+ }
+ if (decoded->opt_index == OPT_SPECIAL_unknown)
+ {
+ /* Give it a chance to define it a spec file. */
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], false, false);
+ return false;
+ }
+ else
+ return true;
+}
+
+/* Handle an option DECODED that is not marked as CL_DRIVER.
+ LANG_MASK will always be CL_DRIVER. */
+
+static void
+driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
+ unsigned int lang_mask ATTRIBUTE_UNUSED)
+{
+ /* At this point, non-driver options are accepted (and expected to
+ be passed down by specs) unless marked to be rejected by the
+ driver. Options to be rejected by the driver but accepted by the
+ compilers proper are treated just like completely unknown
+ options. */
+ const struct cl_option *option = &cl_options[decoded->opt_index];
+
+ if (option->cl_reject_driver)
+ error ("aaunrecognized command-line option %qs",
+ decoded->orig_option_with_args_text);
+ else
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], false, true);
+}
+
+static const char *spec_lang = 0;
+static int last_language_n_infiles;
+
+
+/* Check that GCC is configured to support the offload target. */
+
+static bool
+check_offload_target_name (const char *target, ptrdiff_t len)
+{
+ const char *n, *c = OFFLOAD_TARGETS;
+ while (c)
+ {
+ n = strchr (c, ',');
+ if (n == NULL)
+ n = strchr (c, '\0');
+ if (len == n - c && strncmp (target, c, n - c) == 0)
+ break;
+ c = *n ? n + 1 : NULL;
+ }
+ if (!c)
+ {
+ auto_vec<const char*> candidates;
+ size_t olen = strlen (OFFLOAD_TARGETS) + 1;
+ char *cand = XALLOCAVEC (char, olen);
+ memcpy (cand, OFFLOAD_TARGETS, olen);
+ for (c = strtok (cand, ","); c; c = strtok (NULL, ","))
+ candidates.safe_push (c);
+ candidates.safe_push ("default");
+ candidates.safe_push ("disable");
+
+ char *target2 = XALLOCAVEC (char, len + 1);
+ memcpy (target2, target, len);
+ target2[len] = '\0';
+
+ error ("GCC is not configured to support %qs as %<-foffload=%> argument",
+ target2);
+
+ char *s;
+ const char *hint = candidates_list_and_hint (target2, s, candidates);
+ if (hint)
+ inform (UNKNOWN_LOCATION,
+ "valid %<-foffload=%> arguments are: %s; "
+ "did you mean %qs?", s, hint);
+ else
+ inform (UNKNOWN_LOCATION, "valid %<-foffload=%> arguments are: %s", s);
+ XDELETEVEC (s);
+ return false;
+ }
+ return true;
+}
+
+/* Sanity check for -foffload-options. */
+
+static void
+check_foffload_target_names (const char *arg)
+{
+ const char *cur, *next, *end;
+ /* If option argument starts with '-' then no target is specified and we
+ do not need to parse it. */
+ if (arg[0] == '-')
+ return;
+ end = strchr (arg, '=');
+ if (end == NULL)
+ {
+ error ("%<=%>options missing after %<-foffload-options=%>target");
+ return;
+ }
+
+ cur = arg;
+ while (cur < end)
+ {
+ next = strchr (cur, ',');
+ if (next == NULL)
+ next = end;
+ next = (next > end) ? end : next;
+
+ /* Retain non-supported targets after printing an error as those will not
+ be processed; each enabled target only processes its triplet. */
+ check_offload_target_name (cur, next - cur);
+ cur = next + 1;
+ }
+}
+
+/* Parse -foffload option argument. */
+
+static void
+handle_foffload_option (const char *arg)
+{
+ const char *c, *cur, *n, *next, *end;
+ char *target;
+
+ /* If option argument starts with '-' then no target is specified and we
+ do not need to parse it. */
+ if (arg[0] == '-')
+ return;
+
+ end = strchr (arg, '=');
+ if (end == NULL)
+ end = strchr (arg, '\0');
+ cur = arg;
+
+ while (cur < end)
+ {
+ next = strchr (cur, ',');
+ if (next == NULL)
+ next = end;
+ next = (next > end) ? end : next;
+
+ target = XNEWVEC (char, next - cur + 1);
+ memcpy (target, cur, next - cur);
+ target[next - cur] = '\0';
+
+ /* Reset offloading list and continue. */
+ if (strcmp (target, "default") == 0)
+ {
+ free (offload_targets);
+ offload_targets = NULL;
+ goto next_item;
+ }
+
+ /* If 'disable' is passed to the option, clean the list of
+ offload targets and return, even if more targets follow.
+ Likewise if GCC is not configured to support that offload target. */
+ if (strcmp (target, "disable") == 0
+ || !check_offload_target_name (target, next - cur))
+ {
+ free (offload_targets);
+ offload_targets = xstrdup ("");
+ return;
+ }
+
+ if (!offload_targets)
+ {
+ offload_targets = target;
+ target = NULL;
+ }
+ else
+ {
+ /* Check that the target hasn't already presented in the list. */
+ c = offload_targets;
+ do
+ {
+ n = strchr (c, ':');
+ if (n == NULL)
+ n = strchr (c, '\0');
+
+ if (next - cur == n - c && strncmp (c, target, n - c) == 0)
+ break;
+
+ c = n + 1;
+ }
+ while (*n);
+
+ /* If duplicate is not found, append the target to the list. */
+ if (c > n)
+ {
+ size_t offload_targets_len = strlen (offload_targets);
+ offload_targets
+ = XRESIZEVEC (char, offload_targets,
+ offload_targets_len + 1 + next - cur + 1);
+ offload_targets[offload_targets_len++] = ':';
+ memcpy (offload_targets + offload_targets_len, target, next - cur + 1);
+ }
+ }
+next_item:
+ cur = next + 1;
+ XDELETEVEC (target);
+ }
+}
+
+/* Handle a driver option; arguments and return value as for
+ handle_option. */
+
+static bool
+driver_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
+ location_t loc,
+ const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
+ diagnostic_context *dc,
+ void (*) (void))
+{
+ size_t opt_index = decoded->opt_index;
+ const char *arg = decoded->arg;
+ const char *compare_debug_replacement_opt;
+ const char* orig = decoded->orig_option_with_args_text;
+ int value = decoded->value;
+ bool validated = false;
+ bool do_save = true;
+
+ gcc_assert (opts == &global_options);
+ gcc_assert (opts_set == &global_options_set);
+ gcc_assert (kind == DK_UNSPECIFIED);
+ gcc_assert (loc == UNKNOWN_LOCATION);
+ gcc_assert (dc == global_dc);
+
+ switch (opt_index)
+ {
+ case OPT_dumpspecs:
+ {
+ struct spec_list *sl;
+ init_spec ();
+ for (sl = specs; sl; sl = sl->next)
+ printf ("*%s:\n%s\n\n", sl->name, *(sl->ptr_spec));
+ if (link_command_spec)
+ printf ("*link_command:\n%s\n\n", link_command_spec);
+ exit (0);
+ }
+
+ case OPT_dumpversion:
+ printf ("%s\n", spec_version);
+ exit (0);
+
+ case OPT_dumpmachine:
+ printf ("%s\n", spec_machine);
+ exit (0);
+
+ case OPT_dumpfullversion:
+ printf ("%s\n", BASEVER);
+ exit (0);
+
+ case OPT__version:
+ print_version = 1;
+
+ /* CPP driver cannot obtain switch from cc1_options. */
+ if (is_cpp_driver)
+ add_preprocessor_option ("--version", strlen ("--version"));
+ add_assembler_option ("--version", strlen ("--version"));
+ add_linker_option ("--version", strlen ("--version"));
+ break;
+
+ case OPT__completion_:
+ validated = true;
+ completion = decoded->arg;
+ break;
+
+ case OPT__help:
+ print_help_list = 1;
+
+ /* CPP driver cannot obtain switch from cc1_options. */
+ if (is_cpp_driver)
+ add_preprocessor_option ("--help", 6);
+ add_assembler_option ("--help", 6);
+ add_linker_option ("--help", 6);
+ break;
+
+ case OPT__help_:
+ print_subprocess_help = 2;
+ break;
+
+ case OPT__obj_ext_:
+ validated = true;
+ add_preprocessor_option (orig, strlen (orig));
+ break;
+
+ case OPT__target_help:
+ print_subprocess_help = 1;
+
+ /* CPP driver cannot obtain switch from cc1_options. */
+ if (is_cpp_driver)
+ add_preprocessor_option ("--target-help", 13);
+ add_assembler_option ("--target-help", 13);
+ add_linker_option ("--target-help", 13);
+ break;
+
+ case OPT__no_sysroot_suffix:
+ case OPT_pass_exit_codes:
+ case OPT_print_search_dirs:
+ case OPT_print_file_name_:
+ case OPT_print_prog_name_:
+ case OPT_print_multi_lib:
+ case OPT_print_multi_directory:
+ case OPT_print_sysroot:
+ case OPT_print_multi_os_directory:
+ case OPT_print_multiarch:
+ case OPT_print_sysroot_headers_suffix:
+ case OPT_time:
+ case OPT_wrapper:
+ /* These options set the variables specified in common.opt
+ automatically, and do not need to be saved for spec
+ processing. */
+ do_save = false;
+ break;
+
+ case OPT_print_libgcc_file_name:
+ print_file_name = "libgcc.a";
+ do_save = false;
+ break;
+
+ case OPT_fuse_ld_bfd:
+ use_ld = ".bfd";
+ break;
+
+ case OPT_fuse_ld_gold:
+ use_ld = ".gold";
+ break;
+
+ case OPT_fuse_ld_mold:
+ use_ld = ".mold";
+ break;
+
+ case OPT_fcompare_debug_second:
+ compare_debug_second = 1;
+ break;
+
+ case OPT_fcompare_debug:
+ switch (value)
+ {
+ case 0:
+ compare_debug_replacement_opt = "-fcompare-debug=";
+ arg = "";
+ goto compare_debug_with_arg;
+
+ case 1:
+ compare_debug_replacement_opt = "-fcompare-debug=-gtoggle";
+ arg = "-gtoggle";
+ goto compare_debug_with_arg;
+
+ default:
+ gcc_unreachable ();
+ }
+ break;
+
+ case OPT_fcompare_debug_:
+ compare_debug_replacement_opt = decoded->canonical_option[0];
+ compare_debug_with_arg:
+ gcc_assert (decoded->canonical_option_num_elements == 1);
+ gcc_assert (arg != NULL);
+ if (*arg)
+ compare_debug = 1;
+ else
+ compare_debug = -1;
+ if (compare_debug < 0)
+ compare_debug_opt = NULL;
+ else
+ compare_debug_opt = arg;
+ save_switch (compare_debug_replacement_opt, 0, NULL, validated, true);
+ set_source_date_epoch_envvar ();
+ return true;
+
+ case OPT_fdiagnostics_color_:
+ diagnostic_color_init (dc, value);
+ break;
+
+ case OPT_fdiagnostics_urls_:
+ diagnostic_urls_init (dc, value);
+ break;
+
+ case OPT_fdiagnostics_format_:
+ diagnostic_output_format_init (dc,
+ (enum diagnostics_output_format)value);
+ break;
+
+ case OPT_Wa_:
+ {
+ int prev, j;
+ /* Pass the rest of this option to the assembler. */
+
+ /* Split the argument at commas. */
+ prev = 0;
+ for (j = 0; arg[j]; j++)
+ if (arg[j] == ',')
+ {
+ add_assembler_option (arg + prev, j - prev);
+ prev = j + 1;
+ }
+
+ /* Record the part after the last comma. */
+ add_assembler_option (arg + prev, j - prev);
+ }
+ do_save = false;
+ break;
+
+ case OPT_Wp_:
+ {
+ int prev, j;
+ /* Pass the rest of this option to the preprocessor. */
+
+ /* Split the argument at commas. */
+ prev = 0;
+ for (j = 0; arg[j]; j++)
+ if (arg[j] == ',')
+ {
+ add_preprocessor_option (arg + prev, j - prev);
+ prev = j + 1;
+ }
+
+ /* Record the part after the last comma. */
+ add_preprocessor_option (arg + prev, j - prev);
+ }
+ do_save = false;
+ break;
+
+ case OPT_Wl_:
+ {
+ int prev, j;
+ /* Split the argument at commas. */
+ prev = 0;
+ for (j = 0; arg[j]; j++)
+ if (arg[j] == ',')
+ {
+ add_infile (save_string (arg + prev, j - prev), "*");
+ prev = j + 1;
+ }
+ /* Record the part after the last comma. */
+ add_infile (arg + prev, "*");
+ }
+ do_save = false;
+ break;
+
+ case OPT_Xlinker:
+ add_infile (arg, "*");
+ do_save = false;
+ break;
+
+ case OPT_Xpreprocessor:
+ add_preprocessor_option (arg, strlen (arg));
+ do_save = false;
+ break;
+
+ case OPT_Xassembler:
+ add_assembler_option (arg, strlen (arg));
+ do_save = false;
+ break;
+
+ case OPT_l:
+ /* POSIX allows separation of -l and the lib arg; canonicalize
+ by concatenating -l with its arg */
+ add_infile (concat ("-l", arg, NULL), "*");
+ do_save = false;
+ break;
+
+ case OPT_L:
+ /* Similarly, canonicalize -L for linkers that may not accept
+ separate arguments. */
+ save_switch (concat ("-L", arg, NULL), 0, NULL, validated, true);
+ return true;
+
+ case OPT_F:
+ /* Likewise -F. */
+ save_switch (concat ("-F", arg, NULL), 0, NULL, validated, true);
+ return true;
+
+ case OPT_save_temps:
+ if (!save_temps_flag)
+ save_temps_flag = SAVE_TEMPS_DUMP;
+ validated = true;
+ break;
+
+ case OPT_save_temps_:
+ if (strcmp (arg, "cwd") == 0)
+ save_temps_flag = SAVE_TEMPS_CWD;
+ else if (strcmp (arg, "obj") == 0
+ || strcmp (arg, "object") == 0)
+ save_temps_flag = SAVE_TEMPS_OBJ;
+ else
+ fatal_error (input_location, "%qs is an unknown %<-save-temps%> option",
+ decoded->orig_option_with_args_text);
+ save_temps_overrides_dumpdir = true;
+ break;
+
+ case OPT_dumpdir:
+ free (dumpdir);
+ dumpdir = xstrdup (arg);
+ save_temps_overrides_dumpdir = false;
+ break;
+
+ case OPT_dumpbase:
+ free (dumpbase);
+ dumpbase = xstrdup (arg);
+ break;
+
+ case OPT_dumpbase_ext:
+ free (dumpbase_ext);
+ dumpbase_ext = xstrdup (arg);
+ break;
+
+ case OPT_no_canonical_prefixes:
+ /* Already handled as a special case, so ignored here. */
+ do_save = false;
+ break;
+
+ case OPT_pipe:
+ validated = true;
+ /* These options set the variables specified in common.opt
+ automatically, but do need to be saved for spec
+ processing. */
+ break;
+
+ case OPT_specs_:
+ {
+ struct user_specs *user = XNEW (struct user_specs);
+
+ user->next = (struct user_specs *) 0;
+ user->filename = arg;
+ if (user_specs_tail)
+ user_specs_tail->next = user;
+ else
+ user_specs_head = user;
+ user_specs_tail = user;
+ }
+ validated = true;
+ break;
+
+ case OPT__sysroot_:
+ target_system_root = arg;
+ target_system_root_changed = 1;
+ /* Saving this option is useful to let self-specs decide to
+ provide a default one. */
+ do_save = true;
+ validated = true;
+ break;
+
+ case OPT_time_:
+ if (report_times_to_file)
+ fclose (report_times_to_file);
+ report_times_to_file = fopen (arg, "a");
+ do_save = false;
+ break;
+
+ case OPT____:
+ /* "-###"
+ This is similar to -v except that there is no execution
+ of the commands and the echoed arguments are quoted. It
+ is intended for use in shell scripts to capture the
+ driver-generated command line. */
+ verbose_only_flag++;
+ verbose_flag = 1;
+ do_save = false;
+ break;
+
+ case OPT_B:
+ {
+ size_t len = strlen (arg);
+
+ /* Catch the case where the user has forgotten to append a
+ directory separator to the path. Note, they may be using
+ -B to add an executable name prefix, eg "i386-elf-", in
+ order to distinguish between multiple installations of
+ GCC in the same directory. Hence we must check to see
+ if appending a directory separator actually makes a
+ valid directory name. */
+ if (!IS_DIR_SEPARATOR (arg[len - 1])
+ && is_directory (arg, false))
+ {
+ char *tmp = XNEWVEC (char, len + 2);
+ strcpy (tmp, arg);
+ tmp[len] = DIR_SEPARATOR;
+ tmp[++len] = 0;
+ arg = tmp;
+ }
+
+ add_prefix (&exec_prefixes, arg, NULL,
+ PREFIX_PRIORITY_B_OPT, 0, 0);
+ add_prefix (&startfile_prefixes, arg, NULL,
+ PREFIX_PRIORITY_B_OPT, 0, 0);
+ add_prefix (&include_prefixes, arg, NULL,
+ PREFIX_PRIORITY_B_OPT, 0, 0);
+ }
+ validated = true;
+ break;
+
+ case OPT_E:
+ have_E = true;
+ break;
+
+ case OPT_x:
+ spec_lang = arg;
+ if (!strcmp (spec_lang, "none"))
+ /* Suppress the warning if -xnone comes after the last input
+ file, because alternate command interfaces like g++ might
+ find it useful to place -xnone after each input file. */
+ spec_lang = 0;
+ else
+ last_language_n_infiles = n_infiles;
+ do_save = false;
+ break;
+
+ case OPT_o:
+ have_o = 1;
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
+ arg = convert_filename (arg, ! have_c, 0);
+#endif
+ output_file = arg;
+ /* On some systems, ld cannot handle "-o" without a space. So
+ split the option from its argument. */
+ save_switch ("-o", 1, &arg, validated, true);
+ return true;
+
+#ifdef ENABLE_DEFAULT_PIE
+ case OPT_pie:
+ /* -pie is turned on by default. */
+#endif
+
+ case OPT_static_libgcc:
+ case OPT_shared_libgcc:
+ case OPT_static_libgfortran:
+ case OPT_static_libphobos:
+ case OPT_static_libstdc__:
+ /* These are always valid, since gcc.cc itself understands the
+ first two, gfortranspec.cc understands -static-libgfortran,
+ d-spec.cc understands -static-libphobos, and g++spec.cc
+ understands -static-libstdc++ */
+ validated = true;
+ break;
+
+/// sdcpp case OPT_fwpa:
+/// sdcpp flag_wpa = "";
+/// sdcpp break;
+
+ case OPT_foffload_options_:
+ check_foffload_target_names (arg);
+ break;
+
+ case OPT_foffload_:
+ handle_foffload_option (arg);
+ if (arg[0] == '-' || NULL != strchr (arg, '='))
+ save_switch (concat ("-foffload-options=", arg, NULL),
+ 0, NULL, validated, true);
+ do_save = false;
+ break;
+
+ default:
+ /* Various driver options need no special processing at this
+ point, having been handled in a prescan above or being
+ handled by specs. */
+ break;
+ }
+
+ if (do_save)
+ save_switch (decoded->canonical_option[0],
+ decoded->canonical_option_num_elements - 1,
+ &decoded->canonical_option[1], validated, true);
+ return true;
+}
+
+/* Return true if F2 is F1 followed by a single suffix, i.e., by a
+ period and additional characters other than a period. */
+
+static inline bool
+adds_single_suffix_p (const char *f2, const char *f1)
+{
+ size_t len = strlen (f1);
+
+ return (strncmp (f1, f2, len) == 0
+ && f2[len] == '.'
+ && strchr (f2 + len + 1, '.') == NULL);
+}
+
+/* Put the driver's standard set of option handlers in *HANDLERS. */
+
+static void
+set_option_handlers (struct cl_option_handlers *handlers)
+{
+ handlers->unknown_option_callback = driver_unknown_option_callback;
+ handlers->wrong_lang_callback = driver_wrong_lang_callback;
+ handlers->num_handlers = 3;
+ handlers->handlers[0].handler = driver_handle_option;
+ handlers->handlers[0].mask = CL_DRIVER;
+ handlers->handlers[1].handler = common_handle_option;
+ handlers->handlers[1].mask = CL_COMMON;
+ // sdcpp handlers->handlers[2].handler = target_handle_option;
+ handlers->handlers[2].mask = CL_TARGET;
+}
+
+
+/* Return the index into infiles for the single non-library
+ non-lto-wpa input file, -1 if there isn't any, or -2 if there is
+ more than one. */
+static inline int
+single_input_file_index ()
+{
+ int ret = -1;
+
+ for (int i = 0; i < n_infiles; i++)
+ {
+ if (infiles[i].language
+ && (infiles[i].language[0] == '*'
+ || (flag_wpa
+ && strcmp (infiles[i].language, "lto") == 0)))
+ continue;
+
+ if (ret != -1)
+ return -2;
+
+ ret = i;
+ }
+
+ return ret;
+}
+
+/* Create the vector `switches' and its contents.
+ Store its length in `n_switches'. */
+
+static void
+process_command (unsigned int decoded_options_count,
+ struct cl_decoded_option *decoded_options)
+{
+ const char *temp;
+ char *temp1;
+ char *tooldir_prefix, *tooldir_prefix2;
+ char *(*get_relative_prefix) (const char *, const char *,
+ const char *) = NULL;
+ struct cl_option_handlers handlers;
+ unsigned int j;
+
+ gcc_exec_prefix = env.get ("GCC_EXEC_PREFIX");
+
+ n_switches = 0;
+ n_infiles = 0;
+ added_libraries = 0;
+
+ /* Figure compiler version from version string. */
+
+ compiler_version = temp1 = xstrdup (version_string);
+
+ for (; *temp1; ++temp1)
+ {
+ if (*temp1 == ' ')
+ {
+ *temp1 = '\0';
+ break;
+ }
+ }
+
+ /* Handle any -no-canonical-prefixes flag early, to assign the function
+ that builds relative prefixes. This function creates default search
+ paths that are needed later in normal option handling. */
+
+ for (j = 1; j < decoded_options_count; j++)
+ {
+ if (decoded_options[j].opt_index == OPT_no_canonical_prefixes)
+ {
+ get_relative_prefix = make_relative_prefix_ignore_links;
+ break;
+ }
+ }
+ if (! get_relative_prefix)
+ get_relative_prefix = make_relative_prefix;
+
+ /* Set up the default search paths. If there is no GCC_EXEC_PREFIX,
+ see if we can create it from the pathname specified in
+ decoded_options[0].arg. */
+
+ gcc_libexec_prefix = standard_libexec_prefix;
+#ifndef VMS
+ /* FIXME: make_relative_prefix doesn't yet work for VMS. */
+ if (!gcc_exec_prefix)
+ {
+ gcc_exec_prefix = get_relative_prefix (decoded_options[0].arg,
+ standard_bindir_prefix,
+ standard_exec_prefix);
+ gcc_libexec_prefix = get_relative_prefix (decoded_options[0].arg,
+ standard_bindir_prefix,
+ standard_libexec_prefix);
+ if (gcc_exec_prefix)
+ xputenv (concat ("GCC_EXEC_PREFIX=", gcc_exec_prefix, NULL));
+ }
+ else
+ {
+ /* make_relative_prefix requires a program name, but
+ GCC_EXEC_PREFIX is typically a directory name with a trailing
+ / (which is ignored by make_relative_prefix), so append a
+ program name. */
+ char *tmp_prefix = concat (gcc_exec_prefix, "gcc", NULL);
+ gcc_libexec_prefix = get_relative_prefix (tmp_prefix,
+ standard_exec_prefix,
+ standard_libexec_prefix);
+
+ /* The path is unrelocated, so fallback to the original setting. */
+ if (!gcc_libexec_prefix)
+ gcc_libexec_prefix = standard_libexec_prefix;
+
+ free (tmp_prefix);
+ }
+#else
+#endif
+ /* From this point onward, gcc_exec_prefix is non-null if the toolchain
+ is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
+ or an automatically created GCC_EXEC_PREFIX from
+ decoded_options[0].arg. */
+
+ /* Do language-specific adjustment/addition of flags. */
+ lang_specific_driver (&decoded_options, &decoded_options_count,
+ &added_libraries);
+
+ if (gcc_exec_prefix)
+ {
+ int len = strlen (gcc_exec_prefix);
+
+ if (len > (int) sizeof ("/lib/gcc/") - 1
+ && (IS_DIR_SEPARATOR (gcc_exec_prefix[len-1])))
+ {
+ temp = gcc_exec_prefix + len - sizeof ("/lib/gcc/") + 1;
+ if (IS_DIR_SEPARATOR (*temp)
+ && filename_ncmp (temp + 1, "lib", 3) == 0
+ && IS_DIR_SEPARATOR (temp[4])
+ && filename_ncmp (temp + 5, "gcc", 3) == 0)
+ len -= sizeof ("/lib/gcc/") - 1;
+ }
+
+ set_std_prefix (gcc_exec_prefix, len);
+ add_prefix (&exec_prefixes, gcc_libexec_prefix, "GCC",
+ PREFIX_PRIORITY_LAST, 0, 0);
+ add_prefix (&startfile_prefixes, gcc_exec_prefix, "GCC",
+ PREFIX_PRIORITY_LAST, 0, 0);
+ }
+
+ /* COMPILER_PATH and LIBRARY_PATH have values
+ that are lists of directory names with colons. */
+
+ temp = env.get ("COMPILER_PATH");
+ if (temp)
+ {
+ const char *startp, *endp;
+ char *nstore = (char *) alloca (strlen (temp) + 3);
+
+ startp = endp = temp;
+ while (1)
+ {
+ if (*endp == PATH_SEPARATOR || *endp == 0)
+ {
+ strncpy (nstore, startp, endp - startp);
+ if (endp == startp)
+ strcpy (nstore, concat (".", dir_separator_str, NULL));
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
+ {
+ nstore[endp - startp] = DIR_SEPARATOR;
+ nstore[endp - startp + 1] = 0;
+ }
+ else
+ nstore[endp - startp] = 0;
+ add_prefix (&exec_prefixes, nstore, 0,
+ PREFIX_PRIORITY_LAST, 0, 0);
+ add_prefix (&include_prefixes, nstore, 0,
+ PREFIX_PRIORITY_LAST, 0, 0);
+ if (*endp == 0)
+ break;
+ endp = startp = endp + 1;
+ }
+ else
+ endp++;
+ }
+ }
+
+ temp = env.get (LIBRARY_PATH_ENV);
+ if (temp && *cross_compile == '0')
+ {
+ const char *startp, *endp;
+ char *nstore = (char *) alloca (strlen (temp) + 3);
+
+ startp = endp = temp;
+ while (1)
+ {
+ if (*endp == PATH_SEPARATOR || *endp == 0)
+ {
+ strncpy (nstore, startp, endp - startp);
+ if (endp == startp)
+ strcpy (nstore, concat (".", dir_separator_str, NULL));
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
+ {
+ nstore[endp - startp] = DIR_SEPARATOR;
+ nstore[endp - startp + 1] = 0;
+ }
+ else
+ nstore[endp - startp] = 0;
+ add_prefix (&startfile_prefixes, nstore, NULL,
+ PREFIX_PRIORITY_LAST, 0, 1);
+ if (*endp == 0)
+ break;
+ endp = startp = endp + 1;
+ }
+ else
+ endp++;
+ }
+ }
+
+ /* Use LPATH like LIBRARY_PATH (for the CMU build program). */
+ temp = env.get ("LPATH");
+ if (temp && *cross_compile == '0')
+ {
+ const char *startp, *endp;
+ char *nstore = (char *) alloca (strlen (temp) + 3);
+
+ startp = endp = temp;
+ while (1)
+ {
+ if (*endp == PATH_SEPARATOR || *endp == 0)
+ {
+ strncpy (nstore, startp, endp - startp);
+ if (endp == startp)
+ strcpy (nstore, concat (".", dir_separator_str, NULL));
+ else if (!IS_DIR_SEPARATOR (endp[-1]))
+ {
+ nstore[endp - startp] = DIR_SEPARATOR;
+ nstore[endp - startp + 1] = 0;
+ }
+ else
+ nstore[endp - startp] = 0;
+ add_prefix (&startfile_prefixes, nstore, NULL,
+ PREFIX_PRIORITY_LAST, 0, 1);
+ if (*endp == 0)
+ break;
+ endp = startp = endp + 1;
+ }
+ else
+ endp++;
+ }
+ }
+
+ /* Process the options and store input files and switches in their
+ vectors. */
+
+ last_language_n_infiles = -1;
+
+ set_option_handlers (&handlers);
+
+ for (j = 1; j < decoded_options_count; j++)
+ {
+ switch (decoded_options[j].opt_index)
+ {
+ case OPT_S:
+ case OPT_c:
+ case OPT_E:
+ have_c = 1;
+ break;
+ }
+ if (have_c)
+ break;
+ }
+
+ for (j = 1; j < decoded_options_count; j++)
+ {
+ if (decoded_options[j].opt_index == OPT_SPECIAL_input_file)
+ {
+ const char *arg = decoded_options[j].arg;
+
+#ifdef HAVE_TARGET_OBJECT_SUFFIX
+ arg = convert_filename (arg, 0, access (arg, F_OK));
+#endif
+ add_infile (arg, spec_lang);
+
+ continue;
+ }
+
+ read_cmdline_option (&global_options, &global_options_set,
+ decoded_options + j, UNKNOWN_LOCATION,
+ CL_DRIVER, &handlers, global_dc);
+ }
+
+ /* If the user didn't specify any, default to all configured offload
+ targets. */
+ if (ENABLE_OFFLOADING && offload_targets == NULL)
+ {
+ handle_foffload_option (OFFLOAD_TARGETS);
+#if OFFLOAD_DEFAULTED
+ offload_targets_default = true;
+#endif
+ }
+
+ /* Handle -gtoggle as it would later in toplev.cc:process_options to
+ make the debug-level-gt spec function work as expected. */
+ if (flag_gtoggle)
+ {
+ if (debug_info_level == DINFO_LEVEL_NONE)
+ debug_info_level = DINFO_LEVEL_NORMAL;
+ else
+ debug_info_level = DINFO_LEVEL_NONE;
+ }
+
+ if (output_file
+ && strcmp (output_file, "-") != 0
+ && strcmp (output_file, HOST_BIT_BUCKET) != 0)
+ {
+ int i;
+ for (i = 0; i < n_infiles; i++)
+ if ((!infiles[i].language || infiles[i].language[0] != '*')
+ && canonical_filename_eq (infiles[i].name, output_file))
+ fatal_error (input_location,
+ "input file %qs is the same as output file",
+ output_file);
+ }
+
+ if (output_file != NULL && output_file[0] == '\0')
+ fatal_error (input_location, "output filename may not be empty");
+
+ /* -dumpdir and -save-temps=* both specify the location of aux/dump
+ outputs; the one that appears last prevails. When compiling
+ multiple sources, an explicit dumpbase (minus -ext) may be
+ combined with an explicit or implicit dumpdir, whereas when
+ linking, a specified or implied link output name (minus
+ extension) may be combined with a prevailing -save-temps=* or an
+ otherwise implied dumpdir, but not override a prevailing
+ -dumpdir. Primary outputs (e.g., linker output when linking
+ without -o, or .i, .s or .o outputs when processing multiple
+ inputs with -E, -S or -c, respectively) are NOT affected by these
+ -save-temps=/-dump* options, always landing in the current
+ directory and with the same basename as the input when an output
+ name is not given, but when they're intermediate outputs, they
+ are named like other aux outputs, so the options affect their
+ location and name.
+
+ Here are some examples. There are several more in the
+ documentation of -o and -dump*, and some quite exhaustive tests
+ in gcc.misc-tests/outputs.exp.
+
+ When compiling any number of sources, no -dump* nor
+ -save-temps=*, all outputs in cwd without prefix:
+
+ # gcc -c b.c -gsplit-dwarf
+ -> cc1 [-dumpdir ./] -dumpbase b.c -dumpbase-ext .c # b.o b.dwo
+
+ # gcc -c b.c d.c -gsplit-dwarf
+ -> cc1 [-dumpdir ./] -dumpbase b.c -dumpbase-ext .c # b.o b.dwo
+ && cc1 [-dumpdir ./] -dumpbase d.c -dumpbase-ext .c # d.o d.dwo
+
+ When compiling and linking, no -dump* nor -save-temps=*, .o
+ outputs are temporary, aux outputs land in the dir of the output,
+ prefixed with the basename of the linker output:
+
+ # gcc b.c d.c -o ab -gsplit-dwarf
+ -> cc1 -dumpdir ab- -dumpbase b.c -dumpbase-ext .c # ab-b.dwo
+ && cc1 -dumpdir ab- -dumpbase d.c -dumpbase-ext .c # ab-d.dwo
+ && link ... -o ab
+
+ # gcc b.c d.c [-o a.out] -gsplit-dwarf
+ -> cc1 -dumpdir a- -dumpbase b.c -dumpbase-ext .c # a-b.dwo
+ && cc1 -dumpdir a- -dumpbase d.c -dumpbase-ext .c # a-d.dwo
+ && link ... [-o a.out]
+
+ When compiling and linking, a prevailing -dumpdir fully overrides
+ the prefix of aux outputs given by the output name:
+
+ # gcc -dumpdir f b.c d.c -gsplit-dwarf [-o [dir/]whatever]
+ -> cc1 -dumpdir f -dumpbase b.c -dumpbase-ext .c # fb.dwo
+ && cc1 -dumpdir f -dumpbase d.c -dumpbase-ext .c # fd.dwo
+ && link ... [-o whatever]
+
+ When compiling multiple inputs, an explicit -dumpbase is combined
+ with -dumpdir, affecting aux outputs, but not the .o outputs:
+
+ # gcc -dumpdir f -dumpbase g- b.c d.c -gsplit-dwarf -c
+ -> cc1 -dumpdir fg- -dumpbase b.c -dumpbase-ext .c # b.o fg-b.dwo
+ && cc1 -dumpdir fg- -dumpbase d.c -dumpbase-ext .c # d.o fg-d.dwo
+
+ When compiling and linking with -save-temps, the .o outputs that
+ would have been temporary become aux outputs, so they get
+ affected by -dump* flags:
+
+ # gcc -dumpdir f -dumpbase g- -save-temps b.c d.c
+ -> cc1 -dumpdir fg- -dumpbase b.c -dumpbase-ext .c # fg-b.o
+ && cc1 -dumpdir fg- -dumpbase d.c -dumpbase-ext .c # fg-d.o
+ && link
+
+ If -save-temps=* prevails over -dumpdir, however, the explicit
+ -dumpdir is discarded, as if it wasn't there. The basename of
+ the implicit linker output, a.out or a.exe, becomes a- as the aux
+ output prefix for all compilations:
+
+ # gcc [-dumpdir f] -save-temps=cwd b.c d.c
+ -> cc1 -dumpdir a- -dumpbase b.c -dumpbase-ext .c # a-b.o
+ && cc1 -dumpdir a- -dumpbase d.c -dumpbase-ext .c # a-d.o
+ && link
+
+ A single -dumpbase, applying to multiple inputs, overrides the
+ linker output name, implied or explicit, as the aux output prefix:
+
+ # gcc [-dumpdir f] -dumpbase g- -save-temps=cwd b.c d.c
+ -> cc1 -dumpdir g- -dumpbase b.c -dumpbase-ext .c # g-b.o
+ && cc1 -dumpdir g- -dumpbase d.c -dumpbase-ext .c # g-d.o
+ && link
+
+ # gcc [-dumpdir f] -dumpbase g- -save-temps=cwd b.c d.c -o dir/h.out
+ -> cc1 -dumpdir g- -dumpbase b.c -dumpbase-ext .c # g-b.o
+ && cc1 -dumpdir g- -dumpbase d.c -dumpbase-ext .c # g-d.o
+ && link -o dir/h.out
+
+ Now, if the linker output is NOT overridden as a prefix, but
+ -save-temps=* overrides implicit or explicit -dumpdir, the
+ effective dump dir combines the dir selected by the -save-temps=*
+ option with the basename of the specified or implied link output:
+
+ # gcc [-dumpdir f] -save-temps=cwd b.c d.c -o dir/h.out
+ -> cc1 -dumpdir h- -dumpbase b.c -dumpbase-ext .c # h-b.o
+ && cc1 -dumpdir h- -dumpbase d.c -dumpbase-ext .c # h-d.o
+ && link -o dir/h.out
+
+ # gcc [-dumpdir f] -save-temps=obj b.c d.c -o dir/h.out
+ -> cc1 -dumpdir dir/h- -dumpbase b.c -dumpbase-ext .c # dir/h-b.o
+ && cc1 -dumpdir dir/h- -dumpbase d.c -dumpbase-ext .c # dir/h-d.o
+ && link -o dir/h.out
+
+ But then again, a single -dumpbase applying to multiple inputs
+ gets used instead of the linker output basename in the combined
+ dumpdir:
+
+ # gcc [-dumpdir f] -dumpbase g- -save-temps=obj b.c d.c -o dir/h.out
+ -> cc1 -dumpdir dir/g- -dumpbase b.c -dumpbase-ext .c # dir/g-b.o
+ && cc1 -dumpdir dir/g- -dumpbase d.c -dumpbase-ext .c # dir/g-d.o
+ && link -o dir/h.out
+
+ With a single input being compiled, the output basename does NOT
+ affect the dumpdir prefix.
+
+ # gcc -save-temps=obj b.c -gsplit-dwarf -c -o dir/b.o
+ -> cc1 -dumpdir dir/ -dumpbase b.c -dumpbase-ext .c # dir/b.o dir/b.dwo
+
+ but when compiling and linking even a single file, it does:
+
+ # gcc -save-temps=obj b.c -o dir/h.out
+ -> cc1 -dumpdir dir/h- -dumpbase b.c -dumpbase-ext .c # dir/h-b.o
+
+ unless an explicit -dumpdir prevails:
+
+ # gcc -save-temps[=obj] -dumpdir g- b.c -o dir/h.out
+ -> cc1 -dumpdir g- -dumpbase b.c -dumpbase-ext .c # g-b.o
+
+ */
+
+ bool explicit_dumpdir = dumpdir;
+
+ if ((!save_temps_overrides_dumpdir && explicit_dumpdir)
+ || (output_file && not_actual_file_p (output_file)))
+ {
+ /* Do nothing. */
+ }
+
+ /* If -save-temps=obj and -o name, create the prefix to use for %b.
+ Otherwise just make -save-temps=obj the same as -save-temps=cwd. */
+ else if (save_temps_flag != SAVE_TEMPS_CWD && output_file != NULL)
+ {
+ free (dumpdir);
+ dumpdir = NULL;
+ temp = lbasename (output_file);
+ if (temp != output_file)
+ dumpdir = xstrndup (output_file,
+ strlen (output_file) - strlen (temp));
+ }
+ else if (dumpdir)
+ {
+ free (dumpdir);
+ dumpdir = NULL;
+ }
+
+ if (save_temps_flag)
+ save_temps_flag = SAVE_TEMPS_DUMP;
+
+ /* If there is any pathname component in an explicit -dumpbase, it
+ overrides dumpdir entirely, so discard it right away. Although
+ the presence of an explicit -dumpdir matters for the driver, it
+ shouldn't matter for other processes, that get all that's needed
+ from the -dumpdir and -dumpbase always passed to them. */
+ if (dumpdir && dumpbase && lbasename (dumpbase) != dumpbase)
+ {
+ free (dumpdir);
+ dumpdir = NULL;
+ }
+
+ /* Check that dumpbase_ext matches the end of dumpbase, drop it
+ otherwise. */
+ if (dumpbase_ext && dumpbase && *dumpbase)
+ {
+ int lendb = strlen (dumpbase);
+ int lendbx = strlen (dumpbase_ext);
+
+ /* -dumpbase-ext must be a suffix proper; discard it if it
+ matches all of -dumpbase, as that would make for an empty
+ basename. */
+ if (lendbx >= lendb
+ || strcmp (dumpbase + lendb - lendbx, dumpbase_ext) != 0)
+ {
+ free (dumpbase_ext);
+ dumpbase_ext = NULL;
+ }
+ }
+
+ /* -dumpbase with multiple sources goes into dumpdir. With a single
+ source, it does only if linking and if dumpdir was not explicitly
+ specified. */
+ if (dumpbase && *dumpbase
+ && (single_input_file_index () == -2
+ || (!have_c && !explicit_dumpdir)))
+ {
+ char *prefix;
+
+ if (dumpbase_ext)
+ /* We checked that they match above. */
+ dumpbase[strlen (dumpbase) - strlen (dumpbase_ext)] = '\0';
+
+ if (dumpdir)
+ prefix = concat (dumpdir, dumpbase, "-", NULL);
+ else
+ prefix = concat (dumpbase, "-", NULL);
+
+ free (dumpdir);
+ free (dumpbase);
+ free (dumpbase_ext);
+ dumpbase = dumpbase_ext = NULL;
+ dumpdir = prefix;
+ dumpdir_trailing_dash_added = true;
+ }
+
+ /* If dumpbase was not brought into dumpdir but we're linking, bring
+ output_file into dumpdir unless dumpdir was explicitly specified.
+ The test for !explicit_dumpdir is further below, because we want
+ to use the obase computation for a ghost outbase, passed to
+ GCC_COLLECT_OPTIONS. */
+ else if (!have_c && (!explicit_dumpdir || (dumpbase && !*dumpbase)))
+ {
+ /* If we get here, we know dumpbase was not specified, or it was
+ specified as an empty string. If it was anything else, it
+ would have combined with dumpdir above, because the condition
+ for dumpbase to be used when present is broader than the
+ condition that gets us here. */
+ gcc_assert (!dumpbase || !*dumpbase);
+
+ const char *obase;
+ char *tofree = NULL;
+ if (!output_file || not_actual_file_p (output_file))
+ obase = "a";
+ else
+ {
+ obase = lbasename (output_file);
+ size_t blen = strlen (obase), xlen;
+ /* Drop the suffix if it's dumpbase_ext, if given,
+ otherwise .exe or the target executable suffix, or if the
+ output was explicitly named a.out, but not otherwise. */
+ if (dumpbase_ext
+ ? (blen > (xlen = strlen (dumpbase_ext))
+ && strcmp ((temp = (obase + blen - xlen)),
+ dumpbase_ext) == 0)
+ : ((temp = strrchr (obase + 1, '.'))
+ && (xlen = strlen (temp))
+ && (strcmp (temp, ".exe") == 0
+#if defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
+ || strcmp (temp, TARGET_EXECUTABLE_SUFFIX) == 0
+#endif
+ || strcmp (obase, "a.out") == 0)))
+ {
+ tofree = xstrndup (obase, blen - xlen);
+ obase = tofree;
+ }
+ }
+
+ /* We wish to save this basename to the -dumpdir passed through
+ GCC_COLLECT_OPTIONS within maybe_run_linker, for e.g. LTO,
+ but we do NOT wish to add it to e.g. %b, so we keep
+ outbase_length as zero. */
+ gcc_assert (!outbase);
+ outbase_length = 0;
+
+ /* If we're building [dir1/]foo[.exe] out of a single input
+ [dir2/]foo.c that shares the same basename, dump to
+ [dir2/]foo.c.* rather than duplicating the basename into
+ [dir2/]foo-foo.c.*. */
+ int idxin;
+ if (dumpbase
+ || ((idxin = single_input_file_index ()) >= 0
+ && adds_single_suffix_p (lbasename (infiles[idxin].name),
+ obase)))
+ {
+ if (obase == tofree)
+ outbase = tofree;
+ else
+ {
+ outbase = xstrdup (obase);
+ free (tofree);
+ }
+ obase = tofree = NULL;
+ }
+ else
+ {
+ if (dumpdir)
+ {
+ char *p = concat (dumpdir, obase, "-", NULL);
+ free (dumpdir);
+ dumpdir = p;
+ }
+ else
+ dumpdir = concat (obase, "-", NULL);
+
+ dumpdir_trailing_dash_added = true;
+
+ free (tofree);
+ obase = tofree = NULL;
+ }
+
+ if (!explicit_dumpdir || dumpbase)
+ {
+ /* Absent -dumpbase and present -dumpbase-ext have been applied
+ to the linker output name, so compute fresh defaults for each
+ compilation. */
+ free (dumpbase_ext);
+ dumpbase_ext = NULL;
+ }
+ }
+
+ /* Now, if we're compiling, or if we haven't used the dumpbase
+ above, then outbase (%B) is derived from dumpbase, if given, or
+ from the output name, given or implied. We can't precompute
+ implied output names, but that's ok, since they're derived from
+ input names. Just make sure we skip this if dumpbase is the
+ empty string: we want to use input names then, so don't set
+ outbase. */
+ if ((dumpbase || have_c)
+ && !(dumpbase && !*dumpbase))
+ {
+ gcc_assert (!outbase);
+
+ if (dumpbase)
+ {
+ gcc_assert (single_input_file_index () != -2);
+ /* We do not want lbasename here; dumpbase with dirnames
+ overrides dumpdir entirely, even if dumpdir is
+ specified. */
+ if (dumpbase_ext)
+ /* We've already checked above that the suffix matches. */
+ outbase = xstrndup (dumpbase,
+ strlen (dumpbase) - strlen (dumpbase_ext));
+ else
+ outbase = xstrdup (dumpbase);
+ }
+ else if (output_file && !not_actual_file_p (output_file))
+ {
+ outbase = xstrdup (lbasename (output_file));
+ char *p = strrchr (outbase + 1, '.');
+ if (p)
+ *p = '\0';
+ }
+
+ if (outbase)
+ outbase_length = strlen (outbase);
+ }
+
+ /* If there is any pathname component in an explicit -dumpbase, do
+ not use dumpdir, but retain it to pass it on to the compiler. */
+ if (dumpdir)
+ dumpdir_length = strlen (dumpdir);
+ else
+ dumpdir_length = 0;
+
+ /* Check that dumpbase_ext, if still present, still matches the end
+ of dumpbase, if present, and drop it otherwise. We only retained
+ it above when dumpbase was absent to maybe use it to drop the
+ extension from output_name before combining it with dumpdir. We
+ won't deal with -dumpbase-ext when -dumpbase is not explicitly
+ given, even if just to activate backward-compatible dumpbase:
+ dropping it on the floor is correct, expected and documented
+ behavior. Attempting to deal with a -dumpbase-ext that might
+ match the end of some input filename, or of the combination of
+ the output basename with the suffix of the input filename,
+ possible with an intermediate .gk extension for -fcompare-debug,
+ is just calling for trouble. */
+ if (dumpbase_ext)
+ {
+ if (!dumpbase || !*dumpbase)
+ {
+ free (dumpbase_ext);
+ dumpbase_ext = NULL;
+ }
+ else
+ gcc_assert (strcmp (dumpbase + strlen (dumpbase)
+ - strlen (dumpbase_ext), dumpbase_ext) == 0);
+ }
+
+ if (save_temps_flag && use_pipes)
+ {
+ /* -save-temps overrides -pipe, so that temp files are produced */
+ if (save_temps_flag)
+ warning (0, "%<-pipe%> ignored because %<-save-temps%> specified");
+ use_pipes = 0;
+ }
+
+ if (!compare_debug)
+ {
+ const char *gcd = env.get ("GCC_COMPARE_DEBUG");
+
+ if (gcd && gcd[0] == '-')
+ {
+ compare_debug = 2;
+ compare_debug_opt = gcd;
+ }
+ else if (gcd && *gcd && strcmp (gcd, "0"))
+ {
+ compare_debug = 3;
+ compare_debug_opt = "-gtoggle";
+ }
+ }
+ else if (compare_debug < 0)
+ {
+ compare_debug = 0;
+ gcc_assert (!compare_debug_opt);
+ }
+
+ /* Set up the search paths. We add directories that we expect to
+ contain GNU Toolchain components before directories specified by
+ the machine description so that we will find GNU components (like
+ the GNU assembler) before those of the host system. */
+
+ /* If we don't know where the toolchain has been installed, use the
+ configured-in locations. */
+ if (!gcc_exec_prefix)
+ {
+#ifndef OS2
+ add_prefix (&exec_prefixes, standard_libexec_prefix, "GCC",
+ PREFIX_PRIORITY_LAST, 1, 0);
+ add_prefix (&exec_prefixes, standard_libexec_prefix, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 2, 0);
+ add_prefix (&exec_prefixes, standard_exec_prefix, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 2, 0);
+#endif
+ add_prefix (&startfile_prefixes, standard_exec_prefix, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 1, 0);
+ }
+
+ gcc_assert (!IS_ABSOLUTE_PATH (tooldir_base_prefix));
+ tooldir_prefix2 = concat (tooldir_base_prefix, spec_machine,
+ dir_separator_str, NULL);
+
+ /* Look for tools relative to the location from which the driver is
+ running, or, if that is not available, the configured prefix. */
+ tooldir_prefix
+ = concat (gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
+ spec_host_machine, dir_separator_str, spec_version,
+ accel_dir_suffix, dir_separator_str, tooldir_prefix2, NULL);
+ free (tooldir_prefix2);
+
+ add_prefix (&exec_prefixes,
+ concat (tooldir_prefix, "bin", dir_separator_str, NULL),
+ "BINUTILS", PREFIX_PRIORITY_LAST, 0, 0);
+ add_prefix (&startfile_prefixes,
+ concat (tooldir_prefix, "lib", dir_separator_str, NULL),
+ "BINUTILS", PREFIX_PRIORITY_LAST, 0, 1);
+ free (tooldir_prefix);
+
+#if defined(TARGET_SYSTEM_ROOT_RELOCATABLE) && !defined(VMS)
+ /* If the normal TARGET_SYSTEM_ROOT is inside of $exec_prefix,
+ then consider it to relocate with the rest of the GCC installation
+ if GCC_EXEC_PREFIX is set.
+ ``make_relative_prefix'' is not compiled for VMS, so don't call it. */
+ if (target_system_root && !target_system_root_changed && gcc_exec_prefix)
+ {
+ char *tmp_prefix = get_relative_prefix (decoded_options[0].arg,
+ standard_bindir_prefix,
+ target_system_root);
+ if (tmp_prefix && access_check (tmp_prefix, F_OK) == 0)
+ {
+ target_system_root = tmp_prefix;
+ target_system_root_changed = 1;
+ }
+ }
+#endif
+
+ /* More prefixes are enabled in main, after we read the specs file
+ and determine whether this is cross-compilation or not. */
+
+ if (n_infiles != 0 && n_infiles == last_language_n_infiles && spec_lang != 0)
+ warning (0, "%<-x %s%> after last input file has no effect", spec_lang);
+
+ /* Synthesize -fcompare-debug flag from the GCC_COMPARE_DEBUG
+ environment variable. */
+ if (compare_debug == 2 || compare_debug == 3)
+ {
+ const char *opt = concat ("-fcompare-debug=", compare_debug_opt, NULL);
+ save_switch (opt, 0, NULL, false, true);
+ compare_debug = 1;
+ }
+
+ /* Ensure we only invoke each subprocess once. */
+ if (n_infiles == 0
+ && (print_subprocess_help || print_help_list || print_version))
+ {
+ /* Create a dummy input file, so that we can pass
+ the help option on to the various sub-processes. */
+ add_infile ("help-dummy", "c");
+ }
+
+ /* Decide if undefined variable references are allowed in specs. */
+
+ /* -v alone is safe. --version and --help alone or together are safe. Note
+ that -v would make them unsafe, as they'd then be run for subprocesses as
+ well, the location of which might depend on variables possibly coming
+ from self-specs. Note also that the command name is counted in
+ decoded_options_count. */
+
+ unsigned help_version_count = 0;
+
+ if (print_version)
+ help_version_count++;
+
+ if (print_help_list)
+ help_version_count++;
+
+ spec_undefvar_allowed =
+ ((verbose_flag && decoded_options_count == 2)
+ || help_version_count == decoded_options_count - 1);
+
+ alloc_switch ();
+ switches[n_switches].part1 = 0;
+ alloc_infile ();
+ infiles[n_infiles].name = 0;
+}
+
+/* Store switches not filtered out by %<S in spec in COLLECT_GCC_OPTIONS
+ and place that in the environment. */
+
+static void
+set_collect_gcc_options (void)
+{
+ int i;
+ int first_time;
+
+ /* Build COLLECT_GCC_OPTIONS to have all of the options specified to
+ the compiler. */
+ obstack_grow (&collect_obstack, "COLLECT_GCC_OPTIONS=",
+ sizeof ("COLLECT_GCC_OPTIONS=") - 1);
+
+ first_time = TRUE;
+ for (i = 0; (int) i < n_switches; i++)
+ {
+ const char *const *args;
+ const char *p, *q;
+ if (!first_time)
+ obstack_grow (&collect_obstack, " ", 1);
+
+ first_time = FALSE;
+
+ /* Ignore elided switches. */
+ if ((switches[i].live_cond
+ & (SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC))
+ == SWITCH_IGNORE)
+ continue;
+
+ obstack_grow (&collect_obstack, "'-", 2);
+ q = switches[i].part1;
+ while ((p = strchr (q, '\'')))
+ {
+ obstack_grow (&collect_obstack, q, p - q);
+ obstack_grow (&collect_obstack, "'\\''", 4);
+ q = ++p;
+ }
+ obstack_grow (&collect_obstack, q, strlen (q));
+ obstack_grow (&collect_obstack, "'", 1);
+
+ for (args = switches[i].args; args && *args; args++)
+ {
+ obstack_grow (&collect_obstack, " '", 2);
+ q = *args;
+ while ((p = strchr (q, '\'')))
+ {
+ obstack_grow (&collect_obstack, q, p - q);
+ obstack_grow (&collect_obstack, "'\\''", 4);
+ q = ++p;
+ }
+ obstack_grow (&collect_obstack, q, strlen (q));
+ obstack_grow (&collect_obstack, "'", 1);
+ }
+ }
+
+ if (dumpdir)
+ {
+ if (!first_time)
+ obstack_grow (&collect_obstack, " ", 1);
+ first_time = FALSE;
+
+ obstack_grow (&collect_obstack, "'-dumpdir' '", 12);
+ const char *p, *q;
+
+ q = dumpdir;
+ while ((p = strchr (q, '\'')))
+ {
+ obstack_grow (&collect_obstack, q, p - q);
+ obstack_grow (&collect_obstack, "'\\''", 4);
+ q = ++p;
+ }
+ obstack_grow (&collect_obstack, q, strlen (q));
+
+ obstack_grow (&collect_obstack, "'", 1);
+ }
+
+ obstack_grow (&collect_obstack, "\0", 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+}
+
+/* Process a spec string, accumulating and running commands. */
+
+/* These variables describe the input file name.
+ input_file_number is the index on outfiles of this file,
+ so that the output file name can be stored for later use by %o.
+ input_basename is the start of the part of the input file
+ sans all directory names, and basename_length is the number
+ of characters starting there excluding the suffix .c or whatever. */
+
+static const char *gcc_input_filename;
+static int input_file_number;
+size_t input_filename_length;
+static int basename_length;
+static int suffixed_basename_length;
+static const char *input_basename;
+static const char *input_suffix;
+#ifndef HOST_LACKS_INODE_NUMBERS
+static struct stat input_stat;
+#endif
+static int input_stat_set;
+
+/* The compiler used to process the current input file. */
+static struct compiler *input_file_compiler;
+
+/* These are variables used within do_spec and do_spec_1. */
+
+/* Nonzero if an arg has been started and not yet terminated
+ (with space, tab or newline). */
+static int arg_going;
+
+/* Nonzero means %d or %g has been seen; the next arg to be terminated
+ is a temporary file name. */
+static int delete_this_arg;
+
+/* Nonzero means %w has been seen; the next arg to be terminated
+ is the output file name of this compilation. */
+static int this_is_output_file;
+
+/* Nonzero means %s has been seen; the next arg to be terminated
+ is the name of a library file and we should try the standard
+ search dirs for it. */
+static int this_is_library_file;
+
+/* Nonzero means %T has been seen; the next arg to be terminated
+ is the name of a linker script and we should try all of the
+ standard search dirs for it. If it is found insert a --script
+ command line switch and then substitute the full path in place,
+ otherwise generate an error message. */
+static int this_is_linker_script;
+
+/* Nonzero means that the input of this command is coming from a pipe. */
+static int input_from_pipe;
+
+/* Nonnull means substitute this for any suffix when outputting a switches
+ arguments. */
+static const char *suffix_subst;
+
+/* If there is an argument being accumulated, terminate it and store it. */
+
+static void
+end_going_arg (void)
+{
+ if (arg_going)
+ {
+ const char *string;
+
+ obstack_1grow (&obstack, 0);
+ string = XOBFINISH (&obstack, const char *);
+ if (this_is_library_file)
+ string = find_file (string);
+ if (this_is_linker_script)
+ {
+ char * full_script_path = find_a_file (&startfile_prefixes, string, R_OK, true);
+
+ if (full_script_path == NULL)
+ {
+ error ("unable to locate default linker script %qs in the library search paths", string);
+ /* Script was not found on search path. */
+ return;
+ }
+ store_arg ("--script", false, false);
+ string = full_script_path;
+ }
+ store_arg (string, delete_this_arg, this_is_output_file);
+ if (this_is_output_file)
+ outfiles[input_file_number] = string;
+ arg_going = 0;
+ }
+}
+
+
+/* Parse the WRAPPER string which is a comma separated list of the command line
+ and insert them into the beginning of argbuf. */
+
+static void
+insert_wrapper (const char *wrapper)
+{
+ int n = 0;
+ int i;
+ char *buf = xstrdup (wrapper);
+ char *p = buf;
+ unsigned int old_length = argbuf.length ();
+
+ do
+ {
+ n++;
+ while (*p == ',')
+ p++;
+ }
+ while ((p = strchr (p, ',')) != NULL);
+
+ argbuf.safe_grow (old_length + n, true);
+ memmove (argbuf.address () + n,
+ argbuf.address (),
+ old_length * sizeof (const_char_p));
+
+ i = 0;
+ p = buf;
+ do
+ {
+ while (*p == ',')
+ {
+ *p = 0;
+ p++;
+ }
+ argbuf[i] = p;
+ i++;
+ }
+ while ((p = strchr (p, ',')) != NULL);
+ gcc_assert (i == n);
+}
+
+/* Process the spec SPEC and run the commands specified therein.
+ Returns 0 if the spec is successfully processed; -1 if failed. */
+
+int
+do_spec (const char *spec)
+{
+ int value;
+
+ value = do_spec_2 (spec, NULL);
+
+ /* Force out any unfinished command.
+ If -pipe, this forces out the last command if it ended in `|'. */
+ if (value == 0)
+ {
+ if (argbuf.length () > 0
+ && !strcmp (argbuf.last (), "|"))
+ argbuf.pop ();
+
+ set_collect_gcc_options ();
+
+ if (argbuf.length () > 0)
+ value = execute ();
+ }
+
+ return value;
+}
+
+/* Process the spec SPEC, with SOFT_MATCHED_PART designating the current value
+ of a matched * pattern which may be re-injected by way of %*. */
+
+static int
+do_spec_2 (const char *spec, const char *soft_matched_part)
+{
+ int result;
+
+ clear_args ();
+ arg_going = 0;
+ delete_this_arg = 0;
+ this_is_output_file = 0;
+ this_is_library_file = 0;
+ this_is_linker_script = 0;
+ input_from_pipe = 0;
+ suffix_subst = NULL;
+
+ result = do_spec_1 (spec, 0, soft_matched_part);
+
+ end_going_arg ();
+
+ return result;
+}
+
+/* Process the given spec string and add any new options to the end
+ of the switches/n_switches array. */
+
+static void
+do_option_spec (const char *name, const char *spec)
+{
+ unsigned int i, value_count, value_len;
+ const char *p, *q, *value;
+ char *tmp_spec, *tmp_spec_p;
+
+ if (configure_default_options[0].name == NULL)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
+ if (strcmp (configure_default_options[i].name, name) == 0)
+ break;
+ if (i == ARRAY_SIZE (configure_default_options))
+ return;
+
+ value = configure_default_options[i].value;
+ value_len = strlen (value);
+
+ /* Compute the size of the final spec. */
+ value_count = 0;
+ p = spec;
+ while ((p = strstr (p, "%(VALUE)")) != NULL)
+ {
+ p ++;
+ value_count ++;
+ }
+
+ /* Replace each %(VALUE) by the specified value. */
+ tmp_spec = (char *) alloca (strlen (spec) + 1
+ + value_count * (value_len - strlen ("%(VALUE)")));
+ tmp_spec_p = tmp_spec;
+ q = spec;
+ while ((p = strstr (q, "%(VALUE)")) != NULL)
+ {
+ memcpy (tmp_spec_p, q, p - q);
+ tmp_spec_p = tmp_spec_p + (p - q);
+ memcpy (tmp_spec_p, value, value_len);
+ tmp_spec_p += value_len;
+ q = p + strlen ("%(VALUE)");
+ }
+ strcpy (tmp_spec_p, q);
+
+ do_self_spec (tmp_spec);
+}
+
+/* Process the given spec string and add any new options to the end
+ of the switches/n_switches array. */
+
+static void
+do_self_spec (const char *spec)
+{
+ int i;
+
+ do_spec_2 (spec, NULL);
+ do_spec_1 (" ", 0, NULL);
+
+ /* Mark %<S switches processed by do_self_spec to be ignored permanently.
+ do_self_specs adds the replacements to switches array, so it shouldn't
+ be processed afterwards. */
+ for (i = 0; i < n_switches; i++)
+ if ((switches[i].live_cond & SWITCH_IGNORE))
+ switches[i].live_cond |= SWITCH_IGNORE_PERMANENTLY;
+
+ if (argbuf.length () > 0)
+ {
+ const char **argbuf_copy;
+ struct cl_decoded_option *decoded_options;
+ struct cl_option_handlers handlers;
+ unsigned int decoded_options_count;
+ unsigned int j;
+
+ /* Create a copy of argbuf with a dummy argv[0] entry for
+ decode_cmdline_options_to_array. */
+ argbuf_copy = XNEWVEC (const char *,
+ argbuf.length () + 1);
+ argbuf_copy[0] = "";
+ memcpy (argbuf_copy + 1, argbuf.address (),
+ argbuf.length () * sizeof (const char *));
+
+ decode_cmdline_options_to_array (argbuf.length () + 1,
+ argbuf_copy,
+ CL_DRIVER, &decoded_options,
+ &decoded_options_count);
+ free (argbuf_copy);
+
+ set_option_handlers (&handlers);
+
+ for (j = 1; j < decoded_options_count; j++)
+ {
+ switch (decoded_options[j].opt_index)
+ {
+ case OPT_SPECIAL_input_file:
+ /* Specs should only generate options, not input
+ files. */
+ if (strcmp (decoded_options[j].arg, "-") != 0)
+ fatal_error (input_location,
+ "switch %qs does not start with %<-%>",
+ decoded_options[j].arg);
+ else
+ fatal_error (input_location,
+ "spec-generated switch is just %<-%>");
+ break;
+
+ case OPT_fcompare_debug_second:
+ case OPT_fcompare_debug:
+ case OPT_fcompare_debug_:
+ case OPT_o:
+ /* Avoid duplicate processing of some options from
+ compare-debug specs; just save them here. */
+ save_switch (decoded_options[j].canonical_option[0],
+ (decoded_options[j].canonical_option_num_elements
+ - 1),
+ &decoded_options[j].canonical_option[1], false, true);
+ break;
+
+ default:
+ read_cmdline_option (&global_options, &global_options_set,
+ decoded_options + j, UNKNOWN_LOCATION,
+ CL_DRIVER, &handlers, global_dc);
+ break;
+ }
+ }
+
+ free (decoded_options);
+
+ alloc_switch ();
+ switches[n_switches].part1 = 0;
+ }
+}
+
+/* Callback for processing %D and %I specs. */
+
+struct spec_path_info {
+ const char *option;
+ const char *append;
+ size_t append_len;
+ bool omit_relative;
+ bool separate_options;
+};
+
+static void *
+spec_path (char *path, void *data)
+{
+ struct spec_path_info *info = (struct spec_path_info *) data;
+ size_t len = 0;
+ char save = 0;
+
+ if (info->omit_relative && !IS_ABSOLUTE_PATH (path))
+ return NULL;
+
+ if (info->append_len != 0)
+ {
+ len = strlen (path);
+ memcpy (path + len, info->append, info->append_len + 1);
+ }
+
+ if (!is_directory (path, true))
+ return NULL;
+
+ do_spec_1 (info->option, 1, NULL);
+ if (info->separate_options)
+ do_spec_1 (" ", 0, NULL);
+
+ if (info->append_len == 0)
+ {
+ len = strlen (path);
+ save = path[len - 1];
+ if (IS_DIR_SEPARATOR (path[len - 1]))
+ path[len - 1] = '\0';
+ }
+
+ do_spec_1 (path, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+
+ /* Must not damage the original path. */
+ if (info->append_len == 0)
+ path[len - 1] = save;
+
+ return NULL;
+}
+
+/* True if we should compile INFILE. */
+
+static bool
+compile_input_file_p (struct infile *infile)
+{
+ if ((!infile->language) || (infile->language[0] != '*'))
+ if (infile->incompiler == input_file_compiler)
+ return true;
+ return false;
+}
+
+/* Process each member of VEC as a spec. */
+
+static void
+do_specs_vec (vec<char_p> vec)
+{
+ for (char *opt : vec)
+ {
+ do_spec_1 (opt, 1, NULL);
+ /* Make each accumulated option a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ }
+}
+
+/* Add options passed via -Xassembler or -Wa to COLLECT_AS_OPTIONS. */
+
+static void
+putenv_COLLECT_AS_OPTIONS (vec<char_p> vec)
+{
+ if (vec.is_empty ())
+ return;
+
+ obstack_init (&collect_obstack);
+ obstack_grow (&collect_obstack, "COLLECT_AS_OPTIONS=",
+ strlen ("COLLECT_AS_OPTIONS="));
+
+ char *opt;
+ unsigned ix;
+
+ FOR_EACH_VEC_ELT (vec, ix, opt)
+ {
+ obstack_1grow (&collect_obstack, '\'');
+ obstack_grow (&collect_obstack, opt, strlen (opt));
+ obstack_1grow (&collect_obstack, '\'');
+ if (ix < vec.length () - 1)
+ obstack_1grow(&collect_obstack, ' ');
+ }
+
+ obstack_1grow (&collect_obstack, '\0');
+ xputenv (XOBFINISH (&collect_obstack, char *));
+}
+
+/* Process the sub-spec SPEC as a portion of a larger spec.
+ This is like processing a whole spec except that we do
+ not initialize at the beginning and we do not supply a
+ newline by default at the end.
+ INSWITCH nonzero means don't process %-sequences in SPEC;
+ in this case, % is treated as an ordinary character.
+ This is used while substituting switches.
+ INSWITCH nonzero also causes SPC not to terminate an argument.
+
+ Value is zero unless a line was finished
+ and the command on that line reported an error. */
+
+static int
+do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
+{
+ const char *p = spec;
+ int c;
+ int i;
+ int value;
+
+ /* If it's an empty string argument to a switch, keep it as is. */
+ if (inswitch && !*p)
+ arg_going = 1;
+
+ while ((c = *p++))
+ /* If substituting a switch, treat all chars like letters.
+ Otherwise, NL, SPC, TAB and % are special. */
+ switch (inswitch ? 'a' : c)
+ {
+ case '\n':
+ end_going_arg ();
+
+ if (argbuf.length () > 0
+ && !strcmp (argbuf.last (), "|"))
+ {
+ /* A `|' before the newline means use a pipe here,
+ but only if -pipe was specified.
+ Otherwise, execute now and don't pass the `|' as an arg. */
+ if (use_pipes)
+ {
+ input_from_pipe = 1;
+ break;
+ }
+ else
+ argbuf.pop ();
+ }
+
+ set_collect_gcc_options ();
+
+ if (argbuf.length () > 0)
+ {
+ value = execute ();
+ if (value)
+ return value;
+ }
+ /* Reinitialize for a new command, and for a new argument. */
+ clear_args ();
+ arg_going = 0;
+ delete_this_arg = 0;
+ this_is_output_file = 0;
+ this_is_library_file = 0;
+ this_is_linker_script = 0;
+ input_from_pipe = 0;
+ break;
+
+ case '|':
+ end_going_arg ();
+
+ /* Use pipe */
+ obstack_1grow (&obstack, c);
+ arg_going = 1;
+ break;
+
+ case '\t':
+ case ' ':
+ end_going_arg ();
+
+ /* Reinitialize for a new argument. */
+ delete_this_arg = 0;
+ this_is_output_file = 0;
+ this_is_library_file = 0;
+ this_is_linker_script = 0;
+ break;
+
+ case '%':
+ switch (c = *p++)
+ {
+ case 0:
+ fatal_error (input_location, "spec %qs invalid", spec);
+
+ case 'b':
+ /* Don't use %b in the linker command. */
+ gcc_assert (suffixed_basename_length);
+ if (!this_is_output_file && dumpdir_length)
+ obstack_grow (&obstack, dumpdir, dumpdir_length);
+ if (this_is_output_file || !outbase_length)
+ obstack_grow (&obstack, input_basename, basename_length);
+ else
+ obstack_grow (&obstack, outbase, outbase_length);
+ if (compare_debug < 0)
+ obstack_grow (&obstack, ".gk", 3);
+ arg_going = 1;
+ break;
+
+ case 'B':
+ /* Don't use %B in the linker command. */
+ gcc_assert (suffixed_basename_length);
+ if (!this_is_output_file && dumpdir_length)
+ obstack_grow (&obstack, dumpdir, dumpdir_length);
+ if (this_is_output_file || !outbase_length)
+ obstack_grow (&obstack, input_basename, basename_length);
+ else
+ obstack_grow (&obstack, outbase, outbase_length);
+ if (compare_debug < 0)
+ obstack_grow (&obstack, ".gk", 3);
+ obstack_grow (&obstack, input_basename + basename_length,
+ suffixed_basename_length - basename_length);
+
+ arg_going = 1;
+ break;
+
+ case 'd':
+ delete_this_arg = 2;
+ break;
+
+ /* Dump out the directories specified with LIBRARY_PATH,
+ followed by the absolute directories
+ that we search for startfiles. */
+ case 'D':
+ {
+ struct spec_path_info info;
+
+ info.option = "-L";
+ info.append_len = 0;
+#ifdef RELATIVE_PREFIX_NOT_LINKDIR
+ /* Used on systems which record the specified -L dirs
+ and use them to search for dynamic linking.
+ Relative directories always come from -B,
+ and it is better not to use them for searching
+ at run time. In particular, stage1 loses. */
+ info.omit_relative = true;
+#else
+ info.omit_relative = false;
+#endif
+ info.separate_options = false;
+
+ for_each_path (&startfile_prefixes, true, 0, spec_path, &info);
+ }
+ break;
+
+ case 'e':
+ /* %efoo means report an error with `foo' as error message
+ and don't execute any more commands for this file. */
+ {
+ const char *q = p;
+ char *buf;
+ while (*p != 0 && *p != '\n')
+ p++;
+ buf = (char *) alloca (p - q + 1);
+ strncpy (buf, q, p - q);
+ buf[p - q] = 0;
+ error ("%s", _(buf));
+ return -1;
+ }
+ break;
+ case 'n':
+ /* %nfoo means report a notice with `foo' on stderr. */
+ {
+ const char *q = p;
+ char *buf;
+ while (*p != 0 && *p != '\n')
+ p++;
+ buf = (char *) alloca (p - q + 1);
+ strncpy (buf, q, p - q);
+ buf[p - q] = 0;
+ inform (UNKNOWN_LOCATION, "%s", _(buf));
+ if (*p)
+ p++;
+ }
+ break;
+
+ case 'j':
+ {
+ struct stat st;
+
+ /* If save_temps_flag is off, and the HOST_BIT_BUCKET is
+ defined, and it is not a directory, and it is
+ writable, use it. Otherwise, treat this like any
+ other temporary file. */
+
+ if ((!save_temps_flag)
+ && (stat (HOST_BIT_BUCKET, &st) == 0) && (!S_ISDIR (st.st_mode))
+ && (access (HOST_BIT_BUCKET, W_OK) == 0))
+ {
+ obstack_grow (&obstack, HOST_BIT_BUCKET,
+ strlen (HOST_BIT_BUCKET));
+ delete_this_arg = 0;
+ arg_going = 1;
+ break;
+ }
+ }
+ goto create_temp_file;
+ case '|':
+ if (use_pipes)
+ {
+ obstack_1grow (&obstack, '-');
+ delete_this_arg = 0;
+ arg_going = 1;
+
+ /* consume suffix */
+ while (*p == '.' || ISALNUM ((unsigned char) *p))
+ p++;
+ if (p[0] == '%' && p[1] == 'O')
+ p += 2;
+
+ break;
+ }
+ goto create_temp_file;
+ case 'm':
+ if (use_pipes)
+ {
+ /* consume suffix */
+ while (*p == '.' || ISALNUM ((unsigned char) *p))
+ p++;
+ if (p[0] == '%' && p[1] == 'O')
+ p += 2;
+
+ break;
+ }
+ goto create_temp_file;
+ case 'g':
+ case 'u':
+ case 'U':
+ create_temp_file:
+ {
+ struct temp_name *t;
+ int suffix_length;
+ const char *suffix = p;
+ char *saved_suffix = NULL;
+
+ while (*p == '.' || ISALNUM ((unsigned char) *p))
+ p++;
+ suffix_length = p - suffix;
+ if (p[0] == '%' && p[1] == 'O')
+ {
+ p += 2;
+ /* We don't support extra suffix characters after %O. */
+ if (*p == '.' || ISALNUM ((unsigned char) *p))
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%0%c%>", spec, *p);
+ if (suffix_length == 0)
+ suffix = TARGET_OBJECT_SUFFIX;
+ else
+ {
+ saved_suffix
+ = XNEWVEC (char, suffix_length
+ + strlen (TARGET_OBJECT_SUFFIX) + 1);
+ strncpy (saved_suffix, suffix, suffix_length);
+ strcpy (saved_suffix + suffix_length,
+ TARGET_OBJECT_SUFFIX);
+ }
+ suffix_length += strlen (TARGET_OBJECT_SUFFIX);
+ }
+
+ if (compare_debug < 0)
+ {
+ suffix = concat (".gk", suffix, NULL);
+ suffix_length += 3;
+ }
+
+ /* If -save-temps was specified, use that for the
+ temp file. */
+ if (save_temps_flag)
+ {
+ char *tmp;
+ bool adjusted_suffix = false;
+ if (suffix_length
+ && !outbase_length && !basename_length
+ && !dumpdir_trailing_dash_added)
+ {
+ adjusted_suffix = true;
+ suffix++;
+ suffix_length--;
+ }
+ temp_filename_length
+ = dumpdir_length + suffix_length + 1;
+ if (outbase_length)
+ temp_filename_length += outbase_length;
+ else
+ temp_filename_length += basename_length;
+ tmp = (char *) alloca (temp_filename_length);
+ if (dumpdir_length)
+ memcpy (tmp, dumpdir, dumpdir_length);
+ if (outbase_length)
+ memcpy (tmp + dumpdir_length, outbase,
+ outbase_length);
+ else if (basename_length)
+ memcpy (tmp + dumpdir_length, input_basename,
+ basename_length);
+ memcpy (tmp + temp_filename_length - suffix_length - 1,
+ suffix, suffix_length);
+ if (adjusted_suffix)
+ {
+ adjusted_suffix = false;
+ suffix--;
+ suffix_length++;
+ }
+ tmp[temp_filename_length - 1] = '\0';
+ temp_filename = tmp;
+
+ if (filename_cmp (temp_filename, gcc_input_filename) != 0)
+ {
+#ifndef HOST_LACKS_INODE_NUMBERS
+ struct stat st_temp;
+
+ /* Note, set_input() resets input_stat_set to 0. */
+ if (input_stat_set == 0)
+ {
+ input_stat_set = stat (gcc_input_filename,
+ &input_stat);
+ if (input_stat_set >= 0)
+ input_stat_set = 1;
+ }
+
+ /* If we have the stat for the gcc_input_filename
+ and we can do the stat for the temp_filename
+ then the they could still refer to the same
+ file if st_dev/st_ino's are the same. */
+ if (input_stat_set != 1
+ || stat (temp_filename, &st_temp) < 0
+ || input_stat.st_dev != st_temp.st_dev
+ || input_stat.st_ino != st_temp.st_ino)
+#else
+ /* Just compare canonical pathnames. */
+ char* input_realname = lrealpath (gcc_input_filename);
+ char* temp_realname = lrealpath (temp_filename);
+ bool files_differ = filename_cmp (input_realname, temp_realname);
+ free (input_realname);
+ free (temp_realname);
+ if (files_differ)
+#endif
+ {
+ temp_filename
+ = save_string (temp_filename,
+ temp_filename_length - 1);
+ obstack_grow (&obstack, temp_filename,
+ temp_filename_length);
+ arg_going = 1;
+ delete_this_arg = 0;
+ break;
+ }
+ }
+ }
+
+ /* See if we already have an association of %g/%u/%U and
+ suffix. */
+ for (t = temp_names; t; t = t->next)
+ if (t->length == suffix_length
+ && strncmp (t->suffix, suffix, suffix_length) == 0
+ && t->unique == (c == 'u' || c == 'U' || c == 'j'))
+ break;
+
+ /* Make a new association if needed. %u and %j
+ require one. */
+ if (t == 0 || c == 'u' || c == 'j')
+ {
+ if (t == 0)
+ {
+ t = XNEW (struct temp_name);
+ t->next = temp_names;
+ temp_names = t;
+ }
+ t->length = suffix_length;
+ if (saved_suffix)
+ {
+ t->suffix = saved_suffix;
+ saved_suffix = NULL;
+ }
+ else
+ t->suffix = save_string (suffix, suffix_length);
+ t->unique = (c == 'u' || c == 'U' || c == 'j');
+ temp_filename = make_temp_file (t->suffix);
+ temp_filename_length = strlen (temp_filename);
+ t->filename = temp_filename;
+ t->filename_length = temp_filename_length;
+ }
+
+ free (saved_suffix);
+
+ obstack_grow (&obstack, t->filename, t->filename_length);
+ delete_this_arg = 1;
+ }
+ arg_going = 1;
+ break;
+
+ case 'i':
+ if (combine_inputs)
+ {
+ /* We are going to expand `%i' into `@FILE', where FILE
+ is a newly-created temporary filename. The filenames
+ that would usually be expanded in place of %o will be
+ written to the temporary file. */
+ if (at_file_supplied)
+ open_at_file ();
+
+ for (i = 0; (int) i < n_infiles; i++)
+ if (compile_input_file_p (&infiles[i]))
+ {
+ store_arg (infiles[i].name, 0, 0);
+ infiles[i].compiled = true;
+ }
+
+ if (at_file_supplied)
+ close_at_file ();
+ }
+ else
+ {
+ obstack_grow (&obstack, gcc_input_filename,
+ input_filename_length);
+ arg_going = 1;
+ }
+ break;
+
+ case 'I':
+ {
+ struct spec_path_info info;
+
+ if (multilib_dir)
+ {
+ do_spec_1 ("-imultilib", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (multilib_dir, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
+
+ if (multiarch_dir)
+ {
+ do_spec_1 ("-imultiarch", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (multiarch_dir, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
+
+ if (gcc_exec_prefix)
+ {
+ do_spec_1 ("-iprefix", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (gcc_exec_prefix, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
+
+ if (target_system_root_changed ||
+ (target_system_root && target_sysroot_hdrs_suffix))
+ {
+ do_spec_1 ("-isysroot", 1, NULL);
+ /* Make this a separate argument. */
+ do_spec_1 (" ", 0, NULL);
+ do_spec_1 (target_system_root, 1, NULL);
+ if (target_sysroot_hdrs_suffix)
+ do_spec_1 (target_sysroot_hdrs_suffix, 1, NULL);
+ do_spec_1 (" ", 0, NULL);
+ }
+
+ info.option = "-isystem";
+ info.append = "include";
+ info.append_len = strlen (info.append);
+ info.omit_relative = false;
+ info.separate_options = true;
+
+ for_each_path (&include_prefixes, false, info.append_len,
+ spec_path, &info);
+
+ info.append = "include-fixed";
+ if (*sysroot_hdrs_suffix_spec)
+ info.append = concat (info.append, dir_separator_str,
+ multilib_dir, NULL);
+ info.append_len = strlen (info.append);
+ for_each_path (&include_prefixes, false, info.append_len,
+ spec_path, &info);
+ }
+ break;
+
+ case 'o':
+ /* We are going to expand `%o' into `@FILE', where FILE
+ is a newly-created temporary filename. The filenames
+ that would usually be expanded in place of %o will be
+ written to the temporary file. */
+ if (at_file_supplied)
+ open_at_file ();
+
+ for (i = 0; i < n_infiles + lang_specific_extra_outfiles; i++)
+ if (outfiles[i])
+ store_arg (outfiles[i], 0, 0);
+
+ if (at_file_supplied)
+ close_at_file ();
+ break;
+
+ case 'O':
+ obstack_grow (&obstack, TARGET_OBJECT_SUFFIX, strlen (TARGET_OBJECT_SUFFIX));
+ arg_going = 1;
+ break;
+
+ case 's':
+ this_is_library_file = 1;
+ break;
+
+ case 'T':
+ this_is_linker_script = 1;
+ break;
+
+ case 'V':
+ outfiles[input_file_number] = NULL;
+ break;
+
+ case 'w':
+ this_is_output_file = 1;
+ break;
+
+ case 'W':
+ {
+ unsigned int cur_index = argbuf.length ();
+ /* Handle the {...} following the %W. */
+ if (*p != '{')
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%W%c%>", spec, *p);
+ p = handle_braces (p + 1);
+ if (p == 0)
+ return -1;
+ end_going_arg ();
+ /* If any args were output, mark the last one for deletion
+ on failure. */
+ if (argbuf.length () != cur_index)
+ record_temp_file (argbuf.last (), 0, 1);
+ break;
+ }
+
+ case '@':
+ /* Handle the {...} following the %@. */
+ if (*p != '{')
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%@%c%>", spec, *p);
+ if (at_file_supplied)
+ open_at_file ();
+ p = handle_braces (p + 1);
+ if (at_file_supplied)
+ close_at_file ();
+ if (p == 0)
+ return -1;
+ break;
+
+ /* %x{OPTION} records OPTION for %X to output. */
+ case 'x':
+ {
+ const char *p1 = p;
+ char *string;
+
+ /* Skip past the option value and make a copy. */
+ if (*p != '{')
+ fatal_error (input_location,
+ "spec %qs has invalid %<%%x%c%>", spec, *p);
+ while (*p++ != '}')
+ ;
+ string = save_string (p1 + 1, p - p1 - 2);
+
+ /* See if we already recorded this option. */
+ for (const char *opt : linker_options)
+ if (! strcmp (string, opt))
+ {
+ free (string);
+ return 0;
+ }
+
+ /* This option is new; add it. */
+ add_linker_option (string, strlen (string));
+ free (string);
+ }
+ break;
+
+ /* Dump out the options accumulated previously using %x. */
+ case 'X':
+ do_specs_vec (linker_options);
+ break;
+
+ /* Dump out the options accumulated previously using -Wa,. */
+ case 'Y':
+ do_specs_vec (assembler_options);
+ break;
+
+ /* Dump out the options accumulated previously using -Wp,. */
+ case 'Z':
+ do_specs_vec (preprocessor_options);
+ break;
+
+ /* Here are digits and numbers that just process
+ a certain constant string as a spec. */
+
+ case '1':
+ value = do_spec_1 (cc1_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case '2':
+ value = do_spec_1 (cc1plus_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'a':
+ value = do_spec_1 (asm_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'A':
+ value = do_spec_1 (asm_final_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'C':
+ {
+ const char *const spec
+ = (input_file_compiler->cpp_spec
+ ? input_file_compiler->cpp_spec
+ : cpp_spec);
+ value = do_spec_1 (spec, 0, NULL);
+ if (value != 0)
+ return value;
+ }
+ break;
+
+ case 'E':
+ value = do_spec_1 (endfile_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'l':
+ value = do_spec_1 (link_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'L':
+ value = do_spec_1 (lib_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'M':
+ if (multilib_os_dir == NULL)
+ obstack_1grow (&obstack, '.');
+ else
+ obstack_grow (&obstack, multilib_os_dir,
+ strlen (multilib_os_dir));
+ break;
+
+ case 'G':
+ value = do_spec_1 (libgcc_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ case 'R':
+ /* We assume there is a directory
+ separator at the end of this string. */
+ if (target_system_root)
+ {
+ obstack_grow (&obstack, target_system_root,
+ strlen (target_system_root));
+ if (target_sysroot_suffix)
+ obstack_grow (&obstack, target_sysroot_suffix,
+ strlen (target_sysroot_suffix));
+ }
+ break;
+
+ case 'S':
+ value = do_spec_1 (startfile_spec, 0, NULL);
+ if (value != 0)
+ return value;
+ break;
+
+ /* Here we define characters other than letters and digits. */
+
+ case '{':
+ p = handle_braces (p);
+ if (p == 0)
+ return -1;
+ break;
+
+ case ':':
+ p = handle_spec_function (p, NULL, soft_matched_part);
+ if (p == 0)
+ return -1;
+ break;
+
+ case '%':
+ obstack_1grow (&obstack, '%');
+ break;
+
+ case '.':
+ {
+ unsigned len = 0;
+
+ while (p[len] && p[len] != ' ' && p[len] != '%')
+ len++;
+ suffix_subst = save_string (p - 1, len + 1);
+ p += len;
+ }
+ break;
+
+ /* Henceforth ignore the option(s) matching the pattern
+ after the %<. */
+ case '<':
+ case '>':
+ {
+ unsigned len = 0;
+ int have_wildcard = 0;
+ int i;
+ int switch_option;
+
+ if (c == '>')
+ switch_option = SWITCH_IGNORE | SWITCH_KEEP_FOR_GCC;
+ else
+ switch_option = SWITCH_IGNORE;
+
+ while (p[len] && p[len] != ' ' && p[len] != '\t')
+ len++;
+
+ if (p[len-1] == '*')
+ have_wildcard = 1;
+
+ for (i = 0; i < n_switches; i++)
+ if (!strncmp (switches[i].part1, p, len - have_wildcard)
+ && (have_wildcard || switches[i].part1[len] == '\0'))
+ {
+ switches[i].live_cond |= switch_option;
+ /* User switch be validated from validate_all_switches.
+ when the definition is seen from the spec file.
+ If not defined anywhere, will be rejected. */
+ if (switches[i].known)
+ switches[i].validated = true;
+ }
+
+ p += len;
+ }
+ break;
+
+ case '*':
+ if (soft_matched_part)
+ {
+ if (soft_matched_part[0])
+ do_spec_1 (soft_matched_part, 1, NULL);
+ /* Only insert a space after the substitution if it is at the
+ end of the current sequence. So if:
+
+ "%{foo=*:bar%*}%{foo=*:one%*two}"
+
+ matches -foo=hello then it will produce:
+
+ barhello onehellotwo
+ */
+ if (*p == 0 || *p == '}')
+ do_spec_1 (" ", 0, NULL);
+ }
+ else
+ /* Catch the case where a spec string contains something like
+ '%{foo:%*}'. i.e. there is no * in the pattern on the left
+ hand side of the :. */
+ error ("spec failure: %<%%*%> has not been initialized by pattern match");
+ break;
+
+ /* Process a string found as the value of a spec given by name.
+ This feature allows individual machine descriptions
+ to add and use their own specs. */
+ case '(':
+ {
+ const char *name = p;
+ struct spec_list *sl;
+ int len;
+
+ /* The string after the S/P is the name of a spec that is to be
+ processed. */
+ while (*p && *p != ')')
+ p++;
+
+ /* See if it's in the list. */
+ for (len = p - name, sl = specs; sl; sl = sl->next)
+ if (sl->name_len == len && !strncmp (sl->name, name, len))
+ {
+ name = *(sl->ptr_spec);
+#ifdef DEBUG_SPECS
+ fnotice (stderr, "Processing spec (%s), which is '%s'\n",
+ sl->name, name);
+#endif
+ break;
+ }
+
+ if (sl)
+ {
+ value = do_spec_1 (name, 0, NULL);
+ if (value != 0)
+ return value;
+ }
+
+ /* Discard the closing paren. */
+ if (*p)
+ p++;
+ }
+ break;
+
+ case '"':
+ /* End a previous argument, if there is one, then issue an
+ empty argument. */
+ end_going_arg ();
+ arg_going = 1;
+ end_going_arg ();
+ break;
+
+ default:
+ error ("spec failure: unrecognized spec option %qc", c);
+ break;
+ }
+ break;
+
+ case '\\':
+ /* Backslash: treat next character as ordinary. */
+ c = *p++;
+
+ /* When adding more cases that previously matched default, make
+ sure to adjust quote_spec_char_p as well. */
+
+ /* Fall through. */
+ default:
+ /* Ordinary character: put it into the current argument. */
+ obstack_1grow (&obstack, c);
+ arg_going = 1;
+ }
+
+ /* End of string. If we are processing a spec function, we need to
+ end any pending argument. */
+ if (processing_spec_function)
+ end_going_arg ();
+
+ return 0;
+}
+
+/* Look up a spec function. */
+
+static const struct spec_function *
+lookup_spec_function (const char *name)
+{
+ const struct spec_function *sf;
+
+ for (sf = static_spec_functions; sf->name != NULL; sf++)
+ if (strcmp (sf->name, name) == 0)
+ return sf;
+
+ return NULL;
+}
+
+/* Evaluate a spec function. */
+
+static const char *
+eval_spec_function (const char *func, const char *args,
+ const char *soft_matched_part)
+{
+ const struct spec_function *sf;
+ const char *funcval;
+
+ /* Saved spec processing context. */
+ vec<const_char_p> save_argbuf;
+
+ int save_arg_going;
+ int save_delete_this_arg;
+ int save_this_is_output_file;
+ int save_this_is_library_file;
+ int save_input_from_pipe;
+ int save_this_is_linker_script;
+ const char *save_suffix_subst;
+
+ int save_growing_size;
+ void *save_growing_value = NULL;
+
+ sf = lookup_spec_function (func);
+ if (sf == NULL)
+ fatal_error (input_location, "unknown spec function %qs", func);
+
+ /* Push the spec processing context. */
+ save_argbuf = argbuf;
+
+ save_arg_going = arg_going;
+ save_delete_this_arg = delete_this_arg;
+ save_this_is_output_file = this_is_output_file;
+ save_this_is_library_file = this_is_library_file;
+ save_this_is_linker_script = this_is_linker_script;
+ save_input_from_pipe = input_from_pipe;
+ save_suffix_subst = suffix_subst;
+
+ /* If we have some object growing now, finalize it so the args and function
+ eval proceed from a cleared context. This is needed to prevent the first
+ constructed arg from mistakenly including the growing value. We'll push
+ this value back on the obstack once the function evaluation is done, to
+ restore a consistent processing context for our caller. This is fine as
+ the address of growing objects isn't guaranteed to remain stable until
+ they are finalized, and we expect this situation to be rare enough for
+ the extra copy not to be an issue. */
+ save_growing_size = obstack_object_size (&obstack);
+ if (save_growing_size > 0)
+ save_growing_value = obstack_finish (&obstack);
+
+ /* Create a new spec processing context, and build the function
+ arguments. */
+
+ alloc_args ();
+ if (do_spec_2 (args, soft_matched_part) < 0)
+ fatal_error (input_location, "error in arguments to spec function %qs",
+ func);
+
+ /* argbuf_index is an index for the next argument to be inserted, and
+ so contains the count of the args already inserted. */
+
+ funcval = (*sf->func) (argbuf.length (),
+ argbuf.address ());
+
+ /* Pop the spec processing context. */
+ argbuf.release ();
+ argbuf = save_argbuf;
+
+ arg_going = save_arg_going;
+ delete_this_arg = save_delete_this_arg;
+ this_is_output_file = save_this_is_output_file;
+ this_is_library_file = save_this_is_library_file;
+ this_is_linker_script = save_this_is_linker_script;
+ input_from_pipe = save_input_from_pipe;
+ suffix_subst = save_suffix_subst;
+
+ if (save_growing_size > 0)
+ obstack_grow (&obstack, save_growing_value, save_growing_size);
+
+ return funcval;
+}
+
+/* Handle a spec function call of the form:
+
+ %:function(args)
+
+ ARGS is processed as a spec in a separate context and split into an
+ argument vector in the normal fashion. The function returns a string
+ containing a spec which we then process in the caller's context, or
+ NULL if no processing is required.
+
+ If RETVAL_NONNULL is not NULL, then store a bool whether function
+ returned non-NULL.
+
+ SOFT_MATCHED_PART holds the current value of a matched * pattern, which
+ may be re-expanded with a %* as part of the function arguments. */
+
+static const char *
+handle_spec_function (const char *p, bool *retval_nonnull,
+ const char *soft_matched_part)
+{
+ char *func, *args;
+ const char *endp, *funcval;
+ int count;
+
+ processing_spec_function++;
+
+ /* Get the function name. */
+ for (endp = p; *endp != '\0'; endp++)
+ {
+ if (*endp == '(') /* ) */
+ break;
+ /* Only allow [A-Za-z0-9], -, and _ in function names. */
+ if (!ISALNUM (*endp) && !(*endp == '-' || *endp == '_'))
+ fatal_error (input_location, "malformed spec function name");
+ }
+ if (*endp != '(') /* ) */
+ fatal_error (input_location, "no arguments for spec function");
+ func = save_string (p, endp - p);
+ p = ++endp;
+
+ /* Get the arguments. */
+ for (count = 0; *endp != '\0'; endp++)
+ {
+ /* ( */
+ if (*endp == ')')
+ {
+ if (count == 0)
+ break;
+ count--;
+ }
+ else if (*endp == '(') /* ) */
+ count++;
+ }
+ /* ( */
+ if (*endp != ')')
+ fatal_error (input_location, "malformed spec function arguments");
+ args = save_string (p, endp - p);
+ p = ++endp;
+
+ /* p now points to just past the end of the spec function expression. */
+
+ funcval = eval_spec_function (func, args, soft_matched_part);
+ if (funcval != NULL && do_spec_1 (funcval, 0, NULL) < 0)
+ p = NULL;
+ if (retval_nonnull)
+ *retval_nonnull = funcval != NULL;
+
+ free (func);
+ free (args);
+
+ processing_spec_function--;
+
+ return p;
+}
+
+/* Inline subroutine of handle_braces. Returns true if the current
+ input suffix matches the atom bracketed by ATOM and END_ATOM. */
+static inline bool
+input_suffix_matches (const char *atom, const char *end_atom)
+{
+ return (input_suffix
+ && !strncmp (input_suffix, atom, end_atom - atom)
+ && input_suffix[end_atom - atom] == '\0');
+}
+
+/* Subroutine of handle_braces. Returns true if the current
+ input file's spec name matches the atom bracketed by ATOM and END_ATOM. */
+static bool
+input_spec_matches (const char *atom, const char *end_atom)
+{
+ return (input_file_compiler
+ && input_file_compiler->suffix
+ && input_file_compiler->suffix[0] != '\0'
+ && !strncmp (input_file_compiler->suffix + 1, atom,
+ end_atom - atom)
+ && input_file_compiler->suffix[end_atom - atom + 1] == '\0');
+}
+
+/* Subroutine of handle_braces. Returns true if a switch
+ matching the atom bracketed by ATOM and END_ATOM appeared on the
+ command line. */
+static bool
+switch_matches (const char *atom, const char *end_atom, int starred)
+{
+ int i;
+ int len = end_atom - atom;
+ int plen = starred ? len : -1;
+
+ for (i = 0; i < n_switches; i++)
+ if (!strncmp (switches[i].part1, atom, len)
+ && (starred || switches[i].part1[len] == '\0')
+ && check_live_switch (i, plen))
+ return true;
+
+ /* Check if a switch with separated form matching the atom.
+ We check -D and -U switches. */
+ else if (switches[i].args != 0)
+ {
+ if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
+ && *switches[i].part1 == atom[0])
+ {
+ if (!strncmp (switches[i].args[0], &atom[1], len - 1)
+ && (starred || (switches[i].part1[1] == '\0'
+ && switches[i].args[0][len - 1] == '\0'))
+ && check_live_switch (i, (starred ? 1 : -1)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Inline subroutine of handle_braces. Mark all of the switches which
+ match ATOM (extends to END_ATOM; STARRED indicates whether there
+ was a star after the atom) for later processing. */
+static inline void
+mark_matching_switches (const char *atom, const char *end_atom, int starred)
+{
+ int i;
+ int len = end_atom - atom;
+ int plen = starred ? len : -1;
+
+ for (i = 0; i < n_switches; i++)
+ if (!strncmp (switches[i].part1, atom, len)
+ && (starred || switches[i].part1[len] == '\0')
+ && check_live_switch (i, plen))
+ switches[i].ordering = 1;
+}
+
+/* Inline subroutine of handle_braces. Process all the currently
+ marked switches through give_switch, and clear the marks. */
+static inline void
+process_marked_switches (void)
+{
+ int i;
+
+ for (i = 0; i < n_switches; i++)
+ if (switches[i].ordering == 1)
+ {
+ switches[i].ordering = 0;
+ give_switch (i, 0);
+ }
+}
+
+/* Handle a %{ ... } construct. P points just inside the leading {.
+ Returns a pointer one past the end of the brace block, or 0
+ if we call do_spec_1 and that returns -1. */
+
+static const char *
+handle_braces (const char *p)
+{
+ const char *atom, *end_atom;
+ const char *d_atom = NULL, *d_end_atom = NULL;
+ char *esc_buf = NULL, *d_esc_buf = NULL;
+ int esc;
+ const char *orig = p;
+
+ bool a_is_suffix;
+ bool a_is_spectype;
+ bool a_is_starred;
+ bool a_is_negated;
+ bool a_matched;
+
+ bool a_must_be_last = false;
+ bool ordered_set = false;
+ bool disjunct_set = false;
+ bool disj_matched = false;
+ bool disj_starred = true;
+ bool n_way_choice = false;
+ bool n_way_matched = false;
+
+#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
+
+ do
+ {
+ if (a_must_be_last)
+ goto invalid;
+
+ /* Scan one "atom" (S in the description above of %{}, possibly
+ with '!', '.', '@', ',', or '*' modifiers). */
+ a_matched = false;
+ a_is_suffix = false;
+ a_is_starred = false;
+ a_is_negated = false;
+ a_is_spectype = false;
+
+ SKIP_WHITE ();
+ if (*p == '!')
+ p++, a_is_negated = true;
+
+ SKIP_WHITE ();
+ if (*p == '%' && p[1] == ':')
+ {
+ atom = NULL;
+ end_atom = NULL;
+ p = handle_spec_function (p + 2, &a_matched, NULL);
+ }
+ else
+ {
+ if (*p == '.')
+ p++, a_is_suffix = true;
+ else if (*p == ',')
+ p++, a_is_spectype = true;
+
+ atom = p;
+ esc = 0;
+ while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
+ || *p == ',' || *p == '.' || *p == '@' || *p == '\\')
+ {
+ if (*p == '\\')
+ {
+ p++;
+ if (!*p)
+ fatal_error (input_location,
+ "braced spec %qs ends in escape", orig);
+ esc++;
+ }
+ p++;
+ }
+ end_atom = p;
+
+ if (esc)
+ {
+ const char *ap;
+ char *ep;
+
+ if (esc_buf && esc_buf != d_esc_buf)
+ free (esc_buf);
+ esc_buf = NULL;
+ ep = esc_buf = (char *) xmalloc (end_atom - atom - esc + 1);
+ for (ap = atom; ap != end_atom; ap++, ep++)
+ {
+ if (*ap == '\\')
+ ap++;
+ *ep = *ap;
+ }
+ *ep = '\0';
+ atom = esc_buf;
+ end_atom = ep;
+ }
+
+ if (*p == '*')
+ p++, a_is_starred = 1;
+ }
+
+ SKIP_WHITE ();
+ switch (*p)
+ {
+ case '&': case '}':
+ /* Substitute the switch(es) indicated by the current atom. */
+ ordered_set = true;
+ if (disjunct_set || n_way_choice || a_is_negated || a_is_suffix
+ || a_is_spectype || atom == end_atom)
+ goto invalid;
+
+ mark_matching_switches (atom, end_atom, a_is_starred);
+
+ if (*p == '}')
+ process_marked_switches ();
+ break;
+
+ case '|': case ':':
+ /* Substitute some text if the current atom appears as a switch
+ or suffix. */
+ disjunct_set = true;
+ if (ordered_set)
+ goto invalid;
+
+ if (atom && atom == end_atom)
+ {
+ if (!n_way_choice || disj_matched || *p == '|'
+ || a_is_negated || a_is_suffix || a_is_spectype
+ || a_is_starred)
+ goto invalid;
+
+ /* An empty term may appear as the last choice of an
+ N-way choice set; it means "otherwise". */
+ a_must_be_last = true;
+ disj_matched = !n_way_matched;
+ disj_starred = false;
+ }
+ else
+ {
+ if ((a_is_suffix || a_is_spectype) && a_is_starred)
+ goto invalid;
+
+ if (!a_is_starred)
+ disj_starred = false;
+
+ /* Don't bother testing this atom if we already have a
+ match. */
+ if (!disj_matched && !n_way_matched)
+ {
+ if (atom == NULL)
+ /* a_matched is already set by handle_spec_function. */;
+ else if (a_is_suffix)
+ a_matched = input_suffix_matches (atom, end_atom);
+ else if (a_is_spectype)
+ a_matched = input_spec_matches (atom, end_atom);
+ else
+ a_matched = switch_matches (atom, end_atom, a_is_starred);
+
+ if (a_matched != a_is_negated)
+ {
+ disj_matched = true;
+ d_atom = atom;
+ d_end_atom = end_atom;
+ d_esc_buf = esc_buf;
+ }
+ }
+ }
+
+ if (*p == ':')
+ {
+ /* Found the body, that is, the text to substitute if the
+ current disjunction matches. */
+ p = process_brace_body (p + 1, d_atom, d_end_atom, disj_starred,
+ disj_matched && !n_way_matched);
+ if (p == 0)
+ goto done;
+
+ /* If we have an N-way choice, reset state for the next
+ disjunction. */
+ if (*p == ';')
+ {
+ n_way_choice = true;
+ n_way_matched |= disj_matched;
+ disj_matched = false;
+ disj_starred = true;
+ d_atom = d_end_atom = NULL;
+ }
+ }
+ break;
+
+ default:
+ goto invalid;
+ }
+ }
+ while (*p++ != '}');
+
+ done:
+ if (d_esc_buf && d_esc_buf != esc_buf)
+ free (d_esc_buf);
+ if (esc_buf)
+ free (esc_buf);
+
+ return p;
+
+ invalid:
+ fatal_error (input_location, "braced spec %qs is invalid at %qc", orig, *p);
+
+#undef SKIP_WHITE
+}
+
+/* Subroutine of handle_braces. Scan and process a brace substitution body
+ (X in the description of %{} syntax). P points one past the colon;
+ ATOM and END_ATOM bracket the first atom which was found to be true
+ (present) in the current disjunction; STARRED indicates whether all
+ the atoms in the current disjunction were starred (for syntax validation);
+ MATCHED indicates whether the disjunction matched or not, and therefore
+ whether or not the body is to be processed through do_spec_1 or just
+ skipped. Returns a pointer to the closing } or ;, or 0 if do_spec_1
+ returns -1. */
+
+static const char *
+process_brace_body (const char *p, const char *atom, const char *end_atom,
+ int starred, int matched)
+{
+ const char *body, *end_body;
+ unsigned int nesting_level;
+ bool have_subst = false;
+
+ /* Locate the closing } or ;, honoring nested braces.
+ Trim trailing whitespace. */
+ body = p;
+ nesting_level = 1;
+ for (;;)
+ {
+ if (*p == '{')
+ nesting_level++;
+ else if (*p == '}')
+ {
+ if (!--nesting_level)
+ break;
+ }
+ else if (*p == ';' && nesting_level == 1)
+ break;
+ else if (*p == '%' && p[1] == '*' && nesting_level == 1)
+ have_subst = true;
+ else if (*p == '\0')
+ goto invalid;
+ p++;
+ }
+
+ end_body = p;
+ while (end_body[-1] == ' ' || end_body[-1] == '\t')
+ end_body--;
+
+ if (have_subst && !starred)
+ goto invalid;
+
+ if (matched)
+ {
+ /* Copy the substitution body to permanent storage and execute it.
+ If have_subst is false, this is a simple matter of running the
+ body through do_spec_1... */
+ char *string = save_string (body, end_body - body);
+ if (!have_subst)
+ {
+ if (do_spec_1 (string, 0, NULL) < 0)
+ {
+ free (string);
+ return 0;
+ }
+ }
+ else
+ {
+ /* ... but if have_subst is true, we have to process the
+ body once for each matching switch, with %* set to the
+ variant part of the switch. */
+ unsigned int hard_match_len = end_atom - atom;
+ int i;
+
+ for (i = 0; i < n_switches; i++)
+ if (!strncmp (switches[i].part1, atom, hard_match_len)
+ && check_live_switch (i, hard_match_len))
+ {
+ if (do_spec_1 (string, 0,
+ &switches[i].part1[hard_match_len]) < 0)
+ {
+ free (string);
+ return 0;
+ }
+ /* Pass any arguments this switch has. */
+ give_switch (i, 1);
+ suffix_subst = NULL;
+ }
+ }
+ free (string);
+ }
+
+ return p;
+
+ invalid:
+ fatal_error (input_location, "braced spec body %qs is invalid", body);
+}
+
+/* Return 0 iff switch number SWITCHNUM is obsoleted by a later switch
+ on the command line. PREFIX_LENGTH is the length of XXX in an {XXX*}
+ spec, or -1 if either exact match or %* is used.
+
+ A -O switch is obsoleted by a later -O switch. A -f, -g, -m, or -W switch
+ whose value does not begin with "no-" is obsoleted by the same value
+ with the "no-", similarly for a switch with the "no-" prefix. */
+
+static int
+check_live_switch (int switchnum, int prefix_length)
+{
+ const char *name = switches[switchnum].part1;
+ int i;
+
+ /* If we already processed this switch and determined if it was
+ live or not, return our past determination. */
+ if (switches[switchnum].live_cond != 0)
+ return ((switches[switchnum].live_cond & SWITCH_LIVE) != 0
+ && (switches[switchnum].live_cond & SWITCH_FALSE) == 0
+ && (switches[switchnum].live_cond & SWITCH_IGNORE_PERMANENTLY)
+ == 0);
+
+ /* In the common case of {<at-most-one-letter>*}, a negating
+ switch would always match, so ignore that case. We will just
+ send the conflicting switches to the compiler phase. */
+ if (prefix_length >= 0 && prefix_length <= 1)
+ return 1;
+
+ /* Now search for duplicate in a manner that depends on the name. */
+ switch (*name)
+ {
+ case 'O':
+ for (i = switchnum + 1; i < n_switches; i++)
+ if (switches[i].part1[0] == 'O')
+ {
+ switches[switchnum].validated = true;
+ switches[switchnum].live_cond = SWITCH_FALSE;
+ return 0;
+ }
+ break;
+
+ case 'W': case 'f': case 'm': case 'g':
+ if (startswith (name + 1, "no-"))
+ {
+ /* We have Xno-YYY, search for XYYY. */
+ for (i = switchnum + 1; i < n_switches; i++)
+ if (switches[i].part1[0] == name[0]
+ && ! strcmp (&switches[i].part1[1], &name[4]))
+ {
+ /* --specs are validated with the validate_switches mechanism. */
+ if (switches[switchnum].known)
+ switches[switchnum].validated = true;
+ switches[switchnum].live_cond = SWITCH_FALSE;
+ return 0;
+ }
+ }
+ else
+ {
+ /* We have XYYY, search for Xno-YYY. */
+ for (i = switchnum + 1; i < n_switches; i++)
+ if (switches[i].part1[0] == name[0]
+ && switches[i].part1[1] == 'n'
+ && switches[i].part1[2] == 'o'
+ && switches[i].part1[3] == '-'
+ && !strcmp (&switches[i].part1[4], &name[1]))
+ {
+ /* --specs are validated with the validate_switches mechanism. */
+ if (switches[switchnum].known)
+ switches[switchnum].validated = true;
+ switches[switchnum].live_cond = SWITCH_FALSE;
+ return 0;
+ }
+ }
+ break;
+ }
+
+ /* Otherwise the switch is live. */
+ switches[switchnum].live_cond |= SWITCH_LIVE;
+ return 1;
+}
+
+/* Pass a switch to the current accumulating command
+ in the same form that we received it.
+ SWITCHNUM identifies the switch; it is an index into
+ the vector of switches gcc received, which is `switches'.
+ This cannot fail since it never finishes a command line.
+
+ If OMIT_FIRST_WORD is nonzero, then we omit .part1 of the argument. */
+
+static void
+give_switch (int switchnum, int omit_first_word)
+{
+ if ((switches[switchnum].live_cond & SWITCH_IGNORE) != 0)
+ return;
+
+ if (!omit_first_word)
+ {
+ do_spec_1 ("-", 0, NULL);
+ do_spec_1 (switches[switchnum].part1, 1, NULL);
+ }
+
+ if (switches[switchnum].args != 0)
+ {
+ const char **p;
+ for (p = switches[switchnum].args; *p; p++)
+ {
+ const char *arg = *p;
+
+ do_spec_1 (" ", 0, NULL);
+ if (suffix_subst)
+ {
+ unsigned length = strlen (arg);
+ int dot = 0;
+
+ while (length-- && !IS_DIR_SEPARATOR (arg[length]))
+ if (arg[length] == '.')
+ {
+ (CONST_CAST (char *, arg))[length] = 0;
+ dot = 1;
+ break;
+ }
+ do_spec_1 (arg, 1, NULL);
+ if (dot)
+ (CONST_CAST (char *, arg))[length] = '.';
+ do_spec_1 (suffix_subst, 1, NULL);
+ }
+ else
+ do_spec_1 (arg, 1, NULL);
+ }
+ }
+
+ do_spec_1 (" ", 0, NULL);
+ switches[switchnum].validated = true;
+}
+
+/* Print GCC configuration (e.g. version, thread model, target,
+ configuration_arguments) to a given FILE. */
+
+static void
+print_configuration (FILE *file)
+{
+ int n;
+ const char *thrmod;
+
+ fnotice (file, "Target: %s\n", spec_machine);
+ fnotice (file, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+ /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+ but there's no point in doing all this processing just to get
+ thread_model back. */
+ obstack_init (&obstack);
+ do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+ obstack_1grow (&obstack, '\0');
+ thrmod = XOBFINISH (&obstack, const char *);
+#else
+ thrmod = thread_model;
+#endif
+
+ fnotice (file, "Thread model: %s\n", thrmod);
+ fnotice (file, "Supported LTO compression algorithms: zlib");
+#ifdef HAVE_ZSTD_H
+ fnotice (file, " zstd");
+#endif
+ fnotice (file, "\n");
+
+ /* compiler_version is truncated at the first space when initialized
+ from version string, so truncate version_string at the first space
+ before comparing. */
+ for (n = 0; version_string[n]; n++)
+ if (version_string[n] == ' ')
+ break;
+
+ if (! strncmp (version_string, compiler_version, n)
+ && compiler_version[n] == 0)
+ fnotice (file, "gcc version %s %s\n", version_string,
+ pkgversion_string);
+ else
+ fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n",
+ version_string, pkgversion_string, compiler_version);
+
+}
+
+#define RETRY_ICE_ATTEMPTS 3
+
+/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise. */
+
+static bool
+files_equal_p (char *file1, char *file2)
+{
+ struct stat st1, st2;
+ off_t n, len;
+ int fd1, fd2;
+ const int bufsize = 8192;
+ char *buf = XNEWVEC (char, bufsize);
+
+ fd1 = open (file1, O_RDONLY);
+ fd2 = open (file2, O_RDONLY);
+
+ if (fd1 < 0 || fd2 < 0)
+ goto error;
+
+ if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+ goto error;
+
+ if (st1.st_size != st2.st_size)
+ goto error;
+
+ for (n = st1.st_size; n; n -= len)
+ {
+ len = n;
+ if ((int) len > bufsize / 2)
+ len = bufsize / 2;
+
+ if (read (fd1, buf, len) != (int) len
+ || read (fd2, buf + bufsize / 2, len) != (int) len)
+ {
+ goto error;
+ }
+
+ if (memcmp (buf, buf + bufsize / 2, len) != 0)
+ goto error;
+ }
+
+ free (buf);
+ close (fd1);
+ close (fd2);
+
+ return 1;
+
+error:
+ free (buf);
+ close (fd1);
+ close (fd2);
+ return 0;
+}
+
+/* Check that compiler's output doesn't differ across runs.
+ TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing
+ stdout and stderr for each compiler run. Return true if all of
+ TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent. */
+
+static bool
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+ int i;
+ for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+ {
+ if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1])
+ || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1]))
+ {
+ fnotice (stderr, "The bug is not reproducible, so it is"
+ " likely a hardware or OS problem.\n");
+ break;
+ }
+ }
+ return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+ ATTEMPT_STATUS_FAIL_TO_RUN,
+ ATTEMPT_STATUS_SUCCESS,
+ ATTEMPT_STATUS_ICE
+};
+
+
+/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout
+ to OUT_TEMP and stderr to ERR_TEMP. If APPEND is TRUE, append to OUT_TEMP
+ and ERR_TEMP instead of truncating. If EMIT_SYSTEM_INFO is TRUE, also write
+ GCC configuration into to ERR_TEMP. Return ATTEMPT_STATUS_FAIL_TO_RUN if
+ compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and
+ ATTEMPT_STATUS_SUCCESS otherwise. */
+
+static enum attempt_status
+run_attempt (const char **new_argv, const char *out_temp,
+ const char *err_temp, int emit_system_info, int append)
+{
+
+ if (emit_system_info)
+ {
+ FILE *file_out = fopen (err_temp, "a");
+ print_configuration (file_out);
+ fputs ("\n", file_out);
+ fclose (file_out);
+ }
+
+ int exit_status;
+ const char *errmsg;
+ struct pex_obj *pex;
+ int err;
+ int pex_flags = PEX_USE_PIPES | PEX_LAST;
+ enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN;
+
+ if (append)
+ pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND;
+
+ pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
+ if (!pex)
+ fatal_error (input_location, "%<pex_init%> failed: %m");
+
+ errmsg = pex_run (pex, pex_flags, new_argv[0],
+ CONST_CAST2 (char *const *, const char **, &new_argv[1]),
+ out_temp, err_temp, &err);
+ if (errmsg != NULL)
+ {
+ errno = err;
+ fatal_error (input_location,
+ err ? G_ ("cannot execute %qs: %s: %m")
+ : G_ ("cannot execute %qs: %s"),
+ new_argv[0], errmsg);
+ }
+
+ if (!pex_get_status (pex, 1, &exit_status))
+ goto out;
+
+ switch (WEXITSTATUS (exit_status))
+ {
+ case ICE_EXIT_CODE:
+ status = ATTEMPT_STATUS_ICE;
+ break;
+
+ case SUCCESS_EXIT_CODE:
+ status = ATTEMPT_STATUS_SUCCESS;
+ break;
+
+ default:
+ ;
+ }
+
+out:
+ pex_free (pex);
+ return status;
+}
+
+/* This routine reads lines from IN file, adds C++ style comments
+ at the begining of each line and writes result into OUT. */
+
+static void
+insert_comments (const char *file_in, const char *file_out)
+{
+ FILE *in = fopen (file_in, "rb");
+ FILE *out = fopen (file_out, "wb");
+ char line[256];
+
+ bool add_comment = true;
+ while (fgets (line, sizeof (line), in))
+ {
+ if (add_comment)
+ fputs ("// ", out);
+ fputs (line, out);
+ add_comment = strchr (line, '\n') != NULL;
+ }
+
+ fclose (in);
+ fclose (out);
+}
+
+/* This routine adds preprocessed source code into the given ERR_FILE.
+ To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
+ add information in report file. RUN_ATTEMPT should return
+ ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report. */
+
+static void
+do_report_bug (const char **new_argv, const int nargs,
+ char **out_file, char **err_file)
+{
+ int i, status;
+ int fd = open (*out_file, O_RDWR | O_APPEND);
+ if (fd < 0)
+ return;
+ write (fd, "\n//", 3);
+ for (i = 0; i < nargs; i++)
+ {
+ write (fd, " ", 1);
+ write (fd, new_argv[i], strlen (new_argv[i]));
+ }
+ write (fd, "\n\n", 2);
+ close (fd);
+ new_argv[nargs] = "-E";
+ new_argv[nargs + 1] = NULL;
+
+ status = run_attempt (new_argv, *out_file, *err_file, 0, 1);
+
+ if (status == ATTEMPT_STATUS_SUCCESS)
+ {
+ fnotice (stderr, "Preprocessed source stored into %s file,"
+ " please attach this to your bugreport.\n", *out_file);
+ /* Make sure it is not deleted. */
+ free (*out_file);
+ *out_file = NULL;
+ }
+}
+
+/* Try to reproduce ICE. If bug is reproducible, generate report .err file
+ containing GCC configuration, backtrace, compiler's command line options
+ and preprocessed source code. */
+
+static void
+try_generate_repro (const char **argv)
+{
+ int i, nargs, out_arg = -1, quiet = 0, attempt;
+ const char **new_argv;
+ char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+ char **temp_stdout_files = &temp_files[0];
+ char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+ if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+ return;
+
+ for (nargs = 0; argv[nargs] != NULL; ++nargs)
+ /* Only retry compiler ICEs, not preprocessor ones. */
+ if (! strcmp (argv[nargs], "-E"))
+ return;
+ else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+ {
+ if (out_arg == -1)
+ out_arg = nargs;
+ else
+ return;
+ }
+ /* If the compiler is going to output any time information,
+ it might varry between invocations. */
+ else if (! strcmp (argv[nargs], "-quiet"))
+ quiet = 1;
+ else if (! strcmp (argv[nargs], "-ftime-report"))
+ return;
+
+ if (out_arg == -1 || !quiet)
+ return;
+
+ memset (temp_files, '\0', sizeof (temp_files));
+ new_argv = XALLOCAVEC (const char *, nargs + 4);
+ memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+ new_argv[nargs++] = "-frandom-seed=0";
+ new_argv[nargs++] = "-fdump-noaddr";
+ new_argv[nargs] = NULL;
+ if (new_argv[out_arg][2] == '\0')
+ new_argv[out_arg + 1] = "-";
+ else
+ new_argv[out_arg] = "-o-";
+
+ int status;
+ for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+ {
+ int emit_system_info = 0;
+ int append = 0;
+ temp_stdout_files[attempt] = make_temp_file (".out");
+ temp_stderr_files[attempt] = make_temp_file (".err");
+
+ if (attempt == RETRY_ICE_ATTEMPTS - 1)
+ {
+ append = 1;
+ emit_system_info = 1;
+ }
+
+ status = run_attempt (new_argv, temp_stdout_files[attempt],
+ temp_stderr_files[attempt], emit_system_info,
+ append);
+
+ if (status != ATTEMPT_STATUS_ICE)
+ {
+ fnotice (stderr, "The bug is not reproducible, so it is"
+ " likely a hardware or OS problem.\n");
+ goto out;
+ }
+ }
+
+ if (!check_repro (temp_stdout_files, temp_stderr_files))
+ goto out;
+
+ {
+ /* Insert commented out backtrace into report file. */
+ char **stderr_commented = &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1];
+ insert_comments (temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+ *stderr_commented);
+
+ /* In final attempt we append compiler options and preprocesssed code to last
+ generated .out file with configuration and backtrace. */
+ char **err = &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1];
+ do_report_bug (new_argv, nargs, stderr_commented, err);
+ }
+
+out:
+ for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+ if (temp_files[i])
+ {
+ unlink (temp_stdout_files[i]);
+ free (temp_stdout_files[i]);
+ }
+}
+
+/* Search for a file named NAME trying various prefixes including the
+ user's -B prefix and some standard ones.
+ Return the absolute file name found. If nothing is found, return NAME. */
+
+static const char *
+find_file (const char *name)
+{
+ char *newname = find_a_file (&startfile_prefixes, name, R_OK, true);
+ return newname ? newname : name;
+}
+
+/* Determine whether a directory exists. If LINKER, return 0 for
+ certain fixed names not needed by the linker. */
+
+static int
+is_directory (const char *path1, bool linker)
+{
+ int len1;
+ char *path;
+ char *cp;
+ struct stat st;
+
+ /* Ensure the string ends with "/.". The resulting path will be a
+ directory even if the given path is a symbolic link. */
+ len1 = strlen (path1);
+ path = (char *) alloca (3 + len1);
+ memcpy (path, path1, len1);
+ cp = path + len1;
+ if (!IS_DIR_SEPARATOR (cp[-1]))
+ *cp++ = DIR_SEPARATOR;
+ *cp++ = '.';
+ *cp = '\0';
+
+ /* Exclude directories that the linker is known to search. */
+ if (linker
+ && IS_DIR_SEPARATOR (path[0])
+ && ((cp - path == 6
+ && filename_ncmp (path + 1, "lib", 3) == 0)
+ || (cp - path == 10
+ && filename_ncmp (path + 1, "usr", 3) == 0
+ && IS_DIR_SEPARATOR (path[4])
+ && filename_ncmp (path + 5, "lib", 3) == 0)))
+ return 0;
+
+ return (stat (path, &st) >= 0 && S_ISDIR (st.st_mode));
+}
+
+/* Set up the various global variables to indicate that we're processing
+ the input file named FILENAME. */
+
+void
+set_input (const char *filename)
+{
+ const char *p;
+
+ gcc_input_filename = filename;
+ input_filename_length = strlen (gcc_input_filename);
+ input_basename = lbasename (gcc_input_filename);
+
+ /* Find a suffix starting with the last period,
+ and set basename_length to exclude that suffix. */
+ basename_length = strlen (input_basename);
+ suffixed_basename_length = basename_length;
+ p = input_basename + basename_length;
+ while (p != input_basename && *p != '.')
+ --p;
+ if (*p == '.' && p != input_basename)
+ {
+ basename_length = p - input_basename;
+ input_suffix = p + 1;
+ }
+ else
+ input_suffix = "";
+
+ /* If a spec for 'g', 'u', or 'U' is seen with -save-temps then
+ we will need to do a stat on the gcc_input_filename. The
+ INPUT_STAT_SET signals that the stat is needed. */
+ input_stat_set = 0;
+}
+
+/* On fatal signals, delete all the temporary files. */
+
+static void
+fatal_signal (int signum)
+{
+ signal (signum, SIG_DFL);
+ delete_failure_queue ();
+ delete_temp_files ();
+ /* Get the same signal again, this time not handled,
+ so its normal effect occurs. */
+ kill (getpid (), signum);
+}
+
+/* Compare the contents of the two files named CMPFILE[0] and
+ CMPFILE[1]. Return zero if they're identical, nonzero
+ otherwise. */
+
+static int
+compare_files (char *cmpfile[])
+{
+ int ret = 0;
+ FILE *temp[2] = { NULL, NULL };
+ int i;
+
+#if HAVE_MMAP_FILE
+ {
+ size_t length[2];
+ void *map[2] = { NULL, NULL };
+
+ for (i = 0; i < 2; i++)
+ {
+ struct stat st;
+
+ if (stat (cmpfile[i], &st) < 0 || !S_ISREG (st.st_mode))
+ {
+ error ("%s: could not determine length of compare-debug file %s",
+ gcc_input_filename, cmpfile[i]);
+ ret = 1;
+ break;
+ }
+
+ length[i] = st.st_size;
+ }
+
+ if (!ret && length[0] != length[1])
+ {
+ error ("%s: %<-fcompare-debug%> failure (length)", gcc_input_filename);
+ ret = 1;
+ }
+
+ if (!ret)
+ for (i = 0; i < 2; i++)
+ {
+ int fd = open (cmpfile[i], O_RDONLY);
+ if (fd < 0)
+ {
+ error ("%s: could not open compare-debug file %s",
+ gcc_input_filename, cmpfile[i]);
+ ret = 1;
+ break;
+ }
+
+ map[i] = mmap (NULL, length[i], PROT_READ, MAP_PRIVATE, fd, 0);
+ close (fd);
+
+ if (map[i] == (void *) MAP_FAILED)
+ {
+ ret = -1;
+ break;
+ }
+ }
+
+ if (!ret)
+ {
+ if (memcmp (map[0], map[1], length[0]) != 0)
+ {
+ error ("%s: %<-fcompare-debug%> failure", gcc_input_filename);
+ ret = 1;
+ }
+ }
+
+ for (i = 0; i < 2; i++)
+ if (map[i])
+ munmap ((caddr_t) map[i], length[i]);
+
+ if (ret >= 0)
+ return ret;
+
+ ret = 0;
+ }
+#endif
+
+ for (i = 0; i < 2; i++)
+ {
+ temp[i] = fopen (cmpfile[i], "r");
+ if (!temp[i])
+ {
+ error ("%s: could not open compare-debug file %s",
+ gcc_input_filename, cmpfile[i]);
+ ret = 1;
+ break;
+ }
+ }
+
+ if (!ret && temp[0] && temp[1])
+ for (;;)
+ {
+ int c0, c1;
+ c0 = fgetc (temp[0]);
+ c1 = fgetc (temp[1]);
+
+ if (c0 != c1)
+ {
+ error ("%s: %<-fcompare-debug%> failure",
+ gcc_input_filename);
+ ret = 1;
+ break;
+ }
+
+ if (c0 == EOF)
+ break;
+ }
+
+ for (i = 1; i >= 0; i--)
+ {
+ if (temp[i])
+ fclose (temp[i]);
+ }
+
+ return ret;
+}
+
+driver::driver (bool can_finalize, bool debug) :
+ explicit_link_files (NULL),
+ decoded_options (NULL)
+{
+ env.init (can_finalize, debug);
+}
+
+driver::~driver ()
+{
+ XDELETEVEC (explicit_link_files);
+ XDELETEVEC (decoded_options);
+}
+
+/* driver::main is implemented as a series of driver:: method calls. */
+
+int
+driver::main (int argc, char **argv)
+{
+ bool early_exit;
+
+ set_progname (argv[0]);
+ expand_at_files (&argc, &argv);
+ decode_argv (argc, const_cast <const char **> (argv));
+ global_initializations ();
+ build_multilib_strings ();
+ set_up_specs ();
+ putenv_COLLECT_AS_OPTIONS (assembler_options);
+ putenv_COLLECT_GCC (argv[0]);
+ maybe_putenv_COLLECT_LTO_WRAPPER ();
+ maybe_putenv_OFFLOAD_TARGETS ();
+ handle_unrecognized_options ();
+
+ if (completion)
+ {
+ // sdcpp m_option_proposer.suggest_completion (completion);
+ return 0;
+ }
+
+ if (!maybe_print_and_exit ())
+ return 0;
+
+ early_exit = prepare_infiles ();
+ if (early_exit)
+ return get_exit_code ();
+
+ do_spec_on_infiles ();
+ maybe_run_linker (argv[0]);
+ final_actions ();
+ return get_exit_code ();
+}
+
+/* Locate the final component of argv[0] after any leading path, and set
+ the program name accordingly. */
+
+void
+driver::set_progname (const char *argv0) const
+{
+ const char *p = argv0 + strlen (argv0);
+ while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
+ --p;
+ progname = p;
+
+ xmalloc_set_program_name (progname);
+}
+
+/* Expand any @ files within the command-line args,
+ setting at_file_supplied if any were expanded. */
+
+void
+driver::expand_at_files (int *argc, char ***argv) const
+{
+ char **old_argv = *argv;
+
+ expandargv (argc, argv);
+
+ /* Determine if any expansions were made. */
+ if (*argv != old_argv)
+ at_file_supplied = true;
+}
+
+/* Decode the command-line arguments from argc/argv into the
+ decoded_options array. */
+
+void
+driver::decode_argv (int argc, const char **argv)
+{
+ init_opts_obstack ();
+ init_options_struct (&global_options, &global_options_set);
+
+ decode_cmdline_options_to_array (argc, argv,
+ CL_DRIVER,
+ &decoded_options, &decoded_options_count);
+}
+
+/* Perform various initializations and setup. */
+
+void
+driver::global_initializations ()
+{
+ /* Unlock the stdio streams. */
+ unlock_std_streams ();
+
+ gcc_init_libintl ();
+
+ diagnostic_initialize (global_dc, 0);
+ diagnostic_color_init (global_dc);
+ diagnostic_urls_init (global_dc);
+
+#ifdef GCC_DRIVER_HOST_INITIALIZATION
+ /* Perform host dependent initialization when needed. */
+ GCC_DRIVER_HOST_INITIALIZATION;
+#endif
+
+ if (atexit (delete_temp_files) != 0)
+ fatal_error (input_location, "atexit failed");
+
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN)
+ signal (SIGINT, fatal_signal);
+#ifdef SIGHUP
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
+ signal (SIGHUP, fatal_signal);
+#endif
+ if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
+ signal (SIGTERM, fatal_signal);
+#ifdef SIGPIPE
+ if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
+ signal (SIGPIPE, fatal_signal);
+#endif
+#ifdef SIGCHLD
+ /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+ receive the signal. A different setting is inheritable */
+ signal (SIGCHLD, SIG_DFL);
+#endif
+
+ /* Parsing and gimplification sometimes need quite large stack.
+ Increase stack size limits if possible. */
+ stack_limit_increase (64 * 1024 * 1024);
+
+ /* Allocate the argument vector. */
+ alloc_args ();
+
+ obstack_init (&obstack);
+}
+
+/* Build multilib_select, et. al from the separate lines that make up each
+ multilib selection. */
+
+void
+driver::build_multilib_strings () const
+{
+ {
+ const char *p;
+ const char *const *q = multilib_raw;
+ int need_space;
+
+ obstack_init (&multilib_obstack);
+ while ((p = *q++) != (char *) 0)
+ obstack_grow (&multilib_obstack, p, strlen (p));
+
+ obstack_1grow (&multilib_obstack, 0);
+ multilib_select = XOBFINISH (&multilib_obstack, const char *);
+
+ q = multilib_matches_raw;
+ while ((p = *q++) != (char *) 0)
+ obstack_grow (&multilib_obstack, p, strlen (p));
+
+ obstack_1grow (&multilib_obstack, 0);
+ multilib_matches = XOBFINISH (&multilib_obstack, const char *);
+
+ q = multilib_exclusions_raw;
+ while ((p = *q++) != (char *) 0)
+ obstack_grow (&multilib_obstack, p, strlen (p));
+
+ obstack_1grow (&multilib_obstack, 0);
+ multilib_exclusions = XOBFINISH (&multilib_obstack, const char *);
+
+ q = multilib_reuse_raw;
+ while ((p = *q++) != (char *) 0)
+ obstack_grow (&multilib_obstack, p, strlen (p));
+
+ obstack_1grow (&multilib_obstack, 0);
+ multilib_reuse = XOBFINISH (&multilib_obstack, const char *);
+
+ need_space = FALSE;
+ for (size_t i = 0; i < ARRAY_SIZE (multilib_defaults_raw); i++)
+ {
+ if (need_space)
+ obstack_1grow (&multilib_obstack, ' ');
+ obstack_grow (&multilib_obstack,
+ multilib_defaults_raw[i],
+ strlen (multilib_defaults_raw[i]));
+ need_space = TRUE;
+ }
+
+ obstack_1grow (&multilib_obstack, 0);
+ multilib_defaults = XOBFINISH (&multilib_obstack, const char *);
+ }
+}
+
+/* Set up the spec-handling machinery. */
+
+void
+driver::set_up_specs () const
+{
+ const char *spec_machine_suffix;
+ char *specs_file;
+ size_t i;
+
+#ifdef INIT_ENVIRONMENT
+ /* Set up any other necessary machine specific environment variables. */
+ xputenv (INIT_ENVIRONMENT);
+#endif
+
+ /* Make a table of what switches there are (switches, n_switches).
+ Make a table of specified input files (infiles, n_infiles).
+ Decode switches that are handled locally. */
+
+ process_command (decoded_options_count, decoded_options);
+
+ /* Initialize the vector of specs to just the default.
+ This means one element containing 0s, as a terminator. */
+
+ compilers = XNEWVAR (struct compiler, sizeof default_compilers);
+ memcpy (compilers, default_compilers, sizeof default_compilers);
+ n_compilers = n_default_compilers;
+
+ /* Read specs from a file if there is one. */
+
+ machine_suffix = concat (spec_host_machine, dir_separator_str, spec_version,
+ accel_dir_suffix, dir_separator_str, NULL);
+ just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
+
+ specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
+ /* Read the specs file unless it is a default one. */
+ if (specs_file != 0 && strcmp (specs_file, "specs"))
+ read_specs (specs_file, true, false);
+ else
+ init_spec ();
+
+#ifdef ACCEL_COMPILER
+ spec_machine_suffix = machine_suffix;
+#else
+ spec_machine_suffix = just_machine_suffix;
+#endif
+
+ /* We need to check standard_exec_prefix/spec_machine_suffix/specs
+ for any override of as, ld and libraries. */
+ specs_file = (char *) alloca (strlen (standard_exec_prefix)
+ + strlen (spec_machine_suffix) + sizeof ("specs"));
+ strcpy (specs_file, standard_exec_prefix);
+ strcat (specs_file, spec_machine_suffix);
+ strcat (specs_file, "specs");
+ if (access (specs_file, R_OK) == 0)
+ read_specs (specs_file, true, false);
+
+ /* Process any configure-time defaults specified for the command line
+ options, via OPTION_DEFAULT_SPECS. */
+ for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
+ do_option_spec (option_default_specs[i].name,
+ option_default_specs[i].spec);
+
+ /* Process DRIVER_SELF_SPECS, adding any new options to the end
+ of the command line. */
+
+ for (i = 0; i < ARRAY_SIZE (driver_self_specs); i++)
+ do_self_spec (driver_self_specs[i]);
+
+ /* If not cross-compiling, look for executables in the standard
+ places. */
+ if (*cross_compile == '0')
+ {
+ if (*md_exec_prefix)
+ {
+ add_prefix (&exec_prefixes, md_exec_prefix, "GCC",
+ PREFIX_PRIORITY_LAST, 0, 0);
+ }
+ }
+
+ /* Process sysroot_suffix_spec. */
+ if (*sysroot_suffix_spec != 0
+ && !no_sysroot_suffix
+ && do_spec_2 (sysroot_suffix_spec, NULL) == 0)
+ {
+ if (argbuf.length () > 1)
+ error ("spec failure: more than one argument to "
+ "%<SYSROOT_SUFFIX_SPEC%>");
+ else if (argbuf.length () == 1)
+ target_sysroot_suffix = xstrdup (argbuf.last ());
+ }
+
+#ifdef HAVE_LD_SYSROOT
+ /* Pass the --sysroot option to the linker, if it supports that. If
+ there is a sysroot_suffix_spec, it has already been processed by
+ this point, so target_system_root really is the system root we
+ should be using. */
+ if (target_system_root)
+ {
+ obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
+ obstack_grow0 (&obstack, link_spec, strlen (link_spec));
+ set_spec ("link", XOBFINISH (&obstack, const char *), false);
+ }
+#endif
+
+ /* Process sysroot_hdrs_suffix_spec. */
+ if (*sysroot_hdrs_suffix_spec != 0
+ && !no_sysroot_suffix
+ && do_spec_2 (sysroot_hdrs_suffix_spec, NULL) == 0)
+ {
+ if (argbuf.length () > 1)
+ error ("spec failure: more than one argument "
+ "to %<SYSROOT_HEADERS_SUFFIX_SPEC%>");
+ else if (argbuf.length () == 1)
+ target_sysroot_hdrs_suffix = xstrdup (argbuf.last ());
+ }
+
+ /* Look for startfiles in the standard places. */
+ if (*startfile_prefix_spec != 0
+ && do_spec_2 (startfile_prefix_spec, NULL) == 0
+ && do_spec_1 (" ", 0, NULL) == 0)
+ {
+ for (const char *arg : argbuf)
+ add_sysrooted_prefix (&startfile_prefixes, arg, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 0, 1);
+ }
+ /* We should eventually get rid of all these and stick to
+ startfile_prefix_spec exclusively. */
+ else if (*cross_compile == '0' || target_system_root)
+ {
+ if (*md_startfile_prefix)
+ add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix,
+ "GCC", PREFIX_PRIORITY_LAST, 0, 1);
+
+ if (*md_startfile_prefix_1)
+ add_sysrooted_prefix (&startfile_prefixes, md_startfile_prefix_1,
+ "GCC", PREFIX_PRIORITY_LAST, 0, 1);
+
+ /* If standard_startfile_prefix is relative, base it on
+ standard_exec_prefix. This lets us move the installed tree
+ as a unit. If GCC_EXEC_PREFIX is defined, base
+ standard_startfile_prefix on that as well.
+
+ If the prefix is relative, only search it for native compilers;
+ otherwise we will search a directory containing host libraries. */
+ if (IS_ABSOLUTE_PATH (standard_startfile_prefix))
+ add_sysrooted_prefix (&startfile_prefixes,
+ standard_startfile_prefix, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 0, 1);
+ else if (*cross_compile == '0')
+ {
+ add_prefix (&startfile_prefixes,
+ concat (gcc_exec_prefix
+ ? gcc_exec_prefix : standard_exec_prefix,
+ machine_suffix,
+ standard_startfile_prefix, NULL),
+ NULL, PREFIX_PRIORITY_LAST, 0, 1);
+ }
+
+ /* Sysrooted prefixes are relocated because target_system_root is
+ also relocated by gcc_exec_prefix. */
+ if (*standard_startfile_prefix_1)
+ add_sysrooted_prefix (&startfile_prefixes,
+ standard_startfile_prefix_1, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 0, 1);
+ if (*standard_startfile_prefix_2)
+ add_sysrooted_prefix (&startfile_prefixes,
+ standard_startfile_prefix_2, "BINUTILS",
+ PREFIX_PRIORITY_LAST, 0, 1);
+ }
+
+ /* Process any user specified specs in the order given on the command
+ line. */
+ for (struct user_specs *uptr = user_specs_head; uptr; uptr = uptr->next)
+ {
+ char *filename = find_a_file (&startfile_prefixes, uptr->filename,
+ R_OK, true);
+ read_specs (filename ? filename : uptr->filename, false, true);
+ }
+
+ /* Process any user self specs. */
+ {
+ struct spec_list *sl;
+ for (sl = specs; sl; sl = sl->next)
+ if (sl->name_len == sizeof "self_spec" - 1
+ && !strcmp (sl->name, "self_spec"))
+ do_self_spec (*sl->ptr_spec);
+ }
+
+ if (compare_debug)
+ {
+ enum save_temps save;
+
+ if (!compare_debug_second)
+ {
+ n_switches_debug_check[1] = n_switches;
+ n_switches_alloc_debug_check[1] = n_switches_alloc;
+ switches_debug_check[1] = XDUPVEC (struct switchstr, switches,
+ n_switches_alloc);
+
+ do_self_spec ("%:compare-debug-self-opt()");
+ n_switches_debug_check[0] = n_switches;
+ n_switches_alloc_debug_check[0] = n_switches_alloc;
+ switches_debug_check[0] = switches;
+
+ n_switches = n_switches_debug_check[1];
+ n_switches_alloc = n_switches_alloc_debug_check[1];
+ switches = switches_debug_check[1];
+ }
+
+ /* Avoid crash when computing %j in this early. */
+ save = save_temps_flag;
+ save_temps_flag = SAVE_TEMPS_NONE;
+
+ compare_debug = -compare_debug;
+ do_self_spec ("%:compare-debug-self-opt()");
+
+ save_temps_flag = save;
+
+ if (!compare_debug_second)
+ {
+ n_switches_debug_check[1] = n_switches;
+ n_switches_alloc_debug_check[1] = n_switches_alloc;
+ switches_debug_check[1] = switches;
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[0];
+ n_switches_alloc = n_switches_debug_check[0];
+ switches = switches_debug_check[0];
+ }
+ }
+
+
+ /* If we have a GCC_EXEC_PREFIX envvar, modify it for cpp's sake. */
+ if (gcc_exec_prefix)
+ gcc_exec_prefix = concat (gcc_exec_prefix, spec_host_machine,
+ dir_separator_str, spec_version,
+ accel_dir_suffix, dir_separator_str, NULL);
+
+ /* Now we have the specs.
+ Set the `valid' bits for switches that match anything in any spec. */
+
+ validate_all_switches ();
+
+ /* Now that we have the switches and the specs, set
+ the subdirectory based on the options. */
+ set_multilib_dir ();
+}
+
+/* Set up to remember the pathname of gcc and any options
+ needed for collect. We use argv[0] instead of progname because
+ we need the complete pathname. */
+
+void
+driver::putenv_COLLECT_GCC (const char *argv0) const
+{
+ obstack_init (&collect_obstack);
+ obstack_grow (&collect_obstack, "COLLECT_GCC=", sizeof ("COLLECT_GCC=") - 1);
+ obstack_grow (&collect_obstack, argv0, strlen (argv0) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+}
+
+/* Set up to remember the pathname of the lto wrapper. */
+
+void
+driver::maybe_putenv_COLLECT_LTO_WRAPPER () const
+{
+ char *lto_wrapper_file;
+
+ if (have_c)
+ lto_wrapper_file = NULL;
+ else
+ lto_wrapper_file = find_a_program ("lto-wrapper");
+ if (lto_wrapper_file)
+ {
+ lto_wrapper_file = convert_white_space (lto_wrapper_file);
+ set_static_spec_owned (&lto_wrapper_spec, lto_wrapper_file);
+ obstack_init (&collect_obstack);
+ obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
+ sizeof ("COLLECT_LTO_WRAPPER=") - 1);
+ obstack_grow (&collect_obstack, lto_wrapper_spec,
+ strlen (lto_wrapper_spec) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+ }
+
+}
+
+/* Set up to remember the names of offload targets. */
+
+void
+driver::maybe_putenv_OFFLOAD_TARGETS () const
+{
+ if (offload_targets && offload_targets[0] != '\0')
+ {
+ obstack_grow (&collect_obstack, "OFFLOAD_TARGET_NAMES=",
+ sizeof ("OFFLOAD_TARGET_NAMES=") - 1);
+ obstack_grow (&collect_obstack, offload_targets,
+ strlen (offload_targets) + 1);
+ xputenv (XOBFINISH (&collect_obstack, char *));
+#if OFFLOAD_DEFAULTED
+ if (offload_targets_default)
+ xputenv ("OFFLOAD_TARGET_DEFAULT=1");
+#endif
+ }
+
+ free (offload_targets);
+ offload_targets = NULL;
+}
+
+/* Reject switches that no pass was interested in. */
+
+void
+driver::handle_unrecognized_options ()
+{
+ for (size_t i = 0; (int) i < n_switches; i++)
+ if (! switches[i].validated)
+ {
+ const char *hint = 0; // sdcpp m_option_proposer.suggest_option (switches[i].part1);
+ if (hint)
+ error ("bbunrecognized command-line option %<-%s%>;"
+ " did you mean %<-%s%>?",
+ switches[i].part1, hint);
+ else
+ error ("ccunrecognized command-line option %<-%s%>",
+ switches[i].part1);
+ }
+ else
+ {
+ }
+}
+
+/* Handle the various -print-* options, returning 0 if the driver
+ should exit, or nonzero if the driver should continue. */
+
+int
+driver::maybe_print_and_exit () const
+{
+ if (print_search_dirs)
+ {
+ printf (_("install: %s%s\n"),
+ gcc_exec_prefix ? gcc_exec_prefix : standard_exec_prefix,
+ gcc_exec_prefix ? "" : machine_suffix);
+ printf (_("programs: %s\n"),
+ build_search_list (&exec_prefixes, "", false, false));
+ printf (_("libraries: %s\n"),
+ build_search_list (&startfile_prefixes, "", false, true));
+ return (0);
+ }
+
+ if (print_file_name)
+ {
+ printf ("%s\n", find_file (print_file_name));
+ return (0);
+ }
+
+ if (print_prog_name)
+ {
+ if (use_ld != NULL && ! strcmp (print_prog_name, "ld"))
+ {
+ /* Append USE_LD to the default linker. */
+#ifdef DEFAULT_LINKER
+ char *ld;
+# ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+ int len = (sizeof (DEFAULT_LINKER)
+ - sizeof (HOST_EXECUTABLE_SUFFIX));
+ ld = NULL;
+ if (len > 0)
+ {
+ char *default_linker = xstrdup (DEFAULT_LINKER);
+ /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains
+ HOST_EXECUTABLE_SUFFIX. */
+ if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX))
+ {
+ default_linker[len] = '\0';
+ ld = concat (default_linker, use_ld,
+ HOST_EXECUTABLE_SUFFIX, NULL);
+ }
+ }
+ if (ld == NULL)
+# endif
+ ld = concat (DEFAULT_LINKER, use_ld, NULL);
+ if (access (ld, X_OK) == 0)
+ {
+ printf ("%s\n", ld);
+ return (0);
+ }
+#endif
+ print_prog_name = concat (print_prog_name, use_ld, NULL);
+ }
+ char *newname = find_a_program (print_prog_name);
+ printf ("%s\n", (newname ? newname : print_prog_name));
+ return (0);
+ }
+
+ if (print_multi_lib)
+ {
+ print_multilib_info ();
+ return (0);
+ }
+
+ if (print_multi_directory)
+ {
+ if (multilib_dir == NULL)
+ printf (".\n");
+ else
+ printf ("%s\n", multilib_dir);
+ return (0);
+ }
+
+ if (print_multiarch)
+ {
+ if (multiarch_dir == NULL)
+ printf ("\n");
+ else
+ printf ("%s\n", multiarch_dir);
+ return (0);
+ }
+
+ if (print_sysroot)
+ {
+ if (target_system_root)
+ {
+ if (target_sysroot_suffix)
+ printf ("%s%s\n", target_system_root, target_sysroot_suffix);
+ else
+ printf ("%s\n", target_system_root);
+ }
+ return (0);
+ }
+
+ if (print_multi_os_directory)
+ {
+ if (multilib_os_dir == NULL)
+ printf (".\n");
+ else
+ printf ("%s\n", multilib_os_dir);
+ return (0);
+ }
+
+ if (print_sysroot_headers_suffix)
+ {
+ if (*sysroot_hdrs_suffix_spec)
+ {
+ printf("%s\n", (target_sysroot_hdrs_suffix
+ ? target_sysroot_hdrs_suffix
+ : ""));
+ return (0);
+ }
+ else
+ /* The error status indicates that only one set of fixed
+ headers should be built. */
+ fatal_error (input_location,
+ "not configured with sysroot headers suffix");
+ }
+
+ if (print_help_list)
+ {
+ display_help ();
+
+ if (! verbose_flag)
+ {
+ printf (_("\nFor bug reporting instructions, please see:\n"));
+ printf ("%s.\n", bug_report_url);
+
+ return (0);
+ }
+
+ /* We do not exit here. Instead we have created a fake input file
+ called 'help-dummy' which needs to be compiled, and we pass this
+ on the various sub-processes, along with the --help switch.
+ Ensure their output appears after ours. */
+ fputc ('\n', stdout);
+ fflush (stdout);
+ }
+
+ if (print_version)
+ {
+ printf (_("%s %s%s\n"), progname, pkgversion_string,
+ version_string);
+ printf ("Copyright %s 2022 Free Software Foundation, Inc.\n",
+ _("(C)"));
+ fputs (_("This is free software; see the source for copying conditions. There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
+ stdout);
+ if (! verbose_flag)
+ return 0;
+
+ /* We do not exit here. We use the same mechanism of --help to print
+ the version of the sub-processes. */
+ fputc ('\n', stdout);
+ fflush (stdout);
+ }
+
+ if (verbose_flag)
+ {
+ print_configuration (stderr);
+ if (n_infiles == 0)
+ return (0);
+ }
+
+ return 1;
+}
+
+/* Figure out what to do with each input file.
+ Return true if we need to exit early from "main", false otherwise. */
+
+bool
+driver::prepare_infiles ()
+{
+ size_t i;
+ int lang_n_infiles = 0;
+
+ if (n_infiles == added_libraries)
+ fatal_error (input_location, "no input files");
+
+ if (seen_error ())
+ /* Early exit needed from main. */
+ return true;
+
+ /* Make a place to record the compiler output file names
+ that correspond to the input files. */
+
+ i = n_infiles;
+ i += lang_specific_extra_outfiles;
+ outfiles = XCNEWVEC (const char *, i);
+
+ /* Record which files were specified explicitly as link input. */
+
+ explicit_link_files = XCNEWVEC (char, n_infiles);
+
+ combine_inputs = have_o || flag_wpa;
+
+ for (i = 0; (int) i < n_infiles; i++)
+ {
+ const char *name = infiles[i].name;
+ struct compiler *compiler = lookup_compiler (name,
+ strlen (name),
+ infiles[i].language);
+
+ if (compiler && !(compiler->combinable))
+ combine_inputs = false;
+
+ if (lang_n_infiles > 0 && compiler != input_file_compiler
+ && infiles[i].language && infiles[i].language[0] != '*')
+ infiles[i].incompiler = compiler;
+ else if (compiler)
+ {
+ lang_n_infiles++;
+ input_file_compiler = compiler;
+ infiles[i].incompiler = compiler;
+ }
+ else
+ {
+ /* Since there is no compiler for this input file, assume it is a
+ linker file. */
+ explicit_link_files[i] = 1;
+ infiles[i].incompiler = NULL;
+ }
+ infiles[i].compiled = false;
+ infiles[i].preprocessed = false;
+ }
+
+ if (!combine_inputs && have_c && have_o && lang_n_infiles > 1)
+ fatal_error (input_location,
+ "cannot specify %<-o%> with %<-c%>, %<-S%> or %<-E%> "
+ "with multiple files");
+
+ /* No early exit needed from main; we can continue. */
+ return false;
+}
+
+/* Run the spec machinery on each input file. */
+
+void
+driver::do_spec_on_infiles () const
+{
+ size_t i;
+
+ for (i = 0; (int) i < n_infiles; i++)
+ {
+ int this_file_error = 0;
+
+ /* Tell do_spec what to substitute for %i. */
+
+ input_file_number = i;
+ set_input (infiles[i].name);
+
+ if (infiles[i].compiled)
+ continue;
+
+ /* Use the same thing in %o, unless cp->spec says otherwise. */
+
+ outfiles[i] = gcc_input_filename;
+
+ /* Figure out which compiler from the file's suffix. */
+
+ input_file_compiler
+ = lookup_compiler (infiles[i].name, input_filename_length,
+ infiles[i].language);
+
+ if (input_file_compiler)
+ {
+ /* Ok, we found an applicable compiler. Run its spec. */
+
+ if (input_file_compiler->spec[0] == '#')
+ {
+ error ("%s: %s compiler not installed on this system",
+ gcc_input_filename, &input_file_compiler->spec[1]);
+ this_file_error = 1;
+ }
+ else
+ {
+ int value;
+
+ if (compare_debug)
+ {
+ free (debug_check_temp_file[0]);
+ debug_check_temp_file[0] = NULL;
+
+ free (debug_check_temp_file[1]);
+ debug_check_temp_file[1] = NULL;
+ }
+
+ value = do_spec (input_file_compiler->spec);
+ infiles[i].compiled = true;
+ if (value < 0)
+ this_file_error = 1;
+ else if (compare_debug && debug_check_temp_file[0])
+ {
+ if (verbose_flag)
+ inform (UNKNOWN_LOCATION,
+ "recompiling with %<-fcompare-debug%>");
+
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[1];
+ n_switches_alloc = n_switches_alloc_debug_check[1];
+ switches = switches_debug_check[1];
+
+ value = do_spec (input_file_compiler->spec);
+
+ compare_debug = -compare_debug;
+ n_switches = n_switches_debug_check[0];
+ n_switches_alloc = n_switches_alloc_debug_check[0];
+ switches = switches_debug_check[0];
+
+ if (value < 0)
+ {
+ error ("during %<-fcompare-debug%> recompilation");
+ this_file_error = 1;
+ }
+
+ gcc_assert (debug_check_temp_file[1]
+ && filename_cmp (debug_check_temp_file[0],
+ debug_check_temp_file[1]));
+
+ if (verbose_flag)
+ inform (UNKNOWN_LOCATION, "comparing final insns dumps");
+
+ if (compare_files (debug_check_temp_file))
+ this_file_error = 1;
+ }
+
+ if (compare_debug)
+ {
+ free (debug_check_temp_file[0]);
+ debug_check_temp_file[0] = NULL;
+
+ free (debug_check_temp_file[1]);
+ debug_check_temp_file[1] = NULL;
+ }
+ }
+ }
+
+ /* If this file's name does not contain a recognized suffix,
+ record it as explicit linker input. */
+
+ else
+ explicit_link_files[i] = 1;
+
+ /* Clear the delete-on-failure queue, deleting the files in it
+ if this compilation failed. */
+
+ if (this_file_error)
+ {
+ delete_failure_queue ();
+ errorcount++;
+ }
+ /* If this compilation succeeded, don't delete those files later. */
+ clear_failure_queue ();
+ }
+
+ /* Reset the input file name to the first compile/object file name, for use
+ with %b in LINK_SPEC. We use the first input file that we can find
+ a compiler to compile it instead of using infiles.language since for
+ languages other than C we use aliases that we then lookup later. */
+ if (n_infiles > 0)
+ {
+ int i;
+
+ for (i = 0; i < n_infiles ; i++)
+ if (infiles[i].incompiler
+ || (infiles[i].language && infiles[i].language[0] != '*'))
+ {
+ set_input (infiles[i].name);
+ break;
+ }
+ }
+
+ if (!seen_error ())
+ {
+ /* Make sure INPUT_FILE_NUMBER points to first available open
+ slot. */
+ input_file_number = n_infiles;
+ if (lang_specific_pre_link ())
+ errorcount++;
+ }
+}
+
+/* If we have to run the linker, do it now. */
+
+void
+driver::maybe_run_linker (const char *argv0) const
+{
+ size_t i;
+ int linker_was_run = 0;
+ int num_linker_inputs;
+
+ /* Determine if there are any linker input files. */
+ num_linker_inputs = 0;
+ for (i = 0; (int) i < n_infiles; i++)
+ if (explicit_link_files[i] || outfiles[i] != NULL)
+ num_linker_inputs++;
+
+ /* Arrange for temporary file names created during linking to take
+ on names related with the linker output rather than with the
+ inputs when appropriate. */
+ if (outbase && *outbase)
+ {
+ if (dumpdir)
+ {
+ char *tofree = dumpdir;
+ gcc_checking_assert (strlen (dumpdir) == dumpdir_length);
+ dumpdir = concat (dumpdir, outbase, ".", NULL);
+ free (tofree);
+ }
+ else
+ dumpdir = concat (outbase, ".", NULL);
+ dumpdir_length += strlen (outbase) + 1;
+ dumpdir_trailing_dash_added = true;
+ }
+ else if (dumpdir_trailing_dash_added)
+ {
+ gcc_assert (dumpdir[dumpdir_length - 1] == '-');
+ dumpdir[dumpdir_length - 1] = '.';
+ }
+
+ if (dumpdir_trailing_dash_added)
+ {
+ gcc_assert (dumpdir_length > 0);
+ gcc_assert (dumpdir[dumpdir_length - 1] == '.');
+ dumpdir_length--;
+ }
+
+ free (outbase);
+ input_basename = outbase = NULL;
+ outbase_length = suffixed_basename_length = basename_length = 0;
+
+ /* Run ld to link all the compiler output files. */
+
+ if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
+ {
+ int tmp = execution_count;
+
+ detect_jobserver ();
+
+ if (! have_c)
+ {
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
+ const char *fno_use_linker_plugin = "fno-use-linker-plugin";
+#else
+ const char *fuse_linker_plugin = "fuse-linker-plugin";
+#endif
+#endif
+
+ /* We'll use ld if we can't find collect2. */
+ if (! strcmp (linker_name_spec, "collect2"))
+ {
+ char *s = find_a_program ("collect2");
+ if (s == NULL)
+ set_static_spec_shared (&linker_name_spec, "ld");
+ }
+
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
+ if (!switch_matches (fno_use_linker_plugin,
+ fno_use_linker_plugin
+ + strlen (fno_use_linker_plugin), 0))
+#else
+ if (switch_matches (fuse_linker_plugin,
+ fuse_linker_plugin
+ + strlen (fuse_linker_plugin), 0))
+#endif
+ {
+ char *temp_spec = find_a_file (&exec_prefixes,
+ LTOPLUGINSONAME, R_OK,
+ false);
+ if (!temp_spec)
+ fatal_error (input_location,
+ "%<-fuse-linker-plugin%>, but %s not found",
+ LTOPLUGINSONAME);
+ linker_plugin_file_spec = convert_white_space (temp_spec);
+ }
+#endif
+ set_static_spec_shared (&lto_gcc_spec, argv0);
+ }
+
+ /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
+ for collect. */
+ putenv_from_prefixes (&exec_prefixes, "COMPILER_PATH", false);
+ putenv_from_prefixes (&startfile_prefixes, LIBRARY_PATH_ENV, true);
+
+ if (print_subprocess_help == 1)
+ {
+ printf (_("\nLinker options\n==============\n\n"));
+ printf (_("Use \"-Wl,OPTION\" to pass \"OPTION\""
+ " to the linker.\n\n"));
+ fflush (stdout);
+ }
+ int value = do_spec (link_command_spec);
+ if (value < 0)
+ errorcount = 1;
+ linker_was_run = (tmp != execution_count);
+ }
+
+ /* If options said don't run linker,
+ complain about input files to be given to the linker. */
+
+ if (! linker_was_run && !seen_error ())
+ for (i = 0; (int) i < n_infiles; i++)
+ if (explicit_link_files[i]
+ && !(infiles[i].language && infiles[i].language[0] == '*'))
+ {
+ warning (0, "%s: linker input file unused because linking not done",
+ outfiles[i]);
+ if (access (outfiles[i], F_OK) < 0)
+ /* This is can be an indication the user specifed an errorneous
+ separated option value, (or used the wrong prefix for an
+ option). */
+ error ("%s: linker input file not found: %m", outfiles[i]);
+ }
+}
+
+/* The end of "main". */
+
+void
+driver::final_actions () const
+{
+ /* Delete some or all of the temporary files we made. */
+
+ if (seen_error ())
+ delete_failure_queue ();
+ delete_temp_files ();
+
+ if (print_help_list)
+ {
+ printf (("\nFor bug reporting instructions, please see:\n"));
+ printf ("%s\n", bug_report_url);
+ }
+}
+
+/* Detect whether jobserver is active and working. If not drop
+ --jobserver-auth from MAKEFLAGS. */
+
+void
+driver::detect_jobserver () const
+{
+ /* Detect jobserver and drop it if it's not working. */
+ const char *makeflags = env.get ("MAKEFLAGS");
+ if (makeflags != NULL)
+ {
+ const char *needle = "--jobserver-auth=";
+ const char *n = strstr (makeflags, needle);
+ if (n != NULL)
+ {
+ int rfd = -1;
+ int wfd = -1;
+
+ bool jobserver
+ = (sscanf (n + strlen (needle), "%d,%d", &rfd, &wfd) == 2
+ && rfd > 0
+ && wfd > 0
+ && is_valid_fd (rfd)
+ && is_valid_fd (wfd));
+
+ /* Drop the jobserver if it's not working now. */
+ if (!jobserver)
+ {
+ unsigned offset = n - makeflags;
+ char *dup = xstrdup (makeflags);
+ dup[offset] = '\0';
+
+ const char *space = strchr (makeflags + offset, ' ');
+ if (space != NULL)
+ strcpy (dup + offset, space);
+ xputenv (concat ("MAKEFLAGS=", dup, NULL));
+ }
+ }
+ }
+}
+
+/* Determine what the exit code of the driver should be. */
+
+int
+driver::get_exit_code () const
+{
+ return (signal_count != 0 ? 2
+ : seen_error () ? (pass_exit_codes ? greatest_status : 1)
+ : 0);
+}
+
+/* Find the proper compilation spec for the file name NAME,
+ whose length is LENGTH. LANGUAGE is the specified language,
+ or 0 if this file is to be passed to the linker. */
+
+static struct compiler *
+lookup_compiler (const char *name, size_t length, const char *language)
+{
+ struct compiler *cp;
+
+ /* If this was specified by the user to be a linker input, indicate that. */
+ if (language != 0 && language[0] == '*')
+ return 0;
+
+ /* Otherwise, look for the language, if one is spec'd. */
+ if (language != 0)
+ {
+ for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
+ if (cp->suffix[0] == '@' && !strcmp (cp->suffix + 1, language))
+ {
+ if (name != NULL && strcmp (name, "-") == 0
+ && (strcmp (cp->suffix, "@c-header") == 0
+ || strcmp (cp->suffix, "@c++-header") == 0)
+ && !have_E)
+ fatal_error (input_location,
+ "cannot use %<-%> as input filename for a "
+ "precompiled header");
+
+ return cp;
+ }
+
+ error ("language %s not recognized", language);
+ return 0;
+ }
+
+ /* Look for a suffix. */
+ for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
+ {
+ if (/* The suffix `-' matches only the file name `-'. */
+ (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
+ || (strlen (cp->suffix) < length
+ /* See if the suffix matches the end of NAME. */
+ && !strcmp (cp->suffix,
+ name + length - strlen (cp->suffix))
+ ))
+ break;
+ }
+
+#if defined (OS2) ||defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Look again, but case-insensitively this time. */
+ if (cp < compilers)
+ for (cp = compilers + n_compilers - 1; cp >= compilers; cp--)
+ {
+ if (/* The suffix `-' matches only the file name `-'. */
+ (!strcmp (cp->suffix, "-") && !strcmp (name, "-"))
+ || (strlen (cp->suffix) < length
+ /* See if the suffix matches the end of NAME. */
+ && ((!strcmp (cp->suffix,
+ name + length - strlen (cp->suffix))
+ || !strpbrk (cp->suffix, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+ && !strcasecmp (cp->suffix,
+ name + length - strlen (cp->suffix)))
+ ))
+ break;
+ }
+#endif
+
+ if (cp >= compilers)
+ {
+ if (cp->spec[0] != '@')
+ /* A non-alias entry: return it. */
+ return cp;
+
+ /* An alias entry maps a suffix to a language.
+ Search for the language; pass 0 for NAME and LENGTH
+ to avoid infinite recursion if language not found. */
+ return lookup_compiler (NULL, 0, cp->spec + 1);
+ }
+ return 0;
+}
+
+static char *
+save_string (const char *s, int len)
+{
+ char *result = XNEWVEC (char, len + 1);
+
+ gcc_checking_assert (strlen (s) >= (unsigned int) len);
+ memcpy (result, s, len);
+ result[len] = 0;
+ return result;
+}
+
+
+static inline void
+validate_switches_from_spec (const char *spec, bool user)
+{
+ const char *p = spec;
+ char c;
+ while ((c = *p++))
+ if (c == '%'
+ && (*p == '{'
+ || *p == '<'
+ || (*p == 'W' && *++p == '{')
+ || (*p == '@' && *++p == '{')))
+ /* We have a switch spec. */
+ p = validate_switches (p + 1, user, *p == '{');
+}
+
+static void
+validate_all_switches (void)
+{
+ struct compiler *comp;
+ struct spec_list *spec;
+
+ for (comp = compilers; comp->spec; comp++)
+ validate_switches_from_spec (comp->spec, false);
+
+ /* Look through the linked list of specs read from the specs file. */
+ for (spec = specs; spec; spec = spec->next)
+ validate_switches_from_spec (*spec->ptr_spec, spec->user_p);
+
+ validate_switches_from_spec (link_command_spec, false);
+}
+
+/* Look at the switch-name that comes after START and mark as valid
+ all supplied switches that match it. If BRACED, handle other
+ switches after '|' and '&', and specs after ':' until ';' or '}',
+ going back for more switches after ';'. Without BRACED, handle
+ only one atom. Return a pointer to whatever follows the handled
+ items, after the closing brace if BRACED. */
+
+static const char *
+validate_switches (const char *start, bool user_spec, bool braced)
+{
+ const char *p = start;
+ const char *atom;
+ size_t len;
+ int i;
+ bool suffix = false;
+ bool starred = false;
+
+#define SKIP_WHITE() do { while (*p == ' ' || *p == '\t') p++; } while (0)
+
+next_member:
+ SKIP_WHITE ();
+
+ if (*p == '!')
+ p++;
+
+ SKIP_WHITE ();
+ if (*p == '.' || *p == ',')
+ suffix = true, p++;
+
+ atom = p;
+ while (ISIDNUM (*p) || *p == '-' || *p == '+' || *p == '='
+ || *p == ',' || *p == '.' || *p == '@')
+ p++;
+ len = p - atom;
+
+ if (*p == '*')
+ starred = true, p++;
+
+ SKIP_WHITE ();
+
+ if (!suffix)
+ {
+ /* Mark all matching switches as valid. */
+ for (i = 0; i < n_switches; i++)
+ if (!strncmp (switches[i].part1, atom, len)
+ && (starred || switches[i].part1[len] == '\0')
+ && (switches[i].known || user_spec)){
+ switches[i].validated = true;
+ }
+ }
+
+ if (!braced)
+ return p;
+
+ if (*p) p++;
+ if (*p && (p[-1] == '|' || p[-1] == '&'))
+ goto next_member;
+
+ if (*p && p[-1] == ':')
+ {
+ while (*p && *p != ';' && *p != '}')
+ {
+ if (*p == '%')
+ {
+ p++;
+ if (*p == '{' || *p == '<')
+ p = validate_switches (p+1, user_spec, *p == '{');
+ else if (p[0] == 'W' && p[1] == '{')
+ p = validate_switches (p+2, user_spec, true);
+ else if (p[0] == '@' && p[1] == '{')
+ p = validate_switches (p+2, user_spec, true);
+ }
+ else
+ p++;
+ }
+
+ if (*p) p++;
+ if (*p && p[-1] == ';')
+ goto next_member;
+ }
+
+ return p;
+#undef SKIP_WHITE
+}
+
+struct mdswitchstr
+{
+ const char *str;
+ int len;
+};
+
+static struct mdswitchstr *mdswitches;
+static int n_mdswitches;
+
+/* Check whether a particular argument was used. The first time we
+ canonicalize the switches to keep only the ones we care about. */
+
+struct used_arg_t
+{
+ public:
+ int operator () (const char *p, int len);
+ void finalize ();
+
+ private:
+ struct mswitchstr
+ {
+ const char *str;
+ const char *replace;
+ int len;
+ int rep_len;
+ };
+
+ mswitchstr *mswitches;
+ int n_mswitches;
+
+};
+
+used_arg_t used_arg;
+
+int
+used_arg_t::operator () (const char *p, int len)
+{
+ int i, j;
+
+ if (!mswitches)
+ {
+ struct mswitchstr *matches;
+ const char *q;
+ int cnt = 0;
+
+ /* Break multilib_matches into the component strings of string
+ and replacement string. */
+ for (q = multilib_matches; *q != '\0'; q++)
+ if (*q == ';')
+ cnt++;
+
+ matches
+ = (struct mswitchstr *) alloca ((sizeof (struct mswitchstr)) * cnt);
+ i = 0;
+ q = multilib_matches;
+ while (*q != '\0')
+ {
+ matches[i].str = q;
+ while (*q != ' ')
+ {
+ if (*q == '\0')
+ {
+ invalid_matches:
+ fatal_error (input_location, "multilib spec %qs is invalid",
+ multilib_matches);
+ }
+ q++;
+ }
+ matches[i].len = q - matches[i].str;
+
+ matches[i].replace = ++q;
+ while (*q != ';' && *q != '\0')
+ {
+ if (*q == ' ')
+ goto invalid_matches;
+ q++;
+ }
+ matches[i].rep_len = q - matches[i].replace;
+ i++;
+ if (*q == ';')
+ q++;
+ }
+
+ /* Now build a list of the replacement string for switches that we care
+ about. Make sure we allocate at least one entry. This prevents
+ xmalloc from calling fatal, and prevents us from re-executing this
+ block of code. */
+ mswitches
+ = XNEWVEC (struct mswitchstr, n_mdswitches + (n_switches ? n_switches : 1));
+ for (i = 0; i < n_switches; i++)
+ if ((switches[i].live_cond & SWITCH_IGNORE) == 0)
+ {
+ int xlen = strlen (switches[i].part1);
+ for (j = 0; j < cnt; j++)
+ if (xlen == matches[j].len
+ && ! strncmp (switches[i].part1, matches[j].str, xlen))
+ {
+ mswitches[n_mswitches].str = matches[j].replace;
+ mswitches[n_mswitches].len = matches[j].rep_len;
+ mswitches[n_mswitches].replace = (char *) 0;
+ mswitches[n_mswitches].rep_len = 0;
+ n_mswitches++;
+ break;
+ }
+ }
+
+ /* Add MULTILIB_DEFAULTS switches too, as long as they were not present
+ on the command line nor any options mutually incompatible with
+ them. */
+ for (i = 0; i < n_mdswitches; i++)
+ {
+ const char *r;
+
+ for (q = multilib_options; *q != '\0'; *q && q++)
+ {
+ while (*q == ' ')
+ q++;
+
+ r = q;
+ while (strncmp (q, mdswitches[i].str, mdswitches[i].len) != 0
+ || strchr (" /", q[mdswitches[i].len]) == NULL)
+ {
+ while (*q != ' ' && *q != '/' && *q != '\0')
+ q++;
+ if (*q != '/')
+ break;
+ q++;
+ }
+
+ if (*q != ' ' && *q != '\0')
+ {
+ while (*r != ' ' && *r != '\0')
+ {
+ q = r;
+ while (*q != ' ' && *q != '/' && *q != '\0')
+ q++;
+
+ if (used_arg (r, q - r))
+ break;
+
+ if (*q != '/')
+ {
+ mswitches[n_mswitches].str = mdswitches[i].str;
+ mswitches[n_mswitches].len = mdswitches[i].len;
+ mswitches[n_mswitches].replace = (char *) 0;
+ mswitches[n_mswitches].rep_len = 0;
+ n_mswitches++;
+ break;
+ }
+
+ r = q + 1;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < n_mswitches; i++)
+ if (len == mswitches[i].len && ! strncmp (p, mswitches[i].str, len))
+ return 1;
+
+ return 0;
+}
+
+void used_arg_t::finalize ()
+{
+ XDELETEVEC (mswitches);
+ mswitches = NULL;
+ n_mswitches = 0;
+}
+
+
+static int
+default_arg (const char *p, int len)
+{
+ int i;
+
+ for (i = 0; i < n_mdswitches; i++)
+ if (len == mdswitches[i].len && ! strncmp (p, mdswitches[i].str, len))
+ return 1;
+
+ return 0;
+}
+
+/* Work out the subdirectory to use based on the options. The format of
+ multilib_select is a list of elements. Each element is a subdirectory
+ name followed by a list of options followed by a semicolon. The format
+ of multilib_exclusions is the same, but without the preceding
+ directory. First gcc will check the exclusions, if none of the options
+ beginning with an exclamation point are present, and all of the other
+ options are present, then we will ignore this completely. Passing
+ that, gcc will consider each multilib_select in turn using the same
+ rules for matching the options. If a match is found, that subdirectory
+ will be used.
+ A subdirectory name is optionally followed by a colon and the corresponding
+ multiarch name. */
+
+static void
+set_multilib_dir (void)
+{
+ const char *p;
+ unsigned int this_path_len;
+ const char *this_path, *this_arg;
+ const char *start, *end;
+ int not_arg;
+ int ok, ndfltok, first;
+
+ n_mdswitches = 0;
+ start = multilib_defaults;
+ while (*start == ' ' || *start == '\t')
+ start++;
+ while (*start != '\0')
+ {
+ n_mdswitches++;
+ while (*start != ' ' && *start != '\t' && *start != '\0')
+ start++;
+ while (*start == ' ' || *start == '\t')
+ start++;
+ }
+
+ if (n_mdswitches)
+ {
+ int i = 0;
+
+ mdswitches = XNEWVEC (struct mdswitchstr, n_mdswitches);
+ for (start = multilib_defaults; *start != '\0'; start = end + 1)
+ {
+ while (*start == ' ' || *start == '\t')
+ start++;
+
+ if (*start == '\0')
+ break;
+
+ for (end = start + 1;
+ *end != ' ' && *end != '\t' && *end != '\0'; end++)
+ ;
+
+ obstack_grow (&multilib_obstack, start, end - start);
+ obstack_1grow (&multilib_obstack, 0);
+ mdswitches[i].str = XOBFINISH (&multilib_obstack, const char *);
+ mdswitches[i++].len = end - start;
+
+ if (*end == '\0')
+ break;
+ }
+ }
+
+ p = multilib_exclusions;
+ while (*p != '\0')
+ {
+ /* Ignore newlines. */
+ if (*p == '\n')
+ {
+ ++p;
+ continue;
+ }
+
+ /* Check the arguments. */
+ ok = 1;
+ while (*p != ';')
+ {
+ if (*p == '\0')
+ {
+ invalid_exclusions:
+ fatal_error (input_location, "multilib exclusions %qs is invalid",
+ multilib_exclusions);
+ }
+
+ if (! ok)
+ {
+ ++p;
+ continue;
+ }
+
+ this_arg = p;
+ while (*p != ' ' && *p != ';')
+ {
+ if (*p == '\0')
+ goto invalid_exclusions;
+ ++p;
+ }
+
+ if (*this_arg != '!')
+ not_arg = 0;
+ else
+ {
+ not_arg = 1;
+ ++this_arg;
+ }
+
+ ok = used_arg (this_arg, p - this_arg);
+ if (not_arg)
+ ok = ! ok;
+
+ if (*p == ' ')
+ ++p;
+ }
+
+ if (ok)
+ return;
+
+ ++p;
+ }
+
+ first = 1;
+ p = multilib_select;
+
+ /* Append multilib reuse rules if any. With those rules, we can reuse
+ one multilib for certain different options sets. */
+ if (strlen (multilib_reuse) > 0)
+ p = concat (p, multilib_reuse, NULL);
+
+ while (*p != '\0')
+ {
+ /* Ignore newlines. */
+ if (*p == '\n')
+ {
+ ++p;
+ continue;
+ }
+
+ /* Get the initial path. */
+ this_path = p;
+ while (*p != ' ')
+ {
+ if (*p == '\0')
+ {
+ invalid_select:
+ fatal_error (input_location, "multilib select %qs %qs is invalid",
+ multilib_select, multilib_reuse);
+ }
+ ++p;
+ }
+ this_path_len = p - this_path;
+
+ /* Check the arguments. */
+ ok = 1;
+ ndfltok = 1;
+ ++p;
+ while (*p != ';')
+ {
+ if (*p == '\0')
+ goto invalid_select;
+
+ if (! ok)
+ {
+ ++p;
+ continue;
+ }
+
+ this_arg = p;
+ while (*p != ' ' && *p != ';')
+ {
+ if (*p == '\0')
+ goto invalid_select;
+ ++p;
+ }
+
+ if (*this_arg != '!')
+ not_arg = 0;
+ else
+ {
+ not_arg = 1;
+ ++this_arg;
+ }
+
+ /* If this is a default argument, we can just ignore it.
+ This is true even if this_arg begins with '!'. Beginning
+ with '!' does not mean that this argument is necessarily
+ inappropriate for this library: it merely means that
+ there is a more specific library which uses this
+ argument. If this argument is a default, we need not
+ consider that more specific library. */
+ ok = used_arg (this_arg, p - this_arg);
+ if (not_arg)
+ ok = ! ok;
+
+ if (! ok)
+ ndfltok = 0;
+
+ if (default_arg (this_arg, p - this_arg))
+ ok = 1;
+
+ if (*p == ' ')
+ ++p;
+ }
+
+ if (ok && first)
+ {
+ if (this_path_len != 1
+ || this_path[0] != '.')
+ {
+ char *new_multilib_dir = XNEWVEC (char, this_path_len + 1);
+ char *q;
+
+ strncpy (new_multilib_dir, this_path, this_path_len);
+ new_multilib_dir[this_path_len] = '\0';
+ q = strchr (new_multilib_dir, ':');
+ if (q != NULL)
+ *q = '\0';
+ multilib_dir = new_multilib_dir;
+ }
+ first = 0;
+ }
+
+ if (ndfltok)
+ {
+ const char *q = this_path, *end = this_path + this_path_len;
+
+ while (q < end && *q != ':')
+ q++;
+ if (q < end)
+ {
+ const char *q2 = q + 1, *ml_end = end;
+ char *new_multilib_os_dir;
+
+ while (q2 < end && *q2 != ':')
+ q2++;
+ if (*q2 == ':')
+ ml_end = q2;
+ if (ml_end - q == 1)
+ multilib_os_dir = xstrdup (".");
+ else
+ {
+ new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+ memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+ new_multilib_os_dir[ml_end - q - 1] = '\0';
+ multilib_os_dir = new_multilib_os_dir;
+ }
+
+ if (q2 < end && *q2 == ':')
+ {
+ char *new_multiarch_dir = XNEWVEC (char, end - q2);
+ memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+ new_multiarch_dir[end - q2 - 1] = '\0';
+ multiarch_dir = new_multiarch_dir;
+ }
+ break;
+ }
+ }
+
+ ++p;
+ }
+
+ if (multilib_dir == NULL && multilib_os_dir != NULL
+ && strcmp (multilib_os_dir, ".") == 0)
+ {
+ free (CONST_CAST (char *, multilib_os_dir));
+ multilib_os_dir = NULL;
+ }
+ else if (multilib_dir != NULL && multilib_os_dir == NULL)
+ multilib_os_dir = multilib_dir;
+}
+
+/* Print out the multiple library subdirectory selection
+ information. This prints out a series of lines. Each line looks
+ like SUBDIRECTORY;@OPTION@OPTION, with as many options as is
+ required. Only the desired options are printed out, the negative
+ matches. The options are print without a leading dash. There are
+ no spaces to make it easy to use the information in the shell.
+ Each subdirectory is printed only once. This assumes the ordering
+ generated by the genmultilib script. Also, we leave out ones that match
+ the exclusions. */
+
+static void
+print_multilib_info (void)
+{
+ const char *p = multilib_select;
+ const char *last_path = 0, *this_path;
+ int skip;
+ int not_arg;
+ unsigned int last_path_len = 0;
+
+ while (*p != '\0')
+ {
+ skip = 0;
+ /* Ignore newlines. */
+ if (*p == '\n')
+ {
+ ++p;
+ continue;
+ }
+
+ /* Get the initial path. */
+ this_path = p;
+ while (*p != ' ')
+ {
+ if (*p == '\0')
+ {
+ invalid_select:
+ fatal_error (input_location,
+ "multilib select %qs is invalid", multilib_select);
+ }
+
+ ++p;
+ }
+
+ /* When --disable-multilib was used but target defines
+ MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
+ with .:: for multiarch configurations) are there just to find
+ multilib_os_dir, so skip them from output. */
+ if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
+ skip = 1;
+
+ /* Check for matches with the multilib_exclusions. We don't bother
+ with the '!' in either list. If any of the exclusion rules match
+ all of its options with the select rule, we skip it. */
+ {
+ const char *e = multilib_exclusions;
+ const char *this_arg;
+
+ while (*e != '\0')
+ {
+ int m = 1;
+ /* Ignore newlines. */
+ if (*e == '\n')
+ {
+ ++e;
+ continue;
+ }
+
+ /* Check the arguments. */
+ while (*e != ';')
+ {
+ const char *q;
+ int mp = 0;
+
+ if (*e == '\0')
+ {
+ invalid_exclusion:
+ fatal_error (input_location,
+ "multilib exclusion %qs is invalid",
+ multilib_exclusions);
+ }
+
+ if (! m)
+ {
+ ++e;
+ continue;
+ }
+
+ this_arg = e;
+
+ while (*e != ' ' && *e != ';')
+ {
+ if (*e == '\0')
+ goto invalid_exclusion;
+ ++e;
+ }
+
+ q = p + 1;
+ while (*q != ';')
+ {
+ const char *arg;
+ int len = e - this_arg;
+
+ if (*q == '\0')
+ goto invalid_select;
+
+ arg = q;
+
+ while (*q != ' ' && *q != ';')
+ {
+ if (*q == '\0')
+ goto invalid_select;
+ ++q;
+ }
+
+ if (! strncmp (arg, this_arg,
+ (len < q - arg) ? q - arg : len)
+ || default_arg (this_arg, e - this_arg))
+ {
+ mp = 1;
+ break;
+ }
+
+ if (*q == ' ')
+ ++q;
+ }
+
+ if (! mp)
+ m = 0;
+
+ if (*e == ' ')
+ ++e;
+ }
+
+ if (m)
+ {
+ skip = 1;
+ break;
+ }
+
+ if (*e != '\0')
+ ++e;
+ }
+ }
+
+ if (! skip)
+ {
+ /* If this is a duplicate, skip it. */
+ skip = (last_path != 0
+ && (unsigned int) (p - this_path) == last_path_len
+ && ! filename_ncmp (last_path, this_path, last_path_len));
+
+ last_path = this_path;
+ last_path_len = p - this_path;
+ }
+
+ /* If all required arguments are default arguments, and no default
+ arguments appear in the ! argument list, then we can skip it.
+ We will already have printed a directory identical to this one
+ which does not require that default argument. */
+ if (! skip)
+ {
+ const char *q;
+ bool default_arg_ok = false;
+
+ q = p + 1;
+ while (*q != ';')
+ {
+ const char *arg;
+
+ if (*q == '\0')
+ goto invalid_select;
+
+ if (*q == '!')
+ {
+ not_arg = 1;
+ q++;
+ }
+ else
+ not_arg = 0;
+ arg = q;
+
+ while (*q != ' ' && *q != ';')
+ {
+ if (*q == '\0')
+ goto invalid_select;
+ ++q;
+ }
+
+ if (default_arg (arg, q - arg))
+ {
+ /* Stop checking if any default arguments appeared in not
+ list. */
+ if (not_arg)
+ {
+ default_arg_ok = false;
+ break;
+ }
+
+ default_arg_ok = true;
+ }
+ else if (!not_arg)
+ {
+ /* Stop checking if any required argument is not provided by
+ default arguments. */
+ default_arg_ok = false;
+ break;
+ }
+
+ if (*q == ' ')
+ ++q;
+ }
+
+ /* Make sure all default argument is OK for this multi-lib set. */
+ if (default_arg_ok)
+ skip = 1;
+ else
+ skip = 0;
+ }
+
+ if (! skip)
+ {
+ const char *p1;
+
+ for (p1 = last_path; p1 < p && *p1 != ':'; p1++)
+ putchar (*p1);
+ putchar (';');
+ }
+
+ ++p;
+ while (*p != ';')
+ {
+ int use_arg;
+
+ if (*p == '\0')
+ goto invalid_select;
+
+ if (skip)
+ {
+ ++p;
+ continue;
+ }
+
+ use_arg = *p != '!';
+
+ if (use_arg)
+ putchar ('@');
+
+ while (*p != ' ' && *p != ';')
+ {
+ if (*p == '\0')
+ goto invalid_select;
+ if (use_arg)
+ putchar (*p);
+ ++p;
+ }
+
+ if (*p == ' ')
+ ++p;
+ }
+
+ if (! skip)
+ {
+ /* If there are extra options, print them now. */
+ if (multilib_extra && *multilib_extra)
+ {
+ int print_at = TRUE;
+ const char *q;
+
+ for (q = multilib_extra; *q != '\0'; q++)
+ {
+ if (*q == ' ')
+ print_at = TRUE;
+ else
+ {
+ if (print_at)
+ putchar ('@');
+ putchar (*q);
+ print_at = FALSE;
+ }
+ }
+ }
+
+ putchar ('\n');
+ }
+
+ ++p;
+ }
+}
+
+/* getenv built-in spec function.
+
+ Returns the value of the environment variable given by its first argument,
+ concatenated with the second argument. If the variable is not defined, a
+ fatal error is issued unless such undefs are internally allowed, in which
+ case the variable name prefixed by a '/' is used as the variable value.
+
+ The leading '/' allows using the result at a spot where a full path would
+ normally be expected and when the actual value doesn't really matter since
+ undef vars are allowed. */
+
+static const char *
+getenv_spec_function (int argc, const char **argv)
+{
+ const char *value;
+ const char *varname;
+
+ char *result;
+ char *ptr;
+ size_t len;
+
+ if (argc != 2)
+ return NULL;
+
+ varname = argv[0];
+ value = env.get (varname);
+
+ /* If the variable isn't defined and this is allowed, craft our expected
+ return value. Assume variable names used in specs strings don't contain
+ any active spec character so don't need escaping. */
+ if (!value && spec_undefvar_allowed)
+ {
+ result = XNEWVAR (char, strlen(varname) + 2);
+ sprintf (result, "/%s", varname);
+ return result;
+ }
+
+ if (!value)
+ fatal_error (input_location,
+ "environment variable %qs not defined", varname);
+
+ /* We have to escape every character of the environment variable so
+ they are not interpreted as active spec characters. A
+ particularly painful case is when we are reading a variable
+ holding a windows path complete with \ separators. */
+ len = strlen (value) * 2 + strlen (argv[1]) + 1;
+ result = XNEWVAR (char, len);
+ for (ptr = result; *value; ptr += 2)
+ {
+ ptr[0] = '\\';
+ ptr[1] = *value++;
+ }
+
+ strcpy (ptr, argv[1]);
+
+ return result;
+}
+
+/* if-exists built-in spec function.
+
+ Checks to see if the file specified by the absolute pathname in
+ ARGS exists. Returns that pathname if found.
+
+ The usual use for this function is to check for a library file
+ (whose name has been expanded with %s). */
+
+static const char *
+if_exists_spec_function (int argc, const char **argv)
+{
+ /* Must have only one argument. */
+ if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
+ return argv[0];
+
+ return NULL;
+}
+
+/* if-exists-else built-in spec function.
+
+ This is like if-exists, but takes an additional argument which
+ is returned if the first argument does not exist. */
+
+static const char *
+if_exists_else_spec_function (int argc, const char **argv)
+{
+ /* Must have exactly two arguments. */
+ if (argc != 2)
+ return NULL;
+
+ if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
+ return argv[0];
+
+ return argv[1];
+}
+
+/* if-exists-then-else built-in spec function.
+
+ Checks to see if the file specified by the absolute pathname in
+ the first arg exists. Returns the second arg if so, otherwise returns
+ the third arg if it is present. */
+
+static const char *
+if_exists_then_else_spec_function (int argc, const char **argv)
+{
+
+ /* Must have two or three arguments. */
+ if (argc != 2 && argc != 3)
+ return NULL;
+
+ if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
+ return argv[1];
+
+ if (argc == 3)
+ return argv[2];
+
+ return NULL;
+}
+
+/* sanitize built-in spec function.
+
+ This returns non-NULL, if sanitizing address, thread or
+ any of the undefined behavior sanitizers. */
+
+static const char *
+sanitize_spec_function (int argc, const char **argv)
+{
+ if (argc != 1)
+ return NULL;
+
+ if (strcmp (argv[0], "address") == 0)
+ return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "hwaddress") == 0)
+ return (flag_sanitize & SANITIZE_USER_HWADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "kernel-address") == 0)
+ return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "kernel-hwaddress") == 0)
+ return (flag_sanitize & SANITIZE_KERNEL_HWADDRESS) ? "" : NULL;
+ if (strcmp (argv[0], "thread") == 0)
+ return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL;
+ if (strcmp (argv[0], "undefined") == 0)
+ return ((flag_sanitize
+ & (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT))
+ && !flag_sanitize_undefined_trap_on_error) ? "" : NULL;
+ if (strcmp (argv[0], "leak") == 0)
+ return ((flag_sanitize
+ & (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD))
+ == SANITIZE_LEAK) ? "" : NULL;
+ return NULL;
+}
+
+/* replace-outfile built-in spec function.
+
+ This looks for the first argument in the outfiles array's name and
+ replaces it with the second argument. */
+
+static const char *
+replace_outfile_spec_function (int argc, const char **argv)
+{
+ int i;
+ /* Must have exactly two arguments. */
+ if (argc != 2)
+ abort ();
+
+ for (i = 0; i < n_infiles; i++)
+ {
+ if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
+ outfiles[i] = xstrdup (argv[1]);
+ }
+ return NULL;
+}
+
+/* remove-outfile built-in spec function.
+ *
+ * This looks for the first argument in the outfiles array's name and
+ * removes it. */
+
+static const char *
+remove_outfile_spec_function (int argc, const char **argv)
+{
+ int i;
+ /* Must have exactly one argument. */
+ if (argc != 1)
+ abort ();
+
+ for (i = 0; i < n_infiles; i++)
+ {
+ if (outfiles[i] && !filename_cmp (outfiles[i], argv[0]))
+ outfiles[i] = NULL;
+ }
+ return NULL;
+}
+
+/* Given two version numbers, compares the two numbers.
+ A version number must match the regular expression
+ ([1-9][0-9]*|0)(\.([1-9][0-9]*|0))*
+*/
+static int
+compare_version_strings (const char *v1, const char *v2)
+{
+ int rresult;
+ regex_t r;
+
+ if (regcomp (&r, "^([1-9][0-9]*|0)(\\.([1-9][0-9]*|0))*$",
+ REG_EXTENDED | REG_NOSUB) != 0)
+ abort ();
+ rresult = regexec (&r, v1, 0, NULL, 0);
+ if (rresult == REG_NOMATCH)
+ fatal_error (input_location, "invalid version number %qs", v1);
+ else if (rresult != 0)
+ abort ();
+ rresult = regexec (&r, v2, 0, NULL, 0);
+ if (rresult == REG_NOMATCH)
+ fatal_error (input_location, "invalid version number %qs", v2);
+ else if (rresult != 0)
+ abort ();
+
+ return strverscmp (v1, v2);
+}
+
+
+/* version_compare built-in spec function.
+
+ This takes an argument of the following form:
+
+ <comparison-op> <arg1> [<arg2>] <switch> <result>
+
+ and produces "result" if the comparison evaluates to true,
+ and nothing if it doesn't.
+
+ The supported <comparison-op> values are:
+
+ >= true if switch is a later (or same) version than arg1
+ !> opposite of >=
+ < true if switch is an earlier version than arg1
+ !< opposite of <
+ >< true if switch is arg1 or later, and earlier than arg2
+ <> true if switch is earlier than arg1 or is arg2 or later
+
+ If the switch is not present, the condition is false unless
+ the first character of the <comparison-op> is '!'.
+
+ For example,
+ %:version-compare(>= 10.3 mmacosx-version-min= -lmx)
+ adds -lmx if -mmacosx-version-min=10.3.9 was passed. */
+
+static const char *
+version_compare_spec_function (int argc, const char **argv)
+{
+ int comp1, comp2;
+ size_t switch_len;
+ const char *switch_value = NULL;
+ int nargs = 1, i;
+ bool result;
+
+ if (argc < 3)
+ fatal_error (input_location, "too few arguments to %%:version-compare");
+ if (argv[0][0] == '\0')
+ abort ();
+ if ((argv[0][1] == '<' || argv[0][1] == '>') && argv[0][0] != '!')
+ nargs = 2;
+ if (argc != nargs + 3)
+ fatal_error (input_location, "too many arguments to %%:version-compare");
+
+ switch_len = strlen (argv[nargs + 1]);
+ for (i = 0; i < n_switches; i++)
+ if (!strncmp (switches[i].part1, argv[nargs + 1], switch_len)
+ && check_live_switch (i, switch_len))
+ switch_value = switches[i].part1 + switch_len;
+
+ if (switch_value == NULL)
+ comp1 = comp2 = -1;
+ else
+ {
+ comp1 = compare_version_strings (switch_value, argv[1]);
+ if (nargs == 2)
+ comp2 = compare_version_strings (switch_value, argv[2]);
+ else
+ comp2 = -1; /* This value unused. */
+ }
+
+ switch (argv[0][0] << 8 | argv[0][1])
+ {
+ case '>' << 8 | '=':
+ result = comp1 >= 0;
+ break;
+ case '!' << 8 | '<':
+ result = comp1 >= 0 || switch_value == NULL;
+ break;
+ case '<' << 8:
+ result = comp1 < 0;
+ break;
+ case '!' << 8 | '>':
+ result = comp1 < 0 || switch_value == NULL;
+ break;
+ case '>' << 8 | '<':
+ result = comp1 >= 0 && comp2 < 0;
+ break;
+ case '<' << 8 | '>':
+ result = comp1 < 0 || comp2 >= 0;
+ break;
+
+ default:
+ fatal_error (input_location,
+ "unknown operator %qs in %%:version-compare", argv[0]);
+ }
+ if (! result)
+ return NULL;
+
+ return argv[nargs + 2];
+}
+
+/* %:include builtin spec function. This differs from %include in that it
+ can be nested inside a spec, and thus be conditionalized. It takes
+ one argument, the filename, and looks for it in the startfile path.
+ The result is always NULL, i.e. an empty expansion. */
+
+static const char *
+include_spec_function (int argc, const char **argv)
+{
+ char *file;
+
+ if (argc != 1)
+ abort ();
+
+ file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
+ read_specs (file ? file : argv[0], false, false);
+
+ return NULL;
+}
+
+/* %:find-file spec function. This function replaces its argument by
+ the file found through find_file, that is the -print-file-name gcc
+ program option. */
+static const char *
+find_file_spec_function (int argc, const char **argv)
+{
+ const char *file;
+
+ if (argc != 1)
+ abort ();
+
+ file = find_file (argv[0]);
+ return file;
+}
+
+
+/* %:find-plugindir spec function. This function replaces its argument
+ by the -iplugindir=<dir> option. `dir' is found through find_file, that
+ is the -print-file-name gcc program option. */
+static const char *
+find_plugindir_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
+{
+ const char *option;
+
+ if (argc != 0)
+ abort ();
+
+ option = concat ("-iplugindir=", find_file ("plugin"), NULL);
+ return option;
+}
+
+
+/* %:print-asm-header spec function. Print a banner to say that the
+ following output is from the assembler. */
+
+static const char *
+print_asm_header_spec_function (int arg ATTRIBUTE_UNUSED,
+ const char **argv ATTRIBUTE_UNUSED)
+{
+ printf (_("Assembler options\n=================\n\n"));
+ printf (_("Use \"-Wa,OPTION\" to pass \"OPTION\" to the assembler.\n\n"));
+ fflush (stdout);
+ return NULL;
+}
+
+/* Get a random number for -frandom-seed */
+
+static unsigned HOST_WIDE_INT
+get_random_number (void)
+{
+ unsigned HOST_WIDE_INT ret = 0;
+ int fd;
+
+ fd = open ("/dev/urandom", O_RDONLY);
+ if (fd >= 0)
+ {
+ read (fd, &ret, sizeof (HOST_WIDE_INT));
+ close (fd);
+ if (ret)
+ return ret;
+ }
+
+ /* Get some more or less random data. */
+#ifdef HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ ret = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ }
+#else
+ {
+ time_t now = time (NULL);
+
+ if (now != (time_t)-1)
+ ret = (unsigned) now;
+ }
+#endif
+
+ return ret ^ getpid ();
+}
+
+/* %:compare-debug-dump-opt spec function. Save the last argument,
+ expected to be the last -fdump-final-insns option, or generate a
+ temporary. */
+
+static const char *
+compare_debug_dump_opt_spec_function (int arg,
+ const char **argv ATTRIBUTE_UNUSED)
+{
+ char *ret;
+ char *name;
+ int which;
+ static char random_seed[HOST_BITS_PER_WIDE_INT / 4 + 3];
+
+ if (arg != 0)
+ fatal_error (input_location,
+ "too many arguments to %%:compare-debug-dump-opt");
+
+ do_spec_2 ("%{fdump-final-insns=*:%*}", NULL);
+ do_spec_1 (" ", 0, NULL);
+
+ if (argbuf.length () > 0
+ && strcmp (argv[argbuf.length () - 1], ".") != 0)
+ {
+ if (!compare_debug)
+ return NULL;
+
+ name = xstrdup (argv[argbuf.length () - 1]);
+ ret = NULL;
+ }
+ else
+ {
+ if (argbuf.length () > 0)
+ do_spec_2 ("%B.gkd", NULL);
+ else if (!compare_debug)
+ return NULL;
+ else
+ do_spec_2 ("%{!save-temps*:%g.gkd}%{save-temps*:%B.gkd}", NULL);
+
+ do_spec_1 (" ", 0, NULL);
+
+ gcc_assert (argbuf.length () > 0);
+
+ name = xstrdup (argbuf.last ());
+
+ char *arg = quote_spec (xstrdup (name));
+ ret = concat ("-fdump-final-insns=", arg, NULL);
+ free (arg);
+ }
+
+ which = compare_debug < 0;
+ debug_check_temp_file[which] = name;
+
+ if (!which)
+ {
+ unsigned HOST_WIDE_INT value = get_random_number ();
+
+ sprintf (random_seed, HOST_WIDE_INT_PRINT_HEX, value);
+ }
+
+ if (*random_seed)
+ {
+ char *tmp = ret;
+ ret = concat ("%{!frandom-seed=*:-frandom-seed=", random_seed, "} ",
+ ret, NULL);
+ free (tmp);
+ }
+
+ if (which)
+ *random_seed = 0;
+
+ return ret;
+}
+
+/* %:compare-debug-self-opt spec function. Expands to the options
+ that are to be passed in the second compilation of
+ compare-debug. */
+
+static const char *
+compare_debug_self_opt_spec_function (int arg,
+ const char **argv ATTRIBUTE_UNUSED)
+{
+ if (arg != 0)
+ fatal_error (input_location,
+ "too many arguments to %%:compare-debug-self-opt");
+
+ if (compare_debug >= 0)
+ return NULL;
+
+ return concat ("\
+%<o %<MD %<MMD %<MF* %<MG %<MP %<MQ* %<MT* \
+%<fdump-final-insns=* -w -S -o %j \
+%{!fcompare-debug-second:-fcompare-debug-second} \
+", compare_debug_opt, NULL);
+}
+
+/* %:pass-through-libs spec function. Finds all -l options and input
+ file names in the lib spec passed to it, and makes a list of them
+ prepended with the plugin option to cause them to be passed through
+ to the final link after all the new object files have been added. */
+
+const char *
+pass_through_libs_spec_func (int argc, const char **argv)
+{
+ char *prepended = xstrdup (" ");
+ int n;
+ /* Shlemiel the painter's algorithm. Innately horrible, but at least
+ we know that there will never be more than a handful of strings to
+ concat, and it's only once per run, so it's not worth optimising. */
+ for (n = 0; n < argc; n++)
+ {
+ char *old = prepended;
+ /* Anything that isn't an option is a full path to an output
+ file; pass it through if it ends in '.a'. Among options,
+ pass only -l. */
+ if (argv[n][0] == '-' && argv[n][1] == 'l')
+ {
+ const char *lopt = argv[n] + 2;
+ /* Handle both joined and non-joined -l options. If for any
+ reason there's a trailing -l with no joined or following
+ arg just discard it. */
+ if (!*lopt && ++n >= argc)
+ break;
+ else if (!*lopt)
+ lopt = argv[n];
+ prepended = concat (prepended, "-plugin-opt=-pass-through=-l",
+ lopt, " ", NULL);
+ }
+ else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2))
+ {
+ prepended = concat (prepended, "-plugin-opt=-pass-through=",
+ argv[n], " ", NULL);
+ }
+ if (prepended != old)
+ free (old);
+ }
+ return prepended;
+}
+
+static bool
+not_actual_file_p (const char *name)
+{
+ return (strcmp (name, "-") == 0
+ || strcmp (name, HOST_BIT_BUCKET) == 0);
+}
+
+/* %:dumps spec function. Take an optional argument that overrides
+ the default extension for -dumpbase and -dumpbase-ext.
+ Return -dumpdir, -dumpbase and -dumpbase-ext, if needed. */
+const char *
+dumps_spec_func (int argc, const char **argv ATTRIBUTE_UNUSED)
+{
+ const char *ext = dumpbase_ext;
+ char *p;
+
+ char *args[3] = { NULL, NULL, NULL };
+ int nargs = 0;
+
+ /* Do not compute a default for -dumpbase-ext when -dumpbase was
+ given explicitly. */
+ if (dumpbase && *dumpbase && !ext)
+ ext = "";
+
+ if (argc == 1)
+ {
+ /* Do not override the explicitly-specified -dumpbase-ext with
+ the specs-provided overrider. */
+ if (!ext)
+ ext = argv[0];
+ }
+ else if (argc != 0)
+ fatal_error (input_location, "too many arguments for %%:dumps");
+
+ if (dumpdir)
+ {
+ p = quote_spec_arg (xstrdup (dumpdir));
+ args[nargs++] = concat (" -dumpdir ", p, NULL);
+ free (p);
+ }
+
+ if (!ext)
+ ext = input_basename + basename_length;
+
+ /* Use the precomputed outbase, or compute dumpbase from
+ input_basename, just like %b would. */
+ char *base;
+
+ if (dumpbase && *dumpbase)
+ {
+ base = xstrdup (dumpbase);
+ p = base + outbase_length;
+ gcc_checking_assert (strncmp (base, outbase, outbase_length) == 0);
+ gcc_checking_assert (strcmp (p, ext) == 0);
+ }
+ else if (outbase_length)
+ {
+ base = xstrndup (outbase, outbase_length);
+ p = NULL;
+ }
+ else
+ {
+ base = xstrndup (input_basename, suffixed_basename_length);
+ p = base + basename_length;
+ }
+
+ if (compare_debug < 0 || !p || strcmp (p, ext) != 0)
+ {
+ if (p)
+ *p = '\0';
+
+ const char *gk;
+ if (compare_debug < 0)
+ gk = ".gk";
+ else
+ gk = "";
+
+ p = concat (base, gk, ext, NULL);
+
+ free (base);
+ base = p;
+ }
+
+ base = quote_spec_arg (base);
+ args[nargs++] = concat (" -dumpbase ", base, NULL);
+ free (base);
+
+ if (*ext)
+ {
+ p = quote_spec_arg (xstrdup (ext));
+ args[nargs++] = concat (" -dumpbase-ext ", p, NULL);
+ free (p);
+ }
+
+ const char *ret = concat (args[0], args[1], args[2], NULL);
+ while (nargs > 0)
+ free (args[--nargs]);
+
+ return ret;
+}
+
+/* Returns "" if ARGV[ARGC - 2] is greater than ARGV[ARGC-1].
+ Otherwise, return NULL. */
+
+static const char *
+greater_than_spec_func (int argc, const char **argv)
+{
+ char *converted;
+
+ if (argc == 1)
+ return NULL;
+
+ gcc_assert (argc >= 2);
+
+ long arg = strtol (argv[argc - 2], &converted, 10);
+ gcc_assert (converted != argv[argc - 2]);
+
+ long lim = strtol (argv[argc - 1], &converted, 10);
+ gcc_assert (converted != argv[argc - 1]);
+
+ if (arg > lim)
+ return "";
+
+ return NULL;
+}
+
+/* Returns "" if debug_info_level is greater than ARGV[ARGC-1].
+ Otherwise, return NULL. */
+
+static const char *
+debug_level_greater_than_spec_func (int argc, const char **argv)
+{
+ char *converted;
+
+ if (argc != 1)
+ fatal_error (input_location,
+ "wrong number of arguments to %%:debug-level-gt");
+
+ long arg = strtol (argv[0], &converted, 10);
+ gcc_assert (converted != argv[0]);
+
+ if (debug_info_level > arg)
+ return "";
+
+ return NULL;
+}
+
+/* Returns "" if dwarf_version is greater than ARGV[ARGC-1].
+ Otherwise, return NULL. */
+
+static const char *
+dwarf_version_greater_than_spec_func (int argc, const char **argv)
+{
+ char *converted;
+
+ if (argc != 1)
+ fatal_error (input_location,
+ "wrong number of arguments to %%:dwarf-version-gt");
+
+ long arg = strtol (argv[0], &converted, 10);
+ gcc_assert (converted != argv[0]);
+
+ if (dwarf_version > arg)
+ return "";
+
+ return NULL;
+}
+
+static void
+path_prefix_reset (path_prefix *prefix)
+{
+ struct prefix_list *iter, *next;
+ iter = prefix->plist;
+ while (iter)
+ {
+ next = iter->next;
+ free (const_cast <char *> (iter->prefix));
+ XDELETE (iter);
+ iter = next;
+ }
+ prefix->plist = 0;
+ prefix->max_len = 0;
+}
+
+/* The function takes 3 arguments: OPTION name, file name and location
+ where we search for Fortran modules.
+ When the FILE is found by find_file, return OPTION=path_to_file. */
+
+static const char *
+find_fortran_preinclude_file (int argc, const char **argv)
+{
+ char *result = NULL;
+ if (argc != 3)
+ return NULL;
+
+ struct path_prefix prefixes = { 0, 0, "preinclude" };
+
+ /* Search first for 'finclude' folder location for a header file
+ installed by the compiler (similar to omp_lib.h). */
+ add_prefix (&prefixes, argv[2], NULL, 0, 0, 0);
+#ifdef TOOL_INCLUDE_DIR
+ /* Then search: <prefix>/<target>/<include>/finclude */
+ add_prefix (&prefixes, TOOL_INCLUDE_DIR "/finclude/",
+ NULL, 0, 0, 0);
+#endif
+#ifdef NATIVE_SYSTEM_HEADER_DIR
+ /* Then search: <sysroot>/usr/include/finclude/<multilib> */
+ add_sysrooted_hdrs_prefix (&prefixes, NATIVE_SYSTEM_HEADER_DIR "/finclude/",
+ NULL, 0, 0, 0);
+#endif
+
+ const char *path = find_a_file (&include_prefixes, argv[1], R_OK, false);
+ if (path != NULL)
+ result = concat (argv[0], path, NULL);
+ else
+ {
+ path = find_a_file (&prefixes, argv[1], R_OK, false);
+ if (path != NULL)
+ result = concat (argv[0], path, NULL);
+ }
+
+ path_prefix_reset (&prefixes);
+ return result;
+}
+
+/* If any character in ORIG fits QUOTE_P (_, P), reallocate the string
+ so as to precede every one of them with a backslash. Return the
+ original string or the reallocated one. */
+
+static inline char *
+quote_string (char *orig, bool (*quote_p)(char, void *), void *p)
+{
+ int len, number_of_space = 0;
+
+ for (len = 0; orig[len]; len++)
+ if (quote_p (orig[len], p))
+ number_of_space++;
+
+ if (number_of_space)
+ {
+ char *new_spec = (char *) xmalloc (len + number_of_space + 1);
+ int j, k;
+ for (j = 0, k = 0; j <= len; j++, k++)
+ {
+ if (quote_p (orig[j], p))
+ new_spec[k++] = '\\';
+ new_spec[k] = orig[j];
+ }
+ free (orig);
+ return new_spec;
+ }
+ else
+ return orig;
+}
+
+/* Return true iff C is any of the characters convert_white_space
+ should quote. */
+
+static inline bool
+whitespace_to_convert_p (char c, void *)
+{
+ return (c == ' ' || c == '\t');
+}
+
+/* Insert backslash before spaces in ORIG (usually a file path), to
+ avoid being broken by spec parser.
+
+ This function is needed as do_spec_1 treats white space (' ' and '\t')
+ as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
+ the file name should be treated as a single argument rather than being
+ broken into multiple. Solution is to insert '\\' before the space in a
+ file name.
+
+ This function converts and only converts all occurrence of ' '
+ to '\\' + ' ' and '\t' to '\\' + '\t'. For example:
+ "a b" -> "a\\ b"
+ "a b" -> "a\\ \\ b"
+ "a\tb" -> "a\\\tb"
+ "a\\ b" -> "a\\\\ b"
+
+ orig: input null-terminating string that was allocated by xalloc. The
+ memory it points to might be freed in this function. Behavior undefined
+ if ORIG wasn't xalloced or was freed already at entry.
+
+ Return: ORIG if no conversion needed. Otherwise a newly allocated string
+ that was converted from ORIG. */
+
+static char *
+convert_white_space (char *orig)
+{
+ return quote_string (orig, whitespace_to_convert_p, NULL);
+}
+
+/* Return true iff C matches any of the spec active characters. */
+static inline bool
+quote_spec_char_p (char c, void *)
+{
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '|':
+ case '%':
+ case '\\':
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Like convert_white_space, but deactivate all active spec chars by
+ quoting them. */
+
+static inline char *
+quote_spec (char *orig)
+{
+ return quote_string (orig, quote_spec_char_p, NULL);
+}
+
+/* Like quote_spec, but also turn an empty string into the spec for an
+ empty argument. */
+
+static inline char *
+quote_spec_arg (char *orig)
+{
+ if (!*orig)
+ {
+ free (orig);
+ return xstrdup ("%\"");
+ }
+
+ return quote_spec (orig);
+}
+
+/* Restore all state within gcc.cc to the initial state, so that the driver
+ code can be safely re-run in-process.
+
+ Many const char * variables are referenced by static specs (see
+ INIT_STATIC_SPEC above). These variables are restored to their default
+ values by a simple loop over the static specs.
+
+ For other variables, we directly restore them all to their initial
+ values (often implicitly 0).
+
+ Free the various obstacks in this file, along with "opts_obstack"
+ from opts.cc.
+
+ This function also restores any environment variables that were changed. */
+
+void
+driver::finalize ()
+{
+ env.restore ();
+ diagnostic_finish (global_dc);
+
+ is_cpp_driver = 0;
+ at_file_supplied = 0;
+ print_help_list = 0;
+ print_version = 0;
+ verbose_only_flag = 0;
+ print_subprocess_help = 0;
+ use_ld = NULL;
+ report_times_to_file = NULL;
+ target_system_root = DEFAULT_TARGET_SYSTEM_ROOT;
+ target_system_root_changed = 0;
+ target_sysroot_suffix = 0;
+ target_sysroot_hdrs_suffix = 0;
+ save_temps_flag = SAVE_TEMPS_NONE;
+ save_temps_overrides_dumpdir = false;
+ dumpdir_trailing_dash_added = false;
+ free (dumpdir);
+ free (dumpbase);
+ free (dumpbase_ext);
+ free (outbase);
+ dumpdir = dumpbase = dumpbase_ext = outbase = NULL;
+ dumpdir_length = outbase_length = 0;
+ spec_machine = DEFAULT_TARGET_MACHINE;
+ greatest_status = 1;
+
+ obstack_free (&obstack, NULL);
+ obstack_free (&opts_obstack, NULL); /* in opts.cc */
+ obstack_free (&collect_obstack, NULL);
+
+ link_command_spec = LINK_COMMAND_SPEC;
+
+ obstack_free (&multilib_obstack, NULL);
+
+ user_specs_head = NULL;
+ user_specs_tail = NULL;
+
+ /* Within the "compilers" vec, the fields "suffix" and "spec" were
+ statically allocated for the default compilers, but dynamically
+ allocated for additional compilers. Delete them for the latter. */
+ for (int i = n_default_compilers; i < n_compilers; i++)
+ {
+ free (const_cast <char *> (compilers[i].suffix));
+ free (const_cast <char *> (compilers[i].spec));
+ }
+ XDELETEVEC (compilers);
+ compilers = NULL;
+ n_compilers = 0;
+
+ linker_options.truncate (0);
+ assembler_options.truncate (0);
+ preprocessor_options.truncate (0);
+
+ path_prefix_reset (&exec_prefixes);
+ path_prefix_reset (&startfile_prefixes);
+ path_prefix_reset (&include_prefixes);
+
+ machine_suffix = 0;
+ just_machine_suffix = 0;
+ gcc_exec_prefix = 0;
+ gcc_libexec_prefix = 0;
+ set_static_spec_shared (&md_exec_prefix, MD_EXEC_PREFIX);
+ set_static_spec_shared (&md_startfile_prefix, MD_STARTFILE_PREFIX);
+ set_static_spec_shared (&md_startfile_prefix_1, MD_STARTFILE_PREFIX_1);
+ multilib_dir = 0;
+ multilib_os_dir = 0;
+ multiarch_dir = 0;
+
+ /* Free any specs dynamically-allocated by set_spec.
+ These will be at the head of the list, before the
+ statically-allocated ones. */
+ if (specs)
+ {
+ while (specs != static_specs)
+ {
+ spec_list *next = specs->next;
+ free (const_cast <char *> (specs->name));
+ XDELETE (specs);
+ specs = next;
+ }
+ specs = 0;
+ }
+ for (unsigned i = 0; i < ARRAY_SIZE (static_specs); i++)
+ {
+ spec_list *sl = &static_specs[i];
+ if (sl->alloc_p)
+ {
+ free (const_cast <char *> (*(sl->ptr_spec)));
+ sl->alloc_p = false;
+ }
+ *(sl->ptr_spec) = sl->default_ptr;
+ }
+#ifdef EXTRA_SPECS
+ extra_specs = NULL;
+#endif
+
+ processing_spec_function = 0;
+
+ clear_args ();
+
+ have_c = 0;
+ have_o = 0;
+
+ temp_names = NULL;
+ execution_count = 0;
+ signal_count = 0;
+
+ temp_filename = NULL;
+ temp_filename_length = 0;
+ always_delete_queue = NULL;
+ failure_delete_queue = NULL;
+
+ XDELETEVEC (switches);
+ switches = NULL;
+ n_switches = 0;
+ n_switches_alloc = 0;
+
+ compare_debug = 0;
+ compare_debug_second = 0;
+ compare_debug_opt = NULL;
+ for (int i = 0; i < 2; i++)
+ {
+ switches_debug_check[i] = NULL;
+ n_switches_debug_check[i] = 0;
+ n_switches_alloc_debug_check[i] = 0;
+ debug_check_temp_file[i] = NULL;
+ }
+
+ XDELETEVEC (infiles);
+ infiles = NULL;
+ n_infiles = 0;
+ n_infiles_alloc = 0;
+
+ combine_inputs = false;
+ added_libraries = 0;
+ XDELETEVEC (outfiles);
+ outfiles = NULL;
+ spec_lang = 0;
+ last_language_n_infiles = 0;
+ gcc_input_filename = NULL;
+ input_file_number = 0;
+ input_filename_length = 0;
+ basename_length = 0;
+ suffixed_basename_length = 0;
+ input_basename = NULL;
+ input_suffix = NULL;
+ /* We don't need to purge "input_stat", just to unset "input_stat_set". */
+ input_stat_set = 0;
+ input_file_compiler = NULL;
+ arg_going = 0;
+ delete_this_arg = 0;
+ this_is_output_file = 0;
+ this_is_library_file = 0;
+ this_is_linker_script = 0;
+ input_from_pipe = 0;
+ suffix_subst = NULL;
+
+ mdswitches = NULL;
+ n_mdswitches = 0;
+
+ used_arg.finalize ();
+}
+
+/* PR jit/64810.
+ Targets can provide configure-time default options in
+ OPTION_DEFAULT_SPECS. The jit needs to access these, but
+ they are expressed in the spec language.
+
+ Run just enough of the driver to be able to expand these
+ specs, and then call the callback CB on each
+ such option. The options strings are *without* a leading
+ '-' character e.g. ("march=x86-64"). Finally, clean up. */
+
+void
+driver_get_configure_time_options (void (*cb) (const char *option,
+ void *user_data),
+ void *user_data)
+{
+ size_t i;
+
+ obstack_init (&obstack);
+ init_opts_obstack ();
+ n_switches = 0;
+
+ for (i = 0; i < ARRAY_SIZE (option_default_specs); i++)
+ do_option_spec (option_default_specs[i].name,
+ option_default_specs[i].spec);
+
+ for (i = 0; (int) i < n_switches; i++)
+ {
+ gcc_assert (switches[i].part1);
+ (*cb) (switches[i].part1, user_data);
+ }
+
+ obstack_free (&opts_obstack, NULL);
+ obstack_free (&obstack, NULL);
+ n_switches = 0;
+}
diff --git a/support/cpp/gcc/gcc.h b/support/cpp/gcc/gcc.h
new file mode 100644
index 000000000..63231ddb3
--- /dev/null
+++ b/support/cpp/gcc/gcc.h
@@ -0,0 +1,100 @@
+/* Header file for modules that link with gcc.cc
+ 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.
+
+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_GCC_H
+#define GCC_GCC_H
+
+#include "version.h"
+#include "diagnostic-core.h"
+
+/* The top-level "main" within the driver would be ~1000 lines long.
+ This class breaks it up into smaller functions and contains some
+ state shared by them. */
+
+class driver
+{
+ public:
+ driver (bool can_finalize, bool debug);
+ ~driver ();
+ int main (int argc, char **argv);
+ void finalize ();
+
+ private:
+ void set_progname (const char *argv0) const;
+ void expand_at_files (int *argc, char ***argv) const;
+ void decode_argv (int argc, const char **argv);
+ void global_initializations ();
+ void build_multilib_strings () const;
+ void set_up_specs () const;
+ void putenv_COLLECT_GCC (const char *argv0) const;
+ void maybe_putenv_COLLECT_LTO_WRAPPER () const;
+ void maybe_putenv_OFFLOAD_TARGETS () const;
+ void handle_unrecognized_options ();
+ int maybe_print_and_exit () const;
+ bool prepare_infiles ();
+ void do_spec_on_infiles () const;
+ void maybe_run_linker (const char *argv0) const;
+ void final_actions () const;
+ void detect_jobserver () const;
+ int get_exit_code () const;
+
+ private:
+ char *explicit_link_files;
+ struct cl_decoded_option *decoded_options;
+ unsigned int decoded_options_count;
+ option_proposer m_option_proposer;
+};
+
+/* The mapping of a spec function name to the C function that
+ implements it. */
+struct spec_function
+{
+ const char *name;
+ const char *(*func) (int, const char **);
+};
+
+/* These are exported by gcc.cc. */
+extern int do_spec (const char *);
+extern void record_temp_file (const char *, int, int);
+extern void set_input (const char *);
+
+/* Spec files linked with gcc.cc must provide definitions for these. */
+
+/* Called before processing to change/add/remove arguments. */
+extern void lang_specific_driver (struct cl_decoded_option **,
+ unsigned int *, int *);
+
+/* Called before linking. Returns 0 on success and -1 on failure. */
+extern int lang_specific_pre_link (void);
+
+extern int n_infiles;
+
+/* Number of extra output files that lang_specific_pre_link may generate. */
+extern int lang_specific_extra_outfiles;
+
+/* A vector of corresponding output files is made up later. */
+
+extern const char **outfiles;
+
+extern void
+driver_get_configure_time_options (void (*cb)(const char *option,
+ void *user_data),
+ void *user_data);
+
+#endif /* ! GCC_GCC_H */
diff --git a/support/cpp/gcc/gen-pass-instances.awk b/support/cpp/gcc/gen-pass-instances.awk
new file mode 100644
index 000000000..b80fb9866
--- /dev/null
+++ b/support/cpp/gcc/gen-pass-instances.awk
@@ -0,0 +1,234 @@
+# Copyright (C) 2013-2022 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script takes passes.def and writes pass-instances.def,
+# counting the instances of each kind of pass, adding an instance number
+# to everywhere that NEXT_PASS is used.
+# Also handle INSERT_PASS_AFTER, INSERT_PASS_BEFORE and REPLACE_PASS
+# directives.
+#
+# For example, the single-instanced pass:
+# NEXT_PASS (pass_warn_unused_result);
+# becomes this in the output:
+# NEXT_PASS (pass_warn_unused_result, 1);
+#
+# The various instances of
+# NEXT_PASS (pass_copy_prop);
+# become:
+# NEXT_PASS (pass_copy_prop, 1);
+# through:
+# NEXT_PASS (pass_copy_prop, 8);
+# (currently there are 8 instances of that pass)
+#
+# INSERT_PASS_AFTER (pass_copy_prop, 1, pass_stv);
+# will insert
+# NEXT_PASS (pass_stv, 1);
+# immediately after the NEXT_PASS (pass_copy_prop, 1) line,
+# similarly INSERT_PASS_BEFORE inserts immediately before that line.
+# REPLACE_PASS (pass_copy_prop, 1, pass_stv, true);
+# will replace NEXT_PASS (pass_copy_prop, 1) line with
+# NEXT_PASS (pass_stv, 1, true);
+# line and renumber all higher pass_copy_prop instances if any.
+
+# Usage: awk -f gen-pass-instances.awk passes.def
+
+BEGIN {
+ print "/* This file is auto-generated by gen-pass-instances.awk";
+ print " from passes.def. */";
+ lineno = 1;
+}
+
+function parse_line(line, fnname, len_of_call, len_of_start,
+ len_of_open, len_of_close,
+ len_of_args, args_start_at,
+ args_str, len_of_prefix,
+ call_starts_at,
+ postfix_starts_at)
+{
+ # Find call expression.
+ call_starts_at = match(line, fnname " \\(.+\\)");
+ if (call_starts_at == 0)
+ return 0;
+
+ # Length of the call expression.
+ len_of_call = RLENGTH;
+
+ len_of_start = length(fnname " (");
+ len_of_open = length("(");
+ len_of_close = length(")");
+
+ # Find arguments
+ len_of_args = len_of_call - (len_of_start + len_of_close);
+ args_start_at = call_starts_at + len_of_start;
+ args_str = substr(line, args_start_at, len_of_args);
+ split(args_str, args, ",");
+
+ # Find call expression prefix
+ len_of_prefix = call_starts_at - 1;
+ prefix = substr(line, 1, len_of_prefix);
+
+ # Find call expression postfix
+ postfix_starts_at = call_starts_at + len_of_call;
+ postfix = substr(line, postfix_starts_at);
+ return 1;
+}
+
+function adjust_linenos(above, increment, p, i)
+{
+ for (p in pass_lines)
+ if (pass_lines[p] >= above)
+ pass_lines[p] += increment;
+ if (increment > 0)
+ for (i = lineno - 1; i >= above; i--)
+ lines[i + increment] = lines[i];
+ else
+ for (i = above; i < lineno; i++)
+ lines[i + increment] = lines[i];
+ lineno += increment;
+}
+
+function insert_remove_pass(line, fnname, arg3)
+{
+ parse_line($0, fnname);
+ pass_name = args[1];
+ if (pass_name == "PASS")
+ return 1;
+ pass_num = args[2] + 0;
+ arg3 = args[3];
+ sub(/^[ \t]*/, "", arg3);
+ new_line = prefix "NEXT_PASS (" arg3;
+ if (args[4])
+ new_line = new_line "," args[4];
+ new_line = new_line ")" postfix;
+ if (!pass_lines[pass_name, pass_num])
+ {
+ print "ERROR: Can't locate instance of the pass mentioned in " fnname;
+ return 1;
+ }
+ return 0;
+}
+
+function insert_pass(line, fnname, after, num)
+{
+ if (insert_remove_pass(line, fnname))
+ return;
+ num = pass_lines[pass_name, pass_num];
+ adjust_linenos(num + after, 1);
+ pass_name = args[3];
+ # Set pass_counts
+ if (args[3] in pass_counts)
+ pass_counts[pass_name]++;
+ else
+ pass_counts[pass_name] = 1;
+
+ pass_lines[pass_name, pass_counts[pass_name]] = num + after;
+ lines[num + after] = new_line;
+}
+
+function replace_pass(line, fnname, num, i)
+{
+ if (insert_remove_pass(line, "REPLACE_PASS"))
+ return;
+ num = pass_lines[pass_name, pass_num];
+ for (i = pass_counts[pass_name]; i > pass_num; i--)
+ pass_lines[pass_name, i - 1] = pass_lines[pass_name, i];
+ delete pass_lines[pass_name, pass_counts[pass_name]];
+ if (pass_counts[pass_name] == 1)
+ delete pass_counts[pass_name];
+ else
+ pass_counts[pass_name]--;
+
+ pass_name = args[3];
+ # Set pass_counts
+ if (args[3] in pass_counts)
+ pass_counts[pass_name]++;
+ else
+ pass_counts[pass_name] = 1;
+
+ pass_lines[pass_name, pass_counts[pass_name]] = num;
+ lines[num] = new_line;
+}
+
+/INSERT_PASS_AFTER \(.+\)/ {
+ insert_pass($0, "INSERT_PASS_AFTER", 1);
+ next;
+}
+
+/INSERT_PASS_BEFORE \(.+\)/ {
+ insert_pass($0, "INSERT_PASS_BEFORE", 0);
+ next;
+}
+
+/REPLACE_PASS \(.+\)/ {
+ replace_pass($0, "REPLACE_PASS");
+ next;
+}
+
+{
+ ret = parse_line($0, "NEXT_PASS");
+ if (ret)
+ {
+ pass_name = args[1];
+
+ # Set pass_counts
+ if (pass_name in pass_counts)
+ pass_counts[pass_name]++;
+ else
+ pass_counts[pass_name] = 1;
+
+ pass_lines[pass_name, pass_counts[pass_name]] = lineno;
+ }
+ lines[lineno++] = $0;
+}
+
+END {
+ for (i = 1; i < lineno; i++)
+ {
+ ret = parse_line(lines[i], "NEXT_PASS");
+ if (ret)
+ {
+ # Set pass_name argument, an optional with_arg argument
+ pass_name = args[1];
+ with_arg = args[2];
+
+ # Set pass_final_counts
+ if (pass_name in pass_final_counts)
+ pass_final_counts[pass_name]++;
+ else
+ pass_final_counts[pass_name] = 1;
+
+ pass_num = pass_final_counts[pass_name];
+
+ # Print call expression with extra pass_num argument
+ printf "%s", prefix;
+ if (with_arg)
+ printf "NEXT_PASS_WITH_ARG";
+ else
+ printf "NEXT_PASS";
+ printf " (%s, %s", pass_name, pass_num;
+ if (with_arg)
+ printf ",%s", with_arg;
+ printf ")%s\n", postfix;
+ }
+ else
+ print lines[i];
+ }
+}
+
+# Local Variables:
+# mode:awk
+# c-basic-offset:8
+# End:
diff --git a/support/cpp/gcc/genchecksum.cc b/support/cpp/gcc/genchecksum.cc
new file mode 100644
index 000000000..6ad0a12b5
--- /dev/null
+++ b/support/cpp/gcc/genchecksum.cc
@@ -0,0 +1,120 @@
+/* Generate checksums of executables for PCH validation
+ Copyright (C) 2005-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 "bconfig.h"
+#include "system.h"
+#include "md5.h"
+
+static void
+usage (void)
+{
+ fputs ("Usage: genchecksums <filename> ...\n", stderr);
+}
+
+/* Important: BLOCKSIZE must be a multiple of 64. */
+#define BLOCKSIZE 4096
+
+static void
+dosum (struct md5_ctx *ctx, const char *file)
+{
+ FILE *f;
+ char buffer[BLOCKSIZE + 72];
+ size_t sum;
+
+ f = fopen (file, "rb");
+ if (!f)
+ {
+ fprintf (stderr, "opening %s: %s\n", file, xstrerror (errno));
+ exit (1);
+ }
+
+ /* Some executable formats have timestamps in the first 16 bytes, yuck. */
+ if (fseek (f, 16, SEEK_SET) != 0)
+ {
+ fprintf (stderr, "seeking in %s: %s\n", file, xstrerror (errno));
+ exit (1);
+ }
+
+ /* Iterate over full file contents. */
+ while (1)
+ {
+ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
+ computation function processes the whole buffer so that with the
+ next round of the loop another block can be read. */
+ size_t n;
+ sum = 0;
+
+ /* Read block. Take care for partial reads. */
+ do
+ {
+ n = fread (buffer + sum, 1, BLOCKSIZE - sum, f);
+
+ sum += n;
+ }
+ while (sum < BLOCKSIZE && n != 0);
+ if (n == 0 && ferror (f))
+ exit (1);
+
+ /* If end of file is reached, end the loop. */
+ if (n == 0)
+ break;
+
+ /* Process buffer with BLOCKSIZE bytes. Note that
+ BLOCKSIZE % 64 == 0
+ */
+ md5_process_block (buffer, BLOCKSIZE, ctx);
+ }
+
+ /* Add the last bytes if necessary. */
+ if (sum > 0)
+ md5_process_bytes (buffer, sum, ctx);
+
+ if (fclose (f) != 0)
+ {
+ fprintf (stderr, "reading %s: %s\n", file, xstrerror (errno));
+ exit (1);
+ }
+}
+
+int
+main (int argc, char ** argv)
+{
+ struct md5_ctx ctx;
+ unsigned char result[16];
+ int i;
+
+ if (argc < 2)
+ {
+ usage ();
+ return 1;
+ }
+
+ md5_init_ctx (&ctx);
+ for (i = 1; i < argc; i++)
+ dosum (&ctx, argv[i]);
+ md5_finish_ctx (&ctx, result);
+
+ puts ("#include \"config.h\"");
+ puts ("#include \"system.h\"");
+ fputs ("EXPORTED_CONST unsigned char executable_checksum[16] = { ", stdout);
+ for (i = 0; i < 16; i++)
+ printf ("0x%02x%s", result[i], i == 15 ? " };\n" : ", ");
+
+ return 0;
+}
diff --git a/support/cpp/gcc/gengenrtl.cc b/support/cpp/gcc/gengenrtl.cc
new file mode 100644
index 000000000..b2b5c3c94
--- /dev/null
+++ b/support/cpp/gcc/gengenrtl.cc
@@ -0,0 +1,358 @@
+/* Generate code to allocate RTL structures.
+ 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/>. */
+
+
+#include "bconfig.h"
+#include "system.h"
+
+struct rtx_definition
+{
+ const char *const enumname, *const name, *const format;
+};
+
+/* rtl.def needs CONST_DOUBLE_FORMAT, but we don't care what
+ CONST_DOUBLE_FORMAT is because we're not going to be generating
+ anything for CONST_DOUBLE anyway. */
+#define CONST_DOUBLE_FORMAT ""
+
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) { #ENUM, NAME, FORMAT },
+
+static const struct rtx_definition defs[] =
+{
+#include "rtl.def" /* rtl expressions are documented here */
+};
+#define NUM_RTX_CODE ARRAY_SIZE (defs)
+
+static const char *formats[NUM_RTX_CODE];
+
+/* Decode a format letter into a C type string. */
+
+static const char *
+type_from_format (int c)
+{
+ switch (c)
+ {
+ case 'i':
+ return "int ";
+
+ case 'w':
+ return "HOST_WIDE_INT ";
+
+ case 'p':
+ return "poly_uint16 ";
+
+ case 's':
+ return "const char *";
+
+ case 'e': case 'u':
+ return "rtx ";
+
+ case 'E':
+ return "rtvec ";
+ case 't':
+ return "tree ";
+ case 'B':
+ return "basic_block ";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Decode a format letter into the proper accessor function. */
+
+static const char *
+accessor_from_format (int c)
+{
+ switch (c)
+ {
+ case 'i':
+ return "XINT";
+
+ case 'w':
+ return "XWINT";
+
+ case 's':
+ return "XSTR";
+
+ case 'e': case 'u':
+ return "XEXP";
+
+ case 'E':
+ return "XVEC";
+
+ case 't':
+ return "XTREE";
+
+ case 'B':
+ return "XBBDEF";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return nonzero if we should ignore FMT, an RTL format, when making
+ the list of formats we write routines to create. */
+
+static int
+special_format (const char *fmt)
+{
+ return (strchr (fmt, '*') != 0
+ || strchr (fmt, 'V') != 0
+ || strchr (fmt, 'S') != 0
+ || strchr (fmt, 'n') != 0
+ || strchr (fmt, 'r') != 0);
+}
+
+/* Return true if CODE always has VOIDmode. */
+
+static inline bool
+always_void_p (int idx)
+{
+ return strcmp (defs[idx].enumname, "SET") == 0;
+}
+
+/* Return nonzero if the RTL code given by index IDX is one that we should
+ generate a gen_rtx_raw_FOO macro for, not gen_rtx_FOO (because gen_rtx_FOO
+ is a wrapper in emit-rtl.cc). */
+
+static int
+special_rtx (int idx)
+{
+ return (strcmp (defs[idx].enumname, "EXPR_LIST") == 0
+ || strcmp (defs[idx].enumname, "INSN_LIST") == 0
+ || strcmp (defs[idx].enumname, "INSN") == 0
+ || strcmp (defs[idx].enumname, "CONST_INT") == 0
+ || strcmp (defs[idx].enumname, "REG") == 0
+ || strcmp (defs[idx].enumname, "SUBREG") == 0
+ || strcmp (defs[idx].enumname, "MEM") == 0
+ || strcmp (defs[idx].enumname, "PC") == 0
+ || strcmp (defs[idx].enumname, "RETURN") == 0
+ || strcmp (defs[idx].enumname, "SIMPLE_RETURN") == 0
+ || strcmp (defs[idx].enumname, "CONST_VECTOR") == 0);
+}
+
+/* Return nonzero if the RTL code given by index IDX is one that we should
+ generate no macro for at all (because gen_rtx_FOO is never used or
+ cannot have the obvious interface). */
+
+static int
+excluded_rtx (int idx)
+{
+ return (strcmp (defs[idx].enumname, "VAR_LOCATION") == 0
+ || strcmp (defs[idx].enumname, "CONST_DOUBLE") == 0
+ || strcmp (defs[idx].enumname, "CONST_WIDE_INT") == 0
+ || strcmp (defs[idx].enumname, "CONST_POLY_INT") == 0
+ || strcmp (defs[idx].enumname, "CONST_FIXED") == 0);
+}
+
+/* Place a list of all format specifiers we use into the array FORMAT. */
+
+static void
+find_formats (void)
+{
+ unsigned int i;
+
+ for (i = 0; i < NUM_RTX_CODE; i++)
+ {
+ const char **f;
+
+ if (special_format (defs[i].format))
+ continue;
+
+ for (f = formats; *f; f++)
+ if (! strcmp (*f, defs[i].format))
+ break;
+
+ if (*f == 0)
+ *f = defs[i].format;
+ }
+}
+
+
+/* Generate macros to generate RTL of code IDX using the functions we
+ write. */
+
+static void
+genmacro (int idx)
+{
+ const char *p;
+ const char *sep = "";
+ int i;
+
+ /* We write a macro that defines gen_rtx_RTLCODE to be an equivalent to
+ gen_rtx_fmt_FORMAT where FORMAT is the RTX_FORMAT of RTLCODE. */
+
+ if (excluded_rtx (idx))
+ /* Don't define a macro for this code. */
+ return;
+
+ bool has_mode_p = !always_void_p (idx);
+ printf ("#define gen_rtx_%s%s(",
+ special_rtx (idx) ? "raw_" : "", defs[idx].enumname);
+ if (has_mode_p)
+ {
+ printf ("MODE");
+ sep = ", ";
+ }
+
+ for (p = defs[idx].format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ {
+ printf ("%sARG%d", sep, i++);
+ sep = ", ";
+ }
+
+ printf (") \\\n gen_rtx_fmt_%s (%s, %s",
+ defs[idx].format, defs[idx].enumname,
+ has_mode_p ? "(MODE)" : "VOIDmode");
+
+ for (p = defs[idx].format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", (ARG%d)", i++);
+
+ puts (")");
+}
+
+/* Generate the code for functions to generate RTL whose format is FORMAT. */
+
+static void
+gendef (const char *format)
+{
+ const char *p;
+ int i, j;
+
+ /* Write the definition of the init function name and the types
+ of the arguments. */
+
+ puts ("static inline rtx");
+ printf ("init_rtx_fmt_%s (rtx rt, machine_mode mode", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (",\n\t%sarg%d", type_from_format (*p), i++);
+ puts (")");
+
+ /* Now write out the body of the init function itself. */
+ puts ("{");
+ puts (" PUT_MODE_RAW (rt, mode);");
+
+ for (p = format, i = j = 0; *p ; ++p, ++i)
+ if (*p == '0')
+ printf (" X0EXP (rt, %d) = NULL_RTX;\n", i);
+ else if (*p == 'p')
+ printf (" SUBREG_BYTE (rt) = arg%d;\n", j++);
+ else
+ printf (" %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
+
+ puts (" return rt;\n}\n");
+
+ /* Write the definition of the gen function name and the types
+ of the arguments. */
+
+ puts ("static inline rtx");
+ printf ("gen_rtx_fmt_%s_stat (RTX_CODE code, machine_mode mode", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (",\n\t%sarg%d", type_from_format (*p), i++);
+ puts (" MEM_STAT_DECL)");
+
+ /* Now write out the body of the function itself, which allocates
+ the memory and initializes it. */
+ puts ("{");
+ puts (" rtx rt;\n");
+
+ puts (" rt = rtx_alloc (code PASS_MEM_STAT);");
+ printf (" return init_rtx_fmt_%s (rt, mode", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", arg%d", i++);
+ puts (");\n}\n");
+
+ /* Write the definition of gen macro. */
+
+ printf ("#define gen_rtx_fmt_%s(c, m", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", arg%d", i++);
+ printf (") \\\n gen_rtx_fmt_%s_stat ((c), (m)", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", (arg%d)", i++);
+ printf (" MEM_STAT_INFO)\n\n");
+
+ /* Write the definition of alloca macro. */
+
+ printf ("#define alloca_rtx_fmt_%s(c, m", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", arg%d", i++);
+ printf (") \\\n init_rtx_fmt_%s (rtx_alloca ((c)), (m)", format);
+ for (p = format, i = 0; *p != 0; p++)
+ if (*p != '0')
+ printf (", (arg%d)", i++);
+ printf (")\n\n");
+}
+
+/* Generate the documentation header for files we write. */
+
+static void
+genlegend (void)
+{
+ puts ("/* Generated automatically by gengenrtl from rtl.def. */\n");
+}
+
+/* Generate the text of the header file we make, genrtl.h. */
+
+static void
+genheader (void)
+{
+ unsigned int i;
+ const char **fmt;
+
+ puts ("#ifndef GCC_GENRTL_H");
+ puts ("#define GCC_GENRTL_H\n");
+ puts ("#include \"statistics.h\"\n");
+
+ for (fmt = formats; *fmt; ++fmt)
+ gendef (*fmt);
+
+ putchar ('\n');
+
+ for (i = 0; i < NUM_RTX_CODE; i++)
+ if (! special_format (defs[i].format))
+ genmacro (i);
+
+ puts ("\n#endif /* GCC_GENRTL_H */");
+}
+
+/* This is the main program. */
+
+int
+main (void)
+{
+ find_formats ();
+ genlegend ();
+
+ genheader ();
+
+ if (ferror (stdout) || fflush (stdout) || fclose (stdout))
+ return FATAL_EXIT_CODE;
+
+ return SUCCESS_EXIT_CODE;
+}
diff --git a/support/cpp/gcc/gengtype-lex.l b/support/cpp/gcc/gengtype-lex.l
new file mode 100644
index 000000000..86006180b
--- /dev/null
+++ b/support/cpp/gcc/gengtype-lex.l
@@ -0,0 +1,221 @@
+/* -*- indented-text -*- */
+/* Process source files and output type information.
+ Copyright (C) 2002-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/>. */
+
+%option noinput
+
+%{
+#ifdef HOST_GENERATOR_FILE
+#include "config.h"
+#define GENERATOR_FILE 1
+#else
+#include "bconfig.h"
+#endif
+#include "system.h"
+
+#define malloc xmalloc
+#define realloc xrealloc
+
+#include "gengtype.h"
+
+#define YY_DECL int yylex (const char **yylval)
+#define yyterminate() return EOF_TOKEN
+
+struct fileloc lexer_line;
+int lexer_toplevel_done;
+
+static void
+update_lineno (const char *l, size_t len)
+{
+ while (len-- > 0)
+ if (*l++ == '\n')
+ lexer_line.line++;
+}
+
+%}
+
+CID [[:alpha:]_][[:alnum:]_]*
+WS [[:space:]]+
+HWS [ \t\r\v\f]*
+IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|uint64_t|int64_t|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET
+ITYPE {IWORD}({WS}{IWORD})*
+ /* Include '::' in identifiers to capture C++ scope qualifiers. */
+ID {CID}({HWS}::{HWS}{CID})*
+EOID [^[:alnum:]_]
+CXX_KEYWORD inline|public:|private:|protected:|template|operator|friend|static|mutable
+
+%x in_struct in_struct_comment in_comment
+%option warn noyywrap nounput nodefault perf-report
+%option 8bit never-interactive
+%%
+ /* Do this on entry to yylex(): */
+ *yylval = 0;
+ if (lexer_toplevel_done)
+ {
+ BEGIN(INITIAL);
+ lexer_toplevel_done = 0;
+ }
+
+ /* Things we look for in skipping mode: */
+<INITIAL>{
+^{HWS}typedef/{EOID} {
+ BEGIN(in_struct);
+ return TYPEDEF;
+}
+^{HWS}struct/{EOID} {
+ BEGIN(in_struct);
+ return STRUCT;
+}
+^{HWS}union/{EOID} {
+ BEGIN(in_struct);
+ return UNION;
+}
+^{HWS}class/{EOID} {
+ BEGIN(in_struct);
+ return STRUCT;
+}
+^{HWS}extern/{EOID} {
+ BEGIN(in_struct);
+ return EXTERN;
+}
+^{HWS}static/{EOID} {
+ BEGIN(in_struct);
+ return STATIC;
+}
+}
+
+ /* Parsing inside a struct, union or class declaration. */
+<in_struct>{
+"/*" { BEGIN(in_struct_comment); }
+"//".*\n { lexer_line.line++; }
+
+{WS} { update_lineno (yytext, yyleng); }
+\\\n { lexer_line.line++; }
+
+"const"/{EOID} /* don't care */
+{CXX_KEYWORD}/{EOID} |
+"~" |
+"^" |
+"&" {
+ *yylval = XDUPVAR (const char, yytext, yyleng, yyleng + 1);
+ return IGNORABLE_CXX_KEYWORD;
+}
+"GTY"/{EOID} { return GTY_TOKEN; }
+"union"/{EOID} { return UNION; }
+"struct"/{EOID} { return STRUCT; }
+"class"/{EOID} { return STRUCT; }
+"typedef"/{EOID} { return TYPEDEF; }
+"enum"/{EOID} { return ENUM; }
+"ptr_alias"/{EOID} { return PTR_ALIAS; }
+"nested_ptr"/{EOID} { return NESTED_PTR; }
+"user"/{EOID} { return USER_GTY; }
+[0-9]+ {
+ *yylval = XDUPVAR (const char, yytext, yyleng, yyleng+1);
+ return NUM;
+}
+
+{IWORD}({WS}{IWORD})*/{EOID} |
+"ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" {
+ size_t len;
+
+ for (len = yyleng; ISSPACE (yytext[len-1]); len--)
+ ;
+
+ *yylval = XDUPVAR (const char, yytext, len, len+1);
+ update_lineno (yytext, yyleng);
+ return SCALAR;
+}
+
+{ID}/{EOID} {
+ *yylval = XDUPVAR (const char, yytext, yyleng, yyleng+1);
+ return ID;
+}
+
+\"([^"\\]|\\.)*\" {
+ *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng-1);
+ return STRING;
+}
+ /* This "terminal" avoids having to parse integer constant expressions. */
+"["[^\[\]]*"]" {
+ *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng-1);
+ return ARRAY;
+}
+"'"("\\".|[^\\])"'" {
+ *yylval = XDUPVAR (const char, yytext+1, yyleng-2, yyleng);
+ return CHAR;
+}
+
+"..." { return ELLIPSIS; }
+[(){},*:<>;=%/|+\!\?\.-] { return yytext[0]; }
+
+ /* ignore pp-directives */
+^{HWS}"#"{HWS}[a-z_]+[^\n]*\n {lexer_line.line++;}
+
+. {
+ error_at_line (&lexer_line, "unexpected character `%s'", yytext);
+}
+}
+
+"/*" { BEGIN(in_comment); }
+"//".*\n { lexer_line.line++; }
+\n { lexer_line.line++; }
+{ID} |
+"'"("\\".|[^\\])"'" |
+[^"/\n] /* do nothing */
+\"([^"\\]|\\.|\\\n)*\" { update_lineno (yytext, yyleng); }
+"/"/[^*] /* do nothing */
+
+<in_comment,in_struct_comment>{
+\n { lexer_line.line++; }
+[^*\n]{16} |
+[^*\n] /* do nothing */
+"*"/[^/] /* do nothing */
+}
+
+<in_comment>"*/" { BEGIN(INITIAL); }
+<in_struct_comment>"*/" { BEGIN(in_struct); }
+
+["/] |
+<in_struct_comment,in_comment>"*" {
+ error_at_line (&lexer_line,
+ "unterminated comment or string; unexpected EOF");
+}
+
+^{HWS}"#"{HWS}"define"{WS}"GTY(" /* do nothing */
+
+%%
+
+void
+yybegin (const char *fname)
+{
+ yyin = fopen (fname, "r");
+ if (yyin == NULL)
+ {
+ perror (fname);
+ exit (1);
+ }
+ lexer_line.file = input_file_by_name (fname);
+ lexer_line.line = 1;
+}
+
+void
+yyend (void)
+{
+ fclose (yyin);
+}
diff --git a/support/cpp/gcc/gengtype.h b/support/cpp/gcc/gengtype.h
new file mode 100644
index 000000000..76c1fe663
--- /dev/null
+++ b/support/cpp/gcc/gengtype.h
@@ -0,0 +1,521 @@
+/* Process source files and output type information.
+ Copyright (C) 2002-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_GENGTYPE_H
+#define GCC_GENGTYPE_H
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+#define OBSTACK_CHUNK_SIZE 0
+
+/* Sets of accepted source languages like C, C++, Ada... are
+ represented by a bitmap. */
+typedef unsigned lang_bitmap;
+
+/* Variable length structure representing an input file. A hash table
+ ensure uniqueness for a given input file name. The only function
+ allocating input_file-s is input_file_by_name. */
+struct input_file_st
+{
+ struct outf* inpoutf; /* Cached corresponding output file, computed
+ in get_output_file_with_visibility. */
+ lang_bitmap inpbitmap; /* The set of languages using this file. */
+ bool inpisplugin; /* Flag set for plugin input files. */
+ char inpname[1]; /* A variable-length array, ended by a null
+ char. */
+};
+typedef struct input_file_st input_file;
+
+/* A file position, mostly for error messages.
+ The FILE element may be compared using pointer equality. */
+struct fileloc
+{
+ const input_file *file;
+ int line;
+};
+
+
+/* Table of all input files and its size. */
+extern const input_file** gt_files;
+extern size_t num_gt_files;
+
+/* Table of headers to be included in gtype-desc.cc that are generated
+ during the build. These are identified as "./<filename>.h". */
+extern const char **build_headers;
+extern size_t num_build_headers;
+
+/* A number of places use the name of this "gengtype.cc" file for a
+ location for things that we can't rely on the source to define. We
+ also need to refer to the "system.h" file specifically. These two
+ pointers are initialized early in main. */
+extern input_file* this_file;
+extern input_file* system_h_file;
+
+/* Retrieve or create the input_file for a given name, which is a file
+ path. This is the only function allocating input_file-s and it is
+ hash-consing them. */
+input_file* input_file_by_name (const char* name);
+
+/* For F an input_file, return the relative path to F from $(srcdir)
+ if the latter is a prefix in F, NULL otherwise. */
+const char *get_file_srcdir_relative_path (const input_file *inpf);
+
+/* Get the name of an input file. */
+static inline const char*
+get_input_file_name (const input_file *inpf)
+{
+ if (inpf)
+ return inpf->inpname;
+ return NULL;
+}
+
+/* Return a bitmap which has bit `1 << BASE_FILE_<lang>' set iff
+ INPUT_FILE is used by <lang>.
+
+ This function should be written to assume that a file _is_ used
+ if the situation is unclear. If it wrongly assumes a file _is_ used,
+ a linker error will result. If it wrongly assumes a file _is not_ used,
+ some GC roots may be missed, which is a much harder-to-debug problem.
+ */
+
+static inline lang_bitmap
+get_lang_bitmap (const input_file* inpf)
+{
+ if (inpf == NULL)
+ return 0;
+ return inpf->inpbitmap;
+}
+
+/* Set the bitmap returned by get_lang_bitmap. The only legitimate
+ callers of this function are read_input_list & read_state_*. */
+static inline void
+set_lang_bitmap (input_file* inpf, lang_bitmap n)
+{
+ gcc_assert (inpf);
+ inpf->inpbitmap = n;
+}
+
+/* Vector of per-language directories. */
+extern const char **lang_dir_names;
+extern size_t num_lang_dirs;
+
+/* Data types handed around within, but opaque to, the lexer and parser. */
+typedef struct pair *pair_p;
+typedef struct type *type_p;
+typedef const struct type *const_type_p;
+typedef struct options *options_p;
+
+/* Variables used to communicate between the lexer and the parser. */
+extern int lexer_toplevel_done;
+extern struct fileloc lexer_line;
+
+/* Various things, organized as linked lists, needed both in
+ gengtype.cc & in gengtype-state.cc files. */
+extern pair_p typedefs;
+extern type_p structures;
+extern pair_p variables;
+
+/* An enum for distinguishing GGC vs PCH. */
+
+enum write_types_kinds
+{
+ WTK_GGC,
+ WTK_PCH,
+
+ NUM_WTK
+};
+
+/* Discrimating kind of types we can understand. */
+
+enum typekind {
+ TYPE_NONE=0, /* Never used, so zeroed memory is invalid. */
+ TYPE_UNDEFINED, /* We have not yet seen a definition for this type.
+ If a type is still undefined when generating code,
+ an error will be generated. */
+ TYPE_SCALAR, /* Scalar types like char. */
+ TYPE_STRING, /* The string type. */
+ TYPE_STRUCT, /* Type for GTY-ed structs. */
+ TYPE_UNION, /* Type for GTY-ed discriminated unions. */
+ TYPE_POINTER, /* Pointer type to GTY-ed type. */
+ TYPE_ARRAY, /* Array of GTY-ed types. */
+ TYPE_CALLBACK, /* A function pointer that needs relocation if
+ the executable has been loaded at a different
+ address. */
+ TYPE_LANG_STRUCT, /* GCC front-end language specific structs.
+ Various languages may have homonymous but
+ different structs. */
+ TYPE_USER_STRUCT /* User defined type. Walkers and markers for
+ this type are assumed to be provided by the
+ user. */
+};
+
+/* Discriminating kind for options. */
+enum option_kind {
+ OPTION_NONE=0, /* Never used, so zeroed memory is invalid. */
+ OPTION_STRING, /* A string-valued option. Most options are
+ strings. */
+ OPTION_TYPE, /* A type-valued option. */
+ OPTION_NESTED /* Option data for 'nested_ptr'. */
+};
+
+
+/* A way to pass data through to the output end. */
+struct options {
+ struct options *next; /* next option of the same pair. */
+ const char *name; /* GTY option name. */
+ enum option_kind kind; /* discriminating option kind. */
+ union {
+ const char* string; /* When OPTION_STRING. */
+ type_p type; /* When OPTION_TYPE. */
+ struct nested_ptr_data* nested; /* when OPTION_NESTED. */
+ } info;
+};
+
+
+/* Option data for the 'nested_ptr' option. */
+struct nested_ptr_data {
+ type_p type;
+ const char *convert_to;
+ const char *convert_from;
+};
+
+/* Some functions to create various options structures with name NAME
+ and info INFO. NEXT is the next option in the chain. */
+
+/* Create a string option. */
+options_p create_string_option (options_p next, const char* name,
+ const char* info);
+
+/* Create a type option. */
+options_p create_type_option (options_p next, const char* name,
+ type_p info);
+
+/* Create a nested option. */
+options_p create_nested_option (options_p next, const char* name,
+ struct nested_ptr_data* info);
+
+/* Create a nested pointer option. */
+options_p create_nested_ptr_option (options_p next, type_p t,
+ const char *to, const char *from);
+
+/* A name and a type. */
+struct pair {
+ pair_p next; /* The next pair in the linked list. */
+ const char *name; /* The defined name. */
+ type_p type; /* Its GTY-ed type. */
+ struct fileloc line; /* The file location. */
+ options_p opt; /* GTY options, as a linked list. */
+};
+
+/* Usage information for GTY-ed types. Gengtype has to care only of
+ used GTY-ed types. Types are initially unused, and their usage is
+ computed by set_gc_used_type and set_gc_used functions. */
+
+enum gc_used_enum {
+
+ /* We need that zeroed types are initially unused. */
+ GC_UNUSED=0,
+
+ /* The GTY-ed type is used, e.g by a GTY-ed variable or a field
+ inside a GTY-ed used type. */
+ GC_USED,
+
+ /* For GTY-ed structures whose definitions we haven't seen so far
+ when we encounter a pointer to it that is annotated with
+ ``maybe_undef''. If after reading in everything we don't have
+ source file information for it, we assume that it never has been
+ defined. */
+ GC_MAYBE_POINTED_TO,
+
+ /* For known GTY-ed structures which are pointed to by GTY-ed
+ variables or fields. */
+ GC_POINTED_TO
+};
+
+/* Our type structure describes all types handled by gengtype. */
+struct type {
+ /* Discriminating kind, cannot be TYPE_NONE. */
+ enum typekind kind;
+
+ /* For top-level structs or unions, the 'next' field links the
+ global list 'structures'; for lang_structs, their homonymous structs are
+ linked using this 'next' field. The homonymous list starts at the
+ s.lang_struct field of the lang_struct. See the new_structure function
+ for details. This is tricky! */
+ type_p next;
+
+ /* State number used when writing & reading the persistent state. A
+ type with a positive number has already been written. For ease
+ of debugging, newly allocated types have a unique negative
+ number. */
+ int state_number;
+
+ /* Each GTY-ed type which is pointed to by some GTY-ed type knows
+ the GTY pointer type pointing to it. See create_pointer
+ function. */
+ type_p pointer_to;
+
+ /* Type usage information, computed by set_gc_used_type and
+ set_gc_used functions. */
+ enum gc_used_enum gc_used;
+
+ /* The following union is discriminated by the 'kind' field above. */
+ union {
+ /* TYPE__NONE is impossible. */
+
+ /* when TYPE_POINTER: */
+ type_p p;
+
+ /* when TYPE_STRUCT or TYPE_UNION or TYPE_LANG_STRUCT, we have an
+ aggregate type containing fields: */
+ struct {
+ const char *tag; /* the aggregate tag, if any. */
+ struct fileloc line; /* the source location. */
+ pair_p fields; /* the linked list of fields. */
+ options_p opt; /* the GTY options if any. */
+ lang_bitmap bitmap; /* the set of front-end languages
+ using that GTY-ed aggregate. */
+ /* For TYPE_LANG_STRUCT, the lang_struct field gives the first
+ element of a linked list of homonymous struct or union types.
+ Within this list, each homonymous type has as its lang_struct
+ field the original TYPE_LANG_STRUCT type. This is a dirty
+ trick, see the new_structure function for details. */
+ type_p lang_struct;
+
+ type_p base_class; /* the parent class, if any. */
+
+ /* The following two fields are not serialized in state files, and
+ are instead reconstructed on load. */
+
+ /* The head of a singly-linked list of immediate descendents in
+ the inheritance hierarchy. */
+ type_p first_subclass;
+ /* The next in that list. */
+ type_p next_sibling_class;
+
+ /* Have we already written ggc/pch user func for ptr to this?
+ (in write_user_func_for_structure_ptr). */
+ bool wrote_user_func_for_ptr[NUM_WTK];
+ } s;
+
+ /* when TYPE_SCALAR: */
+ bool scalar_is_char;
+
+ /* when TYPE_ARRAY: */
+ struct {
+ type_p p; /* The array component type. */
+ const char *len; /* The string if any giving its length. */
+ } a;
+
+ } u;
+};
+
+/* The one and only TYPE_STRING. */
+extern struct type string_type;
+
+/* The two and only TYPE_SCALARs. Their u.scalar_is_char flags are
+ set early in main. */
+extern struct type scalar_nonchar;
+extern struct type scalar_char;
+
+/* The one and only TYPE_CALLBACK. */
+extern struct type callback_type;
+
+/* Test if a type is a union, either a plain one or a language
+ specific one. */
+#define UNION_P(x) \
+ ((x)->kind == TYPE_UNION \
+ || ((x)->kind == TYPE_LANG_STRUCT \
+ && (x)->u.s.lang_struct->kind == TYPE_UNION))
+
+/* Test if a type is a union or a structure, perhaps a language
+ specific one. */
+static inline bool
+union_or_struct_p (enum typekind kind)
+{
+ return (kind == TYPE_UNION
+ || kind == TYPE_STRUCT
+ || kind == TYPE_LANG_STRUCT
+ || kind == TYPE_USER_STRUCT);
+}
+
+static inline bool
+union_or_struct_p (const_type_p x)
+{
+ return union_or_struct_p (x->kind);
+}
+
+/* Give the file location of a type, if any. */
+static inline struct fileloc*
+type_fileloc (type_p t)
+{
+ if (!t)
+ return NULL;
+ if (union_or_struct_p (t))
+ return &t->u.s.line;
+ return NULL;
+}
+
+/* Structure representing an output file. */
+struct outf
+{
+ struct outf *next;
+ const char *name;
+ size_t buflength;
+ size_t bufused;
+ char *buf;
+};
+typedef struct outf *outf_p;
+
+/* The list of output files. */
+extern outf_p output_files;
+
+/* The output header file that is included into pretty much every
+ source file. */
+extern outf_p header_file;
+
+/* Print, like fprintf, to O. No-op if O is NULL. */
+void
+oprintf (outf_p o, const char *S, ...)
+ ATTRIBUTE_PRINTF_2;
+
+/* An output file, suitable for definitions, that can see declarations
+ made in INPF and is linked into every language that uses INPF. May
+ return NULL in plugin mode. The INPF argument is almost const, but
+ since the result is cached in its inpoutf field it cannot be
+ declared const. */
+outf_p get_output_file_with_visibility (input_file* inpf);
+
+/* The name of an output file, suitable for definitions, that can see
+ declarations made in INPF and is linked into every language that
+ uses INPF. May return NULL. */
+const char *get_output_file_name (input_file *inpf);
+
+
+/* Source directory. */
+extern const char *srcdir; /* (-S) program argument. */
+
+/* Length of srcdir name. */
+extern size_t srcdir_len;
+
+/* Variable used for reading and writing the state. */
+extern const char *read_state_filename; /* (-r) program argument. */
+extern const char *write_state_filename; /* (-w) program argument. */
+
+/* Functions reading and writing the entire gengtype state, called from
+ main, and implemented in file gengtype-state.cc. */
+void read_state (const char* path);
+/* Write the state, and update the state_number field in types. */
+void write_state (const char* path);
+
+
+/* Print an error message. */
+extern void error_at_line
+(const struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2;
+
+/* Constructor routines for types. */
+extern void do_typedef (const char *s, type_p t, struct fileloc *pos);
+extern void do_scalar_typedef (const char *s, struct fileloc *pos);
+extern type_p resolve_typedef (const char *s, struct fileloc *pos);
+extern void add_subclass (type_p base, type_p subclass);
+extern type_p new_structure (const char *name, enum typekind kind,
+ struct fileloc *pos, pair_p fields,
+ options_p o, type_p base);
+type_p create_user_defined_type (const char *, struct fileloc *);
+extern type_p find_structure (const char *s, enum typekind kind);
+extern type_p create_scalar_type (const char *name);
+extern type_p create_pointer (type_p t);
+extern type_p create_array (type_p t, const char *len);
+extern pair_p create_field_at (pair_p next, type_p type,
+ const char *name, options_p opt,
+ struct fileloc *pos);
+extern pair_p nreverse_pairs (pair_p list);
+extern type_p adjust_field_type (type_p, options_p);
+extern void note_variable (const char *s, type_p t, options_p o,
+ struct fileloc *pos);
+
+/* Lexer and parser routines. */
+extern int yylex (const char **yylval);
+extern void yybegin (const char *fname);
+extern void yyend (void);
+extern void parse_file (const char *name);
+extern bool hit_error;
+
+/* Token codes. */
+enum gty_token
+{
+ EOF_TOKEN = 0,
+
+ /* Per standard convention, codes in the range (0, UCHAR_MAX]
+ represent single characters with those character codes. */
+ CHAR_TOKEN_OFFSET = UCHAR_MAX + 1,
+ GTY_TOKEN = CHAR_TOKEN_OFFSET,
+ TYPEDEF,
+ EXTERN,
+ STATIC,
+ UNION,
+ STRUCT,
+ ENUM,
+ ELLIPSIS,
+ PTR_ALIAS,
+ NESTED_PTR,
+ USER_GTY,
+ NUM,
+ SCALAR,
+ ID,
+ STRING,
+ CHAR,
+ ARRAY,
+ IGNORABLE_CXX_KEYWORD,
+
+ /* print_token assumes that any token >= FIRST_TOKEN_WITH_VALUE may have
+ a meaningful value to be printed. */
+ FIRST_TOKEN_WITH_VALUE = USER_GTY
+};
+
+
+/* Level for verbose messages, e.g. output file generation... */
+extern int verbosity_level; /* (-v) program argument. */
+
+/* For debugging purposes we provide two flags. */
+
+/* Dump everything to understand gengtype's state. Might be useful to
+ gengtype users. */
+extern int do_dump; /* (-d) program argument. */
+
+/* Trace the execution by many DBGPRINTF (with the position inside
+ gengtype source code). Only useful to debug gengtype itself. */
+extern int do_debug; /* (-D) program argument. */
+
+#define DBGPRINTF(Fmt,...) do {if (do_debug) \
+ fprintf (stderr, "%s:%d: " Fmt "\n", \
+ lbasename (__FILE__),__LINE__, ##__VA_ARGS__);} while (0)
+void dbgprint_count_type_at (const char *, int, const char *, type_p);
+#define DBGPRINT_COUNT_TYPE(Msg,Ty) do {if (do_debug) \
+ dbgprint_count_type_at (__FILE__, __LINE__, Msg, Ty);}while (0)
+
+#define FOR_ALL_INHERITED_FIELDS(TYPE, FIELD_VAR) \
+ for (type_p sub = (TYPE); sub; sub = sub->u.s.base_class) \
+ for (FIELD_VAR = sub->u.s.fields; FIELD_VAR; FIELD_VAR = FIELD_VAR->next)
+
+extern bool
+opts_have (options_p opts, const char *str);
+
+
+#endif
diff --git a/support/cpp/gcc/genmultilib b/support/cpp/gcc/genmultilib
new file mode 100644
index 000000000..1e387fb15
--- /dev/null
+++ b/support/cpp/gcc/genmultilib
@@ -0,0 +1,552 @@
+#!/bin/sh
+# Generates multilib.h.
+# Copyright (C) 1994-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 shell script produces a header file which the gcc driver
+# program uses to pick which library to use based on the machine
+# specific options that it is given.
+
+# The first argument is a list of sets of options. The elements in
+# the list are separated by spaces. Within an element, the options
+# are separated by slashes or pipes. No leading dash is used on the
+# options.
+# Each option in a set separated by slashes is mutually incompatible
+# with all other options
+# in the set.
+# Each option in a set separated by pipes will be used for the library
+# compilation and any of the options in the set will be sufficient
+# for it to be triggered.
+
+# The optional second argument is a list of subdirectory names. If
+# the second argument is non-empty, there must be as many elements in
+# the second argument as there are options in the first argument. The
+# elements in the second list are separated by spaces. If the second
+# argument is empty, the option names will be used as the directory
+# names.
+
+# The optional third argument is a list of options which are
+# identical. The elements in the list are separated by spaces. Each
+# element must be of the form OPTION=OPTION. The first OPTION should
+# appear in the first argument, and the second should be a synonym for
+# it. Question marks are replaced with equal signs in both options.
+
+# The optional fourth argument is a list of multilib directory
+# combinations that should not be built.
+
+# The optional fifth argument is a list of options that should be
+# used whenever building multilib libraries.
+
+# The optional sixth argument is a list of exclusions used internally by
+# the compiler similar to exceptions. The difference being that exclusions
+# allow matching default options that genmultilib does not know about and
+# is done at runtime as opposed to being sorted out at compile time.
+# Each element in the list is a separate exclusion rule. Each rule is
+# a list of options (sans preceding '-') separated by a '/'. The options
+# on the rule are grouped as an AND operation, and all options much match
+# for the rule to exclude a set. Options can be preceded with a '!' to
+# match a logical NOT.
+
+# The optional seventh argument is a list of OS subdirectory names.
+# The format is either the same as of the second argument, or a set of
+# mappings. When it is the same as the second argument, it describes
+# the multilib directories using OS conventions, rather than GCC
+# conventions. When it is a set of mappings of the form gccdir=osdir,
+# the left side gives the GCC convention and the right gives the
+# equivalent OS defined location. If the osdir part begins with a !,
+# the os directory names are used exclusively. Use the mapping when
+# there is no one-to-one equivalence between GCC levels and the OS.
+
+# The optional eighth argument which intends to reduce the effort to write
+# so many MULTILIB_EXCEPTIONS rules. This option defines a series of option
+# combinations that we actually required.
+# For some cases, the generated option combinations are far more than what
+# we need, we have to write a lot of rules to screen out combinations we
+# don't need. If we missed some rules, the unexpected libraries will be built.
+# Now with this argument, one can simply give what combinations are needed.
+# It is pretty straigtforward.
+# This argument can be used together with MULTILIB_EXCEPTIONS and will take
+# effect after the MULTILIB_EXCEPTIONS.
+
+# The optional ninth argument is the multiarch name.
+
+# The optional tenth argument specifies how to reuse multilib for different
+# option sets.
+
+# The last option should be "yes" if multilibs are enabled. If it is not
+# "yes", all GCC multilib dir names will be ".".
+
+# The output looks like
+# #define MULTILIB_MATCHES "\
+# SUBDIRECTORY OPTIONS;\
+# ...
+# "
+# The SUBDIRECTORY is the subdirectory to use. The OPTIONS are
+# multiple options separated by spaces. Each option may start with an
+# exclamation point. gcc will consider each line in turn. If none of
+# the options beginning with an exclamation point are present, and all
+# of the other options are present, that subdirectory will be used.
+# The order of the subdirectories is such that they can be created in
+# order; that is, a subdirectory is preceded by all its parents.
+
+# Here is an example (this is from the actual sparc64 case):
+# genmultilib 'm64/m32 mno-app-regs|mcmodel=medany' '64 32 alt'
+# 'mcmodel?medany=mcmodel?medmid' 'm32/mno-app-regs* m32/mcmodel=*'
+# '' 'm32/!m64/mno-app-regs m32/!m64/mcmodel=medany'
+# '../lib64 ../lib32 alt' '' '' '' yes
+# This produces:
+# ". !m64 !m32 !mno-app-regs !mcmodel=medany;",
+# "64:../lib64 m64 !m32 !mno-app-regs !mcmodel=medany;",
+# "32:../lib32 !m64 m32 !mno-app-regs !mcmodel=medany;",
+# "alt !m64 !m32 mno-app-regs mcmodel=medany;",
+# "alt !m64 !m32 mno-app-regs !mcmodel=medany;",
+# "alt !m64 !m32 !mno-app-regs mcmodel=medany;",
+# "64/alt:../lib64/alt m64 !m32 mno-app-regs mcmodel=medany;",
+# "64/alt:../lib64/alt m64 !m32 mno-app-regs !mcmodel=medany;",
+# "64/alt:../lib64/alt m64 !m32 !mno-app-regs mcmodel=medany;",
+#
+# The effect is that `gcc -mno-app-regs' (for example) will append "alt"
+# to the directory name when searching for libraries or startup files and
+# `gcc -m32 -mcmodel=medany' (for example) will append "32/alt". Also note
+# that exclusion above is moot, unless the compiler had a default of -m32,
+# which would mean that all of the "alt" directories (not the 64/alt ones)
+# would be ignored (not generated, nor used) since the exclusion also
+# matches the multilib_default args.
+
+# Copy the positional parameters into variables.
+options=$1
+dirnames=$2
+matches=$3
+exceptions=$4
+extra=$5
+exclusions=$6
+osdirnames=$7
+multilib_required=$8
+multiarch=$9
+multilib_reuse=${10}
+enable_multilib=${11}
+
+echo "static const char *const multilib_raw[] = {"
+
+mkdir tmpmultilib.$$ || exit 1
+# Use cd ./foo to avoid CDPATH output.
+cd ./tmpmultilib.$$ || exit 1
+
+# What we want to do is select all combinations of the sets in
+# options. Each combination which includes a set of mutually
+# exclusive options must then be output multiple times, once for each
+# item in the set. Selecting combinations is a recursive process.
+# Since not all versions of sh support functions, we achieve recursion
+# by creating a temporary shell script which invokes itself.
+rm -f tmpmultilib
+cat >tmpmultilib <<\EOF
+#!/bin/sh
+# This recursive script basically outputs all combinations of its
+# input arguments, handling mutually exclusive sets of options by
+# repetition. When the script is called, ${initial} is the list of
+# options which should appear before all combinations this will
+# output. The output looks like a list of subdirectory names with
+# leading and trailing slashes.
+if [ "$#" != "0" ]; then
+ first=$1
+ shift
+ case "$first" in
+ *\|*)
+ all=${initial}`echo $first | sed -e 's_|_/_'g`
+ first=`echo $first | sed -e 's_|_ _'g`
+ echo ${all}/
+ initial="${initial}${all}/" ./tmpmultilib $@
+ ./tmpmultilib $first $@ | grep -v "^${all}"
+ ;;
+ *)
+ for opt in `echo $first | sed -e 's|/| |'g`; do
+ echo ${initial}${opt}/
+ done
+ ./tmpmultilib $@
+ for opt in `echo $first | sed -e 's|/| |'g`; do
+ initial="${initial}${opt}/" ./tmpmultilib $@
+ done
+ esac
+fi
+EOF
+chmod +x tmpmultilib
+
+combinations=`initial=/ ./tmpmultilib ${options}`
+
+# If there exceptions, weed them out now
+if [ -n "${exceptions}" ]; then
+ cat >tmpmultilib2 <<\EOF
+#!/bin/sh
+# This recursive script weeds out any combination of multilib
+# switches that should not be generated. The output looks like
+# a list of subdirectory names with leading and trailing slashes.
+
+ for opt in $@; do
+ case "$opt" in
+EOF
+
+ for except in ${exceptions}; do
+ echo " /${except}/) : ;;" >> tmpmultilib2
+ done
+
+cat >>tmpmultilib2 <<\EOF
+ *) echo ${opt};;
+ esac
+ done
+EOF
+ chmod +x tmpmultilib2
+ combinations=`./tmpmultilib2 ${combinations}`
+fi
+
+# If the MULTILIB_REQUIRED list are provided,
+# filter out combinations not in this list.
+if [ -n "${multilib_required}" ]; then
+ cat >tmpmultilib2 <<\EOF
+#!/bin/sh
+# This recursive script weeds out any combination of multilib
+# switches that not in the expected list.
+
+ for opt in $@; do
+ case "$opt" in
+EOF
+
+ for expect in ${multilib_required}; do
+ echo " /${expect}/) echo \${opt};;" >> tmpmultilib2
+ done
+
+cat >>tmpmultilib2 <<\EOF
+ *) ;;
+ esac
+ done
+EOF
+
+ chmod +x tmpmultilib2
+ combinations=`./tmpmultilib2 ${combinations}`
+
+fi
+
+# Construct a sed pattern which will convert option names to directory
+# names.
+todirnames=
+if [ -n "${dirnames}" ]; then
+ set x ${dirnames}
+ shift
+ for set in ${options}; do
+ for opts in `echo ${set} | sed -e 's|/| |'g`; do
+ patt="/"
+ for opt in `echo ${opts} | sed -e 's_|_ _'g`; do
+ if [ "$1" != "${opt}" ]; then
+ todirnames="${todirnames} -e s|/${opt}/|/${1}/|g"
+ patt="${patt}${1}/"
+ if [ "${patt}" != "/${1}/" ]; then
+ todirnames="${todirnames} -e s|${patt}|/${1}/|g"
+ fi
+ fi
+ done
+ shift
+ done
+ done
+fi
+
+# Construct a sed pattern which will convert option names to OS directory
+# names.
+toosdirnames=
+defaultosdirname=
+defaultosdirname2=
+if [ -n "${multiarch}" ]; then
+ defaultosdirname=::${multiarch}
+fi
+if [ -n "${osdirnames}" ]; then
+ set x ${osdirnames}
+ shift
+ while [ $# != 0 ] ; do
+ case "$1" in
+ .=*)
+ defaultosdirname=`echo $1 | sed 's|^.=|:|'`
+ if [ -n "${multiarch}" ]; then
+ defaultosdirname=${defaultosdirname}:${multiarch}
+ fi
+ case "$defaultosdirname" in
+ ::*) ;;
+ *)
+ defaultosdirname2=${defaultosdirname}
+ defaultosdirname=
+ ;;
+ esac
+ shift
+ ;;
+ *=*)
+ patt=`echo $1 | sed -e 's|=|/$=/|'`
+ toosdirnames="${toosdirnames} -e s=^/${patt}/="
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+ done
+
+ if [ $# != 0 ]; then
+ for set in ${options}; do
+ for opts in `echo ${set} | sed -e 's|/| |'g`; do
+ patt="/"
+ for opt in `echo ${opts} | sed -e 's_|_ _'g`; do
+ if [ "$1" != "${opt}" ]; then
+ toosdirnames="${toosdirnames} -e s|/${opt}/|/${1}/|g"
+ patt="${patt}${1}/"
+ if [ "${patt}" != "/${1}/" ]; then
+ toosdirnames="${toosdirnames} -e s|${patt}|/${1}/|g"
+ fi
+ fi
+ done
+ shift
+ done
+ done
+ fi
+fi
+
+# We need another recursive shell script to correctly handle positive
+# matches. If we are invoked as
+# genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2"
+# we must output
+# opt1/opt2 opt1 opt2
+# opt1/opt2 nopt1 opt2
+# opt1/opt2 opt1 nopt2
+# opt1/opt2 nopt1 nopt2
+# In other words, we must output all combinations of matches.
+rm -f tmpmultilib2
+cat >tmpmultilib2 <<\EOF
+#!/bin/sh
+# The positional parameters are a list of matches to consider.
+# ${dirout} is the directory name and ${optout} is the current list of
+# options.
+if [ "$#" = "0" ]; then
+ echo "\"${dirout} ${optout};\","
+else
+ first=$1
+ shift
+ dirout="${dirout}" optout="${optout}" ./tmpmultilib2 $@
+ l=`echo ${first} | sed -e 's/=.*$//' -e 's/?/=/g'`
+ r=`echo ${first} | sed -e 's/^.*=//' -e 's/?/=/g'`
+ if expr " ${optout} " : ".* ${l} .*" > /dev/null; then
+ newopt=`echo " ${optout} " | sed -e "s/ ${l} / ${r} /" -e 's/^ //' -e 's/ $//'`
+ dirout="${dirout}" optout="${newopt}" ./tmpmultilib2 $@
+ fi
+fi
+EOF
+chmod +x tmpmultilib2
+
+# Start with the current directory, which includes only negations.
+optout=
+for set in ${options}; do
+ for opt in `echo ${set} | sed -e 's_[/|]_ _g'`; do
+ optout="${optout} !${opt}"
+ done
+done
+optout=`echo ${optout} | sed -e 's/^ //'`
+echo "\".${defaultosdirname} ${optout};\","
+[ -n "${defaultosdirname2}" ] && echo "\".${defaultosdirname2} ${optout};\","
+
+# This part of code convert an option combination to
+# its corresponding directory names.
+# The directory names will be deduced from MULTILIB_DIRNAMES,
+# MULTILIB_OSDIRNAMES or the option combination itself.
+rm -rf tmpmultilib3
+cat >tmpmultilib3 <<\EOF
+#!/bin/sh
+
+dirout=
+combo=$1
+todirnames=$2
+toosdirnames=$3
+enable_multilib=$4
+
+if [ -n "${todirnames}" ]; then
+ dirout=`echo ${combo} | sed ${todirnames}`
+else
+ dirout=`echo ${combo} | sed -e 's/=/-/g'`
+fi
+# Remove the leading and trailing slashes.
+dirout=`echo ${dirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'`
+
+# Use the OS directory names rather than the option names.
+if [ -n "${toosdirnames}" ]; then
+ osdirout=`echo ${combo} | sed ${toosdirnames}`
+ # Remove the leading and trailing slashes.
+ osdirout=`echo ${osdirout} | sed -e 's|^/||' -e 's|/*:/*|:|' -e 's|/$||g'`
+ if [ "x${enable_multilib}" != xyes ]; then
+ dirout=".:${osdirout}"
+ disable_multilib=yes
+ else
+ case "${osdirout}" in
+ !*)
+ dirout=`echo ${osdirout} | sed 's/^!//'`
+ ;;
+ *)
+ dirout="${dirout}:${osdirout}"
+ ;;
+ esac
+ fi
+else
+ if [ "x${enable_multilib}" != xyes ]; then
+ # genmultilib with --disable-multilib should be
+ # called with '' '' '' '' '' '' '' no
+ # if MULTILIB_OSDIRNAMES is empty.
+ exit 1
+ fi
+fi
+echo "${dirout}"
+EOF
+chmod +x tmpmultilib3
+
+# Script to look through the options and output each option that is present,
+# and negate each option that is not present.
+rm -rf tmpmultilib4
+cat > tmpmultilib4 <<\EOF
+#!/bin/sh
+
+optout=
+combo=$1
+options=$2
+
+for set in ${options}; do
+ setopts=`echo ${set} | sed -e 's_[/|]_ _g'`
+ for opt in ${setopts}; do
+ if expr "${combo} " : ".*/${opt}/.*" > /dev/null; then
+ optout="${optout} ${opt}"
+ else
+ optout="${optout} !${opt}"
+ fi
+ done
+done
+optout=`echo ${optout} | sed -e 's/^ //'`
+echo "${optout}"
+EOF
+chmod +x tmpmultilib4
+
+# Work over the list of combinations. We have to translate each one
+# to use the directory names rather than the option names, we have to
+# include the information in matches, and we have to generate the
+# correct list of options and negations.
+for combo in ${combinations}; do
+ # Use the directory names rather than the option names.
+ dirout=`./tmpmultilib3 "${combo}" "${todirnames}" "${toosdirnames}" "${enable_multilib}"`
+
+ # Look through the options. We must output each option that is
+ # present, and negate each option that is not present.
+ optout=`./tmpmultilib4 "${combo}" "${options}"`
+
+ # Output the line with all appropriate matches.
+ dirout="${dirout}" optout="${optout}" ./tmpmultilib2
+done
+
+# Terminate the list of string.
+echo "NULL"
+echo "};"
+
+# Generate a regular expression to validate option combinations.
+options_re=
+for set in ${options}; do
+ for opt in `echo ${set} | sed -e 's_[/|]_ _g' -e 's/+/./g' `; do
+ options_re="${options_re}${options_re:+|}${opt}"
+ done
+done
+options_re="^/((${options_re})/)*\$"
+
+# Output rules used for multilib reuse.
+echo ""
+echo "static const char *const multilib_reuse_raw[] = {"
+for rrule in ${multilib_reuse}; do
+ # The left part of the rule are the options we used to build multilib.
+ # The right part of the rule are the options that can reuse this multilib.
+ combo=`echo ${rrule} | sed -e 's/=.*$//' -e 's/\([^\\]\)\./\1=/g' -e 's/\\\././g'`
+ copts=`echo ${rrule} | sed -e 's/^.*=//' -e 's/\([^\\]\)\./\1=/g' -e 's/\\\././g'`
+ # The variable ${combinations} are the option combinations we will build
+ # multilib from. If the combination in the left part of reuse rule isn't
+ # in this variable, it means no multilib will be built for current reuse
+ # rule. Thus the reuse purpose specified by current rule is meaningless.
+ if expr "${combinations} " : ".*/${combo}/.*" > /dev/null; then
+ if echo "/${copts}/" | grep -E "${options_re}" > /dev/null; then
+ combo="/${combo}/"
+ dirout=`./tmpmultilib3 "${combo}" "${todirnames}" "${toosdirnames}" "${enable_multilib}"`
+ copts="/${copts}/"
+ optout=`./tmpmultilib4 "${copts}" "${options}"`
+ # Output the line with all appropriate matches.
+ dirout="${dirout}" optout="${optout}" ./tmpmultilib2
+ else
+ echo "The rule ${rrule} contains an option absent from MULTILIB_OPTIONS." >&2
+ exit 1
+ fi
+ else
+ echo "The rule ${rrule} is trying to reuse nonexistent multilib." >&2
+ exit 1
+ fi
+done
+
+# Terminate the list of string.
+echo "NULL"
+echo "};"
+
+# Output all of the matches now as option and that is the same as that, with
+# a semicolon trailer. Include all of the normal options as well.
+# Note, the format of the matches is reversed compared
+# to what we want, so switch them around.
+echo ""
+echo "static const char *const multilib_matches_raw[] = {"
+for match in ${matches}; do
+ l=`echo ${match} | sed -e 's/=.*$//' -e 's/?/=/g'`
+ r=`echo ${match} | sed -e 's/^.*=//' -e 's/?/=/g'`
+ echo "\"${r} ${l};\","
+done
+for set in ${options}; do
+ for opt in `echo ${set} | sed -e 's_[/|]_ _'g`; do
+ echo "\"${opt} ${opt};\","
+ done
+done
+echo "NULL"
+echo "};"
+
+# Output the default options now
+echo ""
+echo "static const char *multilib_extra = \"${extra}\";"
+
+# Output the exclusion rules now
+echo ""
+echo "static const char *const multilib_exclusions_raw[] = {"
+for rule in ${exclusions}; do
+ s=`echo ${rule} | sed -e 's,/, ,g'`
+ echo "\"${s};\","
+done
+echo "NULL"
+echo "};"
+
+# Output the options now
+moptions=`echo ${options} | sed -e 's,[ ][ ]*, ,g'`
+echo ""
+echo "static const char *multilib_options = \"${moptions}\";"
+
+# Finally output the disable flag if specified
+if [ "x${disable_multilib}" = xyes ]; then
+ echo ""
+ echo "#define DISABLE_MULTILIB 1"
+fi
+
+cd ..
+rm -r tmpmultilib.$$
+
+exit 0
diff --git a/support/cpp/gcc/gensupport.h b/support/cpp/gcc/gensupport.h
new file mode 100644
index 000000000..9a0fd7393
--- /dev/null
+++ b/support/cpp/gcc/gensupport.h
@@ -0,0 +1,228 @@
+/* Declarations for rtx-reader support for gen* routines.
+ Copyright (C) 2000-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_GENSUPPORT_H
+#define GCC_GENSUPPORT_H
+
+#include "read-md.h"
+
+struct obstack;
+extern struct obstack *rtl_obstack;
+
+/* Information about an .md define_* rtx. */
+class md_rtx_info {
+public:
+ /* The rtx itself. */
+ rtx def;
+
+ /* The location of the first line of the rtx. */
+ file_location loc;
+
+ /* The unique number attached to the rtx. Currently all define_insns,
+ define_expands, define_splits, define_peepholes and define_peephole2s
+ share the same insn_code index space. */
+ int index;
+};
+
+#define OPTAB_CL(name, pat, c, b, l) name,
+#define OPTAB_CX(name, pat)
+#define OPTAB_CD(name, pat) name,
+#define OPTAB_NL(name, pat, c, b, s, l) name,
+#define OPTAB_NC(name, pat, c) name,
+#define OPTAB_NX(name, pat)
+#define OPTAB_VL(name, pat, c, b, s, l) name,
+#define OPTAB_VC(name, pat, c) name,
+#define OPTAB_VX(name, pat)
+#define OPTAB_DC(name, pat, c) name,
+#define OPTAB_D(name, pat) name,
+
+/* Enumerates all optabs. */
+typedef enum optab_tag {
+ unknown_optab,
+#include "optabs.def"
+ NUM_OPTABS
+} optab;
+
+#undef OPTAB_CL
+#undef OPTAB_CX
+#undef OPTAB_CD
+#undef OPTAB_NL
+#undef OPTAB_NC
+#undef OPTAB_NX
+#undef OPTAB_VL
+#undef OPTAB_VC
+#undef OPTAB_VX
+#undef OPTAB_DC
+#undef OPTAB_D
+
+/* Describes one entry in optabs.def. */
+struct optab_def
+{
+ /* The name of the optab (e.g. "add_optab"). */
+ const char *name;
+
+ /* The pattern that matching define_expands and define_insns have.
+ See the comment at the head of optabs.def for details. */
+ const char *pattern;
+
+ /* The initializers (in the form of C code) for the libcall_basename,
+ libcall_suffix and libcall_gen fields of (convert_)optab_libcall_d. */
+ const char *base;
+ const char *suffix;
+ const char *libcall;
+
+ /* The optab's enum value. */
+ unsigned int op;
+
+ /* The value returned by optab_to_code (OP). */
+ enum rtx_code fcode;
+
+ /* CODE if code_to_optab (CODE) should return OP, otherwise UNKNOWN. */
+ enum rtx_code rcode;
+
+ /* 1: conversion optabs with libcall data,
+ 2: conversion optabs without libcall data,
+ 3: non-conversion optabs with libcall data ("normal" and "overflow"
+ optabs in the optabs.def comment)
+ 4: non-conversion optabs without libcall data ("direct" optabs). */
+ unsigned int kind;
+};
+
+extern optab_def optabs[];
+extern unsigned int num_optabs;
+
+/* Information about an instruction name that matches an optab pattern. */
+struct optab_pattern
+{
+ /* The name of the instruction. */
+ const char *name;
+
+ /* The matching optab. */
+ unsigned int op;
+
+ /* The optab modes. M2 is only significant for conversion optabs;
+ it is zero otherwise. */
+ unsigned int m1, m2;
+
+ /* An index that provides a lexicographical sort of (OP, M2, M1).
+ Used by genopinit.cc. */
+ unsigned int sort_num;
+};
+
+extern rtx add_implicit_parallel (rtvec);
+extern rtx_reader *init_rtx_reader_args_cb (int, const char **,
+ bool (*)(const char *));
+extern rtx_reader *init_rtx_reader_args (int, const char **);
+extern bool read_md_rtx (md_rtx_info *);
+extern unsigned int get_num_insn_codes ();
+
+/* Set this to 0 to disable automatic elision of insn patterns which
+ can never be used in this configuration. See genconditions.cc.
+ Must be set before calling init_md_reader. */
+extern int insn_elision;
+
+/* Return the C test that says whether a definition rtx can be used,
+ or "" if it can be used unconditionally. */
+extern const char *get_c_test (rtx);
+
+/* If the C test passed as the argument can be evaluated at compile
+ time, return its truth value; else return -1. The test must have
+ appeared somewhere in the machine description when genconditions
+ was run. */
+extern int maybe_eval_c_test (const char *);
+
+/* Add an entry to the table of conditions. Used by genconditions and
+ by read-rtl.cc. */
+extern void add_c_test (const char *, int);
+
+/* This structure is used internally by gensupport.cc and genconditions.cc. */
+struct c_test
+{
+ const char *expr;
+ int value;
+};
+
+#ifdef __HASHTAB_H__
+extern hashval_t hash_c_test (const void *);
+extern int cmp_c_test (const void *, const void *);
+extern void traverse_c_tests (htab_trav, void *);
+#endif
+
+/* Predicate handling: helper functions and data structures. */
+
+struct pred_data
+{
+ struct pred_data *next; /* for iterating over the set of all preds */
+ const char *name; /* predicate name */
+ bool special; /* special handling of modes? */
+
+ /* data used primarily by genpreds.cc */
+ const char *c_block; /* C test block */
+ rtx exp; /* RTL test expression */
+
+ /* data used primarily by genrecog.cc */
+ enum rtx_code singleton; /* if pred takes only one code, that code */
+ int num_codes; /* number of codes accepted */
+ bool allows_non_lvalue; /* if pred allows non-lvalue expressions */
+ bool allows_non_const; /* if pred allows non-const expressions */
+ bool codes[NUM_RTX_CODE]; /* set of codes accepted */
+};
+
+extern struct pred_data *first_predicate;
+extern struct pred_data *lookup_predicate (const char *);
+extern void add_predicate_code (struct pred_data *, enum rtx_code);
+extern void add_predicate (struct pred_data *);
+
+#define FOR_ALL_PREDICATES(p) for (p = first_predicate; p; p = p->next)
+
+struct pattern_stats
+{
+ /* The largest match_operand, match_operator or match_parallel
+ number found. */
+ int max_opno;
+
+ /* The largest match_dup, match_op_dup or match_par_dup number found. */
+ int max_dup_opno;
+
+ /* The smallest and largest match_scratch number found. */
+ int min_scratch_opno;
+ int max_scratch_opno;
+
+ /* The number of times match_dup, match_op_dup or match_par_dup appears
+ in the pattern. */
+ int num_dups;
+
+ /* The number of rtx arguments to the generator function. */
+ int num_generator_args;
+
+ /* The number of rtx operands in an insn. */
+ int num_insn_operands;
+
+ /* The number of operand variables that are needed. */
+ int num_operand_vars;
+};
+
+extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec);
+extern void compute_test_codes (rtx, file_location, char *);
+extern file_location get_file_location (rtx);
+extern const char *get_emit_function (rtx);
+extern bool needs_barrier_p (rtx);
+extern bool find_optab (optab_pattern *, const char *);
+
+#endif /* GCC_GENSUPPORT_H */
diff --git a/support/cpp/gcc/genversion.cc b/support/cpp/gcc/genversion.cc
new file mode 100644
index 000000000..4c5cf2826
--- /dev/null
+++ b/support/cpp/gcc/genversion.cc
@@ -0,0 +1,89 @@
+/* Generate version strings. See gcov-io.h for
+ description of how the version string is generated.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Contributed by Nathan Sidwell <nathan@codesourcery.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.
+
+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 "bconfig.h"
+#include "system.h"
+
+/* Command line arguments are the base GCC version and the development
+ phase (the latter may be an empty string). */
+
+int
+main (void)
+{
+ unsigned int version = 0;
+ unsigned char v[4];
+ unsigned int ix;
+ unsigned long major;
+ unsigned long minor = 0;
+ char phase = 0;
+ char basever[] = BASEVER;
+ char *ptr = basever;
+
+ major = strtoul (ptr, &ptr, 10);
+
+ if (*ptr == '.')
+ minor = strtoul (ptr + 1, 0, 10);
+
+ /* For releases the development phase is an empty string, for
+ prerelease versions on a release branch it is "prerelease".
+ Consider both equal as patch-level releases do not change
+ the GCOV version either.
+ On the trunk the development phase is "experimental". */
+ phase = DEVPHASE[0];
+ if (phase == '\0'
+ || strcmp (DEVPHASE, "prerelease") == 0)
+ phase = '*';
+
+ v[0] = (major / 10) + 'A';
+ v[1] = (major % 10) + '0';
+ v[2] = minor + '0';
+ v[3] = phase;
+
+ for (ix = 0; ix != 4; ix++)
+ version = (version << 8) | v[ix];
+
+ printf ("#ifndef VERSION_H\n");
+ printf ("#define VERSION_H\n\n");
+ printf ("/* Generated automatically by genversion. */\n");
+ printf ("\n");
+ printf ("#define GCC_major_version %lu\n\n", major);
+
+ printf ("/* The complete version string, assembled from several pieces.\n"
+ "BASEVER, DATESTAMP, DEVPHASE, and REVISION are defined by the\n"
+ "Makefile. */\n\n");
+
+ printf ("#define version_string \"" BASEVER DATESTAMP DEVPHASE REVISION "\"\n");
+ printf ("#define pkgversion_string \"" PKGVERSION "\"\n\n");
+
+ printf ("/* This is the location of the online document giving instructions for\n"
+ "reporting bugs. If you distribute a modified version of GCC,\n"
+ "please configure with --with-bugurl pointing to a document giving\n"
+ "instructions for reporting bugs to you, not us. (You are of course\n"
+ "welcome to forward us bugs reported to you, if you determine that\n"
+ "they are not bugs in your modifications.) */\n\n");
+ printf ("#define bug_report_url \"" BUGURL "\"\n\n");
+
+ printf ("#define GCOV_VERSION ((gcov_unsigned_t)0x%08x) /* %.4s */\n",
+ version, v);
+ printf ("\n#endif /* VERSION_H */\n");
+
+ return 0;
+}
diff --git a/support/cpp/gcc/ggc-common.cc b/support/cpp/gcc/ggc-common.cc
new file mode 100644
index 000000000..423626723
--- /dev/null
+++ b/support/cpp/gcc/ggc-common.cc
@@ -0,0 +1,1307 @@
+/* Simple garbage collection for the GNU compiler.
+ 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.
+
+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/>. */
+
+/* Generic garbage collection (GC) functions and data, not specific to
+ any particular GC implementation. */
+
+#include "config.h"
+#define INCLUDE_MALLOC_H
+#include "system.h"
+#include "coretypes.h"
+#include "timevar.h"
+#include "diagnostic-core.h"
+#include "ggc-internal.h"
+#include "hosthooks.h"
+#include "plugin.h"
+#include "options.h"
+
+/* When true, protect the contents of the identifier hash table. */
+bool ggc_protect_identifiers = true;
+
+/* Statistics about the allocation. */
+static ggc_statistics *ggc_stats;
+
+struct traversal_state;
+
+#if 0 // sdcpp
+static int compare_ptr_data (const void *, const void *);
+static void relocate_ptrs (void *, void *, void *);
+static void write_pch_globals (const struct ggc_root_tab * const *tab,
+ struct traversal_state *state);
+#endif // sdcpp
+
+/* Maintain global roots that are preserved during GC. */
+
+/* This extra vector of dynamically registered root_tab-s is used by
+ ggc_mark_roots and gives the ability to dynamically add new GGC root
+ tables, for instance from some plugins; this vector is on the heap
+ since it is used by GGC internally. */
+typedef const struct ggc_root_tab *const_ggc_root_tab_t;
+static vec<const_ggc_root_tab_t> extra_root_vec;
+
+/* Dynamically register a new GGC root table RT. This is useful for
+ plugins. */
+
+void
+ggc_register_root_tab (const struct ggc_root_tab* rt)
+{
+ if (rt)
+ extra_root_vec.safe_push (rt);
+}
+
+/* Mark all the roots in the table RT. */
+
+static void
+ggc_mark_root_tab (const_ggc_root_tab_t rt)
+{
+ size_t i;
+
+ for ( ; rt->base != NULL; rt++)
+ for (i = 0; i < rt->nelt; i++)
+ (*rt->cb) (*(void **) ((char *)rt->base + rt->stride * i));
+}
+
+/* Iterate through all registered roots and mark each element. */
+
+void
+ggc_mark_roots (void)
+{
+ const struct ggc_root_tab *const *rt;
+ const_ggc_root_tab_t rtp, rti;
+ size_t i;
+
+ for (rt = gt_ggc_deletable_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ memset (rti->base, 0, rti->stride);
+
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ ggc_mark_root_tab (*rt);
+
+ FOR_EACH_VEC_ELT (extra_root_vec, i, rtp)
+ ggc_mark_root_tab (rtp);
+
+ if (ggc_protect_identifiers)
+ ggc_mark_stringpool ();
+
+ gt_clear_caches ();
+
+ if (! ggc_protect_identifiers)
+ ggc_purge_stringpool ();
+
+ /* Some plugins may call ggc_set_mark from here. */
+ invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
+}
+
+/* Allocate a block of memory, then clear it. */
+void *
+ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
+ MEM_STAT_DECL)
+{
+ void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
+ memset (buf, 0, size);
+ return buf;
+}
+
+/* Resize a block of memory, possibly re-allocating it. */
+void *
+ggc_realloc (void *x, size_t size MEM_STAT_DECL)
+{
+ void *r;
+ size_t old_size;
+
+ if (x == NULL)
+ return ggc_internal_alloc (size PASS_MEM_STAT);
+
+ old_size = ggc_get_size (x);
+
+ if (size <= old_size)
+ {
+ /* Mark the unwanted memory as unaccessible. We also need to make
+ the "new" size accessible, since ggc_get_size returns the size of
+ the pool, not the size of the individually allocated object, the
+ size which was previously made accessible. Unfortunately, we
+ don't know that previously allocated size. Without that
+ knowledge we have to lose some initialization-tracking for the
+ old parts of the object. An alternative is to mark the whole
+ old_size as reachable, but that would lose tracking of writes
+ after the end of the object (by small offsets). Discard the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *) x + size,
+ old_size - size));
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, size));
+ return x;
+ }
+
+ r = ggc_internal_alloc (size PASS_MEM_STAT);
+
+ /* Since ggc_get_size returns the size of the pool, not the size of the
+ individually allocated object, we'd access parts of the old object
+ that were marked invalid with the memcpy below. We lose a bit of the
+ initialization-tracking since some of it may be uninitialized. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (x, old_size));
+
+ memcpy (r, x, old_size);
+
+ /* The old object is not supposed to be used anymore. */
+ ggc_free (x);
+
+ return r;
+}
+
+void *
+ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
+ size_t n ATTRIBUTE_UNUSED)
+{
+ gcc_assert (c * n == sizeof (struct htab));
+ return ggc_cleared_alloc<htab> ();
+}
+
+/* TODO: once we actually use type information in GGC, create a new tag
+ gt_gcc_ptr_array and use it for pointer arrays. */
+void *
+ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
+{
+ gcc_assert (sizeof (PTR *) == n);
+ return ggc_cleared_vec_alloc<PTR *> (c);
+}
+
+/* These are for splay_tree_new_ggc. */
+void *
+ggc_splay_alloc (int sz, void *nl)
+{
+ gcc_assert (!nl);
+ return ggc_internal_alloc (sz);
+}
+
+void
+ggc_splay_dont_free (void * x ATTRIBUTE_UNUSED, void *nl)
+{
+ gcc_assert (!nl);
+}
+
+void
+ggc_print_common_statistics (FILE *stream ATTRIBUTE_UNUSED,
+ ggc_statistics *stats)
+{
+ /* Set the pointer so that during collection we will actually gather
+ the statistics. */
+ ggc_stats = stats;
+
+ /* Then do one collection to fill in the statistics. */
+ ggc_collect ();
+
+ /* At present, we don't really gather any interesting statistics. */
+
+ /* Don't gather statistics any more. */
+ ggc_stats = NULL;
+}
+
+/* Functions for saving and restoring GCable memory to disk. */
+
+struct ptr_data
+{
+ void *obj;
+ void *note_ptr_cookie;
+ gt_note_pointers note_ptr_fn;
+ gt_handle_reorder reorder_fn;
+ size_t size;
+ void *new_addr;
+};
+
+#define POINTER_HASH(x) (hashval_t)((intptr_t)x >> 3)
+
+/* Helper for hashing saving_htab. */
+
+struct saving_hasher : free_ptr_hash <ptr_data>
+{
+ typedef void *compare_type;
+ static inline hashval_t hash (const ptr_data *);
+ static inline bool equal (const ptr_data *, const void *);
+};
+
+inline hashval_t
+saving_hasher::hash (const ptr_data *p)
+{
+ return POINTER_HASH (p->obj);
+}
+
+inline bool
+saving_hasher::equal (const ptr_data *p1, const void *p2)
+{
+ return p1->obj == p2;
+}
+
+static hash_table<saving_hasher> *saving_htab;
+static vec<void *> callback_vec;
+// sdcpp static vec<void *> reloc_addrs_vec;
+
+/* Register an object in the hash table. */
+
+#if 0 // sdcpp
+int
+gt_pch_note_object (void *obj, void *note_ptr_cookie,
+ gt_note_pointers note_ptr_fn)
+{
+ struct ptr_data **slot;
+
+ if (obj == NULL || obj == (void *) 1)
+ return 0;
+
+ slot = (struct ptr_data **)
+ saving_htab->find_slot_with_hash (obj, POINTER_HASH (obj), INSERT);
+ if (*slot != NULL)
+ {
+ gcc_assert ((*slot)->note_ptr_fn == note_ptr_fn
+ && (*slot)->note_ptr_cookie == note_ptr_cookie);
+ return 0;
+ }
+
+ *slot = XCNEW (struct ptr_data);
+ (*slot)->obj = obj;
+ (*slot)->note_ptr_fn = note_ptr_fn;
+ (*slot)->note_ptr_cookie = note_ptr_cookie;
+ if (note_ptr_fn == gt_pch_p_S)
+ (*slot)->size = strlen ((const char *)obj) + 1;
+ else
+ (*slot)->size = ggc_get_size (obj);
+ return 1;
+}
+#endif // sdcpp
+
+/* Register address of a callback pointer. */
+void
+gt_pch_note_callback (void *obj, void *base)
+{
+ void *ptr;
+ memcpy (&ptr, obj, sizeof (void *));
+ if (ptr != NULL)
+ {
+ struct ptr_data *data
+ = (struct ptr_data *)
+ saving_htab->find_with_hash (base, POINTER_HASH (base));
+ gcc_assert (data);
+ callback_vec.safe_push ((char *) data->new_addr
+ + ((char *) obj - (char *) base));
+ }
+}
+
+/* Register an object in the hash table. */
+
+#if 0 // sdcpp
+void
+gt_pch_note_reorder (void *obj, void *note_ptr_cookie,
+ gt_handle_reorder reorder_fn)
+{
+ struct ptr_data *data;
+
+ if (obj == NULL || obj == (void *) 1)
+ return;
+
+ data = (struct ptr_data *)
+ saving_htab->find_with_hash (obj, POINTER_HASH (obj));
+ gcc_assert (data && data->note_ptr_cookie == note_ptr_cookie);
+
+ data->reorder_fn = reorder_fn;
+}
+#endif // sdcpp
+
+/* Handy state for the traversal functions. */
+
+struct traversal_state
+{
+ FILE *f;
+ struct ggc_pch_data *d;
+ size_t count;
+ struct ptr_data **ptrs;
+ size_t ptrs_i;
+};
+
+/* Callbacks for htab_traverse. */
+
+int
+ggc_call_count (ptr_data **slot, traversal_state *state)
+{
+ struct ptr_data *d = *slot;
+
+ ggc_pch_count_object (state->d, d->obj, d->size,
+ d->note_ptr_fn == gt_pch_p_S);
+ state->count++;
+ return 1;
+}
+
+int
+ggc_call_alloc (ptr_data **slot, traversal_state *state)
+{
+ struct ptr_data *d = *slot;
+
+ d->new_addr = ggc_pch_alloc_object (state->d, d->obj, d->size,
+ d->note_ptr_fn == gt_pch_p_S);
+ state->ptrs[state->ptrs_i++] = d;
+ return 1;
+}
+
+/* Callback for qsort. */
+
+#if 0 // sdcpp
+static int
+compare_ptr_data (const void *p1_p, const void *p2_p)
+{
+ const struct ptr_data *const p1 = *(const struct ptr_data *const *)p1_p;
+ const struct ptr_data *const p2 = *(const struct ptr_data *const *)p2_p;
+ return (((size_t)p1->new_addr > (size_t)p2->new_addr)
+ - ((size_t)p1->new_addr < (size_t)p2->new_addr));
+}
+
+/* Callbacks for note_ptr_fn. */
+
+static void
+relocate_ptrs (void *ptr_p, void *real_ptr_p, void *state_p)
+{
+ void **ptr = (void **)ptr_p;
+ struct traversal_state *state
+ = (struct traversal_state *)state_p;
+ struct ptr_data *result;
+
+ if (*ptr == NULL || *ptr == (void *)1)
+ return;
+
+ result = (struct ptr_data *)
+ saving_htab->find_with_hash (*ptr, POINTER_HASH (*ptr));
+ gcc_assert (result);
+ *ptr = result->new_addr;
+ if (ptr_p == real_ptr_p)
+ return;
+ if (real_ptr_p == NULL)
+ real_ptr_p = ptr_p;
+ gcc_assert (real_ptr_p >= state->ptrs[state->ptrs_i]->obj
+ && ((char *) real_ptr_p + sizeof (void *)
+ <= ((char *) state->ptrs[state->ptrs_i]->obj
+ + state->ptrs[state->ptrs_i]->size)));
+ void *addr
+ = (void *) ((char *) state->ptrs[state->ptrs_i]->new_addr
+ + ((char *) real_ptr_p
+ - (char *) state->ptrs[state->ptrs_i]->obj));
+ reloc_addrs_vec.safe_push (addr);
+}
+#endif // sdcpp
+
+/* Write out, after relocation, the pointers in TAB. */
+#if 0 // sdcpp
+static void
+write_pch_globals (const struct ggc_root_tab * const *tab,
+ struct traversal_state *state)
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+
+ for (rt = tab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ void *ptr = *(void **)((char *)rti->base + rti->stride * i);
+ struct ptr_data *new_ptr;
+ if (ptr == NULL || ptr == (void *)1)
+ {
+ if (fwrite (&ptr, sizeof (void *), 1, state->f)
+ != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+ }
+ else
+ {
+ new_ptr = (struct ptr_data *)
+ saving_htab->find_with_hash (ptr, POINTER_HASH (ptr));
+ if (fwrite (&new_ptr->new_addr, sizeof (void *), 1, state->f)
+ != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+ }
+ }
+}
+#endif // sdcpp
+
+/* Callback for qsort. */
+
+#if 0 // sdcpp
+static int
+compare_ptr (const void *p1_p, const void *p2_p)
+{
+ void *p1 = *(void *const *)p1_p;
+ void *p2 = *(void *const *)p2_p;
+ return (((uintptr_t)p1 > (uintptr_t)p2)
+ - ((uintptr_t)p1 < (uintptr_t)p2));
+}
+#endif // sdcpp
+
+/* Decode one uleb128 from P, return first byte after it, store
+ decoded value into *VAL. */
+
+static unsigned char *
+read_uleb128 (unsigned char *p, size_t *val)
+{
+ unsigned int shift = 0;
+ unsigned char byte;
+ size_t result;
+
+ result = 0;
+ do
+ {
+ byte = *p++;
+ result |= ((size_t) byte & 0x7f) << shift;
+ shift += 7;
+ }
+ while (byte & 0x80);
+
+ *val = result;
+ return p;
+}
+
+/* Store VAL as uleb128 at P, return length in bytes. */
+
+#if 0 // sdcpp
+static size_t
+write_uleb128 (unsigned char *p, size_t val)
+{
+ size_t len = 0;
+ do
+ {
+ unsigned char byte = (val & 0x7f);
+ val >>= 7;
+ if (val != 0)
+ /* More bytes to follow. */
+ byte |= 0x80;
+
+ *p++ = byte;
+ ++len;
+ }
+ while (val != 0);
+ return len;
+}
+#endif // sdcpp
+
+/* Hold the information we need to mmap the file back in. */
+
+struct mmap_info
+{
+ size_t offset;
+ size_t size;
+ void *preferred_base;
+};
+
+/* Write out the state of the compiler to F. */
+
+void
+gt_pch_save (FILE *f)
+{
+#if 1 // sdcpp
+ (void) f;
+ fprintf(stderr, "unreachable %s %d\n", __FILE__, __LINE__);
+#else // sdcpp
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct traversal_state state;
+ char *this_object = NULL;
+ size_t this_object_size = 0;
+ struct mmap_info mmi;
+ const size_t mmap_offset_alignment = 0; // host_hooks.gt_pch_alloc_granularity ();
+
+ gt_pch_save_stringpool ();
+
+ timevar_push (TV_PCH_PTR_REALLOC);
+ saving_htab = new hash_table<saving_hasher> (50000);
+
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->pchw)(*(void **)((char *)rti->base + rti->stride * i));
+
+ /* Prepare the objects for writing, determine addresses and such. */
+ state.f = f;
+ state.d = init_ggc_pch ();
+ state.count = 0;
+ saving_htab->traverse <traversal_state *, ggc_call_count> (&state);
+
+ mmi.size = ggc_pch_total_size (state.d);
+
+ /* Try to arrange things so that no relocation is necessary, but
+ don't try very hard. On most platforms, this will always work,
+ and on the rest it's a lot of work to do better.
+ (The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
+ HOST_HOOKS_GT_PCH_USE_ADDRESS.) */
+ fprintf(stderr, "incomplete %s %d\n", __FILE__, __LINE__);
+ // mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
+ /* If the host cannot supply any suitable address for this, we are stuck. */
+ if (mmi.preferred_base == NULL)
+ fatal_error (input_location,
+ "cannot write PCH file: required memory segment unavailable");
+
+ ggc_pch_this_base (state.d, mmi.preferred_base);
+
+ state.ptrs = XNEWVEC (struct ptr_data *, state.count);
+ state.ptrs_i = 0;
+
+ saving_htab->traverse <traversal_state *, ggc_call_alloc> (&state);
+ timevar_pop (TV_PCH_PTR_REALLOC);
+
+ timevar_push (TV_PCH_PTR_SORT);
+ qsort (state.ptrs, state.count, sizeof (*state.ptrs), compare_ptr_data);
+ timevar_pop (TV_PCH_PTR_SORT);
+
+ /* Write out all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fwrite (rti->base, rti->stride, 1, f) != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+
+ /* Write out all the global pointers, after translation. */
+ write_pch_globals (gt_ggc_rtab, &state);
+
+ /* Pad the PCH file so that the mmapped area starts on an allocation
+ granularity (usually page) boundary. */
+ {
+ long o;
+ o = ftell (state.f) + sizeof (mmi);
+ if (o == -1)
+ fatal_error (input_location, "cannot get position in PCH file: %m");
+ mmi.offset = mmap_offset_alignment - o % mmap_offset_alignment;
+ if (mmi.offset == mmap_offset_alignment)
+ mmi.offset = 0;
+ mmi.offset += o;
+ }
+ if (fwrite (&mmi, sizeof (mmi), 1, state.f) != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+ if (mmi.offset != 0
+ && fseek (state.f, mmi.offset, SEEK_SET) != 0)
+ fatal_error (input_location, "cannot write padding to PCH file: %m");
+
+ ggc_pch_prepare_write (state.d, state.f);
+
+#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
+ vec<char> vbits = vNULL;
+#endif
+
+ /* Actually write out the objects. */
+ for (i = 0; i < state.count; i++)
+ {
+ state.ptrs_i = i;
+ if (this_object_size < state.ptrs[i]->size)
+ {
+ this_object_size = state.ptrs[i]->size;
+ this_object = XRESIZEVAR (char, this_object, this_object_size);
+ }
+#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
+ /* obj might contain uninitialized bytes, e.g. in the trailing
+ padding of the object. Avoid warnings by making the memory
+ temporarily defined and then restoring previous state. */
+ int get_vbits = 0;
+ size_t valid_size = state.ptrs[i]->size;
+ if (__builtin_expect (RUNNING_ON_VALGRIND, 0))
+ {
+ if (vbits.length () < valid_size)
+ vbits.safe_grow (valid_size, true);
+ get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
+ vbits.address (), valid_size);
+ if (get_vbits == 3)
+ {
+ /* We assume that first part of obj is addressable, and
+ the rest is unaddressable. Find out where the boundary is
+ using binary search. */
+ size_t lo = 0, hi = valid_size;
+ while (hi > lo)
+ {
+ size_t mid = (lo + hi) / 2;
+ get_vbits = VALGRIND_GET_VBITS ((char *) state.ptrs[i]->obj
+ + mid, vbits.address (),
+ 1);
+ if (get_vbits == 3)
+ hi = mid;
+ else if (get_vbits == 1)
+ lo = mid + 1;
+ else
+ break;
+ }
+ if (get_vbits == 1 || get_vbits == 3)
+ {
+ valid_size = lo;
+ get_vbits = VALGRIND_GET_VBITS (state.ptrs[i]->obj,
+ vbits.address (),
+ valid_size);
+ }
+ }
+ if (get_vbits == 1)
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_DEFINED (state.ptrs[i]->obj,
+ state.ptrs[i]->size));
+ }
+#endif
+ memcpy (this_object, state.ptrs[i]->obj, state.ptrs[i]->size);
+ if (state.ptrs[i]->reorder_fn != NULL)
+ state.ptrs[i]->reorder_fn (state.ptrs[i]->obj,
+ state.ptrs[i]->note_ptr_cookie,
+ relocate_ptrs, &state);
+ state.ptrs[i]->note_ptr_fn (state.ptrs[i]->obj,
+ state.ptrs[i]->note_ptr_cookie,
+ relocate_ptrs, &state);
+ ggc_pch_write_object (state.d, state.f, state.ptrs[i]->obj,
+ state.ptrs[i]->new_addr, state.ptrs[i]->size,
+ state.ptrs[i]->note_ptr_fn == gt_pch_p_S);
+ if (state.ptrs[i]->note_ptr_fn != gt_pch_p_S)
+ memcpy (state.ptrs[i]->obj, this_object, state.ptrs[i]->size);
+#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
+ if (__builtin_expect (get_vbits == 1, 0))
+ {
+ (void) VALGRIND_SET_VBITS (state.ptrs[i]->obj, vbits.address (),
+ valid_size);
+ if (valid_size != state.ptrs[i]->size)
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)
+ state.ptrs[i]->obj
+ + valid_size,
+ state.ptrs[i]->size
+ - valid_size));
+ }
+#endif
+ }
+#if defined ENABLE_VALGRIND_ANNOTATIONS && defined VALGRIND_GET_VBITS
+ vbits.release ();
+#endif
+
+ reloc_addrs_vec.qsort (compare_ptr);
+
+ size_t reloc_addrs_size = 0;
+ void *last_addr = NULL;
+ unsigned char uleb128_buf[sizeof (size_t) * 2];
+ for (void *addr : reloc_addrs_vec)
+ {
+ gcc_assert ((uintptr_t) addr >= (uintptr_t) mmi.preferred_base
+ && ((uintptr_t) addr + sizeof (void *)
+ < (uintptr_t) mmi.preferred_base + mmi.size));
+ if (addr == last_addr)
+ continue;
+ if (last_addr == NULL)
+ last_addr = mmi.preferred_base;
+ size_t diff = (uintptr_t) addr - (uintptr_t) last_addr;
+ reloc_addrs_size += write_uleb128 (uleb128_buf, diff);
+ last_addr = addr;
+ }
+ if (fwrite (&reloc_addrs_size, sizeof (reloc_addrs_size), 1, f) != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+ last_addr = NULL;
+ for (void *addr : reloc_addrs_vec)
+ {
+ if (addr == last_addr)
+ continue;
+ if (last_addr == NULL)
+ last_addr = mmi.preferred_base;
+ size_t diff = (uintptr_t) addr - (uintptr_t) last_addr;
+ reloc_addrs_size = write_uleb128 (uleb128_buf, diff);
+ if (fwrite (uleb128_buf, 1, reloc_addrs_size, f) != reloc_addrs_size)
+ fatal_error (input_location, "cannot write PCH file: %m");
+ last_addr = addr;
+ }
+
+ ggc_pch_finish (state.d, state.f);
+
+ gt_pch_fixup_stringpool ();
+
+ unsigned num_callbacks = callback_vec.length ();
+ void (*pch_save) (FILE *) = &gt_pch_save;
+ if (fwrite (&pch_save, sizeof (pch_save), 1, f) != 1
+ || fwrite (&num_callbacks, sizeof (num_callbacks), 1, f) != 1
+ || (num_callbacks
+ && fwrite (callback_vec.address (), sizeof (void *), num_callbacks,
+ f) != num_callbacks))
+ fatal_error (input_location, "cannot write PCH file: %m");
+
+ XDELETE (state.ptrs);
+ XDELETE (this_object);
+ delete saving_htab;
+ saving_htab = NULL;
+ callback_vec.release ();
+ reloc_addrs_vec.release ();
+#endif // sdcpp
+}
+
+/* Read the state of the compiler back in from F. */
+
+void
+gt_pch_restore (FILE *f)
+{
+ const struct ggc_root_tab *const *rt;
+ const struct ggc_root_tab *rti;
+ size_t i;
+ struct mmap_info mmi;
+ int result;
+
+ /* We are about to reload the line maps along with the rest of the PCH
+ data, which means that the (loaded) ones cannot be guaranteed to be
+ in any valid state for reporting diagnostics that happen during the
+ load. Save the current table (and use it during the loading process
+ below). */
+ class line_maps *save_line_table = line_table;
+
+ /* Delete any deletable objects. This makes ggc_pch_read much
+ faster, as it can be sure that no GCable objects remain other
+ than the ones just read in. */
+ for (rt = gt_ggc_deletable_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ memset (rti->base, 0, rti->stride);
+
+ /* Read in all the scalar variables. */
+ for (rt = gt_pch_scalar_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ if (fread (rti->base, rti->stride, 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ /* Read in all the global pointers, in 6 easy loops. */
+ bool error_reading_pointers = false;
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ if (fread ((char *)rti->base + rti->stride * i,
+ sizeof (void *), 1, f) != 1)
+ error_reading_pointers = true;
+
+ /* Stash the newly read-in line table pointer - it does not point to
+ anything meaningful yet, so swap the old one back in. */
+ class line_maps *new_line_table = line_table;
+ line_table = save_line_table;
+ if (error_reading_pointers)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ if (fread (&mmi, sizeof (mmi), 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ void *orig_preferred_base = mmi.preferred_base;
+
+ fprintf(stderr, "incomplete %s %d\n", __FILE__, __LINE__);
+ result = 0; // host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
+// fileno (f), mmi.offset);
+
+ /* We could not mmap or otherwise allocate the required memory at the
+ address needed. */
+ if (result < 0)
+ {
+ sorry_at (input_location, "PCH allocation failure");
+ /* There is no point in continuing from here, we will only end up
+ with a crashed (most likely hanging) compiler. */
+ exit (-1);
+ }
+
+ /* (0) We allocated memory, but did not mmap the file, so we need to read
+ the data in manually. (>0) Otherwise the mmap succeed for the address
+ we wanted. */
+ if (result == 0)
+ {
+ if (fseek (f, mmi.offset, SEEK_SET) != 0
+ || fread (mmi.preferred_base, mmi.size, 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ }
+ else if (fseek (f, mmi.offset + mmi.size, SEEK_SET) != 0)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ size_t reloc_addrs_size;
+ if (fread (&reloc_addrs_size, sizeof (reloc_addrs_size), 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ if (orig_preferred_base != mmi.preferred_base)
+ {
+ uintptr_t bias
+ = (uintptr_t) mmi.preferred_base - (uintptr_t) orig_preferred_base;
+
+ /* Adjust all the global pointers by bias. */
+ line_table = new_line_table;
+ for (rt = gt_ggc_rtab; *rt; rt++)
+ for (rti = *rt; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ {
+ char *addr = (char *)rti->base + rti->stride * i;
+ char *p;
+ memcpy (&p, addr, sizeof (void *));
+ if ((uintptr_t) p >= (uintptr_t) orig_preferred_base
+ && (uintptr_t) p < (uintptr_t) orig_preferred_base + mmi.size)
+ {
+ p = (char *) ((uintptr_t) p + bias);
+ memcpy (addr, &p, sizeof (void *));
+ }
+ }
+ new_line_table = line_table;
+ line_table = save_line_table;
+
+ /* And adjust all the pointers in the image by bias too. */
+ char *addr = (char *) mmi.preferred_base;
+ unsigned char uleb128_buf[4096], *uleb128_ptr = uleb128_buf;
+ while (reloc_addrs_size != 0)
+ {
+ size_t this_size
+ = MIN (reloc_addrs_size,
+ (size_t) (4096 - (uleb128_ptr - uleb128_buf)));
+ if (fread (uleb128_ptr, 1, this_size, f) != this_size)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ unsigned char *uleb128_end = uleb128_ptr + this_size;
+ if (this_size != reloc_addrs_size)
+ uleb128_end -= 2 * sizeof (size_t);
+ uleb128_ptr = uleb128_buf;
+ while (uleb128_ptr < uleb128_end)
+ {
+ size_t diff;
+ uleb128_ptr = read_uleb128 (uleb128_ptr, &diff);
+ addr = (char *) ((uintptr_t) addr + diff);
+
+ char *p;
+ memcpy (&p, addr, sizeof (void *));
+ gcc_assert ((uintptr_t) p >= (uintptr_t) orig_preferred_base
+ && ((uintptr_t) p
+ < (uintptr_t) orig_preferred_base + mmi.size));
+ p = (char *) ((uintptr_t) p + bias);
+ memcpy (addr, &p, sizeof (void *));
+ }
+ reloc_addrs_size -= this_size;
+ if (reloc_addrs_size == 0)
+ break;
+ this_size = uleb128_end + 2 * sizeof (size_t) - uleb128_ptr;
+ memcpy (uleb128_buf, uleb128_ptr, this_size);
+ uleb128_ptr = uleb128_buf + this_size;
+ }
+ }
+ else if (fseek (f, (mmi.offset + mmi.size + sizeof (reloc_addrs_size)
+ + reloc_addrs_size), SEEK_SET) != 0)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ ggc_pch_read (f, mmi.preferred_base);
+
+ void (*pch_save) (FILE *);
+ unsigned num_callbacks;
+ if (fread (&pch_save, sizeof (pch_save), 1, f) != 1
+ || fread (&num_callbacks, sizeof (num_callbacks), 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ if (pch_save != &gt_pch_save)
+ {
+ uintptr_t binbias = (uintptr_t) &gt_pch_save - (uintptr_t) pch_save;
+ void **ptrs = XNEWVEC (void *, num_callbacks);
+ unsigned i;
+ uintptr_t bias
+ = (uintptr_t) mmi.preferred_base - (uintptr_t) orig_preferred_base;
+
+ if (fread (ptrs, sizeof (void *), num_callbacks, f) != num_callbacks)
+ fatal_error (input_location, "cannot read PCH file: %m");
+ for (i = 0; i < num_callbacks; ++i)
+ {
+ void *ptr = (void *) ((uintptr_t) ptrs[i] + bias);
+ memcpy (&pch_save, ptr, sizeof (pch_save));
+ pch_save = (void (*) (FILE *)) ((uintptr_t) pch_save + binbias);
+ memcpy (ptr, &pch_save, sizeof (pch_save));
+ }
+ XDELETE (ptrs);
+ }
+ else if (fseek (f, num_callbacks * sizeof (void *), SEEK_CUR) != 0)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ gt_pch_restore_stringpool ();
+
+ /* Barring corruption of the PCH file, the restored line table should be
+ complete and usable. */
+ line_table = new_line_table;
+}
+
+/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present.
+ Select no address whatsoever, and let gt_pch_save choose what it will with
+ malloc, presumably. */
+
+void *
+default_gt_pch_get_address (size_t size ATTRIBUTE_UNUSED,
+ int fd ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
+
+/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is not present.
+ Allocate SIZE bytes with malloc. Return 0 if the address we got is the
+ same as base, indicating that the memory has been allocated but needs to
+ be read in from the file. Return -1 if the address differs, to relocation
+ of the PCH file would be required. */
+
+int
+default_gt_pch_use_address (void *&base, size_t size, int fd ATTRIBUTE_UNUSED,
+ size_t offset ATTRIBUTE_UNUSED)
+{
+ void *addr = xmalloc (size);
+ return (addr == base) - 1;
+}
+
+/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS. Return the
+ alignment required for allocating virtual memory. Usually this is the
+ same as pagesize. */
+
+size_t
+default_gt_pch_alloc_granularity (void)
+{
+ return getpagesize ();
+}
+
+#if HAVE_MMAP_FILE
+/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is present.
+ We temporarily allocate SIZE bytes, and let the kernel place the data
+ wherever it will. If it worked, that's our spot, if not we're likely
+ to be in trouble. */
+
+void *
+mmap_gt_pch_get_address (size_t size, int fd)
+{
+ void *ret;
+
+ ret = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (ret == (void *) MAP_FAILED)
+ ret = NULL;
+ else
+ munmap ((caddr_t) ret, size);
+
+ return ret;
+}
+
+/* Default version of HOST_HOOKS_GT_PCH_USE_ADDRESS when mmap is present.
+ Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at
+ mapping the data at BASE, -1 if we couldn't.
+
+ This version assumes that the kernel honors the START operand of mmap
+ even without MAP_FIXED if START through START+SIZE are not currently
+ mapped with something. */
+
+int
+mmap_gt_pch_use_address (void *&base, size_t size, int fd, size_t offset)
+{
+ void *addr;
+
+ /* We're called with size == 0 if we're not planning to load a PCH
+ file at all. This allows the hook to free any static space that
+ we might have allocated at link time. */
+ if (size == 0)
+ return -1;
+
+ addr = mmap ((caddr_t) base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fd, offset);
+
+ return addr == base ? 1 : -1;
+}
+#endif /* HAVE_MMAP_FILE */
+
+#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
+
+/* Modify the bound based on rlimits. */
+static double
+ggc_rlimit_bound (double limit)
+{
+#if defined(HAVE_GETRLIMIT)
+ struct rlimit rlim;
+# if defined (RLIMIT_AS)
+ /* RLIMIT_AS is what POSIX says is the limit on mmap. Presumably
+ any OS which has RLIMIT_AS also has a working mmap that GCC will use. */
+ if (getrlimit (RLIMIT_AS, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
+ && rlim.rlim_cur < limit)
+ limit = rlim.rlim_cur;
+# elif defined (RLIMIT_DATA)
+ /* ... but some older OSs bound mmap based on RLIMIT_DATA, or we
+ might be on an OS that has a broken mmap. (Others don't bound
+ mmap at all, apparently.) */
+ if (getrlimit (RLIMIT_DATA, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY
+ && rlim.rlim_cur < limit
+ /* Darwin has this horribly bogus default setting of
+ RLIMIT_DATA, to 6144Kb. No-one notices because RLIMIT_DATA
+ appears to be ignored. Ignore such silliness. If a limit
+ this small was actually effective for mmap, GCC wouldn't even
+ start up. */
+ && rlim.rlim_cur >= 8 * ONE_M)
+ limit = rlim.rlim_cur;
+# endif /* RLIMIT_AS or RLIMIT_DATA */
+#endif /* HAVE_GETRLIMIT */
+
+ return limit;
+}
+
+/* Heuristic to set a default for GGC_MIN_EXPAND. */
+static int
+ggc_min_expand_heuristic (void)
+{
+ double min_expand = physmem_total ();
+
+ /* Adjust for rlimits. */
+ min_expand = ggc_rlimit_bound (min_expand);
+
+ /* The heuristic is a percentage equal to 30% + 70%*(RAM/1GB), yielding
+ a lower bound of 30% and an upper bound of 100% (when RAM >= 1GB). */
+ min_expand /= ONE_G;
+ min_expand *= 70;
+ min_expand = MIN (min_expand, 70);
+ min_expand += 30;
+
+ return min_expand;
+}
+
+/* Heuristic to set a default for GGC_MIN_HEAPSIZE. */
+static int
+ggc_min_heapsize_heuristic (void)
+{
+ double phys_kbytes = physmem_total ();
+ double limit_kbytes = ggc_rlimit_bound (phys_kbytes * 2);
+
+ phys_kbytes /= ONE_K; /* Convert to Kbytes. */
+ limit_kbytes /= ONE_K;
+
+ /* The heuristic is RAM/8, with a lower bound of 4M and an upper
+ bound of 128M (when RAM >= 1GB). */
+ phys_kbytes /= 8;
+
+#if defined(HAVE_GETRLIMIT) && defined (RLIMIT_RSS)
+ /* Try not to overrun the RSS limit while doing garbage collection.
+ The RSS limit is only advisory, so no margin is subtracted. */
+ {
+ struct rlimit rlim;
+ if (getrlimit (RLIMIT_RSS, &rlim) == 0
+ && rlim.rlim_cur != (rlim_t) RLIM_INFINITY)
+ phys_kbytes = MIN (phys_kbytes, rlim.rlim_cur / ONE_K);
+ }
+# endif
+
+ /* Don't blindly run over our data limit; do GC at least when the
+ *next* GC would be within 20Mb of the limit or within a quarter of
+ the limit, whichever is larger. If GCC does hit the data limit,
+ compilation will fail, so this tries to be conservative. */
+ limit_kbytes = MAX (0, limit_kbytes - MAX (limit_kbytes / 4, 20 * ONE_K));
+ limit_kbytes = (limit_kbytes * 100) / (110 + ggc_min_expand_heuristic ());
+ phys_kbytes = MIN (phys_kbytes, limit_kbytes);
+
+ phys_kbytes = MAX (phys_kbytes, 4 * ONE_K);
+ phys_kbytes = MIN (phys_kbytes, 128 * ONE_K);
+
+ return phys_kbytes;
+}
+#endif
+
+void
+init_ggc_heuristics (void)
+{
+#if !defined ENABLE_GC_CHECKING && !defined ENABLE_GC_ALWAYS_COLLECT
+ param_ggc_min_expand = ggc_min_expand_heuristic ();
+ param_ggc_min_heapsize = ggc_min_heapsize_heuristic ();
+#endif
+}
+
+/* GGC memory usage. */
+class ggc_usage: public mem_usage
+{
+public:
+ /* Default constructor. */
+ ggc_usage (): m_freed (0), m_collected (0), m_overhead (0) {}
+ /* Constructor. */
+ ggc_usage (size_t allocated, size_t times, size_t peak,
+ size_t freed, size_t collected, size_t overhead)
+ : mem_usage (allocated, times, peak),
+ m_freed (freed), m_collected (collected), m_overhead (overhead) {}
+
+ /* Equality operator. */
+ inline bool
+ operator== (const ggc_usage &second) const
+ {
+ return (get_balance () == second.get_balance ()
+ && m_peak == second.m_peak
+ && m_times == second.m_times);
+ }
+
+ /* Comparison operator. */
+ inline bool
+ operator< (const ggc_usage &second) const
+ {
+ if (*this == second)
+ return false;
+
+ return (get_balance () == second.get_balance () ?
+ (m_peak == second.m_peak ? m_times < second.m_times
+ : m_peak < second.m_peak)
+ : get_balance () < second.get_balance ());
+ }
+
+ /* Register overhead of ALLOCATED and OVERHEAD bytes. */
+ inline void
+ register_overhead (size_t allocated, size_t overhead)
+ {
+ m_allocated += allocated;
+ m_overhead += overhead;
+ m_times++;
+ }
+
+ /* Release overhead of SIZE bytes. */
+ inline void
+ release_overhead (size_t size)
+ {
+ m_freed += size;
+ }
+
+ /* Sum the usage with SECOND usage. */
+ ggc_usage
+ operator+ (const ggc_usage &second)
+ {
+ return ggc_usage (m_allocated + second.m_allocated,
+ m_times + second.m_times,
+ m_peak + second.m_peak,
+ m_freed + second.m_freed,
+ m_collected + second.m_collected,
+ m_overhead + second.m_overhead);
+ }
+
+ /* Dump usage with PREFIX, where TOTAL is sum of all rows. */
+ inline void
+ dump (const char *prefix, ggc_usage &total) const
+ {
+ size_t balance = get_balance ();
+ fprintf (stderr,
+ "%-48s " PRsa (9) ":%5.1f%%" PRsa (9) ":%5.1f%%"
+ PRsa (9) ":%5.1f%%" PRsa (9) ":%5.1f%%" PRsa (9) "\n",
+ prefix,
+ SIZE_AMOUNT (balance), get_percent (balance, total.get_balance ()),
+ SIZE_AMOUNT (m_collected),
+ get_percent (m_collected, total.m_collected),
+ SIZE_AMOUNT (m_freed), get_percent (m_freed, total.m_freed),
+ SIZE_AMOUNT (m_overhead),
+ get_percent (m_overhead, total.m_overhead),
+ SIZE_AMOUNT (m_times));
+ }
+
+ /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
+ inline void
+ dump (mem_location *loc, ggc_usage &total) const
+ {
+ char *location_string = loc->to_string ();
+
+ dump (location_string, total);
+
+ free (location_string);
+ }
+
+ /* Dump footer. */
+ inline void
+ dump_footer ()
+ {
+ dump ("Total", *this);
+ }
+
+ /* Get balance which is GGC allocation leak. */
+ inline size_t
+ get_balance () const
+ {
+ return m_allocated + m_overhead - m_collected - m_freed;
+ }
+
+ typedef std::pair<mem_location *, ggc_usage *> mem_pair_t;
+
+ /* Compare wrapper used by qsort method. */
+ static int
+ compare (const void *first, const void *second)
+ {
+ const mem_pair_t mem1 = *(const mem_pair_t *) first;
+ const mem_pair_t mem2 = *(const mem_pair_t *) second;
+
+ size_t balance1 = mem1.second->get_balance ();
+ size_t balance2 = mem2.second->get_balance ();
+
+ return balance1 == balance2 ? 0 : (balance1 < balance2 ? 1 : -1);
+ }
+
+ /* Dump header with NAME. */
+ static inline void
+ dump_header (const char *name)
+ {
+ fprintf (stderr, "%-48s %11s%17s%17s%16s%17s\n", name, "Leak", "Garbage",
+ "Freed", "Overhead", "Times");
+ }
+
+ /* Freed memory in bytes. */
+ size_t m_freed;
+ /* Collected memory in bytes. */
+ size_t m_collected;
+ /* Overhead memory in bytes. */
+ size_t m_overhead;
+};
+
+/* GCC memory description. */
+static mem_alloc_description<ggc_usage> ggc_mem_desc;
+
+/* Dump per-site memory statistics. */
+
+void
+dump_ggc_loc_statistics ()
+{
+ if (! GATHER_STATISTICS)
+ return;
+
+ ggc_collect (GGC_COLLECT_FORCE);
+
+ ggc_mem_desc.dump (GGC_ORIGIN);
+}
+
+/* Record ALLOCATED and OVERHEAD bytes to descriptor NAME:LINE (FUNCTION). */
+void
+ggc_record_overhead (size_t allocated, size_t overhead, void *ptr MEM_STAT_DECL)
+{
+ ggc_usage *usage = ggc_mem_desc.register_descriptor (ptr, GGC_ORIGIN, false
+ FINAL_PASS_MEM_STAT);
+
+ ggc_mem_desc.register_object_overhead (usage, allocated + overhead, ptr);
+ usage->register_overhead (allocated, overhead);
+}
+
+/* Notice that the pointer has been freed. */
+void
+ggc_free_overhead (void *ptr)
+{
+ ggc_mem_desc.release_object_overhead (ptr);
+}
+
+/* After live values has been marked, walk all recorded pointers and see if
+ they are still live. */
+void
+ggc_prune_overhead_list (void)
+{
+ typedef hash_map<const void *, std::pair<ggc_usage *, size_t > > map_t;
+
+ map_t::iterator it = ggc_mem_desc.m_reverse_object_map->begin ();
+
+ for (; it != ggc_mem_desc.m_reverse_object_map->end (); ++it)
+ if (!ggc_marked_p ((*it).first))
+ {
+ (*it).second.first->m_collected += (*it).second.second;
+ ggc_mem_desc.m_reverse_object_map->remove ((*it).first);
+ }
+}
+
+/* Print memory used by heap if this info is available. */
+
+void
+report_heap_memory_use ()
+{
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
+#ifdef HAVE_MALLINFO2
+ #define MALLINFO_FN mallinfo2
+#else
+ #define MALLINFO_FN mallinfo
+#endif
+ if (!quiet_flag)
+ fprintf (stderr, " {heap " PRsa (0) "}",
+ SIZE_AMOUNT (MALLINFO_FN ().arena));
+#endif
+}
diff --git a/support/cpp/gcc/ggc-internal.h b/support/cpp/gcc/ggc-internal.h
new file mode 100644
index 000000000..a353de43a
--- /dev/null
+++ b/support/cpp/gcc/ggc-internal.h
@@ -0,0 +1,115 @@
+/* Garbage collection for the GNU compiler. Internal definitions
+ for ggc-*.c and stringpool.cc.
+
+ Copyright (C) 2009-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_GGC_INTERNAL_H
+#define GCC_GGC_INTERNAL_H
+
+
+/* Call ggc_set_mark on all the roots. */
+extern void ggc_mark_roots (void);
+
+/* Stringpool. */
+
+/* Mark the entries in the string pool. */
+extern void ggc_mark_stringpool (void);
+
+/* Purge the entries in the string pool. */
+extern void ggc_purge_stringpool (void);
+
+/* Save and restore the string pool entries for PCH. */
+
+extern void gt_pch_save_stringpool (void);
+extern void gt_pch_fixup_stringpool (void);
+extern void gt_pch_restore_stringpool (void);
+
+/* PCH and GGC handling for strings, mostly trivial. */
+extern void gt_pch_p_S (void *, void *, gt_pointer_operator, void *);
+
+/* PCH. */
+
+struct ggc_pch_data;
+
+/* Return a new ggc_pch_data structure. */
+extern struct ggc_pch_data *init_ggc_pch (void);
+
+/* The second parameter and third parameters give the address and size
+ of an object. Update the ggc_pch_data structure with as much of
+ that information as is necessary. The bool argument should be true
+ if the object is a string. */
+extern void ggc_pch_count_object (struct ggc_pch_data *, void *, size_t, bool);
+
+/* Return the total size of the data to be written to hold all
+ the objects previously passed to ggc_pch_count_object. */
+extern size_t ggc_pch_total_size (struct ggc_pch_data *);
+
+/* The objects, when read, will most likely be at the address
+ in the second parameter. */
+extern void ggc_pch_this_base (struct ggc_pch_data *, void *);
+
+/* Assuming that the objects really do end up at the address
+ passed to ggc_pch_this_base, return the address of this object.
+ The bool argument should be true if the object is a string. */
+extern char *ggc_pch_alloc_object (struct ggc_pch_data *, void *, size_t, bool);
+
+/* Write out any initial information required. */
+extern void ggc_pch_prepare_write (struct ggc_pch_data *, FILE *);
+
+/* Write out this object, including any padding. The last argument should be
+ true if the object is a string. */
+extern void ggc_pch_write_object (struct ggc_pch_data *, FILE *, void *,
+ void *, size_t, bool);
+
+/* All objects have been written, write out any final information
+ required. */
+extern void ggc_pch_finish (struct ggc_pch_data *, FILE *);
+
+/* A PCH file has just been read in at the address specified second
+ parameter. Set up the GC implementation for the new objects. */
+extern void ggc_pch_read (FILE *, void *);
+
+
+/* Allocation and collection. */
+
+extern void ggc_record_overhead (size_t, size_t, void * FINAL_MEM_STAT_DECL);
+
+extern void ggc_free_overhead (void *);
+
+extern void ggc_prune_overhead_list (void);
+
+/* Return the number of bytes allocated at the indicated address. */
+extern size_t ggc_get_size (const void *);
+
+
+/* Statistics. */
+
+/* This structure contains the statistics common to all collectors.
+ Particular collectors can extend this structure. */
+struct ggc_statistics
+{
+ /* At present, we don't really gather any interesting statistics. */
+ int unused;
+};
+
+/* Used by the various collectors to gather and print statistics that
+ do not depend on the collector in use. */
+extern void ggc_print_common_statistics (FILE *, ggc_statistics *);
+
+#endif
diff --git a/support/cpp/gcc/ggc-none.cc b/support/cpp/gcc/ggc-none.cc
new file mode 100644
index 000000000..ea0598039
--- /dev/null
+++ b/support/cpp/gcc/ggc-none.cc
@@ -0,0 +1,81 @@
+/* Null garbage collection for the GNU compiler.
+ 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/>. */
+
+/* This version is used by the gen* programs and certain language-specific
+ targets (such as java), where we don't really need GC at all.
+ This prevents problems with pulling in all the tree stuff. */
+
+#ifdef GENERATOR_FILE
+#include "bconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include "system.h"
+#include "coretypes.h"
+#include "hash-table.h"
+#include <cassert>
+
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ return requested_size;
+}
+
+void *
+ggc_internal_alloc (size_t size, void (*f)(void *), size_t, size_t
+ MEM_STAT_DECL)
+{
+ assert(!f);
+ gcc_assert (!f); // ggc-none doesn't support finalizers
+ return xmalloc (size);
+}
+
+void *
+ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t, size_t
+ MEM_STAT_DECL)
+{
+ gcc_assert (!f); // ggc-none doesn't support finalizers
+ return xcalloc (size, 1);
+}
+
+void *
+ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
+{
+ return xrealloc (x, size);
+}
+
+void
+ggc_free (void *p)
+{
+ free (p);
+}
+
+void
+ggc_grow (void)
+{
+}
+
+void
+ggc_trim (void)
+{
+}
diff --git a/support/cpp/gcc/ggc-page.cc b/support/cpp/gcc/ggc-page.cc
new file mode 100644
index 000000000..b85597d81
--- /dev/null
+++ b/support/cpp/gcc/ggc-page.cc
@@ -0,0 +1,2694 @@
+/* "Bag-of-pages" garbage collector for the GNU compiler.
+ 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.
+
+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 "backend.h"
+#include "alias.h"
+#include "tree.h"
+#include "rtl.h"
+#include "memmodel.h"
+#include "function.h" // sdcpp
+// sdcpp #include "tm_p.h"
+#include "diagnostic-core.h"
+#include "flags.h"
+#include "ggc-internal.h"
+#include "timevar.h"
+#include "cgraph.h"
+#include "cfgloop.h"
+#include "plugin.h"
+
+/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
+ file open. Prefer either to valloc. */
+#ifdef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+# define USING_MMAP
+#endif
+
+#ifdef HAVE_MMAP_DEV_ZERO
+# define USING_MMAP
+#endif
+
+#ifndef USING_MMAP
+#define USING_MALLOC_PAGE_GROUPS
+#endif
+
+#if defined(HAVE_MADVISE) && HAVE_DECL_MADVISE && defined(MADV_DONTNEED) \
+ && defined(USING_MMAP)
+# define USING_MADVISE
+#endif
+
+/* Strategy:
+
+ This garbage-collecting allocator allocates objects on one of a set
+ of pages. Each page can allocate objects of a single size only;
+ available sizes are powers of two starting at four bytes. The size
+ of an allocation request is rounded up to the next power of two
+ (`order'), and satisfied from the appropriate page.
+
+ Each page is recorded in a page-entry, which also maintains an
+ in-use bitmap of object positions on the page. This allows the
+ allocation state of a particular object to be flipped without
+ touching the page itself.
+
+ Each page-entry also has a context depth, which is used to track
+ pushing and popping of allocation contexts. Only objects allocated
+ in the current (highest-numbered) context may be collected.
+
+ Page entries are arranged in an array of singly-linked lists. The
+ array is indexed by the allocation size, in bits, of the pages on
+ it; i.e. all pages on a list allocate objects of the same size.
+ Pages are ordered on the list such that all non-full pages precede
+ all full pages, with non-full pages arranged in order of decreasing
+ context depth.
+
+ Empty pages (of all orders) are kept on a single page cache list,
+ and are considered first when new pages are required; they are
+ deallocated at the start of the next collection if they haven't
+ been recycled by then. */
+
+/* Define GGC_DEBUG_LEVEL to print debugging information.
+ 0: No debugging output.
+ 1: GC statistics only.
+ 2: Page-entry allocations/deallocations as well.
+ 3: Object allocations as well.
+ 4: Object marks as well. */
+#define GGC_DEBUG_LEVEL (0)
+
+/* A two-level tree is used to look up the page-entry for a given
+ pointer. Two chunks of the pointer's bits are extracted to index
+ the first and second levels of the tree, as follows:
+
+ HOST_PAGE_SIZE_BITS
+ 32 | |
+ msb +----------------+----+------+------+ lsb
+ | | |
+ PAGE_L1_BITS |
+ | |
+ PAGE_L2_BITS
+
+ The bottommost HOST_PAGE_SIZE_BITS are ignored, since page-entry
+ pages are aligned on system page boundaries. The next most
+ significant PAGE_L2_BITS and PAGE_L1_BITS are the second and first
+ index values in the lookup table, respectively.
+
+ For 32-bit architectures and the settings below, there are no
+ leftover bits. For architectures with wider pointers, the lookup
+ tree points to a list of pages, which must be scanned to find the
+ correct one. */
+
+#define PAGE_L1_BITS (8)
+#define PAGE_L2_BITS (32 - PAGE_L1_BITS - G.lg_pagesize)
+#define PAGE_L1_SIZE ((uintptr_t) 1 << PAGE_L1_BITS)
+#define PAGE_L2_SIZE ((uintptr_t) 1 << PAGE_L2_BITS)
+
+#define LOOKUP_L1(p) \
+ (((uintptr_t) (p) >> (32 - PAGE_L1_BITS)) & ((1 << PAGE_L1_BITS) - 1))
+
+#define LOOKUP_L2(p) \
+ (((uintptr_t) (p) >> G.lg_pagesize) & ((1 << PAGE_L2_BITS) - 1))
+
+/* The number of objects per allocation page, for objects on a page of
+ the indicated ORDER. */
+#define OBJECTS_PER_PAGE(ORDER) objects_per_page_table[ORDER]
+
+/* The number of objects in P. */
+#define OBJECTS_IN_PAGE(P) ((P)->bytes / OBJECT_SIZE ((P)->order))
+
+/* The size of an object on a page of the indicated ORDER. */
+#define OBJECT_SIZE(ORDER) object_size_table[ORDER]
+
+/* For speed, we avoid doing a general integer divide to locate the
+ offset in the allocation bitmap, by precalculating numbers M, S
+ such that (O * M) >> S == O / Z (modulo 2^32), for any offset O
+ within the page which is evenly divisible by the object size Z. */
+#define DIV_MULT(ORDER) inverse_table[ORDER].mult
+#define DIV_SHIFT(ORDER) inverse_table[ORDER].shift
+#define OFFSET_TO_BIT(OFFSET, ORDER) \
+ (((OFFSET) * DIV_MULT (ORDER)) >> DIV_SHIFT (ORDER))
+
+/* We use this structure to determine the alignment required for
+ allocations. For power-of-two sized allocations, that's not a
+ problem, but it does matter for odd-sized allocations.
+ We do not care about alignment for floating-point types. */
+
+struct max_alignment {
+ char c;
+ union {
+ int64_t i;
+ void *p;
+ } u;
+};
+
+/* The biggest alignment required. */
+
+#define MAX_ALIGNMENT (offsetof (struct max_alignment, u))
+
+
+/* The number of extra orders, not corresponding to power-of-two sized
+ objects. */
+
+#define NUM_EXTRA_ORDERS ARRAY_SIZE (extra_order_size_table)
+
+#define RTL_SIZE(NSLOTS) \
+ (RTX_HDR_SIZE + (NSLOTS) * sizeof (rtunion))
+
+#define TREE_EXP_SIZE(OPS) \
+ (sizeof (struct tree_exp) + ((OPS) - 1) * sizeof (tree))
+
+/* The Ith entry is the maximum size of an object to be stored in the
+ Ith extra order. Adding a new entry to this array is the *only*
+ thing you need to do to add a new special allocation size. */
+
+static const size_t extra_order_size_table[] = {
+ /* Extra orders for small non-power-of-two multiples of MAX_ALIGNMENT.
+ There are a lot of structures with these sizes and explicitly
+ listing them risks orders being dropped because they changed size. */
+ MAX_ALIGNMENT * 3,
+ MAX_ALIGNMENT * 5,
+ MAX_ALIGNMENT * 6,
+ MAX_ALIGNMENT * 7,
+ MAX_ALIGNMENT * 9,
+ MAX_ALIGNMENT * 10,
+ MAX_ALIGNMENT * 11,
+ MAX_ALIGNMENT * 12,
+ MAX_ALIGNMENT * 13,
+ MAX_ALIGNMENT * 14,
+ MAX_ALIGNMENT * 15,
+#if 0 // sdcpp
+ sizeof (struct tree_decl_non_common),
+ sizeof (struct tree_field_decl),
+ sizeof (struct tree_parm_decl),
+ sizeof (struct tree_var_decl),
+ sizeof (struct tree_type_non_common),
+ sizeof (struct function),
+ sizeof (struct basic_block_def),
+ sizeof (struct cgraph_node),
+ sizeof (class loop),
+#endif // sdcpp
+};
+
+/* The total number of orders. */
+
+#define NUM_ORDERS (HOST_BITS_PER_PTR + NUM_EXTRA_ORDERS)
+
+/* Compute the smallest nonnegative number which when added to X gives
+ a multiple of F. */
+
+#define ROUND_UP_VALUE(x, f) ((f) - 1 - ((f) - 1 + (x)) % (f))
+
+/* Round X to next multiple of the page size */
+
+#define PAGE_ALIGN(x) ROUND_UP ((x), G.pagesize)
+
+/* The Ith entry is the number of objects on a page or order I. */
+
+static unsigned objects_per_page_table[NUM_ORDERS];
+
+/* The Ith entry is the size of an object on a page of order I. */
+
+static size_t object_size_table[NUM_ORDERS];
+
+/* The Ith entry is a pair of numbers (mult, shift) such that
+ ((k * mult) >> shift) mod 2^32 == (k / OBJECT_SIZE(I)) mod 2^32,
+ for all k evenly divisible by OBJECT_SIZE(I). */
+
+static struct
+{
+ size_t mult;
+ unsigned int shift;
+}
+inverse_table[NUM_ORDERS];
+
+/* A page_entry records the status of an allocation page. This
+ structure is dynamically sized to fit the bitmap in_use_p. */
+struct page_entry
+{
+ /* The next page-entry with objects of the same size, or NULL if
+ this is the last page-entry. */
+ struct page_entry *next;
+
+ /* The previous page-entry with objects of the same size, or NULL if
+ this is the first page-entry. The PREV pointer exists solely to
+ keep the cost of ggc_free manageable. */
+ struct page_entry *prev;
+
+ /* The number of bytes allocated. (This will always be a multiple
+ of the host system page size.) */
+ size_t bytes;
+
+ /* The address at which the memory is allocated. */
+ char *page;
+
+#ifdef USING_MALLOC_PAGE_GROUPS
+ /* Back pointer to the page group this page came from. */
+ struct page_group *group;
+#endif
+
+ /* This is the index in the by_depth varray where this page table
+ can be found. */
+ unsigned long index_by_depth;
+
+ /* Context depth of this page. */
+ unsigned short context_depth;
+
+ /* The number of free objects remaining on this page. */
+ unsigned short num_free_objects;
+
+ /* A likely candidate for the bit position of a free object for the
+ next allocation from this page. */
+ unsigned short next_bit_hint;
+
+ /* The lg of size of objects allocated from this page. */
+ unsigned char order;
+
+ /* Discarded page? */
+ bool discarded;
+
+ /* A bit vector indicating whether or not objects are in use. The
+ Nth bit is one if the Nth object on this page is allocated. This
+ array is dynamically sized. */
+ unsigned long in_use_p[1];
+};
+
+#ifdef USING_MALLOC_PAGE_GROUPS
+/* A page_group describes a large allocation from malloc, from which
+ we parcel out aligned pages. */
+struct page_group
+{
+ /* A linked list of all extant page groups. */
+ struct page_group *next;
+
+ /* The address we received from malloc. */
+ char *allocation;
+
+ /* The size of the block. */
+ size_t alloc_size;
+
+ /* A bitmask of pages in use. */
+ unsigned int in_use;
+};
+#endif
+
+#if HOST_BITS_PER_PTR <= 32
+
+/* On 32-bit hosts, we use a two level page table, as pictured above. */
+typedef page_entry **page_table[PAGE_L1_SIZE];
+
+#else
+
+/* On 64-bit hosts, we use the same two level page tables plus a linked
+ list that disambiguates the top 32-bits. There will almost always be
+ exactly one entry in the list. */
+typedef struct page_table_chain
+{
+ struct page_table_chain *next;
+ size_t high_bits;
+ page_entry **table[PAGE_L1_SIZE];
+} *page_table;
+
+#endif
+
+class finalizer
+{
+public:
+ finalizer (void *addr, void (*f)(void *)) : m_addr (addr), m_function (f) {}
+
+ void *addr () const { return m_addr; }
+
+ void call () const { m_function (m_addr); }
+
+private:
+ void *m_addr;
+ void (*m_function)(void *);
+};
+
+class vec_finalizer
+{
+public:
+ vec_finalizer (uintptr_t addr, void (*f)(void *), size_t s, size_t n) :
+ m_addr (addr), m_function (f), m_object_size (s), m_n_objects (n) {}
+
+ void call () const
+ {
+ for (size_t i = 0; i < m_n_objects; i++)
+ m_function (reinterpret_cast<void *> (m_addr + (i * m_object_size)));
+ }
+
+ void *addr () const { return reinterpret_cast<void *> (m_addr); }
+
+private:
+ uintptr_t m_addr;
+ void (*m_function)(void *);
+ size_t m_object_size;
+ size_t m_n_objects;
+};
+
+#ifdef ENABLE_GC_ALWAYS_COLLECT
+/* List of free objects to be verified as actually free on the
+ next collection. */
+struct free_object
+{
+ void *object;
+ struct free_object *next;
+};
+#endif
+
+/* The rest of the global variables. */
+static struct ggc_globals
+{
+ /* The Nth element in this array is a page with objects of size 2^N.
+ If there are any pages with free objects, they will be at the
+ head of the list. NULL if there are no page-entries for this
+ object size. */
+ page_entry *pages[NUM_ORDERS];
+
+ /* The Nth element in this array is the last page with objects of
+ size 2^N. NULL if there are no page-entries for this object
+ size. */
+ page_entry *page_tails[NUM_ORDERS];
+
+ /* Lookup table for associating allocation pages with object addresses. */
+ page_table lookup;
+
+ /* The system's page size. */
+ size_t pagesize;
+ size_t lg_pagesize;
+
+ /* Bytes currently allocated. */
+ size_t allocated;
+
+ /* Bytes currently allocated at the end of the last collection. */
+ size_t allocated_last_gc;
+
+ /* Total amount of memory mapped. */
+ size_t bytes_mapped;
+
+ /* Bit N set if any allocations have been done at context depth N. */
+ unsigned long context_depth_allocations;
+
+ /* Bit N set if any collections have been done at context depth N. */
+ unsigned long context_depth_collections;
+
+ /* The current depth in the context stack. */
+ unsigned short context_depth;
+
+ /* A file descriptor open to /dev/zero for reading. */
+#if defined (HAVE_MMAP_DEV_ZERO)
+ int dev_zero_fd;
+#endif
+
+ /* A cache of free system pages. */
+ page_entry *free_pages;
+
+#ifdef USING_MALLOC_PAGE_GROUPS
+ page_group *page_groups;
+#endif
+
+ /* The file descriptor for debugging output. */
+ FILE *debug_file;
+
+ /* Current number of elements in use in depth below. */
+ unsigned int depth_in_use;
+
+ /* Maximum number of elements that can be used before resizing. */
+ unsigned int depth_max;
+
+ /* Each element of this array is an index in by_depth where the given
+ depth starts. This structure is indexed by that given depth we
+ are interested in. */
+ unsigned int *depth;
+
+ /* Current number of elements in use in by_depth below. */
+ unsigned int by_depth_in_use;
+
+ /* Maximum number of elements that can be used before resizing. */
+ unsigned int by_depth_max;
+
+ /* Each element of this array is a pointer to a page_entry, all
+ page_entries can be found in here by increasing depth.
+ index_by_depth in the page_entry is the index into this data
+ structure where that page_entry can be found. This is used to
+ speed up finding all page_entries at a particular depth. */
+ page_entry **by_depth;
+
+ /* Each element is a pointer to the saved in_use_p bits, if any,
+ zero otherwise. We allocate them all together, to enable a
+ better runtime data access pattern. */
+ unsigned long **save_in_use;
+
+ /* Finalizers for single objects. The first index is collection_depth. */
+ vec<vec<finalizer> > finalizers;
+
+ /* Finalizers for vectors of objects. */
+ vec<vec<vec_finalizer> > vec_finalizers;
+
+#ifdef ENABLE_GC_ALWAYS_COLLECT
+ /* List of free objects to be verified as actually free on the
+ next collection. */
+ struct free_object *free_object_list;
+#endif
+
+ struct
+ {
+ /* Total GC-allocated memory. */
+ unsigned long long total_allocated;
+ /* Total overhead for GC-allocated memory. */
+ unsigned long long total_overhead;
+
+ /* Total allocations and overhead for sizes less than 32, 64 and 128.
+ These sizes are interesting because they are typical cache line
+ sizes. */
+
+ unsigned long long total_allocated_under32;
+ unsigned long long total_overhead_under32;
+
+ unsigned long long total_allocated_under64;
+ unsigned long long total_overhead_under64;
+
+ unsigned long long total_allocated_under128;
+ unsigned long long total_overhead_under128;
+
+ /* The allocations for each of the allocation orders. */
+ unsigned long long total_allocated_per_order[NUM_ORDERS];
+
+ /* The overhead for each of the allocation orders. */
+ unsigned long long total_overhead_per_order[NUM_ORDERS];
+ } stats;
+} G;
+
+/* True if a gc is currently taking place. */
+
+static bool in_gc = false;
+
+/* The size in bytes required to maintain a bitmap for the objects
+ on a page-entry. */
+#define BITMAP_SIZE(Num_objects) \
+ (CEIL ((Num_objects), HOST_BITS_PER_LONG) * sizeof (long))
+
+/* Allocate pages in chunks of this size, to throttle calls to memory
+ allocation routines. The first page is used, the rest go onto the
+ free list. This cannot be larger than HOST_BITS_PER_INT for the
+ in_use bitmask for page_group. Hosts that need a different value
+ can override this by defining GGC_QUIRE_SIZE explicitly. */
+#ifndef GGC_QUIRE_SIZE
+# ifdef USING_MMAP
+# define GGC_QUIRE_SIZE 512 /* 2MB for 4K pages */
+# else
+# define GGC_QUIRE_SIZE 16
+# endif
+#endif
+
+/* Initial guess as to how many page table entries we might need. */
+#define INITIAL_PTE_COUNT 128
+
+static page_entry *lookup_page_table_entry (const void *);
+static void set_page_table_entry (void *, page_entry *);
+#ifdef USING_MMAP
+static char *alloc_anon (char *, size_t, bool check);
+#endif
+#ifdef USING_MALLOC_PAGE_GROUPS
+static size_t page_group_index (char *, char *);
+static void set_page_group_in_use (page_group *, char *);
+static void clear_page_group_in_use (page_group *, char *);
+#endif
+static struct page_entry * alloc_page (unsigned);
+static void free_page (struct page_entry *);
+static void clear_marks (void);
+static void sweep_pages (void);
+static void ggc_recalculate_in_use_p (page_entry *);
+static void compute_inverse (unsigned);
+static inline void adjust_depth (void);
+static void move_ptes_to_front (int, int);
+
+void debug_print_page_list (int);
+static void push_depth (unsigned int);
+static void push_by_depth (page_entry *, unsigned long *);
+
+/* Push an entry onto G.depth. */
+
+inline static void
+push_depth (unsigned int i)
+{
+ if (G.depth_in_use >= G.depth_max)
+ {
+ G.depth_max *= 2;
+ G.depth = XRESIZEVEC (unsigned int, G.depth, G.depth_max);
+ }
+ G.depth[G.depth_in_use++] = i;
+}
+
+/* Push an entry onto G.by_depth and G.save_in_use. */
+
+inline static void
+push_by_depth (page_entry *p, unsigned long *s)
+{
+ if (G.by_depth_in_use >= G.by_depth_max)
+ {
+ G.by_depth_max *= 2;
+ G.by_depth = XRESIZEVEC (page_entry *, G.by_depth, G.by_depth_max);
+ G.save_in_use = XRESIZEVEC (unsigned long *, G.save_in_use,
+ G.by_depth_max);
+ }
+ G.by_depth[G.by_depth_in_use] = p;
+ G.save_in_use[G.by_depth_in_use++] = s;
+}
+
+#if (GCC_VERSION < 3001)
+#define prefetch(X) ((void) X)
+#else
+#define prefetch(X) __builtin_prefetch (X)
+#endif
+
+#define save_in_use_p_i(__i) \
+ (G.save_in_use[__i])
+#define save_in_use_p(__p) \
+ (save_in_use_p_i (__p->index_by_depth))
+
+/* Traverse the page table and find the entry for a page.
+ If the object wasn't allocated in GC return NULL. */
+
+static inline page_entry *
+safe_lookup_page_table_entry (const void *p)
+{
+ page_entry ***base;
+ size_t L1, L2;
+
+#if HOST_BITS_PER_PTR <= 32
+ base = &G.lookup[0];
+#else
+ page_table table = G.lookup;
+ uintptr_t high_bits = (uintptr_t) p & ~ (uintptr_t) 0xffffffff;
+ while (1)
+ {
+ if (table == NULL)
+ return NULL;
+ if (table->high_bits == high_bits)
+ break;
+ table = table->next;
+ }
+ base = &table->table[0];
+#endif
+
+ /* Extract the level 1 and 2 indices. */
+ L1 = LOOKUP_L1 (p);
+ L2 = LOOKUP_L2 (p);
+ if (! base[L1])
+ return NULL;
+
+ return base[L1][L2];
+}
+
+/* Traverse the page table and find the entry for a page.
+ Die (probably) if the object wasn't allocated via GC. */
+
+static inline page_entry *
+lookup_page_table_entry (const void *p)
+{
+ page_entry ***base;
+ size_t L1, L2;
+
+#if HOST_BITS_PER_PTR <= 32
+ base = &G.lookup[0];
+#else
+ page_table table = G.lookup;
+ uintptr_t high_bits = (uintptr_t) p & ~ (uintptr_t) 0xffffffff;
+ while (table->high_bits != high_bits)
+ table = table->next;
+ base = &table->table[0];
+#endif
+
+ /* Extract the level 1 and 2 indices. */
+ L1 = LOOKUP_L1 (p);
+ L2 = LOOKUP_L2 (p);
+
+ return base[L1][L2];
+}
+
+/* Set the page table entry for a page. */
+
+static void
+set_page_table_entry (void *p, page_entry *entry)
+{
+ page_entry ***base;
+ size_t L1, L2;
+
+#if HOST_BITS_PER_PTR <= 32
+ base = &G.lookup[0];
+#else
+ page_table table;
+ uintptr_t high_bits = (uintptr_t) p & ~ (uintptr_t) 0xffffffff;
+ for (table = G.lookup; table; table = table->next)
+ if (table->high_bits == high_bits)
+ goto found;
+
+ /* Not found -- allocate a new table. */
+ table = XCNEW (struct page_table_chain);
+ table->next = G.lookup;
+ table->high_bits = high_bits;
+ G.lookup = table;
+found:
+ base = &table->table[0];
+#endif
+
+ /* Extract the level 1 and 2 indices. */
+ L1 = LOOKUP_L1 (p);
+ L2 = LOOKUP_L2 (p);
+
+ if (base[L1] == NULL)
+ base[L1] = XCNEWVEC (page_entry *, PAGE_L2_SIZE);
+
+ base[L1][L2] = entry;
+}
+
+/* Prints the page-entry for object size ORDER, for debugging. */
+
+DEBUG_FUNCTION void
+debug_print_page_list (int order)
+{
+ page_entry *p;
+ printf ("Head=%p, Tail=%p:\n", (void *) G.pages[order],
+ (void *) G.page_tails[order]);
+ p = G.pages[order];
+ while (p != NULL)
+ {
+ printf ("%p(%1d|%3d) -> ", (void *) p, p->context_depth,
+ p->num_free_objects);
+ p = p->next;
+ }
+ printf ("NULL\n");
+ fflush (stdout);
+}
+
+#ifdef USING_MMAP
+/* Allocate SIZE bytes of anonymous memory, preferably near PREF,
+ (if non-null). The ifdef structure here is intended to cause a
+ compile error unless exactly one of the HAVE_* is defined. */
+
+static inline char *
+alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size, bool check)
+{
+#ifdef HAVE_MMAP_ANON
+ char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
+#ifdef HAVE_MMAP_DEV_ZERO
+ char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, G.dev_zero_fd, 0);
+#endif
+
+ if (page == (char *) MAP_FAILED)
+ {
+ if (!check)
+ return NULL;
+ perror ("virtual memory exhausted");
+ exit (FATAL_EXIT_CODE);
+ }
+
+ /* Remember that we allocated this memory. */
+ G.bytes_mapped += size;
+
+ /* Pretend we don't have access to the allocated pages. We'll enable
+ access to smaller pieces of the area in ggc_internal_alloc. Discard the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (page, size));
+
+ return page;
+}
+#endif
+#ifdef USING_MALLOC_PAGE_GROUPS
+/* Compute the index for this page into the page group. */
+
+static inline size_t
+page_group_index (char *allocation, char *page)
+{
+ return (size_t) (page - allocation) >> G.lg_pagesize;
+}
+
+/* Set and clear the in_use bit for this page in the page group. */
+
+static inline void
+set_page_group_in_use (page_group *group, char *page)
+{
+ group->in_use |= 1 << page_group_index (group->allocation, page);
+}
+
+static inline void
+clear_page_group_in_use (page_group *group, char *page)
+{
+ group->in_use &= ~(1 << page_group_index (group->allocation, page));
+}
+#endif
+
+/* Allocate a new page for allocating objects of size 2^ORDER,
+ and return an entry for it. The entry is not added to the
+ appropriate page_table list. */
+
+static inline struct page_entry *
+alloc_page (unsigned order)
+{
+ struct page_entry *entry, *p, **pp;
+ char *page;
+ size_t num_objects;
+ size_t bitmap_size;
+ size_t page_entry_size;
+ size_t entry_size;
+#ifdef USING_MALLOC_PAGE_GROUPS
+ page_group *group;
+#endif
+
+ num_objects = OBJECTS_PER_PAGE (order);
+ bitmap_size = BITMAP_SIZE (num_objects + 1);
+ page_entry_size = sizeof (page_entry) - sizeof (long) + bitmap_size;
+ entry_size = num_objects * OBJECT_SIZE (order);
+ if (entry_size < G.pagesize)
+ entry_size = G.pagesize;
+ entry_size = PAGE_ALIGN (entry_size);
+
+ entry = NULL;
+ page = NULL;
+
+ /* Check the list of free pages for one we can use. */
+ for (pp = &G.free_pages, p = *pp; p; pp = &p->next, p = *pp)
+ if (p->bytes == entry_size)
+ break;
+
+ if (p != NULL)
+ {
+ if (p->discarded)
+ G.bytes_mapped += p->bytes;
+ p->discarded = false;
+
+ /* Recycle the allocated memory from this page ... */
+ *pp = p->next;
+ page = p->page;
+
+#ifdef USING_MALLOC_PAGE_GROUPS
+ group = p->group;
+#endif
+
+ /* ... and, if possible, the page entry itself. */
+ if (p->order == order)
+ {
+ entry = p;
+ memset (entry, 0, page_entry_size);
+ }
+ else
+ free (p);
+ }
+#ifdef USING_MMAP
+ else if (entry_size == G.pagesize)
+ {
+ /* We want just one page. Allocate a bunch of them and put the
+ extras on the freelist. (Can only do this optimization with
+ mmap for backing store.) */
+ struct page_entry *e, *f = G.free_pages;
+ int i, entries = GGC_QUIRE_SIZE;
+
+ page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE, false);
+ if (page == NULL)
+ {
+ page = alloc_anon (NULL, G.pagesize, true);
+ entries = 1;
+ }
+
+ /* This loop counts down so that the chain will be in ascending
+ memory order. */
+ for (i = entries - 1; i >= 1; i--)
+ {
+ e = XCNEWVAR (struct page_entry, page_entry_size);
+ e->order = order;
+ e->bytes = G.pagesize;
+ e->page = page + (i << G.lg_pagesize);
+ e->next = f;
+ f = e;
+ }
+
+ G.free_pages = f;
+ }
+ else
+ page = alloc_anon (NULL, entry_size, true);
+#endif
+#ifdef USING_MALLOC_PAGE_GROUPS
+ else
+ {
+ /* Allocate a large block of memory and serve out the aligned
+ pages therein. This results in much less memory wastage
+ than the traditional implementation of valloc. */
+
+ char *allocation, *a, *enda;
+ size_t alloc_size, head_slop, tail_slop;
+ int multiple_pages = (entry_size == G.pagesize);
+
+ if (multiple_pages)
+ alloc_size = GGC_QUIRE_SIZE * G.pagesize;
+ else
+ alloc_size = entry_size + G.pagesize - 1;
+ allocation = XNEWVEC (char, alloc_size);
+
+ page = (char *) (((uintptr_t) allocation + G.pagesize - 1) & -G.pagesize);
+ head_slop = page - allocation;
+ if (multiple_pages)
+ tail_slop = ((size_t) allocation + alloc_size) & (G.pagesize - 1);
+ else
+ tail_slop = alloc_size - entry_size - head_slop;
+ enda = allocation + alloc_size - tail_slop;
+
+ /* We allocated N pages, which are likely not aligned, leaving
+ us with N-1 usable pages. We plan to place the page_group
+ structure somewhere in the slop. */
+ if (head_slop >= sizeof (page_group))
+ group = (page_group *)page - 1;
+ else
+ {
+ /* We magically got an aligned allocation. Too bad, we have
+ to waste a page anyway. */
+ if (tail_slop == 0)
+ {
+ enda -= G.pagesize;
+ tail_slop += G.pagesize;
+ }
+ gcc_assert (tail_slop >= sizeof (page_group));
+ group = (page_group *)enda;
+ tail_slop -= sizeof (page_group);
+ }
+
+ /* Remember that we allocated this memory. */
+ group->next = G.page_groups;
+ group->allocation = allocation;
+ group->alloc_size = alloc_size;
+ group->in_use = 0;
+ G.page_groups = group;
+ G.bytes_mapped += alloc_size;
+
+ /* If we allocated multiple pages, put the rest on the free list. */
+ if (multiple_pages)
+ {
+ struct page_entry *e, *f = G.free_pages;
+ for (a = enda - G.pagesize; a != page; a -= G.pagesize)
+ {
+ e = XCNEWVAR (struct page_entry, page_entry_size);
+ e->order = order;
+ e->bytes = G.pagesize;
+ e->page = a;
+ e->group = group;
+ e->next = f;
+ f = e;
+ }
+ G.free_pages = f;
+ }
+ }
+#endif
+
+ if (entry == NULL)
+ entry = XCNEWVAR (struct page_entry, page_entry_size);
+
+ entry->bytes = entry_size;
+ entry->page = page;
+ entry->context_depth = G.context_depth;
+ entry->order = order;
+ entry->num_free_objects = num_objects;
+ entry->next_bit_hint = 1;
+
+ G.context_depth_allocations |= (unsigned long)1 << G.context_depth;
+
+#ifdef USING_MALLOC_PAGE_GROUPS
+ entry->group = group;
+ set_page_group_in_use (group, page);
+#endif
+
+ /* Set the one-past-the-end in-use bit. This acts as a sentry as we
+ increment the hint. */
+ entry->in_use_p[num_objects / HOST_BITS_PER_LONG]
+ = (unsigned long) 1 << (num_objects % HOST_BITS_PER_LONG);
+
+ set_page_table_entry (page, entry);
+
+ if (GGC_DEBUG_LEVEL >= 2)
+ fprintf (G.debug_file,
+ "Allocating page at %p, object size=%lu, data %p-%p\n",
+ (void *) entry, (unsigned long) OBJECT_SIZE (order),
+ (void *) page, (void *) (page + entry_size - 1));
+
+ return entry;
+}
+
+/* Adjust the size of G.depth so that no index greater than the one
+ used by the top of the G.by_depth is used. */
+
+static inline void
+adjust_depth (void)
+{
+ page_entry *top;
+
+ if (G.by_depth_in_use)
+ {
+ top = G.by_depth[G.by_depth_in_use-1];
+
+ /* Peel back indices in depth that index into by_depth, so that
+ as new elements are added to by_depth, we note the indices
+ of those elements, if they are for new context depths. */
+ while (G.depth_in_use > (size_t)top->context_depth+1)
+ --G.depth_in_use;
+ }
+}
+
+/* For a page that is no longer needed, put it on the free page list. */
+
+static void
+free_page (page_entry *entry)
+{
+ if (GGC_DEBUG_LEVEL >= 2)
+ fprintf (G.debug_file,
+ "Deallocating page at %p, data %p-%p\n", (void *) entry,
+ (void *) entry->page, (void *) (entry->page + entry->bytes - 1));
+
+ /* Mark the page as inaccessible. Discard the handle to avoid handle
+ leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (entry->page, entry->bytes));
+
+ set_page_table_entry (entry->page, NULL);
+
+#ifdef USING_MALLOC_PAGE_GROUPS
+ clear_page_group_in_use (entry->group, entry->page);
+#endif
+
+ if (G.by_depth_in_use > 1)
+ {
+ page_entry *top = G.by_depth[G.by_depth_in_use-1];
+ int i = entry->index_by_depth;
+
+ /* We cannot free a page from a context deeper than the current
+ one. */
+ gcc_assert (entry->context_depth == top->context_depth);
+
+ /* Put top element into freed slot. */
+ G.by_depth[i] = top;
+ G.save_in_use[i] = G.save_in_use[G.by_depth_in_use-1];
+ top->index_by_depth = i;
+ }
+ --G.by_depth_in_use;
+
+ adjust_depth ();
+
+ entry->next = G.free_pages;
+ G.free_pages = entry;
+}
+
+/* Release the free page cache to the system. */
+
+static void
+release_pages (void)
+{
+ size_t n1 = 0;
+ size_t n2 = 0;
+#ifdef USING_MADVISE
+ page_entry *p, *start_p;
+ char *start;
+ size_t len;
+ size_t mapped_len;
+ page_entry *next, *prev, *newprev;
+ size_t free_unit = (GGC_QUIRE_SIZE/2) * G.pagesize;
+
+ /* First free larger continuous areas to the OS.
+ This allows other allocators to grab these areas if needed.
+ This is only done on larger chunks to avoid fragmentation.
+ This does not always work because the free_pages list is only
+ approximately sorted. */
+
+ p = G.free_pages;
+ prev = NULL;
+ while (p)
+ {
+ start = p->page;
+ start_p = p;
+ len = 0;
+ mapped_len = 0;
+ newprev = prev;
+ while (p && p->page == start + len)
+ {
+ len += p->bytes;
+ if (!p->discarded)
+ mapped_len += p->bytes;
+ newprev = p;
+ p = p->next;
+ }
+ if (len >= free_unit)
+ {
+ while (start_p != p)
+ {
+ next = start_p->next;
+ free (start_p);
+ start_p = next;
+ }
+ munmap (start, len);
+ if (prev)
+ prev->next = p;
+ else
+ G.free_pages = p;
+ G.bytes_mapped -= mapped_len;
+ n1 += len;
+ continue;
+ }
+ prev = newprev;
+ }
+
+ /* Now give back the fragmented pages to the OS, but keep the address
+ space to reuse it next time. */
+
+ for (p = G.free_pages; p; )
+ {
+ if (p->discarded)
+ {
+ p = p->next;
+ continue;
+ }
+ start = p->page;
+ len = p->bytes;
+ start_p = p;
+ p = p->next;
+ while (p && p->page == start + len)
+ {
+ len += p->bytes;
+ p = p->next;
+ }
+ /* Give the page back to the kernel, but don't free the mapping.
+ This avoids fragmentation in the virtual memory map of the
+ process. Next time we can reuse it by just touching it. */
+ madvise (start, len, MADV_DONTNEED);
+ /* Don't count those pages as mapped to not touch the garbage collector
+ unnecessarily. */
+ G.bytes_mapped -= len;
+ n2 += len;
+ while (start_p != p)
+ {
+ start_p->discarded = true;
+ start_p = start_p->next;
+ }
+ }
+#endif
+#if defined(USING_MMAP) && !defined(USING_MADVISE)
+ page_entry *p, *next;
+ char *start;
+ size_t len;
+
+ /* Gather up adjacent pages so they are unmapped together. */
+ p = G.free_pages;
+
+ while (p)
+ {
+ start = p->page;
+ next = p->next;
+ len = p->bytes;
+ free (p);
+ p = next;
+
+ while (p && p->page == start + len)
+ {
+ next = p->next;
+ len += p->bytes;
+ free (p);
+ p = next;
+ }
+
+ munmap (start, len);
+ n1 += len;
+ G.bytes_mapped -= len;
+ }
+
+ G.free_pages = NULL;
+#endif
+#ifdef USING_MALLOC_PAGE_GROUPS
+ page_entry **pp, *p;
+ page_group **gp, *g;
+
+ /* Remove all pages from free page groups from the list. */
+ pp = &G.free_pages;
+ while ((p = *pp) != NULL)
+ if (p->group->in_use == 0)
+ {
+ *pp = p->next;
+ free (p);
+ }
+ else
+ pp = &p->next;
+
+ /* Remove all free page groups, and release the storage. */
+ gp = &G.page_groups;
+ while ((g = *gp) != NULL)
+ if (g->in_use == 0)
+ {
+ *gp = g->next;
+ G.bytes_mapped -= g->alloc_size;
+ n1 += g->alloc_size;
+ free (g->allocation);
+ }
+ else
+ gp = &g->next;
+#endif
+ if (!quiet_flag && (n1 || n2))
+ {
+ fprintf (stderr, " {GC");
+ if (n1)
+ fprintf (stderr, " released " PRsa (0), SIZE_AMOUNT (n1));
+ if (n2)
+ fprintf (stderr, " madv_dontneed " PRsa (0), SIZE_AMOUNT (n2));
+ fprintf (stderr, "}");
+ }
+}
+
+/* This table provides a fast way to determine ceil(log_2(size)) for
+ allocation requests. The minimum allocation size is eight bytes. */
+#define NUM_SIZE_LOOKUP 512
+static unsigned char size_lookup[NUM_SIZE_LOOKUP] =
+{
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
+ 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
+};
+
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated, as well as the size
+ order. */
+
+static void
+ggc_round_alloc_size_1 (size_t requested_size,
+ size_t *size_order,
+ size_t *alloced_size)
+{
+ size_t order, object_size;
+
+ if (requested_size < NUM_SIZE_LOOKUP)
+ {
+ order = size_lookup[requested_size];
+ object_size = OBJECT_SIZE (order);
+ }
+ else
+ {
+ order = 10;
+ while (requested_size > (object_size = OBJECT_SIZE (order)))
+ order++;
+ }
+
+ if (size_order)
+ *size_order = order;
+ if (alloced_size)
+ *alloced_size = object_size;
+}
+
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size = 0;
+
+ ggc_round_alloc_size_1 (requested_size, NULL, &size);
+ return size;
+}
+
+/* Push a finalizer onto the appropriate vec. */
+
+static void
+add_finalizer (void *result, void (*f)(void *), size_t s, size_t n)
+{
+ if (f == NULL)
+ /* No finalizer. */;
+ else if (n == 1)
+ {
+ finalizer fin (result, f);
+ G.finalizers[G.context_depth].safe_push (fin);
+ }
+ else
+ {
+ vec_finalizer fin (reinterpret_cast<uintptr_t> (result), f, s, n);
+ G.vec_finalizers[G.context_depth].safe_push (fin);
+ }
+}
+
+/* Allocate a chunk of memory of SIZE bytes. Its contents are undefined. */
+
+void *
+ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
+ MEM_STAT_DECL)
+{
+ size_t order, word, bit, object_offset, object_size;
+ struct page_entry *entry;
+ void *result;
+
+ ggc_round_alloc_size_1 (size, &order, &object_size);
+
+ /* If there are non-full pages for this size allocation, they are at
+ the head of the list. */
+ entry = G.pages[order];
+
+ /* If there is no page for this object size, or all pages in this
+ context are full, allocate a new page. */
+ if (entry == NULL || entry->num_free_objects == 0)
+ {
+ struct page_entry *new_entry;
+ new_entry = alloc_page (order);
+
+ new_entry->index_by_depth = G.by_depth_in_use;
+ push_by_depth (new_entry, 0);
+
+ /* We can skip context depths, if we do, make sure we go all the
+ way to the new depth. */
+ while (new_entry->context_depth >= G.depth_in_use)
+ push_depth (G.by_depth_in_use-1);
+
+ /* If this is the only entry, it's also the tail. If it is not
+ the only entry, then we must update the PREV pointer of the
+ ENTRY (G.pages[order]) to point to our new page entry. */
+ if (entry == NULL)
+ G.page_tails[order] = new_entry;
+ else
+ entry->prev = new_entry;
+
+ /* Put new pages at the head of the page list. By definition the
+ entry at the head of the list always has a NULL pointer. */
+ new_entry->next = entry;
+ new_entry->prev = NULL;
+ entry = new_entry;
+ G.pages[order] = new_entry;
+
+ /* For a new page, we know the word and bit positions (in the
+ in_use bitmap) of the first available object -- they're zero. */
+ new_entry->next_bit_hint = 1;
+ word = 0;
+ bit = 0;
+ object_offset = 0;
+ }
+ else
+ {
+ /* First try to use the hint left from the previous allocation
+ to locate a clear bit in the in-use bitmap. We've made sure
+ that the one-past-the-end bit is always set, so if the hint
+ has run over, this test will fail. */
+ unsigned hint = entry->next_bit_hint;
+ word = hint / HOST_BITS_PER_LONG;
+ bit = hint % HOST_BITS_PER_LONG;
+
+ /* If the hint didn't work, scan the bitmap from the beginning. */
+ if ((entry->in_use_p[word] >> bit) & 1)
+ {
+ word = bit = 0;
+ while (~entry->in_use_p[word] == 0)
+ ++word;
+
+#if GCC_VERSION >= 3004
+ bit = __builtin_ctzl (~entry->in_use_p[word]);
+#else
+ while ((entry->in_use_p[word] >> bit) & 1)
+ ++bit;
+#endif
+
+ hint = word * HOST_BITS_PER_LONG + bit;
+ }
+
+ /* Next time, try the next bit. */
+ entry->next_bit_hint = hint + 1;
+
+ object_offset = hint * object_size;
+ }
+
+ /* Set the in-use bit. */
+ entry->in_use_p[word] |= ((unsigned long) 1 << bit);
+
+ /* Keep a running total of the number of free objects. If this page
+ fills up, we may have to move it to the end of the list if the
+ next page isn't full. If the next page is full, all subsequent
+ pages are full, so there's no need to move it. */
+ if (--entry->num_free_objects == 0
+ && entry->next != NULL
+ && entry->next->num_free_objects > 0)
+ {
+ /* We have a new head for the list. */
+ G.pages[order] = entry->next;
+
+ /* We are moving ENTRY to the end of the page table list.
+ The new page at the head of the list will have NULL in
+ its PREV field and ENTRY will have NULL in its NEXT field. */
+ entry->next->prev = NULL;
+ entry->next = NULL;
+
+ /* Append ENTRY to the tail of the list. */
+ entry->prev = G.page_tails[order];
+ G.page_tails[order]->next = entry;
+ G.page_tails[order] = entry;
+ }
+
+ /* Calculate the object's address. */
+ result = entry->page + object_offset;
+ if (GATHER_STATISTICS)
+ ggc_record_overhead (OBJECT_SIZE (order), OBJECT_SIZE (order) - size,
+ result FINAL_PASS_MEM_STAT);
+
+#ifdef ENABLE_GC_CHECKING
+ /* Keep poisoning-by-writing-0xaf the object, in an attempt to keep the
+ exact same semantics in presence of memory bugs, regardless of
+ ENABLE_VALGRIND_CHECKING. We override this request below. Drop the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (result, object_size));
+
+ /* `Poison' the entire allocated object, including any padding at
+ the end. */
+ memset (result, 0xaf, object_size);
+
+ /* Make the bytes after the end of the object unaccessible. Discard the
+ handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *) result + size,
+ object_size - size));
+#endif
+
+ /* Tell Valgrind that the memory is there, but its content isn't
+ defined. The bytes at the end of the object are still marked
+ unaccessible. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (result, size));
+
+ /* Keep track of how many bytes are being allocated. This
+ information is used in deciding when to collect. */
+ G.allocated += object_size;
+
+ /* For timevar statistics. */
+ timevar_ggc_mem_total += object_size;
+
+ if (f)
+ add_finalizer (result, f, s, n);
+
+ if (GATHER_STATISTICS)
+ {
+ size_t overhead = object_size - size;
+
+ G.stats.total_overhead += overhead;
+ G.stats.total_allocated += object_size;
+ G.stats.total_overhead_per_order[order] += overhead;
+ G.stats.total_allocated_per_order[order] += object_size;
+
+ if (size <= 32)
+ {
+ G.stats.total_overhead_under32 += overhead;
+ G.stats.total_allocated_under32 += object_size;
+ }
+ if (size <= 64)
+ {
+ G.stats.total_overhead_under64 += overhead;
+ G.stats.total_allocated_under64 += object_size;
+ }
+ if (size <= 128)
+ {
+ G.stats.total_overhead_under128 += overhead;
+ G.stats.total_allocated_under128 += object_size;
+ }
+ }
+
+ if (GGC_DEBUG_LEVEL >= 3)
+ fprintf (G.debug_file,
+ "Allocating object, requested size=%lu, actual=%lu at %p on %p\n",
+ (unsigned long) size, (unsigned long) object_size, result,
+ (void *) entry);
+
+ return result;
+}
+
+/* Mark function for strings. */
+
+#if 0 // sdcpp
+void
+gt_ggc_m_S (const void *p)
+{
+ page_entry *entry;
+ unsigned bit, word;
+ unsigned long mask;
+ unsigned long offset;
+
+ if (!p)
+ return;
+
+ /* Look up the page on which the object is alloced. If it was not
+ GC allocated, gracefully bail out. */
+ entry = safe_lookup_page_table_entry (p);
+ if (!entry)
+ return;
+
+ /* Calculate the index of the object on the page; this is its bit
+ position in the in_use_p bitmap. Note that because a char* might
+ point to the middle of an object, we need special code here to
+ make sure P points to the start of an object. */
+ offset = ((const char *) p - entry->page) % object_size_table[entry->order];
+ if (offset)
+ {
+ /* Here we've seen a char* which does not point to the beginning
+ of an allocated object. We assume it points to the middle of
+ a STRING_CST. */
+ gcc_assert (offset == offsetof (struct tree_string, str));
+ p = ((const char *) p) - offset;
+ gt_ggc_mx_lang_tree_node (CONST_CAST (void *, p));
+ return;
+ }
+
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
+ word = bit / HOST_BITS_PER_LONG;
+ mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
+
+ /* If the bit was previously set, skip it. */
+ if (entry->in_use_p[word] & mask)
+ return;
+
+ /* Otherwise set it, and decrement the free object count. */
+ entry->in_use_p[word] |= mask;
+ entry->num_free_objects -= 1;
+
+ if (GGC_DEBUG_LEVEL >= 4)
+ fprintf (G.debug_file, "Marking %p\n", p);
+
+ return;
+}
+#endif // sdcpp
+
+
+/* User-callable entry points for marking string X. */
+
+void
+gt_ggc_mx (const char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (unsigned char *& x)
+{
+ gt_ggc_m_S (x);
+}
+
+void
+gt_ggc_mx (unsigned char& x ATTRIBUTE_UNUSED)
+{
+}
+
+/* If P is not marked, marks it and return false. Otherwise return true.
+ P must have been allocated by the GC allocator; it mustn't point to
+ static objects, stack variables, or memory allocated with malloc. */
+
+int
+ggc_set_mark (const void *p)
+{
+ page_entry *entry;
+ unsigned bit, word;
+ unsigned long mask;
+
+ /* Look up the page on which the object is alloced. If the object
+ wasn't allocated by the collector, we'll probably die. */
+ entry = lookup_page_table_entry (p);
+ gcc_assert (entry);
+
+ /* Calculate the index of the object on the page; this is its bit
+ position in the in_use_p bitmap. */
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
+ word = bit / HOST_BITS_PER_LONG;
+ mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
+
+ /* If the bit was previously set, skip it. */
+ if (entry->in_use_p[word] & mask)
+ return 1;
+
+ /* Otherwise set it, and decrement the free object count. */
+ entry->in_use_p[word] |= mask;
+ entry->num_free_objects -= 1;
+
+ if (GGC_DEBUG_LEVEL >= 4)
+ fprintf (G.debug_file, "Marking %p\n", p);
+
+ return 0;
+}
+
+/* Return 1 if P has been marked, zero otherwise.
+ P must have been allocated by the GC allocator; it mustn't point to
+ static objects, stack variables, or memory allocated with malloc. */
+
+int
+ggc_marked_p (const void *p)
+{
+ page_entry *entry;
+ unsigned bit, word;
+ unsigned long mask;
+
+ /* Look up the page on which the object is alloced. If the object
+ wasn't allocated by the collector, we'll probably die. */
+ entry = lookup_page_table_entry (p);
+ gcc_assert (entry);
+
+ /* Calculate the index of the object on the page; this is its bit
+ position in the in_use_p bitmap. */
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
+ word = bit / HOST_BITS_PER_LONG;
+ mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
+
+ return (entry->in_use_p[word] & mask) != 0;
+}
+
+/* Return the size of the gc-able object P. */
+
+size_t
+ggc_get_size (const void *p)
+{
+ page_entry *pe = lookup_page_table_entry (p);
+ return OBJECT_SIZE (pe->order);
+}
+
+/* Release the memory for object P. */
+
+void
+ggc_free (void *p)
+{
+ if (in_gc)
+ return;
+
+ page_entry *pe = lookup_page_table_entry (p);
+ size_t order = pe->order;
+ size_t size = OBJECT_SIZE (order);
+
+ if (GATHER_STATISTICS)
+ ggc_free_overhead (p);
+
+ if (GGC_DEBUG_LEVEL >= 3)
+ fprintf (G.debug_file,
+ "Freeing object, actual size=%lu, at %p on %p\n",
+ (unsigned long) size, p, (void *) pe);
+
+#ifdef ENABLE_GC_CHECKING
+ /* Poison the data, to indicate the data is garbage. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (p, size));
+ memset (p, 0xa5, size);
+#endif
+ /* Let valgrind know the object is free. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (p, size));
+
+#ifdef ENABLE_GC_ALWAYS_COLLECT
+ /* In the completely-anal-checking mode, we do *not* immediately free
+ the data, but instead verify that the data is *actually* not
+ reachable the next time we collect. */
+ {
+ struct free_object *fo = XNEW (struct free_object);
+ fo->object = p;
+ fo->next = G.free_object_list;
+ G.free_object_list = fo;
+ }
+#else
+ {
+ unsigned int bit_offset, word, bit;
+
+ G.allocated -= size;
+
+ /* Mark the object not-in-use. */
+ bit_offset = OFFSET_TO_BIT (((const char *) p) - pe->page, order);
+ word = bit_offset / HOST_BITS_PER_LONG;
+ bit = bit_offset % HOST_BITS_PER_LONG;
+ pe->in_use_p[word] &= ~(1UL << bit);
+
+ if (pe->num_free_objects++ == 0)
+ {
+ page_entry *p, *q;
+
+ /* If the page is completely full, then it's supposed to
+ be after all pages that aren't. Since we've freed one
+ object from a page that was full, we need to move the
+ page to the head of the list.
+
+ PE is the node we want to move. Q is the previous node
+ and P is the next node in the list. */
+ q = pe->prev;
+ if (q && q->num_free_objects == 0)
+ {
+ p = pe->next;
+
+ q->next = p;
+
+ /* If PE was at the end of the list, then Q becomes the
+ new end of the list. If PE was not the end of the
+ list, then we need to update the PREV field for P. */
+ if (!p)
+ G.page_tails[order] = q;
+ else
+ p->prev = q;
+
+ /* Move PE to the head of the list. */
+ pe->next = G.pages[order];
+ pe->prev = NULL;
+ G.pages[order]->prev = pe;
+ G.pages[order] = pe;
+ }
+
+ /* Reset the hint bit to point to the only free object. */
+ pe->next_bit_hint = bit_offset;
+ }
+ }
+#endif
+}
+
+/* Subroutine of init_ggc which computes the pair of numbers used to
+ perform division by OBJECT_SIZE (order) and fills in inverse_table[].
+
+ This algorithm is taken from Granlund and Montgomery's paper
+ "Division by Invariant Integers using Multiplication"
+ (Proc. SIGPLAN PLDI, 1994), section 9 (Exact division by
+ constants). */
+
+static void
+compute_inverse (unsigned order)
+{
+ size_t size, inv;
+ unsigned int e;
+
+ size = OBJECT_SIZE (order);
+ e = 0;
+ while (size % 2 == 0)
+ {
+ e++;
+ size >>= 1;
+ }
+
+ inv = size;
+ while (inv * size != 1)
+ inv = inv * (2 - inv*size);
+
+ DIV_MULT (order) = inv;
+ DIV_SHIFT (order) = e;
+}
+
+/* Initialize the ggc-mmap allocator. */
+void
+init_ggc (void)
+{
+ static bool init_p = false;
+ unsigned order;
+
+ if (init_p)
+ return;
+ init_p = true;
+
+ G.pagesize = getpagesize ();
+ G.lg_pagesize = exact_log2 (G.pagesize);
+
+#ifdef HAVE_MMAP_DEV_ZERO
+ G.dev_zero_fd = open ("/dev/zero", O_RDONLY);
+ if (G.dev_zero_fd == -1)
+ internal_error ("open /dev/zero: %m");
+#endif
+
+#if 0
+ G.debug_file = fopen ("ggc-mmap.debug", "w");
+#else
+ G.debug_file = stdout;
+#endif
+
+#ifdef USING_MMAP
+ /* StunOS has an amazing off-by-one error for the first mmap allocation
+ after fiddling with RLIMIT_STACK. The result, as hard as it is to
+ believe, is an unaligned page allocation, which would cause us to
+ hork badly if we tried to use it. */
+ {
+ char *p = alloc_anon (NULL, G.pagesize, true);
+ struct page_entry *e;
+ if ((uintptr_t)p & (G.pagesize - 1))
+ {
+ /* How losing. Discard this one and try another. If we still
+ can't get something useful, give up. */
+
+ p = alloc_anon (NULL, G.pagesize, true);
+ gcc_assert (!((uintptr_t)p & (G.pagesize - 1)));
+ }
+
+ /* We have a good page, might as well hold onto it... */
+ e = XCNEW (struct page_entry);
+ e->bytes = G.pagesize;
+ e->page = p;
+ e->next = G.free_pages;
+ G.free_pages = e;
+ }
+#endif
+
+ /* Initialize the object size table. */
+ for (order = 0; order < HOST_BITS_PER_PTR; ++order)
+ object_size_table[order] = (size_t) 1 << order;
+ for (order = HOST_BITS_PER_PTR; order < NUM_ORDERS; ++order)
+ {
+ size_t s = extra_order_size_table[order - HOST_BITS_PER_PTR];
+
+ /* If S is not a multiple of the MAX_ALIGNMENT, then round it up
+ so that we're sure of getting aligned memory. */
+ s = ROUND_UP (s, MAX_ALIGNMENT);
+ object_size_table[order] = s;
+ }
+
+ /* Initialize the objects-per-page and inverse tables. */
+ for (order = 0; order < NUM_ORDERS; ++order)
+ {
+ objects_per_page_table[order] = G.pagesize / OBJECT_SIZE (order);
+ if (objects_per_page_table[order] == 0)
+ objects_per_page_table[order] = 1;
+ compute_inverse (order);
+ }
+
+ /* Reset the size_lookup array to put appropriately sized objects in
+ the special orders. All objects bigger than the previous power
+ of two, but no greater than the special size, should go in the
+ new order. */
+ for (order = HOST_BITS_PER_PTR; order < NUM_ORDERS; ++order)
+ {
+ int o;
+ int i;
+
+ i = OBJECT_SIZE (order);
+ if (i >= NUM_SIZE_LOOKUP)
+ continue;
+
+ for (o = size_lookup[i]; o == size_lookup [i]; --i)
+ size_lookup[i] = order;
+ }
+
+ G.depth_in_use = 0;
+ G.depth_max = 10;
+ G.depth = XNEWVEC (unsigned int, G.depth_max);
+
+ G.by_depth_in_use = 0;
+ G.by_depth_max = INITIAL_PTE_COUNT;
+ G.by_depth = XNEWVEC (page_entry *, G.by_depth_max);
+ G.save_in_use = XNEWVEC (unsigned long *, G.by_depth_max);
+
+ /* Allocate space for the depth 0 finalizers. */
+ G.finalizers.safe_push (vNULL);
+ G.vec_finalizers.safe_push (vNULL);
+ gcc_assert (G.finalizers.length() == 1);
+}
+
+/* Merge the SAVE_IN_USE_P and IN_USE_P arrays in P so that IN_USE_P
+ reflects reality. Recalculate NUM_FREE_OBJECTS as well. */
+
+static void
+ggc_recalculate_in_use_p (page_entry *p)
+{
+ unsigned int i;
+ size_t num_objects;
+
+ /* Because the past-the-end bit in in_use_p is always set, we
+ pretend there is one additional object. */
+ num_objects = OBJECTS_IN_PAGE (p) + 1;
+
+ /* Reset the free object count. */
+ p->num_free_objects = num_objects;
+
+ /* Combine the IN_USE_P and SAVE_IN_USE_P arrays. */
+ for (i = 0;
+ i < CEIL (BITMAP_SIZE (num_objects),
+ sizeof (*p->in_use_p));
+ ++i)
+ {
+ unsigned long j;
+
+ /* Something is in use if it is marked, or if it was in use in a
+ context further down the context stack. */
+ p->in_use_p[i] |= save_in_use_p (p)[i];
+
+ /* Decrement the free object count for every object allocated. */
+ for (j = p->in_use_p[i]; j; j >>= 1)
+ p->num_free_objects -= (j & 1);
+ }
+
+ gcc_assert (p->num_free_objects < num_objects);
+}
+
+/* Unmark all objects. */
+
+static void
+clear_marks (void)
+{
+ unsigned order;
+
+ for (order = 2; order < NUM_ORDERS; order++)
+ {
+ page_entry *p;
+
+ for (p = G.pages[order]; p != NULL; p = p->next)
+ {
+ size_t num_objects = OBJECTS_IN_PAGE (p);
+ size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
+
+ /* The data should be page-aligned. */
+ gcc_assert (!((uintptr_t) p->page & (G.pagesize - 1)));
+
+ /* Pages that aren't in the topmost context are not collected;
+ nevertheless, we need their in-use bit vectors to store GC
+ marks. So, back them up first. */
+ if (p->context_depth < G.context_depth)
+ {
+ if (! save_in_use_p (p))
+ save_in_use_p (p) = XNEWVAR (unsigned long, bitmap_size);
+ memcpy (save_in_use_p (p), p->in_use_p, bitmap_size);
+ }
+
+ /* Reset reset the number of free objects and clear the
+ in-use bits. These will be adjusted by mark_obj. */
+ p->num_free_objects = num_objects;
+ memset (p->in_use_p, 0, bitmap_size);
+
+ /* Make sure the one-past-the-end bit is always set. */
+ p->in_use_p[num_objects / HOST_BITS_PER_LONG]
+ = ((unsigned long) 1 << (num_objects % HOST_BITS_PER_LONG));
+ }
+ }
+}
+
+/* Check if any blocks with a registered finalizer have become unmarked. If so
+ run the finalizer and unregister it because the block is about to be freed.
+ Note that no garantee is made about what order finalizers will run in so
+ touching other objects in gc memory is extremely unwise. */
+
+static void
+ggc_handle_finalizers ()
+{
+ unsigned dlen = G.finalizers.length();
+ for (unsigned d = G.context_depth; d < dlen; ++d)
+ {
+ vec<finalizer> &v = G.finalizers[d];
+ unsigned length = v.length ();
+ for (unsigned int i = 0; i < length;)
+ {
+ finalizer &f = v[i];
+ if (!ggc_marked_p (f.addr ()))
+ {
+ f.call ();
+ v.unordered_remove (i);
+ length--;
+ }
+ else
+ i++;
+ }
+ }
+
+ gcc_assert (dlen == G.vec_finalizers.length());
+ for (unsigned d = G.context_depth; d < dlen; ++d)
+ {
+ vec<vec_finalizer> &vv = G.vec_finalizers[d];
+ unsigned length = vv.length ();
+ for (unsigned int i = 0; i < length;)
+ {
+ vec_finalizer &f = vv[i];
+ if (!ggc_marked_p (f.addr ()))
+ {
+ f.call ();
+ vv.unordered_remove (i);
+ length--;
+ }
+ else
+ i++;
+ }
+ }
+}
+
+/* Free all empty pages. Partially empty pages need no attention
+ because the `mark' bit doubles as an `unused' bit. */
+
+static void
+sweep_pages (void)
+{
+ unsigned order;
+
+ for (order = 2; order < NUM_ORDERS; order++)
+ {
+ /* The last page-entry to consider, regardless of entries
+ placed at the end of the list. */
+ page_entry * const last = G.page_tails[order];
+
+ size_t num_objects;
+ size_t live_objects;
+ page_entry *p, *previous;
+ int done;
+
+ p = G.pages[order];
+ if (p == NULL)
+ continue;
+
+ previous = NULL;
+ do
+ {
+ page_entry *next = p->next;
+
+ /* Loop until all entries have been examined. */
+ done = (p == last);
+
+ num_objects = OBJECTS_IN_PAGE (p);
+
+ /* Add all live objects on this page to the count of
+ allocated memory. */
+ live_objects = num_objects - p->num_free_objects;
+
+ G.allocated += OBJECT_SIZE (order) * live_objects;
+
+ /* Only objects on pages in the topmost context should get
+ collected. */
+ if (p->context_depth < G.context_depth)
+ ;
+
+ /* Remove the page if it's empty. */
+ else if (live_objects == 0)
+ {
+ /* If P was the first page in the list, then NEXT
+ becomes the new first page in the list, otherwise
+ splice P out of the forward pointers. */
+ if (! previous)
+ G.pages[order] = next;
+ else
+ previous->next = next;
+
+ /* Splice P out of the back pointers too. */
+ if (next)
+ next->prev = previous;
+
+ /* Are we removing the last element? */
+ if (p == G.page_tails[order])
+ G.page_tails[order] = previous;
+ free_page (p);
+ p = previous;
+ }
+
+ /* If the page is full, move it to the end. */
+ else if (p->num_free_objects == 0)
+ {
+ /* Don't move it if it's already at the end. */
+ if (p != G.page_tails[order])
+ {
+ /* Move p to the end of the list. */
+ p->next = NULL;
+ p->prev = G.page_tails[order];
+ G.page_tails[order]->next = p;
+
+ /* Update the tail pointer... */
+ G.page_tails[order] = p;
+
+ /* ... and the head pointer, if necessary. */
+ if (! previous)
+ G.pages[order] = next;
+ else
+ previous->next = next;
+
+ /* And update the backpointer in NEXT if necessary. */
+ if (next)
+ next->prev = previous;
+
+ p = previous;
+ }
+ }
+
+ /* If we've fallen through to here, it's a page in the
+ topmost context that is neither full nor empty. Such a
+ page must precede pages at lesser context depth in the
+ list, so move it to the head. */
+ else if (p != G.pages[order])
+ {
+ previous->next = p->next;
+
+ /* Update the backchain in the next node if it exists. */
+ if (p->next)
+ p->next->prev = previous;
+
+ /* Move P to the head of the list. */
+ p->next = G.pages[order];
+ p->prev = NULL;
+ G.pages[order]->prev = p;
+
+ /* Update the head pointer. */
+ G.pages[order] = p;
+
+ /* Are we moving the last element? */
+ if (G.page_tails[order] == p)
+ G.page_tails[order] = previous;
+ p = previous;
+ }
+
+ previous = p;
+ p = next;
+ }
+ while (! done);
+
+ /* Now, restore the in_use_p vectors for any pages from contexts
+ other than the current one. */
+ for (p = G.pages[order]; p; p = p->next)
+ if (p->context_depth != G.context_depth)
+ ggc_recalculate_in_use_p (p);
+ }
+}
+
+#ifdef ENABLE_GC_CHECKING
+/* Clobber all free objects. */
+
+static void
+poison_pages (void)
+{
+ unsigned order;
+
+ for (order = 2; order < NUM_ORDERS; order++)
+ {
+ size_t size = OBJECT_SIZE (order);
+ page_entry *p;
+
+ for (p = G.pages[order]; p != NULL; p = p->next)
+ {
+ size_t num_objects;
+ size_t i;
+
+ if (p->context_depth != G.context_depth)
+ /* Since we don't do any collection for pages in pushed
+ contexts, there's no need to do any poisoning. And
+ besides, the IN_USE_P array isn't valid until we pop
+ contexts. */
+ continue;
+
+ num_objects = OBJECTS_IN_PAGE (p);
+ for (i = 0; i < num_objects; i++)
+ {
+ size_t word, bit;
+ word = i / HOST_BITS_PER_LONG;
+ bit = i % HOST_BITS_PER_LONG;
+ if (((p->in_use_p[word] >> bit) & 1) == 0)
+ {
+ char *object = p->page + i * size;
+
+ /* Keep poison-by-write when we expect to use Valgrind,
+ so the exact same memory semantics is kept, in case
+ there are memory errors. We override this request
+ below. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (object,
+ size));
+ memset (object, 0xa5, size);
+
+ /* Drop the handle to avoid handle leak. */
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS (object, size));
+ }
+ }
+ }
+ }
+}
+#else
+#define poison_pages()
+#endif
+
+#ifdef ENABLE_GC_ALWAYS_COLLECT
+/* Validate that the reportedly free objects actually are. */
+
+static void
+validate_free_objects (void)
+{
+ struct free_object *f, *next, *still_free = NULL;
+
+ for (f = G.free_object_list; f ; f = next)
+ {
+ page_entry *pe = lookup_page_table_entry (f->object);
+ size_t bit, word;
+
+ bit = OFFSET_TO_BIT ((char *)f->object - pe->page, pe->order);
+ word = bit / HOST_BITS_PER_LONG;
+ bit = bit % HOST_BITS_PER_LONG;
+ next = f->next;
+
+ /* Make certain it isn't visible from any root. Notice that we
+ do this check before sweep_pages merges save_in_use_p. */
+ gcc_assert (!(pe->in_use_p[word] & (1UL << bit)));
+
+ /* If the object comes from an outer context, then retain the
+ free_object entry, so that we can verify that the address
+ isn't live on the stack in some outer context. */
+ if (pe->context_depth != G.context_depth)
+ {
+ f->next = still_free;
+ still_free = f;
+ }
+ else
+ free (f);
+ }
+
+ G.free_object_list = still_free;
+}
+#else
+#define validate_free_objects()
+#endif
+
+/* Top level mark-and-sweep routine. */
+
+void
+ggc_collect (enum ggc_collect mode)
+{
+ /* Avoid frequent unnecessary work by skipping collection if the
+ total allocations haven't expanded much since the last
+ collection. */
+ float allocated_last_gc =
+ MAX (G.allocated_last_gc, (size_t)param_ggc_min_heapsize * ONE_K);
+
+ /* It is also good time to get memory block pool into limits. */
+ memory_block_pool::trim ();
+
+ float min_expand = allocated_last_gc * param_ggc_min_expand / 100;
+ if (mode == GGC_COLLECT_HEURISTIC
+ && G.allocated < allocated_last_gc + min_expand)
+ return;
+
+ timevar_push (TV_GC);
+ if (GGC_DEBUG_LEVEL >= 2)
+ fprintf (G.debug_file, "BEGIN COLLECTING\n");
+
+ /* Zero the total allocated bytes. This will be recalculated in the
+ sweep phase. */
+ size_t allocated = G.allocated;
+ G.allocated = 0;
+
+ /* Release the pages we freed the last time we collected, but didn't
+ reuse in the interim. */
+ release_pages ();
+
+ /* Output this later so we do not interfere with release_pages. */
+ if (!quiet_flag)
+ fprintf (stderr, " {GC " PRsa (0) " -> ", SIZE_AMOUNT (allocated));
+
+ /* Indicate that we've seen collections at this context depth. */
+ G.context_depth_collections = ((unsigned long)1 << (G.context_depth + 1)) - 1;
+
+ invoke_plugin_callbacks (PLUGIN_GGC_START, NULL);
+
+ in_gc = true;
+ clear_marks ();
+ ggc_mark_roots ();
+ ggc_handle_finalizers ();
+
+ if (GATHER_STATISTICS)
+ ggc_prune_overhead_list ();
+
+ poison_pages ();
+ validate_free_objects ();
+ sweep_pages ();
+
+ in_gc = false;
+ G.allocated_last_gc = G.allocated;
+
+ invoke_plugin_callbacks (PLUGIN_GGC_END, NULL);
+
+ timevar_pop (TV_GC);
+
+ if (!quiet_flag)
+ fprintf (stderr, PRsa (0) "}", SIZE_AMOUNT (G.allocated));
+ if (GGC_DEBUG_LEVEL >= 2)
+ fprintf (G.debug_file, "END COLLECTING\n");
+}
+
+/* Return free pages to the system. */
+
+void
+ggc_trim ()
+{
+ timevar_push (TV_GC);
+ G.allocated = 0;
+ sweep_pages ();
+ release_pages ();
+ if (!quiet_flag)
+ fprintf (stderr, " {GC trimmed to " PRsa (0) ", " PRsa (0) " mapped}",
+ SIZE_AMOUNT (G.allocated), SIZE_AMOUNT (G.bytes_mapped));
+ timevar_pop (TV_GC);
+}
+
+/* Assume that all GGC memory is reachable and grow the limits for next
+ collection. With checking, trigger GGC so -Q compilation outputs how much
+ of memory really is reachable. */
+
+void
+ggc_grow (void)
+{
+ if (!flag_checking)
+ G.allocated_last_gc = MAX (G.allocated_last_gc,
+ G.allocated);
+ else
+ ggc_collect ();
+ if (!quiet_flag)
+ fprintf (stderr, " {GC " PRsa (0) "} ", SIZE_AMOUNT (G.allocated));
+}
+
+void
+ggc_print_statistics (void)
+{
+ struct ggc_statistics stats;
+ unsigned int i;
+ size_t total_overhead = 0;
+
+ /* Clear the statistics. */
+ memset (&stats, 0, sizeof (stats));
+
+ /* Make sure collection will really occur. */
+ G.allocated_last_gc = 0;
+
+ /* Collect and print the statistics common across collectors. */
+ ggc_print_common_statistics (stderr, &stats);
+
+ /* Release free pages so that we will not count the bytes allocated
+ there as part of the total allocated memory. */
+ release_pages ();
+
+ /* Collect some information about the various sizes of
+ allocation. */
+ fprintf (stderr,
+ "Memory still allocated at the end of the compilation process\n");
+ fprintf (stderr, "%-8s %10s %10s %10s\n",
+ "Size", "Allocated", "Used", "Overhead");
+ for (i = 0; i < NUM_ORDERS; ++i)
+ {
+ page_entry *p;
+ size_t allocated;
+ size_t in_use;
+ size_t overhead;
+
+ /* Skip empty entries. */
+ if (!G.pages[i])
+ continue;
+
+ overhead = allocated = in_use = 0;
+
+ /* Figure out the total number of bytes allocated for objects of
+ this size, and how many of them are actually in use. Also figure
+ out how much memory the page table is using. */
+ for (p = G.pages[i]; p; p = p->next)
+ {
+ allocated += p->bytes;
+ in_use +=
+ (OBJECTS_IN_PAGE (p) - p->num_free_objects) * OBJECT_SIZE (i);
+
+ overhead += (sizeof (page_entry) - sizeof (long)
+ + BITMAP_SIZE (OBJECTS_IN_PAGE (p) + 1));
+ }
+ fprintf (stderr, "%-8" PRIu64 " " PRsa (10) " " PRsa (10) " "
+ PRsa (10) "\n",
+ (uint64_t)OBJECT_SIZE (i),
+ SIZE_AMOUNT (allocated),
+ SIZE_AMOUNT (in_use),
+ SIZE_AMOUNT (overhead));
+ total_overhead += overhead;
+ }
+ fprintf (stderr, "%-8s " PRsa (10) " " PRsa (10) " " PRsa (10) "\n",
+ "Total",
+ SIZE_AMOUNT (G.bytes_mapped),
+ SIZE_AMOUNT (G.allocated),
+ SIZE_AMOUNT (total_overhead));
+
+ if (GATHER_STATISTICS)
+ {
+ fprintf (stderr, "\nTotal allocations and overheads during "
+ "the compilation process\n");
+
+ fprintf (stderr, "Total Overhead: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_overhead));
+ fprintf (stderr, "Total Allocated: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_allocated));
+
+ fprintf (stderr, "Total Overhead under 32B: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_overhead_under32));
+ fprintf (stderr, "Total Allocated under 32B: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_allocated_under32));
+ fprintf (stderr, "Total Overhead under 64B: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_overhead_under64));
+ fprintf (stderr, "Total Allocated under 64B: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_allocated_under64));
+ fprintf (stderr, "Total Overhead under 128B: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_overhead_under128));
+ fprintf (stderr, "Total Allocated under 128B: "
+ PRsa (9) "\n",
+ SIZE_AMOUNT (G.stats.total_allocated_under128));
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ if (G.stats.total_allocated_per_order[i])
+ {
+ fprintf (stderr, "Total Overhead page size %9" PRIu64 ": "
+ PRsa (9) "\n",
+ (uint64_t)OBJECT_SIZE (i),
+ SIZE_AMOUNT (G.stats.total_overhead_per_order[i]));
+ fprintf (stderr, "Total Allocated page size %9" PRIu64 ": "
+ PRsa (9) "\n",
+ (uint64_t)OBJECT_SIZE (i),
+ SIZE_AMOUNT (G.stats.total_allocated_per_order[i]));
+ }
+ }
+}
+
+struct ggc_pch_ondisk
+{
+ unsigned totals[NUM_ORDERS];
+};
+
+struct ggc_pch_data
+{
+ struct ggc_pch_ondisk d;
+ uintptr_t base[NUM_ORDERS];
+ size_t written[NUM_ORDERS];
+};
+
+struct ggc_pch_data *
+init_ggc_pch (void)
+{
+ return XCNEW (struct ggc_pch_data);
+}
+
+void
+ggc_pch_count_object (struct ggc_pch_data *d, void *x ATTRIBUTE_UNUSED,
+ size_t size, bool is_string ATTRIBUTE_UNUSED)
+{
+ unsigned order;
+
+ if (size < NUM_SIZE_LOOKUP)
+ order = size_lookup[size];
+ else
+ {
+ order = 10;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ d->d.totals[order]++;
+}
+
+size_t
+ggc_pch_total_size (struct ggc_pch_data *d)
+{
+ size_t a = 0;
+ unsigned i;
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ a += PAGE_ALIGN (d->d.totals[i] * OBJECT_SIZE (i));
+ return a;
+}
+
+void
+ggc_pch_this_base (struct ggc_pch_data *d, void *base)
+{
+ uintptr_t a = (uintptr_t) base;
+ unsigned i;
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ d->base[i] = a;
+ a += PAGE_ALIGN (d->d.totals[i] * OBJECT_SIZE (i));
+ }
+}
+
+
+char *
+ggc_pch_alloc_object (struct ggc_pch_data *d, void *x ATTRIBUTE_UNUSED,
+ size_t size, bool is_string ATTRIBUTE_UNUSED)
+{
+ unsigned order;
+ char *result;
+
+ if (size < NUM_SIZE_LOOKUP)
+ order = size_lookup[size];
+ else
+ {
+ order = 10;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ result = (char *) d->base[order];
+ d->base[order] += OBJECT_SIZE (order);
+ return result;
+}
+
+void
+ggc_pch_prepare_write (struct ggc_pch_data *d ATTRIBUTE_UNUSED,
+ FILE *f ATTRIBUTE_UNUSED)
+{
+ /* Nothing to do. */
+}
+
+void
+ggc_pch_write_object (struct ggc_pch_data *d,
+ FILE *f, void *x, void *newx ATTRIBUTE_UNUSED,
+ size_t size, bool is_string ATTRIBUTE_UNUSED)
+{
+ unsigned order;
+ static const char emptyBytes[256] = { 0 };
+
+ if (size < NUM_SIZE_LOOKUP)
+ order = size_lookup[size];
+ else
+ {
+ order = 10;
+ while (size > OBJECT_SIZE (order))
+ order++;
+ }
+
+ if (fwrite (x, size, 1, f) != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+
+ /* If SIZE is not the same as OBJECT_SIZE(order), then we need to pad the
+ object out to OBJECT_SIZE(order). This happens for strings. */
+
+ if (size != OBJECT_SIZE (order))
+ {
+ unsigned padding = OBJECT_SIZE (order) - size;
+
+ /* To speed small writes, we use a nulled-out array that's larger
+ than most padding requests as the source for our null bytes. This
+ permits us to do the padding with fwrite() rather than fseek(), and
+ limits the chance the OS may try to flush any outstanding writes. */
+ if (padding <= sizeof (emptyBytes))
+ {
+ if (fwrite (emptyBytes, 1, padding, f) != padding)
+ fatal_error (input_location, "cannot write PCH file");
+ }
+ else
+ {
+ /* Larger than our buffer? Just default to fseek. */
+ if (fseek (f, padding, SEEK_CUR) != 0)
+ fatal_error (input_location, "cannot write PCH file");
+ }
+ }
+
+ d->written[order]++;
+ if (d->written[order] == d->d.totals[order]
+ && fseek (f, ROUND_UP_VALUE (d->d.totals[order] * OBJECT_SIZE (order),
+ G.pagesize),
+ SEEK_CUR) != 0)
+ fatal_error (input_location, "cannot write PCH file: %m");
+}
+
+void
+ggc_pch_finish (struct ggc_pch_data *d, FILE *f)
+{
+ if (fwrite (&d->d, sizeof (d->d), 1, f) != 1)
+ fatal_error (input_location, "cannot write PCH file: %m");
+ free (d);
+}
+
+/* Move the PCH PTE entries just added to the end of by_depth, to the
+ front. */
+
+static void
+move_ptes_to_front (int count_old_page_tables, int count_new_page_tables)
+{
+ /* First, we swap the new entries to the front of the varrays. */
+ page_entry **new_by_depth;
+ unsigned long **new_save_in_use;
+
+ new_by_depth = XNEWVEC (page_entry *, G.by_depth_max);
+ new_save_in_use = XNEWVEC (unsigned long *, G.by_depth_max);
+
+ memcpy (&new_by_depth[0],
+ &G.by_depth[count_old_page_tables],
+ count_new_page_tables * sizeof (void *));
+ memcpy (&new_by_depth[count_new_page_tables],
+ &G.by_depth[0],
+ count_old_page_tables * sizeof (void *));
+ memcpy (&new_save_in_use[0],
+ &G.save_in_use[count_old_page_tables],
+ count_new_page_tables * sizeof (void *));
+ memcpy (&new_save_in_use[count_new_page_tables],
+ &G.save_in_use[0],
+ count_old_page_tables * sizeof (void *));
+
+ free (G.by_depth);
+ free (G.save_in_use);
+
+ G.by_depth = new_by_depth;
+ G.save_in_use = new_save_in_use;
+
+ /* Now update all the index_by_depth fields. */
+ for (unsigned i = G.by_depth_in_use; i--;)
+ {
+ page_entry *p = G.by_depth[i];
+ p->index_by_depth = i;
+ }
+
+ /* And last, we update the depth pointers in G.depth. The first
+ entry is already 0, and context 0 entries always start at index
+ 0, so there is nothing to update in the first slot. We need a
+ second slot, only if we have old ptes, and if we do, they start
+ at index count_new_page_tables. */
+ if (count_old_page_tables)
+ push_depth (count_new_page_tables);
+}
+
+void
+ggc_pch_read (FILE *f, void *addr)
+{
+ struct ggc_pch_ondisk d;
+ unsigned i;
+ char *offs = (char *) addr;
+ unsigned long count_old_page_tables;
+ unsigned long count_new_page_tables;
+
+ count_old_page_tables = G.by_depth_in_use;
+
+ if (fread (&d, sizeof (d), 1, f) != 1)
+ fatal_error (input_location, "cannot read PCH file: %m");
+
+ /* We've just read in a PCH file. So, every object that used to be
+ allocated is now free. */
+ clear_marks ();
+#ifdef ENABLE_GC_CHECKING
+ poison_pages ();
+#endif
+ /* Since we free all the allocated objects, the free list becomes
+ useless. Validate it now, which will also clear it. */
+ validate_free_objects ();
+
+ /* No object read from a PCH file should ever be freed. So, set the
+ context depth to 1, and set the depth of all the currently-allocated
+ pages to be 1 too. PCH pages will have depth 0. */
+ gcc_assert (!G.context_depth);
+ G.context_depth = 1;
+ /* Allocate space for the depth 1 finalizers. */
+ G.finalizers.safe_push (vNULL);
+ G.vec_finalizers.safe_push (vNULL);
+ gcc_assert (G.finalizers.length() == 2);
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ page_entry *p;
+ for (p = G.pages[i]; p != NULL; p = p->next)
+ p->context_depth = G.context_depth;
+ }
+
+ /* Allocate the appropriate page-table entries for the pages read from
+ the PCH file. */
+
+ for (i = 0; i < NUM_ORDERS; i++)
+ {
+ struct page_entry *entry;
+ char *pte;
+ size_t bytes;
+ size_t num_objs;
+ size_t j;
+
+ if (d.totals[i] == 0)
+ continue;
+
+ bytes = PAGE_ALIGN (d.totals[i] * OBJECT_SIZE (i));
+ num_objs = bytes / OBJECT_SIZE (i);
+ entry = XCNEWVAR (struct page_entry, (sizeof (struct page_entry)
+ - sizeof (long)
+ + BITMAP_SIZE (num_objs + 1)));
+ entry->bytes = bytes;
+ entry->page = offs;
+ entry->context_depth = 0;
+ offs += bytes;
+ entry->num_free_objects = 0;
+ entry->order = i;
+
+ for (j = 0;
+ j + HOST_BITS_PER_LONG <= num_objs + 1;
+ j += HOST_BITS_PER_LONG)
+ entry->in_use_p[j / HOST_BITS_PER_LONG] = -1;
+ for (; j < num_objs + 1; j++)
+ entry->in_use_p[j / HOST_BITS_PER_LONG]
+ |= 1L << (j % HOST_BITS_PER_LONG);
+
+ for (pte = entry->page;
+ pte < entry->page + entry->bytes;
+ pte += G.pagesize)
+ set_page_table_entry (pte, entry);
+
+ if (G.page_tails[i] != NULL)
+ G.page_tails[i]->next = entry;
+ else
+ G.pages[i] = entry;
+ G.page_tails[i] = entry;
+
+ /* We start off by just adding all the new information to the
+ end of the varrays, later, we will move the new information
+ to the front of the varrays, as the PCH page tables are at
+ context 0. */
+ push_by_depth (entry, 0);
+ }
+
+ /* Now, we update the various data structures that speed page table
+ handling. */
+ count_new_page_tables = G.by_depth_in_use - count_old_page_tables;
+
+ move_ptes_to_front (count_old_page_tables, count_new_page_tables);
+
+ /* Update the statistics. */
+ G.allocated = G.allocated_last_gc = offs - (char *)addr;
+}
diff --git a/support/cpp/gcc/ggc.h b/support/cpp/gcc/ggc.h
new file mode 100644
index 000000000..152e26c41
--- /dev/null
+++ b/support/cpp/gcc/ggc.h
@@ -0,0 +1,369 @@
+/* Garbage collection for the GNU compiler.
+
+ 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_GGC_H
+#define GCC_GGC_H
+
+/* Symbols are marked with `ggc' for `gcc gc' so as not to interfere with
+ an external gc library that might be linked in. */
+
+/* Internal functions and data structures used by the GTY
+ machinery, including the generated gt*.[hc] files. */
+
+// sdcpp #include "gtype-desc.h"
+
+/* One of these applies its third parameter (with cookie in the fourth
+ parameter) to each pointer in the object pointed to by the first
+ parameter, using the second parameter. */
+typedef void (*gt_note_pointers) (void *, void *, gt_pointer_operator,
+ void *);
+
+/* One of these is called before objects are re-ordered in memory.
+ The first parameter is the original object, the second is the
+ subobject that has had its pointers reordered, the third parameter
+ can compute the new values of a pointer when given the cookie in
+ the fourth parameter. */
+typedef void (*gt_handle_reorder) (void *, void *, gt_pointer_operator,
+ void *);
+
+/* Used by the gt_pch_n_* routines. Register an object in the hash table. */
+extern int gt_pch_note_object (void *, void *, gt_note_pointers);
+
+/* Used by the gt_pch_p_* routines. Register address of a callback
+ pointer. */
+extern void gt_pch_note_callback (void *, void *);
+
+/* Used by the gt_pch_n_* routines. Register that an object has a reorder
+ function. */
+extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder);
+
+/* generated function to clear caches in gc memory. */
+extern void gt_clear_caches ();
+
+/* Mark the object in the first parameter and anything it points to. */
+typedef void (*gt_pointer_walker) (void *);
+
+/* Structures for the easy way to mark roots.
+ In an array, terminated by having base == NULL. */
+struct ggc_root_tab {
+ void *base;
+ size_t nelt;
+ size_t stride;
+ gt_pointer_walker cb;
+ gt_pointer_walker pchw;
+};
+#define LAST_GGC_ROOT_TAB { NULL, 0, 0, NULL, NULL }
+/* Pointers to arrays of ggc_root_tab, terminated by NULL. */
+extern const struct ggc_root_tab * const gt_ggc_rtab[];
+extern const struct ggc_root_tab * const gt_ggc_deletable_rtab[];
+extern const struct ggc_root_tab * const gt_pch_scalar_rtab[];
+
+/* If EXPR is not NULL and previously unmarked, mark it and evaluate
+ to true. Otherwise evaluate to false. */
+#define ggc_test_and_set_mark(EXPR) \
+ ((EXPR) != NULL && ((void *) (EXPR)) != (void *) 1 && ! ggc_set_mark (EXPR))
+
+#define ggc_mark(EXPR) \
+ do { \
+ const void *const a__ = (EXPR); \
+ if (a__ != NULL && a__ != (void *) 1) \
+ ggc_set_mark (a__); \
+ } while (0)
+
+/* Actually set the mark on a particular region of memory, but don't
+ follow pointers. This function is called by ggc_mark_*. It
+ returns zero if the object was not previously marked; nonzero if
+ the object was already marked, or if, for any other reason,
+ pointers in this data structure should not be traversed. */
+extern int ggc_set_mark (const void *);
+
+/* Return 1 if P has been marked, zero otherwise.
+ P must have been allocated by the GC allocator; it mustn't point to
+ static objects, stack variables, or memory allocated with malloc. */
+extern int ggc_marked_p (const void *);
+
+/* PCH and GGC handling for strings, mostly trivial. */
+extern void gt_pch_n_S (const void *);
+extern void gt_ggc_m_S (const void *);
+
+/* End of GTY machinery API. */
+
+/* Initialize the string pool. */
+extern void init_stringpool (void);
+
+/* Initialize the garbage collector. */
+extern void init_ggc (void);
+
+/* When true, identifier nodes are considered as GC roots. When
+ false, identifier nodes are treated like any other GC-allocated
+ object, and the identifier hash table is treated as a weak
+ hash. */
+extern bool ggc_protect_identifiers;
+
+/* Write out all GCed objects to F. */
+extern void gt_pch_save (FILE *f);
+
+
+/* Allocation. */
+
+/* The internal primitive. */
+extern void *ggc_internal_alloc (size_t, void (*)(void *), size_t,
+ size_t CXX_MEM_STAT_INFO)
+ ATTRIBUTE_MALLOC;
+
+inline void *
+ggc_internal_alloc (size_t s CXX_MEM_STAT_INFO)
+{
+ return ggc_internal_alloc (s, NULL, 0, 1 PASS_MEM_STAT);
+}
+
+extern size_t ggc_round_alloc_size (size_t requested_size);
+
+/* Allocates cleared memory. */
+extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *),
+ size_t, size_t
+ CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
+
+inline void *
+ggc_internal_cleared_alloc (size_t s CXX_MEM_STAT_INFO)
+{
+ return ggc_internal_cleared_alloc (s, NULL, 0, 1 PASS_MEM_STAT);
+}
+
+/* Resize a block. */
+extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
+
+/* Free a block. To be used when known for certain it's not reachable. */
+extern void ggc_free (void *);
+
+extern void dump_ggc_loc_statistics ();
+
+/* Reallocator. */
+#define GGC_RESIZEVEC(T, P, N) \
+ ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
+
+template<typename T>
+void
+finalize (void *p)
+{
+ static_cast<T *> (p)->~T ();
+}
+
+template<typename T>
+inline bool
+need_finalization_p ()
+{
+#if GCC_VERSION >= 4003
+ return !__has_trivial_destructor (T);
+#else
+ return true;
+#endif
+}
+
+template<typename T>
+inline T *
+ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
+{
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_alloc (sizeof (T), finalize<T>, 0, 1
+ PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_alloc (sizeof (T), NULL, 0, 1
+ PASS_MEM_STAT));
+}
+
+/* GGC allocation function that does not call finalizer for type
+ that have need_finalization_p equal to true. User is responsible
+ for calling of the destructor. */
+
+template<typename T>
+inline T *
+ggc_alloc_no_dtor (ALONE_CXX_MEM_STAT_INFO)
+{
+ return static_cast<T *> (ggc_internal_alloc (sizeof (T), NULL, 0, 1
+ PASS_MEM_STAT));
+}
+
+template<typename T>
+inline T *
+ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
+{
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T),
+ finalize<T>, 0, 1
+ PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T), NULL, 0, 1
+ PASS_MEM_STAT));
+}
+
+template<typename T>
+inline T *
+ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
+{
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), finalize<T>,
+ sizeof (T), c PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), NULL, 0, 0
+ PASS_MEM_STAT));
+}
+
+template<typename T>
+inline T *
+ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
+{
+ if (need_finalization_p<T> ())
+ return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T),
+ finalize<T>,
+ sizeof (T), c
+ PASS_MEM_STAT));
+ else
+ return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T), NULL,
+ 0, 0 PASS_MEM_STAT));
+}
+
+inline void *
+ggc_alloc_atomic (size_t s CXX_MEM_STAT_INFO)
+{
+ return ggc_internal_alloc (s PASS_MEM_STAT);
+}
+
+/* Call destructor and free the garbage collected memory. */
+
+template <typename T>
+inline void
+ggc_delete (T *ptr)
+{
+ ptr->~T ();
+ ggc_free (ptr);
+}
+
+/* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
+ If LENGTH is -1, then CONTENTS is assumed to be a
+ null-terminated string and the memory sized accordingly. */
+extern const char *ggc_alloc_string (const char *contents, int length
+ CXX_MEM_STAT_INFO);
+
+/* Make a copy of S, in GC-able memory. */
+#define ggc_strdup(S) ggc_alloc_string ((S), -1 MEM_STAT_INFO)
+
+/* Invoke the collector. Garbage collection occurs only when this
+ function is called, not during allocations. */
+enum ggc_collect {
+ GGC_COLLECT_HEURISTIC,
+ GGC_COLLECT_FORCE
+};
+extern void ggc_collect (enum ggc_collect mode = GGC_COLLECT_HEURISTIC);
+
+/* Return unused memory pages to the system. */
+extern void ggc_trim (void);
+
+/* Assume that all GGC memory is reachable and grow the limits for next collection. */
+extern void ggc_grow (void);
+
+/* Register an additional root table. This can be useful for some
+ plugins. Does nothing if the passed pointer is NULL. */
+extern void ggc_register_root_tab (const struct ggc_root_tab *);
+
+/* Read objects previously saved with gt_pch_save from F. */
+extern void gt_pch_restore (FILE *f);
+
+/* Statistics. */
+
+/* Print allocation statistics. */
+extern void ggc_print_statistics (void);
+
+extern void stringpool_statistics (void);
+
+/* Heuristics. */
+extern void init_ggc_heuristics (void);
+
+/* Report current heap memory use to stderr. */
+extern void report_heap_memory_use (void);
+
+#define ggc_alloc_rtvec_sized(NELT) \
+ (rtvec_def *) ggc_internal_alloc (sizeof (struct rtvec_def) \
+ + ((NELT) - 1) * sizeof (rtx)) \
+
+/* Memory statistics passing versions of some allocators. Too few of them to
+ make gengtype produce them, so just define the needed ones here. */
+inline struct rtx_def *
+ggc_alloc_rtx_def_stat (size_t s CXX_MEM_STAT_INFO)
+{
+ return (struct rtx_def *) ggc_internal_alloc (s PASS_MEM_STAT);
+}
+
+inline union tree_node *
+ggc_alloc_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
+{
+ return (union tree_node *) ggc_internal_alloc (s PASS_MEM_STAT);
+}
+
+inline union tree_node *
+ggc_alloc_cleared_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
+{
+ return (union tree_node *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
+}
+
+inline gimple *
+ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
+{
+ return (gimple *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
+}
+
+inline void
+gt_ggc_mx (const char *s)
+{
+ ggc_test_and_set_mark (const_cast<char *> (s));
+}
+
+inline void
+gt_pch_nx (const char *)
+{
+}
+
+inline void gt_pch_nx (bool) { }
+inline void gt_pch_nx (char) { }
+inline void gt_pch_nx (signed char) { }
+inline void gt_pch_nx (unsigned char) { }
+inline void gt_pch_nx (short) { }
+inline void gt_pch_nx (unsigned short) { }
+inline void gt_pch_nx (int) { }
+inline void gt_pch_nx (unsigned int) { }
+inline void gt_pch_nx (long int) { }
+inline void gt_pch_nx (unsigned long int) { }
+inline void gt_pch_nx (long long int) { }
+inline void gt_pch_nx (unsigned long long int) { }
+
+inline void gt_ggc_mx (bool) { }
+inline void gt_ggc_mx (char) { }
+inline void gt_ggc_mx (signed char) { }
+inline void gt_ggc_mx (unsigned char) { }
+inline void gt_ggc_mx (short) { }
+inline void gt_ggc_mx (unsigned short) { }
+inline void gt_ggc_mx (int) { }
+inline void gt_ggc_mx (unsigned int) { }
+inline void gt_ggc_mx (long int) { }
+inline void gt_ggc_mx (unsigned long int) { }
+inline void gt_ggc_mx (long long int) { }
+inline void gt_ggc_mx (unsigned long long int) { }
+
+#endif
diff --git a/support/cpp/gcc/gimplify-me.h b/support/cpp/gcc/gimplify-me.h
new file mode 100644
index 000000000..caac850da
--- /dev/null
+++ b/support/cpp/gcc/gimplify-me.h
@@ -0,0 +1,37 @@
+/* Header file for middle end gimplification.
+ Copyright (C) 2013-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_GIMPLIFY_ME_H
+#define GCC_GIMPLIFY_ME_H
+
+/* Validation of GIMPLE expressions. Note that these predicates only check
+ * the basic form of the expression, they don't recurse to make sure that
+ * underlying nodes are also of the right form. */
+typedef bool (*gimple_predicate)(tree);
+
+extern tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree);
+extern tree force_gimple_operand (tree, gimple_seq *, bool, tree);
+extern tree force_gimple_operand_gsi_1 (gimple_stmt_iterator *, tree,
+ gimple_predicate, tree,
+ bool, enum gsi_iterator_update);
+extern tree force_gimple_operand_gsi (gimple_stmt_iterator *, tree, bool, tree,
+ bool, enum gsi_iterator_update);
+extern void gimple_regimplify_operands (gimple *, gimple_stmt_iterator *);
+
+#endif /* GCC_GIMPLIFY_ME_H */
diff --git a/support/cpp/gcc/gimplify.h b/support/cpp/gcc/gimplify.h
new file mode 100644
index 000000000..951339d94
--- /dev/null
+++ b/support/cpp/gcc/gimplify.h
@@ -0,0 +1,92 @@
+/* Header file for gimplification.
+ Copyright (C) 2013-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_GIMPLIFY_H
+#define GCC_GIMPLIFY_H
+
+/* Validation of GIMPLE expressions. Note that these predicates only check
+ the basic form of the expression, they don't recurse to make sure that
+ underlying nodes are also of the right form. */
+typedef bool (*gimple_predicate)(tree);
+
+/* FIXME we should deduce this from the predicate. */
+enum fallback {
+ fb_none = 0, /* Do not generate a temporary. */
+
+ fb_rvalue = 1, /* Generate an rvalue to hold the result of a
+ gimplified expression. */
+
+ fb_lvalue = 2, /* Generate an lvalue to hold the result of a
+ gimplified expression. */
+
+ fb_mayfail = 4, /* Gimplification may fail. Error issued
+ afterwards. */
+ fb_either= fb_rvalue | fb_lvalue
+};
+
+typedef int fallback_t;
+
+enum gimplify_status {
+ GS_ERROR = -2, /* Something Bad Seen. */
+ GS_UNHANDLED = -1, /* A langhook result for "I dunno". */
+ GS_OK = 0, /* We did something, maybe more to do. */
+ GS_ALL_DONE = 1 /* The expression is fully gimplified. */
+};
+
+extern void free_gimplify_stack (void);
+extern void push_gimplify_context (bool in_ssa = false,
+ bool rhs_cond_ok = false);
+extern void pop_gimplify_context (gimple *);
+extern gbind *gimple_current_bind_expr (void);
+extern vec<gbind *> gimple_bind_expr_stack (void);
+extern void gimplify_and_add (tree, gimple_seq *);
+extern tree get_formal_tmp_var (tree, gimple_seq *);
+extern tree get_initialized_tmp_var (tree, gimple_seq *, gimple_seq * = NULL,
+ bool = true);
+extern void declare_vars (tree, gimple *, bool);
+extern void gimple_add_tmp_var (tree);
+extern void gimple_add_tmp_var_fn (struct function *, tree);
+extern void copy_if_shared (tree *, void * = NULL);
+extern tree unshare_expr (tree);
+extern tree unshare_expr_without_location (tree);
+extern tree voidify_wrapper_expr (tree, tree);
+extern tree build_and_jump (tree *);
+extern enum gimplify_status gimplify_self_mod_expr (tree *, gimple_seq *,
+ gimple_seq *, bool, tree);
+extern tree gimple_boolify (tree);
+extern gimple_predicate rhs_predicate_for (tree);
+extern bool gimplify_stmt (tree *, gimple_seq *);
+extern void omp_firstprivatize_variable (struct gimplify_omp_ctx *, tree);
+extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
+ bool (*) (tree), fallback_t);
+
+// sdcpp int omp_construct_selector_matches (enum tree_code *, int, int *);
+
+extern void gimplify_type_sizes (tree, gimple_seq *);
+extern void gimplify_one_sizepos (tree *, gimple_seq *);
+extern gbind *gimplify_body (tree, bool);
+extern enum gimplify_status gimplify_arg (tree *, gimple_seq *, location_t,
+ bool = true);
+extern void gimplify_function_tree (tree);
+extern enum gimplify_status gimplify_va_arg_expr (tree *, gimple_seq *,
+ gimple_seq *);
+extern bool generic_expr_could_trap_p (tree expr);
+gimple *gimplify_assign (tree, tree, gimple_seq *);
+
+#endif /* GCC_GIMPLIFY_H */
diff --git a/support/cpp/gcc/gsstruct.def b/support/cpp/gcc/gsstruct.def
new file mode 100644
index 000000000..19e1088b7
--- /dev/null
+++ b/support/cpp/gcc/gsstruct.def
@@ -0,0 +1,53 @@
+/* This file contains the definitions for the gimple IR structure
+ enumeration used in GCC.
+
+ Copyright (C) 2007-2022 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldyh@redhat.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.
+
+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/>. */
+
+/* The format of this file is
+ DEFGSSTRUCT(GSS enumeration value, structure name, has-tree-operands).
+ Each enum value should correspond with a single member of the union
+ gimple_statement_d. */
+
+DEFGSSTRUCT(GSS_BASE, gimple, false)
+DEFGSSTRUCT(GSS_WITH_OPS, gimple_statement_with_ops, true)
+DEFGSSTRUCT(GSS_WITH_MEM_OPS_BASE, gimple_statement_with_memory_ops_base, false)
+DEFGSSTRUCT(GSS_WITH_MEM_OPS, gimple_statement_with_memory_ops, true)
+DEFGSSTRUCT(GSS_CALL, gcall, true)
+DEFGSSTRUCT(GSS_ASM, gasm, true)
+DEFGSSTRUCT(GSS_BIND, gbind, false)
+DEFGSSTRUCT(GSS_PHI, gphi, false)
+DEFGSSTRUCT(GSS_TRY, gtry, false)
+DEFGSSTRUCT(GSS_CATCH, gcatch, false)
+DEFGSSTRUCT(GSS_EH_FILTER, geh_filter, false)
+DEFGSSTRUCT(GSS_EH_MNT, geh_mnt, false)
+DEFGSSTRUCT(GSS_EH_CTRL, gimple_statement_eh_ctrl, false)
+DEFGSSTRUCT(GSS_EH_ELSE, geh_else, false)
+DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
+DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
+DEFGSSTRUCT(GSS_OMP_CRITICAL, gomp_critical, false)
+DEFGSSTRUCT(GSS_OMP_FOR, gomp_for, false)
+DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false)
+DEFGSSTRUCT(GSS_OMP_TASK, gomp_task, false)
+DEFGSSTRUCT(GSS_OMP_SECTIONS, gomp_sections, false)
+DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false)
+DEFGSSTRUCT(GSS_OMP_CONTINUE, gomp_continue, false)
+DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gomp_atomic_load, false)
+DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE_LAYOUT, gomp_atomic_store, false)
+DEFGSSTRUCT(GSS_TRANSACTION, gtransaction, false)
diff --git a/support/cpp/gcc/gtm-builtins.def b/support/cpp/gcc/gtm-builtins.def
new file mode 100644
index 000000000..6d5cfb9b4
--- /dev/null
+++ b/support/cpp/gcc/gtm-builtins.def
@@ -0,0 +1,212 @@
+DEF_TM_BUILTIN (BUILT_IN_TM_START, "_ITM_beginTransaction",
+ BT_FN_UINT32_UINT32_VAR, ATTR_TM_NOTHROW_RT_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT, "_ITM_commitTransaction",
+ BT_FN_VOID, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT_EH, "_ITM_commitTransactionEH",
+ BT_FN_VOID_PTR, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_ABORT, "_ITM_abortTransaction",
+ BT_FN_VOID_INT, ATTR_TM_NORETURN_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_IRREVOCABLE, "_ITM_changeTransactionMode",
+ BT_FN_VOID_INT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY, "_ITM_memcpyRtWt",
+ BT_FN_VOID_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY_RNWT, "_ITM_memcpyRnWt",
+ BT_FN_VOID_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY_RTWN, "_ITM_memcpyRtWn",
+ BT_FN_VOID_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMMOVE, "_ITM_memmoveRtWt",
+ BT_FN_VOID_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_MEMSET, "_ITM_memsetW",
+ BT_FN_VOID_PTR_INT_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_IRR, "_ITM_getTMCloneOrIrrevocable",
+ BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_SAFE, "_ITM_getTMCloneSafe",
+ BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST)
+
+/* Memory allocation builtins. */
+DEF_TM_BUILTIN (BUILT_IN_TM_MALLOC, "_ITM_malloc",
+ BT_FN_PTR_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_CALLOC, "_ITM_calloc",
+ BT_FN_PTR_SIZE_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_FREE, "_ITM_free",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+
+/* Logging builtins. */
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_1, "_ITM_LU1",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_2, "_ITM_LU2",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_4, "_ITM_LU4",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_8, "_ITM_LU8",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_FLOAT, "_ITM_LF",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_DOUBLE, "_ITM_LD",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG_LDOUBLE, "_ITM_LE",
+ BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOG, "_ITM_LB",
+ BT_FN_VOID_VPTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable. */
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M64, "__builtin__ITM_LM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M128, "__builtin__ITM_LM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M256, "__builtin__ITM_LM256")
+
+/* Writes.
+
+ Note: The writes must follow the following order: STORE, WAR, WAW.
+ The TM optimizations depend on this order.
+
+ BUILT_IN_TM_STORE_1 must be the first builtin.
+ BUILTIN_TM_LOAD_STORE_P depends on this. */
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_1, "_ITM_WU1",
+ BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_1, "_ITM_WaRU1",
+ BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_1, "_ITM_WaWU1",
+ BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_2, "_ITM_WU2",
+ BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_2, "_ITM_WaRU2",
+ BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_2, "_ITM_WaWU2",
+ BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_4, "_ITM_WU4",
+ BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_4, "_ITM_WaRU4",
+ BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_4, "_ITM_WaWU4",
+ BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_8, "_ITM_WU8",
+ BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_8, "_ITM_WaRU8",
+ BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_8, "_ITM_WaWU8",
+ BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_FLOAT, "_ITM_WF",
+ BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_FLOAT, "_ITM_WaRF",
+ BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_FLOAT, "_ITM_WaWF",
+ BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_DOUBLE, "_ITM_WD",
+ BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_DOUBLE, "_ITM_WaRD",
+ BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_DOUBLE, "_ITM_WaWD",
+ BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable. */
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M64, "__builtin__ITM_WM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M64, "__builtin__ITM_WaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M64, "__builtin__ITM_WaWM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M128, "__builtin__ITM_WM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M128, "__builtin__ITM_WaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M128, "__builtin__ITM_WaWM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M256, "__builtin__ITM_WM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M256, "__builtin__ITM_WaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M256, "__builtin__ITM_WaWM256")
+
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_LDOUBLE, "_ITM_WE",
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_LDOUBLE, "_ITM_WaRE",
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_LDOUBLE, "_ITM_WaWE",
+ BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST)
+/* Note: BUILT_IN_TM_STORE_WAW_LDOUBLE must be the last TM store.
+ BUILTIN_TM_STORE_P depends on this. */
+
+/* Reads.
+
+ Note: The reads must follow the following order: LOAD, RAR, RAW, RFW.
+ The TM optimizations depend on this order. */
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_1, "_ITM_RU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_1, "_ITM_RaRU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_1, "_ITM_RaWU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_1, "_ITM_RfWU1",
+ BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_2, "_ITM_RU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_2, "_ITM_RaRU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_2, "_ITM_RaWU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_2, "_ITM_RfWU2",
+ BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_4, "_ITM_RU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_4, "_ITM_RaRU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_4, "_ITM_RaWU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_4, "_ITM_RfWU4",
+ BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_8, "_ITM_RU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_8, "_ITM_RaRU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_8, "_ITM_RaWU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_8, "_ITM_RfWU8",
+ BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_FLOAT, "_ITM_RF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_FLOAT, "_ITM_RaRF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_FLOAT, "_ITM_RaWF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_FLOAT, "_ITM_RfWF",
+ BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_DOUBLE, "_ITM_RD",
+ BT_FN_DOUBLE_CONST_DOUBLE_PTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_DOUBLE, "_ITM_RaRD",
+ BT_FN_DOUBLE_CONST_DOUBLE_PTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_DOUBLE, "_ITM_RaWD",
+ BT_FN_DOUBLE_CONST_DOUBLE_PTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_DOUBLE, "_ITM_RfWD",
+ BT_FN_DOUBLE_CONST_DOUBLE_PTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+/* These stubs should get defined in the backend if applicable. */
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M64, "__builtin__ITM_RM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M64, "__builtin__ITM_RaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M64, "__builtin__ITM_RaRM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M64, "__builtin__ITM_RfWM64")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M128, "__builtin__ITM_RM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M128, "__builtin__ITM_RaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M128, "__builtin__ITM_RaRM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M128, "__builtin__ITM_RfWM128")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M256, "__builtin__ITM_RM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M256, "__builtin__ITM_RaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M256, "__builtin__ITM_RaRM256")
+DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M256, "__builtin__ITM_RfWM256")
+
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_LDOUBLE, "_ITM_RE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_LDOUBLE, "_ITM_RaRE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_LDOUBLE, "_ITM_RaWE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_LDOUBLE, "_ITM_RfWE",
+ BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST)
+
+/* Note: BUILT_IN_TM_LOAD_RFW_LDOUBLE must be the last TM load as well
+ as the last builtin. BUILTIN_TM_LOAD_STORE_P and BUILTIN_TM_LOAD_P
+ depend on this. */
diff --git a/support/cpp/gcc/hard-reg-set.h b/support/cpp/gcc/hard-reg-set.h
new file mode 100644
index 000000000..7ad52b39d
--- /dev/null
+++ b/support/cpp/gcc/hard-reg-set.h
@@ -0,0 +1,527 @@
+/* Sets (bit vectors) of hard registers, and operations on them.
+ 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/>. */
+
+#if 0 // sdcpp ndef GCC_HARD_REG_SET_H
+#define GCC_HARD_REG_SET_H
+
+#include "array-traits.h"
+
+/* Define the type of a set of hard registers. */
+
+/* HARD_REG_ELT_TYPE is a typedef of the unsigned integral type which
+ will be used for hard reg sets, either alone or in an array.
+
+ If HARD_REG_SET is a macro, its definition is HARD_REG_ELT_TYPE,
+ and it has enough bits to represent all the target machine's hard
+ registers. Otherwise, it is a typedef for a suitably sized array
+ of HARD_REG_ELT_TYPEs. HARD_REG_SET_LONGS is defined as how many.
+
+ Note that lots of code assumes that the first part of a regset is
+ the same format as a HARD_REG_SET. To help make sure this is true,
+ we only try the widest fast integer mode (HOST_WIDEST_FAST_INT)
+ instead of all the smaller types. This approach loses only if
+ there are very few registers and then only in the few cases where
+ we have an array of HARD_REG_SETs, so it needn't be as complex as
+ it used to be. */
+
+typedef unsigned HOST_WIDEST_FAST_INT HARD_REG_ELT_TYPE;
+
+#if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT
+
+typedef HARD_REG_ELT_TYPE HARD_REG_SET;
+typedef const HARD_REG_SET const_hard_reg_set;
+
+#else
+
+#define HARD_REG_SET_LONGS \
+ ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1) \
+ / HOST_BITS_PER_WIDEST_FAST_INT)
+
+struct HARD_REG_SET
+{
+ HARD_REG_SET
+ operator~ () const
+ {
+ HARD_REG_SET res;
+ for (unsigned int i = 0; i < ARRAY_SIZE (elts); ++i)
+ res.elts[i] = ~elts[i];
+ return res;
+ }
+
+ HARD_REG_SET
+ operator& (const HARD_REG_SET &other) const
+ {
+ HARD_REG_SET res;
+ for (unsigned int i = 0; i < ARRAY_SIZE (elts); ++i)
+ res.elts[i] = elts[i] & other.elts[i];
+ return res;
+ }
+
+ HARD_REG_SET &
+ operator&= (const HARD_REG_SET &other)
+ {
+ for (unsigned int i = 0; i < ARRAY_SIZE (elts); ++i)
+ elts[i] &= other.elts[i];
+ return *this;
+ }
+
+ HARD_REG_SET
+ operator| (const HARD_REG_SET &other) const
+ {
+ HARD_REG_SET res;
+ for (unsigned int i = 0; i < ARRAY_SIZE (elts); ++i)
+ res.elts[i] = elts[i] | other.elts[i];
+ return res;
+ }
+
+ HARD_REG_SET &
+ operator|= (const HARD_REG_SET &other)
+ {
+ for (unsigned int i = 0; i < ARRAY_SIZE (elts); ++i)
+ elts[i] |= other.elts[i];
+ return *this;
+ }
+
+ bool
+ operator== (const HARD_REG_SET &other) const
+ {
+ HARD_REG_ELT_TYPE bad = 0;
+ for (unsigned int i = 0; i < ARRAY_SIZE (elts); ++i)
+ bad |= (elts[i] ^ other.elts[i]);
+ return bad == 0;
+ }
+
+ bool
+ operator!= (const HARD_REG_SET &other) const
+ {
+ return !operator== (other);
+ }
+
+ HARD_REG_ELT_TYPE elts[HARD_REG_SET_LONGS];
+};
+typedef const HARD_REG_SET &const_hard_reg_set;
+
+template<>
+struct array_traits<HARD_REG_SET>
+{
+ typedef HARD_REG_ELT_TYPE element_type;
+ static const bool has_constant_size = true;
+ static const size_t constant_size = HARD_REG_SET_LONGS;
+ static const element_type *base (const HARD_REG_SET &x) { return x.elts; }
+ static size_t size (const HARD_REG_SET &) { return HARD_REG_SET_LONGS; }
+};
+
+#endif
+
+/* HARD_REG_SET wrapped into a structure, to make it possible to
+ use HARD_REG_SET even in APIs that should not include
+ hard-reg-set.h. */
+struct hard_reg_set_container
+{
+ HARD_REG_SET set;
+};
+
+/* HARD_CONST is used to cast a constant to the appropriate type
+ for use with a HARD_REG_SET. */
+
+#define HARD_CONST(X) ((HARD_REG_ELT_TYPE) (X))
+
+/* Define macros SET_HARD_REG_BIT, CLEAR_HARD_REG_BIT and TEST_HARD_REG_BIT
+ to set, clear or test one bit in a hard reg set of type HARD_REG_SET.
+ All three take two arguments: the set and the register number.
+
+ In the case where sets are arrays of longs, the first argument
+ is actually a pointer to a long.
+
+ Define two macros for initializing a set:
+ CLEAR_HARD_REG_SET and SET_HARD_REG_SET.
+ These take just one argument.
+
+ Also define:
+
+ hard_reg_set_subset_p (X, Y), which returns true if X is a subset of Y.
+ hard_reg_set_intersect_p (X, Y), which returns true if X and Y intersect.
+ hard_reg_set_empty_p (X), which returns true if X is empty. */
+
+#define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT)
+
+#if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT
+
+#define SET_HARD_REG_BIT(SET, BIT) \
+ ((SET) |= HARD_CONST (1) << (BIT))
+#define CLEAR_HARD_REG_BIT(SET, BIT) \
+ ((SET) &= ~(HARD_CONST (1) << (BIT)))
+#define TEST_HARD_REG_BIT(SET, BIT) \
+ (!!((SET) & (HARD_CONST (1) << (BIT))))
+
+#define CLEAR_HARD_REG_SET(TO) ((TO) = HARD_CONST (0))
+#define SET_HARD_REG_SET(TO) ((TO) = ~ HARD_CONST (0))
+
+static inline bool
+hard_reg_set_subset_p (const_hard_reg_set x, const_hard_reg_set y)
+{
+ return (x & ~y) == HARD_CONST (0);
+}
+
+static inline bool
+hard_reg_set_intersect_p (const_hard_reg_set x, const_hard_reg_set y)
+{
+ return (x & y) != HARD_CONST (0);
+}
+
+static inline bool
+hard_reg_set_empty_p (const_hard_reg_set x)
+{
+ return x == HARD_CONST (0);
+}
+
+#else
+
+inline void
+SET_HARD_REG_BIT (HARD_REG_SET &set, unsigned int bit)
+{
+ set.elts[bit / UHOST_BITS_PER_WIDE_INT]
+ |= HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT);
+}
+
+inline void
+CLEAR_HARD_REG_BIT (HARD_REG_SET &set, unsigned int bit)
+{
+ set.elts[bit / UHOST_BITS_PER_WIDE_INT]
+ &= ~(HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT));
+}
+
+inline bool
+TEST_HARD_REG_BIT (const_hard_reg_set set, unsigned int bit)
+{
+ return (set.elts[bit / UHOST_BITS_PER_WIDE_INT]
+ & (HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT)));
+}
+
+inline void
+CLEAR_HARD_REG_SET (HARD_REG_SET &set)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE (set.elts); ++i)
+ set.elts[i] = 0;
+}
+
+inline void
+SET_HARD_REG_SET (HARD_REG_SET &set)
+{
+ for (unsigned int i = 0; i < ARRAY_SIZE (set.elts); ++i)
+ set.elts[i] = -1;
+}
+
+static inline bool
+hard_reg_set_subset_p (const_hard_reg_set x, const_hard_reg_set y)
+{
+ HARD_REG_ELT_TYPE bad = 0;
+ for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
+ bad |= (x.elts[i] & ~y.elts[i]);
+ return bad == 0;
+}
+
+static inline bool
+hard_reg_set_intersect_p (const_hard_reg_set x, const_hard_reg_set y)
+{
+ HARD_REG_ELT_TYPE good = 0;
+ for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
+ good |= (x.elts[i] & y.elts[i]);
+ return good != 0;
+}
+
+static inline bool
+hard_reg_set_empty_p (const_hard_reg_set x)
+{
+ HARD_REG_ELT_TYPE bad = 0;
+ for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i)
+ bad |= x.elts[i];
+ return bad == 0;
+}
+#endif
+
+/* Iterator for hard register sets. */
+
+struct hard_reg_set_iterator
+{
+ /* Pointer to the current element. */
+ const HARD_REG_ELT_TYPE *pelt;
+
+ /* The length of the set. */
+ unsigned short length;
+
+ /* Word within the current element. */
+ unsigned short word_no;
+
+ /* Contents of the actually processed word. When finding next bit
+ it is shifted right, so that the actual bit is always the least
+ significant bit of ACTUAL. */
+ HARD_REG_ELT_TYPE bits;
+};
+
+#define HARD_REG_ELT_BITS UHOST_BITS_PER_WIDE_INT
+
+/* The implementation of the iterator functions is fully analogous to
+ the bitmap iterators. */
+static inline void
+hard_reg_set_iter_init (hard_reg_set_iterator *iter, const_hard_reg_set set,
+ unsigned min, unsigned *regno)
+{
+#ifdef HARD_REG_SET_LONGS
+ iter->pelt = set.elts;
+ iter->length = HARD_REG_SET_LONGS;
+#else
+ iter->pelt = &set;
+ iter->length = 1;
+#endif
+ iter->word_no = min / HARD_REG_ELT_BITS;
+ if (iter->word_no < iter->length)
+ {
+ iter->bits = iter->pelt[iter->word_no];
+ iter->bits >>= min % HARD_REG_ELT_BITS;
+
+ /* This is required for correct search of the next bit. */
+ min += !iter->bits;
+ }
+ *regno = min;
+}
+
+static inline bool
+hard_reg_set_iter_set (hard_reg_set_iterator *iter, unsigned *regno)
+{
+ while (1)
+ {
+ /* Return false when we're advanced past the end of the set. */
+ if (iter->word_no >= iter->length)
+ return false;
+
+ if (iter->bits)
+ {
+ /* Find the correct bit and return it. */
+ while (!(iter->bits & 1))
+ {
+ iter->bits >>= 1;
+ *regno += 1;
+ }
+ return (*regno < FIRST_PSEUDO_REGISTER);
+ }
+
+ /* Round to the beginning of the next word. */
+ *regno = (*regno + HARD_REG_ELT_BITS - 1);
+ *regno -= *regno % HARD_REG_ELT_BITS;
+
+ /* Find the next non-zero word. */
+ while (++iter->word_no < iter->length)
+ {
+ iter->bits = iter->pelt[iter->word_no];
+ if (iter->bits)
+ break;
+ *regno += HARD_REG_ELT_BITS;
+ }
+ }
+}
+
+static inline void
+hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
+{
+ iter->bits >>= 1;
+ *regno += 1;
+}
+
+#define EXECUTE_IF_SET_IN_HARD_REG_SET(SET, MIN, REGNUM, ITER) \
+ for (hard_reg_set_iter_init (&(ITER), (SET), (MIN), &(REGNUM)); \
+ hard_reg_set_iter_set (&(ITER), &(REGNUM)); \
+ hard_reg_set_iter_next (&(ITER), &(REGNUM)))
+
+
+/* Define some standard sets of registers. */
+
+/* Indexed by hard register number, contains 1 for registers
+ that are being used for global register decls.
+ These must be exempt from ordinary flow analysis
+ and are also considered fixed. */
+
+extern char global_regs[FIRST_PSEUDO_REGISTER];
+
+extern HARD_REG_SET global_reg_set;
+
+class simplifiable_subreg;
+class subreg_shape;
+
+struct simplifiable_subregs_hasher : nofree_ptr_hash <simplifiable_subreg>
+{
+ typedef const subreg_shape *compare_type;
+
+ static inline hashval_t hash (const simplifiable_subreg *);
+ static inline bool equal (const simplifiable_subreg *, const subreg_shape *);
+};
+
+struct target_hard_regs {
+ void finalize ();
+
+ /* The set of registers that actually exist on the current target. */
+ HARD_REG_SET x_accessible_reg_set;
+
+ /* The set of registers that should be considered to be register
+ operands. It is a subset of x_accessible_reg_set. */
+ HARD_REG_SET x_operand_reg_set;
+
+ /* Indexed by hard register number, contains 1 for registers
+ that are fixed use (stack pointer, pc, frame pointer, etc.;.
+ These are the registers that cannot be used to allocate
+ a pseudo reg whose life does not cross calls. */
+ char x_fixed_regs[FIRST_PSEUDO_REGISTER];
+
+ /* The same info as a HARD_REG_SET. */
+ HARD_REG_SET x_fixed_reg_set;
+
+ /* Indexed by hard register number, contains 1 for registers
+ that are fixed use or are clobbered by function calls.
+ These are the registers that cannot be used to allocate
+ a pseudo reg whose life crosses calls. */
+ char x_call_used_regs[FIRST_PSEUDO_REGISTER];
+
+ /* For targets that use reload rather than LRA, this is the set
+ of registers that we are able to save and restore around calls
+ (i.e. those for which we know a suitable mode and set of
+ load/store instructions exist). For LRA targets it contains
+ all registers.
+
+ This is legacy information and should be removed if all targets
+ switch to LRA. */
+ HARD_REG_SET x_savable_regs;
+
+ /* Contains registers that are fixed use -- i.e. in fixed_reg_set -- but
+ only if they are not merely part of that set because they are global
+ regs. Global regs that are not otherwise fixed can still take part
+ in register allocation. */
+ HARD_REG_SET x_fixed_nonglobal_reg_set;
+
+ /* Contains 1 for registers that are set or clobbered by calls. */
+ /* ??? Ideally, this would be just call_used_regs plus global_regs, but
+ for someone's bright idea to have call_used_regs strictly include
+ fixed_regs. Which leaves us guessing as to the set of fixed_regs
+ that are actually preserved. We know for sure that those associated
+ with the local stack frame are safe, but scant others. */
+ HARD_REG_SET x_regs_invalidated_by_call;
+
+ /* Table of register numbers in the order in which to try to use them. */
+ int x_reg_alloc_order[FIRST_PSEUDO_REGISTER];
+
+ /* The inverse of reg_alloc_order. */
+ int x_inv_reg_alloc_order[FIRST_PSEUDO_REGISTER];
+
+ /* For each reg class, a HARD_REG_SET saying which registers are in it. */
+ HARD_REG_SET x_reg_class_contents[N_REG_CLASSES];
+
+ /* For each reg class, a boolean saying whether the class contains only
+ fixed registers. */
+ bool x_class_only_fixed_regs[N_REG_CLASSES];
+
+ /* For each reg class, number of regs it contains. */
+ unsigned int x_reg_class_size[N_REG_CLASSES];
+
+ /* For each reg class, table listing all the classes contained in it. */
+ enum reg_class x_reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
+
+ /* For each pair of reg classes,
+ a largest reg class contained in their union. */
+ enum reg_class x_reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES];
+
+ /* For each pair of reg classes,
+ the smallest reg class that contains their union. */
+ enum reg_class x_reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
+
+ /* Vector indexed by hardware reg giving its name. */
+ const char *x_reg_names[FIRST_PSEUDO_REGISTER];
+
+ /* Records which registers can form a particular subreg, with the subreg
+ being identified by its outer mode, inner mode and offset. */
+ hash_table <simplifiable_subregs_hasher> *x_simplifiable_subregs;
+};
+
+extern struct target_hard_regs default_target_hard_regs;
+#if SWITCHABLE_TARGET
+extern struct target_hard_regs *this_target_hard_regs;
+#else
+#define this_target_hard_regs (&default_target_hard_regs)
+#endif
+
+#define accessible_reg_set \
+ (this_target_hard_regs->x_accessible_reg_set)
+#define operand_reg_set \
+ (this_target_hard_regs->x_operand_reg_set)
+#define fixed_regs \
+ (this_target_hard_regs->x_fixed_regs)
+#define fixed_reg_set \
+ (this_target_hard_regs->x_fixed_reg_set)
+#define fixed_nonglobal_reg_set \
+ (this_target_hard_regs->x_fixed_nonglobal_reg_set)
+#ifdef IN_TARGET_CODE
+#define call_used_regs \
+ (this_target_hard_regs->x_call_used_regs)
+#endif
+#define savable_regs \
+ (this_target_hard_regs->x_savable_regs)
+#ifdef IN_TARGET_CODE
+#define regs_invalidated_by_call \
+ (this_target_hard_regs->x_regs_invalidated_by_call)
+#define call_used_or_fixed_regs \
+ (regs_invalidated_by_call | fixed_reg_set)
+#endif
+#define reg_alloc_order \
+ (this_target_hard_regs->x_reg_alloc_order)
+#define inv_reg_alloc_order \
+ (this_target_hard_regs->x_inv_reg_alloc_order)
+#define reg_class_contents \
+ (this_target_hard_regs->x_reg_class_contents)
+#define class_only_fixed_regs \
+ (this_target_hard_regs->x_class_only_fixed_regs)
+#define reg_class_size \
+ (this_target_hard_regs->x_reg_class_size)
+#define reg_class_subclasses \
+ (this_target_hard_regs->x_reg_class_subclasses)
+#define reg_class_subunion \
+ (this_target_hard_regs->x_reg_class_subunion)
+#define reg_class_superunion \
+ (this_target_hard_regs->x_reg_class_superunion)
+#define reg_names \
+ (this_target_hard_regs->x_reg_names)
+
+/* Vector indexed by reg class giving its name. */
+
+extern const char * reg_class_names[];
+
+/* Given a hard REGN a FROM mode and a TO mode, return true if
+ REGN can change from mode FROM to mode TO. */
+#define REG_CAN_CHANGE_MODE_P(REGN, FROM, TO) \
+ (targetm.can_change_mode_class (FROM, TO, REGNO_REG_CLASS (REGN)))
+
+#ifdef IN_TARGET_CODE
+/* Return true if register REGNO is either fixed or call-used
+ (aka call-clobbered). */
+
+inline bool
+call_used_or_fixed_reg_p (unsigned int regno)
+{
+ return fixed_regs[regno] || this_target_hard_regs->x_call_used_regs[regno];
+}
+#endif
+
+#endif /* ! GCC_HARD_REG_SET_H */
diff --git a/support/cpp/gcc/hash-map-traits.h b/support/cpp/gcc/hash-map-traits.h
new file mode 100644
index 000000000..fad0c7d52
--- /dev/null
+++ b/support/cpp/gcc/hash-map-traits.h
@@ -0,0 +1,190 @@
+/* A hash map traits.
+ Copyright (C) 2015-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 HASH_MAP_TRAITS_H
+#define HASH_MAP_TRAITS_H
+
+/* Bacause mem-stats.h uses default hashmap traits, we have to
+ put the class to this separate header file. */
+
+#include "hash-traits.h"
+
+/* Implement hash_map traits for a key with hash traits H. Empty and
+ deleted map entries are represented as empty and deleted keys. */
+
+template <typename H, typename Value>
+struct simple_hashmap_traits
+{
+ typedef typename H::value_type key_type;
+ static const bool maybe_mx = true;
+ static inline hashval_t hash (const key_type &);
+ static inline bool equal_keys (const key_type &, const key_type &);
+ template <typename T> static inline void remove (T &);
+ static const bool empty_zero_p = H::empty_zero_p;
+ template <typename T> static inline bool is_empty (const T &);
+ template <typename T> static inline bool is_deleted (const T &);
+ template <typename T> static inline void mark_empty (T &);
+ template <typename T> static inline void mark_deleted (T &);
+};
+
+template <typename H, typename Value>
+inline hashval_t
+simple_hashmap_traits <H, Value>::hash (const key_type &h)
+{
+ return H::hash (h);
+}
+
+template <typename H, typename Value>
+inline bool
+simple_hashmap_traits <H, Value>::equal_keys (const key_type &k1,
+ const key_type &k2)
+{
+ return H::equal (k1, k2);
+}
+
+template <typename H, typename Value>
+template <typename T>
+inline void
+simple_hashmap_traits <H, Value>::remove (T &entry)
+{
+ H::remove (entry.m_key);
+ entry.m_value.~Value ();
+}
+
+template <typename H, typename Value>
+template <typename T>
+inline bool
+simple_hashmap_traits <H, Value>::is_empty (const T &entry)
+{
+ return H::is_empty (entry.m_key);
+}
+
+template <typename H, typename Value>
+template <typename T>
+inline bool
+simple_hashmap_traits <H, Value>::is_deleted (const T &entry)
+{
+ return H::is_deleted (entry.m_key);
+}
+
+template <typename H, typename Value>
+template <typename T>
+inline void
+simple_hashmap_traits <H, Value>::mark_empty (T &entry)
+{
+ H::mark_empty (entry.m_key);
+}
+
+template <typename H, typename Value>
+template <typename T>
+inline void
+simple_hashmap_traits <H, Value>::mark_deleted (T &entry)
+{
+ H::mark_deleted (entry.m_key);
+}
+
+template <typename H, typename Value>
+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. */
+
+template <typename Value>
+struct unbounded_hashmap_traits
+{
+ 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 &);
+ template <typename T> static inline bool is_deleted (const T &);
+ template <typename T> static inline void mark_empty (T &);
+ template <typename T> static inline void mark_deleted (T &);
+};
+
+template <typename Value>
+template <typename T>
+inline void
+unbounded_hashmap_traits <Value>::remove (T &entry)
+{
+ default_hash_traits <Value>::remove (entry.m_value);
+}
+
+template <typename Value>
+template <typename T>
+inline bool
+unbounded_hashmap_traits <Value>::is_empty (const T &entry)
+{
+ return default_hash_traits <Value>::is_empty (entry.m_value);
+}
+
+template <typename Value>
+template <typename T>
+inline bool
+unbounded_hashmap_traits <Value>::is_deleted (const T &entry)
+{
+ return default_hash_traits <Value>::is_deleted (entry.m_value);
+}
+
+template <typename Value>
+template <typename T>
+inline void
+unbounded_hashmap_traits <Value>::mark_empty (T &entry)
+{
+ default_hash_traits <Value>::mark_empty (entry.m_value);
+}
+
+template <typename Value>
+template <typename T>
+inline void
+unbounded_hashmap_traits <Value>::mark_deleted (T &entry)
+{
+ default_hash_traits <Value>::mark_deleted (entry.m_value);
+}
+
+/* Implement traits for a hash_map from integer type Key to Value in
+ cases where Key has no spare values for recording empty and deleted
+ 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;
+}
+
+#endif // HASH_MAP_TRAITS_H
diff --git a/support/cpp/gcc/hash-map.h b/support/cpp/gcc/hash-map.h
new file mode 100644
index 000000000..49865702a
--- /dev/null
+++ b/support/cpp/gcc/hash-map.h
@@ -0,0 +1,390 @@
+/* A type-safe hash map.
+ Copyright (C) 2014-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 hash_map_h
+#define hash_map_h
+
+/* Class hash_map is a hash-value based container mapping objects of
+ KeyId type to those of the Value type.
+ Both KeyId and Value may be non-trivial (non-POD) types provided
+ a suitabe Traits class. A few default Traits specializations are
+ provided for basic types such as integers, pointers, and std::pair.
+ Inserted elements are value-initialized either to zero for POD types
+ or by invoking their default ctor. Removed elements are destroyed
+ by invoking their dtor. On hash_map destruction all elements are
+ removed. Objects of hash_map type are copy-constructible but not
+ assignable. */
+
+const size_t default_hash_map_size = 13;
+template<typename KeyId, typename Value,
+ typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
+ Value> */>
+class GTY((user)) hash_map
+{
+ typedef typename Traits::key_type Key;
+ struct hash_entry
+ {
+ Key m_key;
+ Value m_value;
+
+ typedef hash_entry value_type;
+ typedef Key compare_type;
+
+ static hashval_t hash (const hash_entry &e)
+ {
+ return Traits::hash (e.m_key);
+ }
+
+ static bool equal (const hash_entry &a, const Key &b)
+ {
+ return Traits::equal_keys (a.m_key, b);
+ }
+
+ static void remove (hash_entry &e) { Traits::remove (e); }
+
+ static void mark_deleted (hash_entry &e) { Traits::mark_deleted (e); }
+
+ static bool is_deleted (const hash_entry &e)
+ {
+ return Traits::is_deleted (e);
+ }
+
+ static const bool empty_zero_p = Traits::empty_zero_p;
+ static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
+ static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
+
+ static void ggc_mx (hash_entry &e)
+ {
+ gt_ggc_mx (e.m_key);
+ gt_ggc_mx (e.m_value);
+ }
+
+ static void ggc_maybe_mx (hash_entry &e)
+ {
+ if (Traits::maybe_mx)
+ ggc_mx (e);
+ }
+
+ static void pch_nx (hash_entry &e)
+ {
+ gt_pch_nx (e.m_key);
+ gt_pch_nx (e.m_value);
+ }
+
+ static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
+ {
+ pch_nx_helper (e.m_key, op, c);
+ pch_nx_helper (e.m_value, op, c);
+ }
+
+ static int keep_cache_entry (hash_entry &e)
+ {
+ return ggc_marked_p (e.m_key);
+ }
+
+ private:
+ template<typename T>
+ static void
+ pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
+ {
+ gt_pch_nx (&x, op, cookie);
+ }
+
+ template<typename T>
+ static void
+ pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
+ {
+ op (&x, NULL, cookie);
+ }
+
+ /* The overloads below should match those in ggc.h. */
+#define DEFINE_PCH_HELPER(T) \
+ static void pch_nx_helper (T, gt_pointer_operator, void *) { }
+
+ DEFINE_PCH_HELPER (bool);
+ DEFINE_PCH_HELPER (char);
+ DEFINE_PCH_HELPER (signed char);
+ DEFINE_PCH_HELPER (unsigned char);
+ DEFINE_PCH_HELPER (short);
+ DEFINE_PCH_HELPER (unsigned short);
+ DEFINE_PCH_HELPER (int);
+ DEFINE_PCH_HELPER (unsigned int);
+ DEFINE_PCH_HELPER (long);
+ DEFINE_PCH_HELPER (unsigned long);
+ DEFINE_PCH_HELPER (long long);
+ DEFINE_PCH_HELPER (unsigned long long);
+
+#undef DEFINE_PCH_HELPER
+ };
+
+public:
+ explicit hash_map (size_t n = default_hash_map_size, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
+ bool gather_mem_stats = GATHER_STATISTICS
+ CXX_MEM_STAT_INFO)
+ : m_table (n, ggc, sanitize_eq_and_hash, gather_mem_stats,
+ HASH_MAP_ORIGIN PASS_MEM_STAT)
+ {
+ }
+
+ explicit hash_map (const hash_map &h, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
+ bool gather_mem_stats = GATHER_STATISTICS
+ CXX_MEM_STAT_INFO)
+ : m_table (h.m_table, ggc, sanitize_eq_and_hash, gather_mem_stats,
+ HASH_MAP_ORIGIN PASS_MEM_STAT) {}
+
+ /* Create a hash_map in ggc memory. */
+ static hash_map *create_ggc (size_t size = default_hash_map_size,
+ bool gather_mem_stats = GATHER_STATISTICS
+ CXX_MEM_STAT_INFO)
+ {
+ hash_map *map = ggc_alloc<hash_map> ();
+ new (map) hash_map (size, true, true, gather_mem_stats PASS_MEM_STAT);
+ return map;
+ }
+
+ /* If key k isn't already in the map add key k with value v to the map, and
+ return false. Otherwise set the value of the entry for key k to be v and
+ return true. */
+
+ bool put (const Key &k, const Value &v)
+ {
+#if 1 //sdcpp
+ gcc_assert(false);
+ (void) k;
+ (void) v;
+#else // sdcpp
+ hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
+ INSERT);
+ bool ins = hash_entry::is_empty (*e);
+ if (ins)
+ {
+ e->m_key = k;
+ new ((void *) &e->m_value) Value (v);
+ }
+ else
+ e->m_value = v;
+
+ return !ins;
+#endif // sdcpp
+ }
+
+ /* If the passed in key is in the map return pointer to its value
+ otherwise NULL. */
+
+ Value *get (const Key &k)
+ {
+ hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
+ return Traits::is_empty (e) ? NULL : &e.m_value;
+ }
+
+ /* Return a reference to the value for the passed in key, creating the entry
+ if it doesn't already exist. If existed is not NULL then it is set to
+ false if the key was not previously in the map, and true otherwise. */
+
+ Value &get_or_insert (const Key &k, bool *existed = NULL)
+ {
+ hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
+ INSERT);
+ bool ins = Traits::is_empty (*e);
+ if (ins)
+ {
+ e->m_key = k;
+ new ((void *)&e->m_value) Value ();
+ }
+
+ if (existed != NULL)
+ *existed = !ins;
+
+ return e->m_value;
+ }
+
+ void remove (const Key &k)
+ {
+ m_table.remove_elt_with_hash (k, Traits::hash (k));
+ }
+
+ /* Call the call back on each pair of key and value with the passed in
+ arg until either the call back returns false or all pairs have been seen.
+ The traversal is unordered. */
+
+ template<typename Arg, bool (*f)(const typename Traits::key_type &,
+ const Value &, Arg)>
+ void traverse (Arg a) const
+ {
+ for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
+ iter != m_table.end (); ++iter)
+ if (!f ((*iter).m_key, (*iter).m_value, a))
+ break;
+ }
+
+ template<typename Arg, bool (*f)(const typename Traits::key_type &,
+ Value *, Arg)>
+ void traverse (Arg a) const
+ {
+ for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
+ iter != m_table.end (); ++iter)
+ if (!f ((*iter).m_key, &(*iter).m_value, a))
+ break;
+ }
+
+ size_t elements () const { return m_table.elements (); }
+
+ void empty () { m_table.empty(); }
+
+ /* Return true when there are no elements in this hash map. */
+ bool is_empty () const { return m_table.is_empty (); }
+
+ class iterator
+ {
+ public:
+ explicit iterator (const typename hash_table<hash_entry>::iterator &iter) :
+ m_iter (iter) {}
+
+ iterator &operator++ ()
+ {
+ ++m_iter;
+ return *this;
+ }
+
+ /* Can't use std::pair here, because GCC before 4.3 don't handle
+ std::pair where template parameters are references well.
+ See PR86739. */
+ class reference_pair {
+ public:
+ const Key &first;
+ Value &second;
+
+ reference_pair (const Key &key, Value &value) : first (key), second (value) {}
+
+ template <typename K, typename V>
+ operator std::pair<K, V> () const { return std::pair<K, V> (first, second); }
+ };
+
+ reference_pair operator* ()
+ {
+ hash_entry &e = *m_iter;
+ return reference_pair (e.m_key, e.m_value);
+ }
+
+ bool operator== (const iterator &other) const
+ {
+ return m_iter == other.m_iter;
+ }
+
+ bool operator != (const iterator &other) const
+ {
+ return m_iter != other.m_iter;
+ }
+
+ private:
+ typename hash_table<hash_entry>::iterator m_iter;
+ };
+
+ /* Standard iterator retrieval methods. */
+
+ iterator begin () const { return iterator (m_table.begin ()); }
+ iterator end () const { return iterator (m_table.end ()); }
+
+private:
+
+ template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
+ template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
+ template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
+ template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *);
+
+ hash_table<hash_entry> m_table;
+};
+
+/* ggc marking routines. */
+
+template<typename K, typename V, typename H>
+static inline void
+gt_ggc_mx (hash_map<K, V, H> *h)
+{
+ gt_ggc_mx (&h->m_table);
+}
+
+template<typename K, typename V, typename H>
+static inline void
+gt_pch_nx (hash_map<K, V, H> *h)
+{
+ gt_pch_nx (&h->m_table);
+}
+
+template<typename K, typename V, typename H>
+static inline void
+gt_cleare_cache (hash_map<K, V, H> *h)
+{
+ if (h)
+ gt_cleare_cache (&h->m_table);
+}
+
+template<typename K, typename V, typename H>
+static inline void
+gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
+{
+ op (&h->m_table.m_entries, NULL, cookie);
+}
+
+enum hm_alloc { hm_heap = false, hm_ggc = true };
+template<bool ggc, typename K, typename V, typename H>
+inline hash_map<K,V,H> *
+hash_map_maybe_create (hash_map<K,V,H> *&h,
+ size_t size = default_hash_map_size)
+{
+ if (!h)
+ {
+ if (ggc)
+ h = hash_map<K,V,H>::create_ggc (size);
+ else
+ h = new hash_map<K,V,H> (size);
+ }
+ return h;
+}
+
+/* Like h->get, but handles null h. */
+template<typename K, typename V, typename H>
+inline V*
+hash_map_safe_get (hash_map<K,V,H> *h, const K& k)
+{
+ return h ? h->get (k) : NULL;
+}
+
+/* Like h->get, but handles null h. */
+template<bool ggc, typename K, typename V, typename H>
+inline V&
+hash_map_safe_get_or_insert (hash_map<K,V,H> *&h, const K& k, bool *e = NULL,
+ size_t size = default_hash_map_size)
+{
+ return hash_map_maybe_create<ggc> (h, size)->get_or_insert (k, e);
+}
+
+/* Like h->put, but handles null h. */
+template<bool ggc, typename K, typename V, typename H>
+inline bool
+hash_map_safe_put (hash_map<K,V,H> *&h, const K& k, const V& v,
+ size_t size = default_hash_map_size)
+{
+ return hash_map_maybe_create<ggc> (h, size)->put (k, v);
+}
+
+#endif
diff --git a/support/cpp/gcc/hash-set.h b/support/cpp/gcc/hash-set.h
new file mode 100644
index 000000000..48fbb515c
--- /dev/null
+++ b/support/cpp/gcc/hash-set.h
@@ -0,0 +1,215 @@
+/* A type-safe hash set.
+ Copyright (C) 2014-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 hash_set_h
+#define hash_set_h
+
+#include "hash-table.h" // sdcpp
+#include "hash-traits.h" // sdcpp
+
+/* Class hash_set is a hash-value based container for objects of
+ KeyId type.
+ KeyId may be a non-trivial (non-POD) type provided a suitabe Traits
+ class. Default Traits specializations are provided for basic types
+ such as integers, pointers, and std::pair. Inserted elements are
+ value-initialized either to zero for POD types or by invoking their
+ default ctor. Removed elements are destroyed by invoking their dtor.
+ On hash_set destruction all elements are removed. Objects of
+ hash_set type are copy-constructible but not assignable. */
+
+template<typename KeyId, bool Lazy = false,
+ typename Traits = default_hash_traits<KeyId> >
+class hash_set
+{
+public:
+ typedef typename Traits::value_type Key;
+ explicit hash_set (size_t n = 13, bool ggc = false CXX_MEM_STAT_INFO)
+ : m_table (n, ggc, true, GATHER_STATISTICS, HASH_SET_ORIGIN PASS_MEM_STAT) {}
+
+ /* Create a hash_set in gc memory with space for at least n elements. */
+
+ static hash_set *
+ create_ggc (size_t n)
+ {
+ hash_set *set = ggc_alloc<hash_set> ();
+ new (set) hash_set (n, true);
+ return set;
+ }
+
+ /* If key k isn't already in the map add it to the map, and
+ return false. Otherwise return true. */
+
+ bool add (const Key &k)
+ {
+ Key *e = m_table.find_slot_with_hash (k, Traits::hash (k), INSERT);
+ bool existed = !Traits::is_empty (*e);
+ if (!existed)
+ new (e) Key (k);
+
+ return existed;
+ }
+
+ /* if the passed in key is in the map return its value otherwise NULL. */
+
+ bool contains (const Key &k)
+ {
+ if (Lazy)
+ return (m_table.find_slot_with_hash (k, Traits::hash (k), NO_INSERT)
+ != NULL);
+ Key &e = m_table.find_with_hash (k, Traits::hash (k));
+ return !Traits::is_empty (e);
+ }
+
+ void remove (const Key &k)
+ {
+ m_table.remove_elt_with_hash (k, Traits::hash (k));
+ }
+
+ /* Call the call back on each pair of key and value with the passed in
+ arg. */
+
+ template<typename Arg, bool (*f)(const typename Traits::value_type &, Arg)>
+ void traverse (Arg a) const
+ {
+ for (typename hash_table<Traits, Lazy>::iterator iter = m_table.begin ();
+ iter != m_table.end (); ++iter)
+ f (*iter, a);
+ }
+
+ /* Return the number of elements in the set. */
+
+ size_t elements () const { return m_table.elements (); }
+
+ /* Clear the hash table. */
+
+ void empty () { m_table.empty (); }
+
+ /* Return true when there are no elements in this hash set. */
+ bool is_empty () const { return m_table.is_empty (); }
+
+ class iterator
+ {
+ public:
+ explicit iterator (const typename hash_table<Traits,
+ Lazy>::iterator &iter) :
+ m_iter (iter) {}
+
+ iterator &operator++ ()
+ {
+ ++m_iter;
+ return *this;
+ }
+
+ Key
+ operator* ()
+ {
+ return *m_iter;
+ }
+
+ bool
+ operator != (const iterator &other) const
+ {
+ return m_iter != other.m_iter;
+ }
+
+ private:
+ typename hash_table<Traits, Lazy>::iterator m_iter;
+ };
+
+ /* Standard iterator retrieval methods. */
+
+ iterator begin () const { return iterator (m_table.begin ()); }
+ iterator end () const { return iterator (m_table.end ()); }
+
+
+private:
+
+ template<typename T, typename U>
+ friend void gt_ggc_mx (hash_set<T, false, U> *);
+ template<typename T, typename U>
+ friend void gt_pch_nx (hash_set<T, false, U> *);
+ template<typename T, typename U>
+ friend void gt_pch_nx (hash_set<T, false, U> *, gt_pointer_operator, void *);
+
+ hash_table<Traits, Lazy> m_table;
+};
+
+/* Generic hash_set<TYPE> debug helper.
+
+ This needs to be instantiated for each hash_set<TYPE> used throughout
+ the compiler like this:
+
+ DEFINE_DEBUG_HASH_SET (TYPE)
+
+ The reason we have a debug_helper() is because GDB can't
+ disambiguate a plain call to debug(some_hash), and it must be called
+ like debug<TYPE>(some_hash). */
+template<typename T>
+void
+debug_helper (hash_set<T> &ref)
+{
+ for (typename hash_set<T>::iterator it = ref.begin ();
+ it != ref.end (); ++it)
+ {
+ debug_slim (*it);
+ fputc ('\n', stderr);
+ }
+}
+
+#define DEFINE_DEBUG_HASH_SET(T) \
+ template void debug_helper (hash_set<T> &); \
+ DEBUG_FUNCTION void \
+ debug (hash_set<T> &ref) \
+ { \
+ debug_helper <T> (ref); \
+ } \
+ DEBUG_FUNCTION void \
+ debug (hash_set<T> *ptr) \
+ { \
+ if (ptr) \
+ debug (*ptr); \
+ else \
+ fprintf (stderr, "<nil>\n"); \
+ }
+
+/* ggc marking routines. */
+
+template<typename K, typename H>
+static inline void
+gt_ggc_mx (hash_set<K, false, H> *h)
+{
+ gt_ggc_mx (&h->m_table);
+}
+
+template<typename K, typename H>
+static inline void
+gt_pch_nx (hash_set<K, false, H> *h)
+{
+ gt_pch_nx (&h->m_table);
+}
+
+template<typename K, typename H>
+static inline void
+gt_pch_nx (hash_set<K, false, H> *h, gt_pointer_operator op, void *cookie)
+{
+ op (&h->m_table.m_entries, NULL, cookie);
+}
+
+#endif
diff --git a/support/cpp/gcc/hash-table.cc b/support/cpp/gcc/hash-table.cc
new file mode 100644
index 000000000..dad1d21f0
--- /dev/null
+++ b/support/cpp/gcc/hash-table.cc
@@ -0,0 +1,138 @@
+/* A type-safe hash table template.
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ Contributed by Lawrence Crowl <crowl@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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 implements a typed hash table.
+ The implementation borrows from libiberty's hashtab. */
+
+#ifdef GENERATOR_FILE
+#include "bconfig.h"
+#else
+#include "config.h"
+#endif
+#include "system.h"
+#include "coretypes.h"
+#include "hash-table.h"
+
+/* Table of primes and multiplicative inverses.
+
+ Note that these are not minimally reduced inverses. Unlike when generating
+ code to divide by a constant, we want to be able to use the same algorithm
+ all the time. All of these inverses (are implied to) have bit 32 set.
+
+ For the record, here's the function that computed the table; it's a
+ vastly simplified version of the function of the same name from gcc. */
+
+struct prime_ent const prime_tab[] = {
+ { 7, 0x24924925, 0x9999999b, 2 },
+ { 13, 0x3b13b13c, 0x745d1747, 3 },
+ { 31, 0x08421085, 0x1a7b9612, 4 },
+ { 61, 0x0c9714fc, 0x15b1e5f8, 5 },
+ { 127, 0x02040811, 0x0624dd30, 6 },
+ { 251, 0x05197f7e, 0x073260a5, 7 },
+ { 509, 0x01824366, 0x02864fc8, 8 },
+ { 1021, 0x00c0906d, 0x014191f7, 9 },
+ { 2039, 0x0121456f, 0x0161e69e, 10 },
+ { 4093, 0x00300902, 0x00501908, 11 },
+ { 8191, 0x00080041, 0x00180241, 12 },
+ { 16381, 0x000c0091, 0x00140191, 13 },
+ { 32749, 0x002605a5, 0x002a06e6, 14 },
+ { 65521, 0x000f00e2, 0x00110122, 15 },
+ { 131071, 0x00008001, 0x00018003, 16 },
+ { 262139, 0x00014002, 0x0001c004, 17 },
+ { 524287, 0x00002001, 0x00006001, 18 },
+ { 1048573, 0x00003001, 0x00005001, 19 },
+ { 2097143, 0x00004801, 0x00005801, 20 },
+ { 4194301, 0x00000c01, 0x00001401, 21 },
+ { 8388593, 0x00001e01, 0x00002201, 22 },
+ { 16777213, 0x00000301, 0x00000501, 23 },
+ { 33554393, 0x00001381, 0x00001481, 24 },
+ { 67108859, 0x00000141, 0x000001c1, 25 },
+ { 134217689, 0x000004e1, 0x00000521, 26 },
+ { 268435399, 0x00000391, 0x000003b1, 27 },
+ { 536870909, 0x00000019, 0x00000029, 28 },
+ { 1073741789, 0x0000008d, 0x00000095, 29 },
+ { 2147483647, 0x00000003, 0x00000007, 30 },
+ /* Avoid "decimal constant so large it is unsigned" for 4294967291. */
+ { 0xfffffffb, 0x00000006, 0x00000008, 31 }
+};
+
+/* Limit number of comparisons when calling hash_table<>::verify. */
+unsigned int hash_table_sanitize_eq_limit;
+
+/* The following function returns an index into the above table of the
+ nearest prime number which is at least N, and near a power of two. */
+
+unsigned int
+hash_table_higher_prime_index (unsigned long n)
+{
+ unsigned int low = 0;
+ unsigned int high = sizeof (prime_tab) / sizeof (prime_tab[0]);
+
+ while (low != high)
+ {
+ unsigned int mid = low + (high - low) / 2;
+ if (n > prime_tab[mid].prime)
+ low = mid + 1;
+ else
+ high = mid;
+ }
+
+ /* If we've run out of primes, abort. */
+ gcc_assert (n <= prime_tab[low].prime);
+
+ return low;
+}
+
+/* Return a reference to the lazily initialized hash-table usage description.
+ This needs to be a function rather than a simple global variable so that it
+ is reliably initialized before hash table variables in other files such as
+ sem_item::m_type_hash_cache. */
+mem_alloc_description<mem_usage>&
+hash_table_usage ()
+{
+ static mem_alloc_description<mem_usage> usage;
+ return usage;
+}
+
+/* Support function for statistics. */
+void dump_hash_table_loc_statistics (void)
+{
+ if (!GATHER_STATISTICS)
+ return;
+
+ for (unsigned i = HASH_TABLE_ORIGIN; i <= HASH_SET_ORIGIN; i++)
+ {
+ mem_alloc_origin origin = (mem_alloc_origin) i;
+ hash_table_usage ().dump (origin);
+ }
+}
+
+/* Report a hash table checking error. */
+
+ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+void
+hashtab_chk_error ()
+{
+ fprintf (stderr, "hash table checking failed: "
+ "equal operator returns true for a pair "
+ "of values with a different hash value\n");
+ gcc_unreachable ();
+}
diff --git a/support/cpp/gcc/hash-table.h b/support/cpp/gcc/hash-table.h
new file mode 100644
index 000000000..53507daae
--- /dev/null
+++ b/support/cpp/gcc/hash-table.h
@@ -0,0 +1,1231 @@
+/* A type-safe hash table template.
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ Contributed by Lawrence Crowl <crowl@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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 implements a typed hash table.
+ The implementation borrows from libiberty's htab_t in hashtab.h.
+
+
+ INTRODUCTION TO TYPES
+
+ Users of the hash table generally need to be aware of three types.
+
+ 1. The type being placed into the hash table. This type is called
+ the value type.
+
+ 2. The type used to describe how to handle the value type within
+ the hash table. This descriptor type provides the hash table with
+ several things.
+
+ - A typedef named 'value_type' to the value type (from above).
+ Provided a suitable Descriptor class it may be a user-defined,
+ non-POD type.
+
+ - A static member function named 'hash' that takes a value_type
+ (or 'const value_type &') and returns a hashval_t value.
+
+ - A typedef named 'compare_type' that is used to test when a value
+ is found. This type is the comparison type. Usually, it will be
+ the same as value_type and may be a user-defined, non-POD type.
+ If it is not the same type, you must generally explicitly compute
+ hash values and pass them to the hash table.
+
+ - A static member function named 'equal' that takes a value_type
+ and a compare_type, and returns a bool. Both arguments can be
+ const references.
+
+ - A static function named 'remove' that takes an value_type pointer
+ and frees the memory allocated by it. This function is used when
+ individual elements of the table need to be disposed of (e.g.,
+ when deleting a hash table, removing elements from the table, etc).
+
+ - An optional static function named 'keep_cache_entry'. This
+ function is provided only for garbage-collected elements that
+ are not marked by the normal gc mark pass. It describes what
+ what should happen to the element at the end of the gc mark phase.
+ The return value should be:
+ - 0 if the element should be deleted
+ - 1 if the element should be kept and needs to be marked
+ - -1 if the element should be kept and is already marked.
+ Returning -1 rather than 1 is purely an optimization.
+
+ 3. The type of the hash table itself. (More later.)
+
+ In very special circumstances, users may need to know about a fourth type.
+
+ 4. The template type used to describe how hash table memory
+ is allocated. This type is called the allocator type. It is
+ parameterized on the value type. It provides two functions:
+
+ - A static member function named 'data_alloc'. This function
+ allocates the data elements in the table.
+
+ - A static member function named 'data_free'. This function
+ deallocates the data elements in the table.
+
+ Hash table are instantiated with two type arguments.
+
+ * The descriptor type, (2) above.
+
+ * The allocator type, (4) above. In general, you will not need to
+ provide your own allocator type. By default, hash tables will use
+ the class template xcallocator, which uses malloc/free for allocation.
+
+
+ DEFINING A DESCRIPTOR TYPE
+
+ The first task in using the hash table is to describe the element type.
+ We compose this into a few steps.
+
+ 1. Decide on a removal policy for values stored in the table.
+ hash-traits.h provides class templates for the four most common
+ policies:
+
+ * typed_free_remove implements the static 'remove' member function
+ by calling free().
+
+ * typed_noop_remove implements the static 'remove' member function
+ by doing nothing.
+
+ * ggc_remove implements the static 'remove' member by doing nothing,
+ but instead provides routines for gc marking and for PCH streaming.
+ Use this for garbage-collected data that needs to be preserved across
+ collections.
+
+ * ggc_cache_remove is like ggc_remove, except that it does not
+ mark the entries during the normal gc mark phase. Instead it
+ uses 'keep_cache_entry' (described above) to keep elements that
+ were not collected and delete those that were. Use this for
+ garbage-collected caches that should not in themselves stop
+ the data from being collected.
+
+ You can use these policies by simply deriving the descriptor type
+ from one of those class template, with the appropriate argument.
+
+ Otherwise, you need to write the static 'remove' member function
+ in the descriptor class.
+
+ 2. Choose a hash function. Write the static 'hash' member function.
+
+ 3. Decide whether the lookup function should take as input an object
+ of type value_type or something more restricted. Define compare_type
+ accordingly.
+
+ 4. Choose an equality testing function 'equal' that compares a value_type
+ and a compare_type.
+
+ If your elements are pointers, it is usually easiest to start with one
+ of the generic pointer descriptors described below and override the bits
+ you need to change.
+
+ AN EXAMPLE DESCRIPTOR TYPE
+
+ Suppose you want to put some_type into the hash table. You could define
+ the descriptor type as follows.
+
+ struct some_type_hasher : nofree_ptr_hash <some_type>
+ // Deriving from nofree_ptr_hash means that we get a 'remove' that does
+ // nothing. This choice is good for raw values.
+ {
+ static inline hashval_t hash (const value_type *);
+ static inline bool equal (const value_type *, const compare_type *);
+ };
+
+ inline hashval_t
+ some_type_hasher::hash (const value_type *e)
+ { ... compute and return a hash value for E ... }
+
+ inline bool
+ some_type_hasher::equal (const value_type *p1, const compare_type *p2)
+ { ... compare P1 vs P2. Return true if they are the 'same' ... }
+
+
+ AN EXAMPLE HASH_TABLE DECLARATION
+
+ To instantiate a hash table for some_type:
+
+ hash_table <some_type_hasher> some_type_hash_table;
+
+ There is no need to mention some_type directly, as the hash table will
+ obtain it using some_type_hasher::value_type.
+
+ You can then use any of the functions in hash_table's public interface.
+ See hash_table for details. The interface is very similar to libiberty's
+ htab_t.
+
+ If a hash table is used only in some rare cases, it is possible
+ to construct the hash_table lazily before first use. This is done
+ through:
+
+ hash_table <some_type_hasher, true> some_type_hash_table;
+
+ which will cause whatever methods actually need the allocated entries
+ array to allocate it later.
+
+
+ EASY DESCRIPTORS FOR POINTERS
+
+ There are four descriptors for pointer elements, one for each of
+ the removal policies above:
+
+ * nofree_ptr_hash (based on typed_noop_remove)
+ * free_ptr_hash (based on typed_free_remove)
+ * ggc_ptr_hash (based on ggc_remove)
+ * ggc_cache_ptr_hash (based on ggc_cache_remove)
+
+ These descriptors hash and compare elements by their pointer value,
+ rather than what they point to. So, to instantiate a hash table over
+ pointers to whatever_type, without freeing the whatever_types, use:
+
+ hash_table <nofree_ptr_hash <whatever_type> > whatever_type_hash_table;
+
+
+ HASH TABLE ITERATORS
+
+ The hash table provides standard C++ iterators. For example, consider a
+ hash table of some_info. We wish to consume each element of the table:
+
+ extern void consume (some_info *);
+
+ We define a convenience typedef and the hash table:
+
+ typedef hash_table <some_info_hasher> info_table_type;
+ info_table_type info_table;
+
+ Then we write the loop in typical C++ style:
+
+ for (info_table_type::iterator iter = info_table.begin ();
+ iter != info_table.end ();
+ ++iter)
+ if ((*iter).status == INFO_READY)
+ consume (&*iter);
+
+ Or with common sub-expression elimination:
+
+ for (info_table_type::iterator iter = info_table.begin ();
+ iter != info_table.end ();
+ ++iter)
+ {
+ some_info &elem = *iter;
+ if (elem.status == INFO_READY)
+ consume (&elem);
+ }
+
+ One can also use a more typical GCC style:
+
+ typedef some_info *some_info_p;
+ some_info *elem_ptr;
+ info_table_type::iterator iter;
+ FOR_EACH_HASH_TABLE_ELEMENT (info_table, elem_ptr, some_info_p, iter)
+ if (elem_ptr->status == INFO_READY)
+ consume (elem_ptr);
+
+*/
+
+
+#ifndef TYPED_HASHTAB_H
+#define TYPED_HASHTAB_H
+
+#include "statistics.h"
+#include "ggc.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "inchash.h"
+#include "mem-stats-traits.h"
+#include "hash-traits.h"
+#include "hash-map-traits.h"
+
+template<typename, typename, typename> class hash_map;
+template<typename, bool, typename> class hash_set;
+
+/* The ordinary memory allocator. */
+/* FIXME (crowl): This allocator may be extracted for wider sharing later. */
+
+template <typename Type>
+struct xcallocator
+{
+ static Type *data_alloc (size_t count);
+ static void data_free (Type *memory);
+};
+
+
+/* Allocate memory for COUNT data blocks. */
+
+template <typename Type>
+inline Type *
+xcallocator <Type>::data_alloc (size_t count)
+{
+ return static_cast <Type *> (xcalloc (count, sizeof (Type)));
+}
+
+
+/* Free memory for data blocks. */
+
+template <typename Type>
+inline void
+xcallocator <Type>::data_free (Type *memory)
+{
+ return ::free (memory);
+}
+
+
+/* Table of primes and their inversion information. */
+
+struct prime_ent
+{
+ hashval_t prime;
+ hashval_t inv;
+ hashval_t inv_m2; /* inverse of prime-2 */
+ hashval_t shift;
+};
+
+extern struct prime_ent const prime_tab[];
+
+/* Limit number of comparisons when calling hash_table<>::verify. */
+extern unsigned int hash_table_sanitize_eq_limit;
+
+/* Functions for computing hash table indexes. */
+
+extern unsigned int hash_table_higher_prime_index (unsigned long n)
+ ATTRIBUTE_PURE;
+
+extern ATTRIBUTE_NORETURN ATTRIBUTE_COLD void hashtab_chk_error ();
+
+/* Return X % Y using multiplicative inverse values INV and SHIFT.
+
+ The multiplicative inverses computed above are for 32-bit types,
+ and requires that we be able to compute a highpart multiply.
+
+ FIX: I am not at all convinced that
+ 3 loads, 2 multiplications, 3 shifts, and 3 additions
+ will be faster than
+ 1 load and 1 modulus
+ on modern systems running a compiler. */
+
+inline hashval_t
+mul_mod (hashval_t x, hashval_t y, hashval_t inv, int shift)
+{
+ hashval_t t1, t2, t3, t4, q, r;
+
+ t1 = ((uint64_t)x * inv) >> 32;
+ t2 = x - t1;
+ t3 = t2 >> 1;
+ t4 = t1 + t3;
+ q = t4 >> shift;
+ r = x - (q * y);
+
+ return r;
+}
+
+/* Compute the primary table index for HASH given current prime index. */
+
+inline hashval_t
+hash_table_mod1 (hashval_t hash, unsigned int index)
+{
+ const struct prime_ent *p = &prime_tab[index];
+ gcc_checking_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
+ return mul_mod (hash, p->prime, p->inv, p->shift);
+}
+
+/* Compute the secondary table index for HASH given current prime index. */
+
+inline hashval_t
+hash_table_mod2 (hashval_t hash, unsigned int index)
+{
+ const struct prime_ent *p = &prime_tab[index];
+ gcc_checking_assert (sizeof (hashval_t) * CHAR_BIT <= 32);
+ return 1 + mul_mod (hash, p->prime - 2, p->inv_m2, p->shift);
+}
+
+class mem_usage;
+
+/* User-facing hash table type.
+
+ The table stores elements of type Descriptor::value_type and uses
+ the static descriptor functions described at the top of the file
+ to hash, compare and remove elements.
+
+ Specify the template Allocator to allocate and free memory.
+ The default is xcallocator.
+
+ Storage is an implementation detail and should not be used outside the
+ hash table code.
+
+*/
+template <typename Descriptor, bool Lazy = false,
+ template<typename Type> class Allocator = xcallocator>
+class hash_table
+{
+ typedef typename Descriptor::value_type value_type;
+ typedef typename Descriptor::compare_type compare_type;
+
+public:
+ explicit hash_table (size_t, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
+ bool gather_mem_stats = GATHER_STATISTICS,
+ mem_alloc_origin origin = HASH_TABLE_ORIGIN
+ CXX_MEM_STAT_INFO);
+ explicit hash_table (const hash_table &, bool ggc = false,
+ bool sanitize_eq_and_hash = true,
+ bool gather_mem_stats = GATHER_STATISTICS,
+ mem_alloc_origin origin = HASH_TABLE_ORIGIN
+ CXX_MEM_STAT_INFO);
+ ~hash_table ();
+
+ /* Create a hash_table in gc memory. */
+ static hash_table *
+ create_ggc (size_t n, bool sanitize_eq_and_hash = true CXX_MEM_STAT_INFO)
+ {
+ hash_table *table = ggc_alloc<hash_table> ();
+ new (table) hash_table (n, true, sanitize_eq_and_hash, GATHER_STATISTICS,
+ HASH_TABLE_ORIGIN PASS_MEM_STAT);
+ return table;
+ }
+
+ /* Current size (in entries) of the hash table. */
+ size_t size () const { return m_size; }
+
+ /* Return the current number of elements in this hash table. */
+ size_t elements () const { return m_n_elements - m_n_deleted; }
+
+ /* Return the current number of elements in this hash table. */
+ size_t elements_with_deleted () const { return m_n_elements; }
+
+ /* This function clears all entries in this hash table. */
+ void empty () { if (elements ()) empty_slow (); }
+
+ /* Return true when there are no elements in this hash table. */
+ bool is_empty () const { return elements () == 0; }
+
+ /* This function clears a specified SLOT in a hash table. It is
+ useful when you've already done the lookup and don't want to do it
+ again. */
+ void clear_slot (value_type *);
+
+ /* This function searches for a hash table entry equal to the given
+ COMPARABLE element starting with the given HASH value. It cannot
+ be used to insert or delete an element. */
+ value_type &find_with_hash (const compare_type &, hashval_t);
+
+ /* Like find_slot_with_hash, but compute the hash value from the element. */
+ value_type &find (const value_type &value)
+ {
+ return find_with_hash (value, Descriptor::hash (value));
+ }
+
+ value_type *find_slot (const value_type &value, insert_option insert)
+ {
+ return find_slot_with_hash (value, Descriptor::hash (value), insert);
+ }
+
+ /* This function searches for a hash table slot containing an entry
+ equal to the given COMPARABLE element and starting with the given
+ HASH. To delete an entry, call this with insert=NO_INSERT, then
+ call clear_slot on the slot returned (possibly after doing some
+ checks). To insert an entry, call this with insert=INSERT, then
+ write the value you want into the returned slot. When inserting an
+ entry, NULL may be returned if memory allocation fails. */
+ value_type *find_slot_with_hash (const compare_type &comparable,
+ hashval_t hash, enum insert_option insert);
+
+ /* This function deletes an element with the given COMPARABLE value
+ from hash table starting with the given HASH. If there is no
+ matching element in the hash table, this function does nothing. */
+ void remove_elt_with_hash (const compare_type &, hashval_t);
+
+ /* Like remove_elt_with_hash, but compute the hash value from the
+ element. */
+ void remove_elt (const value_type &value)
+ {
+ remove_elt_with_hash (value, Descriptor::hash (value));
+ }
+
+ /* This function scans over the entire hash table calling CALLBACK for
+ each live entry. If CALLBACK returns false, the iteration stops.
+ ARGUMENT is passed as CALLBACK's second argument. */
+ template <typename Argument,
+ int (*Callback) (value_type *slot, Argument argument)>
+ void traverse_noresize (Argument argument);
+
+ /* Like traverse_noresize, but does resize the table when it is too empty
+ to improve effectivity of subsequent calls. */
+ template <typename Argument,
+ int (*Callback) (value_type *slot, Argument argument)>
+ void traverse (Argument argument);
+
+ class iterator
+ {
+ public:
+ iterator () : m_slot (NULL), m_limit (NULL) {}
+
+ iterator (value_type *slot, value_type *limit) :
+ m_slot (slot), m_limit (limit) {}
+
+ inline value_type &operator * () { return *m_slot; }
+ void slide ();
+ inline iterator &operator ++ ();
+ bool operator != (const iterator &other) const
+ {
+ return m_slot != other.m_slot || m_limit != other.m_limit;
+ }
+
+ private:
+ value_type *m_slot;
+ value_type *m_limit;
+ };
+
+ iterator begin () const
+ {
+ if (Lazy && m_entries == NULL)
+ return iterator ();
+ iterator iter (m_entries, m_entries + m_size);
+ iter.slide ();
+ return iter;
+ }
+
+ iterator end () const { return iterator (); }
+
+ double collisions () const
+ {
+ return m_searches ? static_cast <double> (m_collisions) / m_searches : 0;
+ }
+
+private:
+ /* FIXME: Make the class assignable. See pr90959. */
+ void operator= (hash_table&);
+
+ template<typename T> friend void gt_ggc_mx (hash_table<T> *);
+ template<typename T> friend void gt_pch_nx (hash_table<T> *);
+ template<typename T> friend void
+ hashtab_entry_note_pointers (void *, void *, gt_pointer_operator, void *);
+ template<typename T, typename U, typename V> friend void
+ gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
+ template<typename T, typename U>
+ friend void gt_pch_nx (hash_set<T, false, U> *, gt_pointer_operator, void *);
+ template<typename T> friend void gt_pch_nx (hash_table<T> *,
+ gt_pointer_operator, void *);
+
+ template<typename T> friend void gt_cleare_cache (hash_table<T> *);
+
+ void empty_slow ();
+
+ value_type *alloc_entries (size_t n CXX_MEM_STAT_INFO) const;
+ value_type *find_empty_slot_for_expand (hashval_t);
+ void verify (const compare_type &comparable, hashval_t hash);
+ bool too_empty_p (unsigned int);
+ void expand ();
+ static bool is_deleted (value_type &v)
+ {
+ return Descriptor::is_deleted (v);
+ }
+
+ static bool is_empty (value_type &v)
+ {
+ return Descriptor::is_empty (v);
+ }
+
+ static void mark_deleted (value_type &v)
+ {
+ Descriptor::mark_deleted (v);
+ }
+
+ static void mark_empty (value_type &v)
+ {
+ Descriptor::mark_empty (v);
+ }
+
+ /* Table itself. */
+ typename Descriptor::value_type *m_entries;
+
+ size_t m_size;
+
+ /* Current number of elements including also deleted elements. */
+ size_t m_n_elements;
+
+ /* Current number of deleted elements in the table. */
+ size_t m_n_deleted;
+
+ /* The following member is used for debugging. Its value is number
+ of all calls of `htab_find_slot' for the hash table. */
+ unsigned int m_searches;
+
+ /* The following member is used for debugging. Its value is number
+ of collisions fixed for time of work with the hash table. */
+ unsigned int m_collisions;
+
+ /* Current size (in entries) of the hash table, as an index into the
+ table of primes. */
+ unsigned int m_size_prime_index;
+
+ /* if m_entries is stored in ggc memory. */
+ bool m_ggc;
+
+ /* True if the table should be sanitized for equal and hash functions. */
+ bool m_sanitize_eq_and_hash;
+
+ /* If we should gather memory statistics for the table. */
+#if GATHER_STATISTICS
+ bool m_gather_mem_stats;
+#else
+ static const bool m_gather_mem_stats = false;
+#endif
+};
+
+/* As mem-stats.h heavily utilizes hash maps (hash tables), we have to include
+ mem-stats.h after hash_table declaration. */
+
+#include "mem-stats.h"
+#include "hash-map.h"
+
+extern mem_alloc_description<mem_usage>& hash_table_usage (void);
+
+/* Support function for statistics. */
+extern void dump_hash_table_loc_statistics (void);
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+hash_table<Descriptor, Lazy, Allocator>::hash_table (size_t size, bool ggc,
+ bool sanitize_eq_and_hash,
+ bool gather_mem_stats
+ ATTRIBUTE_UNUSED,
+ mem_alloc_origin origin
+ MEM_STAT_DECL) :
+ m_n_elements (0), m_n_deleted (0), m_searches (0), m_collisions (0),
+ m_ggc (ggc), m_sanitize_eq_and_hash (sanitize_eq_and_hash)
+#if GATHER_STATISTICS
+ , m_gather_mem_stats (gather_mem_stats)
+#endif
+{
+ unsigned int size_prime_index;
+
+ size_prime_index = hash_table_higher_prime_index (size);
+ size = prime_tab[size_prime_index].prime;
+
+ if (m_gather_mem_stats)
+ hash_table_usage ().register_descriptor (this, origin, ggc
+ FINAL_PASS_MEM_STAT);
+
+ if (Lazy)
+ m_entries = NULL;
+ else
+ m_entries = alloc_entries (size PASS_MEM_STAT);
+ m_size = size;
+ m_size_prime_index = size_prime_index;
+}
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+hash_table<Descriptor, Lazy, Allocator>::hash_table (const hash_table &h,
+ bool ggc,
+ bool sanitize_eq_and_hash,
+ bool gather_mem_stats
+ ATTRIBUTE_UNUSED,
+ mem_alloc_origin origin
+ MEM_STAT_DECL) :
+ m_n_elements (h.m_n_elements), m_n_deleted (h.m_n_deleted),
+ m_searches (0), m_collisions (0), m_ggc (ggc),
+ m_sanitize_eq_and_hash (sanitize_eq_and_hash)
+#if GATHER_STATISTICS
+ , m_gather_mem_stats (gather_mem_stats)
+#endif
+{
+ size_t size = h.m_size;
+
+ if (m_gather_mem_stats)
+ hash_table_usage ().register_descriptor (this, origin, ggc
+ FINAL_PASS_MEM_STAT);
+
+ if (Lazy && h.m_entries == NULL)
+ m_entries = NULL;
+ else
+ {
+ value_type *nentries = alloc_entries (size PASS_MEM_STAT);
+ for (size_t i = 0; i < size; ++i)
+ {
+ value_type &entry = h.m_entries[i];
+ if (is_deleted (entry))
+ mark_deleted (nentries[i]);
+ else if (!is_empty (entry))
+ new ((void*) (nentries + i)) value_type (entry);
+ }
+ m_entries = nentries;
+ }
+ m_size = size;
+ m_size_prime_index = h.m_size_prime_index;
+}
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+hash_table<Descriptor, Lazy, Allocator>::~hash_table ()
+{
+ if (!Lazy || m_entries)
+ {
+ for (size_t i = m_size - 1; i < m_size; i--)
+ if (!is_empty (m_entries[i]) && !is_deleted (m_entries[i]))
+ Descriptor::remove (m_entries[i]);
+
+ if (!m_ggc)
+ Allocator <value_type> ::data_free (m_entries);
+ else
+ ggc_free (m_entries);
+ if (m_gather_mem_stats)
+ hash_table_usage ().release_instance_overhead (this,
+ sizeof (value_type)
+ * m_size, true);
+ }
+ else if (m_gather_mem_stats)
+ hash_table_usage ().unregister_descriptor (this);
+}
+
+/* This function returns an array of empty hash table elements. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+inline typename hash_table<Descriptor, Lazy, Allocator>::value_type *
+hash_table<Descriptor, Lazy,
+ Allocator>::alloc_entries (size_t n MEM_STAT_DECL) const
+{
+ value_type *nentries;
+
+ if (m_gather_mem_stats)
+ hash_table_usage ().register_instance_overhead (sizeof (value_type) * n, this);
+
+ if (!m_ggc)
+ nentries = Allocator <value_type> ::data_alloc (n);
+ else
+ nentries = ::ggc_cleared_vec_alloc<value_type> (n PASS_MEM_STAT);
+
+ gcc_assert (nentries != NULL);
+ if (!Descriptor::empty_zero_p)
+ for (size_t i = 0; i < n; i++)
+ mark_empty (nentries[i]);
+
+ return nentries;
+}
+
+/* Similar to find_slot, but without several unwanted side effects:
+ - Does not call equal when it finds an existing entry.
+ - Does not change the count of elements/searches/collisions in the
+ hash table.
+ This function also assumes there are no deleted entries in the table.
+ HASH is the hash value for the element to be inserted. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+typename hash_table<Descriptor, Lazy, Allocator>::value_type *
+hash_table<Descriptor, Lazy,
+ Allocator>::find_empty_slot_for_expand (hashval_t hash)
+{
+ hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
+ size_t size = m_size;
+ value_type *slot = m_entries + index;
+ hashval_t hash2;
+
+ if (is_empty (*slot))
+ return slot;
+ gcc_checking_assert (!is_deleted (*slot));
+
+ hash2 = hash_table_mod2 (hash, m_size_prime_index);
+ for (;;)
+ {
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ slot = m_entries + index;
+ if (is_empty (*slot))
+ return slot;
+ gcc_checking_assert (!is_deleted (*slot));
+ }
+}
+
+/* Return true if the current table is excessively big for ELTS elements. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+inline bool
+hash_table<Descriptor, Lazy, Allocator>::too_empty_p (unsigned int elts)
+{
+ return elts * 8 < m_size && m_size > 32;
+}
+
+/* The following function changes size of memory allocated for the
+ entries and repeatedly inserts the table elements. The occupancy
+ of the table after the call will be about 50%. Naturally the hash
+ table must already exist. Remember also that the place of the
+ table entries is changed. If memory allocation fails, this function
+ will abort. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>::expand ()
+{
+ value_type *oentries = m_entries;
+ unsigned int oindex = m_size_prime_index;
+ size_t osize = size ();
+ value_type *olimit = oentries + osize;
+ size_t elts = elements ();
+
+ /* Resize only when table after removal of unused elements is either
+ too full or too empty. */
+ unsigned int nindex;
+ size_t nsize;
+ if (elts * 2 > osize || too_empty_p (elts))
+ {
+ nindex = hash_table_higher_prime_index (elts * 2);
+ nsize = prime_tab[nindex].prime;
+ }
+ else
+ {
+ nindex = oindex;
+ nsize = osize;
+ }
+
+ value_type *nentries = alloc_entries (nsize);
+
+ if (m_gather_mem_stats)
+ hash_table_usage ().release_instance_overhead (this, sizeof (value_type)
+ * osize);
+
+ m_entries = nentries;
+ m_size = nsize;
+ m_size_prime_index = nindex;
+ m_n_elements -= m_n_deleted;
+ m_n_deleted = 0;
+
+ value_type *p = oentries;
+ do
+ {
+ value_type &x = *p;
+
+ if (!is_empty (x) && !is_deleted (x))
+ {
+ value_type *q = find_empty_slot_for_expand (Descriptor::hash (x));
+ new ((void*) q) value_type (std::move (x));
+ /* After the resources of 'x' have been moved to a new object at 'q',
+ we now have to destroy the 'x' object, to end its lifetime. */
+ x.~value_type ();
+ }
+
+ p++;
+ }
+ while (p < olimit);
+
+ if (!m_ggc)
+ Allocator <value_type> ::data_free (oentries);
+ else
+ ggc_free (oentries);
+}
+
+/* Implements empty() in cases where it isn't a no-op. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>::empty_slow ()
+{
+ size_t size = m_size;
+ size_t nsize = size;
+ value_type *entries = m_entries;
+
+ for (size_t i = size - 1; i < size; i--)
+ if (!is_empty (entries[i]) && !is_deleted (entries[i]))
+ Descriptor::remove (entries[i]);
+
+ /* Instead of clearing megabyte, downsize the table. */
+ if (size > 1024*1024 / sizeof (value_type))
+ nsize = 1024 / sizeof (value_type);
+ else if (too_empty_p (m_n_elements))
+ nsize = m_n_elements * 2;
+
+ if (nsize != size)
+ {
+ unsigned int nindex = hash_table_higher_prime_index (nsize);
+
+ nsize = prime_tab[nindex].prime;
+
+ if (!m_ggc)
+ Allocator <value_type> ::data_free (m_entries);
+ else
+ ggc_free (m_entries);
+
+ m_entries = alloc_entries (nsize);
+ m_size = nsize;
+ m_size_prime_index = nindex;
+ }
+ else if (Descriptor::empty_zero_p)
+ memset ((void *) entries, 0, size * sizeof (value_type));
+ else
+ for (size_t i = 0; i < size; i++)
+ mark_empty (entries[i]);
+
+ m_n_deleted = 0;
+ m_n_elements = 0;
+}
+
+/* This function clears a specified SLOT in a hash table. It is
+ useful when you've already done the lookup and don't want to do it
+ again. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>::clear_slot (value_type *slot)
+{
+ gcc_checking_assert (!(slot < m_entries || slot >= m_entries + size ()
+ || is_empty (*slot) || is_deleted (*slot)));
+
+ Descriptor::remove (*slot);
+
+ mark_deleted (*slot);
+ m_n_deleted++;
+}
+
+/* This function searches for a hash table entry equal to the given
+ COMPARABLE element starting with the given HASH value. It cannot
+ be used to insert or delete an element. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+typename hash_table<Descriptor, Lazy, Allocator>::value_type &
+hash_table<Descriptor, Lazy, Allocator>
+::find_with_hash (const compare_type &comparable, hashval_t hash)
+{
+ m_searches++;
+ size_t size = m_size;
+ hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
+
+ if (Lazy && m_entries == NULL)
+ m_entries = alloc_entries (size);
+
+#if CHECKING_P
+ if (m_sanitize_eq_and_hash)
+ verify (comparable, hash);
+#endif
+
+ value_type *entry = &m_entries[index];
+ if (is_empty (*entry)
+ || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
+ return *entry;
+
+ hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
+ for (;;)
+ {
+ m_collisions++;
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ entry = &m_entries[index];
+ if (is_empty (*entry)
+ || (!is_deleted (*entry) && Descriptor::equal (*entry, comparable)))
+ return *entry;
+ }
+}
+
+/* This function searches for a hash table slot containing an entry
+ equal to the given COMPARABLE element and starting with the given
+ HASH. To delete an entry, call this with insert=NO_INSERT, then
+ call clear_slot on the slot returned (possibly after doing some
+ checks). To insert an entry, call this with insert=INSERT, then
+ write the value you want into the returned slot. When inserting an
+ entry, NULL may be returned if memory allocation fails. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+typename hash_table<Descriptor, Lazy, Allocator>::value_type *
+hash_table<Descriptor, Lazy, Allocator>
+::find_slot_with_hash (const compare_type &comparable, hashval_t hash,
+ enum insert_option insert)
+{
+ if (Lazy && m_entries == NULL)
+ {
+ if (insert == INSERT)
+ m_entries = alloc_entries (m_size);
+ else
+ return NULL;
+ }
+ if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
+ expand ();
+
+#if CHECKING_P
+ if (m_sanitize_eq_and_hash)
+ verify (comparable, hash);
+#endif
+
+ m_searches++;
+ value_type *first_deleted_slot = NULL;
+ hashval_t index = hash_table_mod1 (hash, m_size_prime_index);
+ hashval_t hash2 = hash_table_mod2 (hash, m_size_prime_index);
+ value_type *entry = &m_entries[index];
+ size_t size = m_size;
+ if (is_empty (*entry))
+ goto empty_entry;
+ else if (is_deleted (*entry))
+ first_deleted_slot = &m_entries[index];
+ else if (Descriptor::equal (*entry, comparable))
+ return &m_entries[index];
+
+ for (;;)
+ {
+ m_collisions++;
+ index += hash2;
+ if (index >= size)
+ index -= size;
+
+ entry = &m_entries[index];
+ if (is_empty (*entry))
+ goto empty_entry;
+ else if (is_deleted (*entry))
+ {
+ if (!first_deleted_slot)
+ first_deleted_slot = &m_entries[index];
+ }
+ else if (Descriptor::equal (*entry, comparable))
+ return &m_entries[index];
+ }
+
+ empty_entry:
+ if (insert == NO_INSERT)
+ return NULL;
+
+ if (first_deleted_slot)
+ {
+ m_n_deleted--;
+ mark_empty (*first_deleted_slot);
+ return first_deleted_slot;
+ }
+
+ m_n_elements++;
+ return &m_entries[index];
+}
+
+/* Verify that all existing elements in th hash table which are
+ equal to COMPARABLE have an equal HASH value provided as argument. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>
+::verify (const compare_type &comparable, hashval_t hash)
+{
+ for (size_t i = 0; i < MIN (hash_table_sanitize_eq_limit, m_size); i++)
+ {
+ value_type *entry = &m_entries[i];
+ if (!is_empty (*entry) && !is_deleted (*entry)
+ && hash != Descriptor::hash (*entry)
+ && Descriptor::equal (*entry, comparable))
+ hashtab_chk_error ();
+ }
+}
+
+/* This function deletes an element with the given COMPARABLE value
+ from hash table starting with the given HASH. If there is no
+ matching element in the hash table, this function does nothing. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>
+::remove_elt_with_hash (const compare_type &comparable, hashval_t hash)
+{
+ value_type *slot = find_slot_with_hash (comparable, hash, NO_INSERT);
+ if (slot == NULL)
+ return;
+
+ Descriptor::remove (*slot);
+
+ mark_deleted (*slot);
+ m_n_deleted++;
+}
+
+/* This function scans over the entire hash table calling CALLBACK for
+ each live entry. If CALLBACK returns false, the iteration stops.
+ ARGUMENT is passed as CALLBACK's second argument. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+template<typename Argument,
+ int (*Callback)
+ (typename hash_table<Descriptor, Lazy, Allocator>::value_type *slot,
+ Argument argument)>
+void
+hash_table<Descriptor, Lazy, Allocator>::traverse_noresize (Argument argument)
+{
+ if (Lazy && m_entries == NULL)
+ return;
+
+ value_type *slot = m_entries;
+ value_type *limit = slot + size ();
+
+ do
+ {
+ value_type &x = *slot;
+
+ if (!is_empty (x) && !is_deleted (x))
+ if (! Callback (slot, argument))
+ break;
+ }
+ while (++slot < limit);
+}
+
+/* Like traverse_noresize, but does resize the table when it is too empty
+ to improve effectivity of subsequent calls. */
+
+template <typename Descriptor, bool Lazy,
+ template <typename Type> class Allocator>
+template <typename Argument,
+ int (*Callback)
+ (typename hash_table<Descriptor, Lazy, Allocator>::value_type *slot,
+ Argument argument)>
+void
+hash_table<Descriptor, Lazy, Allocator>::traverse (Argument argument)
+{
+ if (too_empty_p (elements ()) && (!Lazy || m_entries))
+ expand ();
+
+ traverse_noresize <Argument, Callback> (argument);
+}
+
+/* Slide down the iterator slots until an active entry is found. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+void
+hash_table<Descriptor, Lazy, Allocator>::iterator::slide ()
+{
+ for ( ; m_slot < m_limit; ++m_slot )
+ {
+ value_type &x = *m_slot;
+ if (!is_empty (x) && !is_deleted (x))
+ return;
+ }
+ m_slot = NULL;
+ m_limit = NULL;
+}
+
+/* Bump the iterator. */
+
+template<typename Descriptor, bool Lazy,
+ template<typename Type> class Allocator>
+inline typename hash_table<Descriptor, Lazy, Allocator>::iterator &
+hash_table<Descriptor, Lazy, Allocator>::iterator::operator ++ ()
+{
+ ++m_slot;
+ slide ();
+ return *this;
+}
+
+
+/* Iterate through the elements of hash_table HTAB,
+ using hash_table <....>::iterator ITER,
+ storing each element in RESULT, which is of type TYPE. */
+
+#define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \
+ for ((ITER) = (HTAB).begin (); \
+ (ITER) != (HTAB).end () ? (RESULT = *(ITER) , true) : false; \
+ ++(ITER))
+
+/* ggc walking routines. */
+
+template<typename E>
+static inline void
+gt_ggc_mx (hash_table<E> *h)
+{
+ typedef hash_table<E> table;
+
+ if (!ggc_test_and_set_mark (h->m_entries))
+ return;
+
+ for (size_t i = 0; i < h->m_size; i++)
+ {
+ if (table::is_empty (h->m_entries[i])
+ || table::is_deleted (h->m_entries[i]))
+ continue;
+
+ /* Use ggc_maxbe_mx so we don't mark right away for cache tables; we'll
+ mark in gt_cleare_cache if appropriate. */
+ E::ggc_maybe_mx (h->m_entries[i]);
+ }
+}
+
+template<typename D>
+static inline void
+hashtab_entry_note_pointers (void *obj, void *h, gt_pointer_operator op,
+ void *cookie)
+{
+ hash_table<D> *map = static_cast<hash_table<D> *> (h);
+ gcc_checking_assert (map->m_entries == obj);
+ for (size_t i = 0; i < map->m_size; i++)
+ {
+ typedef hash_table<D> table;
+ if (table::is_empty (map->m_entries[i])
+ || table::is_deleted (map->m_entries[i]))
+ continue;
+
+ D::pch_nx (map->m_entries[i], op, cookie);
+ }
+}
+
+template<typename D>
+static void
+gt_pch_nx (hash_table<D> *h)
+{
+ bool success
+ = gt_pch_note_object (h->m_entries, h, hashtab_entry_note_pointers<D>);
+ gcc_checking_assert (success);
+ for (size_t i = 0; i < h->m_size; i++)
+ {
+ if (hash_table<D>::is_empty (h->m_entries[i])
+ || hash_table<D>::is_deleted (h->m_entries[i]))
+ continue;
+
+ D::pch_nx (h->m_entries[i]);
+ }
+}
+
+template<typename D>
+static inline void
+gt_pch_nx (hash_table<D> *h, gt_pointer_operator op, void *cookie)
+{
+ op (&h->m_entries, NULL, cookie);
+}
+
+template<typename H>
+inline void
+gt_cleare_cache (hash_table<H> *h)
+{
+ typedef hash_table<H> table;
+ if (!h)
+ return;
+
+ for (typename table::iterator iter = h->begin (); iter != h->end (); ++iter)
+ if (!table::is_empty (*iter) && !table::is_deleted (*iter))
+ {
+ int res = H::keep_cache_entry (*iter);
+ if (res == 0)
+ h->clear_slot (&*iter);
+ else if (res != -1)
+ H::ggc_mx (*iter);
+ }
+}
+
+#endif /* TYPED_HASHTAB_H */
diff --git a/support/cpp/gcc/hash-traits.h b/support/cpp/gcc/hash-traits.h
new file mode 100644
index 000000000..bef0bd42d
--- /dev/null
+++ b/support/cpp/gcc/hash-traits.h
@@ -0,0 +1,406 @@
+/* Traits for hashable types.
+ Copyright (C) 2014-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 hash_traits_h
+#define hash_traits_h
+
+/* Helpful type for removing with free. */
+
+template <typename Type>
+struct typed_free_remove
+{
+ static inline void remove (Type *p);
+};
+
+template <typename Type>
+struct typed_const_free_remove
+{
+ static inline void remove (const Type *p);
+};
+
+/* Remove with free. */
+
+template <typename Type>
+inline void
+typed_free_remove <Type>::remove (Type *p)
+{
+ free (p);
+}
+
+template <typename Type>
+inline void
+typed_const_free_remove <Type>::remove (const Type *p)
+{
+ free (const_cast <Type *> (p));
+}
+
+/* Helpful type for removing with delete. */
+
+template <typename Type>
+struct typed_delete_remove
+{
+ static inline void remove (Type *p);
+};
+
+
+/* Remove with delete. */
+
+template <typename Type>
+inline void
+typed_delete_remove <Type>::remove (Type *p)
+{
+ delete p;
+}
+
+/* Helpful type for a no-op remove. */
+
+template <typename Type>
+struct typed_noop_remove
+{
+ static inline void remove (Type &);
+};
+
+
+/* Remove doing nothing. */
+
+template <typename Type>
+inline void
+typed_noop_remove <Type>::remove (Type &)
+{
+}
+
+
+/* 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>
+{
+ 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>
+inline hashval_t
+int_hash <Type, Empty, Deleted>::hash (value_type x)
+{
+ return x;
+}
+
+template <typename Type, Type Empty, Type Deleted>
+inline bool
+int_hash <Type, Empty, Deleted>::equal (value_type x, value_type y)
+{
+ return x == y;
+}
+
+template <typename Type, Type Empty, Type Deleted>
+inline void
+int_hash <Type, Empty, Deleted>::mark_deleted (Type &x)
+{
+ gcc_assert (Empty != Deleted);
+ x = Deleted;
+}
+
+template <typename Type, Type Empty, Type Deleted>
+inline void
+int_hash <Type, Empty, Deleted>::mark_empty (Type &x)
+{
+ x = Empty;
+}
+
+template <typename Type, Type Empty, Type Deleted>
+inline bool
+int_hash <Type, Empty, Deleted>::is_deleted (Type x)
+{
+ return Empty != Deleted && x == Deleted;
+}
+
+template <typename Type, Type Empty, Type Deleted>
+inline bool
+int_hash <Type, Empty, Deleted>::is_empty (Type x)
+{
+ return x == Empty;
+}
+
+/* Pointer hasher based on pointer equality. Other types of pointer hash
+ can inherit this and override the hash and equal functions with some
+ other form of equality (such as string equality). */
+
+template <typename Type>
+struct pointer_hash
+{
+ typedef Type *value_type;
+ typedef Type *compare_type;
+
+ static inline hashval_t hash (const value_type &);
+ static inline bool equal (const value_type &existing,
+ const compare_type &candidate);
+ static inline void mark_deleted (Type *&);
+ static const bool empty_zero_p = true;
+ static inline void mark_empty (Type *&);
+ static inline bool is_deleted (Type *);
+ static inline bool is_empty (Type *);
+};
+
+template <typename Type>
+inline hashval_t
+pointer_hash <Type>::hash (const value_type &candidate)
+{
+ /* This is a really poor hash function, but it is what the current code uses,
+ so I am reusing it to avoid an additional axis in testing. */
+ return (hashval_t) ((intptr_t)candidate >> 3);
+}
+
+template <typename Type>
+inline bool
+pointer_hash <Type>::equal (const value_type &existing,
+ const compare_type &candidate)
+{
+ return existing == candidate;
+}
+
+template <typename Type>
+inline void
+pointer_hash <Type>::mark_deleted (Type *&e)
+{
+ e = reinterpret_cast<Type *> (1);
+}
+
+template <typename Type>
+inline void
+pointer_hash <Type>::mark_empty (Type *&e)
+{
+ e = NULL;
+}
+
+template <typename Type>
+inline bool
+pointer_hash <Type>::is_deleted (Type *e)
+{
+ return e == reinterpret_cast<Type *> (1);
+}
+
+template <typename Type>
+inline bool
+pointer_hash <Type>::is_empty (Type *e)
+{
+ return e == NULL;
+}
+
+/* Hasher for "const char *" strings, using string rather than pointer
+ equality. */
+
+struct string_hash : pointer_hash <const char>
+{
+ static inline hashval_t hash (const char *);
+ static inline bool equal (const char *, const char *);
+};
+
+inline hashval_t
+string_hash::hash (const char *id)
+{
+ return htab_hash_string (id);
+}
+
+inline bool
+string_hash::equal (const char *id1, const char *id2)
+{
+ return strcmp (id1, id2) == 0;
+}
+
+/* Remover and marker for entries in gc memory. */
+
+template<typename T>
+struct ggc_remove
+{
+ static void remove (T &) {}
+
+ static void
+ ggc_mx (T &p)
+ {
+ extern void gt_ggc_mx (T &);
+ gt_ggc_mx (p);
+ }
+
+ /* Overridden in ggc_cache_remove. */
+ static void
+ ggc_maybe_mx (T &p)
+ {
+ ggc_mx (p);
+ }
+
+ static void
+ pch_nx (T &p)
+ {
+ extern void gt_pch_nx (T &);
+ gt_pch_nx (p);
+ }
+
+ static void
+ pch_nx (T &p, gt_pointer_operator op, void *cookie)
+ {
+ op (&p, NULL, cookie);
+ }
+};
+
+/* Remover and marker for "cache" entries in gc memory. These entries can
+ be deleted if there are no non-cache references to the data. */
+
+template<typename T>
+struct ggc_cache_remove : ggc_remove<T>
+{
+ /* Entries are weakly held because this is for caches. */
+ static void ggc_maybe_mx (T &) {}
+
+ static int
+ keep_cache_entry (T &e)
+ {
+ return ggc_marked_p (e) ? -1 : 0;
+ }
+};
+
+/* Traits for pointer elements that should not be freed when an element
+ is deleted. */
+
+template <typename T>
+struct nofree_ptr_hash : pointer_hash <T>, typed_noop_remove <T *> {};
+
+/* Traits for pointer elements that should be freed via free() when an
+ element is deleted. */
+
+template <typename T>
+struct free_ptr_hash : pointer_hash <T>, typed_free_remove <T> {};
+
+/* Traits for pointer elements that should be freed via delete operand when an
+ element is deleted. */
+
+template <typename T>
+struct delete_ptr_hash : pointer_hash <T>, typed_delete_remove <T> {};
+
+/* Traits for elements that point to gc memory. The pointed-to data
+ must be kept across collections. */
+
+template <typename T>
+struct ggc_ptr_hash : pointer_hash <T>, ggc_remove <T *> {};
+
+/* Traits for elements that point to gc memory. The elements don't
+ in themselves keep the pointed-to data alive and they can be deleted
+ if the pointed-to data is going to be collected. */
+
+template <typename T>
+struct ggc_cache_ptr_hash : pointer_hash <T>, ggc_cache_remove <T *> {};
+
+/* Traits for string elements that should be freed when an element is
+ deleted. */
+
+struct free_string_hash : string_hash, typed_const_free_remove <char> {};
+
+/* Traits for string elements that should not be freed when an element
+ is deleted. */
+
+struct nofree_string_hash : string_hash, typed_noop_remove <const char *> {};
+
+/* Traits for pairs of values, using the first to record empty and
+ deleted slots. */
+
+template <typename T1, typename T2>
+struct pair_hash
+{
+ typedef std::pair <typename T1::value_type,
+ typename T2::value_type> value_type;
+ typedef std::pair <typename T1::compare_type,
+ typename T2::compare_type> compare_type;
+
+ static inline hashval_t hash (const value_type &);
+ static inline bool equal (const value_type &, const compare_type &);
+ static inline void remove (value_type &);
+ static inline void mark_deleted (value_type &);
+ static const bool empty_zero_p = T1::empty_zero_p;
+ static inline void mark_empty (value_type &);
+ static inline bool is_deleted (const value_type &);
+ static inline bool is_empty (const value_type &);
+};
+
+template <typename T1, typename T2>
+inline hashval_t
+pair_hash <T1, T2>::hash (const value_type &x)
+{
+ return iterative_hash_hashval_t (T1::hash (x.first), T2::hash (x.second));
+}
+
+template <typename T1, typename T2>
+inline bool
+pair_hash <T1, T2>::equal (const value_type &x, const compare_type &y)
+{
+ return T1::equal (x.first, y.first) && T2::equal (x.second, y.second);
+}
+
+template <typename T1, typename T2>
+inline void
+pair_hash <T1, T2>::remove (value_type &x)
+{
+ T1::remove (x.first);
+ T2::remove (x.second);
+}
+
+template <typename T1, typename T2>
+inline void
+pair_hash <T1, T2>::mark_deleted (value_type &x)
+{
+ T1::mark_deleted (x.first);
+}
+
+template <typename T1, typename T2>
+inline void
+pair_hash <T1, T2>::mark_empty (value_type &x)
+{
+ T1::mark_empty (x.first);
+}
+
+template <typename T1, typename T2>
+inline bool
+pair_hash <T1, T2>::is_deleted (const value_type &x)
+{
+ return T1::is_deleted (x.first);
+}
+
+template <typename T1, typename T2>
+inline bool
+pair_hash <T1, T2>::is_empty (const value_type &x)
+{
+ return T1::is_empty (x.first);
+}
+
+template <typename T> struct default_hash_traits : T {};
+
+template <typename T>
+struct default_hash_traits <T *> : ggc_ptr_hash <T> {};
+
+#endif
diff --git a/support/cpp/gcc/highlev-plugin-common.h b/support/cpp/gcc/highlev-plugin-common.h
new file mode 100644
index 000000000..bfa2cab38
--- /dev/null
+++ b/support/cpp/gcc/highlev-plugin-common.h
@@ -0,0 +1,33 @@
+/* Interface for high-level plugins in GCC - Parts common between GCC,
+ ICI and high-level plugins.
+
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
+
+ Contributed by INRIA.
+
+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 HIGHLEV_PLUGIN_COMMON_H
+#define HIGHLEV_PLUGIN_COMMON_H
+
+/* Return codes for invoke_plugin_callbacks / call_plugin_event . */
+#define PLUGEVT_SUCCESS 0
+#define PLUGEVT_NO_EVENTS 1
+#define PLUGEVT_NO_SUCH_EVENT 2
+#define PLUGEVT_NO_CALLBACK 3
+
+#endif /* HIGHLEV_PLUGIN_COMMON_H */
diff --git a/support/cpp/gcc/hooks.cc b/support/cpp/gcc/hooks.cc
new file mode 100644
index 000000000..d8f6929b7
--- /dev/null
+++ b/support/cpp/gcc/hooks.cc
@@ -0,0 +1,573 @@
+/* General-purpose hooks.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+/* This file contains generic hooks that can be used as defaults for
+ target or language-dependent hook initializers. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "hooks.h"
+
+/* Generic hook that does absolutely zappo. */
+void
+hook_void_void (void)
+{
+}
+
+/* Generic hook that takes no arguments and returns false. */
+bool
+hook_bool_void_false (void)
+{
+ return false;
+}
+
+/* Generic hook that takes no arguments and returns true. */
+bool
+hook_bool_void_true (void)
+{
+ return true;
+}
+
+/* Generic hook that takes (bool) and returns false. */
+bool
+hook_bool_bool_false (bool)
+{
+ return false;
+}
+
+/* Generic hook that takes (bool, struct gcc_options *) and returns false. */
+bool
+hook_bool_bool_gcc_optionsp_false (bool, struct gcc_options *)
+{
+ return false;
+}
+
+/* Generic hook that takes const int, const int) and returns true. */
+bool hook_bool_const_int_const_int_true (const int, const int)
+{
+ return true;
+}
+
+/* Generic hook that takes (machine_mode) and returns false. */
+bool
+hook_bool_mode_false (machine_mode)
+{
+ return false;
+}
+
+/* Generic hook that takes (machine_mode) and returns true. */
+bool
+hook_bool_mode_true (machine_mode)
+{
+ return true;
+}
+
+/* Generic hook that takes (machine_mode, machine_mode) and returns true. */
+bool
+hook_bool_mode_mode_true (machine_mode, machine_mode)
+{
+ return true;
+}
+
+/* Generic hook that takes (machine_mode, const_rtx) and returns false. */
+bool
+hook_bool_mode_const_rtx_false (machine_mode, const_rtx)
+{
+ return false;
+}
+
+/* Generic hook that takes (machine_mode, const_rtx) and returns true. */
+bool
+hook_bool_mode_const_rtx_true (machine_mode, const_rtx)
+{
+ return true;
+}
+
+/* Generic hook that takes (machine_mode, rtx) and returns false. */
+bool
+hook_bool_mode_rtx_false (machine_mode, rtx)
+{
+ return false;
+}
+
+/* Generic hook that takes (machine_mode, rtx) and returns true. */
+bool
+hook_bool_mode_rtx_true (machine_mode, rtx)
+{
+ return true;
+}
+
+/* Generic hook that takes (const rtx_insn *, const rtx_insn *) and returns true. */
+bool
+hook_bool_const_rtx_insn_const_rtx_insn_true (const rtx_insn *,
+ const rtx_insn *)
+{
+ return true;
+}
+
+/* Generic hook that takes (machine_mode, unsigned HOST_WIDE_INT)
+ and returns false. */
+bool
+hook_bool_mode_uhwi_false (machine_mode, unsigned HOST_WIDE_INT)
+{
+ return false;
+}
+
+/* Generic hook that takes (poly_uint64, poly_uint64) and returns true. */
+// sdcpp bool
+// sdcpp hook_bool_puint64_puint64_true (poly_uint64, poly_uint64)
+// sdcpp {
+// sdcpp return true;
+// sdcpp }
+
+bool
+hook_bool_uint_uint_mode_false (unsigned int, unsigned int, machine_mode)
+{
+ return false;
+}
+
+/* Generic hook that takes (unsigned int, machine_mode) and returns true. */
+bool
+hook_bool_uint_mode_true (unsigned int, machine_mode)
+{
+ return true;
+}
+
+/* Generic hook that takes (FILE *, const char *) and does nothing. */
+void
+hook_void_FILEptr_constcharptr (FILE *, const char *)
+{
+}
+
+/* Generic hook that takes (FILE *, const char *, constr_tree *) and does
+ nothing. */
+void
+hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *, const_tree)
+{
+}
+
+/* Generic hook that takes (FILE *, rtx) and returns false. */
+bool
+hook_bool_FILEptr_rtx_false (FILE *, rtx)
+{
+ return false;
+}
+
+/* Generic hook that takes (gimple_stmt_iterator *) and returns
+ false. */
+bool
+hook_bool_gsiptr_false (gimple_stmt_iterator *)
+{
+ return false;
+}
+
+/* Used for the TARGET_ASM_CAN_OUTPUT_MI_THUNK hook. */
+bool
+hook_bool_const_tree_hwi_hwi_const_tree_false (const_tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, const_tree)
+{
+ return false;
+}
+
+bool
+hook_bool_const_tree_hwi_hwi_const_tree_true (const_tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, const_tree)
+{
+ return true;
+}
+
+bool
+default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT,
+ HOST_WIDE_INT c, const_tree)
+{
+ return c == 0;
+}
+
+int
+hook_int_uint_mode_1 (unsigned int, machine_mode)
+{
+ return 1;
+}
+
+int
+hook_int_const_tree_0 (const_tree)
+{
+ return 0;
+}
+
+/* ??? Used for comp_type_attributes, which ought to return bool. */
+int
+hook_int_const_tree_const_tree_1 (const_tree, const_tree)
+{
+ return 1;
+}
+
+int
+hook_int_rtx_0 (rtx)
+{
+ return 0;
+}
+
+int
+hook_int_rtx_1 (rtx)
+{
+ return 1;
+}
+
+int
+hook_int_rtx_insn_0 (rtx_insn *)
+{
+ return 0;
+}
+
+int
+hook_int_rtx_insn_unreachable (rtx_insn *)
+{
+ gcc_unreachable ();
+}
+
+int
+hook_int_rtx_bool_0 (rtx, bool)
+{
+ return 0;
+}
+
+int
+hook_int_rtx_mode_as_bool_0 (rtx, machine_mode, addr_space_t, bool)
+{
+ return 0;
+}
+
+unsigned int
+hook_uint_void_0 (void)
+{
+ return 0;
+}
+
+HOST_WIDE_INT
+hook_hwi_void_0 (void)
+{
+ return 0;
+}
+
+void
+hook_void_tree (tree)
+{
+}
+
+void
+hook_void_FILEptr_tree (FILE *, tree)
+{
+}
+
+void
+hook_void_rtx_tree (rtx, tree)
+{
+}
+
+void
+hook_void_constcharptr (const char *)
+{
+}
+
+void
+hook_void_tree_treeptr (tree, tree *)
+{
+}
+
+void
+hook_void_int_int (int, int)
+{
+}
+
+bool
+hook_bool_tree_false (tree)
+{
+ return false;
+}
+
+bool
+hook_bool_const_tree_false (const_tree)
+{
+ return false;
+}
+
+bool
+hook_bool_const_tree_const_tree_true (const_tree, const_tree)
+{
+ return true;
+}
+
+bool
+hook_bool_tree_true (tree)
+{
+ return true;
+}
+
+bool
+hook_bool_const_tree_true (const_tree)
+{
+ return true;
+}
+
+bool
+hook_bool_tree_tree_false (tree, tree)
+{
+ return false;
+}
+
+bool
+hook_bool_tree_tree_true (tree, tree)
+{
+ return true;
+}
+
+bool
+hook_bool_tree_bool_false (tree, bool)
+{
+ return false;
+}
+
+bool
+hook_bool_rtx_insn_true (rtx_insn *)
+{
+ return true;
+}
+
+bool
+hook_bool_rtx_false (rtx)
+{
+ return false;
+}
+
+bool
+hook_bool_uintp_uintp_false (unsigned int *, unsigned int *)
+{
+ return false;
+}
+
+bool
+hook_bool_rtx_mode_int_int_intp_bool_false (rtx, machine_mode, int, int,
+ int *, bool)
+{
+ return false;
+}
+
+#if 0 // sdcpp
+bool
+hook_bool_wint_wint_uint_bool_true (const widest_int &, const widest_int &,
+ unsigned int, bool)
+{
+ return true;
+}
+#endif // sdcpp
+
+/* Generic hook that takes an rtx and returns it. */
+rtx
+hook_rtx_rtx_identity (rtx x)
+{
+ return x;
+}
+
+/* Generic hook that takes an rtx and returns NULL_RTX. */
+rtx
+hook_rtx_rtx_null (rtx)
+{
+ return NULL;
+}
+
+/* Generic hook that takes a tree and an int and returns NULL_RTX. */
+rtx
+hook_rtx_tree_int_null (tree, int)
+{
+ return NULL;
+}
+
+/* Generic hook that takes a machine mode and returns an unsigned int 0. */
+unsigned int
+hook_uint_mode_0 (machine_mode)
+{
+ return 0;
+}
+
+/* Generic hook that takes no arguments and returns a NULL const string. */
+const char *
+hook_constcharptr_void_null (void)
+{
+ return NULL;
+}
+
+/* Generic hook that takes no arguments and returns a NULL string. */
+char *
+hook_charptr_void_null (void)
+{
+ return NULL;
+}
+
+/* Generic hook that takes a tree and returns a NULL string. */
+const char *
+hook_constcharptr_const_tree_null (const_tree)
+{
+ return NULL;
+}
+
+tree
+hook_tree_tree_int_treep_bool_null (tree, int, tree *, bool)
+{
+ return NULL;
+}
+
+tree
+hook_tree_tree_bool_null (tree, bool)
+{
+ return NULL;
+}
+
+tree
+hook_tree_tree_tree_null (tree, tree)
+{
+ return NULL;
+}
+
+tree
+hook_tree_tree_tree_tree_null (tree, tree, tree)
+{
+ return NULL;
+}
+
+tree
+hook_tree_treeptr_tree_tree_int_boolptr_null (tree *, tree, tree, int, bool *)
+{
+ return NULL;
+}
+
+/* Generic hook that takes an rtx_insn *and returns a NULL string. */
+const char *
+hook_constcharptr_const_rtx_insn_null (const rtx_insn *)
+{
+ return NULL;
+}
+
+const char *
+hook_constcharptr_const_tree_const_tree_null (const_tree, const_tree)
+{
+ return NULL;
+}
+
+const char *
+hook_constcharptr_int_const_tree_null (int, const_tree)
+{
+ return NULL;
+}
+
+const char *
+hook_constcharptr_int_const_tree_const_tree_null (int, const_tree, const_tree)
+{
+ return NULL;
+}
+
+/* Generic hook that takes a const_tree and returns NULL_TREE. */
+tree
+hook_tree_const_tree_null (const_tree)
+{
+ return NULL;
+}
+
+/* Generic hook that takes no arguments and returns a NULL_TREE. */
+tree
+hook_tree_void_null (void)
+{
+ return NULL;
+}
+
+/* Generic hook that takes a rtx_insn * and an int and returns a bool. */
+
+bool
+hook_bool_rtx_insn_int_false (rtx_insn *, int)
+{
+ return false;
+}
+
+/* Generic hook that takes a rtx_insn * and an int and returns void. */
+
+void
+hook_void_rtx_insn_int (rtx_insn *, int)
+{
+}
+
+/* Generic hook that takes a struct gcc_options * and returns void. */
+
+void
+hook_void_gcc_optionsp (struct gcc_options *)
+{
+}
+
+/* Generic hook that takes an unsigned int and returns true. */
+
+bool
+hook_bool_uint_true (unsigned int)
+{
+ return true;
+}
+
+/* Generic hook that takes an unsigned int, an unsigned int pointer and
+ returns false. */
+
+bool
+hook_bool_uint_uintp_false (unsigned int, unsigned int *)
+{
+ return false;
+}
+
+/* Generic hook that takes a register class and returns false. */
+bool
+hook_bool_reg_class_t_false (reg_class_t regclass ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+/* Generic hook that takes 2 machine_modes and a register class and
+ returns true. */
+bool
+hook_bool_mode_mode_reg_class_t_true (machine_mode, machine_mode, reg_class_t)
+{
+ return true;
+}
+
+/* Generic hook that takes a machine_mode and 2 register classes
+ and returns false. */
+bool
+hook_bool_mode_reg_class_t_reg_class_t_false (machine_mode, reg_class_t,
+ reg_class_t)
+{
+ return false;
+}
+
+/* Generic hook that takes a mode and an unsigned HOST_WIDE_INT and
+ returns no mode. */
+
+opt_machine_mode
+hook_optmode_mode_uhwi_none (machine_mode, unsigned HOST_WIDE_INT)
+{
+ return opt_machine_mode ();
+}
diff --git a/support/cpp/gcc/hooks.h b/support/cpp/gcc/hooks.h
new file mode 100644
index 000000000..2b8508372
--- /dev/null
+++ b/support/cpp/gcc/hooks.h
@@ -0,0 +1,140 @@
+/* General-purpose hooks.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+#ifndef GCC_HOOKS_H
+#define GCC_HOOKS_H
+
+
+extern bool hook_bool_void_false (void);
+extern bool hook_bool_void_true (void);
+extern bool hook_bool_bool_false (bool);
+extern bool hook_bool_bool_gcc_optionsp_false (bool, struct gcc_options *);
+extern bool hook_bool_const_int_const_int_true (const int, const int);
+extern bool hook_bool_mode_false (machine_mode);
+extern bool hook_bool_mode_true (machine_mode);
+extern bool hook_bool_mode_mode_true (machine_mode, machine_mode);
+extern bool hook_bool_mode_const_rtx_false (machine_mode, const_rtx);
+extern bool hook_bool_mode_const_rtx_true (machine_mode, const_rtx);
+extern bool hook_bool_mode_rtx_false (machine_mode, rtx);
+extern bool hook_bool_mode_rtx_true (machine_mode, rtx);
+extern bool hook_bool_const_rtx_insn_const_rtx_insn_true (const rtx_insn *,
+ const rtx_insn *);
+extern bool hook_bool_mode_uhwi_false (machine_mode,
+ unsigned HOST_WIDE_INT);
+// sdcpp extern bool hook_bool_puint64_puint64_true (poly_uint64, poly_uint64);
+extern bool hook_bool_uint_uint_mode_false (unsigned int, unsigned int,
+ machine_mode);
+extern bool hook_bool_uint_mode_true (unsigned int, machine_mode);
+extern bool hook_bool_tree_false (tree);
+extern bool hook_bool_const_tree_false (const_tree);
+extern bool hook_bool_const_tree_const_tree_true (const_tree, const_tree);
+extern bool hook_bool_tree_true (tree);
+extern bool hook_bool_const_tree_true (const_tree);
+extern bool hook_bool_gsiptr_false (gimple_stmt_iterator *);
+extern bool hook_bool_const_tree_hwi_hwi_const_tree_false (const_tree,
+ HOST_WIDE_INT,
+ HOST_WIDE_INT,
+ const_tree);
+extern bool hook_bool_const_tree_hwi_hwi_const_tree_true (const_tree,
+ HOST_WIDE_INT,
+ HOST_WIDE_INT,
+ const_tree);
+extern bool hook_bool_rtx_insn_true (rtx_insn *);
+extern bool hook_bool_rtx_false (rtx);
+extern bool hook_bool_rtx_insn_int_false (rtx_insn *, int);
+extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
+extern bool hook_bool_reg_class_t_false (reg_class_t regclass);
+extern bool hook_bool_mode_mode_reg_class_t_true (machine_mode, machine_mode,
+ reg_class_t);
+extern bool hook_bool_mode_reg_class_t_reg_class_t_false (machine_mode,
+ reg_class_t,
+ reg_class_t);
+extern bool hook_bool_rtx_mode_int_int_intp_bool_false (rtx, machine_mode,
+ int, int, int *, bool);
+extern bool hook_bool_tree_tree_false (tree, tree);
+extern bool hook_bool_tree_tree_true (tree, tree);
+extern bool hook_bool_tree_bool_false (tree, bool);
+// extern bool hook_bool_wint_wint_uint_bool_true (const widest_int &,
+// const widest_int &,
+// unsigned int, bool);
+
+extern void hook_void_void (void);
+extern void hook_void_constcharptr (const char *);
+extern void hook_void_rtx_insn_int (rtx_insn *, int);
+extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
+extern void hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *,
+ const_tree);
+extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx);
+extern void hook_void_rtx_tree (rtx, tree);
+extern void hook_void_FILEptr_tree (FILE *, tree);
+extern void hook_void_tree (tree);
+extern void hook_void_tree_treeptr (tree, tree *);
+extern void hook_void_int_int (int, int);
+extern void hook_void_gcc_optionsp (struct gcc_options *);
+extern bool hook_bool_uint_true (unsigned int);
+extern bool hook_bool_uint_uintp_false (unsigned int, unsigned int *);
+
+extern int hook_int_uint_mode_1 (unsigned int, machine_mode);
+extern int hook_int_const_tree_0 (const_tree);
+extern int hook_int_const_tree_const_tree_1 (const_tree, const_tree);
+extern int hook_int_const_tree_int (const_tree, int); // sdcpp
+extern int hook_int_rtx_0 (rtx);
+extern int hook_int_rtx_1 (rtx);
+extern int hook_int_rtx_insn_0 (rtx_insn *);
+extern int hook_int_rtx_insn_unreachable (rtx_insn *);
+extern int hook_int_rtx_bool_0 (rtx, bool);
+extern int hook_int_rtx_mode_as_bool_0 (rtx, machine_mode, addr_space_t,
+ bool);
+
+extern HOST_WIDE_INT hook_hwi_void_0 (void);
+
+extern tree hook_tree_const_tree_null (const_tree);
+extern tree hook_tree_void_null (void);
+
+extern tree hook_tree_tree_bool_null (tree, bool);
+extern tree hook_tree_tree_tree_null (tree, tree);
+extern tree hook_tree_tree_tree_tree_null (tree, tree, tree);
+extern tree hook_tree_tree_int_treep_bool_null (tree, int, tree *, bool);
+extern tree hook_tree_treeptr_tree_tree_int_boolptr_null (tree *, tree, tree, int, bool *);
+
+extern unsigned hook_uint_void_0 (void);
+extern unsigned int hook_uint_mode_0 (machine_mode);
+
+extern bool default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, const_tree);
+
+extern rtx hook_rtx_rtx_identity (rtx);
+extern rtx hook_rtx_rtx_null (rtx);
+extern rtx hook_rtx_tree_int_null (tree, int);
+
+extern char *hook_charptr_void_null (void);
+extern const char *hook_constcharptr_void_null (void);
+extern const char *hook_constcharptr_const_tree_null (const_tree);
+extern const char *hook_constcharptr_const_rtx_insn_null (const rtx_insn *);
+extern const char *hook_constcharptr_const_tree_const_tree_null (const_tree, const_tree);
+extern const char *hook_constcharptr_int_const_tree_null (int, const_tree);
+extern const char *hook_constcharptr_int_const_tree_const_tree_null (int, const_tree, const_tree);
+
+#if 0 // sdcpp
+extern opt_machine_mode hook_optmode_mode_uhwi_none (machine_mode,
+ unsigned HOST_WIDE_INT);
+#endif
+#endif
diff --git a/support/cpp/gcc/hosthooks.h b/support/cpp/gcc/hosthooks.h
new file mode 100644
index 000000000..af8ac84da
--- /dev/null
+++ b/support/cpp/gcc/hosthooks.h
@@ -0,0 +1,50 @@
+/* The host_hooks data structure.
+ Copyright (C) 2003-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/>. */
+
+#if 0 // sdcpp GCC_HOST_HOOKS_H
+#define GCC_HOST_HOOKS_H
+
+struct host_hooks
+{
+ void (*extra_signals) (void);
+
+ /* Identify an address that's likely to be free in a subsequent invocation
+ of the compiler. The area should be able to hold SIZE bytes. FD is an
+ open file descriptor if the host would like to probe with mmap. */
+ void * (*gt_pch_get_address) (size_t size, int fd);
+
+ /* ADDR is an address returned by gt_pch_get_address. Attempt to allocate
+ SIZE bytes at the same address (preferrably) or some other address
+ and load it with the data from FD at OFFSET. Return -1 if we couldn't
+ allocate memory, otherwise update ADDR to the actual address where it got
+ allocated, return 0 if the memory is allocated but the data not loaded,
+ return 1 if done. */
+ int (*gt_pch_use_address) (void *&addr, size_t size, int fd, size_t offset);
+
+ /* Return the alignment required for allocating virtual memory. Usually
+ this is the same as pagesize. */
+ size_t (*gt_pch_alloc_granularity) (void);
+
+ /* Whenever you add entries here, make sure you adjust hosthooks-def.h. */
+};
+
+/* Each host provides its own. */
+extern const struct host_hooks host_hooks;
+
+#endif /* GCC_LANG_HOOKS_H */
diff --git a/support/cpp/gcc/hwint.h b/support/cpp/gcc/hwint.h
new file mode 100644
index 000000000..c160bea0c
--- /dev/null
+++ b/support/cpp/gcc/hwint.h
@@ -0,0 +1,378 @@
+/* HOST_WIDE_INT definitions for the GNU compiler.
+ Copyright (C) 1998-2022 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ Provide definitions for macros which depend on HOST_BITS_PER_INT
+ and HOST_BITS_PER_LONG. */
+
+#ifndef GCC_HWINT_H
+#define GCC_HWINT_H
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR CHAR_BIT
+#define HOST_BITS_PER_SHORT (CHAR_BIT * SIZEOF_SHORT)
+#define HOST_BITS_PER_INT (CHAR_BIT * SIZEOF_INT)
+#define HOST_BITS_PER_LONG (CHAR_BIT * SIZEOF_LONG)
+#define HOST_BITS_PER_PTR (CHAR_BIT * SIZEOF_VOID_P)
+
+/* The string that should be inserted into a printf style format to
+ indicate a "long" operand. */
+#ifndef HOST_LONG_FORMAT
+#define HOST_LONG_FORMAT "l"
+#endif
+
+/* The string that should be inserted into a printf style format to
+ indicate a "long long" operand. */
+#ifndef HOST_LONG_LONG_FORMAT
+#define HOST_LONG_LONG_FORMAT "ll"
+#endif
+
+/* If HAVE_LONG_LONG and SIZEOF_LONG_LONG aren't defined, but
+ GCC_VERSION >= 3000, assume this is the second or later stage of a
+ bootstrap, we do have long long, and it's 64 bits. (This is
+ required by C99; we do have some ports that violate that assumption
+ but they're all cross-compile-only.) Just in case, force a
+ constraint violation if that assumption is incorrect. */
+#if !defined HAVE_LONG_LONG
+# if GCC_VERSION >= 3000
+# define HAVE_LONG_LONG 1
+# define SIZEOF_LONG_LONG 8
+extern char sizeof_long_long_must_be_8[sizeof (long long) == 8 ? 1 : -1];
+# endif
+#endif
+
+#ifdef HAVE_LONG_LONG
+# define HOST_BITS_PER_LONGLONG (CHAR_BIT * SIZEOF_LONG_LONG)
+#endif
+
+/* Set HOST_WIDE_INT, this should be always 64 bits.
+ The underlying type is matched to that of int64_t and assumed
+ to be either long or long long. */
+
+#define HOST_BITS_PER_WIDE_INT 64
+#if INT64_T_IS_LONG
+# define HOST_WIDE_INT long
+# define HOST_WIDE_INT_C(X) X ## L
+#else
+# if HOST_BITS_PER_LONGLONG == 64
+# define HOST_WIDE_INT long long
+# define HOST_WIDE_INT_C(X) X ## LL
+# else
+ #error "Unable to find a suitable type for HOST_WIDE_INT"
+# endif
+#endif
+
+#define HOST_WIDE_INT_UC(X) HOST_WIDE_INT_C (X ## U)
+#define HOST_WIDE_INT_0 HOST_WIDE_INT_C (0)
+#define HOST_WIDE_INT_0U HOST_WIDE_INT_UC (0)
+#define HOST_WIDE_INT_1 HOST_WIDE_INT_C (1)
+#define HOST_WIDE_INT_1U HOST_WIDE_INT_UC (1)
+#define HOST_WIDE_INT_M1 HOST_WIDE_INT_C (-1)
+#define HOST_WIDE_INT_M1U HOST_WIDE_INT_UC (-1)
+
+/* This is a magic identifier which allows GCC to figure out the type
+ of HOST_WIDE_INT for %wd specifier checks. You must issue this
+ typedef before using the __asm_fprintf__ format attribute. */
+typedef HOST_WIDE_INT __gcc_host_wide_int__;
+
+/* Provide C99 <inttypes.h> style format definitions for 64bits. */
+#ifndef HAVE_INTTYPES_H
+#if INT64_T_IS_LONG
+# define GCC_PRI64 HOST_LONG_FORMAT
+#else
+# define GCC_PRI64 HOST_LONG_LONG_FORMAT
+#endif
+#undef PRId64
+#define PRId64 GCC_PRI64 "d"
+#undef PRIi64
+#define PRIi64 GCC_PRI64 "i"
+#undef PRIo64
+#define PRIo64 GCC_PRI64 "o"
+#undef PRIu64
+#define PRIu64 GCC_PRI64 "u"
+#undef PRIx64
+#define PRIx64 GCC_PRI64 "x"
+#undef PRIX64
+#define PRIX64 GCC_PRI64 "X"
+#endif
+
+/* Various printf format strings for HOST_WIDE_INT. */
+
+#if INT64_T_IS_LONG
+# define HOST_WIDE_INT_PRINT HOST_LONG_FORMAT
+# define HOST_WIDE_INT_PRINT_C "L"
+#else
+# define HOST_WIDE_INT_PRINT HOST_LONG_LONG_FORMAT
+# define HOST_WIDE_INT_PRINT_C "LL"
+#endif
+
+#define HOST_WIDE_INT_PRINT_DEC "%" PRId64
+#define HOST_WIDE_INT_PRINT_DEC_C "%" PRId64 HOST_WIDE_INT_PRINT_C
+#define HOST_WIDE_INT_PRINT_UNSIGNED "%" PRIu64
+#define HOST_WIDE_INT_PRINT_HEX "%#" PRIx64
+#define HOST_WIDE_INT_PRINT_HEX_PURE "%" PRIx64
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%" PRIx64 "%016" PRIx64
+#define HOST_WIDE_INT_PRINT_PADDED_HEX "%016" PRIx64
+
+/* Define HOST_WIDEST_FAST_INT to the widest integer type supported
+ efficiently in hardware. (That is, the widest integer type that fits
+ in a hardware register.) Normally this is "long" but on some hosts it
+ should be "long long" or "__int64". This is no convenient way to
+ autodetect this, so such systems must set a flag in config.host; see there
+ for details. */
+
+#ifdef USE_LONG_LONG_FOR_WIDEST_FAST_INT
+# ifdef HAVE_LONG_LONG
+# define HOST_WIDEST_FAST_INT long long
+# define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONGLONG
+# else
+# error "Your host said it wanted to use long long but that does not exist"
+# endif
+#else
+# define HOST_WIDEST_FAST_INT long
+# define HOST_BITS_PER_WIDEST_FAST_INT HOST_BITS_PER_LONG
+#endif
+
+/* Inline functions operating on HOST_WIDE_INT. */
+
+/* Return X with all but the lowest bit masked off. */
+
+static inline unsigned HOST_WIDE_INT
+least_bit_hwi (unsigned HOST_WIDE_INT x)
+{
+ return (x & -x);
+}
+
+/* True if X is zero or a power of two. */
+
+static inline bool
+pow2_or_zerop (unsigned HOST_WIDE_INT x)
+{
+ return least_bit_hwi (x) == x;
+}
+
+/* True if X is a power of two. */
+
+static inline bool
+pow2p_hwi (unsigned HOST_WIDE_INT x)
+{
+ return x && pow2_or_zerop (x);
+}
+
+#if GCC_VERSION < 3004
+
+extern int clz_hwi (unsigned HOST_WIDE_INT x);
+extern int ctz_hwi (unsigned HOST_WIDE_INT x);
+extern int ffs_hwi (unsigned HOST_WIDE_INT x);
+
+/* Return the number of set bits in X. */
+extern int popcount_hwi (unsigned HOST_WIDE_INT x);
+
+/* Return log2, or -1 if not exact. */
+extern int exact_log2 (unsigned HOST_WIDE_INT);
+
+/* Return floor of log2, with -1 for zero. */
+extern int floor_log2 (unsigned HOST_WIDE_INT);
+
+/* Return the smallest n such that 2**n >= X. */
+extern int ceil_log2 (unsigned HOST_WIDE_INT);
+
+#else /* GCC_VERSION >= 3004 */
+
+/* For convenience, define 0 -> word_size. */
+static inline int
+clz_hwi (unsigned HOST_WIDE_INT x)
+{
+ if (x == 0)
+ return HOST_BITS_PER_WIDE_INT;
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ return __builtin_clzl (x);
+# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
+ return __builtin_clzll (x);
+# else
+ return __builtin_clz (x);
+# endif
+}
+
+static inline int
+ctz_hwi (unsigned HOST_WIDE_INT x)
+{
+ if (x == 0)
+ return HOST_BITS_PER_WIDE_INT;
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ return __builtin_ctzl (x);
+# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
+ return __builtin_ctzll (x);
+# else
+ return __builtin_ctz (x);
+# endif
+}
+
+static inline int
+ffs_hwi (unsigned HOST_WIDE_INT x)
+{
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ return __builtin_ffsl (x);
+# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
+ return __builtin_ffsll (x);
+# else
+ return __builtin_ffs (x);
+# endif
+}
+
+static inline int
+popcount_hwi (unsigned HOST_WIDE_INT x)
+{
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ return __builtin_popcountl (x);
+# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
+ return __builtin_popcountll (x);
+# else
+ return __builtin_popcount (x);
+# endif
+}
+
+static inline int
+floor_log2 (unsigned HOST_WIDE_INT x)
+{
+ return HOST_BITS_PER_WIDE_INT - 1 - clz_hwi (x);
+}
+
+static inline int
+ceil_log2 (unsigned HOST_WIDE_INT x)
+{
+ return x == 0 ? 0 : floor_log2 (x - 1) + 1;
+}
+
+static inline int
+exact_log2 (unsigned HOST_WIDE_INT x)
+{
+ return pow2p_hwi (x) ? ctz_hwi (x) : -1;
+}
+
+#endif /* GCC_VERSION >= 3004 */
+
+#define HOST_WIDE_INT_MIN (HOST_WIDE_INT) \
+ (HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1))
+#define HOST_WIDE_INT_MAX (~(HOST_WIDE_INT_MIN))
+
+extern HOST_WIDE_INT abs_hwi (HOST_WIDE_INT);
+extern unsigned HOST_WIDE_INT absu_hwi (HOST_WIDE_INT);
+extern HOST_WIDE_INT gcd (HOST_WIDE_INT, HOST_WIDE_INT);
+extern HOST_WIDE_INT pos_mul_hwi (HOST_WIDE_INT, HOST_WIDE_INT);
+extern HOST_WIDE_INT mul_hwi (HOST_WIDE_INT, HOST_WIDE_INT);
+extern HOST_WIDE_INT least_common_multiple (HOST_WIDE_INT, HOST_WIDE_INT);
+
+/* Like ctz_hwi, except 0 when x == 0. */
+
+static inline int
+ctz_or_zero (unsigned HOST_WIDE_INT x)
+{
+ return ffs_hwi (x) - 1;
+}
+
+/* Sign extend SRC starting from PREC. */
+
+static inline HOST_WIDE_INT
+sext_hwi (HOST_WIDE_INT src, unsigned int prec)
+{
+ if (prec == HOST_BITS_PER_WIDE_INT)
+ return src;
+ else
+#if defined (__GNUC__)
+ {
+ /* Take the faster path if the implementation-defined bits it's relying
+ on are implemented the way we expect them to be. Namely, conversion
+ from unsigned to signed preserves bit pattern, and right shift of
+ a signed value propagates the sign bit.
+ We have to convert from signed to unsigned and back, because when left
+ shifting signed values, any overflow is undefined behavior. */
+ gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
+ int shift = HOST_BITS_PER_WIDE_INT - prec;
+ return ((HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) src << shift)) >> shift;
+ }
+#else
+ {
+ /* Fall back to the slower, well defined path otherwise. */
+ gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
+ HOST_WIDE_INT sign_mask = HOST_WIDE_INT_1 << (prec - 1);
+ HOST_WIDE_INT value_mask = (HOST_WIDE_INT_1U << prec) - HOST_WIDE_INT_1U;
+ return (((src & value_mask) ^ sign_mask) - sign_mask);
+ }
+#endif
+}
+
+/* Zero extend SRC starting from PREC. */
+static inline unsigned HOST_WIDE_INT
+zext_hwi (unsigned HOST_WIDE_INT src, unsigned int prec)
+{
+ if (prec == HOST_BITS_PER_WIDE_INT)
+ return src;
+ else
+ {
+ gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT);
+ return src & ((HOST_WIDE_INT_1U << prec) - 1);
+ }
+}
+
+/* Compute the absolute value of X. */
+
+inline HOST_WIDE_INT
+abs_hwi (HOST_WIDE_INT x)
+{
+ gcc_checking_assert (x != HOST_WIDE_INT_MIN);
+ return x >= 0 ? x : -x;
+}
+
+/* Compute the absolute value of X as an unsigned type. */
+
+inline unsigned HOST_WIDE_INT
+absu_hwi (HOST_WIDE_INT x)
+{
+ return x >= 0 ? (unsigned HOST_WIDE_INT)x : -(unsigned HOST_WIDE_INT)x;
+}
+
+/* Compute the sum of signed A and B and indicate in *OVERFLOW whether
+ that operation overflowed. */
+
+inline HOST_WIDE_INT
+add_hwi (HOST_WIDE_INT a, HOST_WIDE_INT b, bool *overflow)
+{
+#if GCC_VERSION < 11000
+ unsigned HOST_WIDE_INT result = a + (unsigned HOST_WIDE_INT)b;
+ if ((((result ^ a) & (result ^ b))
+ >> (HOST_BITS_PER_WIDE_INT - 1)) & 1)
+ *overflow = true;
+ else
+ *overflow = false;
+ return result;
+#else
+ HOST_WIDE_INT result;
+ *overflow = __builtin_add_overflow (a, b, &result);
+ return result;
+#endif
+}
+
+/* Compute the product of signed A and B and indicate in *OVERFLOW whether
+ that operation overflowed. */
+
+inline HOST_WIDE_INT
+mul_hwi (HOST_WIDE_INT a, HOST_WIDE_INT b, bool *overflow)
+{
+#if GCC_VERSION < 11000
+ unsigned HOST_WIDE_INT result = a * (unsigned HOST_WIDE_INT)b;
+ if ((a == -1 && b == HOST_WIDE_INT_MIN)
+ || (a != 0 && (HOST_WIDE_INT)result / a != b))
+ *overflow = true;
+ else
+ *overflow = false;
+ return result;
+#else
+ HOST_WIDE_INT result;
+ *overflow = __builtin_mul_overflow (a, b, &result);
+ return result;
+#endif
+}
+
+#endif /* ! GCC_HWINT_H */
diff --git a/support/cpp/gcc/inchash.h b/support/cpp/gcc/inchash.h
new file mode 100644
index 000000000..b5c1b7cec
--- /dev/null
+++ b/support/cpp/gcc/inchash.h
@@ -0,0 +1,213 @@
+/* An incremental hash abstract data type.
+ Copyright (C) 2014-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 INCHASH_H
+#define INCHASH_H 1
+
+
+/* This file implements an incremential hash function ADT, to be used
+ by code that incrementially hashes a lot of unrelated data
+ (not in a single memory block) into a single value. The goal
+ is to make it easy to plug in efficient hash algorithms.
+ Currently it just implements the plain old jhash based
+ incremental hash from gcc's tree.cc. */
+
+hashval_t iterative_hash_host_wide_int (HOST_WIDE_INT, hashval_t);
+hashval_t iterative_hash_hashval_t (hashval_t, hashval_t);
+
+namespace inchash
+{
+
+class hash
+{
+ public:
+
+ /* Start incremential hashing, optionally with SEED. */
+ hash (hashval_t seed = 0)
+ {
+ val = seed;
+ bits = 0;
+ }
+
+ /* End incremential hashing and provide the final value. */
+ hashval_t end ()
+ {
+ return val;
+ }
+
+ /* Add unsigned value V. */
+ void add_int (unsigned v)
+ {
+ val = iterative_hash_hashval_t (v, val);
+ }
+
+ /* Add polynomial value V, treating each element as an unsigned int. */
+// sdcpp template<unsigned int N, typename T>
+// sdcpp void add_poly_int (const poly_int_pod<N, T> &v)
+// sdcpp {
+// sdcpp for (unsigned int i = 0; i < N; ++i)
+// sdcpp add_int (v.coeffs[i]);
+// sdcpp }
+
+ /* Add HOST_WIDE_INT value V. */
+ void add_hwi (HOST_WIDE_INT v)
+ {
+ val = iterative_hash_host_wide_int (v, val);
+ }
+
+#if 0 // sdcpp
+ /* Add polynomial value V, treating each element as a HOST_WIDE_INT. */
+ template<unsigned int N, typename T>
+ void add_poly_hwi (const poly_int_pod<N, T> &v)
+ {
+ for (unsigned int i = 0; i < N; ++i)
+ add_hwi (v.coeffs[i]);
+ }
+
+ /* Add wide_int-based value V. */
+ template<typename T>
+ void add_wide_int (const generic_wide_int<T> &x)
+ {
+ add_int (x.get_len ());
+ for (unsigned i = 0; i < x.get_len (); i++)
+ add_hwi (x.sext_elt (i));
+ }
+#endif // sdcpp
+
+ /* Hash in pointer PTR. */
+ void add_ptr (const void *ptr)
+ {
+ add (&ptr, sizeof (ptr));
+ }
+
+ /* Add a memory block DATA with size LEN. */
+ void add (const void *data, size_t len)
+ {
+ val = iterative_hash (data, len, val);
+ }
+
+ /* Merge hash value OTHER. */
+ void merge_hash (hashval_t other)
+ {
+ val = iterative_hash_hashval_t (other, val);
+ }
+
+ /* Hash in state from other inchash OTHER. */
+ void merge (hash &other)
+ {
+ merge_hash (other.val);
+ }
+
+ template<class T> void add_object(T &obj)
+ {
+ add (&obj, sizeof(T));
+ }
+
+ /* Support for accumulating boolean flags */
+
+ void add_flag (bool flag)
+ {
+ bits = (bits << 1) | flag;
+ }
+
+ void commit_flag ()
+ {
+ add_int (bits);
+ bits = 0;
+ }
+
+ /* Support for commutative hashing. Add A and B in a defined order
+ based on their value. This is useful for hashing commutative
+ expressions, so that A+B and B+A get the same hash. */
+
+ void add_commutative (hash &a, hash &b)
+ {
+ if (a.end() > b.end())
+ {
+ merge (b);
+ merge (a);
+ }
+ else
+ {
+ merge (a);
+ merge (b);
+ }
+ }
+
+ private:
+ hashval_t val;
+ unsigned bits;
+};
+
+}
+
+/* Borrowed from hashtab.c iterative_hash implementation. */
+#define mix(a,b,c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<< 8); \
+ c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
+ a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
+ b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
+ c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
+ a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
+ b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
+ c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
+}
+
+
+/* Produce good hash value combining VAL and VAL2. */
+inline
+hashval_t
+iterative_hash_hashval_t (hashval_t val, hashval_t val2)
+{
+ /* the golden ratio; an arbitrary value. */
+ hashval_t a = 0x9e3779b9;
+
+ mix (a, val, val2);
+ return val2;
+}
+
+/* Produce good hash value combining VAL and VAL2. */
+
+inline
+hashval_t
+iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2)
+{
+ if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t))
+ return iterative_hash_hashval_t (val, val2);
+ else
+ {
+ hashval_t a = (hashval_t) val;
+ /* Avoid warnings about shifting of more than the width of the type on
+ hosts that won't execute this path. */
+ int zero = 0;
+ hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+ mix (a, b, val2);
+ if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t))
+ {
+ hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero));
+ hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero));
+ mix (a, b, val2);
+ }
+ return val2;
+ }
+}
+
+#endif
diff --git a/support/cpp/gcc/incpath.cc b/support/cpp/gcc/incpath.cc
new file mode 100644
index 000000000..cee835afc
--- /dev/null
+++ b/support/cpp/gcc/incpath.cc
@@ -0,0 +1,537 @@
+/* Set up combined include path chain for the preprocessor.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
+
+ Broken out of cppinit.c and cppfiles.c and rewritten Mar 2003.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "cpplib.h"
+#include "prefix.h"
+#include "intl.h"
+#include "incpath.h"
+#include "cppdefault.h"
+#include "options.h" // sdcpp
+
+/* Microsoft Windows does not natively support inodes.
+ VMS has non-numeric inodes. */
+#ifdef VMS
+# define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A)))
+# define INO_T_COPY(DEST, SRC) memcpy (&(DEST), &(SRC), sizeof (SRC))
+#elif !defined (HOST_LACKS_INODE_NUMBERS)
+# define INO_T_EQ(A, B) ((A) == (B))
+# define INO_T_COPY(DEST, SRC) (DEST) = (SRC)
+#endif
+
+#if defined INO_T_EQ
+#define DIRS_EQ(A, B) ((A)->dev == (B)->dev \
+ && INO_T_EQ ((A)->ino, (B)->ino))
+#else
+#define DIRS_EQ(A, B) (!filename_cmp ((A)->canonical_name, (B)->canonical_name))
+#endif
+
+#ifndef HOST_STAT_FOR_64BIT_INODES
+#define HOST_STAT_FOR_64BIT_INODES stat
+#endif
+
+static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
+
+static void add_env_var_paths (const char *, incpath_kind);
+static void add_standard_paths (const char *, const char *, const char *, int);
+static void free_path (struct cpp_dir *, int);
+static void merge_include_chains (const char *, cpp_reader *, int);
+static void add_sysroot_to_chain (const char *, int);
+static struct cpp_dir *remove_duplicates (cpp_reader *, struct cpp_dir *,
+ struct cpp_dir *, struct cpp_dir *,
+ int);
+
+/* Include chains heads and tails. */
+static struct cpp_dir *heads[INC_MAX];
+static struct cpp_dir *tails[INC_MAX];
+
+static bool quote_ignores_source_dir;
+enum { REASON_QUIET = 0, REASON_NOENT, REASON_DUP, REASON_DUP_SYS };
+
+/* Free an element of the include chain, possibly giving a reason. */
+static void
+free_path (struct cpp_dir *path, int reason)
+{
+ switch (reason)
+ {
+ case REASON_DUP:
+ case REASON_DUP_SYS:
+ fprintf (stderr, _("ignoring duplicate directory \"%s\"\n"), path->name);
+ if (reason == REASON_DUP_SYS)
+ fprintf (stderr,
+ _(" as it is a non-system directory that duplicates a system directory\n"));
+ break;
+
+ case REASON_NOENT:
+ fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"),
+ path->name);
+ break;
+
+ case REASON_QUIET:
+ default:
+ break;
+ }
+
+ free (path->name);
+ free (path);
+}
+
+/* Read ENV_VAR for a PATH_SEPARATOR-separated list of file names; and
+ append all the names to the search path CHAIN. */
+static void
+add_env_var_paths (const char *env_var, incpath_kind chain)
+{
+ char *p, *q, *path;
+
+ q = getenv (env_var);
+
+ if (!q)
+ return;
+
+ for (p = q; *q; p = q + 1)
+ {
+ q = p;
+ while (*q != 0 && *q != PATH_SEPARATOR)
+ q++;
+
+ if (p == q)
+ path = xstrdup (".");
+ else
+ {
+ path = XNEWVEC (char, q - p + 1);
+ memcpy (path, p, q - p);
+ path[q - p] = '\0';
+ }
+
+ add_path (path, chain, chain == INC_SYSTEM, false);
+ }
+}
+
+/* Append the standard include chain defined in cppdefault.cc. */
+static void
+add_standard_paths (const char *sysroot, const char *iprefix,
+ const char *imultilib, int cxx_stdinc)
+{
+ const struct default_include *p;
+ int relocated = cpp_relocated ();
+ size_t len;
+
+ if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0)
+ {
+ /* Look for directories that start with the standard prefix.
+ "Translate" them, i.e. replace /usr/local/lib/gcc... with
+ IPREFIX and search them first. */
+ for (p = cpp_include_defaults; p->fname; p++)
+ {
+ if (p->cplusplus == 0
+ || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))
+ {
+ /* Should we be translating sysrooted dirs too? Assume
+ that iprefix and sysroot are mutually exclusive, for
+ now. */
+ if (sysroot && p->add_sysroot)
+ continue;
+ if (!filename_ncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))
+ {
+ char *str = concat (iprefix, p->fname + len, NULL);
+ if (p->multilib == 1 && imultilib)
+ str = reconcat (str, str, dir_separator_str,
+ imultilib, NULL);
+ else if (p->multilib == 2)
+ {
+ if (!imultiarch)
+ {
+ free (str);
+ continue;
+ }
+ str = reconcat (str, str, dir_separator_str,
+ imultiarch, NULL);
+ }
+ add_path (str, INC_SYSTEM, p->cxx_aware, false);
+ }
+ }
+ }
+ }
+
+ for (p = cpp_include_defaults; p->fname; p++)
+ {
+ if (p->cplusplus == 0
+ || (cxx_stdinc && (p->cplusplus == flag_stdlib_kind)))
+ {
+ char *str;
+
+ /* Should this directory start with the sysroot? */
+ if (sysroot && p->add_sysroot)
+ {
+ char *sysroot_no_trailing_dir_separator = xstrdup (sysroot);
+ size_t sysroot_len = strlen (sysroot);
+
+ if (sysroot_len > 0 && sysroot[sysroot_len - 1] == DIR_SEPARATOR)
+ sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+ str = concat (sysroot_no_trailing_dir_separator, p->fname, NULL);
+ free (sysroot_no_trailing_dir_separator);
+ }
+ else if (!p->add_sysroot && relocated
+ && !filename_ncmp (p->fname, cpp_PREFIX, cpp_PREFIX_len))
+ {
+ static const char *relocated_prefix;
+ char *ostr;
+ /* If this path starts with the configure-time prefix,
+ but the compiler has been relocated, replace it
+ with the run-time prefix. The run-time exec prefix
+ is GCC_EXEC_PREFIX. Compute the path from there back
+ to the toplevel prefix. */
+ if (!relocated_prefix)
+ {
+ char *dummy;
+ /* Make relative prefix expects the first argument
+ to be a program, not a directory. */
+ dummy = concat (gcc_exec_prefix, "dummy", NULL);
+ relocated_prefix
+ = make_relative_prefix (dummy,
+ cpp_EXEC_PREFIX,
+ cpp_PREFIX);
+ free (dummy);
+ }
+ ostr = concat (relocated_prefix,
+ p->fname + cpp_PREFIX_len,
+ NULL);
+ str = update_path (ostr, p->component);
+ free (ostr);
+ }
+ else
+ str = update_path (p->fname, p->component);
+
+ if (p->multilib == 1 && imultilib)
+ str = reconcat (str, str, dir_separator_str, imultilib, NULL);
+ else if (p->multilib == 2)
+ {
+ if (!imultiarch)
+ {
+ free (str);
+ continue;
+ }
+ str = reconcat (str, str, dir_separator_str, imultiarch, NULL);
+ }
+
+ add_path (str, INC_SYSTEM, p->cxx_aware, false);
+ }
+ }
+}
+
+/* For each duplicate path in chain HEAD, keep just the first one.
+ Remove each path in chain HEAD that also exists in chain SYSTEM.
+ Set the NEXT pointer of the last path in the resulting chain to
+ JOIN, unless it duplicates JOIN in which case the last path is
+ removed. Return the head of the resulting chain. Any of HEAD,
+ JOIN and SYSTEM can be NULL. */
+
+static struct cpp_dir *
+remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
+ struct cpp_dir *system, struct cpp_dir *join,
+ int verbose)
+{
+ struct cpp_dir **pcur, *tmp, *cur;
+ struct HOST_STAT_FOR_64BIT_INODES st;
+
+ for (pcur = &head; *pcur; )
+ {
+ int reason = REASON_QUIET;
+
+ cur = *pcur;
+
+ if (HOST_STAT_FOR_64BIT_INODES (cur->name, &st))
+ {
+ /* Dirs that don't exist or have denied permissions are
+ silently ignored, unless verbose. */
+ if ((errno != ENOENT) && (errno != EPERM))
+ cpp_errno (pfile, CPP_DL_ERROR, cur->name);
+ else
+ {
+ /* If -Wmissing-include-dirs is given, warn. */
+ cpp_options *opts = cpp_get_options (pfile);
+ if (opts->warn_missing_include_dirs && cur->user_supplied_p)
+ cpp_warning (pfile, CPP_W_MISSING_INCLUDE_DIRS, "%s: %s",
+ cur->name, xstrerror (errno));
+ reason = REASON_NOENT;
+ }
+ }
+ else if (!S_ISDIR (st.st_mode))
+ cpp_error_with_line (pfile, CPP_DL_WARNING, 0, 0,
+ "%s: not a directory", cur->name);
+ else
+ {
+#if defined (INO_T_COPY)
+ INO_T_COPY (cur->ino, st.st_ino);
+ cur->dev = st.st_dev;
+#endif
+
+ /* Remove this one if it is in the system chain. */
+ reason = REASON_DUP_SYS;
+ for (tmp = system; tmp; tmp = tmp->next)
+ if (DIRS_EQ (tmp, cur) && cur->construct == tmp->construct)
+ break;
+
+ if (!tmp)
+ {
+ /* Duplicate of something earlier in the same chain? */
+ reason = REASON_DUP;
+ for (tmp = head; tmp != cur; tmp = tmp->next)
+ if (DIRS_EQ (cur, tmp) && cur->construct == tmp->construct)
+ break;
+
+ if (tmp == cur
+ /* Last in the chain and duplicate of JOIN? */
+ && !(cur->next == NULL && join
+ && DIRS_EQ (cur, join)
+ && cur->construct == join->construct))
+ {
+ /* Unique, so keep this directory. */
+ pcur = &cur->next;
+ continue;
+ }
+ }
+ }
+
+ /* Remove this entry from the chain. */
+ *pcur = cur->next;
+ free_path (cur, verbose ? reason: REASON_QUIET);
+ }
+
+ *pcur = join;
+ return head;
+}
+
+/* Add SYSROOT to any user-supplied paths in CHAIN starting with
+ "=" or "$SYSROOT". */
+
+static void
+add_sysroot_to_chain (const char *sysroot, int chain)
+{
+ struct cpp_dir *p;
+
+ for (p = heads[chain]; p != NULL; p = p->next)
+ {
+ if (p->user_supplied_p)
+ {
+ if (p->name[0] == '=')
+ p->name = concat (sysroot, p->name + 1, NULL);
+ if (startswith (p->name, "$SYSROOT"))
+ p->name = concat (sysroot, p->name + strlen ("$SYSROOT"), NULL);
+ }
+ }
+}
+
+/* Merge the four include chains together in the order quote, bracket,
+ system, after. Remove duplicate dirs (determined in
+ system-specific manner).
+
+ We can't just merge the lists and then uniquify them because then
+ we may lose directories from the <> search path that should be
+ there; consider -iquote foo -iquote bar -Ifoo -Iquux. It is
+ however safe to treat -iquote bar -iquote foo -Ifoo -Iquux as if
+ written -iquote bar -Ifoo -Iquux. */
+
+static void
+merge_include_chains (const char *sysroot, cpp_reader *pfile, int verbose)
+{
+ /* Add the sysroot to user-supplied paths starting with "=". */
+ if (sysroot)
+ {
+ add_sysroot_to_chain (sysroot, INC_QUOTE);
+ add_sysroot_to_chain (sysroot, INC_BRACKET);
+ add_sysroot_to_chain (sysroot, INC_SYSTEM);
+ add_sysroot_to_chain (sysroot, INC_AFTER);
+ }
+
+ /* Join the SYSTEM and AFTER chains. Remove duplicates in the
+ resulting SYSTEM chain. */
+ if (heads[INC_SYSTEM])
+ tails[INC_SYSTEM]->next = heads[INC_AFTER];
+ else
+ heads[INC_SYSTEM] = heads[INC_AFTER];
+ heads[INC_SYSTEM]
+ = remove_duplicates (pfile, heads[INC_SYSTEM], 0, 0, verbose);
+
+ /* Remove duplicates from BRACKET that are in itself or SYSTEM, and
+ join it to SYSTEM. */
+ heads[INC_BRACKET]
+ = remove_duplicates (pfile, heads[INC_BRACKET], heads[INC_SYSTEM],
+ heads[INC_SYSTEM], verbose);
+
+ /* Remove duplicates from QUOTE that are in itself or SYSTEM, and
+ join it to BRACKET. */
+ heads[INC_QUOTE]
+ = remove_duplicates (pfile, heads[INC_QUOTE], heads[INC_SYSTEM],
+ heads[INC_BRACKET], verbose);
+
+ /* If verbose, print the list of dirs to search. */
+ if (verbose)
+ {
+ struct cpp_dir *p;
+
+ fprintf (stderr, _("#include \"...\" search starts here:\n"));
+ for (p = heads[INC_QUOTE];; p = p->next)
+ {
+ if (p == heads[INC_BRACKET])
+ fprintf (stderr, _("#include <...> search starts here:\n"));
+ if (!p)
+ break;
+ fprintf (stderr, " %s\n", p->name);
+ }
+ fprintf (stderr, _("End of search list.\n"));
+ }
+}
+
+/* Use given -I paths for #include "..." but not #include <...>, and
+ don't search the directory of the present file for #include "...".
+ (Note that -I. -I- is not the same as the default setup; -I. uses
+ the compiler's working dir.) */
+void
+split_quote_chain (void)
+{
+ if (heads[INC_QUOTE])
+ free_path (heads[INC_QUOTE], REASON_QUIET);
+ if (tails[INC_QUOTE])
+ free_path (tails[INC_QUOTE], REASON_QUIET);
+ heads[INC_QUOTE] = heads[INC_BRACKET];
+ tails[INC_QUOTE] = tails[INC_BRACKET];
+ heads[INC_BRACKET] = NULL;
+ tails[INC_BRACKET] = NULL;
+ /* This is NOT redundant. */
+ quote_ignores_source_dir = true;
+}
+
+/* Add P to the chain specified by CHAIN. */
+
+void
+add_cpp_dir_path (cpp_dir *p, incpath_kind chain)
+{
+ if (tails[chain])
+ tails[chain]->next = p;
+ else
+ heads[chain] = p;
+ tails[chain] = p;
+}
+
+/* Add PATH to the include chain CHAIN. PATH must be malloc-ed and
+ NUL-terminated. */
+void
+add_path (char *path, incpath_kind chain, int cxx_aware, bool user_supplied_p)
+{
+ cpp_dir *p;
+ size_t pathlen = strlen (path);
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+ /* Remove unnecessary trailing slashes. On some versions of MS
+ Windows, trailing _forward_ slashes cause no problems for stat().
+ On newer versions, stat() does not recognize a directory that ends
+ in a '\\' or '/', unless it is a drive root dir, such as "c:/",
+ where it is obligatory. */
+ char* end = path + pathlen - 1;
+ /* Preserve the lead '/' or lead "c:/". */
+ char* start = path + (pathlen > 2 && path[1] == ':' ? 3 : 1);
+
+ for (; end > start && IS_DIR_SEPARATOR (*end); end--)
+ *end = 0;
+ pathlen = end - path;
+#endif
+
+ p = XNEW (cpp_dir);
+ p->next = NULL;
+ p->name = path;
+ p->len = pathlen;
+#ifndef INO_T_EQ
+ p->canonical_name = lrealpath (path);
+#endif
+ if (chain == INC_SYSTEM || chain == INC_AFTER)
+ p->sysp = 1 + !cxx_aware;
+ else
+ p->sysp = 0;
+ p->construct = 0;
+ p->user_supplied_p = user_supplied_p;
+
+ add_cpp_dir_path (p, chain);
+}
+
+/* Exported function to handle include chain merging, duplicate
+ removal, and registration with cpplib. */
+void
+register_include_chains (cpp_reader *pfile, const char *sysroot,
+ const char *iprefix, const char *imultilib,
+ int stdinc, int cxx_stdinc, int verbose)
+{
+ static const char *const lang_env_vars[] =
+ { "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH",
+ "OBJC_INCLUDE_PATH", "OBJCPLUS_INCLUDE_PATH" };
+ cpp_options *cpp_opts = cpp_get_options (pfile);
+ size_t idx = (cpp_opts->objc ? 2: 0);
+
+ if (cpp_opts->cplusplus)
+ idx++;
+ else
+ cxx_stdinc = false;
+
+ /* CPATH and language-dependent environment variables may add to the
+ include chain. */
+ add_env_var_paths ("CPATH", INC_BRACKET);
+ add_env_var_paths (lang_env_vars[idx], INC_SYSTEM);
+
+ target_c_incpath.extra_pre_includes (sysroot, iprefix, stdinc);
+
+ /* Finally chain on the standard directories. */
+ if (stdinc)
+ add_standard_paths (sysroot, iprefix, imultilib, cxx_stdinc);
+
+ target_c_incpath.extra_includes (sysroot, iprefix, stdinc);
+
+ merge_include_chains (sysroot, pfile, verbose);
+
+ cpp_set_include_chains (pfile, heads[INC_QUOTE], heads[INC_BRACKET],
+ quote_ignores_source_dir);
+}
+
+/* Return the current chain of cpp dirs. */
+
+struct cpp_dir *
+get_added_cpp_dirs (incpath_kind chain)
+{
+ return heads[chain];
+}
+
+#if !(defined TARGET_EXTRA_INCLUDES) || !(defined TARGET_EXTRA_PRE_INCLUDES)
+static void hook_void_charptr_charptr_int (const char *sysroot ATTRIBUTE_UNUSED,
+ const char *iprefix ATTRIBUTE_UNUSED,
+ int stdinc ATTRIBUTE_UNUSED)
+{
+}
+#endif
+
+#ifndef TARGET_EXTRA_INCLUDES
+#define TARGET_EXTRA_INCLUDES hook_void_charptr_charptr_int
+#endif
+#ifndef TARGET_EXTRA_PRE_INCLUDES
+#define TARGET_EXTRA_PRE_INCLUDES hook_void_charptr_charptr_int
+#endif
+
+struct target_c_incpath_s target_c_incpath = { TARGET_EXTRA_PRE_INCLUDES, TARGET_EXTRA_INCLUDES };
+
diff --git a/support/cpp/gcc/incpath.h b/support/cpp/gcc/incpath.h
new file mode 100644
index 000000000..1f531523d
--- /dev/null
+++ b/support/cpp/gcc/incpath.h
@@ -0,0 +1,46 @@
+/* Set up combined include path for the preprocessor.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_INCPATH_H
+#define GCC_INCPATH_H
+
+/* Various fragments of include path. */
+enum incpath_kind {
+ INC_QUOTE = 0, /* include "foo" */
+ INC_BRACKET, /* include <foo> */
+ INC_SYSTEM, /* sys-include */
+ INC_AFTER, /* post-sysinclude */
+ INC_MAX
+};
+
+extern void split_quote_chain (void);
+extern void add_path (char *, incpath_kind, int, bool);
+extern void register_include_chains (cpp_reader *, const char *,
+ const char *, const char *,
+ int, int, int);
+extern void add_cpp_dir_path (struct cpp_dir *, incpath_kind);
+extern struct cpp_dir *get_added_cpp_dirs (incpath_kind);
+
+struct target_c_incpath_s {
+ /* Do extra includes processing. STDINC is false iff -nostdinc was given. */
+ void (*extra_pre_includes) (const char *, const char *, int);
+ void (*extra_includes) (const char *, const char *, int);
+};
+
+extern struct target_c_incpath_s target_c_incpath;
+
+#endif /* GCC_INCPATH_H */
diff --git a/support/cpp/gcc/input.cc b/support/cpp/gcc/input.cc
new file mode 100644
index 000000000..b3970613d
--- /dev/null
+++ b/support/cpp/gcc/input.cc
@@ -0,0 +1,3932 @@
+/* Data and functions related to line maps and input files.
+ Copyright (C) 2004-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 "intl.h"
+#include "diagnostic.h"
+#include "selftest.h"
+#include "cpplib.h"
+
+#ifndef HAVE_ICONV
+#define HAVE_ICONV 0
+#endif
+
+/* Input charset configuration. */
+static const char *default_charset_callback (const char *)
+{
+ return nullptr;
+}
+
+void
+file_cache::initialize_input_context (diagnostic_input_charset_callback ccb,
+ bool should_skip_bom)
+{
+ in_context.ccb = (ccb ? ccb : default_charset_callback);
+ in_context.should_skip_bom = should_skip_bom;
+}
+
+/* This is a cache used by get_next_line to store the content of a
+ file to be searched for file lines. */
+class file_cache_slot
+{
+public:
+ file_cache_slot ();
+ ~file_cache_slot ();
+
+ bool read_line_num (size_t line_num,
+ char ** line, ssize_t *line_len);
+
+ /* Accessors. */
+ const char *get_file_path () const { return m_file_path; }
+ unsigned get_use_count () const { return m_use_count; }
+ bool missing_trailing_newline_p () const
+ {
+ return m_missing_trailing_newline;
+ }
+
+ void inc_use_count () { m_use_count++; }
+
+ bool create (const file_cache::input_context &in_context,
+ const char *file_path, FILE *fp, unsigned highest_use_count);
+ void evict ();
+
+ private:
+ /* These are information used to store a line boundary. */
+ class line_info
+ {
+ public:
+ /* The line number. It starts from 1. */
+ size_t line_num;
+
+ /* The position (byte count) of the beginning of the line,
+ relative to the file data pointer. This starts at zero. */
+ size_t start_pos;
+
+ /* The position (byte count) of the last byte of the line. This
+ normally points to the '\n' character, or to one byte after the
+ last byte of the file, if the file doesn't contain a '\n'
+ character. */
+ size_t end_pos;
+
+ line_info (size_t l, size_t s, size_t e)
+ : line_num (l), start_pos (s), end_pos (e)
+ {}
+
+ line_info ()
+ :line_num (0), start_pos (0), end_pos (0)
+ {}
+ };
+
+ bool needs_read_p () const;
+ bool needs_grow_p () const;
+ void maybe_grow ();
+ bool read_data ();
+ bool maybe_read_data ();
+ bool get_next_line (char **line, ssize_t *line_len);
+ bool read_next_line (char ** line, ssize_t *line_len);
+ bool goto_next_line ();
+
+ static const size_t buffer_size = 4 * 1024;
+ static const size_t line_record_size = 100;
+
+ /* The number of time this file has been accessed. This is used
+ to designate which file cache to evict from the cache
+ array. */
+ unsigned m_use_count;
+
+ /* The file_path is the key for identifying a particular file in
+ the cache.
+ For libcpp-using code, the underlying buffer for this field is
+ owned by the corresponding _cpp_file within the cpp_reader. */
+ const char *m_file_path;
+
+ FILE *m_fp;
+
+ /* This points to the content of the file that we've read so
+ far. */
+ char *m_data;
+
+ /* The allocated buffer to be freed may start a little earlier than DATA,
+ e.g. if a UTF8 BOM was skipped at the beginning. */
+ int m_alloc_offset;
+
+ /* The size of the DATA array above.*/
+ size_t m_size;
+
+ /* The number of bytes read from the underlying file so far. This
+ must be less (or equal) than SIZE above. */
+ size_t m_nb_read;
+
+ /* The index of the beginning of the current line. */
+ size_t m_line_start_idx;
+
+ /* The number of the previous line read. This starts at 1. Zero
+ means we've read no line so far. */
+ size_t m_line_num;
+
+ /* This is the total number of lines of the current file. At the
+ moment, we try to get this information from the line map
+ subsystem. Note that this is just a hint. When using the C++
+ front-end, this hint is correct because the input file is then
+ completely tokenized before parsing starts; so the line map knows
+ the number of lines before compilation really starts. For e.g,
+ the C front-end, it can happen that we start emitting diagnostics
+ before the line map has seen the end of the file. */
+ size_t m_total_lines;
+
+ /* Could this file be missing a trailing newline on its final line?
+ Initially true (to cope with empty files), set to true/false
+ as each line is read. */
+ bool m_missing_trailing_newline;
+
+ /* This is a record of the beginning and end of the lines we've seen
+ while reading the file. This is useful to avoid walking the data
+ from the beginning when we are asked to read a line that is
+ before LINE_START_IDX above. Note that the maximum size of this
+ record is line_record_size, so that the memory consumption
+ doesn't explode. We thus scale total_lines down to
+ line_record_size. */
+ vec<line_info, va_heap> m_line_record;
+
+ void offset_buffer (int offset)
+ {
+ gcc_assert (offset < 0 ? m_alloc_offset + offset >= 0
+ : (size_t) offset <= m_size);
+ gcc_assert (m_data);
+ m_alloc_offset += offset;
+ m_data += offset;
+ m_size -= offset;
+ }
+
+};
+
+/* Current position in real source file. */
+
+location_t input_location = UNKNOWN_LOCATION;
+
+class line_maps *line_table;
+
+/* A stashed copy of "line_table" for use by selftest::line_table_test.
+ This needs to be a global so that it can be a GC root, and thus
+ prevent the stashed copy from being garbage-collected if the GC runs
+ during a line_table_test. */
+
+class line_maps *saved_line_table;
+
+/* Expand the source location LOC into a human readable location. If
+ LOC resolves to a builtin location, the file name of the readable
+ location is set to the string "<built-in>". If EXPANSION_POINT_P is
+ TRUE and LOC is virtual, then it is resolved to the expansion
+ point of the involved macro. Otherwise, it is resolved to the
+ spelling location of the token.
+
+ When resolving to the spelling location of the token, if the
+ resulting location is for a built-in location (that is, it has no
+ associated line/column) in the context of a macro expansion, the
+ returned location is the first one (while unwinding the macro
+ location towards its expansion point) that is in real source
+ code.
+
+ ASPECT controls which part of the location to use. */
+
+static expanded_location
+expand_location_1 (location_t loc,
+ bool expansion_point_p,
+ enum location_aspect aspect)
+{
+ expanded_location xloc;
+ const line_map_ordinary *map;
+ enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
+ tree block = NULL;
+
+ if (IS_ADHOC_LOC (loc))
+ {
+ block = LOCATION_BLOCK (loc);
+ loc = LOCATION_LOCUS (loc);
+ }
+
+ memset (&xloc, 0, sizeof (xloc));
+
+ if (loc >= RESERVED_LOCATION_COUNT)
+ {
+ if (!expansion_point_p)
+ {
+ /* We want to resolve LOC to its spelling location.
+
+ But if that spelling location is a reserved location that
+ appears in the context of a macro expansion (like for a
+ location for a built-in token), let's consider the first
+ location (toward the expansion point) that is not reserved;
+ that is, the first location that is in real source code. */
+ loc = linemap_unwind_to_first_non_reserved_loc (line_table,
+ loc, NULL);
+ lrk = LRK_SPELLING_LOCATION;
+ }
+ loc = linemap_resolve_location (line_table, loc, lrk, &map);
+
+ /* loc is now either in an ordinary map, or is a reserved location.
+ If it is a compound location, the caret is in a spelling location,
+ but the start/finish might still be a virtual location.
+ Depending of what the caller asked for, we may need to recurse
+ one level in order to resolve any virtual locations in the
+ end-points. */
+ switch (aspect)
+ {
+ default:
+ gcc_unreachable ();
+ /* Fall through. */
+ case LOCATION_ASPECT_CARET:
+ break;
+ case LOCATION_ASPECT_START:
+ {
+ location_t start = get_start (loc);
+ if (start != loc)
+ return expand_location_1 (start, expansion_point_p, aspect);
+ }
+ break;
+ case LOCATION_ASPECT_FINISH:
+ {
+ location_t finish = get_finish (loc);
+ if (finish != loc)
+ return expand_location_1 (finish, expansion_point_p, aspect);
+ }
+ break;
+ }
+ xloc = linemap_expand_location (line_table, map, loc);
+ }
+
+ xloc.data = block;
+ if (loc <= BUILTINS_LOCATION)
+ xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
+
+ return xloc;
+}
+
+/* Initialize the set of cache used for files accessed by caret
+ diagnostic. */
+
+static void
+diagnostic_file_cache_init (void)
+{
+ gcc_assert (global_dc);
+ if (global_dc->m_file_cache == NULL)
+ global_dc->m_file_cache = new file_cache ();
+}
+
+/* Free the resources used by the set of cache used for files accessed
+ by caret diagnostic. */
+
+void
+diagnostic_file_cache_fini (void)
+{
+ if (global_dc->m_file_cache)
+ {
+ delete global_dc->m_file_cache;
+ global_dc->m_file_cache = NULL;
+ }
+}
+
+/* Return the total lines number that have been read so far by the
+ line map (in the preprocessor) so far. For languages like C++ that
+ entirely preprocess the input file before starting to parse, this
+ equals the actual number of lines of the file. */
+
+static size_t
+total_lines_num (const char *file_path)
+{
+ size_t r = 0;
+ location_t l = 0;
+ if (linemap_get_file_highest_location (line_table, file_path, &l))
+ {
+ gcc_assert (l >= RESERVED_LOCATION_COUNT);
+ expanded_location xloc = expand_location (l);
+ r = xloc.line;
+ }
+ return r;
+}
+
+/* Lookup the cache used for the content of a given file accessed by
+ caret diagnostic. Return the found cached file, or NULL if no
+ cached file was found. */
+
+file_cache_slot *
+file_cache::lookup_file (const char *file_path)
+{
+ gcc_assert (file_path);
+
+ /* This will contain the found cached file. */
+ file_cache_slot *r = NULL;
+ for (unsigned i = 0; i < num_file_slots; ++i)
+ {
+ file_cache_slot *c = &m_file_slots[i];
+ if (c->get_file_path () && !strcmp (c->get_file_path (), file_path))
+ {
+ c->inc_use_count ();
+ r = c;
+ }
+ }
+
+ if (r)
+ r->inc_use_count ();
+
+ return r;
+}
+
+/* Purge any mention of FILENAME from the cache of files used for
+ printing source code. For use in selftests when working
+ with tempfiles. */
+
+void
+diagnostics_file_cache_forcibly_evict_file (const char *file_path)
+{
+ gcc_assert (file_path);
+
+ if (!global_dc->m_file_cache)
+ return;
+
+ global_dc->m_file_cache->forcibly_evict_file (file_path);
+}
+
+void
+file_cache::forcibly_evict_file (const char *file_path)
+{
+ gcc_assert (file_path);
+
+ file_cache_slot *r = lookup_file (file_path);
+ if (!r)
+ /* Not found. */
+ return;
+
+ r->evict ();
+}
+
+void
+file_cache_slot::evict ()
+{
+ m_file_path = NULL;
+ if (m_fp)
+ fclose (m_fp);
+ m_fp = NULL;
+ m_nb_read = 0;
+ m_line_start_idx = 0;
+ m_line_num = 0;
+ m_line_record.truncate (0);
+ m_use_count = 0;
+ m_total_lines = 0;
+ m_missing_trailing_newline = true;
+}
+
+/* Return the file cache that has been less used, recently, or the
+ first empty one. If HIGHEST_USE_COUNT is non-null,
+ *HIGHEST_USE_COUNT is set to the highest use count of the entries
+ in the cache table. */
+
+file_cache_slot*
+file_cache::evicted_cache_tab_entry (unsigned *highest_use_count)
+{
+ diagnostic_file_cache_init ();
+
+ file_cache_slot *to_evict = &m_file_slots[0];
+ unsigned huc = to_evict->get_use_count ();
+ for (unsigned i = 1; i < num_file_slots; ++i)
+ {
+ file_cache_slot *c = &m_file_slots[i];
+ bool c_is_empty = (c->get_file_path () == NULL);
+
+ if (c->get_use_count () < to_evict->get_use_count ()
+ || (to_evict->get_file_path () && c_is_empty))
+ /* We evict C because it's either an entry with a lower use
+ count or one that is empty. */
+ to_evict = c;
+
+ if (huc < c->get_use_count ())
+ huc = c->get_use_count ();
+
+ if (c_is_empty)
+ /* We've reached the end of the cache; subsequent elements are
+ all empty. */
+ break;
+ }
+
+ if (highest_use_count)
+ *highest_use_count = huc;
+
+ return to_evict;
+}
+
+/* Create the cache used for the content of a given file to be
+ accessed by caret diagnostic. This cache is added to an array of
+ cache and can be retrieved by lookup_file_in_cache_tab. This
+ function returns the created cache. Note that only the last
+ num_file_slots files are cached. */
+
+file_cache_slot*
+file_cache::add_file (const char *file_path)
+{
+
+ FILE *fp = fopen (file_path, "r");
+ if (fp == NULL)
+ return NULL;
+
+ unsigned highest_use_count = 0;
+ file_cache_slot *r = evicted_cache_tab_entry (&highest_use_count);
+ if (!r->create (in_context, file_path, fp, highest_use_count))
+ return NULL;
+ return r;
+}
+
+/* Populate this slot for use on FILE_PATH and FP, dropping any
+ existing cached content within it. */
+
+bool
+file_cache_slot::create (const file_cache::input_context &in_context,
+ const char *file_path, FILE *fp,
+ unsigned highest_use_count)
+{
+ m_file_path = file_path;
+ if (m_fp)
+ fclose (m_fp);
+ m_fp = fp;
+ if (m_alloc_offset)
+ offset_buffer (-m_alloc_offset);
+ m_nb_read = 0;
+ m_line_start_idx = 0;
+ m_line_num = 0;
+ m_line_record.truncate (0);
+ /* Ensure that this cache entry doesn't get evicted next time
+ add_file_to_cache_tab is called. */
+ m_use_count = ++highest_use_count;
+ m_total_lines = total_lines_num (file_path);
+ m_missing_trailing_newline = true;
+
+
+ /* Check the input configuration to determine if we need to do any
+ transformations, such as charset conversion or BOM skipping. */
+ if (const char *input_charset = in_context.ccb (file_path))
+ {
+ /* Need a full-blown conversion of the input charset. */
+ fclose (m_fp);
+ m_fp = NULL;
+ const cpp_converted_source cs
+ = cpp_get_converted_source (file_path, input_charset);
+ if (!cs.data)
+ return false;
+ if (m_data)
+ XDELETEVEC (m_data);
+ m_data = cs.data;
+ m_nb_read = m_size = cs.len;
+ m_alloc_offset = cs.data - cs.to_free;
+ }
+ else if (in_context.should_skip_bom)
+ {
+ if (read_data ())
+ {
+ const int offset = cpp_check_utf8_bom (m_data, m_nb_read);
+ offset_buffer (offset);
+ m_nb_read -= offset;
+ }
+ }
+
+ return true;
+}
+
+/* file_cache's ctor. */
+
+file_cache::file_cache ()
+: m_file_slots (new file_cache_slot[num_file_slots])
+{
+ initialize_input_context (nullptr, false);
+}
+
+/* file_cache's dtor. */
+
+file_cache::~file_cache ()
+{
+ delete[] m_file_slots;
+}
+
+/* Lookup the cache used for the content of a given file accessed by
+ caret diagnostic. If no cached file was found, create a new cache
+ for this file, add it to the array of cached file and return
+ it. */
+
+file_cache_slot*
+file_cache::lookup_or_add_file (const char *file_path)
+{
+ file_cache_slot *r = lookup_file (file_path);
+ if (r == NULL)
+ r = add_file (file_path);
+ return r;
+}
+
+/* Default constructor for a cache of file used by caret
+ diagnostic. */
+
+file_cache_slot::file_cache_slot ()
+: m_use_count (0), m_file_path (NULL), m_fp (NULL), m_data (0),
+ m_alloc_offset (0), m_size (0), m_nb_read (0), m_line_start_idx (0),
+ m_line_num (0), m_total_lines (0), m_missing_trailing_newline (true)
+{
+ m_line_record.create (0);
+}
+
+/* Destructor for a cache of file used by caret diagnostic. */
+
+file_cache_slot::~file_cache_slot ()
+{
+ if (m_fp)
+ {
+ fclose (m_fp);
+ m_fp = NULL;
+ }
+ if (m_data)
+ {
+ offset_buffer (-m_alloc_offset);
+ XDELETEVEC (m_data);
+ m_data = 0;
+ }
+ m_line_record.release ();
+}
+
+/* Returns TRUE iff the cache would need to be filled with data coming
+ from the file. That is, either the cache is empty or full or the
+ current line is empty. Note that if the cache is full, it would
+ need to be extended and filled again. */
+
+bool
+file_cache_slot::needs_read_p () const
+{
+ return m_fp && (m_nb_read == 0
+ || m_nb_read == m_size
+ || (m_line_start_idx >= m_nb_read - 1));
+}
+
+/* Return TRUE iff the cache is full and thus needs to be
+ extended. */
+
+bool
+file_cache_slot::needs_grow_p () const
+{
+ return m_nb_read == m_size;
+}
+
+/* Grow the cache if it needs to be extended. */
+
+void
+file_cache_slot::maybe_grow ()
+{
+ if (!needs_grow_p ())
+ return;
+
+ if (!m_data)
+ {
+ gcc_assert (m_size == 0 && m_alloc_offset == 0);
+ m_size = buffer_size;
+ m_data = XNEWVEC (char, m_size);
+ }
+ else
+ {
+ const int offset = m_alloc_offset;
+ offset_buffer (-offset);
+ m_size *= 2;
+ m_data = XRESIZEVEC (char, m_data, m_size);
+ offset_buffer (offset);
+ }
+}
+
+/* Read more data into the cache. Extends the cache if need be.
+ Returns TRUE iff new data could be read. */
+
+bool
+file_cache_slot::read_data ()
+{
+ if (feof (m_fp) || ferror (m_fp))
+ return false;
+
+ maybe_grow ();
+
+ char * from = m_data + m_nb_read;
+ size_t to_read = m_size - m_nb_read;
+ size_t nb_read = fread (from, 1, to_read, m_fp);
+
+ if (ferror (m_fp))
+ return false;
+
+ m_nb_read += nb_read;
+ return !!nb_read;
+}
+
+/* Read new data iff the cache needs to be filled with more data
+ coming from the file FP. Return TRUE iff the cache was filled with
+ mode data. */
+
+bool
+file_cache_slot::maybe_read_data ()
+{
+ if (!needs_read_p ())
+ return false;
+ return read_data ();
+}
+
+/* Read a new line from file FP, using C as a cache for the data
+ coming from the file. Upon successful completion, *LINE is set to
+ the beginning of the line found. *LINE points directly in the
+ line cache and is only valid until the next call of get_next_line.
+ *LINE_LEN is set to the length of the line. Note that the line
+ does not contain any terminal delimiter. This function returns
+ true if some data was read or process from the cache, false
+ otherwise. Note that subsequent calls to get_next_line might
+ make the content of *LINE invalid. */
+
+bool
+file_cache_slot::get_next_line (char **line, ssize_t *line_len)
+{
+ /* Fill the cache with data to process. */
+ maybe_read_data ();
+
+ size_t remaining_size = m_nb_read - m_line_start_idx;
+ if (remaining_size == 0)
+ /* There is no more data to process. */
+ return false;
+
+ char *line_start = m_data + m_line_start_idx;
+
+ char *next_line_start = NULL;
+ size_t len = 0;
+ char *line_end = (char *) memchr (line_start, '\n', remaining_size);
+ if (line_end == NULL)
+ {
+ /* We haven't found the end-of-line delimiter in the cache.
+ Fill the cache with more data from the file and look for the
+ '\n'. */
+ while (maybe_read_data ())
+ {
+ line_start = m_data + m_line_start_idx;
+ remaining_size = m_nb_read - m_line_start_idx;
+ line_end = (char *) memchr (line_start, '\n', remaining_size);
+ if (line_end != NULL)
+ {
+ next_line_start = line_end + 1;
+ break;
+ }
+ }
+ if (line_end == NULL)
+ {
+ /* We've loadded all the file into the cache and still no
+ '\n'. Let's say the line ends up at one byte passed the
+ end of the file. This is to stay consistent with the case
+ of when the line ends up with a '\n' and line_end points to
+ that terminal '\n'. That consistency is useful below in
+ the len calculation. */
+ line_end = m_data + m_nb_read ;
+ m_missing_trailing_newline = true;
+ }
+ else
+ m_missing_trailing_newline = false;
+ }
+ else
+ {
+ next_line_start = line_end + 1;
+ m_missing_trailing_newline = false;
+ }
+
+ if (m_fp && ferror (m_fp))
+ return false;
+
+ /* At this point, we've found the end of the of line. It either
+ points to the '\n' or to one byte after the last byte of the
+ file. */
+ gcc_assert (line_end != NULL);
+
+ len = line_end - line_start;
+
+ if (m_line_start_idx < m_nb_read)
+ *line = line_start;
+
+ ++m_line_num;
+
+ /* Before we update our line record, make sure the hint about the
+ total number of lines of the file is correct. If it's not, then
+ we give up recording line boundaries from now on. */
+ bool update_line_record = true;
+ if (m_line_num > m_total_lines)
+ update_line_record = false;
+
+ /* Now update our line record so that re-reading lines from the
+ before m_line_start_idx is faster. */
+ if (update_line_record
+ && m_line_record.length () < line_record_size)
+ {
+ /* If the file lines fits in the line record, we just record all
+ its lines ...*/
+ if (m_total_lines <= line_record_size
+ && m_line_num > m_line_record.length ())
+ m_line_record.safe_push
+ (file_cache_slot::line_info (m_line_num,
+ m_line_start_idx,
+ line_end - m_data));
+ else if (m_total_lines > line_record_size)
+ {
+ /* ... otherwise, we just scale total_lines down to
+ (line_record_size lines. */
+ size_t n = (m_line_num * line_record_size) / m_total_lines;
+ if (m_line_record.length () == 0
+ || n >= m_line_record.length ())
+ m_line_record.safe_push
+ (file_cache_slot::line_info (m_line_num,
+ m_line_start_idx,
+ line_end - m_data));
+ }
+ }
+
+ /* Update m_line_start_idx so that it points to the next line to be
+ read. */
+ if (next_line_start)
+ m_line_start_idx = next_line_start - m_data;
+ else
+ /* We didn't find any terminal '\n'. Let's consider that the end
+ of line is the end of the data in the cache. The next
+ invocation of get_next_line will either read more data from the
+ underlying file or return false early because we've reached the
+ end of the file. */
+ m_line_start_idx = m_nb_read;
+
+ *line_len = len;
+
+ return true;
+}
+
+/* Consume the next bytes coming from the cache (or from its
+ underlying file if there are remaining unread bytes in the file)
+ until we reach the next end-of-line (or end-of-file). There is no
+ copying from the cache involved. Return TRUE upon successful
+ completion. */
+
+bool
+file_cache_slot::goto_next_line ()
+{
+ char *l;
+ ssize_t len;
+
+ return get_next_line (&l, &len);
+}
+
+/* Read an arbitrary line number LINE_NUM from the file cached in C.
+ If the line was read successfully, *LINE points to the beginning
+ of the line in the file cache and *LINE_LEN is the length of the
+ line. *LINE is not nul-terminated, but may contain zero bytes.
+ *LINE is only valid until the next call of read_line_num.
+ This function returns bool if a line was read. */
+
+bool
+file_cache_slot::read_line_num (size_t line_num,
+ char ** line, ssize_t *line_len)
+{
+ gcc_assert (line_num > 0);
+
+ if (line_num <= m_line_num)
+ {
+ /* We've been asked to read lines that are before m_line_num.
+ So lets use our line record (if it's not empty) to try to
+ avoid re-reading the file from the beginning again. */
+
+ if (m_line_record.is_empty ())
+ {
+ m_line_start_idx = 0;
+ m_line_num = 0;
+ }
+ else
+ {
+ file_cache_slot::line_info *i = NULL;
+ if (m_total_lines <= line_record_size)
+ {
+ /* In languages where the input file is not totally
+ preprocessed up front, the m_total_lines hint
+ can be smaller than the number of lines of the
+ file. In that case, only the first
+ m_total_lines have been recorded.
+
+ Otherwise, the first m_total_lines we've read have
+ their start/end recorded here. */
+ i = (line_num <= m_total_lines)
+ ? &m_line_record[line_num - 1]
+ : &m_line_record[m_total_lines - 1];
+ gcc_assert (i->line_num <= line_num);
+ }
+ else
+ {
+ /* So the file had more lines than our line record
+ size. Thus the number of lines we've recorded has
+ been scaled down to line_record_size. Let's
+ pick the start/end of the recorded line that is
+ closest to line_num. */
+ size_t n = (line_num <= m_total_lines)
+ ? line_num * line_record_size / m_total_lines
+ : m_line_record.length () - 1;
+ if (n < m_line_record.length ())
+ {
+ i = &m_line_record[n];
+ gcc_assert (i->line_num <= line_num);
+ }
+ }
+
+ if (i && i->line_num == line_num)
+ {
+ /* We have the start/end of the line. */
+ *line = m_data + i->start_pos;
+ *line_len = i->end_pos - i->start_pos;
+ return true;
+ }
+
+ if (i)
+ {
+ m_line_start_idx = i->start_pos;
+ m_line_num = i->line_num - 1;
+ }
+ else
+ {
+ m_line_start_idx = 0;
+ m_line_num = 0;
+ }
+ }
+ }
+
+ /* Let's walk from line m_line_num up to line_num - 1, without
+ copying any line. */
+ while (m_line_num < line_num - 1)
+ if (!goto_next_line ())
+ return false;
+
+ /* The line we want is the next one. Let's read and copy it back to
+ the caller. */
+ return get_next_line (line, line_len);
+}
+
+/* Return the physical source line that corresponds to FILE_PATH/LINE.
+ The line is not nul-terminated. The returned pointer is only
+ valid until the next call of location_get_source_line.
+ Note that the line can contain several null characters,
+ so the returned value's length has the actual length of the line.
+ If the function fails, a NULL char_span is returned. */
+
+char_span
+location_get_source_line (const char *file_path, int line)
+{
+ char *buffer = NULL;
+ ssize_t len;
+
+ if (line == 0)
+ return char_span (NULL, 0);
+
+ if (file_path == NULL)
+ return char_span (NULL, 0);
+
+ diagnostic_file_cache_init ();
+
+ file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
+ if (c == NULL)
+ return char_span (NULL, 0);
+
+ bool read = c->read_line_num (line, &buffer, &len);
+ if (!read)
+ return char_span (NULL, 0);
+
+ return char_span (buffer, len);
+}
+
+/* Determine if FILE_PATH missing a trailing newline on its final line.
+ Only valid to call once all of the file has been loaded, by
+ requesting a line number beyond the end of the file. */
+
+bool
+location_missing_trailing_newline (const char *file_path)
+{
+ diagnostic_file_cache_init ();
+
+ file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
+ if (c == NULL)
+ return false;
+
+ return c->missing_trailing_newline_p ();
+}
+
+/* Test if the location originates from the spelling location of a
+ builtin-tokens. That is, return TRUE if LOC is a (possibly
+ virtual) location of a built-in token that appears in the expansion
+ list of a macro. Please note that this function also works on
+ tokens that result from built-in tokens. For instance, the
+ function would return true if passed a token "4" that is the result
+ of the expansion of the built-in __LINE__ macro. */
+bool
+is_location_from_builtin_token (location_t loc)
+{
+ const line_map_ordinary *map = NULL;
+ loc = linemap_resolve_location (line_table, loc,
+ LRK_SPELLING_LOCATION, &map);
+ return loc == BUILTINS_LOCATION;
+}
+
+/* Expand the source location LOC into a human readable location. If
+ LOC is virtual, it resolves to the expansion point of the involved
+ macro. If LOC resolves to a builtin location, the file name of the
+ readable location is set to the string "<built-in>". */
+
+expanded_location
+expand_location (location_t loc)
+{
+ return expand_location_1 (loc, /*expansion_point_p=*/true,
+ LOCATION_ASPECT_CARET);
+}
+
+/* Expand the source location LOC into a human readable location. If
+ LOC is virtual, it resolves to the expansion location of the
+ relevant macro. If LOC resolves to a builtin location, the file
+ name of the readable location is set to the string
+ "<built-in>". */
+
+expanded_location
+expand_location_to_spelling_point (location_t loc,
+ enum location_aspect aspect)
+{
+ return expand_location_1 (loc, /*expansion_point_p=*/false, aspect);
+}
+
+/* The rich_location class within libcpp requires a way to expand
+ location_t instances, and relies on the client code
+ providing a symbol named
+ linemap_client_expand_location_to_spelling_point
+ to do this.
+
+ This is the implementation for libcommon.a (all host binaries),
+ which simply calls into expand_location_1. */
+
+expanded_location
+linemap_client_expand_location_to_spelling_point (location_t loc,
+ enum location_aspect aspect)
+{
+ return expand_location_1 (loc, /*expansion_point_p=*/false, aspect);
+}
+
+
+/* If LOCATION is in a system header and if it is a virtual location
+ for a token coming from the expansion of a macro, unwind it to
+ the location of the expansion point of the macro. If the expansion
+ point is also in a system header return the original LOCATION.
+ Otherwise, return the location of the expansion point.
+
+ This is used for instance when we want to emit diagnostics about a
+ token that may be located in a macro that is itself defined in a
+ system header, for example, for the NULL macro. In such a case, if
+ LOCATION were passed directly to diagnostic functions such as
+ warning_at, the diagnostic would be suppressed (unless
+ -Wsystem-headers). */
+
+location_t
+expansion_point_location_if_in_system_header (location_t location)
+{
+ if (!in_system_header_at (location))
+ return location;
+
+ location_t xloc = linemap_resolve_location (line_table, location,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+ return in_system_header_at (xloc) ? location : xloc;
+}
+
+/* If LOCATION is a virtual location for a token coming from the expansion
+ of a macro, unwind to the location of the expansion point of the macro. */
+
+location_t
+expansion_point_location (location_t location)
+{
+ return linemap_resolve_location (line_table, location,
+ LRK_MACRO_EXPANSION_POINT, NULL);
+}
+
+/* Construct a location with caret at CARET, ranging from START to
+ finish e.g.
+
+ 11111111112
+ 12345678901234567890
+ 522
+ 523 return foo + bar;
+ ~~~~^~~~~
+ 524
+
+ The location's caret is at the "+", line 523 column 15, but starts
+ earlier, at the "f" of "foo" at column 11. The finish is at the "r"
+ of "bar" at column 19. */
+
+location_t
+make_location (location_t caret, location_t start, location_t finish)
+{
+ location_t pure_loc = get_pure_location (caret);
+ source_range src_range;
+ src_range.m_start = get_start (start);
+ src_range.m_finish = get_finish (finish);
+ location_t combined_loc = COMBINE_LOCATION_DATA (line_table,
+ pure_loc,
+ src_range,
+ NULL);
+ return combined_loc;
+}
+
+/* Same as above, but taking a source range rather than two locations. */
+
+location_t
+make_location (location_t caret, source_range src_range)
+{
+ location_t pure_loc = get_pure_location (caret);
+ return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, NULL);
+}
+
+/* An expanded_location stores the column in byte units. This function
+ converts that column to display units. That requires reading the associated
+ source line in order to calculate the display width. If that cannot be done
+ for any reason, then returns the byte column as a fallback. */
+int
+location_compute_display_column (expanded_location exploc,
+ const cpp_char_column_policy &policy)
+{
+ if (!(exploc.file && *exploc.file && exploc.line && exploc.column))
+ return exploc.column;
+ char_span line = location_get_source_line (exploc.file, exploc.line);
+ /* If line is NULL, this function returns exploc.column which is the
+ desired fallback. */
+ return cpp_byte_column_to_display_column (line.get_buffer (), line.length (),
+ exploc.column, policy);
+}
+
+/* Dump statistics to stderr about the memory usage of the line_table
+ set of line maps. This also displays some statistics about macro
+ expansion. */
+
+void
+dump_line_table_statistics (void)
+{
+ struct linemap_stats s;
+ long total_used_map_size,
+ macro_maps_size,
+ total_allocated_map_size;
+
+ memset (&s, 0, sizeof (s));
+
+ linemap_get_statistics (line_table, &s);
+
+ macro_maps_size = s.macro_maps_used_size
+ + s.macro_maps_locations_size;
+
+ total_allocated_map_size = s.ordinary_maps_allocated_size
+ + s.macro_maps_allocated_size
+ + s.macro_maps_locations_size;
+
+ total_used_map_size = s.ordinary_maps_used_size
+ + s.macro_maps_used_size
+ + s.macro_maps_locations_size;
+
+ fprintf (stderr, "Number of expanded macros: %5ld\n",
+ s.num_expanded_macros);
+ if (s.num_expanded_macros != 0)
+ fprintf (stderr, "Average number of tokens per macro expansion: %5ld\n",
+ s.num_macro_tokens / s.num_expanded_macros);
+ fprintf (stderr,
+ "\nLine Table allocations during the "
+ "compilation process\n");
+ fprintf (stderr, "Number of ordinary maps used: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.num_ordinary_maps_used));
+ fprintf (stderr, "Ordinary map used size: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.ordinary_maps_used_size));
+ fprintf (stderr, "Number of ordinary maps allocated: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.num_ordinary_maps_allocated));
+ fprintf (stderr, "Ordinary maps allocated size: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.ordinary_maps_allocated_size));
+ fprintf (stderr, "Number of macro maps used: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.num_macro_maps_used));
+ fprintf (stderr, "Macro maps used size: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.macro_maps_used_size));
+ fprintf (stderr, "Macro maps locations size: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.macro_maps_locations_size));
+ fprintf (stderr, "Macro maps size: " PRsa (5) "\n",
+ SIZE_AMOUNT (macro_maps_size));
+ fprintf (stderr, "Duplicated maps locations size: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.duplicated_macro_maps_locations_size));
+ fprintf (stderr, "Total allocated maps size: " PRsa (5) "\n",
+ SIZE_AMOUNT (total_allocated_map_size));
+ fprintf (stderr, "Total used maps size: " PRsa (5) "\n",
+ SIZE_AMOUNT (total_used_map_size));
+ fprintf (stderr, "Ad-hoc table size: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.adhoc_table_size));
+ fprintf (stderr, "Ad-hoc table entries used: " PRsa (5) "\n",
+ SIZE_AMOUNT (s.adhoc_table_entries_used));
+ fprintf (stderr, "optimized_ranges: " PRsa (5) "\n",
+ SIZE_AMOUNT (line_table->num_optimized_ranges));
+ fprintf (stderr, "unoptimized_ranges: " PRsa (5) "\n",
+ SIZE_AMOUNT (line_table->num_unoptimized_ranges));
+
+ fprintf (stderr, "\n");
+}
+
+/* Get location one beyond the final location in ordinary map IDX. */
+
+static location_t
+get_end_location (class line_maps *set, unsigned int idx)
+{
+ if (idx == LINEMAPS_ORDINARY_USED (set) - 1)
+ return set->highest_location;
+
+ struct line_map *next_map = LINEMAPS_ORDINARY_MAP_AT (set, idx + 1);
+ return MAP_START_LOCATION (next_map);
+}
+
+/* Helper function for write_digit_row. */
+
+static void
+write_digit (FILE *stream, int digit)
+{
+ fputc ('0' + (digit % 10), stream);
+}
+
+/* Helper function for dump_location_info.
+ Write a row of numbers to STREAM, numbering a source line,
+ giving the units, tens, hundreds etc of the column number. */
+
+static void
+write_digit_row (FILE *stream, int indent,
+ const line_map_ordinary *map,
+ location_t loc, int max_col, int divisor)
+{
+ fprintf (stream, "%*c", indent, ' ');
+ fprintf (stream, "|");
+ for (int column = 1; column < max_col; column++)
+ {
+ location_t column_loc = loc + (column << map->m_range_bits);
+ write_digit (stream, column_loc / divisor);
+ }
+ fprintf (stream, "\n");
+}
+
+/* Write a half-closed (START) / half-open (END) interval of
+ location_t to STREAM. */
+
+static void
+dump_location_range (FILE *stream,
+ location_t start, location_t end)
+{
+ fprintf (stream,
+ " location_t interval: %u <= loc < %u\n",
+ start, end);
+}
+
+/* Write a labelled description of a half-closed (START) / half-open (END)
+ interval of location_t to STREAM. */
+
+static void
+dump_labelled_location_range (FILE *stream,
+ const char *name,
+ location_t start, location_t end)
+{
+ fprintf (stream, "%s\n", name);
+ dump_location_range (stream, start, end);
+ fprintf (stream, "\n");
+}
+
+/* Write a visualization of the locations in the line_table to STREAM. */
+
+void
+dump_location_info (FILE *stream)
+{
+ /* Visualize the reserved locations. */
+ dump_labelled_location_range (stream, "RESERVED LOCATIONS",
+ 0, RESERVED_LOCATION_COUNT);
+
+ /* Visualize the ordinary line_map instances, rendering the sources. */
+ for (unsigned int idx = 0; idx < LINEMAPS_ORDINARY_USED (line_table); idx++)
+ {
+ location_t end_location = get_end_location (line_table, idx);
+ /* half-closed: doesn't include this one. */
+
+ const line_map_ordinary *map
+ = LINEMAPS_ORDINARY_MAP_AT (line_table, idx);
+ fprintf (stream, "ORDINARY MAP: %i\n", idx);
+ dump_location_range (stream,
+ MAP_START_LOCATION (map), end_location);
+ fprintf (stream, " file: %s\n", ORDINARY_MAP_FILE_NAME (map));
+ fprintf (stream, " starting at line: %i\n",
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map));
+ fprintf (stream, " column and range bits: %i\n",
+ map->m_column_and_range_bits);
+ fprintf (stream, " column bits: %i\n",
+ map->m_column_and_range_bits - map->m_range_bits);
+ fprintf (stream, " range bits: %i\n",
+ map->m_range_bits);
+ const char * reason;
+ switch (map->reason) {
+ case LC_ENTER:
+ reason = "LC_ENTER";
+ break;
+ case LC_LEAVE:
+ reason = "LC_LEAVE";
+ break;
+ case LC_RENAME:
+ reason = "LC_RENAME";
+ break;
+ case LC_RENAME_VERBATIM:
+ reason = "LC_RENAME_VERBATIM";
+ break;
+ case LC_ENTER_MACRO:
+ reason = "LC_RENAME_MACRO";
+ break;
+ default:
+ reason = "Unknown";
+ }
+ fprintf (stream, " reason: %d (%s)\n", map->reason, reason);
+
+ const line_map_ordinary *includer_map
+ = linemap_included_from_linemap (line_table, map);
+ fprintf (stream, " included from location: %d",
+ linemap_included_from (map));
+ if (includer_map) {
+ fprintf (stream, " (in ordinary map %d)",
+ int (includer_map - line_table->info_ordinary.maps));
+ }
+ fprintf (stream, "\n");
+
+ /* Render the span of source lines that this "map" covers. */
+ for (location_t loc = MAP_START_LOCATION (map);
+ loc < end_location;
+ loc += (1 << map->m_range_bits) )
+ {
+ gcc_assert (pure_location_p (line_table, loc) );
+
+ expanded_location exploc
+ = linemap_expand_location (line_table, map, loc);
+
+ if (exploc.column == 0)
+ {
+ /* Beginning of a new source line: draw the line. */
+
+ char_span line_text = location_get_source_line (exploc.file,
+ exploc.line);
+ if (!line_text)
+ break;
+ fprintf (stream,
+ "%s:%3i|loc:%5i|%.*s\n",
+ exploc.file, exploc.line,
+ loc,
+ (int)line_text.length (), line_text.get_buffer ());
+
+ /* "loc" is at column 0, which means "the whole line".
+ Render the locations *within* the line, by underlining
+ it, showing the location_t numeric values
+ at each column. */
+ size_t max_col = (1 << map->m_column_and_range_bits) - 1;
+ if (max_col > line_text.length ())
+ max_col = line_text.length () + 1;
+
+ int len_lnum = num_digits (exploc.line);
+ if (len_lnum < 3)
+ len_lnum = 3;
+ int len_loc = num_digits (loc);
+ if (len_loc < 5)
+ len_loc = 5;
+
+ int indent = 6 + strlen (exploc.file) + len_lnum + len_loc;
+
+ /* Thousands. */
+ if (end_location > 999)
+ write_digit_row (stream, indent, map, loc, max_col, 1000);
+
+ /* Hundreds. */
+ if (end_location > 99)
+ write_digit_row (stream, indent, map, loc, max_col, 100);
+
+ /* Tens. */
+ write_digit_row (stream, indent, map, loc, max_col, 10);
+
+ /* Units. */
+ write_digit_row (stream, indent, map, loc, max_col, 1);
+ }
+ }
+ fprintf (stream, "\n");
+ }
+
+ /* Visualize unallocated values. */
+ dump_labelled_location_range (stream, "UNALLOCATED LOCATIONS",
+ line_table->highest_location,
+ LINEMAPS_MACRO_LOWEST_LOCATION (line_table));
+
+ /* Visualize the macro line_map instances, rendering the sources. */
+ for (unsigned int i = 0; i < LINEMAPS_MACRO_USED (line_table); i++)
+ {
+ /* Each macro map that is allocated owns location_t values
+ that are *lower* that the one before them.
+ Hence it's meaningful to view them either in order of ascending
+ source locations, or in order of ascending macro map index. */
+ const bool ascending_location_ts = true;
+ unsigned int idx = (ascending_location_ts
+ ? (LINEMAPS_MACRO_USED (line_table) - (i + 1))
+ : i);
+ const line_map_macro *map = LINEMAPS_MACRO_MAP_AT (line_table, idx);
+ fprintf (stream, "MACRO %i: %s (%u tokens)\n",
+ idx,
+ linemap_map_get_macro_name (map),
+ MACRO_MAP_NUM_MACRO_TOKENS (map));
+ dump_location_range (stream,
+ map->start_location,
+ (map->start_location
+ + MACRO_MAP_NUM_MACRO_TOKENS (map)));
+ inform (MACRO_MAP_EXPANSION_POINT_LOCATION (map),
+ "expansion point is location %i",
+ MACRO_MAP_EXPANSION_POINT_LOCATION (map));
+ fprintf (stream, " map->start_location: %u\n",
+ map->start_location);
+
+ fprintf (stream, " macro_locations:\n");
+ for (unsigned int i = 0; i < MACRO_MAP_NUM_MACRO_TOKENS (map); i++)
+ {
+ location_t x = MACRO_MAP_LOCATIONS (map)[2 * i];
+ location_t y = MACRO_MAP_LOCATIONS (map)[(2 * i) + 1];
+
+ /* linemap_add_macro_token encodes token numbers in an expansion
+ by putting them after MAP_START_LOCATION. */
+
+ /* I'm typically seeing 4 uninitialized entries at the end of
+ 0xafafafaf.
+ This appears to be due to macro.cc:replace_args
+ adding 2 extra args for padding tokens; presumably there may
+ be a leading and/or trailing padding token injected,
+ each for 2 more location slots.
+ This would explain there being up to 4 location_ts slots
+ that may be uninitialized. */
+
+ fprintf (stream, " %u: %u, %u\n",
+ i,
+ x,
+ y);
+ if (x == y)
+ {
+ if (x < MAP_START_LOCATION (map))
+ inform (x, "token %u has %<x-location == y-location == %u%>",
+ i, x);
+ else
+ fprintf (stream,
+ "x-location == y-location == %u encodes token # %u\n",
+ x, x - MAP_START_LOCATION (map));
+ }
+ else
+ {
+ inform (x, "token %u has %<x-location == %u%>", i, x);
+ inform (x, "token %u has %<y-location == %u%>", i, y);
+ }
+ }
+ fprintf (stream, "\n");
+ }
+
+ /* It appears that MAX_LOCATION_T itself is never assigned to a
+ macro map, presumably due to an off-by-one error somewhere
+ between the logic in linemap_enter_macro and
+ LINEMAPS_MACRO_LOWEST_LOCATION. */
+ dump_labelled_location_range (stream, "MAX_LOCATION_T",
+ MAX_LOCATION_T,
+ MAX_LOCATION_T + 1);
+
+ /* Visualize ad-hoc values. */
+ dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
+ MAX_LOCATION_T + 1, UINT_MAX);
+}
+
+/* string_concat's constructor. */
+
+string_concat::string_concat (int num, location_t *locs)
+ : m_num (num)
+{
+ m_locs = ggc_vec_alloc <location_t> (num);
+ for (int i = 0; i < num; i++)
+ m_locs[i] = locs[i];
+}
+
+/* string_concat_db's constructor. */
+
+string_concat_db::string_concat_db ()
+{
+ m_table = hash_map <location_hash, string_concat *>::create_ggc (64);
+}
+
+/* Record that a string concatenation occurred, covering NUM
+ string literal tokens. LOCS is an array of size NUM, containing the
+ locations of the tokens. A copy of LOCS is taken. */
+
+void
+string_concat_db::record_string_concatenation (int num, location_t *locs)
+{
+ gcc_assert (num > 1);
+ gcc_assert (locs);
+
+ location_t key_loc = get_key_loc (locs[0]);
+ /* We don't record data for 'RESERVED_LOCATION_P (key_loc)' key values:
+ any data now recorded under key 'key_loc' would be overwritten by a
+ subsequent call with the same key 'key_loc'. */
+ if (RESERVED_LOCATION_P (key_loc))
+ return;
+
+ string_concat *concat
+ = new (ggc_alloc <string_concat> ()) string_concat (num, locs);
+ m_table->put (key_loc, concat);
+}
+
+/* Determine if LOC was the location of the initial token of a
+ concatenation of string literal tokens.
+ If so, *OUT_NUM is written to with the number of tokens, and
+ *OUT_LOCS with the location of an array of locations of the
+ tokens, and return true. *OUT_LOCS is a borrowed pointer to
+ storage owned by the string_concat_db.
+ Otherwise, return false. */
+
+bool
+string_concat_db::get_string_concatenation (location_t loc,
+ int *out_num,
+ location_t **out_locs)
+{
+ gcc_assert (out_num);
+ gcc_assert (out_locs);
+
+ location_t key_loc = get_key_loc (loc);
+ /* We don't record data for 'RESERVED_LOCATION_P (key_loc)' key values; see
+ discussion in 'string_concat_db::record_string_concatenation'. */
+ if (RESERVED_LOCATION_P (key_loc))
+ return false;
+
+ string_concat **concat = m_table->get (key_loc);
+ if (!concat)
+ return false;
+
+ *out_num = (*concat)->m_num;
+ *out_locs =(*concat)->m_locs;
+ return true;
+}
+
+/* Internal function. Canonicalize LOC into a form suitable for
+ use as a key within the database, stripping away macro expansion,
+ ad-hoc information, and range information, using the location of
+ the start of LOC within an ordinary linemap. */
+
+location_t
+string_concat_db::get_key_loc (location_t loc)
+{
+ loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION,
+ NULL);
+
+ loc = get_range_from_loc (line_table, loc).m_start;
+
+ return loc;
+}
+
+/* Helper class for use within get_substring_ranges_for_loc.
+ An vec of cpp_string with responsibility for releasing all of the
+ str->text for each str in the vector. */
+
+class auto_cpp_string_vec : public auto_vec <cpp_string>
+{
+ public:
+ auto_cpp_string_vec (int alloc)
+ : auto_vec <cpp_string> (alloc) {}
+
+ ~auto_cpp_string_vec ()
+ {
+ /* Clean up the copies within this vec. */
+ int i;
+ cpp_string *str;
+ FOR_EACH_VEC_ELT (*this, i, str)
+ free (const_cast <unsigned char *> (str->text));
+ }
+};
+
+/* Attempt to populate RANGES with source location information on the
+ individual characters within the string literal found at STRLOC.
+ If CONCATS is non-NULL, then any string literals that the token at
+ STRLOC was concatenated with are also added to RANGES.
+
+ Return NULL if successful, or an error message if any errors occurred (in
+ which case RANGES may be only partially populated and should not
+ be used).
+
+ This is implemented by re-parsing the relevant source line(s). */
+
+static const char *
+get_substring_ranges_for_loc (cpp_reader *pfile,
+ string_concat_db *concats,
+ location_t strloc,
+ enum cpp_ttype type,
+ cpp_substring_ranges &ranges)
+{
+ gcc_assert (pfile);
+
+ if (strloc == UNKNOWN_LOCATION)
+ return "unknown location";
+
+ /* Reparsing the strings requires accurate location information.
+ If -ftrack-macro-expansion has been overridden from its default
+ of 2, then we might have a location of a macro expansion point,
+ rather than the location of the literal itself.
+ Avoid this by requiring that we have full macro expansion tracking
+ for substring locations to be available. */
+ if (cpp_get_options (pfile)->track_macro_expansion != 2)
+ return "track_macro_expansion != 2";
+
+ /* If #line or # 44 "file"-style directives are present, then there's
+ no guarantee that the line numbers we have can be used to locate
+ the strings. For example, we might have a .i file with # directives
+ pointing back to lines within a .c file, but the .c file might
+ have been edited since the .i file was created.
+ In such a case, the safest course is to disable on-demand substring
+ locations. */
+ if (line_table->seen_line_directive)
+ return "seen line directive";
+
+ /* If string concatenation has occurred at STRLOC, get the locations
+ of all of the literal tokens making up the compound string.
+ Otherwise, just use STRLOC. */
+ int num_locs = 1;
+ location_t *strlocs = &strloc;
+ if (concats)
+ concats->get_string_concatenation (strloc, &num_locs, &strlocs);
+
+ auto_cpp_string_vec strs (num_locs);
+ auto_vec <cpp_string_location_reader> loc_readers (num_locs);
+ for (int i = 0; i < num_locs; i++)
+ {
+ /* Get range of strloc. We will use it to locate the start and finish
+ of the literal token within the line. */
+ source_range src_range = get_range_from_loc (line_table, strlocs[i]);
+
+ if (src_range.m_start >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
+ {
+ /* If the string token was within a macro expansion, then we can
+ cope with it for the simple case where we have a single token.
+ Otherwise, bail out. */
+ if (src_range.m_start != src_range.m_finish)
+ return "macro expansion";
+ }
+ else
+ {
+ if (src_range.m_start >= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* If so, we can't reliably determine where the token started within
+ its line. */
+ return "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS";
+
+ if (src_range.m_finish >= LINE_MAP_MAX_LOCATION_WITH_COLS)
+ /* If so, we can't reliably determine where the token finished
+ within its line. */
+ return "range ends after LINE_MAP_MAX_LOCATION_WITH_COLS";
+ }
+
+ expanded_location start
+ = expand_location_to_spelling_point (src_range.m_start,
+ LOCATION_ASPECT_START);
+ expanded_location finish
+ = expand_location_to_spelling_point (src_range.m_finish,
+ LOCATION_ASPECT_FINISH);
+ if (start.file != finish.file)
+ return "range endpoints are in different files";
+ if (start.line != finish.line)
+ return "range endpoints are on different lines";
+ if (start.column > finish.column)
+ return "range endpoints are reversed";
+
+ char_span line = location_get_source_line (start.file, start.line);
+ if (!line)
+ return "unable to read source line";
+
+ /* Determine the location of the literal (including quotes
+ and leading prefix chars, such as the 'u' in a u""
+ token). */
+ size_t literal_length = finish.column - start.column + 1;
+
+ /* Ensure that we don't crash if we got the wrong location. */
+ if (start.column < 1)
+ return "zero start column";
+ if (line.length () < (start.column - 1 + literal_length))
+ return "line is not wide enough";
+
+ char_span literal = line.subspan (start.column - 1, literal_length);
+
+ cpp_string from;
+ from.len = literal_length;
+ /* Make a copy of the literal, to avoid having to rely on
+ the lifetime of the copy of the line within the cache.
+ This will be released by the auto_cpp_string_vec dtor. */
+ from.text = (unsigned char *)literal.xstrdup ();
+ strs.safe_push (from);
+
+ /* For very long lines, a new linemap could have started
+ halfway through the token.
+ Ensure that the loc_reader uses the linemap of the
+ *end* of the token for its start location. */
+ const line_map_ordinary *start_ord_map;
+ linemap_resolve_location (line_table, src_range.m_start,
+ LRK_SPELLING_LOCATION, &start_ord_map);
+ const line_map_ordinary *final_ord_map;
+ linemap_resolve_location (line_table, src_range.m_finish,
+ LRK_SPELLING_LOCATION, &final_ord_map);
+ if (start_ord_map == NULL || final_ord_map == NULL)
+ return "failed to get ordinary maps";
+ /* Bulletproofing. We ought to only have different ordinary maps
+ for start vs finish due to line-length jumps. */
+ if (start_ord_map != final_ord_map
+ && start_ord_map->to_file != final_ord_map->to_file)
+ return "start and finish are spelled in different ordinary maps";
+ /* The file from linemap_resolve_location ought to match that from
+ expand_location_to_spelling_point. */
+ if (start_ord_map->to_file != start.file)
+ return "mismatching file after resolving linemap";
+
+ location_t start_loc
+ = linemap_position_for_line_and_column (line_table, final_ord_map,
+ start.line, start.column);
+
+ cpp_string_location_reader loc_reader (start_loc, line_table);
+ loc_readers.safe_push (loc_reader);
+ }
+
+ /* Rerun cpp_interpret_string, or rather, a modified version of it. */
+ const char *err = cpp_interpret_string_ranges (pfile, strs.address (),
+ loc_readers.address (),
+ num_locs, &ranges, type);
+ if (err)
+ return err;
+
+ /* Success: "ranges" should now contain information on the string. */
+ return NULL;
+}
+
+/* Attempt to populate *OUT_LOC with source location information on the
+ given characters within the string literal found at STRLOC.
+ CARET_IDX, START_IDX, and END_IDX refer to offsets within the execution
+ character set.
+
+ For example, given CARET_IDX = 4, START_IDX = 3, END_IDX = 7
+ and string literal "012345\n789"
+ *OUT_LOC is written to with:
+ "012345\n789"
+ ~^~~~~
+
+ If CONCATS is non-NULL, then any string literals that the token at
+ STRLOC was concatenated with are also considered.
+
+ This is implemented by re-parsing the relevant source line(s).
+
+ Return NULL if successful, or an error message if any errors occurred.
+ Error messages are intended for GCC developers (to help debugging) rather
+ than for end-users. */
+
+const char *
+get_location_within_string (cpp_reader *pfile,
+ string_concat_db *concats,
+ location_t strloc,
+ enum cpp_ttype type,
+ int caret_idx, int start_idx, int end_idx,
+ location_t *out_loc)
+{
+ gcc_checking_assert (caret_idx >= 0);
+ gcc_checking_assert (start_idx >= 0);
+ gcc_checking_assert (end_idx >= 0);
+ gcc_assert (out_loc);
+
+ cpp_substring_ranges ranges;
+ const char *err
+ = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
+ if (err)
+ return err;
+
+ if (caret_idx >= ranges.get_num_ranges ())
+ return "caret_idx out of range";
+ if (start_idx >= ranges.get_num_ranges ())
+ return "start_idx out of range";
+ if (end_idx >= ranges.get_num_ranges ())
+ return "end_idx out of range";
+
+ *out_loc = make_location (ranges.get_range (caret_idx).m_start,
+ ranges.get_range (start_idx).m_start,
+ ranges.get_range (end_idx).m_finish);
+ return NULL;
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests of location handling. */
+
+/* Attempt to populate *OUT_RANGE with source location information on the
+ given character within the string literal found at STRLOC.
+ CHAR_IDX refers to an offset within the execution character set.
+ If CONCATS is non-NULL, then any string literals that the token at
+ STRLOC was concatenated with are also considered.
+
+ This is implemented by re-parsing the relevant source line(s).
+
+ Return NULL if successful, or an error message if any errors occurred.
+ Error messages are intended for GCC developers (to help debugging) rather
+ than for end-users. */
+
+static const char *
+get_source_range_for_char (cpp_reader *pfile,
+ string_concat_db *concats,
+ location_t strloc,
+ enum cpp_ttype type,
+ int char_idx,
+ source_range *out_range)
+{
+ gcc_checking_assert (char_idx >= 0);
+ gcc_assert (out_range);
+
+ cpp_substring_ranges ranges;
+ const char *err
+ = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
+ if (err)
+ return err;
+
+ if (char_idx >= ranges.get_num_ranges ())
+ return "char_idx out of range";
+
+ *out_range = ranges.get_range (char_idx);
+ return NULL;
+}
+
+/* As get_source_range_for_char, but write to *OUT the number
+ of ranges that are available. */
+
+static const char *
+get_num_source_ranges_for_substring (cpp_reader *pfile,
+ string_concat_db *concats,
+ location_t strloc,
+ enum cpp_ttype type,
+ int *out)
+{
+ gcc_assert (out);
+
+ cpp_substring_ranges ranges;
+ const char *err
+ = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
+
+ if (err)
+ return err;
+
+ *out = ranges.get_num_ranges ();
+ return NULL;
+}
+
+/* Selftests of location handling. */
+
+/* Verify that compare() on linenum_type handles comparisons over the full
+ range of the type. */
+
+static void
+test_linenum_comparisons ()
+{
+ linenum_type min_line (0);
+ linenum_type max_line (0xffffffff);
+ ASSERT_EQ (0, compare (min_line, min_line));
+ ASSERT_EQ (0, compare (max_line, max_line));
+
+ ASSERT_GT (compare (max_line, min_line), 0);
+ ASSERT_LT (compare (min_line, max_line), 0);
+}
+
+/* Helper function for verifying location data: when location_t
+ values are > LINE_MAP_MAX_LOCATION_WITH_COLS, they are treated
+ as having column 0. */
+
+static bool
+should_have_column_data_p (location_t loc)
+{
+ if (IS_ADHOC_LOC (loc))
+ loc = get_location_from_adhoc_loc (line_table, loc);
+ if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return false;
+ return true;
+}
+
+/* Selftest for should_have_column_data_p. */
+
+static void
+test_should_have_column_data_p ()
+{
+ ASSERT_TRUE (should_have_column_data_p (RESERVED_LOCATION_COUNT));
+ ASSERT_TRUE
+ (should_have_column_data_p (LINE_MAP_MAX_LOCATION_WITH_COLS));
+ ASSERT_FALSE
+ (should_have_column_data_p (LINE_MAP_MAX_LOCATION_WITH_COLS + 1));
+}
+
+/* Verify the result of LOCATION_FILE/LOCATION_LINE/LOCATION_COLUMN
+ on LOC. */
+
+static void
+assert_loceq (const char *exp_filename, int exp_linenum, int exp_colnum,
+ location_t loc)
+{
+ ASSERT_STREQ (exp_filename, LOCATION_FILE (loc));
+ ASSERT_EQ (exp_linenum, LOCATION_LINE (loc));
+ /* If location_t values are sufficiently high, then column numbers
+ will be unavailable and LOCATION_COLUMN (loc) will be 0.
+ When close to the threshold, column numbers *may* be present: if
+ the final linemap before the threshold contains a line that straddles
+ the threshold, locations in that line have column information. */
+ if (should_have_column_data_p (loc))
+ ASSERT_EQ (exp_colnum, LOCATION_COLUMN (loc));
+}
+
+/* Various selftests involve constructing a line table and one or more
+ line maps within it.
+
+ For maximum test coverage we want to run these tests with a variety
+ of situations:
+ - line_table->default_range_bits: some frontends use a non-zero value
+ and others use zero
+ - the fallback modes within line-map.cc: there are various threshold
+ values for location_t beyond line-map.cc changes
+ behavior (disabling of the range-packing optimization, disabling
+ of column-tracking). We can exercise these by starting the line_table
+ at interesting values at or near these thresholds.
+
+ The following struct describes a particular case within our test
+ matrix. */
+
+class line_table_case
+{
+public:
+ line_table_case (int default_range_bits, int base_location)
+ : m_default_range_bits (default_range_bits),
+ m_base_location (base_location)
+ {}
+
+ int m_default_range_bits;
+ int m_base_location;
+};
+
+/* Constructor. Store the old value of line_table, and create a new
+ one, using sane defaults. */
+
+line_table_test::line_table_test ()
+{
+ gcc_assert (saved_line_table == NULL);
+ saved_line_table = line_table;
+ line_table = ggc_alloc<line_maps> ();
+ linemap_init (line_table, BUILTINS_LOCATION);
+ gcc_assert (saved_line_table->reallocator);
+ line_table->reallocator = saved_line_table->reallocator;
+ gcc_assert (saved_line_table->round_alloc_size);
+ line_table->round_alloc_size = saved_line_table->round_alloc_size;
+ line_table->default_range_bits = 0;
+}
+
+/* Constructor. Store the old value of line_table, and create a new
+ one, using the sitation described in CASE_. */
+
+line_table_test::line_table_test (const line_table_case &case_)
+{
+ gcc_assert (saved_line_table == NULL);
+ saved_line_table = line_table;
+ line_table = ggc_alloc<line_maps> ();
+ linemap_init (line_table, BUILTINS_LOCATION);
+ gcc_assert (saved_line_table->reallocator);
+ line_table->reallocator = saved_line_table->reallocator;
+ gcc_assert (saved_line_table->round_alloc_size);
+ line_table->round_alloc_size = saved_line_table->round_alloc_size;
+ line_table->default_range_bits = case_.m_default_range_bits;
+ if (case_.m_base_location)
+ {
+ line_table->highest_location = case_.m_base_location;
+ line_table->highest_line = case_.m_base_location;
+ }
+}
+
+/* Destructor. Restore the old value of line_table. */
+
+line_table_test::~line_table_test ()
+{
+ gcc_assert (saved_line_table != NULL);
+ line_table = saved_line_table;
+ saved_line_table = NULL;
+}
+
+/* Verify basic operation of ordinary linemaps. */
+
+static void
+test_accessing_ordinary_linemaps (const line_table_case &case_)
+{
+ line_table_test ltt (case_);
+
+ /* Build a simple linemap describing some locations. */
+ linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
+
+ linemap_line_start (line_table, 1, 100);
+ location_t loc_a = linemap_position_for_column (line_table, 1);
+ location_t loc_b = linemap_position_for_column (line_table, 23);
+
+ linemap_line_start (line_table, 2, 100);
+ location_t loc_c = linemap_position_for_column (line_table, 1);
+ location_t loc_d = linemap_position_for_column (line_table, 17);
+
+ /* Example of a very long line. */
+ linemap_line_start (line_table, 3, 2000);
+ location_t loc_e = linemap_position_for_column (line_table, 700);
+
+ /* Transitioning back to a short line. */
+ linemap_line_start (line_table, 4, 0);
+ location_t loc_back_to_short = linemap_position_for_column (line_table, 100);
+
+ if (should_have_column_data_p (loc_back_to_short))
+ {
+ /* Verify that we switched to short lines in the linemap. */
+ line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+ ASSERT_EQ (7, map->m_column_and_range_bits - map->m_range_bits);
+ }
+
+ /* Example of a line that will eventually be seen to be longer
+ than LINE_MAP_MAX_COLUMN_NUMBER; the initially seen width is
+ below that. */
+ linemap_line_start (line_table, 5, 2000);
+
+ location_t loc_start_of_very_long_line
+ = linemap_position_for_column (line_table, 2000);
+ location_t loc_too_wide
+ = linemap_position_for_column (line_table, 4097);
+ location_t loc_too_wide_2
+ = linemap_position_for_column (line_table, 4098);
+
+ /* ...and back to a sane line length. */
+ linemap_line_start (line_table, 6, 100);
+ location_t loc_sane_again = linemap_position_for_column (line_table, 10);
+
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+ /* Multiple files. */
+ linemap_add (line_table, LC_ENTER, false, "bar.c", 0);
+ linemap_line_start (line_table, 1, 200);
+ location_t loc_f = linemap_position_for_column (line_table, 150);
+ linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+ /* Verify that we can recover the location info. */
+ assert_loceq ("foo.c", 1, 1, loc_a);
+ assert_loceq ("foo.c", 1, 23, loc_b);
+ assert_loceq ("foo.c", 2, 1, loc_c);
+ assert_loceq ("foo.c", 2, 17, loc_d);
+ assert_loceq ("foo.c", 3, 700, loc_e);
+ assert_loceq ("foo.c", 4, 100, loc_back_to_short);
+
+ /* In the very wide line, the initial location should be fully tracked. */
+ assert_loceq ("foo.c", 5, 2000, loc_start_of_very_long_line);
+ /* ...but once we exceed LINE_MAP_MAX_COLUMN_NUMBER column-tracking should
+ be disabled. */
+ assert_loceq ("foo.c", 5, 0, loc_too_wide);
+ assert_loceq ("foo.c", 5, 0, loc_too_wide_2);
+ /*...and column-tracking should be re-enabled for subsequent lines. */
+ assert_loceq ("foo.c", 6, 10, loc_sane_again);
+
+ assert_loceq ("bar.c", 1, 150, loc_f);
+
+ ASSERT_FALSE (is_location_from_builtin_token (loc_a));
+ ASSERT_TRUE (pure_location_p (line_table, loc_a));
+
+ /* Verify using make_location to build a range, and extracting data
+ back from it. */
+ location_t range_c_b_d = make_location (loc_c, loc_b, loc_d);
+ ASSERT_FALSE (pure_location_p (line_table, range_c_b_d));
+ ASSERT_EQ (loc_c, get_location_from_adhoc_loc (line_table, range_c_b_d));
+ source_range src_range = get_range_from_loc (line_table, range_c_b_d);
+ ASSERT_EQ (loc_b, src_range.m_start);
+ ASSERT_EQ (loc_d, src_range.m_finish);
+}
+
+/* Verify various properties of UNKNOWN_LOCATION. */
+
+static void
+test_unknown_location ()
+{
+ ASSERT_EQ (NULL, LOCATION_FILE (UNKNOWN_LOCATION));
+ ASSERT_EQ (0, LOCATION_LINE (UNKNOWN_LOCATION));
+ ASSERT_EQ (0, LOCATION_COLUMN (UNKNOWN_LOCATION));
+}
+
+/* Verify various properties of BUILTINS_LOCATION. */
+
+static void
+test_builtins ()
+{
+ assert_loceq (_("<built-in>"), 0, 0, BUILTINS_LOCATION);
+ ASSERT_PRED1 (is_location_from_builtin_token, BUILTINS_LOCATION);
+}
+
+/* Regression test for make_location.
+ Ensure that we use pure locations for the start/finish of the range,
+ rather than storing a packed or ad-hoc range as the start/finish. */
+
+static void
+test_make_location_nonpure_range_endpoints (const line_table_case &case_)
+{
+ /* Issue seen with testsuite/c-c++-common/Wlogical-not-parentheses-2.c
+ with C++ frontend.
+ ....................0000000001111111111222.
+ ....................1234567890123456789012. */
+ const char *content = " r += !aaa == bbb;\n";
+ temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
+ line_table_test ltt (case_);
+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
+
+ const location_t c11 = linemap_position_for_column (line_table, 11);
+ const location_t c12 = linemap_position_for_column (line_table, 12);
+ const location_t c13 = linemap_position_for_column (line_table, 13);
+ const location_t c14 = linemap_position_for_column (line_table, 14);
+ const location_t c21 = linemap_position_for_column (line_table, 21);
+
+ if (c21 > LINE_MAP_MAX_LOCATION_WITH_COLS)
+ return;
+
+ /* Use column 13 for the caret location, arbitrarily, to verify that we
+ handle start != caret. */
+ const location_t aaa = make_location (c13, c12, c14);
+ ASSERT_EQ (c13, get_pure_location (aaa));
+ ASSERT_EQ (c12, get_start (aaa));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_start (aaa)));
+ ASSERT_EQ (c14, get_finish (aaa));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_finish (aaa)));
+
+ /* Make a location using a location with a range as the start-point. */
+ const location_t not_aaa = make_location (c11, aaa, c14);
+ ASSERT_EQ (c11, get_pure_location (not_aaa));
+ /* It should use the start location of the range, not store the range
+ itself. */
+ ASSERT_EQ (c12, get_start (not_aaa));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_start (not_aaa)));
+ ASSERT_EQ (c14, get_finish (not_aaa));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa)));
+
+ /* Similarly, make a location with a range as the end-point. */
+ const location_t aaa_eq_bbb = make_location (c12, c12, c21);
+ ASSERT_EQ (c12, get_pure_location (aaa_eq_bbb));
+ ASSERT_EQ (c12, get_start (aaa_eq_bbb));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_start (aaa_eq_bbb)));
+ ASSERT_EQ (c21, get_finish (aaa_eq_bbb));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_finish (aaa_eq_bbb)));
+ const location_t not_aaa_eq_bbb = make_location (c11, c12, aaa_eq_bbb);
+ /* It should use the finish location of the range, not store the range
+ itself. */
+ ASSERT_EQ (c11, get_pure_location (not_aaa_eq_bbb));
+ ASSERT_EQ (c12, get_start (not_aaa_eq_bbb));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_start (not_aaa_eq_bbb)));
+ ASSERT_EQ (c21, get_finish (not_aaa_eq_bbb));
+ ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa_eq_bbb)));
+}
+
+/* Verify reading of input files (e.g. for caret-based diagnostics). */
+
+static void
+test_reading_source_line ()
+{
+ /* Create a tempfile and write some text to it. */
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt",
+ "01234567890123456789\n"
+ "This is the test text\n"
+ "This is the 3rd line");
+
+ /* Read back a specific line from the tempfile. */
+ char_span source_line = location_get_source_line (tmp.get_filename (), 3);
+ ASSERT_TRUE (source_line);
+ ASSERT_TRUE (source_line.get_buffer () != NULL);
+ ASSERT_EQ (20, source_line.length ());
+ ASSERT_TRUE (!strncmp ("This is the 3rd line",
+ source_line.get_buffer (), source_line.length ()));
+
+ source_line = location_get_source_line (tmp.get_filename (), 2);
+ ASSERT_TRUE (source_line);
+ ASSERT_TRUE (source_line.get_buffer () != NULL);
+ ASSERT_EQ (21, source_line.length ());
+ ASSERT_TRUE (!strncmp ("This is the test text",
+ source_line.get_buffer (), source_line.length ()));
+
+ source_line = location_get_source_line (tmp.get_filename (), 4);
+ ASSERT_FALSE (source_line);
+ ASSERT_TRUE (source_line.get_buffer () == NULL);
+}
+
+/* Tests of lexing. */
+
+/* Verify that token TOK from PARSER has cpp_token_as_text
+ equal to EXPECTED_TEXT. */
+
+#define ASSERT_TOKEN_AS_TEXT_EQ(PARSER, TOK, EXPECTED_TEXT) \
+ SELFTEST_BEGIN_STMT \
+ unsigned char *actual_txt = cpp_token_as_text ((PARSER), (TOK)); \
+ ASSERT_STREQ ((EXPECTED_TEXT), (const char *)actual_txt); \
+ SELFTEST_END_STMT
+
+/* Verify that TOK's src_loc is within EXP_FILENAME at EXP_LINENUM,
+ and ranges from EXP_START_COL to EXP_FINISH_COL.
+ Use LOC as the effective location of the selftest. */
+
+static void
+assert_token_loc_eq (const location &loc,
+ const cpp_token *tok,
+ const char *exp_filename, int exp_linenum,
+ int exp_start_col, int exp_finish_col)
+{
+ location_t tok_loc = tok->src_loc;
+ ASSERT_STREQ_AT (loc, exp_filename, LOCATION_FILE (tok_loc));
+ ASSERT_EQ_AT (loc, exp_linenum, LOCATION_LINE (tok_loc));
+
+ /* If location_t values are sufficiently high, then column numbers
+ will be unavailable. */
+ if (!should_have_column_data_p (tok_loc))
+ return;
+
+ ASSERT_EQ_AT (loc, exp_start_col, LOCATION_COLUMN (tok_loc));
+ source_range tok_range = get_range_from_loc (line_table, tok_loc);
+ ASSERT_EQ_AT (loc, exp_start_col, LOCATION_COLUMN (tok_range.m_start));
+ ASSERT_EQ_AT (loc, exp_finish_col, LOCATION_COLUMN (tok_range.m_finish));
+}
+
+/* Use assert_token_loc_eq to verify the TOK->src_loc, using
+ SELFTEST_LOCATION as the effective location of the selftest. */
+
+#define ASSERT_TOKEN_LOC_EQ(TOK, EXP_FILENAME, EXP_LINENUM, \
+ EXP_START_COL, EXP_FINISH_COL) \
+ assert_token_loc_eq (SELFTEST_LOCATION, (TOK), (EXP_FILENAME), \
+ (EXP_LINENUM), (EXP_START_COL), (EXP_FINISH_COL))
+
+/* Test of lexing a file using libcpp, verifying tokens and their
+ location information. */
+
+static void
+test_lexer (const line_table_case &case_)
+{
+ /* Create a tempfile and write some text to it. */
+ const char *content =
+ /*00000000011111111112222222222333333.3333444444444.455555555556
+ 12345678901234567890123456789012345.6789012345678.901234567890. */
+ ("test_name /* c-style comment */\n"
+ " \"test literal\"\n"
+ " // test c++-style comment\n"
+ " 42\n");
+ temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
+
+ line_table_test ltt (case_);
+
+ cpp_reader *parser = cpp_create_reader (CLK_GNUC89, NULL, line_table);
+
+ const char *fname = cpp_read_main_file (parser, tmp.get_filename ());
+ ASSERT_NE (fname, NULL);
+
+ /* Verify that we get the expected tokens back, with the correct
+ location information. */
+
+ location_t loc;
+ const cpp_token *tok;
+ tok = cpp_get_token_with_location (parser, &loc);
+ ASSERT_NE (tok, NULL);
+ ASSERT_EQ (tok->type, CPP_NAME);
+ ASSERT_TOKEN_AS_TEXT_EQ (parser, tok, "test_name");
+ ASSERT_TOKEN_LOC_EQ (tok, tmp.get_filename (), 1, 1, 9);
+
+ tok = cpp_get_token_with_location (parser, &loc);
+ ASSERT_NE (tok, NULL);
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (parser, tok, "\"test literal\"");
+ ASSERT_TOKEN_LOC_EQ (tok, tmp.get_filename (), 2, 35, 48);
+
+ tok = cpp_get_token_with_location (parser, &loc);
+ ASSERT_NE (tok, NULL);
+ ASSERT_EQ (tok->type, CPP_NUMBER);
+ ASSERT_TOKEN_AS_TEXT_EQ (parser, tok, "42");
+ ASSERT_TOKEN_LOC_EQ (tok, tmp.get_filename (), 4, 4, 5);
+
+ tok = cpp_get_token_with_location (parser, &loc);
+ ASSERT_NE (tok, NULL);
+ ASSERT_EQ (tok->type, CPP_EOF);
+
+ cpp_finish (parser, NULL);
+ cpp_destroy (parser);
+}
+
+/* Forward decls. */
+
+class lexer_test;
+class lexer_test_options;
+
+/* A class for specifying options of a lexer_test.
+ The "apply" vfunc is called during the lexer_test constructor. */
+
+class lexer_test_options
+{
+ public:
+ virtual void apply (lexer_test &) = 0;
+};
+
+/* Wrapper around an cpp_reader *, which calls cpp_finish and cpp_destroy
+ in its dtor.
+
+ This is needed by struct lexer_test to ensure that the cleanup of the
+ cpp_reader happens *after* the cleanup of the temp_source_file. */
+
+class cpp_reader_ptr
+{
+ public:
+ cpp_reader_ptr (cpp_reader *ptr) : m_ptr (ptr) {}
+
+ ~cpp_reader_ptr ()
+ {
+ cpp_finish (m_ptr, NULL);
+ cpp_destroy (m_ptr);
+ }
+
+ operator cpp_reader * () const { return m_ptr; }
+
+ private:
+ cpp_reader *m_ptr;
+};
+
+/* A struct for writing lexer tests. */
+
+class lexer_test
+{
+public:
+ lexer_test (const line_table_case &case_, const char *content,
+ lexer_test_options *options);
+ ~lexer_test ();
+
+ const cpp_token *get_token ();
+
+ /* The ordering of these fields matters.
+ The line_table_test must be first, since the cpp_reader_ptr
+ uses it.
+ The cpp_reader must be cleaned up *after* the temp_source_file
+ since the filenames in input.cc's input cache are owned by the
+ cpp_reader; in particular, when ~temp_source_file evicts the
+ filename the filenames must still be alive. */
+ line_table_test m_ltt;
+ cpp_reader_ptr m_parser;
+ temp_source_file m_tempfile;
+ string_concat_db m_concats;
+ bool m_implicitly_expect_EOF;
+};
+
+/* Use an EBCDIC encoding for the execution charset, specifically
+ IBM1047-encoded (aka "EBCDIC 1047", or "Code page 1047").
+
+ This exercises iconv integration within libcpp.
+ Not every build of iconv supports the given charset,
+ so we need to flag this error and handle it gracefully. */
+
+class ebcdic_execution_charset : public lexer_test_options
+{
+ public:
+ ebcdic_execution_charset () : m_num_iconv_errors (0)
+ {
+ gcc_assert (s_singleton == NULL);
+ s_singleton = this;
+ }
+ ~ebcdic_execution_charset ()
+ {
+ gcc_assert (s_singleton == this);
+ s_singleton = NULL;
+ }
+
+ void apply (lexer_test &test) FINAL OVERRIDE
+ {
+ cpp_options *cpp_opts = cpp_get_options (test.m_parser);
+ cpp_opts->narrow_charset = "IBM1047";
+
+ cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser);
+ callbacks->diagnostic = on_diagnostic;
+ }
+
+ static bool on_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
+ enum cpp_diagnostic_level level ATTRIBUTE_UNUSED,
+ enum cpp_warning_reason reason ATTRIBUTE_UNUSED,
+ rich_location *richloc ATTRIBUTE_UNUSED,
+ const char *msgid, va_list *ap ATTRIBUTE_UNUSED)
+ ATTRIBUTE_FPTR_PRINTF(5,0)
+ {
+ gcc_assert (s_singleton);
+ /* Avoid exgettext from picking this up, it is translated in libcpp. */
+ const char *msg = "conversion from %s to %s not supported by iconv";
+#ifdef ENABLE_NLS
+ msg = dgettext ("cpplib", msg);
+#endif
+ /* Detect and record errors emitted by libcpp/charset.cc:init_iconv_desc
+ when the local iconv build doesn't support the conversion. */
+ if (strcmp (msgid, msg) == 0)
+ {
+ s_singleton->m_num_iconv_errors++;
+ return true;
+ }
+
+ /* Otherwise, we have an unexpected error. */
+ abort ();
+ }
+
+ bool iconv_errors_occurred_p () const { return m_num_iconv_errors > 0; }
+
+ private:
+ static ebcdic_execution_charset *s_singleton;
+ int m_num_iconv_errors;
+};
+
+ebcdic_execution_charset *ebcdic_execution_charset::s_singleton;
+
+/* A lexer_test_options subclass that records a list of diagnostic
+ messages emitted by the lexer. */
+
+class lexer_diagnostic_sink : public lexer_test_options
+{
+ public:
+ lexer_diagnostic_sink ()
+ {
+ gcc_assert (s_singleton == NULL);
+ s_singleton = this;
+ }
+ ~lexer_diagnostic_sink ()
+ {
+ gcc_assert (s_singleton == this);
+ s_singleton = NULL;
+
+ int i;
+ char *str;
+ FOR_EACH_VEC_ELT (m_diagnostics, i, str)
+ free (str);
+ }
+
+ void apply (lexer_test &test) FINAL OVERRIDE
+ {
+ cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser);
+ callbacks->diagnostic = on_diagnostic;
+ }
+
+ static bool on_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
+ enum cpp_diagnostic_level level ATTRIBUTE_UNUSED,
+ enum cpp_warning_reason reason ATTRIBUTE_UNUSED,
+ rich_location *richloc ATTRIBUTE_UNUSED,
+ const char *msgid, va_list *ap)
+ ATTRIBUTE_FPTR_PRINTF(5,0)
+ {
+ char *msg = xvasprintf (msgid, *ap);
+ s_singleton->m_diagnostics.safe_push (msg);
+ return true;
+ }
+
+ auto_vec<char *> m_diagnostics;
+
+ private:
+ static lexer_diagnostic_sink *s_singleton;
+};
+
+lexer_diagnostic_sink *lexer_diagnostic_sink::s_singleton;
+
+/* Constructor. Override line_table with a new instance based on CASE_,
+ and write CONTENT to a tempfile. Create a cpp_reader, and use it to
+ start parsing the tempfile. */
+
+lexer_test::lexer_test (const line_table_case &case_, const char *content,
+ lexer_test_options *options)
+: m_ltt (case_),
+ m_parser (cpp_create_reader (CLK_GNUC99, NULL, line_table)),
+ /* Create a tempfile and write the text to it. */
+ m_tempfile (SELFTEST_LOCATION, ".c", content),
+ m_concats (),
+ m_implicitly_expect_EOF (true)
+{
+ if (options)
+ options->apply (*this);
+
+ cpp_init_iconv (m_parser);
+
+ /* Parse the file. */
+ const char *fname = cpp_read_main_file (m_parser,
+ m_tempfile.get_filename ());
+ ASSERT_NE (fname, NULL);
+}
+
+/* Destructor. By default, verify that the next token in m_parser is EOF. */
+
+lexer_test::~lexer_test ()
+{
+ location_t loc;
+ const cpp_token *tok;
+
+ if (m_implicitly_expect_EOF)
+ {
+ tok = cpp_get_token_with_location (m_parser, &loc);
+ ASSERT_NE (tok, NULL);
+ ASSERT_EQ (tok->type, CPP_EOF);
+ }
+}
+
+/* Get the next token from m_parser. */
+
+const cpp_token *
+lexer_test::get_token ()
+{
+ location_t loc;
+ const cpp_token *tok;
+
+ tok = cpp_get_token_with_location (m_parser, &loc);
+ ASSERT_NE (tok, NULL);
+ return tok;
+}
+
+/* Verify that locations within string literals are correctly handled. */
+
+/* Verify get_source_range_for_substring for token(s) at STRLOC,
+ using the string concatenation database for TEST.
+
+ Assert that the character at index IDX is on EXPECTED_LINE,
+ and that it begins at column EXPECTED_START_COL and ends at
+ EXPECTED_FINISH_COL (unless the locations are beyond
+ LINE_MAP_MAX_LOCATION_WITH_COLS, in which case don't check their
+ columns). */
+
+static void
+assert_char_at_range (const location &loc,
+ lexer_test& test,
+ location_t strloc, enum cpp_ttype type, int idx,
+ int expected_line, int expected_start_col,
+ int expected_finish_col)
+{
+ cpp_reader *pfile = test.m_parser;
+ string_concat_db *concats = &test.m_concats;
+
+ source_range actual_range = source_range();
+ const char *err
+ = get_source_range_for_char (pfile, concats, strloc, type, idx,
+ &actual_range);
+ if (should_have_column_data_p (strloc))
+ ASSERT_EQ_AT (loc, NULL, err);
+ else
+ {
+ ASSERT_STREQ_AT (loc,
+ "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS",
+ err);
+ return;
+ }
+
+ int actual_start_line = LOCATION_LINE (actual_range.m_start);
+ ASSERT_EQ_AT (loc, expected_line, actual_start_line);
+ int actual_finish_line = LOCATION_LINE (actual_range.m_finish);
+ ASSERT_EQ_AT (loc, expected_line, actual_finish_line);
+
+ if (should_have_column_data_p (actual_range.m_start))
+ {
+ int actual_start_col = LOCATION_COLUMN (actual_range.m_start);
+ ASSERT_EQ_AT (loc, expected_start_col, actual_start_col);
+ }
+ if (should_have_column_data_p (actual_range.m_finish))
+ {
+ int actual_finish_col = LOCATION_COLUMN (actual_range.m_finish);
+ ASSERT_EQ_AT (loc, expected_finish_col, actual_finish_col);
+ }
+}
+
+/* Macro for calling assert_char_at_range, supplying SELFTEST_LOCATION for
+ the effective location of any errors. */
+
+#define ASSERT_CHAR_AT_RANGE(LEXER_TEST, STRLOC, TYPE, IDX, EXPECTED_LINE, \
+ EXPECTED_START_COL, EXPECTED_FINISH_COL) \
+ assert_char_at_range (SELFTEST_LOCATION, (LEXER_TEST), (STRLOC), (TYPE), \
+ (IDX), (EXPECTED_LINE), (EXPECTED_START_COL), \
+ (EXPECTED_FINISH_COL))
+
+/* Verify get_num_source_ranges_for_substring for token(s) at STRLOC,
+ using the string concatenation database for TEST.
+
+ Assert that the token(s) at STRLOC contain EXPECTED_NUM_RANGES. */
+
+static void
+assert_num_substring_ranges (const location &loc,
+ lexer_test& test,
+ location_t strloc,
+ enum cpp_ttype type,
+ int expected_num_ranges)
+{
+ cpp_reader *pfile = test.m_parser;
+ string_concat_db *concats = &test.m_concats;
+
+ int actual_num_ranges = -1;
+ const char *err
+ = get_num_source_ranges_for_substring (pfile, concats, strloc, type,
+ &actual_num_ranges);
+ if (should_have_column_data_p (strloc))
+ ASSERT_EQ_AT (loc, NULL, err);
+ else
+ {
+ ASSERT_STREQ_AT (loc,
+ "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS",
+ err);
+ return;
+ }
+ ASSERT_EQ_AT (loc, expected_num_ranges, actual_num_ranges);
+}
+
+/* Macro for calling assert_num_substring_ranges, supplying
+ SELFTEST_LOCATION for the effective location of any errors. */
+
+#define ASSERT_NUM_SUBSTRING_RANGES(LEXER_TEST, STRLOC, TYPE, \
+ EXPECTED_NUM_RANGES) \
+ assert_num_substring_ranges (SELFTEST_LOCATION, (LEXER_TEST), (STRLOC), \
+ (TYPE), (EXPECTED_NUM_RANGES))
+
+
+/* Verify that get_num_source_ranges_for_substring for token(s) at STRLOC
+ returns an error (using the string concatenation database for TEST). */
+
+static void
+assert_has_no_substring_ranges (const location &loc,
+ lexer_test& test,
+ location_t strloc,
+ enum cpp_ttype type,
+ const char *expected_err)
+{
+ cpp_reader *pfile = test.m_parser;
+ string_concat_db *concats = &test.m_concats;
+ cpp_substring_ranges ranges;
+ const char *actual_err
+ = get_substring_ranges_for_loc (pfile, concats, strloc,
+ type, ranges);
+ if (should_have_column_data_p (strloc))
+ ASSERT_STREQ_AT (loc, expected_err, actual_err);
+ else
+ ASSERT_STREQ_AT (loc,
+ "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS",
+ actual_err);
+}
+
+#define ASSERT_HAS_NO_SUBSTRING_RANGES(LEXER_TEST, STRLOC, TYPE, ERR) \
+ assert_has_no_substring_ranges (SELFTEST_LOCATION, (LEXER_TEST), \
+ (STRLOC), (TYPE), (ERR))
+
+/* Lex a simple string literal. Verify the substring location data, before
+ and after running cpp_interpret_string on it. */
+
+static void
+test_lexer_string_locations_simple (const line_table_case &case_)
+{
+ /* Digits 0-9 (with 0 at column 10), the simple way.
+ ....................000000000.11111111112.2222222223333333333
+ ....................123456789.01234567890.1234567890123456789
+ We add a trailing comment to ensure that we correctly locate
+ the end of the string literal token. */
+ const char *content = " \"0123456789\" /* not a string */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"0123456789\"");
+ ASSERT_TOKEN_LOC_EQ (tok, test.m_tempfile.get_filename (), 1, 9, 20);
+
+ /* At this point in lexing, the quote characters are treated as part of
+ the string (they are stripped off by cpp_interpret_string). */
+
+ ASSERT_EQ (tok->val.str.len, 12);
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote. */
+ for (int i = 0; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1,
+ 10 + i, 10 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 11);
+}
+
+/* As test_lexer_string_locations_simple, but use an EBCDIC execution
+ encoding. */
+
+static void
+test_lexer_string_locations_ebcdic (const line_table_case &case_)
+{
+ /* EBCDIC support requires iconv. */
+ if (!HAVE_ICONV)
+ return;
+
+ /* Digits 0-9 (with 0 at column 10), the simple way.
+ ....................000000000.11111111112.2222222223333333333
+ ....................123456789.01234567890.1234567890123456789
+ We add a trailing comment to ensure that we correctly locate
+ the end of the string literal token. */
+ const char *content = " \"0123456789\" /* not a string */\n";
+ ebcdic_execution_charset use_ebcdic;
+ lexer_test test (case_, content, &use_ebcdic);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"0123456789\"");
+ ASSERT_TOKEN_LOC_EQ (tok, test.m_tempfile.get_filename (), 1, 9, 20);
+
+ /* At this point in lexing, the quote characters are treated as part of
+ the string (they are stripped off by cpp_interpret_string). */
+
+ ASSERT_EQ (tok->val.str.len, 12);
+
+ /* The remainder of the test requires an iconv implementation that
+ can convert from UTF-8 to the EBCDIC encoding requested above. */
+ if (use_ebcdic.iconv_errors_occurred_p ())
+ return;
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ /* We should now have EBCDIC-encoded text, specifically
+ IBM1047-encoded (aka "EBCDIC 1047", or "Code page 1047").
+ The digits 0-9 are encoded as 240-249 i.e. 0xf0-0xf9. */
+ ASSERT_STREQ ("\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
+ (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify that we don't attempt to record substring location information
+ for such cases. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES
+ (test, tok->src_loc, type,
+ "execution character set != source character set");
+}
+
+/* Lex a string literal containing a hex-escaped character.
+ Verify the substring location data, before and after running
+ cpp_interpret_string on it. */
+
+static void
+test_lexer_string_locations_hex (const line_table_case &case_)
+{
+ /* Digits 0-9, expressing digit 5 in ASCII as "\x35"
+ and with a space in place of digit 6, to terminate the escaped
+ hex code.
+ ....................000000000.111111.11112222.
+ ....................123456789.012345.67890123. */
+ const char *content = " \"01234\\x35 789\"\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"01234\\x35 789\"");
+ ASSERT_TOKEN_LOC_EQ (tok, test.m_tempfile.get_filename (), 1, 9, 23);
+
+ /* At this point in lexing, the quote characters are treated as part of
+ the string (they are stripped off by cpp_interpret_string). */
+ ASSERT_EQ (tok->val.str.len, 15);
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("012345 789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote. */
+ for (int i = 0; i <= 4; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 5, 1, 15, 18);
+ for (int i = 6; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 13 + i, 13 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 11);
+}
+
+/* Lex a string literal containing an octal-escaped character.
+ Verify the substring location data after running cpp_interpret_string
+ on it. */
+
+static void
+test_lexer_string_locations_oct (const line_table_case &case_)
+{
+ /* Digits 0-9, expressing digit 5 in ASCII as "\065"
+ and with a space in place of digit 6, to terminate the escaped
+ octal code.
+ ....................000000000.111111.11112222.2222223333333333444
+ ....................123456789.012345.67890123.4567890123456789012 */
+ const char *content = " \"01234\\065 789\" /* not a string */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"01234\\065 789\"");
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("012345 789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote. */
+ for (int i = 0; i < 5; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 5, 1, 15, 18);
+ for (int i = 6; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 13 + i, 13 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 11);
+}
+
+/* Test of string literal containing letter escapes. */
+
+static void
+test_lexer_string_locations_letter_escape_1 (const line_table_case &case_)
+{
+ /* The string "\tfoo\\\nbar" i.e. tab, "foo", backslash, newline, bar.
+ .....................000000000.1.11111.1.1.11222.22222223333333
+ .....................123456789.0.12345.6.7.89012.34567890123456. */
+ const char *content = (" \"\\tfoo\\\\\\nbar\" /* non-str */\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected tokens back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"\\tfoo\\\\\\nbar\"");
+
+ /* Verify ranges of individual characters. */
+ /* "\t". */
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ 0, 1, 10, 11);
+ /* "foo". */
+ for (int i = 1; i <= 3; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ i, 1, 11 + i, 11 + i);
+ /* "\\" and "\n". */
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ 4, 1, 15, 16);
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ 5, 1, 17, 18);
+
+ /* "bar" and closing quote for nul-terminator. */
+ for (int i = 6; i <= 9; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ i, 1, 13 + i, 13 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 10);
+}
+
+/* Another test of a string literal containing a letter escape.
+ Based on string seen in
+ printf ("%-%\n");
+ in gcc.dg/format/c90-printf-1.c. */
+
+static void
+test_lexer_string_locations_letter_escape_2 (const line_table_case &case_)
+{
+ /* .....................000000000.1111.11.1111.22222222223.
+ .....................123456789.0123.45.6789.01234567890. */
+ const char *content = (" \"%-%\\n\" /* non-str */\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected tokens back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"%-%\\n\"");
+
+ /* Verify ranges of individual characters. */
+ /* "%-%". */
+ for (int i = 0; i < 3; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ i, 1, 10 + i, 10 + i);
+ /* "\n". */
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ 3, 1, 13, 14);
+
+ /* Closing quote for nul-terminator. */
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ 4, 1, 15, 15);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 5);
+}
+
+/* Lex a string literal containing UCN 4 characters.
+ Verify the substring location data after running cpp_interpret_string
+ on it. */
+
+static void
+test_lexer_string_locations_ucn4 (const line_table_case &case_)
+{
+ /* Digits 0-9, expressing digits 5 and 6 as Roman numerals expressed
+ as UCN 4.
+ ....................000000000.111111.111122.222222223.33333333344444
+ ....................123456789.012345.678901.234567890.12345678901234 */
+ const char *content = " \"01234\\u2174\\u2175789\" /* non-str */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"01234\\u2174\\u2175789\"");
+
+ /* Verify that cpp_interpret_string works.
+ The string should be encoded in the execution character
+ set. Assuming that is UTF-8, we should have the following:
+ ----------- ---- ----- ------- ----------------
+ Byte offset Byte Octal Unicode Source Column(s)
+ ----------- ---- ----- ------- ----------------
+ 0 0x30 '0' 10
+ 1 0x31 '1' 11
+ 2 0x32 '2' 12
+ 3 0x33 '3' 13
+ 4 0x34 '4' 14
+ 5 0xE2 \342 U+2174 15-20
+ 6 0x85 \205 (cont) 15-20
+ 7 0xB4 \264 (cont) 15-20
+ 8 0xE2 \342 U+2175 21-26
+ 9 0x85 \205 (cont) 21-26
+ 10 0xB5 \265 (cont) 21-26
+ 11 0x37 '7' 27
+ 12 0x38 '8' 28
+ 13 0x39 '9' 29
+ 14 0x00 30 (closing quote)
+ ----------- ---- ----- ------- ---------------. */
+
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("01234\342\205\264\342\205\265789",
+ (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote.
+ '01234'. */
+ for (int i = 0; i <= 4; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
+ /* U+2174. */
+ for (int i = 5; i <= 7; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 15, 20);
+ /* U+2175. */
+ for (int i = 8; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 21, 26);
+ /* '789' and nul terminator */
+ for (int i = 11; i <= 14; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 16 + i, 16 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 15);
+}
+
+/* Lex a string literal containing UCN 8 characters.
+ Verify the substring location data after running cpp_interpret_string
+ on it. */
+
+static void
+test_lexer_string_locations_ucn8 (const line_table_case &case_)
+{
+ /* Digits 0-9, expressing digits 5 and 6 as Roman numerals as UCN 8.
+ ....................000000000.111111.1111222222.2222333333333.344444
+ ....................123456789.012345.6789012345.6789012345678.901234 */
+ const char *content = " \"01234\\U00002174\\U00002175789\" /* */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok,
+ "\"01234\\U00002174\\U00002175789\"");
+
+ /* Verify that cpp_interpret_string works.
+ The UTF-8 encoding of the string is identical to that from
+ the ucn4 testcase above; the only difference is the column
+ locations. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("01234\342\205\264\342\205\265789",
+ (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote.
+ '01234'. */
+ for (int i = 0; i <= 4; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
+ /* U+2174. */
+ for (int i = 5; i <= 7; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 15, 24);
+ /* U+2175. */
+ for (int i = 8; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 25, 34);
+ /* '789' at columns 35-37 */
+ for (int i = 11; i <= 13; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 24 + i, 24 + i);
+ /* Closing quote/nul-terminator at column 38. */
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 14, 1, 38, 38);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 15);
+}
+
+/* Fetch a big-endian 32-bit value and convert to host endianness. */
+
+static uint32_t
+uint32_from_big_endian (const uint32_t *ptr_be_value)
+{
+ const unsigned char *buf = (const unsigned char *)ptr_be_value;
+ return (((uint32_t) buf[0] << 24)
+ | ((uint32_t) buf[1] << 16)
+ | ((uint32_t) buf[2] << 8)
+ | (uint32_t) buf[3]);
+}
+
+/* Lex a wide string literal and verify that attempts to read substring
+ location data from it fail gracefully. */
+
+static void
+test_lexer_string_locations_wide_string (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ ....................000000000.11111111112.22222222233333
+ ....................123456789.01234567890.12345678901234 */
+ const char *content = " L\"0123456789\" /* non-str */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_WSTRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "L\"0123456789\"");
+
+ /* Verify that cpp_interpret_string works, using CPP_WSTRING. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_WSTRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ /* The cpp_reader defaults to big-endian with
+ CHAR_BIT * sizeof (int) for the wchar_precision, so dst_string should
+ now be encoded as UTF-32BE. */
+ const uint32_t *be32_chars = (const uint32_t *)dst_string.text;
+ ASSERT_EQ ('0', uint32_from_big_endian (&be32_chars[0]));
+ ASSERT_EQ ('5', uint32_from_big_endian (&be32_chars[5]));
+ ASSERT_EQ ('9', uint32_from_big_endian (&be32_chars[9]));
+ ASSERT_EQ (0, uint32_from_big_endian (&be32_chars[10]));
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* We don't yet support generating substring location information
+ for L"" strings. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES
+ (test, tok->src_loc, type,
+ "execution character set != source character set");
+}
+
+/* Fetch a big-endian 16-bit value and convert to host endianness. */
+
+static uint16_t
+uint16_from_big_endian (const uint16_t *ptr_be_value)
+{
+ const unsigned char *buf = (const unsigned char *)ptr_be_value;
+ return ((uint16_t) buf[0] << 8) | (uint16_t) buf[1];
+}
+
+/* Lex a u"" string literal and verify that attempts to read substring
+ location data from it fail gracefully. */
+
+static void
+test_lexer_string_locations_string16 (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ ....................000000000.11111111112.22222222233333
+ ....................123456789.01234567890.12345678901234 */
+ const char *content = " u\"0123456789\" /* non-str */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING16);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "u\"0123456789\"");
+
+ /* Verify that cpp_interpret_string works, using CPP_STRING16. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING16;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+
+ /* The cpp_reader defaults to big-endian, so dst_string should
+ now be encoded as UTF-16BE. */
+ const uint16_t *be16_chars = (const uint16_t *)dst_string.text;
+ ASSERT_EQ ('0', uint16_from_big_endian (&be16_chars[0]));
+ ASSERT_EQ ('5', uint16_from_big_endian (&be16_chars[5]));
+ ASSERT_EQ ('9', uint16_from_big_endian (&be16_chars[9]));
+ ASSERT_EQ (0, uint16_from_big_endian (&be16_chars[10]));
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* We don't yet support generating substring location information
+ for L"" strings. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES
+ (test, tok->src_loc, type,
+ "execution character set != source character set");
+}
+
+/* Lex a U"" string literal and verify that attempts to read substring
+ location data from it fail gracefully. */
+
+static void
+test_lexer_string_locations_string32 (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ ....................000000000.11111111112.22222222233333
+ ....................123456789.01234567890.12345678901234 */
+ const char *content = " U\"0123456789\" /* non-str */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING32);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "U\"0123456789\"");
+
+ /* Verify that cpp_interpret_string works, using CPP_STRING32. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING32;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+
+ /* The cpp_reader defaults to big-endian, so dst_string should
+ now be encoded as UTF-32BE. */
+ const uint32_t *be32_chars = (const uint32_t *)dst_string.text;
+ ASSERT_EQ ('0', uint32_from_big_endian (&be32_chars[0]));
+ ASSERT_EQ ('5', uint32_from_big_endian (&be32_chars[5]));
+ ASSERT_EQ ('9', uint32_from_big_endian (&be32_chars[9]));
+ ASSERT_EQ (0, uint32_from_big_endian (&be32_chars[10]));
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* We don't yet support generating substring location information
+ for L"" strings. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES
+ (test, tok->src_loc, type,
+ "execution character set != source character set");
+}
+
+/* Lex a u8-string literal.
+ Verify the substring location data after running cpp_interpret_string
+ on it. */
+
+static void
+test_lexer_string_locations_u8 (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ ....................000000000.11111111112.22222222233333
+ ....................123456789.01234567890.12345678901234 */
+ const char *content = " u8\"0123456789\" /* non-str */\n";
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_UTF8STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "u8\"0123456789\"");
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote. */
+ for (int i = 0; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
+}
+
+/* Lex a string literal containing UTF-8 source characters.
+ Verify the substring location data after running cpp_interpret_string
+ on it. */
+
+static void
+test_lexer_string_locations_utf8_source (const line_table_case &case_)
+{
+ /* This string literal is written out to the source file as UTF-8,
+ and is of the form "before mojibake after", where "mojibake"
+ is written as the following four unicode code points:
+ U+6587 CJK UNIFIED IDEOGRAPH-6587
+ U+5B57 CJK UNIFIED IDEOGRAPH-5B57
+ U+5316 CJK UNIFIED IDEOGRAPH-5316
+ U+3051 HIRAGANA LETTER KE.
+ Each of these is 3 bytes wide when encoded in UTF-8, whereas the
+ "before" and "after" are 1 byte per unicode character.
+
+ The numbering shown are "columns", which are *byte* numbers within
+ the line, rather than unicode character numbers.
+
+ .................... 000000000.1111111.
+ .................... 123456789.0123456. */
+ const char *content = (" \"before "
+ /* U+6587 CJK UNIFIED IDEOGRAPH-6587
+ UTF-8: 0xE6 0x96 0x87
+ C octal escaped UTF-8: \346\226\207
+ "column" numbers: 17-19. */
+ "\346\226\207"
+
+ /* U+5B57 CJK UNIFIED IDEOGRAPH-5B57
+ UTF-8: 0xE5 0xAD 0x97
+ C octal escaped UTF-8: \345\255\227
+ "column" numbers: 20-22. */
+ "\345\255\227"
+
+ /* U+5316 CJK UNIFIED IDEOGRAPH-5316
+ UTF-8: 0xE5 0x8C 0x96
+ C octal escaped UTF-8: \345\214\226
+ "column" numbers: 23-25. */
+ "\345\214\226"
+
+ /* U+3051 HIRAGANA LETTER KE
+ UTF-8: 0xE3 0x81 0x91
+ C octal escaped UTF-8: \343\201\221
+ "column" numbers: 26-28. */
+ "\343\201\221"
+
+ /* column numbers 29 onwards
+ 2333333.33334444444444
+ 9012345.67890123456789. */
+ " after\" /* non-str */\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back, with the correct
+ location information. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ
+ (test.m_parser, tok,
+ "\"before \346\226\207\345\255\227\345\214\226\343\201\221 after\"");
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ
+ ("before \346\226\207\345\255\227\345\214\226\343\201\221 after",
+ (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Verify ranges of individual characters. This no longer includes the
+ opening quote, but does include the closing quote.
+ Assuming that both source and execution encodings are UTF-8, we have
+ a run of 25 octets in each, plus the NUL terminator. */
+ for (int i = 0; i < 25; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
+ /* NUL-terminator should use the closing quote at column 35. */
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 25, 1, 35, 35);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 26);
+}
+
+/* Test of string literal concatenation. */
+
+static void
+test_lexer_string_locations_concatenation_1 (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ .....................000000000.111111.11112222222222
+ .....................123456789.012345.67890123456789. */
+ const char *content = (" \"01234\" /* non-str */\n"
+ " \"56789\" /* non-str */\n");
+ lexer_test test (case_, content, NULL);
+
+ location_t input_locs[2];
+
+ /* Verify that we get the expected tokens back. */
+ auto_vec <cpp_string> input_strings;
+ const cpp_token *tok_a = test.get_token ();
+ ASSERT_EQ (tok_a->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok_a, "\"01234\"");
+ input_strings.safe_push (tok_a->val.str);
+ input_locs[0] = tok_a->src_loc;
+
+ const cpp_token *tok_b = test.get_token ();
+ ASSERT_EQ (tok_b->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok_b, "\"56789\"");
+ input_strings.safe_push (tok_b->val.str);
+ input_locs[1] = tok_b->src_loc;
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser,
+ input_strings.address (), 2,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Simulate c-lex.cc's lex_string in order to record concatenation. */
+ test.m_concats.record_string_concatenation (2, input_locs);
+
+ location_t initial_loc = input_locs[0];
+
+ /* "01234" on line 1. */
+ for (int i = 0; i <= 4; i++)
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 1, 10 + i, 10 + i);
+ /* "56789" in line 2, plus its closing quote for the nul terminator. */
+ for (int i = 5; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 2, 5 + i, 5 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, initial_loc, type, 11);
+}
+
+/* Another test of string literal concatenation. */
+
+static void
+test_lexer_string_locations_concatenation_2 (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ .....................000000000.111.11111112222222
+ .....................123456789.012.34567890123456. */
+ const char *content = (" \"01\" /* non-str */\n"
+ " \"23\" /* non-str */\n"
+ " \"45\" /* non-str */\n"
+ " \"67\" /* non-str */\n"
+ " \"89\" /* non-str */\n");
+ lexer_test test (case_, content, NULL);
+
+ auto_vec <cpp_string> input_strings;
+ location_t input_locs[5];
+
+ /* Verify that we get the expected tokens back. */
+ for (int i = 0; i < 5; i++)
+ {
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ input_strings.safe_push (tok->val.str);
+ input_locs[i] = tok->src_loc;
+ }
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser,
+ input_strings.address (), 5,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Simulate c-lex.cc's lex_string in order to record concatenation. */
+ test.m_concats.record_string_concatenation (5, input_locs);
+
+ location_t initial_loc = input_locs[0];
+
+ /* Within ASSERT_CHAR_AT_RANGE (actually assert_char_at_range), we can
+ detect if the initial loc is after LINE_MAP_MAX_LOCATION_WITH_COLS
+ and expect get_source_range_for_substring to fail.
+ However, for a string concatenation test, we can have a case
+ where the initial string is fully before LINE_MAP_MAX_LOCATION_WITH_COLS,
+ but subsequent strings can be after it.
+ Attempting to detect this within assert_char_at_range
+ would overcomplicate the logic for the common test cases, so
+ we detect it here. */
+ if (should_have_column_data_p (input_locs[0])
+ && !should_have_column_data_p (input_locs[4]))
+ {
+ /* Verify that get_source_range_for_substring gracefully rejects
+ this case. */
+ source_range actual_range;
+ const char *err
+ = get_source_range_for_char (test.m_parser, &test.m_concats,
+ initial_loc, type, 0, &actual_range);
+ ASSERT_STREQ ("range starts after LINE_MAP_MAX_LOCATION_WITH_COLS", err);
+ return;
+ }
+
+ for (int i = 0; i < 5; i++)
+ for (int j = 0; j < 2; j++)
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, (i * 2) + j,
+ i + 1, 10 + j, 10 + j);
+
+ /* NUL-terminator should use the final closing quote at line 5 column 12. */
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 10, 5, 12, 12);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, initial_loc, type, 11);
+}
+
+/* Another test of string literal concatenation, this time combined with
+ various kinds of escaped characters. */
+
+static void
+test_lexer_string_locations_concatenation_3 (const line_table_case &case_)
+{
+ /* Digits 0-9, expressing digit 5 in ASCII as hex "\x35"
+ digit 6 in ASCII as octal "\066", concatenating multiple strings. */
+ const char *content
+ /* .000000000.111111.111.1.2222.222.2.2233.333.3333.34444444444555
+ .123456789.012345.678.9.0123.456.7.8901.234.5678.90123456789012. */
+ = (" \"01234\" \"\\x35\" \"\\066\" \"789\" /* non-str */\n");
+ lexer_test test (case_, content, NULL);
+
+ auto_vec <cpp_string> input_strings;
+ location_t input_locs[4];
+
+ /* Verify that we get the expected tokens back. */
+ for (int i = 0; i < 4; i++)
+ {
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ input_strings.safe_push (tok->val.str);
+ input_locs[i] = tok->src_loc;
+ }
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser,
+ input_strings.address (), 4,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ /* Simulate c-lex.cc's lex_string in order to record concatenation. */
+ test.m_concats.record_string_concatenation (4, input_locs);
+
+ location_t initial_loc = input_locs[0];
+
+ for (int i = 0; i <= 4; i++)
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 1, 10 + i, 10 + i);
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 5, 1, 19, 22);
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 6, 1, 27, 30);
+ for (int i = 7; i <= 9; i++)
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 1, 28 + i, 28 + i);
+
+ /* NUL-terminator should use the location of the final closing quote. */
+ ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 10, 1, 38, 38);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, initial_loc, type, 11);
+}
+
+/* Test of string literal in a macro. */
+
+static void
+test_lexer_string_locations_macro (const line_table_case &case_)
+{
+ /* Digits 0-9.
+ .....................0000000001111111111.22222222223.
+ .....................1234567890123456789.01234567890. */
+ const char *content = ("#define MACRO \"0123456789\" /* non-str */\n"
+ " MACRO");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected tokens back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_PADDING);
+
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"0123456789\"");
+
+ /* Verify ranges of individual characters. We ought to
+ see columns within the macro definition. */
+ for (int i = 0; i <= 10; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ i, 1, 20 + i, 20 + i);
+
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 11);
+
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_PADDING);
+}
+
+/* Test of stringification of a macro argument. */
+
+static void
+test_lexer_string_locations_stringified_macro_argument
+ (const line_table_case &case_)
+{
+ /* .....................000000000111111111122222222223.
+ .....................123456789012345678901234567890. */
+ const char *content = ("#define MACRO(X) #X /* non-str */\n"
+ "MACRO(foo)\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_PADDING);
+
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"foo\"");
+
+ /* We don't support getting the location of a stringified macro
+ argument. Verify that it fails gracefully. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING,
+ "cpp_interpret_string_1 failed");
+
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_PADDING);
+
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_PADDING);
+}
+
+/* Ensure that we are fail gracefully if something attempts to pass
+ in a location that isn't a string literal token. Seen on this code:
+
+ const char a[] = " %d ";
+ __builtin_printf (a, 0.5);
+ ^
+
+ when c-format.cc erroneously used the indicated one-character
+ location as the format string location, leading to a read past the
+ end of a string buffer in cpp_interpret_string_1. */
+
+static void
+test_lexer_string_locations_non_string (const line_table_case &case_)
+{
+ /* .....................000000000111111111122222222223.
+ .....................123456789012345678901234567890. */
+ const char *content = (" a\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_NAME);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "a");
+
+ /* At this point, libcpp is attempting to interpret the name as a
+ string literal, despite it not starting with a quote. We don't detect
+ that, but we should at least fail gracefully. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING,
+ "cpp_interpret_string_1 failed");
+}
+
+/* Ensure that we can read substring information for a token which
+ starts in one linemap and ends in another . Adapted from
+ gcc.dg/cpp/pr69985.c. */
+
+static void
+test_lexer_string_locations_long_line (const line_table_case &case_)
+{
+ /* .....................000000.000111111111
+ .....................123456.789012346789. */
+ const char *content = ("/* A very long line, so that we start a new line map. */\n"
+ " \"0123456789012345678901234567890123456789"
+ "0123456789012345678901234567890123456789"
+ "0123456789012345678901234567890123456789"
+ "0123456789\"\n");
+
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+
+ if (!should_have_column_data_p (line_table->highest_location))
+ return;
+
+ /* Verify ranges of individual characters. */
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 131);
+ for (int i = 0; i < 131; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ i, 2, 7 + i, 7 + i);
+}
+
+/* Test of locations within a raw string that doesn't contain a newline. */
+
+static void
+test_lexer_string_locations_raw_string_one_line (const line_table_case &case_)
+{
+ /* .....................00.0000000111111111122.
+ .....................12.3456789012345678901. */
+ const char *content = ("R\"foo(0123456789)foo\"\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ if (!should_have_column_data_p (line_table->highest_location))
+ return;
+
+ /* 0-9, plus the nil terminator. */
+ ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 11);
+ for (int i = 0; i < 11; i++)
+ ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
+ i, 1, 7 + i, 7 + i);
+}
+
+/* Test of locations within a raw string that contains a newline. */
+
+static void
+test_lexer_string_locations_raw_string_multiline (const line_table_case &case_)
+{
+ /* .....................00.0000.
+ .....................12.3456. */
+ const char *content = ("R\"foo(\n"
+ /* .....................00000.
+ .....................12345. */
+ "hello\n"
+ "world\n"
+ /* .....................00000.
+ .....................12345. */
+ ")foo\"\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected token back. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_STRING);
+
+ /* Verify that cpp_interpret_string works. */
+ cpp_string dst_string;
+ const enum cpp_ttype type = CPP_STRING;
+ bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
+ &dst_string, type);
+ ASSERT_TRUE (result);
+ ASSERT_STREQ ("\nhello\nworld\n", (const char *)dst_string.text);
+ free (const_cast <unsigned char *> (dst_string.text));
+
+ if (!should_have_column_data_p (line_table->highest_location))
+ return;
+
+ /* Currently we don't support locations within raw strings that
+ contain newlines. */
+ ASSERT_HAS_NO_SUBSTRING_RANGES (test, tok->src_loc, tok->type,
+ "range endpoints are on different lines");
+}
+
+/* Test of parsing an unterminated raw string. */
+
+static void
+test_lexer_string_locations_raw_string_unterminated (const line_table_case &case_)
+{
+ const char *content = "R\"ouch()ouCh\" /* etc */";
+
+ lexer_diagnostic_sink diagnostics;
+ lexer_test test (case_, content, &diagnostics);
+ test.m_implicitly_expect_EOF = false;
+
+ /* Attempt to parse the raw string. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_EOF);
+
+ ASSERT_EQ (1, diagnostics.m_diagnostics.length ());
+ /* We expect the message "unterminated raw string"
+ in the "cpplib" translation domain.
+ It's not clear that dgettext is available on all supported hosts,
+ so this assertion is commented-out for now.
+ ASSERT_STREQ (dgettext ("cpplib", "unterminated raw string"),
+ diagnostics.m_diagnostics[0]);
+ */
+}
+
+/* Test of lexing char constants. */
+
+static void
+test_lexer_char_constants (const line_table_case &case_)
+{
+ /* Various char constants.
+ .....................0000000001111111111.22222222223.
+ .....................1234567890123456789.01234567890. */
+ const char *content = (" 'a'\n"
+ " u'a'\n"
+ " U'a'\n"
+ " L'a'\n"
+ " 'abc'\n");
+ lexer_test test (case_, content, NULL);
+
+ /* Verify that we get the expected tokens back. */
+ /* 'a'. */
+ const cpp_token *tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_CHAR);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "'a'");
+
+ unsigned int chars_seen;
+ int unsignedp;
+ cppchar_t cc = cpp_interpret_charconst (test.m_parser, tok,
+ &chars_seen, &unsignedp);
+ ASSERT_EQ (cc, 'a');
+ ASSERT_EQ (chars_seen, 1);
+
+ /* u'a'. */
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_CHAR16);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "u'a'");
+
+ /* U'a'. */
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_CHAR32);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "U'a'");
+
+ /* L'a'. */
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_WCHAR);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "L'a'");
+
+ /* 'abc' (c-char-sequence). */
+ tok = test.get_token ();
+ ASSERT_EQ (tok->type, CPP_CHAR);
+ ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "'abc'");
+}
+/* A table of interesting location_t values, giving one axis of our test
+ matrix. */
+
+static const location_t boundary_locations[] = {
+ /* Zero means "don't override the default values for a new line_table". */
+ 0,
+
+ /* An arbitrary non-zero value that isn't close to one of
+ the boundary values below. */
+ 0x10000,
+
+ /* Values near LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES. */
+ LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES - 0x100,
+ LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES - 1,
+ LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES,
+ LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1,
+ LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 0x100,
+
+ /* Values near LINE_MAP_MAX_LOCATION_WITH_COLS. */
+ LINE_MAP_MAX_LOCATION_WITH_COLS - 0x100,
+ LINE_MAP_MAX_LOCATION_WITH_COLS - 1,
+ LINE_MAP_MAX_LOCATION_WITH_COLS,
+ LINE_MAP_MAX_LOCATION_WITH_COLS + 1,
+ LINE_MAP_MAX_LOCATION_WITH_COLS + 0x100,
+};
+
+/* Run TESTCASE multiple times, once for each case in our test matrix. */
+
+void
+for_each_line_table_case (void (*testcase) (const line_table_case &))
+{
+ /* As noted above in the description of struct line_table_case,
+ we want to explore a test matrix of interesting line_table
+ situations, running various selftests for each case within the
+ matrix. */
+
+ /* Run all tests with:
+ (a) line_table->default_range_bits == 0, and
+ (b) line_table->default_range_bits == 5. */
+ int num_cases_tested = 0;
+ for (int default_range_bits = 0; default_range_bits <= 5;
+ default_range_bits += 5)
+ {
+ /* ...and use each of the "interesting" location values as
+ the starting location within line_table. */
+ const int num_boundary_locations
+ = sizeof (boundary_locations) / sizeof (boundary_locations[0]);
+ for (int loc_idx = 0; loc_idx < num_boundary_locations; loc_idx++)
+ {
+ line_table_case c (default_range_bits, boundary_locations[loc_idx]);
+
+ testcase (c);
+
+ num_cases_tested++;
+ }
+ }
+
+ /* Verify that we fully covered the test matrix. */
+ ASSERT_EQ (num_cases_tested, 2 * 12);
+}
+
+/* Verify that when presented with a consecutive pair of locations with
+ a very large line offset, we don't attempt to consolidate them into
+ a single ordinary linemap where the line offsets within the line map
+ would lead to overflow (PR lto/88147). */
+
+static void
+test_line_offset_overflow ()
+{
+ line_table_test ltt (line_table_case (5, 0));
+
+ linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
+ linemap_line_start (line_table, 1, 100);
+ location_t loc_a = linemap_line_start (line_table, 2578, 255);
+ assert_loceq ("foo.c", 2578, 0, loc_a);
+
+ const line_map_ordinary *ordmap_a = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+ ASSERT_EQ (ordmap_a->m_column_and_range_bits, 13);
+ ASSERT_EQ (ordmap_a->m_range_bits, 5);
+
+ location_t loc_b = linemap_line_start (line_table, 404198, 512);
+ assert_loceq ("foo.c", 404198, 0, loc_b);
+
+ /* We should have started a new linemap, rather than attempting to store
+ a very large line offset. */
+ const line_map_ordinary *ordmap_b = LINEMAPS_LAST_ORDINARY_MAP (line_table);
+ ASSERT_NE (ordmap_a, ordmap_b);
+}
+
+void test_cpp_utf8 ()
+{
+ const int def_tabstop = 8;
+ cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
+
+ /* Verify that wcwidth of invalid UTF-8 or control bytes is 1. */
+ {
+ int w_bad = cpp_display_width ("\xf0!\x9f!\x98!\x82!", 8, policy);
+ ASSERT_EQ (8, w_bad);
+ int w_ctrl = cpp_display_width ("\r\n\v\0\1", 5, policy);
+ ASSERT_EQ (5, w_ctrl);
+ }
+
+ /* Verify that wcwidth of valid UTF-8 is as expected. */
+ {
+ const int w_pi = cpp_display_width ("\xcf\x80", 2, policy);
+ ASSERT_EQ (1, w_pi);
+ const int w_emoji = cpp_display_width ("\xf0\x9f\x98\x82", 4, policy);
+ ASSERT_EQ (2, w_emoji);
+ const int w_umlaut_precomposed = cpp_display_width ("\xc3\xbf", 2,
+ policy);
+ ASSERT_EQ (1, w_umlaut_precomposed);
+ const int w_umlaut_combining = cpp_display_width ("y\xcc\x88", 3,
+ policy);
+ ASSERT_EQ (1, w_umlaut_combining);
+ const int w_han = cpp_display_width ("\xe4\xb8\xba", 3, policy);
+ ASSERT_EQ (2, w_han);
+ const int w_ascii = cpp_display_width ("GCC", 3, policy);
+ ASSERT_EQ (3, w_ascii);
+ const int w_mixed = cpp_display_width ("\xcf\x80 = 3.14 \xf0\x9f\x98\x82"
+ "\x9f! \xe4\xb8\xba y\xcc\x88",
+ 24, policy);
+ ASSERT_EQ (18, w_mixed);
+ }
+
+ /* Verify that display width properly expands tabs. */
+ {
+ const char *tstr = "\tabc\td";
+ ASSERT_EQ (6, cpp_display_width (tstr, 6,
+ cpp_char_column_policy (1, cpp_wcwidth)));
+ ASSERT_EQ (10, cpp_display_width (tstr, 6,
+ cpp_char_column_policy (3, cpp_wcwidth)));
+ ASSERT_EQ (17, cpp_display_width (tstr, 6,
+ cpp_char_column_policy (8, cpp_wcwidth)));
+ ASSERT_EQ (1,
+ cpp_display_column_to_byte_column
+ (tstr, 6, 7, cpp_char_column_policy (8, cpp_wcwidth)));
+ }
+
+ /* Verify that cpp_byte_column_to_display_column can go past the end,
+ and similar edge cases. */
+ {
+ const char *str
+ /* Display columns.
+ 111111112345 */
+ = "\xcf\x80 abc";
+ /* 111122223456
+ Byte columns. */
+
+ ASSERT_EQ (5, cpp_display_width (str, 6, policy));
+ ASSERT_EQ (105,
+ cpp_byte_column_to_display_column (str, 6, 106, policy));
+ ASSERT_EQ (10000,
+ cpp_byte_column_to_display_column (NULL, 0, 10000, policy));
+ ASSERT_EQ (0,
+ cpp_byte_column_to_display_column (NULL, 10000, 0, policy));
+ }
+
+ /* Verify that cpp_display_column_to_byte_column can go past the end,
+ and similar edge cases, and check invertibility. */
+ {
+ const char *str
+ /* Display columns.
+ 000000000000000000000000000000000000011
+ 111111112222222234444444455555555678901 */
+ = "\xf0\x9f\x98\x82 \xf0\x9f\x98\x82 hello";
+ /* 000000000000000000000000000000000111111
+ 111122223333444456666777788889999012345
+ Byte columns. */
+ ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 2, policy));
+ ASSERT_EQ (15,
+ cpp_display_column_to_byte_column (str, 15, 11, policy));
+ ASSERT_EQ (115,
+ cpp_display_column_to_byte_column (str, 15, 111, policy));
+ ASSERT_EQ (10000,
+ cpp_display_column_to_byte_column (NULL, 0, 10000, policy));
+ ASSERT_EQ (0,
+ cpp_display_column_to_byte_column (NULL, 10000, 0, policy));
+
+ /* Verify that we do not interrupt a UTF-8 sequence. */
+ ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 1, policy));
+
+ for (int byte_col = 1; byte_col <= 15; ++byte_col)
+ {
+ const int disp_col
+ = cpp_byte_column_to_display_column (str, 15, byte_col, policy);
+ const int byte_col2
+ = cpp_display_column_to_byte_column (str, 15, disp_col, policy);
+
+ /* If we ask for the display column in the middle of a UTF-8
+ sequence, it will return the length of the partial sequence,
+ matching the behavior of GCC before display column support.
+ Otherwise check the round trip was successful. */
+ if (byte_col < 4)
+ ASSERT_EQ (byte_col, disp_col);
+ else if (byte_col >= 6 && byte_col < 9)
+ ASSERT_EQ (3 + (byte_col - 5), disp_col);
+ else
+ ASSERT_EQ (byte_col2, byte_col);
+ }
+ }
+
+}
+
+/* Run all of the selftests within this file. */
+
+void
+input_cc_tests ()
+{
+ test_linenum_comparisons ();
+ test_should_have_column_data_p ();
+ test_unknown_location ();
+ test_builtins ();
+ for_each_line_table_case (test_make_location_nonpure_range_endpoints);
+
+ for_each_line_table_case (test_accessing_ordinary_linemaps);
+ for_each_line_table_case (test_lexer);
+ for_each_line_table_case (test_lexer_string_locations_simple);
+ for_each_line_table_case (test_lexer_string_locations_ebcdic);
+ for_each_line_table_case (test_lexer_string_locations_hex);
+ for_each_line_table_case (test_lexer_string_locations_oct);
+ for_each_line_table_case (test_lexer_string_locations_letter_escape_1);
+ for_each_line_table_case (test_lexer_string_locations_letter_escape_2);
+ for_each_line_table_case (test_lexer_string_locations_ucn4);
+ for_each_line_table_case (test_lexer_string_locations_ucn8);
+ for_each_line_table_case (test_lexer_string_locations_wide_string);
+ for_each_line_table_case (test_lexer_string_locations_string16);
+ for_each_line_table_case (test_lexer_string_locations_string32);
+ for_each_line_table_case (test_lexer_string_locations_u8);
+ for_each_line_table_case (test_lexer_string_locations_utf8_source);
+ for_each_line_table_case (test_lexer_string_locations_concatenation_1);
+ for_each_line_table_case (test_lexer_string_locations_concatenation_2);
+ for_each_line_table_case (test_lexer_string_locations_concatenation_3);
+ for_each_line_table_case (test_lexer_string_locations_macro);
+ for_each_line_table_case (test_lexer_string_locations_stringified_macro_argument);
+ for_each_line_table_case (test_lexer_string_locations_non_string);
+ for_each_line_table_case (test_lexer_string_locations_long_line);
+ for_each_line_table_case (test_lexer_string_locations_raw_string_one_line);
+ for_each_line_table_case (test_lexer_string_locations_raw_string_multiline);
+ for_each_line_table_case (test_lexer_string_locations_raw_string_unterminated);
+ for_each_line_table_case (test_lexer_char_constants);
+
+ test_reading_source_line ();
+
+ test_line_offset_overflow ();
+
+ test_cpp_utf8 ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/support/cpp/gcc/input.h b/support/cpp/gcc/input.h
new file mode 100644
index 000000000..882e57b8b
--- /dev/null
+++ b/support/cpp/gcc/input.h
@@ -0,0 +1,285 @@
+/* Declarations for variables relating to reading the source file.
+ Used by parsers, lexical analyzers, and error message routines.
+ Copyright (C) 1993-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_INPUT_H
+#define GCC_INPUT_H
+
+#include "line-map.h"
+
+extern GTY(()) class line_maps *line_table;
+extern GTY(()) class line_maps *saved_line_table;
+
+/* A value which will never be used to represent a real location. */
+#define UNKNOWN_LOCATION ((location_t) 0)
+
+/* The location for declarations in "<built-in>" */
+#define BUILTINS_LOCATION ((location_t) 1)
+
+/* line-map.cc reserves RESERVED_LOCATION_COUNT to the user. Ensure
+ both UNKNOWN_LOCATION and BUILTINS_LOCATION fit into that. */
+STATIC_ASSERT (BUILTINS_LOCATION < RESERVED_LOCATION_COUNT);
+
+/* Hasher for 'location_t' values satisfying '!RESERVED_LOCATION_P', thus able
+ to use 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' as spare values for
+ 'Empty'/'Deleted'. */
+/* Per PR103157 "'gengtype': 'typedef' causing infinite-recursion code to be
+ generated", don't use
+ typedef int_hash<location_t, UNKNOWN_LOCATION, BUILTINS_LOCATION>
+ location_hash;
+ here.
+
+ It works for a single-use case, but when using a 'struct'-based variant
+ struct location_hash
+ : int_hash<location_t, UNKNOWN_LOCATION, BUILTINS_LOCATION> {};
+ in more than one place, 'gengtype' generates duplicate functions (thus:
+ "error: redefinition of 'void gt_ggc_mx(location_hash&)'" etc.).
+ Attempting to mark that one up with GTY options, we run into a 'gengtype'
+ "parse error: expected '{', have '<'", which probably falls into category
+ "understanding of C++ is limited", as documented in 'gcc/doc/gty.texi'.
+
+ Thus, use a plain ol' '#define':
+*/
+#define location_hash int_hash<location_t, UNKNOWN_LOCATION, BUILTINS_LOCATION>
+
+extern bool is_location_from_builtin_token (location_t);
+extern expanded_location expand_location (location_t);
+
+class cpp_char_column_policy;
+
+extern int
+location_compute_display_column (expanded_location exploc,
+ const cpp_char_column_policy &policy);
+
+/* A class capturing the bounds of a buffer, to allow for run-time
+ bounds-checking in a checked build. */
+
+class char_span
+{
+ public:
+ char_span (const char *ptr, size_t n_elts) : m_ptr (ptr), m_n_elts (n_elts) {}
+
+ /* Test for a non-NULL pointer. */
+ operator bool() const { return m_ptr; }
+
+ /* Get length, not including any 0-terminator (which may not be,
+ in fact, present). */
+ size_t length () const { return m_n_elts; }
+
+ const char *get_buffer () const { return m_ptr; }
+
+ char operator[] (int idx) const
+ {
+ gcc_assert (idx >= 0);
+ gcc_assert ((size_t)idx < m_n_elts);
+ return m_ptr[idx];
+ }
+
+ char_span subspan (int offset, int n_elts) const
+ {
+ gcc_assert (offset >= 0);
+ gcc_assert (offset < (int)m_n_elts);
+ gcc_assert (n_elts >= 0);
+ gcc_assert (offset + n_elts <= (int)m_n_elts);
+ return char_span (m_ptr + offset, n_elts);
+ }
+
+ char *xstrdup () const
+ {
+ return ::xstrndup (m_ptr, m_n_elts);
+ }
+
+ private:
+ const char *m_ptr;
+ size_t m_n_elts;
+};
+
+extern char_span location_get_source_line (const char *file_path, int line);
+
+extern bool location_missing_trailing_newline (const char *file_path);
+
+/* Forward decl of slot within file_cache, so that the definition doesn't
+ need to be in this header. */
+class file_cache_slot;
+
+/* A cache of source files for use when emitting diagnostics
+ (and in a few places in the C/C++ frontends).
+
+ Results are only valid until the next call to the cache, as
+ slots can be evicted.
+
+ Filenames are stored by pointer, and so must outlive the cache
+ instance. */
+
+class file_cache
+{
+ public:
+ file_cache ();
+ ~file_cache ();
+
+ file_cache_slot *lookup_or_add_file (const char *file_path);
+ void forcibly_evict_file (const char *file_path);
+
+ /* See comments in diagnostic.h about the input conversion context. */
+ struct input_context
+ {
+ diagnostic_input_charset_callback ccb;
+ bool should_skip_bom;
+ };
+ void initialize_input_context (diagnostic_input_charset_callback ccb,
+ bool should_skip_bom);
+
+ private:
+ file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
+ file_cache_slot *add_file (const char *file_path);
+ file_cache_slot *lookup_file (const char *file_path);
+
+ private:
+ static const size_t num_file_slots = 16;
+ file_cache_slot *m_file_slots;
+ input_context in_context;
+};
+
+extern expanded_location
+expand_location_to_spelling_point (location_t,
+ enum location_aspect aspect
+ = LOCATION_ASPECT_CARET);
+extern location_t expansion_point_location_if_in_system_header (location_t);
+extern location_t expansion_point_location (location_t);
+
+extern location_t input_location;
+
+#define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
+#define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
+#define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
+#define LOCATION_LOCUS(LOC) \
+ ((IS_ADHOC_LOC (LOC)) ? get_location_from_adhoc_loc (line_table, LOC) \
+ : (LOC))
+#define LOCATION_BLOCK(LOC) \
+ ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (line_table, (LOC)) \
+ : NULL))
+#define RESERVED_LOCATION_P(LOC) \
+ (LOCATION_LOCUS (LOC) < RESERVED_LOCATION_COUNT)
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+
+static inline int
+in_system_header_at (location_t loc)
+{
+ return linemap_location_in_system_header_p (line_table, loc);
+}
+
+/* Return true if LOCATION is the locus of a token that
+ comes from a macro expansion, false otherwise. */
+
+static inline bool
+from_macro_expansion_at (location_t loc)
+{
+ return linemap_location_from_macro_expansion_p (line_table, loc);
+}
+
+/* Return true if LOCATION is the locus of a token that comes from
+ a macro definition, false otherwise. This differs from from_macro_expansion_at
+ in its treatment of macro arguments, for which this returns false. */
+
+static inline bool
+from_macro_definition_at (location_t loc)
+{
+ return linemap_location_from_macro_definition_p (line_table, loc);
+}
+
+static inline location_t
+get_pure_location (location_t loc)
+{
+ return get_pure_location (line_table, loc);
+}
+
+/* Get the start of any range encoded within location LOC. */
+
+static inline location_t
+get_start (location_t loc)
+{
+ return get_range_from_loc (line_table, loc).m_start;
+}
+
+/* Get the endpoint of any range encoded within location LOC. */
+
+static inline location_t
+get_finish (location_t loc)
+{
+ return get_range_from_loc (line_table, loc).m_finish;
+}
+
+extern location_t make_location (location_t caret,
+ location_t start, location_t finish);
+extern location_t make_location (location_t caret, source_range src_range);
+
+void dump_line_table_statistics (void);
+
+void dump_location_info (FILE *stream);
+
+void diagnostics_file_cache_fini (void);
+
+void diagnostics_file_cache_forcibly_evict_file (const char *file_path);
+
+class GTY(()) string_concat
+{
+public:
+ string_concat (int num, location_t *locs);
+
+ int m_num;
+ location_t * GTY ((atomic)) m_locs;
+};
+
+class GTY(()) string_concat_db
+{
+ public:
+ string_concat_db ();
+ void record_string_concatenation (int num, location_t *locs);
+
+ bool get_string_concatenation (location_t loc,
+ int *out_num,
+ location_t **out_locs);
+
+ private:
+ static location_t get_key_loc (location_t loc);
+
+ /* For the fields to be private, we must grant access to the
+ generated code in gtype-desc.cc. */
+
+#if 0 // sdcpp
+ friend void ::gt_ggc_mx_string_concat_db (void *x_p);
+ friend void ::gt_pch_nx_string_concat_db (void *x_p);
+ friend void ::gt_pch_p_16string_concat_db (void *this_obj, void *x_p,
+ gt_pointer_operator op,
+ void *cookie);
+#endif // sdcpp
+
+ hash_map <location_hash, string_concat *> *m_table;
+};
+
+#endif
diff --git a/support/cpp/gcc/insn-addr.h b/support/cpp/gcc/insn-addr.h
new file mode 100644
index 000000000..5a1c0b26d
--- /dev/null
+++ b/support/cpp/gcc/insn-addr.h
@@ -0,0 +1,63 @@
+/* Macros to support INSN_ADDRESSES
+ Copyright (C) 2000-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/>. */
+
+#if 0 // sdcpp ndef GCC_INSN_ADDR_H
+#define GCC_INSN_ADDR_H
+
+extern vec<int> insn_addresses_;
+extern int insn_current_address;
+
+#define INSN_ADDRESSES(id) (insn_addresses_[id])
+#define INSN_ADDRESSES_ALLOC(size) \
+ do \
+ { \
+ insn_addresses_.create (size); \
+ insn_addresses_.safe_grow_cleared (size, true); \
+ memset (insn_addresses_.address (), \
+ 0, sizeof (int) * size); \
+ } \
+ while (0)
+#define INSN_ADDRESSES_FREE() (insn_addresses_.release ())
+#define INSN_ADDRESSES_SET_P() (insn_addresses_.exists ())
+#define INSN_ADDRESSES_SIZE() (insn_addresses_.length ())
+
+static inline void
+insn_addresses_new (rtx_insn *insn, int insn_addr)
+{
+ unsigned insn_uid = INSN_UID ((insn));
+
+ if (INSN_ADDRESSES_SET_P ())
+ {
+ size_t size = INSN_ADDRESSES_SIZE ();
+ if (size <= insn_uid)
+ {
+ int *p;
+ insn_addresses_.safe_grow (insn_uid + 1, true);
+ p = insn_addresses_.address ();
+ memset (&p[size],
+ 0, sizeof (int) * (insn_uid + 1 - size));
+ }
+ INSN_ADDRESSES (insn_uid) = insn_addr;
+ }
+}
+
+#define INSN_ADDRESSES_NEW(insn, addr) \
+ (insn_addresses_new (insn, addr))
+
+#endif /* ! GCC_INSN_ADDR_H */
diff --git a/support/cpp/gcc/insn-attr-common.h b/support/cpp/gcc/insn-attr-common.h
new file mode 100644
index 000000000..6802c0efb
--- /dev/null
+++ b/support/cpp/gcc/insn-attr-common.h
@@ -0,0 +1,8 @@
+// scraped together from autogenerated files in gcc
+
+#ifndef GCC_INSN_ATTR_COMMON_H
+#define GCC_INSN_ATTR_COMMON_H
+#define DELAY_SLOTS 0
+enum attr_cpu {CPU_NONE, CPU_PENTIUM, CPU_PENTIUMPRO, CPU_GEODE, CPU_K6, CPU_ATHLON, CPU_K8, CPU_CORE2, CPU_NEHALEM, CPU_ATOM, CPU_SLM, CPU_GLM, CPU_HASWELL, CPU_GENERIC, CPU_AMDFAM10, CPU_BDVER1, CPU_BDVER2, CPU_BDVER3, CPU_BDVER4, CPU_BTVER2, CPU_ZNVER1, CPU_ZNVER2, CPU_ZNVER3};
+
+#endif
diff --git a/support/cpp/gcc/insn-attr.h b/support/cpp/gcc/insn-attr.h
new file mode 100644
index 000000000..0df4c476c
--- /dev/null
+++ b/support/cpp/gcc/insn-attr.h
@@ -0,0 +1,6 @@
+// dummy
+#ifndef GCC_INSN_ATTR_H
+#define GCC_INSN_ATTR_H
+
+#include "insn-attr-common.h"
+#endif // guard
diff --git a/support/cpp/gcc/insn-codes.h b/support/cpp/gcc/insn-codes.h
new file mode 100644
index 000000000..32b8c9c55
--- /dev/null
+++ b/support/cpp/gcc/insn-codes.h
@@ -0,0 +1,4 @@
+// dummy
+#ifndef GCC_INSN_CODES_H
+#define GCC_INSN_CODES_H
+#endif
diff --git a/support/cpp/gcc/insn-config.h b/support/cpp/gcc/insn-config.h
new file mode 100644
index 000000000..b14890d3d
--- /dev/null
+++ b/support/cpp/gcc/insn-config.h
@@ -0,0 +1,7 @@
+// scraped together from gcc automatically generated header
+#ifndef GCC_INSN_CONFIG_H
+#define GCC_INSN_CONFIG_H
+
+#define HAVE_conditional_move 1
+
+#endif
diff --git a/support/cpp/gcc/insn-constants.h b/support/cpp/gcc/insn-constants.h
new file mode 100644
index 000000000..1344bda09
--- /dev/null
+++ b/support/cpp/gcc/insn-constants.h
@@ -0,0 +1,306 @@
+/* Generated automatically by the program `genconstants'
+ from the machine description file `md'. */
+
+#ifndef GCC_INSN_CONSTANTS_H
+#define GCC_INSN_CONSTANTS_H
+
+#define MM7_REG 35
+#define XMM27_REG 63
+#define ST6_REG 14
+#define R13_REG 41
+#define XMM14_REG 50
+#define XMM19_REG 55
+#define ARGP_REG 16
+#define PCOM_TRUE 1
+#define PPERM_ZERO 0x80
+#define XMM6_REG 26
+#define ST3_REG 11
+#define R10_REG 38
+#define XMM11_REG 47
+#define XMM24_REG 60
+#define DX_REG 1
+#define FLAGS_REG 17
+#define ST1_REG 9
+#define MM5_REG 33
+#define MASK7_REG 75
+#define PPERM_SRC 0x00
+#define MM4_REG 32
+#define ST7_REG 15
+#define COM_FALSE_P 3
+#define XMM3_REG 23
+#define ST0_REG 8
+#define COM_FALSE_S 2
+#define SP_REG 7
+#define AX_REG 0
+#define MM1_REG 29
+#define MM3_REG 31
+#define XMM1_REG 21
+#define MASK5_REG 73
+#define ROUND_ZERO 3
+#define PPERM_SRC1 0x00
+#define XMM16_REG 52
+#define PCOM_FALSE 0
+#define XMM8_REG 44
+#define XMM4_REG 24
+#define ST5_REG 13
+#define XMM29_REG 65
+#define XMM23_REG 59
+#define R12_REG 40
+#define R9_REG 37
+#define XMM20_REG 56
+#define ROUND_MXCSR 0x4
+#define MASK4_REG 72
+#define PPERM_INVERT 0x20
+#define MM6_REG 34
+#define XMM26_REG 62
+#define PPERM_SRC2 0x10
+#define ST2_REG 10
+#define MASK1_REG 69
+#define ABI_VZEROUPPER 1
+#define NO_ROUND 4
+#define XMM10_REG 46
+#define ROUND_TRUNC 0x3
+#define PPERM_SIGN 0xc0
+#define R8_REG 36
+#define XMM9_REG 45
+#define XMM18_REG 54
+#define MASK3_REG 71
+#define DI_REG 5
+#define XMM25_REG 61
+#define ABI_DEFAULT 0
+#define BP_REG 6
+#define ROUND_ROUNDEVEN 0x0
+#define XMM12_REG 48
+#define XMM5_REG 25
+#define COM_TRUE_S 4
+#define ROUND_FLOOR 0x1
+#define FPSR_REG 18
+#define MASK6_REG 74
+#define R14_REG 42
+#define XMM15_REG 51
+#define XMM28_REG 64
+#define R15_REG 43
+#define XMM13_REG 49
+#define ROUND_NEAREST_INT 0
+#define ROUND_CEIL 0x2
+#define MM0_REG 28
+#define XMM31_REG 67
+#define BX_REG 3
+#define XMM7_REG 27
+#define XMM30_REG 66
+#define ST4_REG 12
+#define PPERM_INV_SIGN 0xe0
+#define R11_REG 39
+#define FIRST_PSEUDO_REG 76
+#define PPERM_REVERSE 0x40
+#define CX_REG 2
+#define ABI_UNKNOWN 2
+#define MASK0_REG 68
+#define COM_TRUE_P 5
+#define SI_REG 4
+#define XMM22_REG 58
+#define XMM0_REG 20
+#define XMM17_REG 53
+#define ROUND_NEG_INF 1
+#define ROUND_POS_INF 2
+#define XMM2_REG 22
+#define FRAME_REG 19
+#define PPERM_ONES 0xa0
+#define XMM21_REG 57
+#define ROUND_NO_EXC 0x8
+#define MM2_REG 30
+#define ROUND_SAE 8
+#define MASK2_REG 70
+#define PPERM_REV_INV 0x60
+
+enum unspec {
+ UNSPEC_GOT = 0,
+ UNSPEC_GOTOFF = 1,
+ UNSPEC_GOTPCREL = 2,
+ UNSPEC_GOTTPOFF = 3,
+ UNSPEC_TPOFF = 4,
+ UNSPEC_NTPOFF = 5,
+ UNSPEC_DTPOFF = 6,
+ UNSPEC_GOTNTPOFF = 7,
+ UNSPEC_INDNTPOFF = 8,
+ UNSPEC_PLTOFF = 9,
+ UNSPEC_MACHOPIC_OFFSET = 10,
+ UNSPEC_PCREL = 11,
+ UNSPEC_SIZEOF = 12,
+ UNSPEC_STACK_ALLOC = 13,
+ UNSPEC_SET_GOT = 14,
+ UNSPEC_SET_RIP = 15,
+ UNSPEC_SET_GOT_OFFSET = 16,
+ UNSPEC_MEMORY_BLOCKAGE = 17,
+ UNSPEC_PROBE_STACK = 18,
+ UNSPEC_TP = 19,
+ UNSPEC_TLS_GD = 20,
+ UNSPEC_TLS_LD_BASE = 21,
+ UNSPEC_TLSDESC = 22,
+ UNSPEC_TLS_IE_SUN = 23,
+ UNSPEC_SCAS = 24,
+ UNSPEC_FNSTSW = 25,
+ UNSPEC_SAHF = 26,
+ UNSPEC_NOTRAP = 27,
+ UNSPEC_PARITY = 28,
+ UNSPEC_FSTCW = 29,
+ UNSPEC_REP = 30,
+ UNSPEC_LD_MPIC = 31,
+ UNSPEC_TRUNC_NOOP = 32,
+ UNSPEC_DIV_ALREADY_SPLIT = 33,
+ UNSPEC_PAUSE = 34,
+ UNSPEC_LEA_ADDR = 35,
+ UNSPEC_XBEGIN_ABORT = 36,
+ UNSPEC_STOS = 37,
+ UNSPEC_PEEPSIB = 38,
+ UNSPEC_INSN_FALSE_DEP = 39,
+ UNSPEC_SBB = 40,
+ UNSPEC_FIX_NOTRUNC = 41,
+ UNSPEC_MASKMOV = 42,
+ UNSPEC_MOVCC_MASK = 43,
+ UNSPEC_MOVMSK = 44,
+ UNSPEC_BLENDV = 45,
+ UNSPEC_PSHUFB = 46,
+ UNSPEC_XOP_PERMUTE = 47,
+ UNSPEC_RCP = 48,
+ UNSPEC_RSQRT = 49,
+ UNSPEC_PSADBW = 50,
+ UNSPEC_SCALEF = 51,
+ UNSPEC_PCMP = 52,
+ UNSPEC_IEEE_MIN = 53,
+ UNSPEC_IEEE_MAX = 54,
+ UNSPEC_SIN = 55,
+ UNSPEC_COS = 56,
+ UNSPEC_FPATAN = 57,
+ UNSPEC_FYL2X = 58,
+ UNSPEC_FYL2XP1 = 59,
+ UNSPEC_FRNDINT = 60,
+ UNSPEC_FIST = 61,
+ UNSPEC_F2XM1 = 62,
+ UNSPEC_TAN = 63,
+ UNSPEC_FXAM = 64,
+ UNSPEC_FRNDINT_ROUNDEVEN = 65,
+ UNSPEC_FRNDINT_FLOOR = 66,
+ UNSPEC_FRNDINT_CEIL = 67,
+ UNSPEC_FRNDINT_TRUNC = 68,
+ UNSPEC_FIST_FLOOR = 69,
+ UNSPEC_FIST_CEIL = 70,
+ UNSPEC_SINCOS_COS = 71,
+ UNSPEC_SINCOS_SIN = 72,
+ UNSPEC_XTRACT_FRACT = 73,
+ UNSPEC_XTRACT_EXP = 74,
+ UNSPEC_FSCALE_FRACT = 75,
+ UNSPEC_FSCALE_EXP = 76,
+ UNSPEC_FPREM_F = 77,
+ UNSPEC_FPREM_U = 78,
+ UNSPEC_FPREM1_F = 79,
+ UNSPEC_FPREM1_U = 80,
+ UNSPEC_C2_FLAG = 81,
+ UNSPEC_FXAM_MEM = 82,
+ UNSPEC_SP_SET = 83,
+ UNSPEC_SP_TEST = 84,
+ UNSPEC_ROUND = 85,
+ UNSPEC_CRC32 = 86,
+ UNSPEC_LZCNT = 87,
+ UNSPEC_TZCNT = 88,
+ UNSPEC_BEXTR = 89,
+ UNSPEC_PDEP = 90,
+ UNSPEC_PEXT = 91,
+ UNSPEC_INTERRUPT_RETURN = 92,
+ UNSPEC_MOVDIRI = 93,
+ UNSPEC_MOVDIR64B = 94,
+ UNSPEC_CALLEE_ABI = 95
+};
+#define NUM_UNSPEC_VALUES 96
+extern const char *const unspec_strings[];
+
+enum unspecv {
+ UNSPECV_UD2 = 0,
+ UNSPECV_BLOCKAGE = 1,
+ UNSPECV_STACK_PROBE = 2,
+ UNSPECV_PROBE_STACK_RANGE = 3,
+ UNSPECV_ALIGN = 4,
+ UNSPECV_PROLOGUE_USE = 5,
+ UNSPECV_SPLIT_STACK_RETURN = 6,
+ UNSPECV_CLD = 7,
+ UNSPECV_NOPS = 8,
+ UNSPECV_RDTSC = 9,
+ UNSPECV_RDTSCP = 10,
+ UNSPECV_RDPMC = 11,
+ UNSPECV_LLWP_INTRINSIC = 12,
+ UNSPECV_SLWP_INTRINSIC = 13,
+ UNSPECV_LWPVAL_INTRINSIC = 14,
+ UNSPECV_LWPINS_INTRINSIC = 15,
+ UNSPECV_RDFSBASE = 16,
+ UNSPECV_RDGSBASE = 17,
+ UNSPECV_WRFSBASE = 18,
+ UNSPECV_WRGSBASE = 19,
+ UNSPECV_FXSAVE = 20,
+ UNSPECV_FXRSTOR = 21,
+ UNSPECV_FXSAVE64 = 22,
+ UNSPECV_FXRSTOR64 = 23,
+ UNSPECV_XSAVE = 24,
+ UNSPECV_XRSTOR = 25,
+ UNSPECV_XSAVE64 = 26,
+ UNSPECV_XRSTOR64 = 27,
+ UNSPECV_XSAVEOPT = 28,
+ UNSPECV_XSAVEOPT64 = 29,
+ UNSPECV_XSAVES = 30,
+ UNSPECV_XRSTORS = 31,
+ UNSPECV_XSAVES64 = 32,
+ UNSPECV_XRSTORS64 = 33,
+ UNSPECV_XSAVEC = 34,
+ UNSPECV_XSAVEC64 = 35,
+ UNSPECV_XGETBV = 36,
+ UNSPECV_XSETBV = 37,
+ UNSPECV_WBINVD = 38,
+ UNSPECV_WBNOINVD = 39,
+ UNSPECV_FNSTENV = 40,
+ UNSPECV_FLDENV = 41,
+ UNSPECV_FNSTSW = 42,
+ UNSPECV_FNCLEX = 43,
+ UNSPECV_RDRAND = 44,
+ UNSPECV_RDSEED = 45,
+ UNSPECV_XBEGIN = 46,
+ UNSPECV_XEND = 47,
+ UNSPECV_XABORT = 48,
+ UNSPECV_XTEST = 49,
+ UNSPECV_NLGR = 50,
+ UNSPECV_CLWB = 51,
+ UNSPECV_CLFLUSHOPT = 52,
+ UNSPECV_MONITORX = 53,
+ UNSPECV_MWAITX = 54,
+ UNSPECV_CLZERO = 55,
+ UNSPECV_PKU = 56,
+ UNSPECV_RDPID = 57,
+ UNSPECV_NOP_ENDBR = 58,
+ UNSPECV_NOP_RDSSP = 59,
+ UNSPECV_INCSSP = 60,
+ UNSPECV_SAVEPREVSSP = 61,
+ UNSPECV_RSTORSSP = 62,
+ UNSPECV_WRSS = 63,
+ UNSPECV_WRUSS = 64,
+ UNSPECV_SETSSBSY = 65,
+ UNSPECV_CLRSSBSY = 66,
+ UNSPECV_XSUSLDTRK = 67,
+ UNSPECV_XRESLDTRK = 68,
+ UNSPECV_UMWAIT = 69,
+ UNSPECV_UMONITOR = 70,
+ UNSPECV_TPAUSE = 71,
+ UNSPECV_CLUI = 72,
+ UNSPECV_STUI = 73,
+ UNSPECV_TESTUI = 74,
+ UNSPECV_SENDUIPI = 75,
+ UNSPECV_CLDEMOTE = 76,
+ UNSPECV_SPECULATION_BARRIER = 77,
+ UNSPECV_PTWRITE = 78,
+ UNSPECV_ENQCMD = 79,
+ UNSPECV_ENQCMDS = 80,
+ UNSPECV_SERIALIZE = 81,
+ UNSPECV_PATCHABLE_AREA = 82,
+ UNSPECV_HRESET = 83
+};
+#define NUM_UNSPECV_VALUES 84
+extern const char *const unspecv_strings[];
+
+#endif /* GCC_INSN_CONSTANTS_H */
diff --git a/support/cpp/gcc/insn-flags.h b/support/cpp/gcc/insn-flags.h
new file mode 100644
index 000000000..8b262d51e
--- /dev/null
+++ b/support/cpp/gcc/insn-flags.h
@@ -0,0 +1,5 @@
+// dummy
+
+#ifndef GCC_INSN_FLAGS_H
+#define GCC_INSN_FLAGS_H
+#endif
diff --git a/support/cpp/gcc/insn-modes-inline.h b/support/cpp/gcc/insn-modes-inline.h
new file mode 100644
index 000000000..c62be0637
--- /dev/null
+++ b/support/cpp/gcc/insn-modes-inline.h
@@ -0,0 +1,24 @@
+#ifndef GCC_INSN_MODES_INLINE_H
+#define GCC_INSN_MODES_INLINE_H
+#ifdef __cplusplus
+inline __attribute__((__always_inline__))
+#else
+extern __inline__ __attribute__((__always_inline__, __gnu_inline__))
+#endif
+unsigned char
+mode_inner_inline (machine_mode mode)
+{
+ extern const unsigned char mode_inner[NUM_MACHINE_MODES];
+ gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);
+ switch (mode)
+ {
+ case E_VOIDmode: return E_VOIDmode;
+ case E_BLKmode: return E_BLKmode;
+ case E_HFmode: return E_HFmode;
+ case E_TFmode: return E_TFmode;
+ case E_SDmode: return E_SDmode;
+ case E_TDmode: return E_TDmode;
+ default: return mode_inner[mode];
+ }
+}
+#endif
diff --git a/support/cpp/gcc/insn-modes.h b/support/cpp/gcc/insn-modes.h
new file mode 100644
index 000000000..80bcc1153
--- /dev/null
+++ b/support/cpp/gcc/insn-modes.h
@@ -0,0 +1,43 @@
+#ifndef GCC_INSN_MODES_H
+#define GCC_INSN_MODES_H
+
+// sdcpp hacks
+#define BITS_PER_UNIT 8
+#define MAX_BITSIZE_MODE_ANY_INT (64*BITS_PER_UNIT)
+#define NUM_INT_N_ENTS 1
+
+
+enum machine_mode
+{
+ E_VOIDmode, /* machmode.def:193 */
+#define HAVE_VOIDmode
+#ifdef USE_ENUM_MODES
+#define VOIDmode E_VOIDmode
+#else
+#define VOIDmode ((void) 0, E_VOIDmode)
+#endif
+ E_BLKmode, /* machmode.def:197 */
+#define HAVE_BLKmode
+#ifdef USE_ENUM_MODES
+#define BLKmode E_BLKmode
+#else
+#define BLKmode ((void) 0, E_BLKmode)
+#endif
+ MAX_MACHINE_MODE,
+ E_HFmode, /* config/i386/i386-modes.def:26 */
+ E_TFmode, /* config/i386/i386-modes.def:25 */
+ E_SDmode, /* machmode.def:271 */
+ E_TDmode, /* machmode.def:273 */
+ MIN_MODE_DECIMAL_FLOAT = E_SDmode,
+ MAX_MODE_DECIMAL_FLOAT = E_TDmode,
+ MIN_MODE_FLOAT = E_HFmode,
+ MAX_MODE_FLOAT = E_TFmode,
+ NUM_MACHINE_MODES = MAX_MACHINE_MODE
+};
+
+// sdcpp insn-modes ..
+#define NUM_MODE_FLOAT (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)
+#define NUM_MODE_DECIMAL_FLOAT (MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1)
+
+
+#endif
diff --git a/support/cpp/gcc/insn-notes.def b/support/cpp/gcc/insn-notes.def
new file mode 100644
index 000000000..dd3f1558c
--- /dev/null
+++ b/support/cpp/gcc/insn-notes.def
@@ -0,0 +1,98 @@
+/* Insn note definitions.
+ Copyright (C) 2004-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 defines all the codes that may appear in the
+ NOTE_LINE_NUMBER field of a NOTE insn for kinds of notes that are
+ not line numbers. Source files define DEF_INSN_NOTE appropriately
+ before including this file.
+
+ We are slowly removing the concept of insn-chain notes from the
+ compiler. Adding new codes to this file is STRONGLY DISCOURAGED.
+ If you think you need one, look for other ways to express what you
+ mean, such as register notes or bits in the basic-block structure. */
+
+/* Shorthand. */
+#define INSN_NOTE(NAME) DEF_INSN_NOTE (NOTE_INSN_##NAME)
+
+/* This note is used to get rid of an insn when it isn't safe to patch
+ the insn out of the chain. */
+INSN_NOTE (DELETED)
+
+/* Generated in place of user-declared labels when they are deleted. */
+INSN_NOTE (DELETED_LABEL)
+/* Similarly, but for labels that have been present in debug stmts
+ earlier and thus will only appear with -g. These must use different
+ label namespace. */
+INSN_NOTE (DELETED_DEBUG_LABEL)
+
+/* These are used to mark the beginning and end of a lexical block.
+ See NOTE_BLOCK and reorder_blocks. */
+INSN_NOTE (BLOCK_BEG)
+INSN_NOTE (BLOCK_END)
+
+/* This note indicates the start of the real body of the function,
+ i.e. the point just after all of the parms have been moved into
+ their homes, etc. */
+INSN_NOTE (FUNCTION_BEG)
+
+/* This marks the point immediately after the last prologue insn. */
+INSN_NOTE (PROLOGUE_END)
+
+/* This marks the point immediately prior to the first epilogue insn. */
+INSN_NOTE (EPILOGUE_BEG)
+
+/* These note where exception handling regions begin and end.
+ Uses NOTE_EH_HANDLER to identify the region in question. */
+INSN_NOTE (EH_REGION_BEG)
+INSN_NOTE (EH_REGION_END)
+
+/* The location of a variable. */
+INSN_NOTE (VAR_LOCATION)
+
+/* The beginning of a statement. */
+INSN_NOTE (BEGIN_STMT)
+
+/* The entry point for an inlined function. Its NOTE_BLOCK references
+ the lexical block whose abstract origin is the inlined function. */
+INSN_NOTE (INLINE_ENTRY)
+
+/* Record the struct for the following basic block. Uses
+ NOTE_BASIC_BLOCK. FIXME: Redundant with the basic block pointer
+ now included in every insn. NOTE: If there's no CFG anymore, in other words,
+ if BLOCK_FOR_INSN () == NULL, NOTE_BASIC_BLOCK cannot be considered reliable
+ anymore. */
+INSN_NOTE (BASIC_BLOCK)
+
+/* Mark the inflection point in the instruction stream where we switch
+ between hot and cold text sections. */
+INSN_NOTE (SWITCH_TEXT_SECTIONS)
+
+/* When emitting dwarf2 frame information, contains a directive that
+ should be emitted. */
+INSN_NOTE (CFI)
+
+/* When emitting dwarf2 frame information, contains the number of a debug
+ label that should be emitted. */
+INSN_NOTE (CFI_LABEL)
+
+/* This note indicates that the function context must be updated if
+ the Setjmp/Longjmp exception mechanism is used. */
+INSN_NOTE (UPDATE_SJLJ_CONTEXT)
+
+#undef INSN_NOTE
diff --git a/support/cpp/gcc/int-vector-builder.h b/support/cpp/gcc/int-vector-builder.h
new file mode 100644
index 000000000..36680a7cd
--- /dev/null
+++ b/support/cpp/gcc/int-vector-builder.h
@@ -0,0 +1,93 @@
+/* A class for building vector integer constants.
+ Copyright (C) 2017-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_INT_VECTOR_BUILDER_H
+#define GCC_INT_VECTOR_BUILDER_H 1
+
+#include "vector-builder.h"
+
+/* This class is used to build vectors of integer type T using the same
+ encoding as tree and rtx constants. See vector_builder for more
+ details. */
+template<typename T>
+class int_vector_builder : public vector_builder<T, poly_uint64,
+ int_vector_builder<T> >
+{
+ typedef vector_builder<T, poly_uint64, int_vector_builder> parent;
+ friend class vector_builder<T, poly_uint64, int_vector_builder>;
+
+public:
+ int_vector_builder () {}
+ int_vector_builder (poly_uint64, unsigned int, unsigned int);
+
+ using parent::new_vector;
+
+private:
+ bool equal_p (T, T) const;
+ bool allow_steps_p () const { return true; }
+ bool integral_p (T) const { return true; }
+ T step (T, T) const;
+ T apply_step (T, unsigned int, T) const;
+ bool can_elide_p (T) const { return true; }
+ void note_representative (T *, T) {}
+
+ static poly_uint64 shape_nelts (poly_uint64 x) { return x; }
+};
+
+/* Create a new builder for a vector with FULL_NELTS elements.
+ Initially encode the value as NPATTERNS interleaved patterns with
+ NELTS_PER_PATTERN elements each. */
+
+template<typename T>
+inline
+int_vector_builder<T>::int_vector_builder (poly_uint64 full_nelts,
+ unsigned int npatterns,
+ unsigned int nelts_per_pattern)
+{
+ new_vector (full_nelts, npatterns, nelts_per_pattern);
+}
+
+/* Return true if elements ELT1 and ELT2 are equal. */
+
+template<typename T>
+inline bool
+int_vector_builder<T>::equal_p (T elt1, T elt2) const
+{
+ return known_eq (elt1, elt2);
+}
+
+/* Return the value of element ELT2 minus the value of element ELT1. */
+
+template<typename T>
+inline T
+int_vector_builder<T>::step (T elt1, T elt2) const
+{
+ return elt2 - elt1;
+}
+
+/* Return a vector element with the value BASE + FACTOR * STEP. */
+
+template<typename T>
+inline T
+int_vector_builder<T>::apply_step (T base, unsigned int factor, T step) const
+{
+ return base + factor * step;
+}
+
+#endif
diff --git a/support/cpp/gcc/internal-fn.def b/support/cpp/gcc/internal-fn.def
new file mode 100644
index 000000000..d2d550d35
--- /dev/null
+++ b/support/cpp/gcc/internal-fn.def
@@ -0,0 +1,441 @@
+/* Internal functions.
+ 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/>. */
+
+/* This file specifies a list of internal "functions". These functions
+ differ from built-in functions in that they have no linkage and cannot
+ be called directly by the user. They represent operations that are only
+ synthesised by GCC itself.
+
+ Internal functions are used instead of tree codes if the operation
+ and its operands are more naturally represented as a GIMPLE_CALL
+ than a GIMPLE_ASSIGN.
+
+ Each entry in this file has one of the forms:
+
+ DEF_INTERNAL_FN (NAME, FLAGS, FNSPEC)
+ DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
+ DEF_INTERNAL_SIGNED_OPTAB_FN (NAME, FLAGS, SELECTOR, SIGNED_OPTAB,
+ UNSIGNED_OPTAB, TYPE)
+ DEF_INTERNAL_FLT_FN (NAME, FLAGS, OPTAB, TYPE)
+ DEF_INTERNAL_INT_FN (NAME, FLAGS, OPTAB, TYPE)
+
+ where NAME is the name of the function, FLAGS is a set of
+ ECF_* flags and FNSPEC is a string describing functions fnspec.
+
+ DEF_INTERNAL_OPTAB_FN defines an internal function that maps to a
+ direct optab. The function should only be called with a given
+ set of types if the associated optab is available for the modes
+ of those types. OPTAB says what optab to use (without the trailing
+ "_optab") and TYPE categorizes the optab based on its inputs and
+ outputs. The possible types of optab are:
+
+ - mask_load: currently just maskload
+ - load_lanes: currently just vec_load_lanes
+ - mask_load_lanes: currently just vec_mask_load_lanes
+ - gather_load: used for {mask_,}gather_load
+ - len_load: currently just len_load
+
+ - mask_store: currently just maskstore
+ - store_lanes: currently just vec_store_lanes
+ - mask_store_lanes: currently just vec_mask_store_lanes
+ - scatter_store: used for {mask_,}scatter_store
+ - len_store: currently just len_store
+
+ - unary: a normal unary optab, such as vec_reverse_<mode>
+ - binary: a normal binary optab, such as vec_interleave_lo_<mode>
+ - ternary: a normal ternary optab, such as fma<mode>4
+
+ - cond_binary: a conditional binary optab, such as cond_add<mode>
+ - cond_ternary: a conditional ternary optab, such as cond_fma_rev<mode>
+
+ - fold_left: for scalar = FN (scalar, vector), keyed off the vector mode
+ - check_ptrs: used for check_{raw,war}_ptrs
+
+ DEF_INTERNAL_SIGNED_OPTAB_FN defines an internal function that
+ maps to one of two optabs, depending on the signedness of an input.
+ SIGNED_OPTAB and UNSIGNED_OPTAB are the optabs for signed and
+ unsigned inputs respectively, both without the trailing "_optab".
+ SELECTOR says which type in the tree_pair determines the signedness.
+
+ DEF_INTERNAL_FLT_FN is like DEF_INTERNAL_OPTAB_FN, but in addition,
+ the function implements the computational part of a built-in math
+ function BUILT_IN_<NAME>{F,,L}. Unlike some built-in functions,
+ these internal functions never set errno.
+
+ DEF_INTERNAL_INT_FN is like DEF_INTERNAL_OPTAB_FN, but in addition
+ says that the function extends the C-level BUILT_IN_<NAME>{,L,LL,IMAX}
+ group of functions to any integral mode (including vector modes).
+
+ Each entry must have a corresponding expander of the form:
+
+ void expand_NAME (gimple_call stmt)
+
+ where STMT is the statement that performs the call. These are generated
+ automatically for optab functions and call out to a function or macro
+ called expand_<TYPE>_optab_fn. */
+
+#ifndef DEF_INTERNAL_FN
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC)
+#endif
+
+#ifndef DEF_INTERNAL_OPTAB_FN
+#define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \
+ DEF_INTERNAL_FN (NAME, FLAGS | ECF_LEAF, NULL)
+#endif
+
+#ifndef DEF_INTERNAL_SIGNED_OPTAB_FN
+#define DEF_INTERNAL_SIGNED_OPTAB_FN(NAME, FLAGS, SELECTOR, SIGNED_OPTAB, \
+ UNSIGNED_OPTAB, TYPE) \
+ DEF_INTERNAL_FN (NAME, FLAGS | ECF_LEAF, NULL)
+#endif
+
+#ifndef DEF_INTERNAL_FLT_FN
+#define DEF_INTERNAL_FLT_FN(NAME, FLAGS, OPTAB, TYPE) \
+ DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
+#endif
+
+#ifndef DEF_INTERNAL_FLT_FLOATN_FN
+#define DEF_INTERNAL_FLT_FLOATN_FN(NAME, FLAGS, OPTAB, TYPE) \
+ DEF_INTERNAL_FLT_FN (NAME, FLAGS, OPTAB, TYPE)
+#endif
+
+#ifndef DEF_INTERNAL_INT_FN
+#define DEF_INTERNAL_INT_FN(NAME, FLAGS, OPTAB, TYPE) \
+ DEF_INTERNAL_OPTAB_FN (NAME, FLAGS, OPTAB, TYPE)
+#endif
+
+DEF_INTERNAL_OPTAB_FN (MASK_LOAD, ECF_PURE, maskload, mask_load)
+DEF_INTERNAL_OPTAB_FN (LOAD_LANES, ECF_CONST, vec_load_lanes, load_lanes)
+DEF_INTERNAL_OPTAB_FN (MASK_LOAD_LANES, ECF_PURE,
+ vec_mask_load_lanes, mask_load_lanes)
+
+DEF_INTERNAL_OPTAB_FN (GATHER_LOAD, ECF_PURE, gather_load, gather_load)
+DEF_INTERNAL_OPTAB_FN (MASK_GATHER_LOAD, ECF_PURE,
+ mask_gather_load, gather_load)
+
+DEF_INTERNAL_OPTAB_FN (LEN_LOAD, ECF_PURE, len_load, len_load)
+
+DEF_INTERNAL_OPTAB_FN (SCATTER_STORE, 0, scatter_store, scatter_store)
+DEF_INTERNAL_OPTAB_FN (MASK_SCATTER_STORE, 0,
+ mask_scatter_store, scatter_store)
+
+DEF_INTERNAL_OPTAB_FN (MASK_STORE, 0, maskstore, mask_store)
+DEF_INTERNAL_OPTAB_FN (STORE_LANES, ECF_CONST, vec_store_lanes, store_lanes)
+DEF_INTERNAL_OPTAB_FN (MASK_STORE_LANES, 0,
+ vec_mask_store_lanes, mask_store_lanes)
+
+DEF_INTERNAL_OPTAB_FN (VCOND, 0, vcond, vec_cond)
+DEF_INTERNAL_OPTAB_FN (VCONDU, 0, vcondu, vec_cond)
+DEF_INTERNAL_OPTAB_FN (VCONDEQ, 0, vcondeq, vec_cond)
+DEF_INTERNAL_OPTAB_FN (VCOND_MASK, 0, vcond_mask, vec_cond_mask)
+
+DEF_INTERNAL_OPTAB_FN (VEC_SET, 0, vec_set, vec_set)
+
+DEF_INTERNAL_OPTAB_FN (LEN_STORE, 0, len_store, len_store)
+
+DEF_INTERNAL_OPTAB_FN (WHILE_ULT, ECF_CONST | ECF_NOTHROW, while_ult, while)
+DEF_INTERNAL_OPTAB_FN (CHECK_RAW_PTRS, ECF_CONST | ECF_NOTHROW,
+ check_raw_ptrs, check_ptrs)
+DEF_INTERNAL_OPTAB_FN (CHECK_WAR_PTRS, ECF_CONST | ECF_NOTHROW,
+ check_war_ptrs, check_ptrs)
+
+DEF_INTERNAL_OPTAB_FN (VEC_SHL_INSERT, ECF_CONST | ECF_NOTHROW,
+ vec_shl_insert, binary)
+
+DEF_INTERNAL_OPTAB_FN (DIV_POW2, ECF_CONST | ECF_NOTHROW, sdiv_pow2, binary)
+
+DEF_INTERNAL_OPTAB_FN (FMS, ECF_CONST, fms, ternary)
+DEF_INTERNAL_OPTAB_FN (FNMA, ECF_CONST, fnma, ternary)
+DEF_INTERNAL_OPTAB_FN (FNMS, ECF_CONST, fnms, ternary)
+
+DEF_INTERNAL_SIGNED_OPTAB_FN (AVG_FLOOR, ECF_CONST | ECF_NOTHROW, first,
+ savg_floor, uavg_floor, binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (AVG_CEIL, ECF_CONST | ECF_NOTHROW, first,
+ savg_ceil, uavg_ceil, binary)
+
+DEF_INTERNAL_SIGNED_OPTAB_FN (MULH, ECF_CONST | ECF_NOTHROW, first,
+ smul_highpart, umul_highpart, binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (MULHS, ECF_CONST | ECF_NOTHROW, first,
+ smulhs, umulhs, binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (MULHRS, ECF_CONST | ECF_NOTHROW, first,
+ smulhrs, umulhrs, binary)
+
+DEF_INTERNAL_OPTAB_FN (COND_ADD, ECF_CONST, cond_add, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_SUB, ECF_CONST, cond_sub, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_MUL, ECF_CONST, cond_smul, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_DIV, ECF_CONST, first,
+ cond_sdiv, cond_udiv, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MOD, ECF_CONST, first,
+ cond_smod, cond_umod, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_RDIV, ECF_CONST, cond_sdiv, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MIN, ECF_CONST, first,
+ cond_smin, cond_umin, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MAX, ECF_CONST, first,
+ cond_smax, cond_umax, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_FMIN, ECF_CONST, cond_fmin, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_FMAX, ECF_CONST, cond_fmax, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_AND, ECF_CONST | ECF_NOTHROW,
+ cond_and, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_IOR, ECF_CONST | ECF_NOTHROW,
+ cond_ior, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_XOR, ECF_CONST | ECF_NOTHROW,
+ cond_xor, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_SHL, ECF_CONST | ECF_NOTHROW,
+ cond_ashl, cond_binary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (COND_SHR, ECF_CONST | ECF_NOTHROW, first,
+ cond_ashr, cond_lshr, cond_binary)
+
+DEF_INTERNAL_OPTAB_FN (COND_FMA, ECF_CONST, cond_fma, cond_ternary)
+DEF_INTERNAL_OPTAB_FN (COND_FMS, ECF_CONST, cond_fms, cond_ternary)
+DEF_INTERNAL_OPTAB_FN (COND_FNMA, ECF_CONST, cond_fnma, cond_ternary)
+DEF_INTERNAL_OPTAB_FN (COND_FNMS, ECF_CONST, cond_fnms, cond_ternary)
+
+DEF_INTERNAL_OPTAB_FN (COND_NEG, ECF_CONST, cond_neg, cond_unary)
+
+DEF_INTERNAL_OPTAB_FN (RSQRT, ECF_CONST, rsqrt, unary)
+
+DEF_INTERNAL_OPTAB_FN (REDUC_PLUS, ECF_CONST | ECF_NOTHROW,
+ reduc_plus_scal, unary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (REDUC_MAX, ECF_CONST | ECF_NOTHROW, first,
+ reduc_smax_scal, reduc_umax_scal, unary)
+DEF_INTERNAL_SIGNED_OPTAB_FN (REDUC_MIN, ECF_CONST | ECF_NOTHROW, first,
+ reduc_smin_scal, reduc_umin_scal, unary)
+DEF_INTERNAL_OPTAB_FN (REDUC_FMAX, ECF_CONST | ECF_NOTHROW,
+ reduc_fmax_scal, unary)
+DEF_INTERNAL_OPTAB_FN (REDUC_FMIN, ECF_CONST | ECF_NOTHROW,
+ reduc_fmin_scal, unary)
+DEF_INTERNAL_OPTAB_FN (REDUC_AND, ECF_CONST | ECF_NOTHROW,
+ reduc_and_scal, unary)
+DEF_INTERNAL_OPTAB_FN (REDUC_IOR, ECF_CONST | ECF_NOTHROW,
+ reduc_ior_scal, unary)
+DEF_INTERNAL_OPTAB_FN (REDUC_XOR, ECF_CONST | ECF_NOTHROW,
+ reduc_xor_scal, unary)
+
+/* Extract the last active element from a vector. */
+DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
+ extract_last, fold_left)
+
+/* Same, but return the first argument if no elements are active. */
+DEF_INTERNAL_OPTAB_FN (FOLD_EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
+ fold_extract_last, fold_extract)
+
+DEF_INTERNAL_OPTAB_FN (FOLD_LEFT_PLUS, ECF_CONST | ECF_NOTHROW,
+ fold_left_plus, fold_left)
+
+DEF_INTERNAL_OPTAB_FN (MASK_FOLD_LEFT_PLUS, ECF_CONST | ECF_NOTHROW,
+ mask_fold_left_plus, mask_fold_left)
+
+/* Unary math functions. */
+DEF_INTERNAL_FLT_FN (ACOS, ECF_CONST, acos, unary)
+DEF_INTERNAL_FLT_FN (ACOSH, ECF_CONST, acosh, unary)
+DEF_INTERNAL_FLT_FN (ASIN, ECF_CONST, asin, unary)
+DEF_INTERNAL_FLT_FN (ASINH, ECF_CONST, asinh, unary)
+DEF_INTERNAL_FLT_FN (ATAN, ECF_CONST, atan, unary)
+DEF_INTERNAL_FLT_FN (ATANH, ECF_CONST, atanh, unary)
+DEF_INTERNAL_FLT_FN (COS, ECF_CONST, cos, unary)
+DEF_INTERNAL_FLT_FN (COSH, ECF_CONST, cosh, unary)
+DEF_INTERNAL_FLT_FN (EXP, ECF_CONST, exp, unary)
+DEF_INTERNAL_FLT_FN (EXP10, ECF_CONST, exp10, unary)
+DEF_INTERNAL_FLT_FN (EXP2, ECF_CONST, exp2, unary)
+DEF_INTERNAL_FLT_FN (EXPM1, ECF_CONST, expm1, unary)
+DEF_INTERNAL_FLT_FN (LOG, ECF_CONST, log, unary)
+DEF_INTERNAL_FLT_FN (LOG10, ECF_CONST, log10, unary)
+DEF_INTERNAL_FLT_FN (LOG1P, ECF_CONST, log1p, unary)
+DEF_INTERNAL_FLT_FN (LOG2, ECF_CONST, log2, unary)
+DEF_INTERNAL_FLT_FN (LOGB, ECF_CONST, logb, unary)
+DEF_INTERNAL_FLT_FN (SIGNBIT, ECF_CONST, signbit, unary)
+DEF_INTERNAL_FLT_FN (SIGNIFICAND, ECF_CONST, significand, unary)
+DEF_INTERNAL_FLT_FN (SIN, ECF_CONST, sin, unary)
+DEF_INTERNAL_FLT_FN (SINH, ECF_CONST, sinh, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (SQRT, ECF_CONST, sqrt, unary)
+DEF_INTERNAL_FLT_FN (TAN, ECF_CONST, tan, unary)
+DEF_INTERNAL_FLT_FN (TANH, ECF_CONST, tanh, unary)
+
+/* FP rounding. */
+DEF_INTERNAL_FLT_FLOATN_FN (CEIL, ECF_CONST, ceil, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (FLOOR, ECF_CONST, floor, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (NEARBYINT, ECF_CONST, nearbyint, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (RINT, ECF_CONST, rint, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUND, ECF_CONST, round, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (ROUNDEVEN, ECF_CONST, roundeven, unary)
+DEF_INTERNAL_FLT_FLOATN_FN (TRUNC, ECF_CONST, btrunc, unary)
+
+/* Binary math functions. */
+DEF_INTERNAL_FLT_FN (ATAN2, ECF_CONST, atan2, binary)
+DEF_INTERNAL_FLT_FLOATN_FN (COPYSIGN, ECF_CONST, copysign, binary)
+DEF_INTERNAL_FLT_FN (FMOD, ECF_CONST, fmod, binary)
+DEF_INTERNAL_FLT_FN (HYPOT, ECF_CONST, hypot, binary)
+DEF_INTERNAL_FLT_FN (POW, ECF_CONST, pow, binary)
+DEF_INTERNAL_FLT_FN (REMAINDER, ECF_CONST, remainder, binary)
+DEF_INTERNAL_FLT_FN (SCALB, ECF_CONST, scalb, binary)
+DEF_INTERNAL_FLT_FLOATN_FN (FMIN, ECF_CONST, fmin, binary)
+DEF_INTERNAL_FLT_FLOATN_FN (FMAX, ECF_CONST, fmax, binary)
+DEF_INTERNAL_OPTAB_FN (XORSIGN, ECF_CONST, xorsign, binary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_ADD_ROT90, ECF_CONST, cadd90, binary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_ADD_ROT270, ECF_CONST, cadd270, binary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_MUL, ECF_CONST, cmul, binary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_MUL_CONJ, ECF_CONST, cmul_conj, binary)
+DEF_INTERNAL_OPTAB_FN (VEC_ADDSUB, ECF_CONST, vec_addsub, binary)
+DEF_INTERNAL_OPTAB_FN (VEC_FMADDSUB, ECF_CONST, vec_fmaddsub, ternary)
+DEF_INTERNAL_OPTAB_FN (VEC_FMSUBADD, ECF_CONST, vec_fmsubadd, ternary)
+
+/* FP scales. */
+DEF_INTERNAL_FLT_FN (LDEXP, ECF_CONST, ldexp, binary)
+
+/* Ternary math functions. */
+DEF_INTERNAL_FLT_FLOATN_FN (FMA, ECF_CONST, fma, ternary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_FMA, ECF_CONST, cmla, ternary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_FMA_CONJ, ECF_CONST, cmla_conj, ternary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_FMS, ECF_CONST, cmls, ternary)
+DEF_INTERNAL_OPTAB_FN (COMPLEX_FMS_CONJ, ECF_CONST, cmls_conj, ternary)
+
+/* Unary integer ops. */
+DEF_INTERNAL_INT_FN (CLRSB, ECF_CONST | ECF_NOTHROW, clrsb, unary)
+DEF_INTERNAL_INT_FN (CLZ, ECF_CONST | ECF_NOTHROW, clz, unary)
+DEF_INTERNAL_INT_FN (CTZ, ECF_CONST | ECF_NOTHROW, ctz, unary)
+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_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)
+DEF_INTERNAL_FN (GOMP_SIMT_EXIT, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_VF, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_LAST_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_ORDERED_PRED, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_VOTE_ANY, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_XCHG_BFLY, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMT_XCHG_IDX, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_START, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (GOMP_SIMD_ORDERED_END, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (LOOP_DIST_ALIAS, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, ". R . ")
+DEF_INTERNAL_FN (UBSAN_BOUNDS, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_VPTR, ECF_LEAF | ECF_NOTHROW, ". R R . . ")
+DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (UBSAN_PTR, ECF_LEAF | ECF_NOTHROW, ". R . ")
+DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
+DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (HWASAN_ALLOCA_UNPOISON, ECF_LEAF | ECF_NOTHROW, ". R ")
+DEF_INTERNAL_FN (HWASAN_CHOOSE_TAG, ECF_LEAF | ECF_NOTHROW, ". ")
+DEF_INTERNAL_FN (HWASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW,
+ ". . R . . ")
+DEF_INTERNAL_FN (HWASAN_MARK, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (HWASAN_SET_TAG,
+ ECF_TM_PURE | ECF_PURE | ECF_LEAF | ECF_NOTHROW, ". R R ")
+DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW,
+ ". . R . . ")
+DEF_INTERNAL_FN (ASAN_MARK, ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (ASAN_POISON, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
+DEF_INTERNAL_FN (ASAN_POISON_USE, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
+DEF_INTERNAL_FN (ADD_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (SUB_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (MUL_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (TSAN_FUNC_EXIT, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
+DEF_INTERNAL_FN (VEC_CONVERT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (RAWMEMCHR, ECF_PURE | ECF_LEAF | ECF_NOTHROW, NULL)
+
+/* An unduplicable, uncombinable function. Generally used to preserve
+ a CFG property in the face of jump threading, tail merging or
+ other such optimizations. The first argument distinguishes
+ between uses. See internal-fn.h for usage. */
+DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (PHI, 0, NULL)
+
+/* A function to represent an artifical initialization to an uninitialized
+ automatic variable. */
+DEF_INTERNAL_FN (DEFERRED_INIT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
+/* DIM_SIZE and DIM_POS return the size of a particular compute
+ dimension and the executing thread's position within that
+ dimension. DIM_POS is pure (and not const) so that it isn't
+ thought to clobber memory and can be gcse'd within a single
+ parallel region, but not across FORK/JOIN boundaries. They take a
+ single INTEGER_CST argument. This might be overly conservative. */
+DEF_INTERNAL_FN (GOACC_DIM_SIZE, ECF_CONST | ECF_NOTHROW | ECF_LEAF, NULL)
+DEF_INTERNAL_FN (GOACC_DIM_POS, ECF_PURE | ECF_NOTHROW | ECF_LEAF, NULL)
+
+/* OpenACC looping abstraction. See internal-fn.h for usage. */
+DEF_INTERNAL_FN (GOACC_LOOP, ECF_PURE | ECF_NOTHROW, NULL)
+
+/* OpenACC reduction abstraction. See internal-fn.h for usage. */
+DEF_INTERNAL_FN (GOACC_REDUCTION, ECF_NOTHROW | ECF_LEAF, NULL)
+
+/* Openacc tile abstraction. Describes the spans of the element loop.
+ GOACC_TILE (num-loops, loop-no, tile-arg, tile-mask, element-mask). */
+DEF_INTERNAL_FN (GOACC_TILE, ECF_NOTHROW | ECF_LEAF, NULL)
+
+/* Set errno to EDOM, if GCC knows how to do that directly for the
+ current target. */
+DEF_INTERNAL_FN (SET_EDOM, ECF_LEAF | ECF_NOTHROW, NULL)
+
+/* Atomic functions. These don't have ECF_NOTHROW because for
+ -fnon-call-exceptions they can throw, otherwise we set
+ gimple_call_nothrow_p on it. */
+DEF_INTERNAL_FN (ATOMIC_BIT_TEST_AND_SET, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_BIT_TEST_AND_COMPLEMENT, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_BIT_TEST_AND_RESET, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_COMPARE_EXCHANGE, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_ADD_FETCH_CMP_0, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_SUB_FETCH_CMP_0, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_AND_FETCH_CMP_0, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_OR_FETCH_CMP_0, ECF_LEAF, NULL)
+DEF_INTERNAL_FN (ATOMIC_XOR_FETCH_CMP_0, ECF_LEAF, NULL)
+
+/* To implement [[fallthrough]]. */
+DEF_INTERNAL_FN (FALLTHROUGH, ECF_LEAF | ECF_NOTHROW, NULL)
+
+/* To implement __builtin_launder. */
+DEF_INTERNAL_FN (LAUNDER, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
+
+/* Divmod function. */
+DEF_INTERNAL_FN (DIVMOD, ECF_CONST | ECF_LEAF, NULL)
+
+/* For coroutines. */
+DEF_INTERNAL_FN (CO_ACTOR, ECF_NOTHROW | ECF_LEAF, NULL)
+DEF_INTERNAL_FN (CO_YIELD, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (CO_SUSPN, ECF_NOTHROW, NULL)
+DEF_INTERNAL_FN (CO_FRAME, ECF_PURE | ECF_NOTHROW | ECF_LEAF, NULL)
+
+/* A NOP function with arbitrary arguments and return value. */
+DEF_INTERNAL_FN (NOP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
+/* Temporary vehicle for __builtin_shufflevector. */
+DEF_INTERNAL_FN (SHUFFLEVECTOR, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
+/* <=> optimization. */
+DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
+
+#undef DEF_INTERNAL_INT_FN
+#undef DEF_INTERNAL_FLT_FN
+#undef DEF_INTERNAL_FLT_FLOATN_FN
+#undef DEF_INTERNAL_SIGNED_OPTAB_FN
+#undef DEF_INTERNAL_OPTAB_FN
+#undef DEF_INTERNAL_FN
diff --git a/support/cpp/gcc/internal-fn.h b/support/cpp/gcc/internal-fn.h
new file mode 100644
index 000000000..c930f6cfa
--- /dev/null
+++ b/support/cpp/gcc/internal-fn.h
@@ -0,0 +1,257 @@
+/* Internal functions.
+ 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/>. */
+
+#ifndef GCC_INTERNAL_FN_H
+#define GCC_INTERNAL_FN_H
+
+/* INTEGER_CST values for IFN_UNIQUE function arg-0.
+
+ UNSPEC: Undifferentiated UNIQUE.
+
+ FORK and JOIN mark the points at which OpenACC partitioned
+ execution is entered or exited.
+ DEP_VAR = UNIQUE ({FORK,JOIN}, DEP_VAR, AXIS)
+
+ HEAD_MARK and TAIL_MARK are used to demark the sequence entering
+ or leaving partitioned execution.
+ DEP_VAR = UNIQUE ({HEAD,TAIL}_MARK, REMAINING_MARKS, ...PRIMARY_FLAGS)
+
+ The PRIMARY_FLAGS only occur on the first HEAD_MARK of a sequence.
+
+ PRIVATE captures variables to be made private at the surrounding parallelism
+ level. */
+#define IFN_UNIQUE_CODES \
+ DEF(UNSPEC), \
+ DEF(OACC_FORK), DEF(OACC_JOIN), \
+ DEF(OACC_HEAD_MARK), DEF(OACC_TAIL_MARK), \
+ DEF(OACC_PRIVATE)
+
+enum ifn_unique_kind {
+#define DEF(X) IFN_UNIQUE_##X
+ IFN_UNIQUE_CODES
+#undef DEF
+};
+
+/* INTEGER_CST values for IFN_GOACC_LOOP arg-0. Allows the precise
+ stepping of the compute geometry over the loop iterations to be
+ deferred until it is known which compiler is generating the code.
+ The action is encoded in a constant first argument.
+
+ CHUNK_MAX = LOOP (CODE_CHUNKS, DIR, RANGE, STEP, CHUNK_SIZE, MASK)
+ STEP = LOOP (CODE_STEP, DIR, RANGE, STEP, CHUNK_SIZE, MASK)
+ OFFSET = LOOP (CODE_OFFSET, DIR, RANGE, STEP, CHUNK_SIZE, MASK, CHUNK_NO)
+ BOUND = LOOP (CODE_BOUND, DIR, RANGE, STEP, CHUNK_SIZE, MASK, OFFSET)
+
+ DIR - +1 for up loop, -1 for down loop
+ RANGE - Range of loop (END - BASE)
+ STEP - iteration step size
+ CHUNKING - size of chunking, (constant zero for no chunking)
+ CHUNK_NO - chunk number
+ MASK - partitioning mask. */
+
+#define IFN_GOACC_LOOP_CODES \
+ DEF(CHUNKS), DEF(STEP), DEF(OFFSET), DEF(BOUND)
+enum ifn_goacc_loop_kind {
+#define DEF(X) IFN_GOACC_LOOP_##X
+ IFN_GOACC_LOOP_CODES
+#undef DEF
+};
+
+/* The GOACC_REDUCTION function defines a generic interface to support
+ gang, worker and vector reductions. All calls are of the following
+ form:
+
+ V = REDUCTION (CODE, REF_TO_RES, LOCAL_VAR, LEVEL, OP, OFFSET)
+
+ REF_TO_RES - is a reference to the original reduction varl, may be NULL
+ LOCAL_VAR is the intermediate reduction variable
+ LEVEL corresponds to the GOMP_DIM of the reduction
+ OP is the tree code of the reduction operation
+ OFFSET may be used as an offset into a reduction array for the
+ reductions occuring at this level.
+ In general the return value is LOCAL_VAR, which creates a data
+ dependency between calls operating on the same reduction. */
+
+#define IFN_GOACC_REDUCTION_CODES \
+ DEF(SETUP), DEF(INIT), DEF(FINI), DEF(TEARDOWN)
+enum ifn_goacc_reduction_kind {
+#define DEF(X) IFN_GOACC_REDUCTION_##X
+ IFN_GOACC_REDUCTION_CODES
+#undef DEF
+};
+
+/* Initialize internal function tables. */
+
+extern void init_internal_fns ();
+
+/* Return the name of internal function FN. The name is only meaningful
+ for dumps; it has no linkage. */
+
+extern const char *const internal_fn_name_array[];
+
+static inline const char *
+internal_fn_name (enum internal_fn fn)
+{
+ return internal_fn_name_array[(int) fn];
+}
+
+extern internal_fn lookup_internal_fn (const char *);
+
+/* Return the ECF_* flags for function FN. */
+
+extern const int internal_fn_flags_array[];
+
+static inline int
+internal_fn_flags (enum internal_fn fn)
+{
+ return internal_fn_flags_array[(int) fn];
+}
+
+/* Return fnspec for function FN. */
+
+extern GTY(()) const_tree internal_fn_fnspec_array[IFN_LAST + 1];
+
+static inline const_tree
+internal_fn_fnspec (enum internal_fn fn)
+{
+ return internal_fn_fnspec_array[(int) fn];
+}
+
+/* Describes an internal function that maps directly to an optab. */
+struct direct_internal_fn_info
+{
+ /* optabs can be parameterized by one or two modes. These fields describe
+ how to select those modes from the types of the return value and
+ arguments. A value of -1 says that the mode is determined by the
+ return type while a value N >= 0 says that the mode is determined by
+ the type of argument N. A value of -2 says that this internal
+ function isn't directly mapped to an optab. */
+ signed int type0 : 8;
+ signed int type1 : 8;
+ /* True if the function is pointwise, so that it can be vectorized by
+ converting the return type and all argument types to vectors of the
+ same number of elements. E.g. we can vectorize an IFN_SQRT on
+ floats as an IFN_SQRT on vectors of N floats.
+
+ This only needs 1 bit, but occupies the full 16 to ensure a nice
+ layout. */
+ unsigned int vectorizable : 16;
+};
+
+extern const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1];
+
+/* Return true if FN is mapped directly to an optab. */
+
+inline bool
+direct_internal_fn_p (internal_fn fn)
+{
+ return direct_internal_fn_array[fn].type0 >= -1;
+}
+
+/* Return true if FN is a direct internal function that can be vectorized by
+ converting the return type and all argument types to vectors of the same
+ number of elements. E.g. we can vectorize an IFN_SQRT on floats as an
+ IFN_SQRT on vectors of N floats. */
+
+inline bool
+vectorizable_internal_fn_p (internal_fn fn)
+{
+ return direct_internal_fn_array[fn].vectorizable;
+}
+
+/* Return optab information about internal function FN. Only meaningful
+ if direct_internal_fn_p (FN). */
+
+inline const direct_internal_fn_info &
+direct_internal_fn (internal_fn fn)
+{
+ gcc_checking_assert (direct_internal_fn_p (fn));
+ return direct_internal_fn_array[fn];
+}
+
+extern tree_pair direct_internal_fn_types (internal_fn, tree, tree *);
+extern tree_pair direct_internal_fn_types (internal_fn, gcall *);
+extern bool direct_internal_fn_supported_p (internal_fn, tree_pair,
+ optimization_type);
+extern bool direct_internal_fn_supported_p (internal_fn, tree,
+ optimization_type);
+extern bool direct_internal_fn_supported_p (gcall *, optimization_type);
+
+/* Return true if FN is supported for types TYPE0 and TYPE1 when the
+ optimization type is OPT_TYPE. The types are those associated with
+ the "type0" and "type1" fields of FN's direct_internal_fn_info
+ structure. */
+
+inline bool
+direct_internal_fn_supported_p (internal_fn fn, tree type0, tree type1,
+ optimization_type opt_type)
+{
+ return direct_internal_fn_supported_p (fn, tree_pair (type0, type1),
+ opt_type);
+}
+
+extern bool commutative_binary_fn_p (internal_fn);
+extern bool commutative_ternary_fn_p (internal_fn);
+extern int first_commutative_argument (internal_fn);
+extern bool associative_binary_fn_p (internal_fn);
+
+extern bool set_edom_supported_p (void);
+
+extern internal_fn get_conditional_internal_fn (tree_code);
+extern internal_fn get_conditional_internal_fn (internal_fn);
+extern tree_code conditional_internal_fn_code (internal_fn);
+extern internal_fn get_unconditional_internal_fn (internal_fn);
+extern bool can_interpret_as_conditional_op_p (gimple *, tree *,
+ tree_code *, tree (&)[3],
+ tree *);
+
+extern bool internal_load_fn_p (internal_fn);
+extern bool internal_store_fn_p (internal_fn);
+extern bool internal_gather_scatter_fn_p (internal_fn);
+extern int internal_fn_mask_index (internal_fn);
+extern int internal_fn_stored_value_index (internal_fn);
+extern bool internal_gather_scatter_fn_supported_p (internal_fn, tree,
+ tree, tree, int);
+// sdcpp extern bool internal_check_ptrs_fn_supported_p (internal_fn, tree,
+// sdcpp poly_uint64, unsigned int);
+#define VECT_PARTIAL_BIAS_UNSUPPORTED 127
+
+extern signed char internal_len_load_store_bias (internal_fn ifn,
+ machine_mode);
+
+extern void expand_addsub_overflow (location_t, tree_code, tree, tree, tree,
+ bool, bool, bool, bool, tree *);
+extern void expand_internal_call (gcall *);
+extern void expand_internal_call (internal_fn, gcall *);
+extern void expand_PHI (internal_fn, gcall *);
+extern void expand_SHUFFLEVECTOR (internal_fn, gcall *);
+extern void expand_SPACESHIP (internal_fn, gcall *);
+
+extern bool vectorized_internal_fn_supported_p (internal_fn, tree);
+
+enum {
+ ATOMIC_OP_FETCH_CMP_0_EQ = 0,
+ ATOMIC_OP_FETCH_CMP_0_NE = 1,
+ ATOMIC_OP_FETCH_CMP_0_LT = 2,
+ ATOMIC_OP_FETCH_CMP_0_LE = 3,
+ ATOMIC_OP_FETCH_CMP_0_GT = 4,
+ ATOMIC_OP_FETCH_CMP_0_GE = 5
+};
+
+#endif
diff --git a/support/cpp/gcc/intl.cc b/support/cpp/gcc/intl.cc
new file mode 100644
index 000000000..d83e35113
--- /dev/null
+++ b/support/cpp/gcc/intl.cc
@@ -0,0 +1,150 @@
+/* Message translation utilities.
+ Copyright (C) 2001-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 "intl.h"
+
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#endif
+
+/* Opening quotation mark for diagnostics. */
+const char *open_quote = "'";
+
+/* Closing quotation mark for diagnostics. */
+const char *close_quote = "'";
+
+/* The name of the locale encoding. */
+const char *locale_encoding = NULL;
+
+/* Whether the locale is using UTF-8. */
+bool locale_utf8 = false;
+
+#ifdef ENABLE_NLS
+
+/* Initialize the translation library for GCC. This performs the
+ appropriate sequence of calls - setlocale, bindtextdomain,
+ textdomain. LC_CTYPE determines the character set used by the
+ terminal, so it has be set to output messages correctly. */
+
+void
+gcc_init_libintl (void)
+{
+#ifdef HAVE_LC_MESSAGES
+ setlocale (LC_CTYPE, "");
+ setlocale (LC_MESSAGES, "");
+#else
+ setlocale (LC_ALL, "");
+#endif
+
+ (void) bindtextdomain ("gcc", LOCALEDIR);
+ (void) textdomain ("gcc");
+
+ /* Opening quotation mark. */
+ open_quote = _("`");
+
+ /* Closing quotation mark. */
+ close_quote = _("'");
+
+#if defined HAVE_LANGINFO_CODESET
+ locale_encoding = nl_langinfo (CODESET);
+ if (locale_encoding != NULL
+ && (!strcasecmp (locale_encoding, "utf-8")
+ || !strcasecmp (locale_encoding, "utf8")))
+ locale_utf8 = true;
+#endif
+
+ if (!strcmp (open_quote, "`") && !strcmp (close_quote, "'"))
+ {
+ /* Untranslated quotes that it may be possible to replace with
+ U+2018 and U+2019; but otherwise use "'" instead of "`" as
+ opening quote. */
+ open_quote = "'";
+#if defined HAVE_LANGINFO_CODESET
+ if (locale_utf8)
+ {
+ open_quote = "\xe2\x80\x98";
+ close_quote = "\xe2\x80\x99";
+ }
+#endif
+ }
+}
+
+#if defined HAVE_WCHAR_H && defined HAVE_WORKING_MBSTOWCS && defined HAVE_WCSWIDTH
+#include <wchar.h>
+
+/* Returns the width in columns of MSGSTR, which came from gettext.
+ This is for indenting subsequent output. */
+
+size_t
+gcc_gettext_width (const char *msgstr)
+{
+ size_t nwcs = mbstowcs (0, msgstr, 0);
+ wchar_t *wmsgstr = XALLOCAVEC (wchar_t, nwcs + 1);
+
+ mbstowcs (wmsgstr, msgstr, nwcs + 1);
+ return wcswidth (wmsgstr, nwcs);
+}
+
+#else /* no wcswidth */
+
+/* We don't have any way of knowing how wide the string is. Guess
+ the length of the string. */
+
+size_t
+gcc_gettext_width (const char *msgstr)
+{
+ return strlen (msgstr);
+}
+
+#endif
+
+#endif /* ENABLE_NLS */
+
+#ifndef ENABLE_NLS
+
+const char *
+fake_ngettext (const char *singular, const char *plural, unsigned long n)
+{
+ if (n == 1UL)
+ return singular;
+
+ return plural;
+}
+
+#endif
+
+/* Return the indent for successive lines, using the width of
+ the STR. STR must have been translated already. The string
+ must be freed by the caller. */
+
+char *
+get_spaces (const char *str)
+{
+ size_t len = gcc_gettext_width (str);
+ char *spaces = XNEWVEC (char, len + 1);
+ memset (spaces, ' ', len);
+ spaces[len] = '\0';
+ return spaces;
+}
+
+
+
diff --git a/support/cpp/gcc/intl.h b/support/cpp/gcc/intl.h
new file mode 100644
index 000000000..a359a037e
--- /dev/null
+++ b/support/cpp/gcc/intl.h
@@ -0,0 +1,73 @@
+/* intl.h - internationalization
+ Copyright (C) 1998-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/>. */
+
+#ifndef GCC_INTL_H
+#define GCC_INTL_H
+
+#ifdef HAVE_LOCALE_H
+# include <locale.h>
+#endif
+
+#ifndef HAVE_SETLOCALE
+# define setlocale(category, locale) (locale)
+#endif
+
+#ifdef ENABLE_NLS
+#include <libintl.h>
+extern void gcc_init_libintl (void);
+extern size_t gcc_gettext_width (const char *);
+#else
+/* Stubs. */
+# undef textdomain
+# define textdomain(domain) (domain)
+# undef bindtextdomain
+# define bindtextdomain(domain, directory) (domain)
+# undef gettext
+# define gettext(msgid) (msgid)
+# define ngettext(singular,plural,n) fake_ngettext (singular, plural, n)
+# define gcc_init_libintl() /* nothing */
+# define gcc_gettext_width(s) strlen (s)
+
+extern const char *fake_ngettext (const char *singular, const char *plural,
+ unsigned long int n);
+
+#endif
+
+/* Used to immediately translate the argument. */
+#ifndef _
+# define _(msgid) gettext (msgid)
+#endif
+
+/* Used to mark strings that will be translated later. */
+#ifndef N_
+# define N_(msgid) msgid
+#endif
+
+/* Like N_, but for GCC diagnostic format strings. See ABOUT-GCC-NLS for
+ details. */
+#ifndef G_
+# define G_(gmsgid) gmsgid
+#endif
+
+extern char *get_spaces (const char *);
+
+extern const char *open_quote;
+extern const char *close_quote;
+extern const char *locale_encoding;
+extern bool locale_utf8;
+
+#endif /* intl.h */
diff --git a/support/cpp/gcc/ira.h b/support/cpp/gcc/ira.h
new file mode 100644
index 000000000..bdeae8c0f
--- /dev/null
+++ b/support/cpp/gcc/ira.h
@@ -0,0 +1,242 @@
+/* Communication between the Integrated Register Allocator (IRA) and
+ the rest of the compiler.
+ Copyright (C) 2006-2022 Free Software Foundation, Inc.
+ Contributed by Vladimir Makarov <vmakarov@redhat.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.
+
+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/>. */
+
+#if 0 // sdcpp ndef GCC_IRA_H
+#define GCC_IRA_H
+
+#include "emit-rtl.h"
+
+/* True when we use LRA instead of reload pass for the current
+ function. */
+extern bool ira_use_lra_p;
+
+/* True if we have allocno conflicts. It is false for non-optimized
+ mode or when the conflict table is too big. */
+extern bool ira_conflicts_p;
+
+struct target_ira
+{
+ /* Map: hard register number -> allocno class it belongs to. If the
+ corresponding class is NO_REGS, the hard register is not available
+ for allocation. */
+ enum reg_class x_ira_hard_regno_allocno_class[FIRST_PSEUDO_REGISTER];
+
+ /* Number of allocno classes. Allocno classes are register classes
+ which can be used for allocations of allocnos. */
+ int x_ira_allocno_classes_num;
+
+ /* The array containing allocno classes. Only first
+ IRA_ALLOCNO_CLASSES_NUM elements are used for this. */
+ enum reg_class x_ira_allocno_classes[N_REG_CLASSES];
+
+ /* Map of all register classes to corresponding allocno classes
+ containing the given class. If given class is not a subset of an
+ allocno class, we translate it into the cheapest allocno class. */
+ enum reg_class x_ira_allocno_class_translate[N_REG_CLASSES];
+
+ /* Number of pressure classes. Pressure classes are register
+ classes for which we calculate register pressure. */
+ int x_ira_pressure_classes_num;
+
+ /* The array containing pressure classes. Only first
+ IRA_PRESSURE_CLASSES_NUM elements are used for this. */
+ enum reg_class x_ira_pressure_classes[N_REG_CLASSES];
+
+ /* Map of all register classes to corresponding pressure classes
+ containing the given class. If given class is not a subset of an
+ pressure class, we translate it into the cheapest pressure
+ class. */
+ enum reg_class x_ira_pressure_class_translate[N_REG_CLASSES];
+
+ /* Biggest pressure register class containing stack registers.
+ NO_REGS if there are no stack registers. */
+ enum reg_class x_ira_stack_reg_pressure_class;
+
+ /* Maps: register class x machine mode -> maximal/minimal number of
+ hard registers of given class needed to store value of given
+ mode. */
+ unsigned char x_ira_reg_class_max_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
+ unsigned char x_ira_reg_class_min_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
+
+ /* Array analogous to target hook TARGET_MEMORY_MOVE_COST. */
+ short x_ira_memory_move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][2];
+
+ /* Array of number of hard registers of given class which are
+ available for the allocation. The order is defined by the
+ allocation order. */
+ short x_ira_class_hard_regs[N_REG_CLASSES][FIRST_PSEUDO_REGISTER];
+
+ /* The number of elements of the above array for given register
+ class. */
+ int x_ira_class_hard_regs_num[N_REG_CLASSES];
+
+ /* Register class subset relation: TRUE if the first class is a subset
+ of the second one considering only hard registers available for the
+ allocation. */
+ int x_ira_class_subset_p[N_REG_CLASSES][N_REG_CLASSES];
+
+ /* The biggest class inside of intersection of the two classes (that
+ is calculated taking only hard registers available for allocation
+ into account. If the both classes contain no hard registers
+ available for allocation, the value is calculated with taking all
+ hard-registers including fixed ones into account. */
+ enum reg_class x_ira_reg_class_subset[N_REG_CLASSES][N_REG_CLASSES];
+
+ /* True if the two classes (that is calculated taking only hard
+ registers available for allocation into account; are
+ intersected. */
+ bool x_ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES];
+
+ /* If class CL has a single allocatable register of mode M,
+ index [CL][M] gives the number of that register, otherwise it is -1. */
+ short x_ira_class_singleton[N_REG_CLASSES][MAX_MACHINE_MODE];
+
+ /* Function specific hard registers cannot be used for the register
+ allocation. */
+ HARD_REG_SET x_ira_no_alloc_regs;
+
+ /* Array whose values are hard regset of hard registers available for
+ the allocation of given register class whose targetm.hard_regno_mode_ok
+ values for given mode are false. */
+ HARD_REG_SET x_ira_prohibited_class_mode_regs[N_REG_CLASSES][NUM_MACHINE_MODES];
+
+ /* When an allocatable hard register in given mode can not be placed in given
+ register class, it is in the set of the following array element. It can
+ happen only when given mode requires more one hard register. */
+ HARD_REG_SET x_ira_exclude_class_mode_regs[N_REG_CLASSES][NUM_MACHINE_MODES];
+};
+
+extern struct target_ira default_target_ira;
+#if SWITCHABLE_TARGET
+extern struct target_ira *this_target_ira;
+#else
+#define this_target_ira (&default_target_ira)
+#endif
+
+#define ira_hard_regno_allocno_class \
+ (this_target_ira->x_ira_hard_regno_allocno_class)
+#define ira_allocno_classes_num \
+ (this_target_ira->x_ira_allocno_classes_num)
+#define ira_allocno_classes \
+ (this_target_ira->x_ira_allocno_classes)
+#define ira_allocno_class_translate \
+ (this_target_ira->x_ira_allocno_class_translate)
+#define ira_pressure_classes_num \
+ (this_target_ira->x_ira_pressure_classes_num)
+#define ira_pressure_classes \
+ (this_target_ira->x_ira_pressure_classes)
+#define ira_pressure_class_translate \
+ (this_target_ira->x_ira_pressure_class_translate)
+#define ira_stack_reg_pressure_class \
+ (this_target_ira->x_ira_stack_reg_pressure_class)
+#define ira_reg_class_max_nregs \
+ (this_target_ira->x_ira_reg_class_max_nregs)
+#define ira_reg_class_min_nregs \
+ (this_target_ira->x_ira_reg_class_min_nregs)
+#define ira_memory_move_cost \
+ (this_target_ira->x_ira_memory_move_cost)
+#define ira_class_hard_regs \
+ (this_target_ira->x_ira_class_hard_regs)
+#define ira_class_hard_regs_num \
+ (this_target_ira->x_ira_class_hard_regs_num)
+#define ira_class_subset_p \
+ (this_target_ira->x_ira_class_subset_p)
+#define ira_reg_class_subset \
+ (this_target_ira->x_ira_reg_class_subset)
+#define ira_reg_classes_intersect_p \
+ (this_target_ira->x_ira_reg_classes_intersect_p)
+#define ira_class_singleton \
+ (this_target_ira->x_ira_class_singleton)
+#define ira_no_alloc_regs \
+ (this_target_ira->x_ira_no_alloc_regs)
+#define ira_prohibited_class_mode_regs \
+ (this_target_ira->x_ira_prohibited_class_mode_regs)
+#define ira_exclude_class_mode_regs \
+ (this_target_ira->x_ira_exclude_class_mode_regs)
+
+/* Major structure describing equivalence info for a pseudo. */
+struct ira_reg_equiv_s
+{
+ /* True if we can use this equivalence. */
+ bool defined_p;
+ /* True if the usage of the equivalence is profitable. */
+ bool profitable_p;
+ /* Equiv. memory, constant, invariant, and initializing insns of
+ given pseudo-register or NULL_RTX. */
+ rtx memory;
+ rtx constant;
+ rtx invariant;
+ /* Always NULL_RTX if defined_p is false. */
+ rtx_insn_list *init_insns;
+};
+
+/* The length of the following array. */
+extern int ira_reg_equiv_len;
+
+/* Info about equiv. info for each register. */
+extern struct ira_reg_equiv_s *ira_reg_equiv;
+
+extern void ira_init_once (void);
+extern void ira_init (void);
+extern void ira_setup_eliminable_regset (void);
+extern rtx ira_eliminate_regs (rtx, machine_mode);
+extern void ira_set_pseudo_classes (bool, FILE *);
+extern void ira_expand_reg_equiv (void);
+extern void ira_update_equiv_info_by_shuffle_insn (int, int, rtx_insn *);
+
+extern void ira_sort_regnos_for_alter_reg (int *, int, machine_mode *);
+extern void ira_mark_allocation_change (int);
+extern void ira_mark_memory_move_deletion (int, int);
+extern bool ira_reassign_pseudos (int *, int, HARD_REG_SET, HARD_REG_SET *,
+ HARD_REG_SET *, bitmap);
+extern rtx ira_reuse_stack_slot (int, poly_uint64, poly_uint64);
+extern void ira_mark_new_stack_slot (rtx, int, poly_uint64);
+extern bool ira_better_spill_reload_regno_p (int *, int *, rtx, rtx, rtx_insn *);
+extern bool ira_bad_reload_regno (int, rtx, rtx);
+
+extern void ira_adjust_equiv_reg_cost (unsigned, int);
+
+extern bool ira_former_scratch_p (int regno);
+extern bool ira_former_scratch_operand_p (rtx_insn *insn, int nop);
+extern void ira_register_new_scratch_op (rtx_insn *insn, int nop, int icode);
+extern bool ira_remove_insn_scratches (rtx_insn *insn, bool all_p, FILE *dump_file,
+ rtx (*get_reg) (rtx original));
+extern void ira_restore_scratches (FILE *dump_file);
+extern void ira_nullify_asm_goto (rtx_insn *insn);
+
+/* ira-costs.cc */
+extern void ira_costs_cc_finalize (void);
+
+/* ira-lives.cc */
+extern rtx non_conflicting_reg_copy_p (rtx_insn *);
+
+/* Spilling static chain pseudo may result in generation of wrong
+ non-local goto code using frame-pointer to address saved stack
+ pointer value after restoring old frame pointer value. The
+ function returns TRUE if REGNO is such a static chain pseudo. */
+static inline bool
+non_spilled_static_chain_regno_p (int regno)
+{
+ return (cfun->static_chain_decl && crtl->has_nonlocal_goto
+ && REG_EXPR (regno_reg_rtx[regno]) == cfun->static_chain_decl);
+}
+
+#endif /* GCC_IRA_H */
diff --git a/support/cpp/gcc/is-a.h b/support/cpp/gcc/is-a.h
new file mode 100644
index 000000000..2012e7bab
--- /dev/null
+++ b/support/cpp/gcc/is-a.h
@@ -0,0 +1,284 @@
+/* Dynamic testing for abstract is-a relationships.
+ Copyright (C) 2012-2022 Free Software Foundation, Inc.
+ Contributed by Lawrence Crowl.
+
+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 header generic type query and conversion functions.
+
+
+USING THE GENERIC TYPE FACILITY
+
+
+The user functions are:
+
+bool is_a <TYPE> (pointer)
+
+ Tests whether the pointer actually points to a more derived TYPE.
+
+ Suppose you have a symtab_node *ptr, AKA symtab_node *ptr. You can test
+ whether it points to a 'derived' cgraph_node as follows.
+
+ if (is_a <cgraph_node *> (ptr))
+ ....
+
+
+TYPE as_a <TYPE> (pointer)
+
+ Converts pointer to a TYPE.
+
+ You can just assume that it is such a node.
+
+ do_something_with (as_a <cgraph_node *> *ptr);
+
+TYPE safe_as_a <TYPE> (pointer)
+
+ Like as_a <TYPE> (pointer), but where pointer could be NULL. This
+ adds a check against NULL where the regular is_a_helper hook for TYPE
+ assumes non-NULL.
+
+ do_something_with (safe_as_a <cgraph_node *> *ptr);
+
+TYPE dyn_cast <TYPE> (pointer)
+
+ Converts pointer to TYPE if and only if "is_a <TYPE> pointer". Otherwise,
+ returns NULL. This function is essentially a checked down cast.
+
+ This functions reduce compile time and increase type safety when treating a
+ generic item as a more specific item.
+
+ You can test and obtain a pointer to the 'derived' type in one indivisible
+ operation.
+
+ if (cgraph_node *cptr = dyn_cast <cgraph_node *> (ptr))
+ ....
+
+ As an example, the code change is from
+
+ if (symtab_function_p (node))
+ {
+ struct cgraph_node *cnode = cgraph (node);
+ ....
+ }
+
+ to
+
+ if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
+ {
+ ....
+ }
+
+ The necessary conditional test defines a variable that holds a known good
+ pointer to the specific item and avoids subsequent conversion calls and
+ the assertion checks that may come with them.
+
+ When, the property test is embedded within a larger condition, the
+ variable declaration gets pulled out of the condition. (This approach
+ leaves some room for using the variable inappropriately.)
+
+ if (symtab_variable_p (node) && varpool (node)->finalized)
+ varpool_analyze_node (varpool (node));
+
+ becomes
+
+ varpool_node *vnode = dyn_cast <varpool_node *> (node);
+ if (vnode && vnode->finalized)
+ varpool_analyze_node (vnode);
+
+ Note that we have converted two sets of assertions in the calls to varpool
+ into safe and efficient use of a variable.
+
+TYPE safe_dyn_cast <TYPE> (pointer)
+
+ Like dyn_cast <TYPE> (pointer), except that it accepts null pointers
+ and returns null results for them.
+
+
+If you use these functions and get a 'inline function not defined' or a
+'missing symbol' error message for 'is_a_helper<....>::test', it means that
+the connection between the types has not been made. See below.
+
+
+EXTENDING THE GENERIC TYPE FACILITY
+
+Method 1
+--------
+
+If DERIVED is derived from BASE, and if BASE contains enough information
+to determine whether an object is actually an instance of DERIVED,
+then you can make the above routines work for DERIVED by defining
+a specialization of is_a_helper such as:
+
+ template<>
+ struct is_a_helper<DERIVED *> : static_is_a_helper<DERIVED *>
+ {
+ static inline bool test (const BASE *p) { return ...; }
+ };
+
+This test function should return true if P is an instanced of DERIVED.
+This on its own is enough; the comments below for method 2 do not apply.
+
+Method 2
+--------
+
+Alternatively, if two types are connected in ways other than C++
+inheritance, each connection between them must be made by defining a
+specialization of the template member function 'test' of the template
+class 'is_a_helper'. For example,
+
+ template <>
+ template <>
+ inline bool
+ is_a_helper <cgraph_node *>::test (symtab_node *p)
+ {
+ return p->type == SYMTAB_FUNCTION;
+ }
+
+If a simple reinterpret_cast between the pointer types is incorrect, then you
+must also specialize the template member function 'cast'. Failure to do so
+when needed may result in a crash. For example,
+
+ template <>
+ template <>
+ inline bool
+ is_a_helper <cgraph_node *>::cast (symtab_node *p)
+ {
+ return &p->x_function;
+ }
+
+*/
+
+#ifndef GCC_IS_A_H
+#define GCC_IS_A_H
+
+/* A base class that specializations of is_a_helper can use if casting
+ U * to T is simply a reinterpret_cast. */
+
+template <typename T>
+struct reinterpret_is_a_helper
+{
+ template <typename U>
+ static inline T cast (U *p) { return reinterpret_cast <T> (p); }
+};
+
+/* A base class that specializations of is_a_helper can use if casting
+ U * to T is simply a static_cast. This is more type-safe than
+ reinterpret_is_a_helper. */
+
+template <typename T>
+struct static_is_a_helper
+{
+ template <typename U>
+ static inline T cast (U *p) { return static_cast <T> (p); }
+};
+
+/* A generic type conversion internal helper class. */
+
+template <typename T>
+struct is_a_helper : reinterpret_is_a_helper<T>
+{
+ template <typename U>
+ static inline bool test (U *p);
+};
+
+/* Reuse the definition of is_a_helper<T *> to implement
+ is_a_helper<const T *>. */
+
+template <typename T>
+struct is_a_helper<const T *>
+{
+ template <typename U>
+ static inline const T *cast (const U *p)
+ {
+ return is_a_helper<T *>::cast (const_cast <U *> (p));
+ }
+ template <typename U>
+ static inline bool test (const U *p)
+ {
+ return is_a_helper<T *>::test (p);
+ }
+};
+
+/* Note that we deliberately do not define the 'test' member template. Not
+ doing so will result in a build-time error for type relationships that have
+ not been defined, rather than a run-time error. See the discussion above
+ for when to define this member. */
+
+/* The public interface. */
+
+/* A generic test for a type relationship. See the discussion above for when
+ to use this function. The question answered is "Is type T a derived type of
+ type U?". */
+
+template <typename T, typename U>
+inline bool
+is_a (U *p)
+{
+ return is_a_helper<T>::test (p);
+}
+
+/* A generic conversion from a base type U to a derived type T. See the
+ discussion above for when to use this function. */
+
+template <typename T, typename U>
+inline T
+as_a (U *p)
+{
+ gcc_checking_assert (is_a <T> (p));
+ return is_a_helper <T>::cast (p);
+}
+
+/* Similar to as_a<>, but where the pointer can be NULL, even if
+ is_a_helper<T> doesn't check for NULL. */
+
+template <typename T, typename U>
+inline T
+safe_as_a (U *p)
+{
+ if (p)
+ {
+ gcc_checking_assert (is_a <T> (p));
+ return is_a_helper <T>::cast (p);
+ }
+ else
+ return NULL;
+}
+
+/* A generic checked conversion from a base type U to a derived type T. See
+ the discussion above for when to use this function. */
+
+template <typename T, typename U>
+inline T
+dyn_cast (U *p)
+{
+ if (is_a <T> (p))
+ return is_a_helper <T>::cast (p);
+ else
+ return static_cast <T> (0);
+}
+
+/* Similar to dyn_cast, except that the pointer may be null. */
+
+template <typename T, typename U>
+inline T
+safe_dyn_cast (U *p)
+{
+ return p ? dyn_cast <T> (p) : 0;
+}
+
+#endif /* GCC_IS_A_H */
diff --git a/support/cpp/gcc/iterator-utils.h b/support/cpp/gcc/iterator-utils.h
new file mode 100644
index 000000000..2da5556ec
--- /dev/null
+++ b/support/cpp/gcc/iterator-utils.h
@@ -0,0 +1,203 @@
+// Iterator-related utilities.
+// Copyright (C) 2002-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_ITERATOR_UTILS_H
+#define GCC_ITERATOR_UTILS_H 1
+
+// A half-open [begin, end) range of iterators.
+template<typename T>
+struct iterator_range
+{
+public:
+ using const_iterator = T;
+
+ iterator_range () = default;
+ iterator_range (const T &begin, const T &end)
+ : m_begin (begin), m_end (end) {}
+
+ T begin () const { return m_begin; }
+ T end () const { return m_end; }
+
+ explicit operator bool () const { return m_begin != m_end; }
+
+private:
+ T m_begin;
+ T m_end;
+};
+
+// Provide an iterator like BaseIT, except that it yields values of type T,
+// which is derived from the type that BaseIT normally yields.
+//
+// The class doesn't inherit from BaseIT for two reasons:
+// - using inheritance would stop the class working with plain pointers
+// - not using inheritance increases type-safety for writable iterators
+//
+// Constructing this class from a BaseIT involves an assertion that all
+// contents really do have type T. The constructor is therefore explicit.
+template<typename T, typename BaseIT>
+class derived_iterator
+{
+public:
+ using value_type = T;
+
+ derived_iterator () = default;
+
+ template<typename... Ts>
+ explicit derived_iterator (Ts... args)
+ : m_base (std::forward<Ts> (args)...) {}
+
+ derived_iterator &operator++ () { ++m_base; return *this; }
+ derived_iterator operator++ (int);
+
+ T operator* () const { return static_cast<T> (*m_base); }
+ T *operator-> () const { return static_cast<T *> (m_base.operator-> ()); }
+
+ bool operator== (const derived_iterator &other) const;
+ bool operator!= (const derived_iterator &other) const;
+
+protected:
+ BaseIT m_base;
+};
+
+template<typename T, typename BaseIT>
+inline derived_iterator<T, BaseIT>
+derived_iterator<T, BaseIT>::operator++ (int)
+{
+ derived_iterator ret = *this;
+ ++m_base;
+ return ret;
+}
+
+template<typename T, typename BaseIT>
+inline bool
+derived_iterator<T, BaseIT>::operator== (const derived_iterator &other) const
+{
+ return m_base == other.m_base;
+}
+
+template<typename T, typename BaseIT>
+inline bool
+derived_iterator<T, BaseIT>::operator!= (const derived_iterator &other) const
+{
+ return m_base != other.m_base;
+}
+
+// Provide a constant view of a BaseCT in which every value is known to
+// have type T, which is derived from the type that BaseCT normally presents.
+//
+// Constructing this class from a BaseCT involves an assertion that all
+// contents really do have type T. The constructor is therefore explicit.
+template<typename T, typename BaseCT>
+class const_derived_container : public BaseCT
+{
+ using base_const_iterator = typename BaseCT::const_iterator;
+
+public:
+ using value_type = T;
+ using const_iterator = derived_iterator<T, base_const_iterator>;
+
+ const_derived_container () = default;
+
+ template<typename... Ts>
+ explicit const_derived_container (Ts... args)
+ : BaseCT (std::forward<Ts> (args)...) {}
+
+ const_iterator begin () const { return const_iterator (BaseCT::begin ()); }
+ const_iterator end () const { return const_iterator (BaseCT::end ()); }
+
+ T front () const { return static_cast<T> (BaseCT::front ()); }
+ T back () const { return static_cast<T> (BaseCT::back ()); }
+ T operator[] (unsigned int i) const;
+};
+
+template<typename T, typename BaseCT>
+inline T
+const_derived_container<T, BaseCT>::operator[] (unsigned int i) const
+{
+ return static_cast<T> (BaseCT::operator[] (i));
+}
+
+// A base class for iterators whose contents consist of a StoredT and that
+// when dereferenced yield those StoredT contents as a T. Derived classes
+// should implement at least operator++ or operator--.
+template<typename T, typename StoredT = T>
+class wrapper_iterator
+{
+public:
+ using value_type = T;
+
+ wrapper_iterator () = default;
+
+ template<typename... Ts>
+ wrapper_iterator (Ts... args) : m_contents (std::forward<Ts> (args)...) {}
+
+ T operator* () const { return static_cast<T> (m_contents); }
+ bool operator== (const wrapper_iterator &) const;
+ bool operator!= (const wrapper_iterator &) const;
+
+protected:
+ StoredT m_contents;
+};
+
+template<typename T, typename StoredT>
+inline bool
+wrapper_iterator<T, StoredT>::operator== (const wrapper_iterator &other) const
+{
+ return m_contents == other.m_contents;
+}
+
+template<typename T, typename StoredT>
+inline bool
+wrapper_iterator<T, StoredT>::operator!= (const wrapper_iterator &other) const
+{
+ return m_contents != other.m_contents;
+}
+
+// A forward iterator for a linked list whose nodes are referenced using
+// type T. Given a node "T N", the next element is given by (N->*Next) ().
+template<typename T, T *(T::*Next) () const>
+class list_iterator : public wrapper_iterator<T *>
+{
+private:
+ using parent = wrapper_iterator<T *>;
+
+public:
+ using parent::parent;
+ list_iterator &operator++ ();
+ list_iterator operator++ (int);
+};
+
+template<typename T, T *(T::*Next) () const>
+inline list_iterator<T, Next> &
+list_iterator<T, Next>::operator++ ()
+{
+ this->m_contents = (this->m_contents->*Next) ();
+ return *this;
+}
+
+template<typename T, T *(T::*Next) () const>
+inline list_iterator<T, Next>
+list_iterator<T, Next>::operator++ (int)
+{
+ list_iterator ret = *this;
+ this->m_contents = (this->m_contents->*Next) ();
+ return ret;
+}
+
+#endif
diff --git a/support/cpp/gcc/json.cc b/support/cpp/gcc/json.cc
new file mode 100644
index 000000000..3bf9b61a6
--- /dev/null
+++ b/support/cpp/gcc/json.cc
@@ -0,0 +1,375 @@
+/* JSON trees
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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 "json.h"
+#include "pretty-print.h"
+#include "math.h"
+#include "selftest.h"
+
+using namespace json;
+
+/* class json::value. */
+
+/* Dump this json::value tree to OUTF.
+ No formatting is done. There are no guarantees about the order
+ in which the key/value pairs of json::objects are printed. */
+
+void
+value::dump (FILE *outf) const
+{
+ pretty_printer pp;
+ pp_buffer (&pp)->stream = outf;
+ print (&pp);
+ pp_flush (&pp);
+}
+
+/* class json::object, a subclass of json::value, representing
+ an unordered collection of key/value pairs. */
+
+/* json:object's dtor. */
+
+object::~object ()
+{
+ for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
+ {
+ free (const_cast <char *>((*it).first));
+ delete ((*it).second);
+ }
+}
+
+/* Implementation of json::value::print for json::object. */
+
+void
+object::print (pretty_printer *pp) const
+{
+ /* Note that the order is not guaranteed. */
+ pp_character (pp, '{');
+ for (map_t::iterator it = m_map.begin (); it != m_map.end (); ++it)
+ {
+ if (it != m_map.begin ())
+ pp_string (pp, ", ");
+ const char *key = const_cast <char *>((*it).first);
+ value *value = (*it).second;
+ pp_doublequote (pp);
+ pp_string (pp, key); // FIXME: escaping?
+ pp_doublequote (pp);
+ pp_string (pp, ": ");
+ value->print (pp);
+ }
+ pp_character (pp, '}');
+}
+
+/* Set the json::value * for KEY, taking ownership of V
+ (and taking a copy of KEY if necessary). */
+
+void
+object::set (const char *key, value *v)
+{
+ gcc_assert (key);
+ gcc_assert (v);
+
+ value **ptr = m_map.get (key);
+ if (ptr)
+ {
+ /* If the key is already present, delete the existing value
+ and overwrite it. */
+ delete *ptr;
+ *ptr = v;
+ }
+ else
+ /* If the key wasn't already present, take a copy of the key,
+ and store the value. */
+ m_map.put (xstrdup (key), v);
+}
+
+/* Get the json::value * for KEY.
+
+ The object retains ownership of the value. */
+
+value *
+object::get (const char *key) const
+{
+ gcc_assert (key);
+
+ value **ptr = const_cast <map_t &> (m_map).get (key);
+ if (ptr)
+ return *ptr;
+ else
+ return NULL;
+}
+
+/* class json::array, a subclass of json::value, representing
+ an ordered collection of values. */
+
+/* json::array's dtor. */
+
+array::~array ()
+{
+ unsigned i;
+ value *v;
+ FOR_EACH_VEC_ELT (m_elements, i, v)
+ delete v;
+}
+
+/* Implementation of json::value::print for json::array. */
+
+void
+array::print (pretty_printer *pp) const
+{
+ pp_character (pp, '[');
+ unsigned i;
+ value *v;
+ FOR_EACH_VEC_ELT (m_elements, i, v)
+ {
+ if (i)
+ pp_string (pp, ", ");
+ v->print (pp);
+ }
+ pp_character (pp, ']');
+}
+
+/* Append non-NULL value V to a json::array, taking ownership of V. */
+
+void
+array::append (value *v)
+{
+ gcc_assert (v);
+ m_elements.safe_push (v);
+}
+
+/* class json::float_number, a subclass of json::value, wrapping a double. */
+
+/* Implementation of json::value::print for json::float_number. */
+
+void
+float_number::print (pretty_printer *pp) const
+{
+ char tmp[1024];
+ snprintf (tmp, sizeof (tmp), "%g", m_value);
+ pp_string (pp, tmp);
+}
+
+/* class json::integer_number, a subclass of json::value, wrapping a long. */
+
+/* Implementation of json::value::print for json::integer_number. */
+
+void
+integer_number::print (pretty_printer *pp) const
+{
+ char tmp[1024];
+ snprintf (tmp, sizeof (tmp), "%ld", m_value);
+ pp_string (pp, tmp);
+}
+
+
+/* class json::string, a subclass of json::value. */
+
+/* json::string's ctor. */
+
+string::string (const char *utf8)
+{
+ gcc_assert (utf8);
+ m_utf8 = xstrdup (utf8);
+}
+
+/* Implementation of json::value::print for json::string. */
+
+void
+string::print (pretty_printer *pp) const
+{
+ pp_character (pp, '"');
+ for (const char *ptr = m_utf8; *ptr; ptr++)
+ {
+ char ch = *ptr;
+ switch (ch)
+ {
+ case '"':
+ pp_string (pp, "\\\"");
+ break;
+ case '\\':
+ pp_string (pp, "\\n");
+ break;
+ case '\b':
+ pp_string (pp, "\\b");
+ break;
+ case '\f':
+ pp_string (pp, "\\f");
+ break;
+ case '\n':
+ pp_string (pp, "\\n");
+ break;
+ case '\r':
+ pp_string (pp, "\\r");
+ break;
+ case '\t':
+ pp_string (pp, "\\t");
+ break;
+
+ default:
+ pp_character (pp, ch);
+ }
+ }
+ pp_character (pp, '"');
+}
+
+/* class json::literal, a subclass of json::value. */
+
+/* Implementation of json::value::print for json::literal. */
+
+void
+literal::print (pretty_printer *pp) const
+{
+ switch (m_kind)
+ {
+ case JSON_TRUE:
+ pp_string (pp, "true");
+ break;
+ case JSON_FALSE:
+ pp_string (pp, "false");
+ break;
+ case JSON_NULL:
+ pp_string (pp, "null");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests. */
+
+/* Verify that JV->print () prints EXPECTED_JSON. */
+
+static void
+assert_print_eq (const json::value &jv, const char *expected_json)
+{
+ pretty_printer pp;
+ jv.print (&pp);
+ ASSERT_STREQ (expected_json, pp_formatted_text (&pp));
+}
+
+/* Verify that object::get works as expected. */
+
+static void
+test_object_get ()
+{
+ object obj;
+ value *val = new json::string ("value");
+ obj.set ("foo", val);
+ ASSERT_EQ (obj.get ("foo"), val);
+ ASSERT_EQ (obj.get ("not-present"), NULL);
+}
+
+/* Verify that JSON objects are written correctly. We can't test more than
+ one key/value pair, as we don't impose a guaranteed ordering. */
+
+static void
+test_writing_objects ()
+{
+ object obj;
+ obj.set ("foo", new json::string ("bar"));
+ assert_print_eq (obj, "{\"foo\": \"bar\"}");
+}
+
+/* Verify that JSON arrays are written correctly. */
+
+static void
+test_writing_arrays ()
+{
+ array arr;
+ assert_print_eq (arr, "[]");
+
+ arr.append (new json::string ("foo"));
+ assert_print_eq (arr, "[\"foo\"]");
+
+ arr.append (new json::string ("bar"));
+ assert_print_eq (arr, "[\"foo\", \"bar\"]");
+}
+
+/* Verify that JSON numbers are written correctly. */
+
+static void
+test_writing_float_numbers ()
+{
+ assert_print_eq (float_number (0), "0");
+ assert_print_eq (float_number (42), "42");
+ assert_print_eq (float_number (-100), "-100");
+ assert_print_eq (float_number (123456789), "1.23457e+08");
+}
+
+static void
+test_writing_integer_numbers ()
+{
+ assert_print_eq (integer_number (0), "0");
+ assert_print_eq (integer_number (42), "42");
+ assert_print_eq (integer_number (-100), "-100");
+ assert_print_eq (integer_number (123456789), "123456789");
+ assert_print_eq (integer_number (-123456789), "-123456789");
+}
+
+/* Verify that JSON strings are written correctly. */
+
+static void
+test_writing_strings ()
+{
+ string foo ("foo");
+ assert_print_eq (foo, "\"foo\"");
+
+ string contains_quotes ("before \"quoted\" after");
+ assert_print_eq (contains_quotes, "\"before \\\"quoted\\\" after\"");
+}
+
+/* Verify that JSON literals are written correctly. */
+
+static void
+test_writing_literals ()
+{
+ assert_print_eq (literal (JSON_TRUE), "true");
+ assert_print_eq (literal (JSON_FALSE), "false");
+ assert_print_eq (literal (JSON_NULL), "null");
+
+ assert_print_eq (literal (true), "true");
+ assert_print_eq (literal (false), "false");
+}
+
+/* Run all of the selftests within this file. */
+
+void
+json_cc_tests ()
+{
+ test_object_get ();
+ test_writing_objects ();
+ test_writing_arrays ();
+ test_writing_float_numbers ();
+ test_writing_integer_numbers ();
+ test_writing_strings ();
+ test_writing_literals ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/support/cpp/gcc/json.h b/support/cpp/gcc/json.h
new file mode 100644
index 000000000..9ab6a5b3e
--- /dev/null
+++ b/support/cpp/gcc/json.h
@@ -0,0 +1,191 @@
+/* JSON trees
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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_JSON_H
+#define GCC_JSON_H
+
+/* Implementation of JSON, a lightweight data-interchange format.
+
+ See http://www.json.org/
+ and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
+ and https://tools.ietf.org/html/rfc7159
+
+ Supports creating a DOM-like tree of json::value *, and then dumping
+ json::value * to text. */
+
+namespace json
+{
+
+/* Forward decls of json::value and its subclasses (using indentation
+ to denote inheritance. */
+
+class value;
+ class object;
+ class array;
+ class float_number;
+ class integer_number;
+ class string;
+ class literal;
+
+/* An enum for discriminating the subclasses of json::value. */
+
+enum kind
+{
+ /* class json::object. */
+ JSON_OBJECT,
+
+ /* class json::array. */
+ JSON_ARRAY,
+
+ /* class json::integer_number. */
+ JSON_INTEGER,
+
+ /* class json::float_number. */
+ JSON_FLOAT,
+
+ /* class json::string. */
+ JSON_STRING,
+
+ /* class json::literal uses these three values to identify the
+ particular literal. */
+ JSON_TRUE,
+ JSON_FALSE,
+ JSON_NULL
+};
+
+/* Base class of JSON value. */
+
+class value
+{
+ public:
+ virtual ~value () {}
+ virtual enum kind get_kind () const = 0;
+ virtual void print (pretty_printer *pp) const = 0;
+
+ void dump (FILE *) const;
+};
+
+/* Subclass of value for objects: an unordered collection of
+ key/value pairs. */
+
+class object : public value
+{
+ public:
+ ~object ();
+
+ enum kind get_kind () const FINAL OVERRIDE { return JSON_OBJECT; }
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+ void set (const char *key, value *v);
+ value *get (const char *key) const;
+
+ private:
+ typedef hash_map <char *, value *,
+ simple_hashmap_traits<nofree_string_hash, value *> > map_t;
+ map_t m_map;
+};
+
+/* Subclass of value for arrays. */
+
+class array : public value
+{
+ public:
+ ~array ();
+
+ enum kind get_kind () const FINAL OVERRIDE { return JSON_ARRAY; }
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+ void append (value *v);
+
+ private:
+ auto_vec<value *> m_elements;
+};
+
+/* Subclass of value for floating-point numbers. */
+
+class float_number : public value
+{
+ public:
+ float_number (double value) : m_value (value) {}
+
+ enum kind get_kind () const FINAL OVERRIDE { return JSON_FLOAT; }
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+ double get () const { return m_value; }
+
+ private:
+ double m_value;
+};
+
+/* Subclass of value for integer-valued numbers. */
+
+class integer_number : public value
+{
+ public:
+ integer_number (long value) : m_value (value) {}
+
+ enum kind get_kind () const FINAL OVERRIDE { return JSON_INTEGER; }
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+ long get () const { return m_value; }
+
+ private:
+ long m_value;
+};
+
+
+/* Subclass of value for strings. */
+
+class string : public value
+{
+ public:
+ string (const char *utf8);
+ ~string () { free (m_utf8); }
+
+ enum kind get_kind () const FINAL OVERRIDE { return JSON_STRING; }
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+ const char *get_string () const { return m_utf8; }
+
+ private:
+ char *m_utf8;
+};
+
+/* Subclass of value for the three JSON literals "true", "false",
+ and "null". */
+
+class literal : public value
+{
+ public:
+ literal (enum kind kind) : m_kind (kind) {}
+
+ /* Construct literal for a boolean value. */
+ literal (bool value): m_kind (value ? JSON_TRUE : JSON_FALSE) {}
+
+ enum kind get_kind () const FINAL OVERRIDE { return m_kind; }
+ void print (pretty_printer *pp) const FINAL OVERRIDE;
+
+ private:
+ enum kind m_kind;
+};
+
+} // namespace json
+
+#endif /* GCC_JSON_H */
diff --git a/support/cpp/gcc/langhooks-def.h b/support/cpp/gcc/langhooks-def.h
new file mode 100644
index 000000000..92791c07b
--- /dev/null
+++ b/support/cpp/gcc/langhooks-def.h
@@ -0,0 +1,399 @@
+/* Default macros to initialize the lang_hooks data structure.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.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.
+
+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_LANG_HOOKS_DEF_H
+#define GCC_LANG_HOOKS_DEF_H
+
+#include "hooks.h"
+
+struct diagnostic_info;
+class substring_loc;
+
+/* Note to creators of new hooks:
+
+ The macros in this file should NOT be surrounded by a
+ #ifdef...#endif pair, since this file declares the defaults. Each
+ front end overrides any hooks it wishes to, in the file containing
+ its struct lang_hooks, AFTER including this file. */
+
+/* See langhooks.h for the definition and documentation of each hook. */
+
+extern void lhd_do_nothing (void);
+extern void lhd_do_nothing_t (tree);
+extern void lhd_do_nothing_f (struct function *);
+extern tree lhd_pass_through_t (tree);
+extern void lhd_register_dumps (gcc::dump_manager *);
+extern bool lhd_post_options (const char **);
+extern alias_set_type lhd_get_alias_set (tree);
+extern tree lhd_return_null_tree (tree);
+extern tree lhd_return_null_const_tree (const_tree);
+extern tree lhd_do_nothing_iii_return_null_tree (int, int, int);
+extern void lhd_print_tree_nothing (FILE *, tree, int);
+extern const char *lhd_decl_printable_name (tree, int);
+extern const char *lhd_dwarf_name (tree, int);
+extern int lhd_types_compatible_p (tree, tree);
+extern void lhd_print_error_function (diagnostic_context *,
+ const char *, struct diagnostic_info *);
+extern void lhd_set_decl_assembler_name (tree decl);
+extern void lhd_overwrite_decl_assembler_name (tree decl, tree name);
+extern bool lhd_warn_unused_global_decl (const_tree);
+extern tree lhd_simulate_enum_decl (location_t, const char *,
+ vec<string_int_pair> *);
+extern tree lhd_simulate_record_decl (location_t, const char *,
+ array_slice<const tree>);
+extern tree lhd_type_for_size (unsigned precision, int unsignedp);
+extern void lhd_incomplete_type_error (location_t, const_tree, const_tree);
+extern tree lhd_type_promotes_to (tree);
+extern void lhd_register_builtin_type (tree, const char *);
+extern bool lhd_decl_ok_for_sibcall (const_tree);
+extern size_t lhd_tree_size (enum tree_code);
+extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
+extern tree lhd_expr_to_decl (tree, bool *, bool *);
+extern tree lhd_builtin_function (tree);
+extern tree lhd_enum_underlying_base_type (const_tree);
+
+/* Declarations of default tree inlining hooks. */
+extern void lhd_initialize_diagnostics (diagnostic_context *);
+extern void lhd_init_options (unsigned int,
+ struct cl_decoded_option *);
+extern bool lhd_complain_wrong_lang_p (const struct cl_option *);
+extern bool lhd_handle_option (size_t, const char *, HOST_WIDE_INT, int,
+ location_t, const struct cl_option_handlers *);
+
+
+/* Declarations for tree gimplification hooks. */
+extern int lhd_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+#if 0 // sdcpp
+extern enum omp_clause_default_kind lhd_omp_predetermined_sharing (tree);
+extern enum omp_clause_defaultmap_kind lhd_omp_predetermined_mapping (tree);
+extern tree lhd_omp_assignment (tree, tree, tree);
+extern void lhd_omp_finish_clause (tree, gimple_seq *, bool);
+struct gimplify_omp_ctx;
+extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
+ tree);
+extern bool lhd_omp_mappable_type (tree);
+extern bool lhd_omp_scalar_p (tree, bool);
+extern tree *lhd_omp_get_decl_init (tree);
+extern void lhd_omp_finish_decl_inits ();
+#endif // sdcpp
+
+extern const char *lhd_get_substring_location (const substring_loc &,
+ location_t *out_loc);
+extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
+extern void lhd_finalize_early_debug (void);
+
+#define LANG_HOOKS_NAME "GNU unknown"
+#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
+#define LANG_HOOKS_INIT hook_bool_void_false
+#define LANG_HOOKS_FINISH lhd_do_nothing
+#define LANG_HOOKS_PARSE_FILE lhd_do_nothing
+#define LANG_HOOKS_OPTION_LANG_MASK hook_uint_void_0
+#define LANG_HOOKS_INIT_OPTIONS_STRUCT hook_void_gcc_optionsp
+#define LANG_HOOKS_INIT_OPTIONS sdcpp_init_options // lhd_init_options
+#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS lhd_initialize_diagnostics
+#define LANG_HOOKS_PREPROCESS_MAIN_FILE NULL
+#define LANG_HOOKS_PREPROCESS_OPTIONS NULL
+#define LANG_HOOKS_PREPROCESS_UNDEF NULL
+#define LANG_HOOKS_PREPROCESS_TOKEN NULL
+#define LANG_HOOKS_REGISTER_DUMPS lhd_register_dumps
+#define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lhd_complain_wrong_lang_p
+#define LANG_HOOKS_HANDLE_OPTION lhd_handle_option
+#define LANG_HOOKS_POST_OPTIONS lhd_post_options
+#define LANG_HOOKS_MISSING_NORETURN_OK_P hook_bool_tree_true
+#define LANG_HOOKS_GET_ALIAS_SET lhd_get_alias_set
+#define LANG_HOOKS_FINISH_INCOMPLETE_DECL lhd_do_nothing_t
+#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL lhd_do_nothing_t
+#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lhd_set_decl_assembler_name
+#define LANG_HOOKS_OVERWRITE_DECL_ASSEMBLER_NAME lhd_overwrite_decl_assembler_name
+#define LANG_HOOKS_PRINT_STATISTICS lhd_do_nothing
+#define LANG_HOOKS_PRINT_XNODE lhd_print_tree_nothing
+#define LANG_HOOKS_PRINT_DECL lhd_print_tree_nothing
+#define LANG_HOOKS_PRINT_TYPE lhd_print_tree_nothing
+#define LANG_HOOKS_PRINT_IDENTIFIER lhd_print_tree_nothing
+#define LANG_HOOKS_PRINT_ERROR_FUNCTION lhd_print_error_function
+#define LANG_HOOKS_DECL_PRINTABLE_NAME lhd_decl_printable_name
+#define LANG_HOOKS_DWARF_NAME lhd_dwarf_name
+#define LANG_HOOKS_FREE_LANG_DATA lhd_do_nothing_t
+#define LANG_HOOKS_TREE_SIZE lhd_tree_size
+#define LANG_HOOKS_TYPES_COMPATIBLE_P lhd_types_compatible_p
+#define LANG_HOOKS_BUILTIN_FUNCTION lhd_builtin_function
+#define LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE LANG_HOOKS_BUILTIN_FUNCTION
+#define LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL LANG_HOOKS_BUILTIN_FUNCTION
+#define LANG_HOOKS_EXPR_TO_DECL lhd_expr_to_decl
+#define LANG_HOOKS_TO_TARGET_CHARSET lhd_to_target_charset
+#define LANG_HOOKS_INIT_TS lhd_do_nothing
+#define LANG_HOOKS_EH_PERSONALITY NULL // sdcpp lhd_gcc_personality
+#define LANG_HOOKS_EH_RUNTIME_TYPE lhd_pass_through_t
+#define LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS NULL
+#define LANG_HOOKS_BLOCK_MAY_FALLTHRU hook_bool_const_tree_true
+#define LANG_HOOKS_EH_USE_CXA_END_CLEANUP false
+#define LANG_HOOKS_DEEP_UNSHARING false
+#define LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS false
+#define LANG_HOOKS_EMITS_BEGIN_STMT false
+#define LANG_HOOKS_RUN_LANG_SELFTESTS lhd_do_nothing
+#define LANG_HOOKS_GET_SUBSTRING_LOCATION lhd_get_substring_location
+#define LANG_HOOKS_FINALIZE_EARLY_DEBUG lhd_finalize_early_debug
+
+/* Attribute hooks. */
+#define LANG_HOOKS_ATTRIBUTE_TABLE NULL
+#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE NULL
+#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE NULL
+
+/* Tree inlining hooks. */
+#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
+ hook_bool_tree_tree_false
+
+#define LANG_HOOKS_TREE_INLINING_INITIALIZER { \
+ LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \
+}
+
+/* Hooks for tree gimplification. */
+#define LANG_HOOKS_GIMPLIFY_EXPR lhd_gimplify_expr
+
+/* Tree dump hooks. */
+extern bool lhd_tree_dump_dump_tree (void *, tree);
+extern int lhd_tree_dump_type_quals (const_tree);
+extern tree lhd_make_node (enum tree_code);
+
+#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN lhd_tree_dump_dump_tree
+#define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN lhd_tree_dump_type_quals
+
+#define LANG_HOOKS_TREE_DUMP_INITIALIZER { \
+ LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN, \
+ LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN \
+}
+
+/* Types hooks. There are no reasonable defaults for most of them,
+ so we create a compile-time error instead. */
+extern tree lhd_unit_size_without_reusable_padding (tree);
+
+#define LANG_HOOKS_MAKE_TYPE lhd_make_node
+#define LANG_HOOKS_SIMULATE_ENUM_DECL lhd_simulate_enum_decl
+#define LANG_HOOKS_SIMULATE_RECORD_DECL lhd_simulate_record_decl
+#define LANG_HOOKS_CLASSIFY_RECORD NULL
+#define LANG_HOOKS_TYPE_FOR_SIZE lhd_type_for_size
+#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
+#define LANG_HOOKS_GENERIC_TYPE_P hook_bool_const_tree_false
+#define LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS hook_tree_const_tree_null
+#define LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS hook_tree_const_tree_null
+#define LANG_HOOKS_FUNCTION_PARAMETER_PACK_P hook_bool_const_tree_false
+#define LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS hook_tree_const_tree_null
+#define LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P hook_bool_const_tree_false
+#define LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P \
+ hook_bool_tree_tree_false
+#define LANG_HOOKS_GET_GENERIC_FUNCTION_DECL hook_tree_const_tree_null
+#define LANG_HOOKS_TYPE_PROMOTES_TO lhd_type_promotes_to
+#define LANG_HOOKS_REGISTER_BUILTIN_TYPE lhd_register_builtin_type
+#define LANG_HOOKS_TYPE_MAX_SIZE lhd_return_null_const_tree
+#define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \
+ NULL // sdcpp lhd_omp_firstprivatize_type_sizes
+#define LANG_HOOKS_OMP_MAPPABLE_TYPE NULL // sdcpp lhd_omp_mappable_type
+#define LANG_HOOKS_TYPE_HASH_EQ NULL
+#define LANG_HOOKS_COPY_LANG_QUALIFIERS NULL
+#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL
+#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
+#define LANG_HOOKS_GET_TYPE_BIAS NULL
+#define LANG_HOOKS_DESCRIPTIVE_TYPE NULL
+#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE NULL // sdcpp reconstruct_complex_type
+#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
+#define LANG_HOOKS_GET_DEBUG_TYPE NULL
+#define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE lhd_type_dwarf_attribute
+#define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING lhd_unit_size_without_reusable_padding
+#define LANG_HOOKS_CLASSTYPE_AS_BASE hook_tree_const_tree_null
+
+#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
+ LANG_HOOKS_MAKE_TYPE, \
+ LANG_HOOKS_SIMULATE_ENUM_DECL, \
+ LANG_HOOKS_SIMULATE_RECORD_DECL, \
+ LANG_HOOKS_CLASSIFY_RECORD, \
+ LANG_HOOKS_TYPE_FOR_MODE, \
+ LANG_HOOKS_TYPE_FOR_SIZE, \
+ LANG_HOOKS_GENERIC_TYPE_P, \
+ LANG_HOOKS_GET_ARGUMENT_PACK_ELEMS, \
+ LANG_HOOKS_TYPE_PROMOTES_TO, \
+ LANG_HOOKS_REGISTER_BUILTIN_TYPE, \
+ LANG_HOOKS_INCOMPLETE_TYPE_ERROR, \
+ LANG_HOOKS_TYPE_MAX_SIZE, \
+ LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
+ LANG_HOOKS_OMP_MAPPABLE_TYPE, \
+ LANG_HOOKS_TYPE_HASH_EQ, \
+ LANG_HOOKS_COPY_LANG_QUALIFIERS, \
+ LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
+ LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
+ LANG_HOOKS_GET_TYPE_BIAS, \
+ LANG_HOOKS_DESCRIPTIVE_TYPE, \
+ LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
+ LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
+ LANG_HOOKS_GET_DEBUG_TYPE, \
+ LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+ LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, \
+ LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING, \
+ LANG_HOOKS_CLASSTYPE_AS_BASE \
+}
+
+/* Declaration hooks. */
+#define LANG_HOOKS_GLOBAL_BINDINGS_P hook_bool_void_false // global_bindings_p
+#define LANG_HOOKS_PUSHDECL pushdecl
+#define LANG_HOOKS_GETDECLS getdecls
+#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE hook_int_const_tree_int // lhd_decl_dwarf_attribute
+#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl
+#define LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS NULL
+#define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall
+#define LANG_HOOKS_OMP_ARRAY_DATA hook_tree_tree_bool_null
+#define LANG_HOOKS_OMP_IS_ALLOCATABLE_OR_PTR hook_bool_const_tree_false
+#define LANG_HOOKS_OMP_CHECK_OPTIONAL_ARGUMENT hook_tree_tree_bool_null
+#define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_const_tree_false
+#define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing
+#define LANG_HOOKS_OMP_PREDETERMINED_MAPPING lhd_omp_predetermined_mapping
+#define LANG_HOOKS_OMP_REPORT_DECL lhd_pass_through_t
+#define LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR hook_bool_tree_bool_false
+#define LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE hook_bool_tree_bool_false
+#define LANG_HOOKS_OMP_PRIVATE_OUTER_REF hook_bool_tree_false
+#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR hook_tree_tree_tree_tree_null
+#define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR lhd_omp_assignment
+#define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP lhd_omp_assignment
+#define LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR NULL
+#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
+#define LANG_HOOKS_OMP_FINISH_CLAUSE NULL // sdcpp lhd_omp_finish_clause
+#define LANG_HOOKS_OMP_ALLOCATABLE_P hook_bool_tree_false
+#define LANG_HOOKS_OMP_SCALAR_P NULL // sdcpp lhd_omp_scalar_p
+#define LANG_HOOKS_OMP_SCALAR_TARGET_P hook_bool_tree_false
+#define LANG_HOOKS_OMP_GET_DECL_INIT NULL // sdcpp lhd_omp_get_decl_init
+#define LANG_HOOKS_OMP_FINISH_DECL_INITS NULL // sdcpp lhd_omp_finish_decl_inits
+
+#define LANG_HOOKS_DECLS { \
+ LANG_HOOKS_GLOBAL_BINDINGS_P, \
+ LANG_HOOKS_PUSHDECL, \
+ LANG_HOOKS_GETDECLS, \
+ LANG_HOOKS_DECL_DWARF_ATTRIBUTE, \
+ LANG_HOOKS_GENERIC_GENERIC_PARAMETER_DECL_P, \
+ LANG_HOOKS_FUNCTION_PARM_EXPANDED_FROM_PACK_P, \
+ LANG_HOOKS_GET_GENERIC_FUNCTION_DECL, \
+ LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \
+ LANG_HOOKS_POST_COMPILATION_PARSING_CLEANUPS, \
+ LANG_HOOKS_DECL_OK_FOR_SIBCALL, \
+ LANG_HOOKS_OMP_ARRAY_DATA, \
+ LANG_HOOKS_OMP_IS_ALLOCATABLE_OR_PTR, \
+ LANG_HOOKS_OMP_CHECK_OPTIONAL_ARGUMENT, \
+ LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE, \
+ LANG_HOOKS_OMP_PREDETERMINED_SHARING, \
+ LANG_HOOKS_OMP_PREDETERMINED_MAPPING, \
+ LANG_HOOKS_OMP_REPORT_DECL, \
+ LANG_HOOKS_OMP_DISREGARD_VALUE_EXPR, \
+ LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE, \
+ LANG_HOOKS_OMP_PRIVATE_OUTER_REF, \
+ LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR, \
+ LANG_HOOKS_OMP_CLAUSE_COPY_CTOR, \
+ LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP, \
+ LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR, \
+ LANG_HOOKS_OMP_CLAUSE_DTOR, \
+ LANG_HOOKS_OMP_FINISH_CLAUSE, \
+ LANG_HOOKS_OMP_ALLOCATABLE_P, \
+ LANG_HOOKS_OMP_SCALAR_P, \
+ LANG_HOOKS_OMP_SCALAR_TARGET_P, \
+ LANG_HOOKS_OMP_GET_DECL_INIT, \
+ LANG_HOOKS_OMP_FINISH_DECL_INITS \
+}
+
+/* LTO hooks. */
+extern void lhd_begin_section (const char *);
+extern void lhd_append_data (const void *, size_t, void *);
+extern void lhd_end_section (void);
+
+#define LANG_HOOKS_BEGIN_SECTION lhd_begin_section
+#define LANG_HOOKS_APPEND_DATA lhd_append_data
+#define LANG_HOOKS_END_SECTION lhd_end_section
+
+#define LANG_HOOKS_LTO { \
+ LANG_HOOKS_BEGIN_SECTION, \
+ LANG_HOOKS_APPEND_DATA, \
+ LANG_HOOKS_END_SECTION \
+}
+
+/* The whole thing. The structure is defined in langhooks.h. */
+#define LANG_HOOKS_INITIALIZER { \
+ LANG_HOOKS_NAME, \
+ LANG_HOOKS_IDENTIFIER_SIZE, \
+ LANG_HOOKS_FREE_LANG_DATA, \
+ LANG_HOOKS_TREE_SIZE, \
+ LANG_HOOKS_OPTION_LANG_MASK, \
+ LANG_HOOKS_INIT_OPTIONS_STRUCT, \
+ LANG_HOOKS_INIT_OPTIONS, \
+ LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
+ LANG_HOOKS_PREPROCESS_MAIN_FILE, \
+ LANG_HOOKS_PREPROCESS_OPTIONS, \
+ LANG_HOOKS_PREPROCESS_UNDEF, \
+ LANG_HOOKS_PREPROCESS_TOKEN, \
+ LANG_HOOKS_REGISTER_DUMPS, \
+ LANG_HOOKS_COMPLAIN_WRONG_LANG_P, \
+ LANG_HOOKS_HANDLE_OPTION, \
+ LANG_HOOKS_POST_OPTIONS, \
+ LANG_HOOKS_INIT, \
+ LANG_HOOKS_FINISH, \
+ LANG_HOOKS_PARSE_FILE, \
+ LANG_HOOKS_MISSING_NORETURN_OK_P, \
+ LANG_HOOKS_GET_ALIAS_SET, \
+ LANG_HOOKS_FINISH_INCOMPLETE_DECL, \
+ LANG_HOOKS_DUP_LANG_SPECIFIC_DECL, \
+ LANG_HOOKS_SET_DECL_ASSEMBLER_NAME, \
+ LANG_HOOKS_OVERWRITE_DECL_ASSEMBLER_NAME, \
+ LANG_HOOKS_PRINT_STATISTICS, \
+ LANG_HOOKS_PRINT_XNODE, \
+ LANG_HOOKS_PRINT_DECL, \
+ LANG_HOOKS_PRINT_TYPE, \
+ LANG_HOOKS_PRINT_IDENTIFIER, \
+ LANG_HOOKS_DECL_PRINTABLE_NAME, \
+ LANG_HOOKS_DWARF_NAME, \
+ LANG_HOOKS_TYPES_COMPATIBLE_P, \
+ LANG_HOOKS_PRINT_ERROR_FUNCTION, \
+ LANG_HOOKS_TO_TARGET_CHARSET, \
+ LANG_HOOKS_ATTRIBUTE_TABLE, \
+ LANG_HOOKS_COMMON_ATTRIBUTE_TABLE, \
+ LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE, \
+ LANG_HOOKS_TREE_INLINING_INITIALIZER, \
+ LANG_HOOKS_TREE_DUMP_INITIALIZER, \
+ LANG_HOOKS_DECLS, \
+ LANG_HOOKS_FOR_TYPES_INITIALIZER, \
+ LANG_HOOKS_LTO, \
+ LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \
+ LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \
+ LANG_HOOKS_FUNCTION_PARAMETER_PACK_P, \
+ LANG_HOOKS_GIMPLIFY_EXPR, \
+ LANG_HOOKS_BUILTIN_FUNCTION, \
+ LANG_HOOKS_BUILTIN_FUNCTION_EXT_SCOPE, \
+ LANG_HOOKS_SIMULATE_BUILTIN_FUNCTION_DECL, \
+ LANG_HOOKS_INIT_TS, \
+ LANG_HOOKS_EXPR_TO_DECL, \
+ LANG_HOOKS_EH_PERSONALITY, \
+ LANG_HOOKS_EH_RUNTIME_TYPE, \
+ LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS, \
+ LANG_HOOKS_BLOCK_MAY_FALLTHRU, \
+ LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \
+ LANG_HOOKS_DEEP_UNSHARING, \
+ LANG_HOOKS_CUSTOM_FUNCTION_DESCRIPTORS, \
+ LANG_HOOKS_EMITS_BEGIN_STMT, \
+ LANG_HOOKS_RUN_LANG_SELFTESTS, \
+ LANG_HOOKS_GET_SUBSTRING_LOCATION, \
+ LANG_HOOKS_FINALIZE_EARLY_DEBUG \
+}
+
+#endif /* GCC_LANG_HOOKS_DEF_H */
diff --git a/support/cpp/gcc/langhooks.h b/support/cpp/gcc/langhooks.h
new file mode 100644
index 000000000..c20b94d2d
--- /dev/null
+++ b/support/cpp/gcc/langhooks.h
@@ -0,0 +1,666 @@
+/* The lang_hooks data structure.
+ Copyright (C) 2001-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_LANG_HOOKS_H
+#define GCC_LANG_HOOKS_H
+
+/* FIXME: This file should be #include-d after tree.h (for enum tree_code). */
+
+struct diagnostic_info;
+
+struct gimplify_omp_ctx;
+
+struct array_descr_info;
+
+/* A print hook for print_tree (). */
+typedef void (*lang_print_tree_hook) (FILE *, tree, int indent);
+
+enum classify_record
+ { RECORD_IS_STRUCT, RECORD_IS_CLASS, RECORD_IS_INTERFACE };
+
+class substring_loc;
+
+/* The following hooks are documented in langhooks.cc. Must not be
+ NULL. */
+
+struct lang_hooks_for_tree_inlining
+{
+ bool (*var_mod_type_p) (tree, tree);
+};
+
+/* The following hooks are used by tree-dump.cc. */
+
+struct lang_hooks_for_tree_dump
+{
+ /* Dump language-specific parts of tree nodes. Returns nonzero if it
+ does not want the usual dumping of the second argument. */
+ bool (*dump_tree) (void *, tree);
+
+ /* Determine type qualifiers in a language-specific way. */
+ int (*type_quals) (const_tree);
+};
+
+/* Hooks related to types. */
+
+struct lang_hooks_for_types
+{
+ /* Return a new type (with the indicated CODE), doing whatever
+ language-specific processing is required. */
+ tree (*make_type) (enum tree_code);
+
+ /* Make an enum type with the given name and values, associating
+ them all with the given source location. */
+ tree (*simulate_enum_decl) (location_t, const char *, vec<string_int_pair> *);
+
+ /* Do the equivalent of:
+
+ typedef struct NAME { FIELDS; } NAME;
+
+ associating it with location LOC. Return the associated RECORD_TYPE.
+
+ FIELDS is a list of FIELD_DECLs, in layout order. */
+ tree (*simulate_record_decl) (location_t loc, const char *name,
+ array_slice<const tree> fields);
+
+ /* Return what kind of RECORD_TYPE this is, mainly for purposes of
+ debug information. If not defined, record types are assumed to
+ be structures. */
+ enum classify_record (*classify_record) (tree);
+
+ /* Given MODE and UNSIGNEDP, return a suitable type-tree with that
+ mode. */
+ tree (*type_for_mode) (machine_mode, int);
+
+ /* Given PRECISION and UNSIGNEDP, return a suitable type-tree for an
+ integer type with at least that precision. */
+ tree (*type_for_size) (unsigned, int);
+
+ /* True if the type is an instantiation of a generic type,
+ e.g. C++ template implicit specializations. */
+ bool (*generic_p) (const_tree);
+
+ /* Returns the TREE_VEC of elements of a given generic argument pack. */
+ tree (*get_argument_pack_elems) (const_tree);
+
+ /* Given a type, apply default promotions to unnamed function
+ arguments and return the new type. Return the same type if no
+ change. Required by any language that supports variadic
+ arguments. The default hook dies. */
+ tree (*type_promotes_to) (tree);
+
+ /* Register TYPE as a builtin type with the indicated NAME. The
+ TYPE is placed in the outermost lexical scope. The semantics
+ should be analogous to:
+
+ typedef TYPE NAME;
+
+ in C. The default hook ignores the declaration. */
+ void (*register_builtin_type) (tree, const char *);
+
+ /* This routine is called in tree.cc to print an error message for
+ invalid use of an incomplete type. VALUE is the expression that
+ was used (or 0 if that isn't known) and TYPE is the type that was
+ invalid. LOC is the location of the use. */
+ void (*incomplete_type_error) (location_t loc, const_tree value,
+ const_tree type);
+
+ /* Called from assign_temp to return the maximum size, if there is one,
+ for a type. */
+ tree (*max_size) (const_tree);
+
+ /* Register language specific type size variables as potentially OpenMP
+ firstprivate variables. */
+ void (*omp_firstprivatize_type_sizes) (struct gimplify_omp_ctx *, tree);
+
+ /* Return true if TYPE is a mappable type. */
+ bool (*omp_mappable_type) (tree type);
+
+ /* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+ Called only after doing all language independent checks.
+ At present, this function is only called when both TYPE1 and TYPE2 are
+ FUNCTION_TYPE or METHOD_TYPE. */
+ bool (*type_hash_eq) (const_tree, const_tree);
+
+ /* If non-NULL, return TYPE1 with any language-specific modifiers copied from
+ TYPE2. */
+ tree (*copy_lang_qualifiers) (const_tree, const_tree);
+
+ /* Return TRUE if TYPE uses a hidden descriptor and fills in information
+ for the debugger about the array bounds, strides, etc. */
+ bool (*get_array_descr_info) (const_tree, struct array_descr_info *);
+
+ /* Fill in information for the debugger about the bounds of TYPE. */
+ void (*get_subrange_bounds) (const_tree, tree *, tree *);
+
+ /* Called on INTEGER_TYPEs. Return NULL_TREE for non-biased types. For
+ biased types, return as an INTEGER_CST node the value that is represented
+ by a physical zero. */
+ tree (*get_type_bias) (const_tree);
+
+ /* A type descriptive of TYPE's complex layout generated to help the
+ debugger to decode variable-length or self-referential constructs.
+ This is only used for the AT_GNAT_descriptive_type DWARF attribute. */
+ tree (*descriptive_type) (const_tree);
+
+ /* If we requested a pointer to a vector, build up the pointers that
+ we stripped off while looking for the inner type. Similarly for
+ return values from functions. The argument TYPE is the top of the
+ chain, and BOTTOM is the new type which we will point to. */
+ tree (*reconstruct_complex_type) (tree, tree);
+
+ /* Returns the tree that represents the underlying data type used to
+ implement the enumeration. The default implementation will just use
+ type_for_size. Used in dwarf2out.cc to add a DW_AT_type base type
+ reference to a DW_TAG_enumeration. */
+ tree (*enum_underlying_base_type) (const_tree);
+
+ /* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
+ keep TYPE. This is useful to keep a single "source type" when the
+ middle-end uses specialized types, for instance constrained discriminated
+ types in Ada. */
+ tree (*get_debug_type) (const_tree);
+
+ /* Return TRUE if TYPE implements a fixed point type and fills in information
+ for the debugger about scale factor, etc. */
+ bool (*get_fixed_point_type_info) (const_tree,
+ struct fixed_point_type_info *);
+
+ /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+ int (*type_dwarf_attribute) (const_tree, int);
+
+ /* Returns a tree for the unit size of T excluding tail padding that
+ might be used by objects inheriting from T. */
+ tree (*unit_size_without_reusable_padding) (tree);
+
+ /* Returns type corresponding to FIELD's type when FIELD is a C++ base class
+ i.e., type without virtual base classes or tail padding. Returns
+ NULL_TREE otherwise. */
+ tree (*classtype_as_base) (const_tree);
+};
+
+/* Language hooks related to decls and the symbol table. */
+
+struct lang_hooks_for_decls
+{
+ /* Return true if we are in the global binding level. This hook is really
+ needed only if the language supports variable-sized types at the global
+ level, i.e. declared outside subprograms. */
+ bool (*global_bindings_p) (void);
+
+ /* Function to add a decl to the current scope level. Takes one
+ argument, a decl to add. Returns that decl, or, if the same
+ symbol is already declared, may return a different decl for that
+ name. */
+ tree (*pushdecl) (tree);
+
+ /* Returns the chain of decls so far in the current scope level. */
+ tree (*getdecls) (void);
+
+ /* Returns -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
+ value otherwise. */
+ int (*decl_dwarf_attribute) (const_tree, int);
+
+ /* Returns True if the parameter is a generic parameter decl
+ of a generic type, e.g a template template parameter for the C++ FE. */
+ bool (*generic_generic_parameter_decl_p) (const_tree);
+
+ /* Determine if a function parameter got expanded from a
+ function parameter pack. */
+ bool (*function_parm_expanded_from_pack_p) (tree, tree);
+
+ /* Returns the generic declaration of a generic function instantiations. */
+ tree (*get_generic_function_decl) (const_tree);
+
+ /* Returns true when we should warn for an unused global DECL.
+ We will already have checked that it has static binding. */
+ bool (*warn_unused_global) (const_tree);
+
+ /* Perform any post compilation-proper parser cleanups and
+ processing. This is currently only needed for the C++ parser,
+ which hopefully can be cleaned up so this hook is no longer
+ necessary. */
+ void (*post_compilation_parsing_cleanups) (void);
+
+ /* True if this decl may be called via a sibcall. */
+ bool (*ok_for_sibcall) (const_tree);
+
+ /* Return a tree for the actual data of an array descriptor - or NULL_TREE
+ if original tree is not an array descriptor. If the second argument
+ is true, only the TREE_TYPE is returned without generating a new tree. */
+ tree (*omp_array_data) (tree, bool);
+
+ /* True if OpenMP should regard this DECL as being a scalar which has Fortran's
+ allocatable or pointer attribute. */
+ bool (*omp_is_allocatable_or_ptr) (const_tree);
+
+ /* Check whether this DECL belongs to a Fortran optional argument.
+ With 'for_present_check' set to false, decls which are optional parameters
+ themselve are returned as tree - or a NULL_TREE otherwise. Those decls are
+ always pointers. With 'for_present_check' set to true, the decl for
+ checking whether an argument is present is returned; for arguments with
+ value attribute this is the hidden argument and of BOOLEAN_TYPE. If the
+ decl is unrelated to optional arguments, NULL_TREE is returned. */
+ tree (*omp_check_optional_argument) (tree, bool);
+
+ /* True if OpenMP should privatize what this DECL points to rather
+ than the DECL itself. */
+ bool (*omp_privatize_by_reference) (const_tree);
+
+ /* Return sharing kind if OpenMP sharing attribute of DECL is
+ predetermined, OMP_CLAUSE_DEFAULT_UNSPECIFIED otherwise. */
+ enum omp_clause_default_kind (*omp_predetermined_sharing) (tree);
+
+ /* Return mapping kind if OpenMP mapping attribute of DECL is
+ predetermined, OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED otherwise. */
+ enum omp_clause_defaultmap_kind (*omp_predetermined_mapping) (tree);
+
+ /* Return decl that should be reported for DEFAULT(NONE) failure
+ diagnostics. Usually the DECL passed in. */
+ tree (*omp_report_decl) (tree);
+
+ /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
+ disregarded in OpenMP construct, because it is going to be
+ remapped during OpenMP lowering. SHARED is true if DECL
+ is going to be shared, false if it is going to be privatized. */
+ bool (*omp_disregard_value_expr) (tree, bool);
+
+ /* Return true if DECL that is shared iff SHARED is true should
+ be put into OMP_CLAUSE_PRIVATE_DEBUG. */
+ bool (*omp_private_debug_clause) (tree, bool);
+
+ /* Return true if DECL in private clause needs
+ OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
+ bool (*omp_private_outer_ref) (tree);
+
+ /* Build and return code for a default constructor for DECL in
+ response to CLAUSE. OUTER is corresponding outer region's
+ variable if needed. Return NULL if nothing to be done. */
+ tree (*omp_clause_default_ctor) (tree clause, tree decl, tree outer);
+
+ /* Build and return code for a copy constructor from SRC to DST. */
+ tree (*omp_clause_copy_ctor) (tree clause, tree dst, tree src);
+
+ /* Similarly, except use an assignment operator instead. */
+ tree (*omp_clause_assign_op) (tree clause, tree dst, tree src);
+
+ /* Build and return code for a constructor of DST that sets it to
+ SRC + ADD. */
+ tree (*omp_clause_linear_ctor) (tree clause, tree dst, tree src, tree add);
+
+ /* Build and return code destructing DECL. Return NULL if nothing
+ to be done. */
+ tree (*omp_clause_dtor) (tree clause, tree decl);
+
+ /* Do language specific checking on an implicitly determined clause. */
+ void (*omp_finish_clause) (tree clause, gimple_seq *pre_p, bool);
+
+ /* Return true if DECL is an allocatable variable (for the purpose of
+ implicit mapping). */
+ bool (*omp_allocatable_p) (tree decl);
+
+ /* Return true if DECL is a scalar variable (for the purpose of
+ implicit firstprivatization). If 'ptr_or', pointers and
+ allocatables are also permitted. */
+ bool (*omp_scalar_p) (tree decl, bool ptr_ok);
+
+ /* Return true if DECL is a scalar variable with Fortran target but not
+ allocatable or pointer attribute (for the purpose of implicit mapping). */
+ bool (*omp_scalar_target_p) (tree decl);
+
+ /* Return a pointer to the tree representing the initializer
+ expression for the non-local variable DECL. Return NULL if
+ DECL is not initialized. */
+ tree *(*omp_get_decl_init) (tree decl);
+
+ /* Free any extra memory used to hold initializer information for
+ variable declarations. omp_get_decl_init must not be called
+ after calling this. */
+ void (*omp_finish_decl_inits) (void);
+};
+
+/* Language hooks related to LTO serialization. */
+
+struct lang_hooks_for_lto
+{
+ /* Begin a new LTO section named NAME. */
+ void (*begin_section) (const char *name);
+
+ /* Write DATA of length LEN to the currently open LTO section. BLOCK is a
+ pointer to the dynamically allocated memory containing DATA. The
+ append_data function is responsible for freeing it when it is no longer
+ needed. */
+ void (*append_data) (const void *data, size_t len, void *block);
+
+ /* End the previously begun LTO section. */
+ void (*end_section) (void);
+};
+
+/* Language-specific hooks. See langhooks-def.h for defaults. */
+
+struct lang_hooks
+{
+ /* String identifying the front end and optionally language standard
+ version, e.g. "GNU C++98". */
+ const char *name;
+
+ /* sizeof (struct lang_identifier), so make_node () creates
+ identifier nodes long enough for the language-specific slots. */
+ size_t identifier_size;
+
+ /* Remove any parts of the tree that are used only by the FE. */
+ void (*free_lang_data) (tree);
+
+ /* Determines the size of any language-specific tcc_constant,
+ tcc_exceptional or tcc_type nodes. Since it is called from
+ make_node, the only information available is the tree code.
+ Expected to die on unrecognized codes. */
+ size_t (*tree_size) (enum tree_code);
+
+ /* Return the language mask used for converting argv into a sequence
+ of options. */
+ unsigned int (*option_lang_mask) (void);
+
+ /* Initialize variables in an options structure. */
+ void (*init_options_struct) (struct gcc_options *opts);
+
+ /* After the initialize_diagnostics hook is called, do any simple
+ initialization needed before any calls to handle_option, other
+ than that done by the init_options_struct hook. */
+ void (*init_options) (unsigned int decoded_options_count,
+ struct cl_decoded_option *decoded_options);
+
+ /* Callback used to perform language-specific initialization for the
+ global diagnostic context structure. */
+ void (*initialize_diagnostics) (diagnostic_context *);
+
+ /* Beginning the main source file. */
+ void (*preprocess_main_file) (cpp_reader *, line_maps *,
+ const line_map_ordinary *);
+
+ /* Adjust libcpp options and callbacks. */
+ void (*preprocess_options) (cpp_reader *);
+
+ /* Undefining a macro. */
+ void (*preprocess_undef) (cpp_reader *, location_t, cpp_hashnode *);
+
+ /* Observer for preprocessing stream. */
+ uintptr_t (*preprocess_token) (cpp_reader *, const cpp_token *, uintptr_t);
+ /* Various flags it can return about the token. */
+ enum PT_flags
+ {
+ PT_begin_pragma = 1 << 0
+ };
+
+ /* Register language-specific dumps. */
+ void (*register_dumps) (gcc::dump_manager *);
+
+ /* Return true if a warning should be given about option OPTION,
+ which is for the wrong language, false if it should be quietly
+ ignored. */
+ bool (*complain_wrong_lang_p) (const struct cl_option *option);
+
+ /* Handle the switch CODE, which has real type enum opt_code from
+ options.h. If the switch takes an argument, it is passed in ARG
+ which points to permanent storage. The handler is responsible for
+ checking whether ARG is NULL, which indicates that no argument
+ was in fact supplied. For -f and -W switches, VALUE is 1 or 0
+ for the positive and negative forms respectively. HANDLERS should
+ be passed to any recursive handle_option calls. LOC is the
+ location of the option.
+
+ Return true if the switch is valid, false if invalid. */
+ bool (*handle_option) (size_t code, const char *arg, HOST_WIDE_INT value,
+ int kind, location_t loc,
+ const struct cl_option_handlers *handlers);
+
+ /* Called when all command line options have been parsed to allow
+ further processing and initialization
+
+ Should return true to indicate that a compiler back-end is
+ not required, such as with the -E option.
+
+ If errorcount is nonzero after this call the compiler exits
+ immediately and the finish hook is not called. */
+ bool (*post_options) (const char **);
+
+ /* Called after post_options to initialize the front end. Return
+ false to indicate that no further compilation be performed, in
+ which case the finish hook is called immediately. */
+ bool (*init) (void);
+
+ /* Called at the end of compilation, as a finalizer. */
+ void (*finish) (void);
+
+ /* Parses the entire file. */
+ void (*parse_file) (void);
+
+ /* Determines if it's ok for a function to have no noreturn attribute. */
+ bool (*missing_noreturn_ok_p) (tree);
+
+ /* Called to obtain the alias set to be used for an expression or type.
+ Returns -1 if the language does nothing special for it. */
+ alias_set_type (*get_alias_set) (tree);
+
+ /* Function to finish handling an incomplete decl at the end of
+ compilation. Default hook is does nothing. */
+ void (*finish_incomplete_decl) (tree);
+
+ /* Replace the DECL_LANG_SPECIFIC data, which may be NULL, of the
+ DECL_NODE with a newly GC-allocated copy. */
+ void (*dup_lang_specific_decl) (tree);
+
+ /* Set the DECL_ASSEMBLER_NAME for a node. If it is the sort of
+ thing that the assembler should talk about, set
+ DECL_ASSEMBLER_NAME to an appropriate IDENTIFIER_NODE.
+ Otherwise, set it to the ERROR_MARK_NODE to ensure that the
+ assembler does not talk about it. */
+ void (*set_decl_assembler_name) (tree);
+
+ /* Overwrite the DECL_ASSEMBLER_NAME for a node. The name is being
+ changed (including to or from NULL_TREE). */
+ void (*overwrite_decl_assembler_name) (tree, tree);
+
+ /* The front end can add its own statistics to -fmem-report with
+ this hook. It should output to stderr. */
+ void (*print_statistics) (void);
+
+ /* Called by print_tree when there is a tree of class tcc_exceptional
+ or tcc_constant that it doesn't know how to display. */
+ lang_print_tree_hook print_xnode;
+
+ /* Called to print language-dependent parts of tcc_decl, tcc_type,
+ and IDENTIFIER_NODE nodes. */
+ lang_print_tree_hook print_decl;
+ lang_print_tree_hook print_type;
+ lang_print_tree_hook print_identifier;
+
+ /* Computes the name to use to print a declaration. DECL is the
+ non-NULL declaration in question. VERBOSITY determines what
+ information will be printed: 0: DECL_NAME, demangled as
+ necessary. 1: and scope information. 2: and any other
+ information that might be interesting, such as function parameter
+ types in C++. The name is in the internal character set and
+ needs to be converted to the locale character set of diagnostics,
+ or to the execution character set for strings such as
+ __PRETTY_FUNCTION__. */
+ const char *(*decl_printable_name) (tree decl, int verbosity);
+
+ /* Computes the dwarf-2/3 name for a tree. VERBOSITY determines what
+ information will be printed: 0: DECL_NAME, demangled as
+ necessary. 1: and scope information. */
+ const char *(*dwarf_name) (tree, int verbosity);
+
+ /* This compares two types for equivalence ("compatible" in C-based languages).
+ This routine should only return 1 if it is sure. It should not be used
+ in contexts where erroneously returning 0 causes problems. */
+ int (*types_compatible_p) (tree x, tree y);
+
+ /* Called by report_error_function to print out function name. */
+ void (*print_error_function) (diagnostic_context *, const char *,
+ struct diagnostic_info *);
+
+ /* Convert a character from the host's to the target's character
+ set. The character should be in what C calls the "basic source
+ character set" (roughly, the set of characters defined by plain
+ old ASCII). The default is to return the character unchanged,
+ which is correct in most circumstances. Note that both argument
+ and result should be sign-extended under -fsigned-char,
+ zero-extended under -fno-signed-char. */
+ HOST_WIDE_INT (*to_target_charset) (HOST_WIDE_INT);
+
+ /* Pointers to machine-independent attribute tables, for front ends
+ using attribs.cc. If one is NULL, it is ignored. Respectively, a
+ table of attributes specific to the language, a table of
+ attributes common to two or more languages (to allow easy
+ sharing), and a table of attributes for checking formats. */
+ const struct attribute_spec *attribute_table;
+ const struct attribute_spec *common_attribute_table;
+ const struct attribute_spec *format_attribute_table;
+
+ struct lang_hooks_for_tree_inlining tree_inlining;
+
+ struct lang_hooks_for_tree_dump tree_dump;
+
+ struct lang_hooks_for_decls decls;
+
+ struct lang_hooks_for_types types;
+
+ struct lang_hooks_for_lto lto;
+
+ /* Returns a TREE_VEC of the generic parameters of an instantiation of
+ a generic type or decl, e.g. C++ template instantiation. If
+ TREE_CHAIN of the return value is set, it is an INTEGER_CST
+ indicating how many of the elements are non-default. */
+ tree (*get_innermost_generic_parms) (const_tree);
+
+ /* Returns the TREE_VEC of arguments of an instantiation
+ of a generic type of decl, e.g. C++ template instantiation. */
+ tree (*get_innermost_generic_args) (const_tree);
+
+ /* Determine if a tree is a function parameter pack. */
+ bool (*function_parameter_pack_p) (const_tree);
+
+ /* Perform language-specific gimplification on the argument. Returns an
+ enum gimplify_status, though we can't see that type here. */
+ int (*gimplify_expr) (tree *, gimple_seq *, gimple_seq *);
+
+ /* Do language specific processing in the builtin function DECL */
+ tree (*builtin_function) (tree decl);
+
+ /* Like builtin_function, but make sure the scope is the external scope.
+ This is used to delay putting in back end builtin functions until the ISA
+ that defines the builtin is declared via function specific target options,
+ which can save memory for machines like the x86_64 that have multiple
+ ISAs. If this points to the same function as builtin_function, the
+ backend must add all of the builtins at program initialization time. */
+ tree (*builtin_function_ext_scope) (tree decl);
+
+ /* Do language-specific processing for target-specific built-in
+ function DECL, so that it is defined in the global scope (only)
+ and is available without needing to be explicitly declared.
+
+ This is intended for targets that want to inject declarations of
+ built-in functions into the source language (such as in response
+ to a pragma) rather than providing them in the source language itself. */
+ tree (*simulate_builtin_function_decl) (tree decl);
+
+ /* Used to set up the tree_contains_structure array for a frontend. */
+ void (*init_ts) (void);
+
+ /* Called by recompute_tree_invariant_for_addr_expr to go from EXPR
+ to a contained expression or DECL, possibly updating *TC or *SE
+ if in the process TREE_CONSTANT or TREE_SIDE_EFFECTS need updating. */
+ tree (*expr_to_decl) (tree expr, bool *tc, bool *se);
+
+ /* The EH personality function decl. */
+ tree (*eh_personality) (void);
+
+ /* Map a type to a runtime object to match type. */
+ tree (*eh_runtime_type) (tree);
+
+ /* If non-NULL, this is a function that returns a function decl to be
+ executed if an unhandled exception is propagated out of a cleanup
+ region. For example, in C++, an exception thrown by a destructor
+ during stack unwinding is required to result in a call to
+ `std::terminate', so the C++ version of this function returns a
+ FUNCTION_DECL for `std::terminate'. */
+ tree (*eh_protect_cleanup_actions) (void);
+
+ /* Return true if a stmt can fallthru. Used by block_may_fallthru
+ to possibly handle language trees. */
+ bool (*block_may_fallthru) (const_tree);
+
+ /* True if this language uses __cxa_end_cleanup when the ARM EABI
+ is enabled. */
+ bool eh_use_cxa_end_cleanup;
+
+ /* True if this language requires deep unsharing of tree nodes prior to
+ gimplification. */
+ bool deep_unsharing;
+
+ /* True if this language may use custom descriptors for nested functions
+ instead of trampolines. */
+ bool custom_function_descriptors;
+
+ /* True if this language emits begin stmt notes. */
+ bool emits_begin_stmt;
+
+ /* Run all lang-specific selftests. */
+ void (*run_lang_selftests) (void);
+
+ /* Attempt to determine the source location of the substring.
+ If successful, return NULL and write the source location to *OUT_LOC.
+ Otherwise return an error message. Error messages are intended
+ for GCC developers (to help debugging) rather than for end-users. */
+ const char *(*get_substring_location) (const substring_loc &,
+ location_t *out_loc);
+
+ /* Invoked before the early_finish debug hook is invoked. */
+ void (*finalize_early_debug) (void);
+
+ /* Whenever you add entries here, make sure you adjust langhooks-def.h
+ and langhooks.cc accordingly. */
+};
+
+/* Each front end provides its own. */
+extern struct lang_hooks lang_hooks;
+
+// sdcpp extern tree add_builtin_function (const char *name, tree type,
+// sdcpp int function_code, enum built_in_class cl,
+// sdcpp const char *library_name,
+// sdcpp tree attrs);
+
+// sdcpp extern tree add_builtin_function_ext_scope (const char *name, tree type,
+// sdcpp int function_code,
+// sdcpp enum built_in_class cl,
+// sdcpp const char *library_name,
+// sdcpp tree attrs);
+extern tree simulate_builtin_function_decl (location_t, const char *, tree,
+ int, const char *, tree);
+extern tree add_builtin_type (const char *name, tree type);
+
+/* Language helper functions. */
+
+extern bool lang_GNU_C (void);
+extern bool lang_GNU_CXX (void);
+extern bool lang_GNU_Fortran (void);
+extern bool lang_GNU_OBJC (void);
+
+#endif /* GCC_LANG_HOOKS_H */
diff --git a/support/cpp/gcc/libfuncs.h b/support/cpp/gcc/libfuncs.h
new file mode 100644
index 000000000..354be0b78
--- /dev/null
+++ b/support/cpp/gcc/libfuncs.h
@@ -0,0 +1,84 @@
+/* Definitions for code generation pass of GNU compiler.
+ Copyright (C) 2001-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_LIBFUNCS_H
+#define GCC_LIBFUNCS_H
+
+
+/* Enumeration of indexes into libfunc_table. */
+enum libfunc_index
+{
+ LTI_unwind_sjlj_register,
+ LTI_unwind_sjlj_unregister,
+ LTI_synchronize,
+ LTI_MAX
+};
+
+/* Information about an optab-related libfunc. The op field is logically
+ an enum optab_d, and the mode fields are logically machine_mode.
+ However, in the absence of forward-declared enums, there's no practical
+ benefit of pulling in the defining headers.
+
+ We use the same hashtable for normal optabs and conversion optabs. In
+ the first case mode2 is forced to VOIDmode. */
+
+struct GTY((for_user)) libfunc_entry {
+ int op, mode1, mode2;
+ rtx libfunc;
+};
+
+/* Descriptor for libfunc_entry. */
+
+struct libfunc_hasher : ggc_ptr_hash<libfunc_entry>
+{
+ static hashval_t hash (libfunc_entry *);
+ static bool equal (libfunc_entry *, libfunc_entry *);
+};
+
+/* Target-dependent globals. */
+struct GTY(()) target_libfuncs {
+ /* SYMBOL_REF rtx's for the library functions that are called
+ implicitly and not via optabs. */
+ rtx x_libfunc_table[LTI_MAX];
+
+ /* Hash table used to convert declarations into nodes. */
+ hash_table<libfunc_hasher> *GTY(()) x_libfunc_hash;
+};
+
+extern GTY(()) struct target_libfuncs default_target_libfuncs;
+#if SWITCHABLE_TARGET
+extern struct target_libfuncs *this_target_libfuncs;
+#else
+#define this_target_libfuncs (&default_target_libfuncs)
+#endif
+
+#define libfunc_table \
+ (this_target_libfuncs->x_libfunc_table)
+
+/* Accessor macros for libfunc_table. */
+
+#define unwind_sjlj_register_libfunc (libfunc_table[LTI_unwind_sjlj_register])
+#define unwind_sjlj_unregister_libfunc \
+ (libfunc_table[LTI_unwind_sjlj_unregister])
+#define synchronize_libfunc (libfunc_table[LTI_synchronize])
+
+/* In explow.cc */
+extern void set_stack_check_libfunc (const char *);
+
+#endif /* GCC_LIBFUNCS_H */
diff --git a/support/cpp/gcc/lto-streamer.h b/support/cpp/gcc/lto-streamer.h
new file mode 100644
index 000000000..0c46fd07c
--- /dev/null
+++ b/support/cpp/gcc/lto-streamer.h
@@ -0,0 +1,1246 @@
+/* Data structures and declarations used for reading and writing
+ GIMPLE to a file stream.
+
+ Copyright (C) 2009-2022 Free Software Foundation, Inc.
+ Contributed by Doug Kwan <dougkwan@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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/>. */
+
+#if 0 // sdcpp ndef GCC_LTO_STREAMER_H
+#define GCC_LTO_STREAMER_H
+
+#include "plugin-api.h"
+// #include "gcov-io.h"
+#include "diagnostic.h"
+#include "version.h"
+
+/* The encoding for a function consists of the following sections:
+
+ 1) The header.
+ 2) FIELD_DECLS.
+ 3) FUNCTION_DECLS.
+ 4) global VAR_DECLS.
+ 5) type_decls
+ 6) types.
+ 7) Names for the labels that have names
+ 8) The SSA names.
+ 9) The control flow graph.
+ 10-11)Gimple for local decls.
+ 12) Gimple for the function.
+ 13) Strings.
+
+ 1) THE HEADER.
+ 2-6) THE GLOBAL DECLS AND TYPES.
+
+ The global decls and types are encoded in the same way. For each
+ entry, there is word with the offset within the section to the
+ entry.
+
+ 7) THE LABEL NAMES.
+
+ Since most labels do not have names, this section my be of zero
+ length. It consists of an array of string table references, one
+ per label. In the lto code, the labels are given either
+ positive or negative indexes. the positive ones have names and
+ the negative ones do not. The positive index can be used to
+ find the name in this array.
+
+ 9) THE CFG.
+
+ 10) Index into the local decls. Since local decls can have local
+ decls inside them, they must be read in randomly in order to
+ properly restore them.
+
+ 11-12) GIMPLE FOR THE LOCAL DECLS AND THE FUNCTION BODY.
+
+ The gimple consists of a set of records.
+
+ THE FUNCTION
+
+ At the top level of (8) is the function. It consists of five
+ pieces:
+
+ LTO_function - The tag.
+ eh tree - This is all of the exception handling regions
+ put out in a post order traversial of the
+ tree. Siblings are output as lists terminated
+ by a 0. The set of fields matches the fields
+ defined in except.cc.
+
+ last_basic_block - in uleb128 form.
+
+ basic blocks - This is the set of basic blocks.
+
+ zero - The termination of the basic blocks.
+
+ BASIC BLOCKS
+
+ There are two forms of basic blocks depending on if they are
+ empty or not.
+
+ The basic block consists of:
+
+ LTO_bb1 or LTO_bb0 - The tag.
+
+ bb->index - the index in uleb128 form.
+
+ #succs - The number of successors un uleb128 form.
+
+ the successors - For each edge, a pair. The first of the
+ pair is the index of the successor in
+ uleb128 form and the second are the flags in
+ uleb128 form.
+
+ the statements - A gimple tree, as described above.
+ These are only present for LTO_BB1.
+ Following each statement is an optional
+ exception handling record LTO_eh_region
+ which contains the region number (for
+ regions >= 0).
+
+ zero - This is only present for LTO_BB1 and is used
+ to terminate the statements and exception
+ regions within this block.
+
+ 12) STRINGS
+
+ String are represented in the table as pairs, a length in ULEB128
+ form followed by the data for the string. */
+
+#define LTO_major_version GCC_major_version
+#define LTO_minor_version 0
+
+typedef unsigned char lto_decl_flags_t;
+
+/* Stream additional data to LTO object files to make it easier to debug
+ streaming code. This changes object files. */
+static const bool streamer_debugging = false;
+
+/* Tags representing the various IL objects written to the bytecode file
+ (GIMPLE statements, basic blocks, EH regions, tree nodes, etc).
+
+ NOTE, when adding new LTO tags, also update lto_tag_name. */
+enum LTO_tags
+{
+ LTO_null = 0,
+
+ /* Reference to previously-streamed node. */
+ LTO_tree_pickle_reference,
+
+ /* References to indexable tree nodes. These objects are stored in
+ tables that are written separately from the function bodies
+ and variable constructors that reference them. This way they can be
+ instantiated even when the referencing functions aren't (e.g., during WPA)
+ and it also allows functions to be copied from one file to another without
+ having to unpickle the body first (the references are location
+ independent). */
+ LTO_global_stream_ref,
+
+ LTO_ssa_name_ref,
+
+ /* Special for global streamer. A blob of unnamed tree nodes. */
+ LTO_tree_scc,
+
+ /* Sequence of trees. */
+ LTO_trees,
+
+ /* Shared INTEGER_CST node. */
+ LTO_integer_cst,
+
+ /* Tags of trees are encoded as
+ LTO_first_tree_tag + TREE_CODE. */
+ LTO_first_tree_tag,
+ /* Tags of gimple typles are encoded as
+ LTO_first_gimple_tag + gimple_code. */
+ LTO_first_gimple_tag = LTO_first_tree_tag + MAX_TREE_CODES,
+
+ /* Entry and exit basic blocks. */
+ LTO_bb0 = LTO_first_gimple_tag + LAST_AND_UNUSED_GIMPLE_CODE,
+ LTO_bb1,
+
+ /* EH region holding the previous statement. */
+ LTO_eh_region,
+
+ /* Function body. */
+ LTO_function,
+
+ /* EH table. */
+ LTO_eh_table,
+
+ /* EH region types. These mirror enum eh_region_type. */
+ LTO_ert_cleanup,
+ LTO_ert_try,
+ LTO_ert_allowed_exceptions,
+ LTO_ert_must_not_throw,
+
+ /* EH landing pad. */
+ LTO_eh_landing_pad,
+
+ /* EH try/catch node. */
+ LTO_eh_catch,
+
+ /* This tag must always be last. */
+ LTO_NUM_TAGS
+};
+
+
+/* Set of section types that are in an LTO file. This list will grow
+ as the number of IPA passes grows since each IPA pass will need its
+ own section type to store its summary information.
+
+ When adding a new section type, you must also extend the
+ LTO_SECTION_NAME array in lto-section-in.cc. */
+enum lto_section_type
+{
+ LTO_section_decls = 0,
+ LTO_section_function_body,
+ LTO_section_static_initializer,
+ LTO_section_symtab,
+ LTO_section_symtab_extension,
+ LTO_section_refs,
+ LTO_section_asm,
+ LTO_section_jump_functions,
+ LTO_section_ipa_pure_const,
+ LTO_section_ipa_reference,
+ LTO_section_ipa_profile,
+ LTO_section_symtab_nodes,
+ LTO_section_opts,
+ LTO_section_cgraph_opt_sum,
+ LTO_section_ipa_fn_summary,
+ LTO_section_ipcp_transform,
+ LTO_section_ipa_icf,
+ LTO_section_offload_table,
+ LTO_section_mode_table,
+ LTO_section_lto,
+ LTO_section_ipa_sra,
+ LTO_section_odr_types,
+ LTO_section_ipa_modref,
+ LTO_N_SECTION_TYPES /* Must be last. */
+};
+
+/* Indices to the various function, type and symbol streams. */
+enum lto_decl_stream_e_t
+{
+ LTO_DECL_STREAM = 0, /* Must be first. */
+ LTO_N_DECL_STREAMS
+};
+
+typedef enum ld_plugin_symbol_resolution ld_plugin_symbol_resolution_t;
+
+/* Return a char pointer to the start of a data stream for an lto pass
+ or function. The first parameter is the file data that contains
+ the information. The second parameter is the type of information
+ to be obtained. The third parameter is the name of the function
+ and is only used when finding a function body; otherwise it is
+ NULL. The fourth parameter is the length of the data returned. */
+typedef const char* (lto_get_section_data_f) (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *,
+ int,
+ size_t *);
+
+/* Return the data found from the above call. The first three
+ parameters are the same as above. The fourth parameter is the data
+ itself and the fifth is the length of the data. */
+typedef void (lto_free_section_data_f) (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *,
+ const char *,
+ size_t);
+
+/* The location cache holds expanded locations for streamed in trees.
+ This is done to reduce memory usage of libcpp linemap that strongly prefers
+ locations to be inserted in the source order. */
+
+class lto_location_cache
+{
+public:
+ /* Apply all changes in location cache. Add locations into linemap and patch
+ trees. */
+ bool apply_location_cache ();
+ /* Tree merging did not suceed; mark all changes in the cache as accepted. */
+ void accept_location_cache ();
+ /* Tree merging did suceed; throw away recent changes. */
+ void revert_location_cache ();
+ void input_location (location_t *loc, struct bitpack_d *bp,
+ class data_in *data_in);
+ void input_location_and_block (location_t *loc, struct bitpack_d *bp,
+ class lto_input_block *ib,
+ class data_in *data_in);
+ lto_location_cache ()
+ : loc_cache (), accepted_length (0), current_file (NULL), current_line (0),
+ current_col (0), current_sysp (false), current_loc (UNKNOWN_LOCATION),
+ current_block (NULL_TREE)
+ {
+ gcc_assert (!current_cache);
+ current_cache = this;
+ }
+ ~lto_location_cache ()
+ {
+ apply_location_cache ();
+ gcc_assert (current_cache == this);
+ current_cache = NULL;
+ }
+
+ /* There can be at most one instance of location cache (combining multiple
+ would bring it out of sync with libcpp linemap); point to current
+ one. */
+ static lto_location_cache *current_cache;
+
+private:
+ static int cmp_loc (const void *pa, const void *pb);
+
+ struct cached_location
+ {
+ const char *file;
+ location_t *loc;
+ int line, col;
+ bool sysp;
+ tree block;
+ };
+
+ /* The location cache. */
+
+ auto_vec<cached_location> loc_cache;
+
+ /* Accepted entries are ones used by trees that are known to be not unified
+ by tree merging. */
+
+ int accepted_length;
+
+ /* Bookkeeping to remember state in between calls to lto_apply_location_cache
+ When streaming gimple, the location cache is not used and thus
+ lto_apply_location_cache happens per location basis. It is then
+ useful to avoid redundant calls of linemap API. */
+
+ const char *current_file;
+ int current_line;
+ int current_col;
+ bool current_sysp;
+ location_t current_loc;
+ tree current_block;
+};
+
+/* Structure used as buffer for reading an LTO file. */
+class lto_input_block
+{
+public:
+ /* Special constructor for the string table, it abuses this to
+ do random access but use the uhwi decoder. */
+ lto_input_block (const char *data_, unsigned int p_, unsigned int len_,
+ const unsigned char *mode_table_)
+ : data (data_), mode_table (mode_table_), p (p_), len (len_) {}
+ lto_input_block (const char *data_, unsigned int len_,
+ const unsigned char *mode_table_)
+ : data (data_), mode_table (mode_table_), p (0), len (len_) {}
+
+ const char *data;
+ const unsigned char *mode_table;
+ unsigned int p;
+ unsigned int len;
+};
+
+/* Compression algorithm used for compression of LTO bytecode. */
+
+enum lto_compression
+{
+ ZLIB,
+ ZSTD
+};
+
+/* Structure that represents LTO ELF section with information
+ about the format. */
+
+struct lto_section
+{
+ int16_t major_version;
+ int16_t minor_version;
+ unsigned char slim_object;
+ unsigned char _padding;
+
+ /* Flags is a private field that is not defined publicly. */
+ uint16_t flags;
+
+ /* Set compression to FLAGS. */
+ inline void set_compression (lto_compression c)
+ {
+ flags = c;
+ }
+
+ /* Get compression from FLAGS. */
+ inline lto_compression get_compression ()
+ {
+ return (lto_compression) flags;
+ }
+};
+
+STATIC_ASSERT (sizeof (lto_section) == 8);
+
+/* The is the first part of the record in an LTO file for many of the
+ IPA passes. */
+struct lto_simple_header
+{
+ /* Size of main gimple body of function. */
+ int32_t main_size;
+};
+
+struct lto_simple_header_with_strings : lto_simple_header
+{
+ /* Size of the string table. */
+ int32_t string_size;
+};
+
+/* The header for a function body. */
+struct lto_function_header : lto_simple_header_with_strings
+{
+ /* Size of the cfg. */
+ int32_t cfg_size;
+};
+
+
+/* Structure describing a symbol section. */
+struct lto_decl_header : lto_simple_header_with_strings
+{
+ /* Size of region for decl state. */
+ int32_t decl_state_size;
+
+ /* Number of nodes in globals stream. */
+ int32_t num_nodes;
+};
+
+
+/* Statistics gathered during LTO, WPA and LTRANS. */
+struct lto_stats_d
+{
+ unsigned HOST_WIDE_INT num_input_cgraph_nodes;
+ unsigned HOST_WIDE_INT num_output_symtab_nodes;
+ unsigned HOST_WIDE_INT num_input_files;
+ unsigned HOST_WIDE_INT num_output_files;
+ unsigned HOST_WIDE_INT num_cgraph_partitions;
+ unsigned HOST_WIDE_INT section_size[LTO_N_SECTION_TYPES];
+ unsigned HOST_WIDE_INT num_function_bodies;
+ unsigned HOST_WIDE_INT num_trees[NUM_TREE_CODES];
+ unsigned HOST_WIDE_INT num_output_il_bytes;
+ unsigned HOST_WIDE_INT num_compressed_il_bytes;
+ unsigned HOST_WIDE_INT num_input_il_bytes;
+ unsigned HOST_WIDE_INT num_uncompressed_il_bytes;
+ unsigned HOST_WIDE_INT num_tree_bodies_output;
+ unsigned HOST_WIDE_INT num_pickle_refs_output;
+};
+
+/* Entry of LTO symtab encoder. */
+struct lto_encoder_entry
+{
+ symtab_node *node;
+ /* Is the node in this partition (i.e. ltrans of this partition will
+ be responsible for outputting it)? */
+ unsigned int in_partition:1;
+ /* Do we encode body in this partition? */
+ unsigned int body:1;
+ /* Do we encode initializer in this partition?
+ For example the readonly variable initializers are encoded to aid
+ constant folding even if they are not in the partition. */
+ unsigned int initializer:1;
+};
+
+
+/* Encoder data structure used to stream callgraph nodes. */
+struct lto_symtab_encoder_d
+{
+ vec<lto_encoder_entry> nodes;
+ hash_map<symtab_node *, size_t> *map;
+};
+
+typedef struct lto_symtab_encoder_d *lto_symtab_encoder_t;
+
+/* Iterator structure for cgraph node sets. */
+struct lto_symtab_encoder_iterator
+{
+ lto_symtab_encoder_t encoder;
+ unsigned index;
+};
+
+
+
+/* The lto_tree_ref_encoder struct is used to encode trees into indices. */
+
+struct lto_tree_ref_encoder
+{
+ hash_map<tree, unsigned> *tree_hash_table; /* Maps pointers to indices. */
+ vec<tree> trees; /* Maps indices to pointers. */
+};
+
+
+/* Structure to hold states of input scope. */
+struct GTY((for_user)) lto_in_decl_state
+{
+ /* Array of lto_in_decl_buffers to store type and decls streams. */
+ vec<tree, va_gc> *streams[LTO_N_DECL_STREAMS];
+
+ /* If this in-decl state is associated with a function. FN_DECL
+ point to the FUNCTION_DECL. */
+ tree fn_decl;
+
+ /* True if decl state is compressed. */
+ bool compressed;
+};
+
+typedef struct lto_in_decl_state *lto_in_decl_state_ptr;
+
+struct decl_state_hasher : ggc_ptr_hash<lto_in_decl_state>
+{
+ static hashval_t
+ hash (lto_in_decl_state *s)
+ {
+ return htab_hash_pointer (s->fn_decl);
+ }
+
+ static bool
+ equal (lto_in_decl_state *a, lto_in_decl_state *b)
+ {
+ return a->fn_decl == b->fn_decl;
+ }
+};
+
+/* The structure that holds all of the vectors of global types,
+ decls and cgraph nodes used in the serialization of this file. */
+struct lto_out_decl_state
+{
+ /* The buffers contain the sets of decls of various kinds and types we have
+ seen so far and the indexes assigned to them. */
+ struct lto_tree_ref_encoder streams[LTO_N_DECL_STREAMS];
+
+ /* Encoder for cgraph nodes. */
+ lto_symtab_encoder_t symtab_node_encoder;
+
+ /* If this out-decl state belongs to a function, fn_decl points to that
+ function. Otherwise, it is NULL. */
+ tree fn_decl;
+
+ /* True if decl state is compressed. */
+ bool compressed;
+};
+
+typedef struct lto_out_decl_state *lto_out_decl_state_ptr;
+
+
+/* Compact representation of a index <-> resolution pair. Unpacked to an
+ vector later. */
+struct res_pair
+{
+ ld_plugin_symbol_resolution_t res;
+ unsigned index;
+};
+
+
+/* One of these is allocated for each object file that being compiled
+ by lto. This structure contains the tables that are needed by the
+ serialized functions and ipa passes to connect themselves to the
+ global types and decls as they are reconstituted. */
+struct GTY(()) lto_file_decl_data
+{
+ /* Decl state currently used. */
+ struct lto_in_decl_state *current_decl_state;
+
+ /* Decl state corresponding to regions outside of any functions
+ in the compilation unit. */
+ struct lto_in_decl_state *global_decl_state;
+
+ /* Table of cgraph nodes present in this file. */
+ lto_symtab_encoder_t GTY((skip)) symtab_node_encoder;
+
+ /* Hash table maps lto-related section names to location in file. */
+ hash_table<decl_state_hasher> *function_decl_states;
+
+ /* The .o file that these offsets relate to. */
+ const char *GTY((skip)) file_name;
+
+ /* Hash table maps lto-related section names to location in file. */
+ htab_t GTY((skip)) section_hash_table;
+
+ /* Hash new name of renamed global declaration to its original name. */
+ htab_t GTY((skip)) renaming_hash_table;
+
+ /* Linked list used temporarily in reader */
+ struct lto_file_decl_data *next;
+
+ /* Order in which the file appears on the command line. */
+ int order;
+
+ /* Sub ID for merged objects. */
+ unsigned HOST_WIDE_INT id;
+
+ /* Symbol resolutions for this file */
+ vec<res_pair> GTY((skip)) respairs;
+ unsigned max_index;
+
+ // sdcpp
+ // gcov_summary GTY((skip)) profile_info;
+
+ /* Map assigning declarations their resolutions. */
+ hash_map<tree, ld_plugin_symbol_resolution> * GTY((skip)) resolution_map;
+
+ /* Mode translation table. */
+ const unsigned char *mode_table;
+
+ /* Read LTO section. */
+ lto_section lto_section_header;
+
+ int order_base;
+
+ int unit_base;
+};
+
+typedef struct lto_file_decl_data *lto_file_decl_data_ptr;
+
+struct lto_char_ptr_base
+{
+ char *ptr;
+};
+
+/* An incore byte stream to buffer the various parts of the function.
+ The entire structure should be zeroed when created. The record
+ consists of a set of blocks. The first sizeof (ptr) bytes are used
+ as a chain, and the rest store the bytes to be written. */
+struct lto_output_stream
+{
+ /* The pointer to the first block in the stream. */
+ struct lto_char_ptr_base * first_block;
+
+ /* The pointer to the last and current block in the stream. */
+ struct lto_char_ptr_base * current_block;
+
+ /* The pointer to where the next char should be written. */
+ char * current_pointer;
+
+ /* The number of characters left in the current block. */
+ unsigned int left_in_block;
+
+ /* The block size of the last block allocated. */
+ unsigned int block_size;
+
+ /* The total number of characters written. */
+ unsigned int total_size;
+};
+
+/* A simple output block. This can be used for simple IPA passes that
+ do not need more than one stream. */
+struct lto_simple_output_block
+{
+ enum lto_section_type section_type;
+ struct lto_out_decl_state *decl_state;
+
+ /* The stream that the main tree codes are written to. */
+ struct lto_output_stream *main_stream;
+};
+
+/* String hashing. */
+
+struct string_slot
+{
+ const char *s;
+ int len;
+ unsigned int slot_num;
+};
+
+/* Hashtable helpers. */
+
+struct string_slot_hasher : nofree_ptr_hash <string_slot>
+{
+ static inline hashval_t hash (const string_slot *);
+ static inline bool equal (const string_slot *, const string_slot *);
+};
+
+/* Returns a hash code for DS. Adapted from libiberty's htab_hash_string
+ to support strings that may not end in '\0'. */
+
+inline hashval_t
+string_slot_hasher::hash (const string_slot *ds)
+{
+ hashval_t r = ds->len;
+ int i;
+
+ for (i = 0; i < ds->len; i++)
+ r = r * 67 + (unsigned)ds->s[i] - 113;
+ return r;
+}
+
+/* Returns nonzero if DS1 and DS2 are equal. */
+
+inline bool
+string_slot_hasher::equal (const string_slot *ds1, const string_slot *ds2)
+{
+ if (ds1->len == ds2->len)
+ return memcmp (ds1->s, ds2->s, ds1->len) == 0;
+
+ return 0;
+}
+
+/* Data structure holding all the data and descriptors used when writing
+ an LTO file. */
+struct output_block
+{
+ enum lto_section_type section_type;
+ struct lto_out_decl_state *decl_state;
+
+ /* The stream that the main tree codes are written to. */
+ struct lto_output_stream *main_stream;
+
+ /* The stream that contains the string table. */
+ struct lto_output_stream *string_stream;
+
+ /* The stream that contains the cfg. */
+ struct lto_output_stream *cfg_stream;
+
+ /* The hash table that contains the set of strings we have seen so
+ far and the indexes assigned to them. */
+ hash_table<string_slot_hasher> *string_hash_table;
+
+ /* The current symbol that we are currently serializing. Null
+ if we are serializing something else. */
+ symtab_node *symbol;
+
+ /* These are the last file and line that were seen in the stream.
+ If the current node differs from these, it needs to insert
+ something into the stream and fix these up. */
+ const char *current_file;
+ int current_line;
+ int current_col;
+ bool current_sysp;
+ bool reset_locus;
+ bool emit_pwd;
+ tree current_block;
+
+ /* Cache of nodes written in this section. */
+ struct streamer_tree_cache_d *writer_cache;
+
+ /* All trees identified as local to the unit streamed. */
+ hash_set<tree> *local_trees;
+
+ /* All data persistent across whole duration of output block
+ can go here. */
+ struct obstack obstack;
+};
+
+
+/* Data and descriptors used when reading from an LTO file. */
+class data_in
+{
+public:
+ /* The global decls and types. */
+ struct lto_file_decl_data *file_data;
+
+ /* The string table. */
+ const char *strings;
+
+ /* The length of the string table. */
+ unsigned int strings_len;
+
+ /* Maps each reference number to the resolution done by the linker. */
+ vec<ld_plugin_symbol_resolution_t> globals_resolution;
+
+ /* Cache of pickled nodes. */
+ struct streamer_tree_cache_d *reader_cache;
+
+ /* Cache of source code location. */
+ lto_location_cache location_cache;
+};
+
+
+/* In lto-section-in.cc */
+extern class lto_input_block * lto_create_simple_input_block (
+ struct lto_file_decl_data *,
+ enum lto_section_type, const char **, size_t *);
+extern void
+lto_destroy_simple_input_block (struct lto_file_decl_data *,
+ enum lto_section_type,
+ class lto_input_block *, const char *, size_t);
+extern void lto_set_in_hooks (struct lto_file_decl_data **,
+ lto_get_section_data_f *,
+ lto_free_section_data_f *);
+extern struct lto_file_decl_data **lto_get_file_decl_data (void);
+extern const char *lto_get_section_data (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *, int, size_t *,
+ bool decompress = false);
+extern const char *lto_get_summary_section_data (struct lto_file_decl_data *,
+ enum lto_section_type,
+ size_t *);
+extern const char *lto_get_raw_section_data (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *, int, size_t *);
+extern void lto_free_section_data (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *, const char *, size_t,
+ bool decompress = false);
+extern void lto_free_raw_section_data (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *, const char *, size_t);
+extern htab_t lto_create_renaming_table (void);
+extern void lto_record_renamed_decl (struct lto_file_decl_data *,
+ const char *, const char *);
+extern const char *lto_get_decl_name_mapping (struct lto_file_decl_data *,
+ const char *);
+extern struct lto_in_decl_state *lto_new_in_decl_state (void);
+extern void lto_delete_in_decl_state (struct lto_in_decl_state *);
+extern struct lto_in_decl_state *lto_get_function_in_decl_state (
+ struct lto_file_decl_data *, tree);
+extern void lto_free_function_in_decl_state (struct lto_in_decl_state *);
+extern void lto_free_function_in_decl_state_for_node (symtab_node *);
+extern void lto_section_overrun (class lto_input_block *) ATTRIBUTE_NORETURN;
+extern void lto_value_range_error (const char *,
+ HOST_WIDE_INT, HOST_WIDE_INT,
+ HOST_WIDE_INT) ATTRIBUTE_NORETURN;
+
+/* In lto-section-out.cc */
+extern void lto_begin_section (const char *, bool);
+extern void lto_end_section (void);
+extern void lto_write_data (const void *, unsigned int);
+extern void lto_write_raw_data (const void *, unsigned int);
+extern void lto_write_stream (struct lto_output_stream *);
+extern struct lto_simple_output_block *lto_create_simple_output_block (
+ enum lto_section_type);
+extern void lto_destroy_simple_output_block (struct lto_simple_output_block *);
+extern struct lto_out_decl_state *lto_new_out_decl_state (void);
+extern void lto_delete_out_decl_state (struct lto_out_decl_state *);
+extern struct lto_out_decl_state *lto_get_out_decl_state (void);
+extern void lto_push_out_decl_state (struct lto_out_decl_state *);
+extern struct lto_out_decl_state *lto_pop_out_decl_state (void);
+extern void lto_record_function_out_decl_state (tree,
+ struct lto_out_decl_state *);
+extern void lto_append_block (struct lto_output_stream *);
+
+
+/* In lto-streamer.cc. */
+
+/* Set when streaming LTO for offloading compiler. */
+extern bool lto_stream_offload_p;
+
+extern const char *lto_tag_name (enum LTO_tags);
+extern char *lto_get_section_name (int, const char *, int,
+ struct lto_file_decl_data *);
+extern void print_lto_report (const char *);
+extern void lto_streamer_init (void);
+extern bool gate_lto_out (void);
+extern void lto_check_version (int, int, const char *);
+extern void lto_streamer_hooks_init (void);
+
+/* In lto-streamer-in.cc */
+extern void lto_input_cgraph (struct lto_file_decl_data *, const char *);
+extern void lto_reader_init (void);
+extern void lto_free_file_name_hash (void);
+extern void lto_input_function_body (struct lto_file_decl_data *,
+ struct cgraph_node *,
+ const char *);
+extern void lto_input_variable_constructor (struct lto_file_decl_data *,
+ struct varpool_node *,
+ const char *);
+extern void lto_input_constructors_and_inits (struct lto_file_decl_data *,
+ const char *);
+extern void lto_input_toplevel_asms (struct lto_file_decl_data *, int);
+extern void lto_input_mode_table (struct lto_file_decl_data *);
+extern class data_in *lto_data_in_create (struct lto_file_decl_data *,
+ const char *, unsigned,
+ vec<ld_plugin_symbol_resolution_t> );
+extern void lto_data_in_delete (class data_in *);
+extern void lto_input_data_block (class lto_input_block *, void *, size_t);
+void lto_input_location (location_t *, struct bitpack_d *, class data_in *);
+tree lto_input_tree_ref (class lto_input_block *, class data_in *,
+ struct function *, enum LTO_tags);
+void lto_tag_check_set (enum LTO_tags, int, ...);
+void lto_init_eh (void);
+hashval_t lto_input_scc (class lto_input_block *, class data_in *,
+ unsigned *, unsigned *, bool);
+tree lto_input_tree_1 (class lto_input_block *, class data_in *,
+ enum LTO_tags, hashval_t hash);
+tree lto_input_tree (class lto_input_block *, class data_in *);
+tree stream_read_tree_ref (class lto_input_block *, class data_in *);
+
+
+/* In lto-streamer-out.cc */
+extern void lto_register_decl_definition (tree, struct lto_file_decl_data *);
+extern struct output_block *create_output_block (enum lto_section_type);
+extern void destroy_output_block (struct output_block *);
+extern void lto_output_tree (struct output_block *, tree, bool, bool);
+extern void stream_write_tree_ref (struct output_block *, tree);
+extern void lto_output_var_decl_ref (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+extern void lto_output_fn_decl_ref (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+extern tree lto_input_var_decl_ref (lto_input_block *, lto_file_decl_data *);
+extern tree lto_input_fn_decl_ref (lto_input_block *, lto_file_decl_data *);
+extern void lto_output_toplevel_asms (void);
+extern void produce_asm (struct output_block *ob, tree fn);
+extern void lto_output ();
+extern void produce_asm_for_decls ();
+void lto_output_decl_state_streams (struct output_block *,
+ struct lto_out_decl_state *);
+void lto_output_decl_state_refs (struct output_block *,
+ struct lto_output_stream *,
+ struct lto_out_decl_state *);
+void lto_output_location (struct output_block *, struct bitpack_d *,
+ location_t);
+void lto_output_location_and_block (struct output_block *, struct bitpack_d *,
+ location_t);
+void lto_output_init_mode_table (void);
+void lto_prepare_function_for_streaming (cgraph_node *);
+
+
+/* In lto-cgraph.cc */
+extern bool asm_nodes_output;
+lto_symtab_encoder_t lto_symtab_encoder_new (bool);
+int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node *);
+void lto_symtab_encoder_delete (lto_symtab_encoder_t);
+bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node *);
+bool lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t,
+ struct cgraph_node *);
+bool lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t,
+ symtab_node *);
+void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t,
+ symtab_node *);
+
+bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t,
+ varpool_node *);
+void output_symtab (void);
+void input_symtab (void);
+void output_offload_tables (void);
+void input_offload_tables (bool);
+bool referenced_from_other_partition_p (struct ipa_ref_list *,
+ lto_symtab_encoder_t);
+bool reachable_from_other_partition_p (struct cgraph_node *,
+ lto_symtab_encoder_t);
+bool referenced_from_this_partition_p (symtab_node *,
+ lto_symtab_encoder_t);
+bool reachable_from_this_partition_p (struct cgraph_node *,
+ lto_symtab_encoder_t);
+lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
+void select_what_to_stream (void);
+
+/* In omp-general.cc. */
+void omp_lto_output_declare_variant_alt (lto_simple_output_block *,
+ cgraph_node *, lto_symtab_encoder_t);
+void omp_lto_input_declare_variant_alt (lto_input_block *, cgraph_node *,
+ vec<symtab_node *>);
+
+/* In options-save.cc. */
+void cl_target_option_stream_out (struct output_block *, struct bitpack_d *,
+ struct cl_target_option *);
+
+void cl_target_option_stream_in (class data_in *,
+ struct bitpack_d *,
+ struct cl_target_option *);
+
+void cl_optimization_stream_out (struct output_block *,
+ struct bitpack_d *, struct cl_optimization *);
+
+void cl_optimization_stream_in (class data_in *,
+ struct bitpack_d *, struct cl_optimization *);
+
+
+
+/* In lto-opts.cc. */
+extern void lto_write_options (void);
+
+
+/* Statistics gathered during LTO, WPA and LTRANS. */
+extern struct lto_stats_d lto_stats;
+
+/* Section names corresponding to the values of enum lto_section_type. */
+extern const char *lto_section_name[];
+
+/* Holds all the out decl states of functions output so far in the
+ current output file. */
+extern vec<lto_out_decl_state_ptr> lto_function_decl_states;
+
+/* Return true if LTO tag TAG corresponds to a tree code. */
+static inline bool
+lto_tag_is_tree_code_p (enum LTO_tags tag)
+{
+ return tag > LTO_first_tree_tag && (unsigned) tag <= MAX_TREE_CODES;
+}
+
+
+/* Return true if LTO tag TAG corresponds to a gimple code. */
+static inline bool
+lto_tag_is_gimple_code_p (enum LTO_tags tag)
+{
+ return (unsigned) tag >= LTO_first_gimple_tag
+ && (unsigned) tag
+ < LTO_first_gimple_tag + LAST_AND_UNUSED_GIMPLE_CODE;
+}
+
+
+/* Return the LTO tag corresponding to gimple code CODE. See enum
+ LTO_tags for details on the conversion. */
+static inline enum LTO_tags
+lto_gimple_code_to_tag (enum gimple_code code)
+{
+ return (enum LTO_tags) ((unsigned) code + LTO_first_gimple_tag);
+}
+
+
+/* Return the GIMPLE code corresponding to TAG. See enum LTO_tags for
+ details on the conversion. */
+static inline enum gimple_code
+lto_tag_to_gimple_code (enum LTO_tags tag)
+{
+ gcc_assert (lto_tag_is_gimple_code_p (tag));
+ return (enum gimple_code) ((unsigned) tag - LTO_first_gimple_tag);
+}
+
+
+/* Return the LTO tag corresponding to tree code CODE. See enum
+ LTO_tags for details on the conversion. */
+static inline enum LTO_tags
+lto_tree_code_to_tag (enum tree_code code)
+{
+ return (enum LTO_tags) ((unsigned) code + LTO_first_tree_tag);
+}
+
+
+/* Return the tree code corresponding to TAG. See enum LTO_tags for
+ details on the conversion. */
+static inline enum tree_code
+lto_tag_to_tree_code (enum LTO_tags tag)
+{
+ gcc_assert (lto_tag_is_tree_code_p (tag));
+ return (enum tree_code) ((unsigned) tag - LTO_first_tree_tag);
+}
+
+/* Check that tag ACTUAL == EXPECTED. */
+static inline void
+lto_tag_check (enum LTO_tags actual, enum LTO_tags expected)
+{
+ if (actual != expected)
+ internal_error ("bytecode stream: expected tag %s instead of %s",
+ lto_tag_name (expected), lto_tag_name (actual));
+}
+
+/* Check that tag ACTUAL is in the range [TAG1, TAG2]. */
+static inline void
+lto_tag_check_range (enum LTO_tags actual, enum LTO_tags tag1,
+ enum LTO_tags tag2)
+{
+ if (actual < tag1 || actual > tag2)
+ internal_error ("bytecode stream: tag %s is not in the expected range "
+ "[%s, %s]",
+ lto_tag_name (actual),
+ lto_tag_name (tag1),
+ lto_tag_name (tag2));
+}
+
+/* Initialize an lto_out_decl_buffer ENCODER. */
+static inline void
+lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder)
+{
+ encoder->tree_hash_table = new hash_map<tree, unsigned> (251);
+ encoder->trees.create (0);
+}
+
+
+/* Destroy an lto_tree_ref_encoder ENCODER by freeing its contents. The
+ memory used by ENCODER is not freed by this function. */
+static inline void
+lto_destroy_tree_ref_encoder (struct lto_tree_ref_encoder *encoder)
+{
+ /* Hash table may be delete already. */
+ delete encoder->tree_hash_table;
+ encoder->tree_hash_table = NULL;
+ encoder->trees.release ();
+}
+
+/* Return the number of trees encoded in ENCODER. */
+static inline unsigned int
+lto_tree_ref_encoder_size (struct lto_tree_ref_encoder *encoder)
+{
+ return encoder->trees.length ();
+}
+
+/* Return the IDX-th tree in ENCODER. */
+static inline tree
+lto_tree_ref_encoder_get_tree (struct lto_tree_ref_encoder *encoder,
+ unsigned int idx)
+{
+ return encoder->trees[idx];
+}
+
+/* Return number of encoded nodes in ENCODER. */
+static inline int
+lto_symtab_encoder_size (lto_symtab_encoder_t encoder)
+{
+ return encoder->nodes.length ();
+}
+
+/* Value used to represent failure of lto_symtab_encoder_lookup. */
+#define LCC_NOT_FOUND (-1)
+
+/* Look up NODE in encoder. Return NODE's reference if it has been encoded
+ or LCC_NOT_FOUND if it is not there. */
+
+static inline int
+lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder,
+ symtab_node *node)
+{
+ size_t *slot = encoder->map->get (node);
+ return (slot && *slot ? *(slot) - 1 : LCC_NOT_FOUND);
+}
+
+/* Return true if iterator LSE points to nothing. */
+static inline bool
+lsei_end_p (lto_symtab_encoder_iterator lsei)
+{
+ return lsei.index >= (unsigned)lto_symtab_encoder_size (lsei.encoder);
+}
+
+/* Advance iterator LSE. */
+static inline void
+lsei_next (lto_symtab_encoder_iterator *lsei)
+{
+ lsei->index++;
+}
+
+/* Return the node pointed to by LSI. */
+static inline symtab_node *
+lsei_node (lto_symtab_encoder_iterator lsei)
+{
+ return lsei.encoder->nodes[lsei.index].node;
+}
+
+/* Return the node pointed to by LSI. */
+static inline struct cgraph_node *
+lsei_cgraph_node (lto_symtab_encoder_iterator lsei)
+{
+ return dyn_cast<cgraph_node *> (lsei.encoder->nodes[lsei.index].node);
+}
+
+/* Return the node pointed to by LSI. */
+static inline varpool_node *
+lsei_varpool_node (lto_symtab_encoder_iterator lsei)
+{
+ return dyn_cast<varpool_node *> (lsei.encoder->nodes[lsei.index].node);
+}
+
+/* Return the cgraph node corresponding to REF using ENCODER. */
+
+static inline symtab_node *
+lto_symtab_encoder_deref (lto_symtab_encoder_t encoder, int ref)
+{
+ if (ref == LCC_NOT_FOUND)
+ return NULL;
+
+ return encoder->nodes[ref].node;
+}
+
+/* Return an iterator to the first node in LSI. */
+static inline lto_symtab_encoder_iterator
+lsei_start (lto_symtab_encoder_t encoder)
+{
+ lto_symtab_encoder_iterator lsei;
+
+ lsei.encoder = encoder;
+ lsei.index = 0;
+ return lsei;
+}
+
+/* Advance iterator LSE. */
+static inline void
+lsei_next_in_partition (lto_symtab_encoder_iterator *lsei)
+{
+ lsei_next (lsei);
+ while (!lsei_end_p (*lsei)
+ && !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei)))
+ lsei_next (lsei);
+}
+
+/* Return an iterator to the first node in LSI. */
+static inline lto_symtab_encoder_iterator
+lsei_start_in_partition (lto_symtab_encoder_t encoder)
+{
+ lto_symtab_encoder_iterator lsei = lsei_start (encoder);
+
+ if (lsei_end_p (lsei))
+ return lsei;
+ if (!lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
+ lsei_next_in_partition (&lsei);
+
+ return lsei;
+}
+
+/* Advance iterator LSE. */
+static inline void
+lsei_next_function_in_partition (lto_symtab_encoder_iterator *lsei)
+{
+ lsei_next (lsei);
+ while (!lsei_end_p (*lsei)
+ && (!is_a <cgraph_node *> (lsei_node (*lsei))
+ || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei))))
+ lsei_next (lsei);
+}
+
+/* Return an iterator to the first node in LSI. */
+static inline lto_symtab_encoder_iterator
+lsei_start_function_in_partition (lto_symtab_encoder_t encoder)
+{
+ lto_symtab_encoder_iterator lsei = lsei_start (encoder);
+
+ if (lsei_end_p (lsei))
+ return lsei;
+ if (!is_a <cgraph_node *> (lsei_node (lsei))
+ || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
+ lsei_next_function_in_partition (&lsei);
+
+ return lsei;
+}
+
+/* Advance iterator LSE. */
+static inline void
+lsei_next_variable_in_partition (lto_symtab_encoder_iterator *lsei)
+{
+ lsei_next (lsei);
+ while (!lsei_end_p (*lsei)
+ && (!is_a <varpool_node *> (lsei_node (*lsei))
+ || !lto_symtab_encoder_in_partition_p (lsei->encoder, lsei_node (*lsei))))
+ lsei_next (lsei);
+}
+
+/* Return an iterator to the first node in LSI. */
+static inline lto_symtab_encoder_iterator
+lsei_start_variable_in_partition (lto_symtab_encoder_t encoder)
+{
+ lto_symtab_encoder_iterator lsei = lsei_start (encoder);
+
+ if (lsei_end_p (lsei))
+ return lsei;
+ if (!is_a <varpool_node *> (lsei_node (lsei))
+ || !lto_symtab_encoder_in_partition_p (encoder, lsei_node (lsei)))
+ lsei_next_variable_in_partition (&lsei);
+
+ return lsei;
+}
+
+/* Entry for the delayed registering of decl -> DIE references. */
+struct dref_entry {
+ tree decl;
+ const char *sym;
+ unsigned HOST_WIDE_INT off;
+};
+
+extern vec<dref_entry> dref_queue;
+
+extern FILE *streamer_dump_file;
+
+#endif /* GCC_LTO_STREAMER_H */
diff --git a/support/cpp/gcc/machmode.def b/support/cpp/gcc/machmode.def
new file mode 100644
index 000000000..b62a5fbc6
--- /dev/null
+++ b/support/cpp/gcc/machmode.def
@@ -0,0 +1,283 @@
+/* This file contains the definitions and documentation for the
+ machine modes used in the 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/>. */
+
+
+/* This file defines all the MACHINE MODES used by GCC.
+
+ A machine mode specifies a size and format of data
+ at the machine level.
+
+ Each RTL expression has a machine mode.
+
+ At the syntax tree level, each ..._TYPE and each ..._DECL node
+ has a machine mode which describes data of that type or the
+ data of the variable declared. */
+
+/* This file is included by the genmodes program. Its text is the
+ body of a function. Do not rely on this, it will change in the
+ future.
+
+ The following statements can be used in this file -- all have
+ the form of a C macro call. In their arguments:
+
+ A CLASS argument must be one of the constants defined in
+ mode-classes.def, less the leading MODE_ prefix; some statements
+ that take CLASS arguments have restrictions on which classes are
+ acceptable. For instance, INT.
+
+ A MODE argument must be the printable name of a machine mode,
+ without quotation marks or trailing "mode". For instance, SI.
+
+ A PRECISION, BYTESIZE, or COUNT argument must be a positive integer
+ constant.
+
+ A FORMAT argument must be one of the real_mode_format structures
+ declared in real.h, or else a literal 0. Do not put a leading &
+ on the argument.
+
+ An EXPR argument must be a syntactically valid C expression.
+ If an EXPR contains commas, you may need to write an extra pair of
+ parentheses around it, so it appears to be a single argument to the
+ statement.
+
+ This file defines only those modes which are of use on almost all
+ machines. Other modes can be defined in the target-specific
+ mode definition file, config/ARCH/ARCH-modes.def.
+
+ Order matters in this file in so far as statements which refer to
+ other modes must appear after the modes they refer to. However,
+ statements which do not refer to other modes may appear in any
+ order.
+
+ RANDOM_MODE (MODE);
+ declares MODE to be of class RANDOM.
+
+ CC_MODE (MODE);
+ declares MODE to be of class CC.
+
+ INT_MODE (MODE, BYTESIZE);
+ declares MODE to be of class INT and BYTESIZE bytes wide.
+ All of the bits of its representation are significant.
+
+ FRACTIONAL_INT_MODE (MODE, PRECISION, BYTESIZE);
+ declares MODE to be of class INT, BYTESIZE bytes wide in
+ storage, but with only PRECISION significant bits.
+
+ FLOAT_MODE (MODE, BYTESIZE, FORMAT);
+ declares MODE to be of class FLOAT and BYTESIZE bytes wide,
+ using floating point format FORMAT.
+ All of the bits of its representation are significant.
+
+ FRACTIONAL_FLOAT_MODE (MODE, PRECISION, BYTESIZE, FORMAT);
+ declares MODE to be of class FLOAT, BYTESIZE bytes wide in
+ storage, but with only PRECISION significant bits, using
+ floating point format FORMAT.
+
+ DECIMAL_FLOAT_MODE (MODE, BYTESIZE, FORMAT);
+ declares MODE to be of class DECIMAL_FLOAT and BYTESIZE bytes
+ wide. All of the bits of its representation are significant.
+
+ FRACTIONAL_DECIMAL_FLOAT_MODE (MODE, BYTESIZE, FORMAT);
+ declares MODE to be of class DECIMAL_FLOAT and BYTESIZE bytes
+ wide. All of the bits of its representation are significant.
+
+ FRACT_MODE (MODE, BYTESIZE, FBIT);
+ declares MODE to be of class FRACT and BYTESIZE bytes wide
+ with FBIT fractional bits. There may be padding bits.
+
+ UFRACT_MODE (MODE, BYTESIZE, FBIT);
+ declares MODE to be of class UFRACT and BYTESIZE bytes wide
+ with FBIT fractional bits. There may be padding bits.
+
+ ACCUM_MODE (MODE, BYTESIZE, IBIT, FBIT);
+ declares MODE to be of class ACCUM and BYTESIZE bytes wide
+ with IBIT integral bits and FBIT fractional bits.
+ There may be padding bits.
+
+ UACCUM_MODE (MODE, BYTESIZE, IBIT, FBIT);
+ declares MODE to be of class UACCUM and BYTESIZE bytes wide
+ with IBIT integral bits and FBIT fractional bits.
+ There may be padding bits.
+
+ RESET_FLOAT_FORMAT (MODE, FORMAT);
+ changes the format of MODE, which must be class FLOAT,
+ to FORMAT. Use in an ARCH-modes.def to reset the format
+ of one of the float modes defined in this file.
+
+ PARTIAL_INT_MODE (MODE, PRECISION, NAME);
+ declares a mode of class PARTIAL_INT with the same size as
+ MODE (which must be an INT mode) and precision PREC.
+ Optionally, NAME is the new name of the mode. NAME is the
+ name of the mode.
+
+ VECTOR_MODE (CLASS, MODE, COUNT);
+ Declare a vector mode whose component mode is MODE (of class
+ CLASS) with COUNT components. CLASS must be INT or FLOAT.
+ The name of the vector mode takes the form VnX where n is
+ COUNT in decimal and X is MODE.
+
+ VECTOR_MODES (CLASS, WIDTH);
+ For all modes presently declared in class CLASS, construct
+ corresponding vector modes having width WIDTH. Modes whose
+ byte sizes do not evenly divide WIDTH are ignored, as are
+ modes that would produce vector modes with only one component,
+ and modes smaller than one byte (if CLASS is INT) or smaller
+ than two bytes (if CLASS is FLOAT). CLASS must be INT or
+ FLOAT. The names follow the same rule as VECTOR_MODE uses.
+
+ VECTOR_MODES_WITH_PREFIX (PREFIX, CLASS, WIDTH);
+ Like VECTOR_MODES, but start the mode names with PREFIX instead
+ of the usual "V".
+
+ VECTOR_BOOL_MODE (NAME, COUNT, COMPONENT, BYTESIZE)
+ Create a vector mode called NAME that contains COUNT boolean
+ elements and occupies BYTESIZE bytes in total. Each boolean
+ element is of COMPONENT type and occupies (COUNT * BITS_PER_UNIT) /
+ BYTESIZE bits, with the element at index 0 occupying the lsb of the
+ first byte in memory. Only the lowest bit of each element is
+ significant.
+
+ OPAQUE_MODE (NAME, BYTESIZE)
+ Create an opaque mode called NAME that is BYTESIZE bytes wide.
+
+ COMPLEX_MODES (CLASS);
+ For all modes presently declared in class CLASS, construct
+ corresponding complex modes. Modes smaller than one byte
+ are ignored. For FLOAT modes, the names are derived by
+ replacing the 'F' in the mode name with a 'C'. (It is an
+ error if there is no 'F'. For INT modes, the names are
+ derived by prefixing a C to the name.
+
+ ADJUST_BYTESIZE (MODE, EXPR);
+ ADJUST_ALIGNMENT (MODE, EXPR);
+ ADJUST_FLOAT_FORMAT (MODE, EXPR);
+ ADJUST_IBIT (MODE, EXPR);
+ ADJUST_FBIT (MODE, EXPR);
+ Arrange for the byte size, alignment, floating point format, ibit,
+ or fbit of MODE to be adjustable at run time. EXPR will be executed
+ once after processing all command line options, and should
+ evaluate to the desired byte size, alignment, format, ibit or fbit.
+
+ Unlike a FORMAT argument, if you are adjusting a float format
+ you must put an & in front of the name of each format structure.
+
+ ADJUST_NUNITS (MODE, EXPR);
+ Like the above, but set the number of nunits of MODE to EXPR.
+ This changes the size and precision of the mode in proportion
+ to the change in the number of units; for example, doubling
+ the number of units doubles the size and precision as well.
+
+ Note: If a mode is ever made which is more than 255 bytes wide,
+ machmode.h and genmodes.cc will have to be changed to allocate
+ more space for the mode_size and mode_alignment arrays. */
+
+/* VOIDmode is used when no mode needs to be specified,
+ as for example on CONST_INT RTL expressions. */
+RANDOM_MODE (VOID);
+
+/* BLKmode is used for structures, arrays, etc.
+ that fit no more specific mode. */
+RANDOM_MODE (BLK);
+
+/* Single bit mode used for booleans. */
+BOOL_MODE (BI, 1, 1);
+
+/* Basic integer modes. We go up to TI in generic code (128 bits).
+ TImode is needed here because the some front ends now genericly
+ support __int128. If the front ends decide to generically support
+ larger types, then corresponding modes must be added here. The
+ name OI is reserved for a 256-bit type (needed by some back ends).
+ */
+INT_MODE (QI, 1);
+INT_MODE (HI, 2);
+INT_MODE (SI, 4);
+INT_MODE (DI, 8);
+INT_MODE (TI, 16);
+
+/* No partial integer modes are defined by default. */
+
+/* The target normally defines any target-specific __intN types and
+ their modes, but __int128 for TImode is fairly common so define it
+ here. The type will not be created unless the target supports
+ TImode. */
+
+INT_N (TI, 128);
+
+/* Basic floating point modes. SF and DF are the only modes provided
+ by default. The names QF, HF, XF, and TF are reserved for targets
+ that need 1-word, 2-word, 80-bit, or 128-bit float types respectively.
+
+ These are the IEEE mappings. They can be overridden with
+ RESET_FLOAT_FORMAT or at runtime (in TARGET_OPTION_OVERRIDE). */
+
+FLOAT_MODE (SF, 4, ieee_single_format);
+FLOAT_MODE (DF, 8, ieee_double_format);
+
+/* Basic CC modes.
+ FIXME define this only for targets that need it. */
+CC_MODE (CC);
+
+/* Fixed-point modes. */
+FRACT_MODE (QQ, 1, 7); /* s.7 */
+FRACT_MODE (HQ, 2, 15); /* s.15 */
+FRACT_MODE (SQ, 4, 31); /* s.31 */
+FRACT_MODE (DQ, 8, 63); /* s.63 */
+FRACT_MODE (TQ, 16, 127); /* s.127 */
+
+UFRACT_MODE (UQQ, 1, 8); /* .8 */
+UFRACT_MODE (UHQ, 2, 16); /* .16 */
+UFRACT_MODE (USQ, 4, 32); /* .32 */
+UFRACT_MODE (UDQ, 8, 64); /* .64 */
+UFRACT_MODE (UTQ, 16, 128); /* .128 */
+
+ACCUM_MODE (HA, 2, 8, 7); /* s8.7 */
+ACCUM_MODE (SA, 4, 16, 15); /* s16.15 */
+ACCUM_MODE (DA, 8, 32, 31); /* s32.31 */
+ACCUM_MODE (TA, 16, 64, 63); /* s64.63 */
+
+UACCUM_MODE (UHA, 2, 8, 8); /* 8.8 */
+UACCUM_MODE (USA, 4, 16, 16); /* 16.16 */
+UACCUM_MODE (UDA, 8, 32, 32); /* 32.32 */
+UACCUM_MODE (UTA, 16, 64, 64); /* 64.64 */
+
+/* Allow the target to specify additional modes of various kinds. */
+#if HAVE_EXTRA_MODES
+# include EXTRA_MODES_FILE
+#endif
+
+/* Complex modes. */
+COMPLEX_MODES (INT);
+COMPLEX_MODES (PARTIAL_INT);
+COMPLEX_MODES (FLOAT);
+
+/* Decimal floating point modes. */
+DECIMAL_FLOAT_MODE (SD, 4, decimal_single_format);
+DECIMAL_FLOAT_MODE (DD, 8, decimal_double_format);
+DECIMAL_FLOAT_MODE (TD, 16, decimal_quad_format);
+
+/* The symbol Pmode stands for one of the above machine modes (usually SImode).
+ The tm.h file specifies which one. It is not a distinct mode. */
+
+/*
+Local variables:
+mode:c
+version-control: t
+End:
+*/
diff --git a/support/cpp/gcc/machmode.h b/support/cpp/gcc/machmode.h
new file mode 100644
index 000000000..b89765c0f
--- /dev/null
+++ b/support/cpp/gcc/machmode.h
@@ -0,0 +1,1217 @@
+/* Machine mode definitions for GCC; included by rtl.h and tree.h.
+ Copyright (C) 1991-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 HAVE_MACHINE_MODES
+#define HAVE_MACHINE_MODES
+
+typedef opt_mode<machine_mode> opt_machine_mode;
+
+// sdcpp extern CONST_MODE_SIZE poly_uint16_pod mode_size[NUM_MACHINE_MODES];
+// sdcpp extern CONST_MODE_PRECISION poly_uint16_pod mode_precision[NUM_MACHINE_MODES];
+extern const unsigned char mode_inner[NUM_MACHINE_MODES];
+// sdcpp extern CONST_MODE_NUNITS poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];
+// sdcpp extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
+// sdcpp extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
+// sdcpp extern const unsigned char mode_wider[NUM_MACHINE_MODES];
+// sdcpp extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
+
+template<typename T>
+struct mode_traits
+{
+ /* For use by the machmode support code only.
+
+ There are cases in which the machmode support code needs to forcibly
+ convert a machine_mode to a specific mode class T, and in which the
+ context guarantees that this is valid without the need for an assert.
+ This can be done using:
+
+ return typename mode_traits<T>::from_int (mode);
+
+ when returning a T and:
+
+ res = T (typename mode_traits<T>::from_int (mode));
+
+ when assigning to a value RES that must be assignment-compatible
+ with (but possibly not the same as) T. */
+#ifdef USE_ENUM_MODES
+ /* Allow direct conversion of enums to specific mode classes only
+ when USE_ENUM_MODES is defined. This is only intended for use
+ by gencondmd, so that it can tell more easily when .md conditions
+ are always false. */
+ typedef machine_mode from_int;
+#else
+ /* Here we use an enum type distinct from machine_mode but with the
+ same range as machine_mode. T should have a constructor that
+ accepts this enum type; it should not have a constructor that
+ accepts machine_mode.
+
+ We use this somewhat indirect approach to avoid too many constructor
+ calls when the compiler is built with -O0. For example, even in
+ unoptimized code, the return statement above would construct the
+ returned T directly from the numerical value of MODE. */
+ enum from_int { dummy = MAX_MACHINE_MODE };
+#endif
+};
+
+template<>
+struct mode_traits<machine_mode>
+{
+ /* machine_mode itself needs no conversion. */
+ typedef machine_mode from_int;
+};
+
+/* Always treat machine modes as fixed-size while compiling code specific
+ to targets that have no variable-size modes. */
+#if defined (IN_TARGET_CODE) && NUM_POLY_INT_COEFFS == 1
+#define ONLY_FIXED_SIZE_MODES 1
+#else
+#define ONLY_FIXED_SIZE_MODES 0
+#endif
+
+/* Get the name of mode MODE as a string. */
+
+extern const char * const mode_name[NUM_MACHINE_MODES];
+#define GET_MODE_NAME(MODE) mode_name[MODE]
+
+/* Mode classes. */
+
+#include "mode-classes.def"
+#define DEF_MODE_CLASS(M) M
+enum mode_class { MODE_CLASSES, MAX_MODE_CLASS };
+#undef DEF_MODE_CLASS
+#undef MODE_CLASSES
+
+/* Get the general kind of object that mode MODE represents
+ (integer, floating, complex, etc.) */
+
+extern const unsigned char mode_class[NUM_MACHINE_MODES];
+#define GET_MODE_CLASS(MODE) ((enum mode_class) mode_class[MODE])
+
+/* Nonzero if MODE is an integral mode. */
+#define INTEGRAL_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_INT \
+ || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
+
+/* Nonzero if MODE is a floating-point mode. */
+#define FLOAT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT)
+
+/* Nonzero if MODE is a complex mode. */
+#define COMPLEX_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
+
+/* Nonzero if MODE is a vector mode. */
+#define VECTOR_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_ACCUM \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_UACCUM)
+
+/* Nonzero if MODE is a scalar integral mode. */
+#define SCALAR_INT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_INT \
+ || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT)
+
+/* Nonzero if MODE is a scalar floating point mode. */
+#define SCALAR_FLOAT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
+
+/* Nonzero if MODE is a decimal floating point mode. */
+#define DECIMAL_FLOAT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
+
+/* Nonzero if MODE is a scalar fract mode. */
+#define SCALAR_FRACT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_FRACT)
+
+/* Nonzero if MODE is a scalar ufract mode. */
+#define SCALAR_UFRACT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_UFRACT)
+
+/* Nonzero if MODE is a scalar fract or ufract mode. */
+#define ALL_SCALAR_FRACT_MODE_P(MODE) \
+ (SCALAR_FRACT_MODE_P (MODE) || SCALAR_UFRACT_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar accum mode. */
+#define SCALAR_ACCUM_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_ACCUM)
+
+/* Nonzero if MODE is a scalar uaccum mode. */
+#define SCALAR_UACCUM_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_UACCUM)
+
+/* Nonzero if MODE is a scalar accum or uaccum mode. */
+#define ALL_SCALAR_ACCUM_MODE_P(MODE) \
+ (SCALAR_ACCUM_MODE_P (MODE) || SCALAR_UACCUM_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar fract or accum mode. */
+#define SIGNED_SCALAR_FIXED_POINT_MODE_P(MODE) \
+ (SCALAR_FRACT_MODE_P (MODE) || SCALAR_ACCUM_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar ufract or uaccum mode. */
+#define UNSIGNED_SCALAR_FIXED_POINT_MODE_P(MODE) \
+ (SCALAR_UFRACT_MODE_P (MODE) || SCALAR_UACCUM_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar fract, ufract, accum or uaccum mode. */
+#define ALL_SCALAR_FIXED_POINT_MODE_P(MODE) \
+ (SIGNED_SCALAR_FIXED_POINT_MODE_P (MODE) \
+ || UNSIGNED_SCALAR_FIXED_POINT_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar/vector fract mode. */
+#define FRACT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_FRACT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT)
+
+/* Nonzero if MODE is a scalar/vector ufract mode. */
+#define UFRACT_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_UFRACT \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT)
+
+/* Nonzero if MODE is a scalar/vector fract or ufract mode. */
+#define ALL_FRACT_MODE_P(MODE) \
+ (FRACT_MODE_P (MODE) || UFRACT_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar/vector accum mode. */
+#define ACCUM_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_ACCUM \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_ACCUM)
+
+/* Nonzero if MODE is a scalar/vector uaccum mode. */
+#define UACCUM_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_UACCUM \
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_UACCUM)
+
+/* Nonzero if MODE is a scalar/vector accum or uaccum mode. */
+#define ALL_ACCUM_MODE_P(MODE) \
+ (ACCUM_MODE_P (MODE) || UACCUM_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar/vector fract or accum mode. */
+#define SIGNED_FIXED_POINT_MODE_P(MODE) \
+ (FRACT_MODE_P (MODE) || ACCUM_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar/vector ufract or uaccum mode. */
+#define UNSIGNED_FIXED_POINT_MODE_P(MODE) \
+ (UFRACT_MODE_P (MODE) || UACCUM_MODE_P (MODE))
+
+/* Nonzero if MODE is a scalar/vector fract, ufract, accum or uaccum mode. */
+#define ALL_FIXED_POINT_MODE_P(MODE) \
+ (SIGNED_FIXED_POINT_MODE_P (MODE) \
+ || UNSIGNED_FIXED_POINT_MODE_P (MODE))
+
+/* Nonzero if MODE is opaque. */
+#define OPAQUE_MODE_P(MODE) \
+ (GET_MODE_CLASS (MODE) == MODE_OPAQUE)
+
+/* Nonzero if CLASS modes can be widened. */
+#define CLASS_HAS_WIDER_MODES_P(CLASS) \
+ (CLASS == MODE_INT \
+ || CLASS == MODE_PARTIAL_INT \
+ || CLASS == MODE_FLOAT \
+ || CLASS == MODE_DECIMAL_FLOAT \
+ || CLASS == MODE_COMPLEX_FLOAT \
+ || CLASS == MODE_FRACT \
+ || CLASS == MODE_UFRACT \
+ || CLASS == MODE_ACCUM \
+ || CLASS == MODE_UACCUM)
+
+/* An optional T (i.e. a T or nothing), where T is some form of mode class. */
+template<typename T>
+class opt_mode
+{
+public:
+ enum from_int { dummy = MAX_MACHINE_MODE };
+
+ ALWAYS_INLINE CONSTEXPR opt_mode () : m_mode (E_VOIDmode) {}
+ ALWAYS_INLINE CONSTEXPR opt_mode (const T &m) : m_mode (m) {}
+ template<typename U>
+ ALWAYS_INLINE CONSTEXPR opt_mode (const U &m) : m_mode (T (m)) {}
+ ALWAYS_INLINE CONSTEXPR opt_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ machine_mode else_void () const;
+ machine_mode else_blk () const { return else_mode (BLKmode); }
+ machine_mode else_mode (machine_mode) const;
+ T require () const;
+
+ bool exists () const;
+ template<typename U> bool exists (U *) const;
+
+ bool operator== (const T &m) const { return m_mode == m; }
+ bool operator!= (const T &m) const { return m_mode != m; }
+
+private:
+ machine_mode m_mode;
+};
+
+/* If the object contains a T, return its enum value, otherwise return
+ E_VOIDmode. */
+
+template<typename T>
+ALWAYS_INLINE machine_mode
+opt_mode<T>::else_void () const
+{
+ return m_mode;
+}
+
+/* If the T exists, return its enum value, otherwise return FALLBACK. */
+
+template<typename T>
+inline machine_mode
+opt_mode<T>::else_mode (machine_mode fallback) const
+{
+ return m_mode == E_VOIDmode ? fallback : m_mode;
+}
+
+/* Assert that the object contains a T and return it. */
+
+template<typename T>
+inline T
+opt_mode<T>::require () const
+{
+ gcc_checking_assert (m_mode != E_VOIDmode);
+ return typename mode_traits<T>::from_int (m_mode);
+}
+
+/* Return true if the object contains a T rather than nothing. */
+
+template<typename T>
+ALWAYS_INLINE bool
+opt_mode<T>::exists () const
+{
+ return m_mode != E_VOIDmode;
+}
+
+/* Return true if the object contains a T, storing it in *MODE if so. */
+
+template<typename T>
+template<typename U>
+inline bool
+opt_mode<T>::exists (U *mode) const
+{
+ if (m_mode != E_VOIDmode)
+ {
+ *mode = T (typename mode_traits<T>::from_int (m_mode));
+ return true;
+ }
+ return false;
+}
+
+/* A POD version of mode class T. */
+
+template<typename T>
+struct pod_mode
+{
+ typedef typename mode_traits<T>::from_int from_int;
+ typedef typename T::measurement_type measurement_type;
+
+ machine_mode m_mode;
+ ALWAYS_INLINE CONSTEXPR
+ operator machine_mode () const { return m_mode; }
+
+ ALWAYS_INLINE CONSTEXPR
+ operator T () const { return from_int (m_mode); }
+
+ ALWAYS_INLINE pod_mode &operator = (const T &m) { m_mode = m; return *this; }
+};
+
+/* Return true if mode M has type T. */
+
+template<typename T>
+inline bool
+is_a (machine_mode m)
+{
+ return T::includes_p (m);
+}
+
+template<typename T, typename U>
+inline bool
+is_a (const opt_mode<U> &m)
+{
+ return T::includes_p (m.else_void ());
+}
+
+/* Assert that mode M has type T, and return it in that form. */
+
+template<typename T>
+inline T
+as_a (machine_mode m)
+{
+ gcc_checking_assert (T::includes_p (m));
+ return typename mode_traits<T>::from_int (m);
+}
+
+template<typename T, typename U>
+inline T
+as_a (const opt_mode<U> &m)
+{
+ return as_a <T> (m.else_void ());
+}
+
+/* Convert M to an opt_mode<T>. */
+
+template<typename T>
+inline opt_mode<T>
+dyn_cast (machine_mode m)
+{
+ if (T::includes_p (m))
+ return T (typename mode_traits<T>::from_int (m));
+ return opt_mode<T> ();
+}
+
+template<typename T, typename U>
+inline opt_mode<T>
+dyn_cast (const opt_mode<U> &m)
+{
+ return dyn_cast <T> (m.else_void ());
+}
+
+/* Return true if mode M has type T, storing it as a T in *RESULT
+ if so. */
+
+template<typename T, typename U>
+inline bool
+is_a (machine_mode m, U *result)
+{
+ if (T::includes_p (m))
+ {
+ *result = T (typename mode_traits<T>::from_int (m));
+ return true;
+ }
+ return false;
+}
+
+/* Represents a machine mode that is known to be a SCALAR_INT_MODE_P. */
+class scalar_int_mode
+{
+public:
+ typedef mode_traits<scalar_int_mode>::from_int from_int;
+ typedef unsigned short measurement_type;
+
+ ALWAYS_INLINE scalar_int_mode () {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_int_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
+
+ static bool includes_p (machine_mode);
+
+protected:
+ machine_mode m_mode;
+};
+
+/* Return true if M is a scalar_int_mode. */
+
+inline bool
+scalar_int_mode::includes_p (machine_mode m)
+{
+ return SCALAR_INT_MODE_P (m);
+}
+
+/* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P. */
+class scalar_float_mode
+{
+public:
+ typedef mode_traits<scalar_float_mode>::from_int from_int;
+ typedef unsigned short measurement_type;
+
+ ALWAYS_INLINE scalar_float_mode () {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
+
+ static bool includes_p (machine_mode);
+
+protected:
+ machine_mode m_mode;
+};
+
+/* Return true if M is a scalar_float_mode. */
+
+inline bool
+scalar_float_mode::includes_p (machine_mode m)
+{
+ return SCALAR_FLOAT_MODE_P (m);
+}
+
+/* Represents a machine mode that is known to be scalar. */
+class scalar_mode
+{
+public:
+ typedef mode_traits<scalar_mode>::from_int from_int;
+ typedef unsigned short measurement_type;
+
+ ALWAYS_INLINE scalar_mode () {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (const scalar_int_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (const scalar_float_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
+
+ static bool includes_p (machine_mode);
+
+protected:
+ machine_mode m_mode;
+};
+
+/* Return true if M represents some kind of scalar value. */
+
+inline bool
+scalar_mode::includes_p (machine_mode m)
+{
+ switch (GET_MODE_CLASS (m))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ case MODE_FRACT:
+ case MODE_UFRACT:
+ case MODE_ACCUM:
+ case MODE_UACCUM:
+ case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Represents a machine mode that is known to be a COMPLEX_MODE_P. */
+class complex_mode
+{
+public:
+ typedef mode_traits<complex_mode>::from_int from_int;
+ typedef unsigned short measurement_type;
+
+ ALWAYS_INLINE complex_mode () {}
+
+ ALWAYS_INLINE CONSTEXPR
+ complex_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
+
+ static bool includes_p (machine_mode);
+
+protected:
+ machine_mode m_mode;
+};
+
+/* Return true if M is a complex_mode. */
+
+inline bool
+complex_mode::includes_p (machine_mode m)
+{
+ return COMPLEX_MODE_P (m);
+}
+
+/* Return the base GET_MODE_SIZE value for MODE. */
+
+#if 0 // sdcpp
+ALWAYS_INLINE poly_uint16
+mode_to_bytes (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+ return (__builtin_constant_p (mode)
+ ? mode_size_inline (mode) : mode_size[mode]);
+#else
+ return mode_size[mode];
+#endif
+}
+
+/* Return the base GET_MODE_BITSIZE value for MODE. */
+
+ALWAYS_INLINE poly_uint16
+mode_to_bits (machine_mode mode)
+{
+ return mode_to_bytes (mode) * BITS_PER_UNIT;
+}
+
+/* Return the base GET_MODE_PRECISION value for MODE. */
+
+ALWAYS_INLINE poly_uint16
+mode_to_precision (machine_mode mode)
+{
+ return mode_precision[mode];
+}
+
+/* Return the base GET_MODE_INNER value for MODE. */
+#endif // sdcpp
+
+ALWAYS_INLINE scalar_mode
+mode_to_inner (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+ return scalar_mode::from_int (__builtin_constant_p (mode)
+ ? mode_inner_inline (mode)
+ : mode_inner[mode]);
+#else
+ return scalar_mode::from_int (mode_inner[mode]);
+#endif
+}
+
+#if 0 // sdcpp
+
+/* Return the base GET_MODE_UNIT_SIZE value for MODE. */
+
+ALWAYS_INLINE unsigned char
+mode_to_unit_size (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+ return (__builtin_constant_p (mode)
+ ? mode_unit_size_inline (mode) : mode_unit_size[mode]);
+#else
+ return mode_unit_size[mode];
+#endif
+}
+
+/* Return the base GET_MODE_UNIT_PRECISION value for MODE. */
+
+ALWAYS_INLINE unsigned short
+mode_to_unit_precision (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+ return (__builtin_constant_p (mode)
+ ? mode_unit_precision_inline (mode) : mode_unit_precision[mode]);
+#else
+ return mode_unit_precision[mode];
+#endif
+}
+
+/* Return the base GET_MODE_NUNITS value for MODE. */
+
+ALWAYS_INLINE poly_uint16
+mode_to_nunits (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+ return (__builtin_constant_p (mode)
+ ? mode_nunits_inline (mode) : mode_nunits[mode]);
+#else
+ return mode_nunits[mode];
+#endif
+}
+
+/* Get the size in bytes of an object of mode MODE. */
+
+#if ONLY_FIXED_SIZE_MODES
+#define GET_MODE_SIZE(MODE) ((unsigned short) mode_to_bytes (MODE).coeffs[0])
+#else
+ALWAYS_INLINE poly_uint16
+GET_MODE_SIZE (machine_mode mode)
+{
+ return mode_to_bytes (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
+GET_MODE_SIZE (const T &mode)
+{
+ return mode_to_bytes (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
+GET_MODE_SIZE (const T &mode)
+{
+ return mode_to_bytes (mode).coeffs[0];
+}
+#endif
+#endif // sdcpp
+
+/* Get the size in bits of an object of mode MODE. */
+
+#if 0 // sdcpp
+#if ONLY_FIXED_SIZE_MODES
+#define GET_MODE_BITSIZE(MODE) ((unsigned short) mode_to_bits (MODE).coeffs[0])
+#else
+ALWAYS_INLINE poly_uint16
+GET_MODE_BITSIZE (machine_mode mode)
+{
+ return mode_to_bits (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
+GET_MODE_BITSIZE (const T &mode)
+{
+ return mode_to_bits (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
+GET_MODE_BITSIZE (const T &mode)
+{
+ return mode_to_bits (mode).coeffs[0];
+}
+#endif
+
+/* Get the number of value bits of an object of mode MODE. */
+
+#if ONLY_FIXED_SIZE_MODES
+#define GET_MODE_PRECISION(MODE) \
+ ((unsigned short) mode_to_precision (MODE).coeffs[0])
+#else
+ALWAYS_INLINE poly_uint16
+GET_MODE_PRECISION (machine_mode mode)
+{
+ return mode_to_precision (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
+GET_MODE_PRECISION (const T &mode)
+{
+ return mode_to_precision (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
+GET_MODE_PRECISION (const T &mode)
+{
+ return mode_to_precision (mode).coeffs[0];
+}
+#endif
+
+/* Get the number of integral bits of an object of mode MODE. */
+extern CONST_MODE_IBIT unsigned char mode_ibit[NUM_MACHINE_MODES];
+#define GET_MODE_IBIT(MODE) mode_ibit[MODE]
+
+/* Get the number of fractional bits of an object of mode MODE. */
+extern CONST_MODE_FBIT unsigned char mode_fbit[NUM_MACHINE_MODES];
+#define GET_MODE_FBIT(MODE) mode_fbit[MODE]
+
+/* Get a bitmask containing 1 for all bits in a word
+ that fit within mode MODE. */
+
+extern CONST_MODE_MASK unsigned HOST_WIDE_INT
+ mode_mask_array[NUM_MACHINE_MODES];
+
+#define GET_MODE_MASK(MODE) mode_mask_array[MODE]
+
+/* Return the mode of the basic parts of MODE. For vector modes this is the
+ mode of the vector elements. For complex modes it is the mode of the real
+ and imaginary parts. For other modes it is MODE itself. */
+#endif // sdcpp
+
+#define GET_MODE_INNER(MODE) (mode_to_inner (MODE))
+
+#if 0 // sdcpp
+
+/* Get the size in bytes or bits of the basic parts of an
+ object of mode MODE. */
+
+#define GET_MODE_UNIT_SIZE(MODE) mode_to_unit_size (MODE)
+
+#define GET_MODE_UNIT_BITSIZE(MODE) \
+ ((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT))
+
+#define GET_MODE_UNIT_PRECISION(MODE) (mode_to_unit_precision (MODE))
+
+/* Get the number of units in an object of mode MODE. This is 2 for
+ complex modes and the number of elements for vector modes. */
+
+#if ONLY_FIXED_SIZE_MODES
+#define GET_MODE_NUNITS(MODE) (mode_to_nunits (MODE).coeffs[0])
+#else
+ALWAYS_INLINE poly_uint16
+GET_MODE_NUNITS (machine_mode mode)
+{
+ return mode_to_nunits (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
+GET_MODE_NUNITS (const T &mode)
+{
+ return mode_to_nunits (mode);
+}
+
+template<typename T>
+ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
+GET_MODE_NUNITS (const T &mode)
+{
+ return mode_to_nunits (mode).coeffs[0];
+}
+#endif
+
+/* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */
+
+template<typename T>
+ALWAYS_INLINE opt_mode<T>
+GET_MODE_WIDER_MODE (const T &m)
+{
+ return typename opt_mode<T>::from_int (mode_wider[m]);
+}
+
+/* For scalars, this is a mode with twice the precision. For vectors,
+ this is a mode with the same inner mode but with twice the elements. */
+
+template<typename T>
+ALWAYS_INLINE opt_mode<T>
+GET_MODE_2XWIDER_MODE (const T &m)
+{
+ return typename opt_mode<T>::from_int (mode_2xwider[m]);
+}
+
+/* Get the complex mode from the component mode. */
+extern const unsigned char mode_complex[NUM_MACHINE_MODES];
+#define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
+
+/* Represents a machine mode that must have a fixed size. The main
+ use of this class is to represent the modes of objects that always
+ have static storage duration, such as constant pool entries.
+ (No current target supports the concept of variable-size static data.) */
+class fixed_size_mode
+{
+public:
+ typedef mode_traits<fixed_size_mode>::from_int from_int;
+ typedef unsigned short measurement_type;
+
+ ALWAYS_INLINE fixed_size_mode () {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR
+ fixed_size_mode (const complex_mode &m) : m_mode (m) {}
+
+ ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
+
+ static bool includes_p (machine_mode);
+
+protected:
+ machine_mode m_mode;
+};
+
+/* Return true if MODE has a fixed size. */
+
+inline bool
+fixed_size_mode::includes_p (machine_mode mode)
+{
+ return mode_to_bytes (mode).is_constant ();
+}
+
+/* Wrapper for mode arguments to target macros, so that if a target
+ doesn't need polynomial-sized modes, its header file can continue
+ to treat everything as fixed_size_mode. This should go away once
+ macros are moved to target hooks. It shouldn't be used in other
+ contexts. */
+#if NUM_POLY_INT_COEFFS == 1
+#define MACRO_MODE(MODE) (as_a <fixed_size_mode> (MODE))
+#else
+#define MACRO_MODE(MODE) (MODE)
+#endif
+
+extern opt_machine_mode mode_for_size (poly_uint64, enum mode_class, int);
+
+/* Return the machine mode to use for a MODE_INT of SIZE bits, if one
+ exists. If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
+ will not be used. */
+
+inline opt_scalar_int_mode
+int_mode_for_size (poly_uint64 size, int limit)
+{
+ return dyn_cast <scalar_int_mode> (mode_for_size (size, MODE_INT, limit));
+}
+
+/* Return the machine mode to use for a MODE_FLOAT of SIZE bits, if one
+ exists. */
+
+inline opt_scalar_float_mode
+float_mode_for_size (poly_uint64 size)
+{
+ return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0));
+}
+
+/* Likewise for MODE_DECIMAL_FLOAT. */
+
+inline opt_scalar_float_mode
+decimal_float_mode_for_size (unsigned int size)
+{
+ return dyn_cast <scalar_float_mode>
+ (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
+}
+
+extern machine_mode smallest_mode_for_size (poly_uint64, enum mode_class);
+
+/* Find the narrowest integer mode that contains at least SIZE bits.
+ Such a mode must exist. */
+
+inline scalar_int_mode
+smallest_int_mode_for_size (poly_uint64 size)
+{
+ return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
+}
+
+extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
+extern opt_machine_mode bitwise_mode_for_mode (machine_mode);
+extern opt_machine_mode mode_for_vector (scalar_mode, poly_uint64);
+extern opt_machine_mode related_vector_mode (machine_mode, scalar_mode,
+ poly_uint64 = 0);
+extern opt_machine_mode related_int_vector_mode (machine_mode);
+
+/* A class for iterating through possible bitfield modes. */
+class bit_field_mode_iterator
+{
+public:
+ bit_field_mode_iterator (HOST_WIDE_INT, HOST_WIDE_INT,
+ poly_int64, poly_int64,
+ unsigned int, bool);
+ bool next_mode (scalar_int_mode *);
+ bool prefer_smaller_modes ();
+
+private:
+ opt_scalar_int_mode m_mode;
+ /* We use signed values here because the bit position can be negative
+ for invalid input such as gcc.dg/pr48335-8.c. */
+ HOST_WIDE_INT m_bitsize;
+ HOST_WIDE_INT m_bitpos;
+ poly_int64 m_bitregion_start;
+ poly_int64 m_bitregion_end;
+ unsigned int m_align;
+ bool m_volatilep;
+ int m_count;
+};
+
+/* Find the best mode to use to access a bit field. */
+
+extern bool get_best_mode (int, int, poly_uint64, poly_uint64, unsigned int,
+ unsigned HOST_WIDE_INT, bool, scalar_int_mode *);
+
+/* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */
+
+extern CONST_MODE_BASE_ALIGN unsigned short mode_base_align[NUM_MACHINE_MODES];
+
+extern unsigned get_mode_alignment (machine_mode);
+
+#define GET_MODE_ALIGNMENT(MODE) get_mode_alignment (MODE)
+
+/* For each class, get the narrowest mode in that class. */
+
+extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
+#define GET_CLASS_NARROWEST_MODE(CLASS) \
+ ((machine_mode) class_narrowest_mode[CLASS])
+
+/* The narrowest full integer mode available on the target. */
+
+#define NARROWEST_INT_MODE \
+ (scalar_int_mode \
+ (scalar_int_mode::from_int (class_narrowest_mode[MODE_INT])))
+
+/* Return the narrowest mode in T's class. */
+
+template<typename T>
+inline T
+get_narrowest_mode (T mode)
+{
+ return typename mode_traits<T>::from_int
+ (class_narrowest_mode[GET_MODE_CLASS (mode)]);
+}
+
+/* Define the integer modes whose sizes are BITS_PER_UNIT and BITS_PER_WORD
+ and the mode whose class is Pmode and whose size is POINTER_SIZE. */
+
+extern scalar_int_mode byte_mode;
+extern scalar_int_mode word_mode;
+extern scalar_int_mode ptr_mode;
+
+/* Target-dependent machine mode initialization - in insn-modes.cc. */
+extern void init_adjust_machine_modes (void);
+
+#define TRULY_NOOP_TRUNCATION_MODES_P(MODE1, MODE2) \
+ (targetm.truly_noop_truncation (GET_MODE_PRECISION (MODE1), \
+ GET_MODE_PRECISION (MODE2)))
+
+/* Return true if MODE is a scalar integer mode that fits in a
+ HOST_WIDE_INT. */
+
+inline bool
+HWI_COMPUTABLE_MODE_P (machine_mode mode)
+{
+ machine_mode mme = mode;
+ return (SCALAR_INT_MODE_P (mme)
+ && mode_to_precision (mme).coeffs[0] <= HOST_BITS_PER_WIDE_INT);
+}
+
+inline bool
+HWI_COMPUTABLE_MODE_P (scalar_int_mode mode)
+{
+ return GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT;
+}
+
+struct int_n_data_t {
+ /* These parts are initailized by genmodes output */
+ unsigned int bitsize;
+ scalar_int_mode_pod m;
+ /* RID_* is RID_INTN_BASE + index into this array */
+};
+
+/* This is also in tree.h. genmodes.cc guarantees the're sorted from
+ smallest bitsize to largest bitsize. */
+extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
+
+/* Return true if MODE has class MODE_INT, storing it as a scalar_int_mode
+ in *INT_MODE if so. */
+
+template<typename T>
+inline bool
+is_int_mode (machine_mode mode, T *int_mode)
+{
+ if (GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ *int_mode = scalar_int_mode (scalar_int_mode::from_int (mode));
+ return true;
+ }
+ return false;
+}
+
+/* Return true if MODE has class MODE_FLOAT, storing it as a
+ scalar_float_mode in *FLOAT_MODE if so. */
+
+template<typename T>
+inline bool
+is_float_mode (machine_mode mode, T *float_mode)
+{
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *float_mode = scalar_float_mode (scalar_float_mode::from_int (mode));
+ return true;
+ }
+ return false;
+}
+
+/* Return true if MODE has class MODE_COMPLEX_INT, storing it as
+ a complex_mode in *CMODE if so. */
+
+template<typename T>
+inline bool
+is_complex_int_mode (machine_mode mode, T *cmode)
+{
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+ {
+ *cmode = complex_mode (complex_mode::from_int (mode));
+ return true;
+ }
+ return false;
+}
+
+/* Return true if MODE has class MODE_COMPLEX_FLOAT, storing it as
+ a complex_mode in *CMODE if so. */
+
+template<typename T>
+inline bool
+is_complex_float_mode (machine_mode mode, T *cmode)
+{
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ {
+ *cmode = complex_mode (complex_mode::from_int (mode));
+ return true;
+ }
+ return false;
+}
+
+/* Return true if MODE is a scalar integer mode with a precision
+ smaller than LIMIT's precision. */
+
+inline bool
+is_narrower_int_mode (machine_mode mode, scalar_int_mode limit)
+{
+ scalar_int_mode int_mode;
+ return (is_a <scalar_int_mode> (mode, &int_mode)
+ && GET_MODE_PRECISION (int_mode) < GET_MODE_PRECISION (limit));
+}
+
+namespace mode_iterator
+{
+ /* Start mode iterator *ITER at the first mode in class MCLASS, if any. */
+
+ template<typename T>
+ inline void
+ start (opt_mode<T> *iter, enum mode_class mclass)
+ {
+ if (GET_CLASS_NARROWEST_MODE (mclass) == E_VOIDmode)
+ *iter = opt_mode<T> ();
+ else
+ *iter = as_a<T> (GET_CLASS_NARROWEST_MODE (mclass));
+ }
+
+ inline void
+ start (machine_mode *iter, enum mode_class mclass)
+ {
+ *iter = GET_CLASS_NARROWEST_MODE (mclass);
+ }
+
+ /* Return true if mode iterator *ITER has not reached the end. */
+
+ template<typename T>
+ inline bool
+ iterate_p (opt_mode<T> *iter)
+ {
+ return iter->exists ();
+ }
+
+ inline bool
+ iterate_p (machine_mode *iter)
+ {
+ return *iter != E_VOIDmode;
+ }
+
+ /* Set mode iterator *ITER to the next widest mode in the same class,
+ if any. */
+
+ template<typename T>
+ inline void
+ get_wider (opt_mode<T> *iter)
+ {
+ *iter = GET_MODE_WIDER_MODE (iter->require ());
+ }
+
+ inline void
+ get_wider (machine_mode *iter)
+ {
+ *iter = GET_MODE_WIDER_MODE (*iter).else_void ();
+ }
+
+ /* Set mode iterator *ITER to the next widest mode in the same class.
+ Such a mode is known to exist. */
+
+ template<typename T>
+ inline void
+ get_known_wider (T *iter)
+ {
+ *iter = GET_MODE_WIDER_MODE (*iter).require ();
+ }
+
+ /* Set mode iterator *ITER to the mode that is two times wider than the
+ current one, if such a mode exists. */
+
+ template<typename T>
+ inline void
+ get_2xwider (opt_mode<T> *iter)
+ {
+ *iter = GET_MODE_2XWIDER_MODE (iter->require ());
+ }
+
+ inline void
+ get_2xwider (machine_mode *iter)
+ {
+ *iter = GET_MODE_2XWIDER_MODE (*iter).else_void ();
+ }
+}
+
+/* Make ITERATOR iterate over all the modes in mode class CLASS,
+ from narrowest to widest. */
+#define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS) \
+ for (mode_iterator::start (&(ITERATOR), CLASS); \
+ mode_iterator::iterate_p (&(ITERATOR)); \
+ mode_iterator::get_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over all the modes in the range [START, END),
+ in order of increasing width. */
+#define FOR_EACH_MODE(ITERATOR, START, END) \
+ for ((ITERATOR) = (START); \
+ (ITERATOR) != (END); \
+ mode_iterator::get_known_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over START and all wider modes in the same
+ class, in order of increasing width. */
+#define FOR_EACH_MODE_FROM(ITERATOR, START) \
+ for ((ITERATOR) = (START); \
+ mode_iterator::iterate_p (&(ITERATOR)); \
+ mode_iterator::get_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over modes in the range [NARROWEST, END)
+ in order of increasing width, where NARROWEST is the narrowest mode
+ in END's class. */
+#define FOR_EACH_MODE_UNTIL(ITERATOR, END) \
+ FOR_EACH_MODE (ITERATOR, get_narrowest_mode (END), END)
+
+/* Make ITERATOR iterate over modes in the same class as MODE, in order
+ of increasing width. Start at the first mode wider than START,
+ or don't iterate at all if there is no wider mode. */
+#define FOR_EACH_WIDER_MODE(ITERATOR, START) \
+ for ((ITERATOR) = (START), mode_iterator::get_wider (&(ITERATOR)); \
+ mode_iterator::iterate_p (&(ITERATOR)); \
+ mode_iterator::get_wider (&(ITERATOR)))
+
+/* Make ITERATOR iterate over modes in the same class as MODE, in order
+ of increasing width, and with each mode being twice the width of the
+ previous mode. Start at the mode that is two times wider than START,
+ or don't iterate at all if there is no such mode. */
+#define FOR_EACH_2XWIDER_MODE(ITERATOR, START) \
+ for ((ITERATOR) = (START), mode_iterator::get_2xwider (&(ITERATOR)); \
+ mode_iterator::iterate_p (&(ITERATOR)); \
+ mode_iterator::get_2xwider (&(ITERATOR)))
+
+template<typename T>
+void
+gt_ggc_mx (pod_mode<T> *)
+{
+}
+
+template<typename T>
+void
+gt_pch_nx (pod_mode<T> *)
+{
+}
+
+template<typename T>
+void
+gt_pch_nx (pod_mode<T> *, gt_pointer_operator, void *)
+{
+}
+
+#endif // sdcpp
+
+#endif /* not HAVE_MACHINE_MODES */
diff --git a/support/cpp/gcc/main.cc b/support/cpp/gcc/main.cc
new file mode 100644
index 000000000..4ba28b7de
--- /dev/null
+++ b/support/cpp/gcc/main.cc
@@ -0,0 +1,45 @@
+/* main.c: defines main() for cc1, cc1plus, etc.
+ Copyright (C) 2007-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 "diagnostic-core.h"
+#include "toplev.h"
+
+int main (int argc, char **argv);
+
+/* We define main() to call toplev::main(), which is defined in toplev.cc.
+ We do this in a separate file in order to allow the language front-end
+ to define a different main(), if it so desires. */
+
+int
+main (int argc, char **argv)
+{
+ toplev toplev (NULL, /* external_timer */
+ true /* init_signals */);
+
+ int r = toplev.main (argc, argv);
+
+ if (flag_checking && !seen_error ())
+ toplev.finalize ();
+
+ return r;
+}
diff --git a/support/cpp/gcc/match.pd b/support/cpp/gcc/match.pd
new file mode 100644
index 000000000..6d691d302
--- /dev/null
+++ b/support/cpp/gcc/match.pd
@@ -0,0 +1,7748 @@
+/* Match-and-simplify patterns for shared GENERIC and GIMPLE folding.
+ This file is consumed by genmatch which produces gimple-match.cc
+ and generic-match.cc from it.
+
+ Copyright (C) 2014-2022 Free Software Foundation, Inc.
+ Contributed by Richard Biener <rguenther@suse.de>
+ and Prathamesh Kulkarni <bilbotheelffriend@gmail.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.
+
+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/>. */
+
+
+/* Generic tree predicates we inherit. */
+(define_predicates
+ integer_onep integer_zerop integer_all_onesp integer_minus_onep
+ integer_each_onep integer_truep integer_nonzerop
+ real_zerop real_onep real_minus_onep
+ zerop
+ initializer_each_zero_or_onep
+ CONSTANT_CLASS_P
+ tree_expr_nonnegative_p
+ tree_expr_nonzero_p
+ integer_valued_real_p
+ integer_pow2p
+ uniform_integer_cst_p
+ HONOR_NANS
+ uniform_vector_p
+ expand_vec_cmp_expr_p
+ bitmask_inv_cst_vector_p)
+
+/* Operator lists. */
+(define_operator_list tcc_comparison
+ lt le eq ne ge gt unordered ordered unlt unle ungt unge uneq ltgt)
+(define_operator_list inverted_tcc_comparison
+ ge gt ne eq lt le ordered unordered ge gt le lt ltgt uneq)
+(define_operator_list inverted_tcc_comparison_with_nans
+ unge ungt ne eq unlt unle ordered unordered ge gt le lt ltgt uneq)
+(define_operator_list swapped_tcc_comparison
+ gt ge eq ne le lt unordered ordered ungt unge unlt unle uneq ltgt)
+(define_operator_list simple_comparison lt le eq ne ge gt)
+(define_operator_list swapped_simple_comparison gt ge eq ne le lt)
+
+#include "cfn-operators.pd"
+
+/* Define operand lists for math rounding functions {,i,l,ll}FN,
+ where the versions prefixed with "i" return an int, those prefixed with
+ "l" return a long and those prefixed with "ll" return a long long.
+
+ Also define operand lists:
+
+ X<FN>F for all float functions, in the order i, l, ll
+ X<FN> for all double functions, in the same order
+ X<FN>L for all long double functions, in the same order. */
+#define DEFINE_INT_AND_FLOAT_ROUND_FN(FN) \
+ (define_operator_list X##FN##F BUILT_IN_I##FN##F \
+ BUILT_IN_L##FN##F \
+ BUILT_IN_LL##FN##F) \
+ (define_operator_list X##FN BUILT_IN_I##FN \
+ BUILT_IN_L##FN \
+ BUILT_IN_LL##FN) \
+ (define_operator_list X##FN##L BUILT_IN_I##FN##L \
+ BUILT_IN_L##FN##L \
+ BUILT_IN_LL##FN##L)
+
+DEFINE_INT_AND_FLOAT_ROUND_FN (FLOOR)
+DEFINE_INT_AND_FLOAT_ROUND_FN (CEIL)
+DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND)
+DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+
+/* Unary operations and their associated IFN_COND_* function. */
+(define_operator_list UNCOND_UNARY
+ negate)
+(define_operator_list COND_UNARY
+ IFN_COND_NEG)
+
+/* Binary operations and their associated IFN_COND_* function. */
+(define_operator_list UNCOND_BINARY
+ plus minus
+ mult trunc_div trunc_mod rdiv
+ min max
+ IFN_FMIN IFN_FMAX
+ bit_and bit_ior bit_xor
+ lshift rshift)
+(define_operator_list COND_BINARY
+ IFN_COND_ADD IFN_COND_SUB
+ IFN_COND_MUL IFN_COND_DIV IFN_COND_MOD IFN_COND_RDIV
+ IFN_COND_MIN IFN_COND_MAX
+ IFN_COND_FMIN IFN_COND_FMAX
+ IFN_COND_AND IFN_COND_IOR IFN_COND_XOR
+ IFN_COND_SHL IFN_COND_SHR)
+
+/* Same for ternary operations. */
+(define_operator_list UNCOND_TERNARY
+ IFN_FMA IFN_FMS IFN_FNMA IFN_FNMS)
+(define_operator_list COND_TERNARY
+ IFN_COND_FMA IFN_COND_FMS IFN_COND_FNMA IFN_COND_FNMS)
+
+/* __atomic_fetch_or_*, __atomic_fetch_xor_*, __atomic_xor_fetch_* */
+(define_operator_list ATOMIC_FETCH_OR_XOR_N
+ BUILT_IN_ATOMIC_FETCH_OR_1 BUILT_IN_ATOMIC_FETCH_OR_2
+ BUILT_IN_ATOMIC_FETCH_OR_4 BUILT_IN_ATOMIC_FETCH_OR_8
+ BUILT_IN_ATOMIC_FETCH_OR_16
+ BUILT_IN_ATOMIC_FETCH_XOR_1 BUILT_IN_ATOMIC_FETCH_XOR_2
+ BUILT_IN_ATOMIC_FETCH_XOR_4 BUILT_IN_ATOMIC_FETCH_XOR_8
+ BUILT_IN_ATOMIC_FETCH_XOR_16
+ BUILT_IN_ATOMIC_XOR_FETCH_1 BUILT_IN_ATOMIC_XOR_FETCH_2
+ BUILT_IN_ATOMIC_XOR_FETCH_4 BUILT_IN_ATOMIC_XOR_FETCH_8
+ BUILT_IN_ATOMIC_XOR_FETCH_16)
+/* __sync_fetch_and_or_*, __sync_fetch_and_xor_*, __sync_xor_and_fetch_* */
+(define_operator_list SYNC_FETCH_OR_XOR_N
+ BUILT_IN_SYNC_FETCH_AND_OR_1 BUILT_IN_SYNC_FETCH_AND_OR_2
+ BUILT_IN_SYNC_FETCH_AND_OR_4 BUILT_IN_SYNC_FETCH_AND_OR_8
+ BUILT_IN_SYNC_FETCH_AND_OR_16
+ BUILT_IN_SYNC_FETCH_AND_XOR_1 BUILT_IN_SYNC_FETCH_AND_XOR_2
+ BUILT_IN_SYNC_FETCH_AND_XOR_4 BUILT_IN_SYNC_FETCH_AND_XOR_8
+ BUILT_IN_SYNC_FETCH_AND_XOR_16
+ BUILT_IN_SYNC_XOR_AND_FETCH_1 BUILT_IN_SYNC_XOR_AND_FETCH_2
+ BUILT_IN_SYNC_XOR_AND_FETCH_4 BUILT_IN_SYNC_XOR_AND_FETCH_8
+ BUILT_IN_SYNC_XOR_AND_FETCH_16)
+/* __atomic_fetch_and_*. */
+(define_operator_list ATOMIC_FETCH_AND_N
+ BUILT_IN_ATOMIC_FETCH_AND_1 BUILT_IN_ATOMIC_FETCH_AND_2
+ BUILT_IN_ATOMIC_FETCH_AND_4 BUILT_IN_ATOMIC_FETCH_AND_8
+ BUILT_IN_ATOMIC_FETCH_AND_16)
+/* __sync_fetch_and_and_*. */
+(define_operator_list SYNC_FETCH_AND_AND_N
+ BUILT_IN_SYNC_FETCH_AND_AND_1 BUILT_IN_SYNC_FETCH_AND_AND_2
+ BUILT_IN_SYNC_FETCH_AND_AND_4 BUILT_IN_SYNC_FETCH_AND_AND_8
+ BUILT_IN_SYNC_FETCH_AND_AND_16)
+
+/* With nop_convert? combine convert? and view_convert? in one pattern
+ plus conditionalize on tree_nop_conversion_p conversions. */
+(match (nop_convert @0)
+ (convert @0)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))))
+(match (nop_convert @0)
+ (view_convert @0)
+ (if (VECTOR_TYPE_P (type) && VECTOR_TYPE_P (TREE_TYPE (@0))
+ && known_eq (TYPE_VECTOR_SUBPARTS (type),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0)))
+ && tree_nop_conversion_p (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (@0))))))
+
+/* Transform likes of (char) ABS_EXPR <(int) x> into (char) ABSU_EXPR <x>
+ ABSU_EXPR returns unsigned absolute value of the operand and the operand
+ of the ABSU_EXPR will have the corresponding signed type. */
+(simplify (abs (convert @0))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && element_precision (type) > element_precision (TREE_TYPE (@0)))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (convert (absu:utype @0)))))
+
+#if GIMPLE
+/* Optimize (X + (X >> (prec - 1))) ^ (X >> (prec - 1)) into abs (X). */
+(simplify
+ (bit_xor:c (plus:c @0 (rshift@2 @0 INTEGER_CST@1)) @2)
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && wi::to_widest (@1) == element_precision (TREE_TYPE (@0)) - 1)
+ (abs @0)))
+#endif
+
+/* Simplifications of operations with one constant operand and
+ simplifications to constants or single values. */
+
+(for op (plus pointer_plus minus bit_ior bit_xor)
+ (simplify
+ (op @0 integer_zerop)
+ (non_lvalue @0)))
+
+/* 0 +p index -> (type)index */
+(simplify
+ (pointer_plus integer_zerop @1)
+ (non_lvalue (convert @1)))
+
+/* ptr - 0 -> (type)ptr */
+(simplify
+ (pointer_diff @0 integer_zerop)
+ (convert @0))
+
+/* See if ARG1 is zero and X + ARG1 reduces to X.
+ Likewise if the operands are reversed. */
+(simplify
+ (plus:c @0 real_zerop@1)
+ (if (fold_real_zero_addition_p (type, @0, @1, 0))
+ (non_lvalue @0)))
+
+/* See if ARG1 is zero and X - ARG1 reduces to X. */
+(simplify
+ (minus @0 real_zerop@1)
+ (if (fold_real_zero_addition_p (type, @0, @1, 1))
+ (non_lvalue @0)))
+
+/* Even if the fold_real_zero_addition_p can't simplify X + 0.0
+ into X, we can optimize (X + 0.0) + 0.0 or (X + 0.0) - 0.0
+ or (X - 0.0) + 0.0 into X + 0.0 and (X - 0.0) - 0.0 into X - 0.0
+ if not -frounding-math. For sNaNs the first operation would raise
+ exceptions but turn the result into qNan, so the second operation
+ would not raise it. */
+(for inner_op (plus minus)
+ (for outer_op (plus minus)
+ (simplify
+ (outer_op (inner_op@3 @0 REAL_CST@1) REAL_CST@2)
+ (if (real_zerop (@1)
+ && real_zerop (@2)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (type))
+ (with { bool inner_plus = ((inner_op == PLUS_EXPR)
+ ^ REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)));
+ bool outer_plus
+ = ((outer_op == PLUS_EXPR)
+ ^ REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@2))); }
+ (if (outer_plus && !inner_plus)
+ (outer_op @0 @2)
+ @3))))))
+
+/* Simplify x - x.
+ This is unsafe for certain floats even in non-IEEE formats.
+ In IEEE, it is unsafe because it does wrong for NaNs.
+ PR middle-end/98420: x - x may be -0.0 with FE_DOWNWARD.
+ Also note that operand_equal_p is always false if an operand
+ is volatile. */
+(simplify
+ (minus @0 @0)
+ (if (!FLOAT_TYPE_P (type)
+ || (!tree_expr_maybe_nan_p (@0)
+ && !tree_expr_maybe_infinite_p (@0)
+ && (!HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ || !HONOR_SIGNED_ZEROS (type))))
+ { build_zero_cst (type); }))
+(simplify
+ (pointer_diff @@0 @0)
+ { build_zero_cst (type); })
+
+(simplify
+ (mult @0 integer_zerop@1)
+ @1)
+
+/* -x == x -> x == 0 */
+(for cmp (eq ne)
+ (simplify
+ (cmp:c @0 (negate @0))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_OVERFLOW_WRAPS (TREE_TYPE(@0)))
+ (cmp @0 { build_zero_cst (TREE_TYPE(@0)); }))))
+
+/* Maybe fold x * 0 to 0. The expressions aren't the same
+ when x is NaN, since x * 0 is also NaN. Nor are they the
+ same in modes with signed zeros, since multiplying a
+ negative value by 0 gives -0, not +0. Nor when x is +-Inf,
+ since x * 0 is NaN. */
+(simplify
+ (mult @0 real_zerop@1)
+ (if (!tree_expr_maybe_nan_p (@0)
+ && (!HONOR_NANS (type) || !tree_expr_maybe_infinite_p (@0))
+ && (!HONOR_SIGNED_ZEROS (type) || tree_expr_nonnegative_p (@0)))
+ @1))
+
+/* In IEEE floating point, x*1 is not equivalent to x for snans.
+ Likewise for complex arithmetic with signed zeros. */
+(simplify
+ (mult @0 real_onep)
+ (if (!tree_expr_maybe_signaling_nan_p (@0)
+ && (!HONOR_SIGNED_ZEROS (type)
+ || !COMPLEX_FLOAT_TYPE_P (type)))
+ (non_lvalue @0)))
+
+/* Transform x * -1.0 into -x. */
+(simplify
+ (mult @0 real_minus_onep)
+ (if (!tree_expr_maybe_signaling_nan_p (@0)
+ && (!HONOR_SIGNED_ZEROS (type)
+ || !COMPLEX_FLOAT_TYPE_P (type)))
+ (negate @0)))
+
+/* Transform { 0 or 1 } * { 0 or 1 } into { 0 or 1 } & { 0 or 1 } */
+(simplify
+ (mult SSA_NAME@1 SSA_NAME@2)
+ (if (INTEGRAL_TYPE_P (type)
+ && get_nonzero_bits (@1) == 1
+ && get_nonzero_bits (@2) == 1)
+ (bit_and @1 @2)))
+
+/* Transform x * { 0 or 1, 0 or 1, ... } into x & { 0 or -1, 0 or -1, ...},
+ unless the target has native support for the former but not the latter. */
+(simplify
+ (mult @0 VECTOR_CST@1)
+ (if (initializer_each_zero_or_onep (@1)
+ && !HONOR_SNANS (type)
+ && !HONOR_SIGNED_ZEROS (type))
+ (with { tree itype = FLOAT_TYPE_P (type) ? unsigned_type_for (type) : type; }
+ (if (itype
+ && (!VECTOR_MODE_P (TYPE_MODE (type))
+ || (VECTOR_MODE_P (TYPE_MODE (itype))
+ && optab_handler (and_optab,
+ TYPE_MODE (itype)) != CODE_FOR_nothing)))
+ (view_convert (bit_and:itype (view_convert @0)
+ (ne @1 { build_zero_cst (type); })))))))
+
+(for cmp (gt ge lt le)
+ outp (convert convert negate negate)
+ outn (negate negate convert convert)
+ /* Transform X * (X > 0.0 ? 1.0 : -1.0) into abs(X). */
+ /* Transform X * (X >= 0.0 ? 1.0 : -1.0) into abs(X). */
+ /* Transform X * (X < 0.0 ? 1.0 : -1.0) into -abs(X). */
+ /* Transform X * (X <= 0.0 ? 1.0 : -1.0) into -abs(X). */
+ (simplify
+ (mult:c @0 (cond (cmp @0 real_zerop) real_onep@1 real_minus_onep))
+ (if (!tree_expr_maybe_nan_p (@0) && !HONOR_SIGNED_ZEROS (type))
+ (outp (abs @0))))
+ /* Transform X * (X > 0.0 ? -1.0 : 1.0) into -abs(X). */
+ /* Transform X * (X >= 0.0 ? -1.0 : 1.0) into -abs(X). */
+ /* Transform X * (X < 0.0 ? -1.0 : 1.0) into abs(X). */
+ /* Transform X * (X <= 0.0 ? -1.0 : 1.0) into abs(X). */
+ (simplify
+ (mult:c @0 (cond (cmp @0 real_zerop) real_minus_onep real_onep@1))
+ (if (!tree_expr_maybe_nan_p (@0) && !HONOR_SIGNED_ZEROS (type))
+ (outn (abs @0)))))
+
+/* Transform X * copysign (1.0, X) into abs(X). */
+(simplify
+ (mult:c @0 (COPYSIGN_ALL real_onep @0))
+ (if (!tree_expr_maybe_nan_p (@0) && !HONOR_SIGNED_ZEROS (type))
+ (abs @0)))
+
+/* Transform X * copysign (1.0, -X) into -abs(X). */
+(simplify
+ (mult:c @0 (COPYSIGN_ALL real_onep (negate @0)))
+ (if (!tree_expr_maybe_nan_p (@0) && !HONOR_SIGNED_ZEROS (type))
+ (negate (abs @0))))
+
+/* Transform copysign (CST, X) into copysign (ABS(CST), X). */
+(simplify
+ (COPYSIGN_ALL REAL_CST@0 @1)
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
+ (COPYSIGN_ALL (negate @0) @1)))
+
+/* X * 1, X / 1 -> X. */
+(for op (mult trunc_div ceil_div floor_div round_div exact_div)
+ (simplify
+ (op @0 integer_onep)
+ (non_lvalue @0)))
+
+/* (A / (1 << B)) -> (A >> B).
+ Only for unsigned A. For signed A, this would not preserve rounding
+ toward zero.
+ For example: (-1 / ( 1 << B)) != -1 >> B.
+ Also also widening conversions, like:
+ (A / (unsigned long long) (1U << B)) -> (A >> B)
+ or
+ (A / (unsigned long long) (1 << B)) -> (A >> B).
+ If the left shift is signed, it can be done only if the upper bits
+ of A starting from shift's type sign bit are zero, as
+ (unsigned long long) (1 << 31) is -2147483648ULL, not 2147483648ULL,
+ so it is valid only if A >> 31 is zero. */
+(simplify
+ (trunc_div (convert?@0 @3) (convert2? (lshift integer_onep@1 @2)))
+ (if ((TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (@0))
+ && (!VECTOR_TYPE_P (type)
+ || target_supports_op_p (type, RSHIFT_EXPR, optab_vector)
+ || target_supports_op_p (type, RSHIFT_EXPR, optab_scalar))
+ && (useless_type_conversion_p (type, TREE_TYPE (@1))
+ || (element_precision (type) >= element_precision (TREE_TYPE (@1))
+ && (TYPE_UNSIGNED (TREE_TYPE (@1))
+ || (element_precision (type)
+ == element_precision (TREE_TYPE (@1)))
+ || (INTEGRAL_TYPE_P (type)
+ && (tree_nonzero_bits (@0)
+ & wi::mask (element_precision (TREE_TYPE (@1)) - 1,
+ true,
+ element_precision (type))) == 0)))))
+ (if (!VECTOR_TYPE_P (type)
+ && useless_type_conversion_p (TREE_TYPE (@3), TREE_TYPE (@1))
+ && element_precision (TREE_TYPE (@3)) < element_precision (type))
+ (convert (rshift @3 @2))
+ (rshift @0 @2))))
+
+/* Preserve explicit divisions by 0: the C++ front-end wants to detect
+ undefined behavior in constexpr evaluation, and assuming that the division
+ traps enables better optimizations than these anyway. */
+(for div (trunc_div ceil_div floor_div round_div exact_div)
+ /* 0 / X is always zero. */
+ (simplify
+ (div integer_zerop@0 @1)
+ /* But not for 0 / 0 so that we can get the proper warnings and errors. */
+ (if (!integer_zerop (@1))
+ @0))
+ /* X / -1 is -X. */
+ (simplify
+ (div @0 integer_minus_onep@1)
+ (if (!TYPE_UNSIGNED (type))
+ (negate @0)))
+ /* X / bool_range_Y is X. */
+ (simplify
+ (div @0 SSA_NAME@1)
+ (if (INTEGRAL_TYPE_P (type)
+ && ssa_name_has_boolean_range (@1)
+ && !flag_non_call_exceptions)
+ @0))
+ /* X / X is one. */
+ (simplify
+ (div @0 @0)
+ /* But not for 0 / 0 so that we can get the proper warnings and errors.
+ And not for _Fract types where we can't build 1. */
+ (if (!ALL_FRACT_MODE_P (TYPE_MODE (type))
+ && !integer_zerop (@0)
+ && (!flag_non_call_exceptions || tree_expr_nonzero_p (@0)))
+ { build_one_cst (type); }))
+ /* X / abs (X) is X < 0 ? -1 : 1. */
+ (simplify
+ (div:C @0 (abs @0))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && !integer_zerop (@0)
+ && (!flag_non_call_exceptions || tree_expr_nonzero_p (@0)))
+ (cond (lt @0 { build_zero_cst (type); })
+ { build_minus_one_cst (type); } { build_one_cst (type); })))
+ /* X / -X is -1. */
+ (simplify
+ (div:C @0 (negate @0))
+ (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && !integer_zerop (@0)
+ && (!flag_non_call_exceptions || tree_expr_nonzero_p (@0)))
+ { build_minus_one_cst (type); })))
+
+/* For unsigned integral types, FLOOR_DIV_EXPR is the same as
+ TRUNC_DIV_EXPR. Rewrite into the latter in this case. Similarly
+ for MOD instead of DIV. */
+(for floor_divmod (floor_div floor_mod)
+ trunc_divmod (trunc_div trunc_mod)
+ (simplify
+ (floor_divmod @0 @1)
+ (if ((INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+ && TYPE_UNSIGNED (type))
+ (trunc_divmod @0 @1))))
+
+/* 1 / X -> X == 1 for unsigned integer X.
+ 1 / X -> X >= -1 && X <= 1 ? X : 0 for signed integer X.
+ But not for 1 / 0 so that we can get proper warnings and errors,
+ and not for 1-bit integers as they are edge cases better handled
+ elsewhere. */
+(simplify
+ (trunc_div integer_onep@0 @1)
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) > 1
+ && !integer_zerop (@1)
+ && (!flag_non_call_exceptions || tree_expr_nonzero_p (@1)))
+ (if (TYPE_UNSIGNED (type))
+ (convert (eq:boolean_type_node @1 { build_one_cst (type); }))
+ (with { tree utype = unsigned_type_for (type); }
+ (cond (le (plus (convert:utype @1) { build_one_cst (utype); })
+ { build_int_cst (utype, 2); })
+ @1 { build_zero_cst (type); })))))
+
+/* Combine two successive divisions. Note that combining ceil_div
+ and floor_div is trickier and combining round_div even more so. */
+(for div (trunc_div exact_div)
+ (simplify
+ (div (div@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+ (with {
+ wi::overflow_type overflow;
+ wide_int mul = wi::mul (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (type), &overflow);
+ }
+ (if (div == EXACT_DIV_EXPR
+ || optimize_successive_divisions_p (@2, @3))
+ (if (!overflow)
+ (div @0 { wide_int_to_tree (type, mul); })
+ (if (TYPE_UNSIGNED (type)
+ || mul != wi::min_value (TYPE_PRECISION (type), SIGNED))
+ { build_zero_cst (type); }))))))
+
+/* Combine successive multiplications. Similar to above, but handling
+ overflow is different. */
+(simplify
+ (mult (mult @0 INTEGER_CST@1) INTEGER_CST@2)
+ (with {
+ wi::overflow_type overflow;
+ wide_int mul = wi::mul (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (type), &overflow);
+ }
+ /* Skip folding on overflow: the only special case is @1 * @2 == -INT_MIN,
+ otherwise undefined overflow implies that @0 must be zero. */
+ (if (!overflow || TYPE_OVERFLOW_WRAPS (type))
+ (mult @0 { wide_int_to_tree (type, mul); }))))
+
+/* Optimize A / A to 1.0 if we don't care about
+ NaNs or Infinities. */
+(simplify
+ (rdiv @0 @0)
+ (if (FLOAT_TYPE_P (type)
+ && ! HONOR_NANS (type)
+ && ! HONOR_INFINITIES (type))
+ { build_one_cst (type); }))
+
+/* Optimize -A / A to -1.0 if we don't care about
+ NaNs or Infinities. */
+(simplify
+ (rdiv:C @0 (negate @0))
+ (if (FLOAT_TYPE_P (type)
+ && ! HONOR_NANS (type)
+ && ! HONOR_INFINITIES (type))
+ { build_minus_one_cst (type); }))
+
+/* PR71078: x / abs(x) -> copysign (1.0, x) */
+(simplify
+ (rdiv:C (convert? @0) (convert? (abs @0)))
+ (if (SCALAR_FLOAT_TYPE_P (type)
+ && ! HONOR_NANS (type)
+ && ! HONOR_INFINITIES (type))
+ (switch
+ (if (types_match (type, float_type_node))
+ (BUILT_IN_COPYSIGNF { build_one_cst (type); } (convert @0)))
+ (if (types_match (type, double_type_node))
+ (BUILT_IN_COPYSIGN { build_one_cst (type); } (convert @0)))
+ (if (types_match (type, long_double_type_node))
+ (BUILT_IN_COPYSIGNL { build_one_cst (type); } (convert @0))))))
+
+/* In IEEE floating point, x/1 is not equivalent to x for snans. */
+(simplify
+ (rdiv @0 real_onep)
+ (if (!tree_expr_maybe_signaling_nan_p (@0))
+ (non_lvalue @0)))
+
+/* In IEEE floating point, x/-1 is not equivalent to -x for snans. */
+(simplify
+ (rdiv @0 real_minus_onep)
+ (if (!tree_expr_maybe_signaling_nan_p (@0))
+ (negate @0)))
+
+(if (flag_reciprocal_math)
+ /* Convert (A/B)/C to A/(B*C). */
+ (simplify
+ (rdiv (rdiv:s @0 @1) @2)
+ (rdiv @0 (mult @1 @2)))
+
+ /* Canonicalize x / (C1 * y) to (x * C2) / y. */
+ (simplify
+ (rdiv @0 (mult:s @1 REAL_CST@2))
+ (with
+ { tree tem = const_binop (RDIV_EXPR, type, build_one_cst (type), @2); }
+ (if (tem)
+ (rdiv (mult @0 { tem; } ) @1))))
+
+ /* Convert A/(B/C) to (A/B)*C */
+ (simplify
+ (rdiv @0 (rdiv:s @1 @2))
+ (mult (rdiv @0 @1) @2)))
+
+/* Simplify x / (- y) to -x / y. */
+(simplify
+ (rdiv @0 (negate @1))
+ (rdiv (negate @0) @1))
+
+(if (flag_unsafe_math_optimizations)
+ /* Simplify (C / x op 0.0) to x op 0.0 for C != 0, C != Inf/Nan.
+ Since C / x may underflow to zero, do this only for unsafe math. */
+ (for op (lt le gt ge)
+ neg_op (gt ge lt le)
+ (simplify
+ (op (rdiv REAL_CST@0 @1) real_zerop@2)
+ (if (!HONOR_SIGNED_ZEROS (@1) && !HONOR_INFINITIES (@1))
+ (switch
+ (if (real_less (&dconst0, TREE_REAL_CST_PTR (@0)))
+ (op @1 @2))
+ /* For C < 0, use the inverted operator. */
+ (if (real_less (TREE_REAL_CST_PTR (@0), &dconst0))
+ (neg_op @1 @2)))))))
+
+/* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */
+(for div (trunc_div ceil_div floor_div round_div exact_div)
+ (simplify
+ (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (integer_pow2p (@2)
+ && tree_int_cst_sgn (@2) > 0
+ && tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && wi::to_wide (@2) + wi::to_wide (@1) == 0)
+ (rshift (convert @0)
+ { build_int_cst (integer_type_node,
+ wi::exact_log2 (wi::to_wide (@2))); }))))
+
+/* If ARG1 is a constant, we can convert this to a multiply by the
+ reciprocal. This does not have the same rounding properties,
+ so only do this if -freciprocal-math. We can actually
+ always safely do it if ARG1 is a power of two, but it's hard to
+ tell if it is or not in a portable manner. */
+(for cst (REAL_CST COMPLEX_CST VECTOR_CST)
+ (simplify
+ (rdiv @0 cst@1)
+ (if (optimize)
+ (if (flag_reciprocal_math
+ && !real_zerop (@1))
+ (with
+ { tree tem = const_binop (RDIV_EXPR, type, build_one_cst (type), @1); }
+ (if (tem)
+ (mult @0 { tem; } )))
+ (if (cst != COMPLEX_CST)
+ (with { tree inverse = exact_inverse (type, @1); }
+ (if (inverse)
+ (mult @0 { inverse; } ))))))))
+
+(for mod (ceil_mod floor_mod round_mod trunc_mod)
+ /* 0 % X is always zero. */
+ (simplify
+ (mod integer_zerop@0 @1)
+ /* But not for 0 % 0 so that we can get the proper warnings and errors. */
+ (if (!integer_zerop (@1))
+ @0))
+ /* X % 1 is always zero. */
+ (simplify
+ (mod @0 integer_onep)
+ { build_zero_cst (type); })
+ /* X % -1 is zero. */
+ (simplify
+ (mod @0 integer_minus_onep@1)
+ (if (!TYPE_UNSIGNED (type))
+ { build_zero_cst (type); }))
+ /* X % X is zero. */
+ (simplify
+ (mod @0 @0)
+ /* But not for 0 % 0 so that we can get the proper warnings and errors. */
+ (if (!integer_zerop (@0))
+ { build_zero_cst (type); }))
+ /* (X % Y) % Y is just X % Y. */
+ (simplify
+ (mod (mod@2 @0 @1) @1)
+ @2)
+ /* From extract_muldiv_1: (X * C1) % C2 is zero if C1 is a multiple of C2. */
+ (simplify
+ (mod (mult @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (ANY_INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && wi::multiple_of_p (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (type)))
+ { build_zero_cst (type); }))
+ /* For (X % C) == 0, if X is signed and C is power of 2, use unsigned
+ modulo and comparison, since it is simpler and equivalent. */
+ (for cmp (eq ne)
+ (simplify
+ (cmp (mod @0 integer_pow2p@2) integer_zerop@1)
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (cmp (mod (convert:utype @0) (convert:utype @2)) (convert:utype @1)))))))
+
+/* X % -C is the same as X % C. */
+(simplify
+ (trunc_mod @0 INTEGER_CST@1)
+ (if (TYPE_SIGN (type) == SIGNED
+ && !TREE_OVERFLOW (@1)
+ && wi::neg_p (wi::to_wide (@1))
+ && !TYPE_OVERFLOW_TRAPS (type)
+ /* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
+ && !sign_bit_p (@1, @1))
+ (trunc_mod @0 (negate @1))))
+
+/* X % -Y is the same as X % Y. */
+(simplify
+ (trunc_mod @0 (convert? (negate @1)))
+ (if (INTEGRAL_TYPE_P (type)
+ && !TYPE_UNSIGNED (type)
+ && !TYPE_OVERFLOW_TRAPS (type)
+ && tree_nop_conversion_p (type, TREE_TYPE (@1))
+ /* Avoid this transformation if X might be INT_MIN or
+ Y might be -1, because we would then change valid
+ INT_MIN % -(-1) into invalid INT_MIN % -1. */
+ && (expr_not_equal_to (@0, wi::to_wide (TYPE_MIN_VALUE (type)))
+ || expr_not_equal_to (@1, wi::minus_one (TYPE_PRECISION
+ (TREE_TYPE (@1))))))
+ (trunc_mod @0 (convert @1))))
+
+/* X - (X / Y) * Y is the same as X % Y. */
+(simplify
+ (minus (convert1? @0) (convert2? (mult:c (trunc_div @@0 @@1) @1)))
+ (if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type))
+ (convert (trunc_mod @0 @1))))
+
+/* x * (1 + y / x) - y -> x - y % x */
+(simplify
+ (minus (mult:cs @0 (plus:s (trunc_div:s @1 @0) integer_onep)) @1)
+ (if (INTEGRAL_TYPE_P (type))
+ (minus @0 (trunc_mod @1 @0))))
+
+/* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
+ i.e. "X % C" into "X & (C - 1)", if X and C are positive.
+ Also optimize A % (C << N) where C is a power of 2,
+ to A & ((C << N) - 1).
+ Also optimize "A shift (B % C)", if C is a power of 2, to
+ "A shift (B & (C - 1))". SHIFT operation include "<<" and ">>"
+ and assume (B % C) is nonnegative as shifts negative values would
+ be UB. */
+(match (power_of_two_cand @1)
+ INTEGER_CST@1)
+(match (power_of_two_cand @1)
+ (lshift INTEGER_CST@1 @2))
+(for mod (trunc_mod floor_mod)
+ (for shift (lshift rshift)
+ (simplify
+ (shift @0 (mod @1 (power_of_two_cand@2 @3)))
+ (if (integer_pow2p (@3) && tree_int_cst_sgn (@3) > 0)
+ (shift @0 (bit_and @1 (minus @2 { build_int_cst (TREE_TYPE (@2),
+ 1); }))))))
+ (simplify
+ (mod @0 (convert? (power_of_two_cand@1 @2)))
+ (if ((TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (@0))
+ /* Allow any integral conversions of the divisor, except
+ conversion from narrower signed to wider unsigned type
+ where if @1 would be negative power of two, the divisor
+ would not be a power of two. */
+ && INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+ || TYPE_UNSIGNED (TREE_TYPE (@1))
+ || !TYPE_UNSIGNED (type))
+ && integer_pow2p (@2) && tree_int_cst_sgn (@2) > 0)
+ (with { tree utype = TREE_TYPE (@1);
+ if (!TYPE_OVERFLOW_WRAPS (utype))
+ utype = unsigned_type_for (utype); }
+ (bit_and @0 (convert (minus (convert:utype @1)
+ { build_one_cst (utype); })))))))
+
+/* Simplify (unsigned t * 2)/2 -> unsigned t & 0x7FFFFFFF. */
+(simplify
+ (trunc_div (mult @0 integer_pow2p@1) @1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (bit_and @0 { wide_int_to_tree
+ (type, wi::mask (TYPE_PRECISION (type)
+ - wi::exact_log2 (wi::to_wide (@1)),
+ false, TYPE_PRECISION (type))); })))
+
+/* Simplify (unsigned t / 2) * 2 -> unsigned t & ~1. */
+(simplify
+ (mult (trunc_div @0 integer_pow2p@1) @1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (bit_and @0 (negate @1))))
+
+/* Simplify (t * 2) / 2) -> t. */
+(for div (trunc_div ceil_div floor_div round_div exact_div)
+ (simplify
+ (div (mult:c @0 @1) @1)
+ (if (ANY_INTEGRAL_TYPE_P (type))
+ (if (TYPE_OVERFLOW_UNDEFINED (type))
+ @0
+#if GIMPLE
+ (with
+ {
+ bool overflowed = true;
+ value_range vr0, vr1;
+ if (INTEGRAL_TYPE_P (type)
+ && get_global_range_query ()->range_of_expr (vr0, @0)
+ && get_global_range_query ()->range_of_expr (vr1, @1)
+ && vr0.kind () == VR_RANGE
+ && vr1.kind () == VR_RANGE)
+ {
+ wide_int wmin0 = vr0.lower_bound ();
+ wide_int wmax0 = vr0.upper_bound ();
+ wide_int wmin1 = vr1.lower_bound ();
+ wide_int wmax1 = vr1.upper_bound ();
+ /* If the multiplication can't overflow/wrap around, then
+ it can be optimized too. */
+ wi::overflow_type min_ovf, max_ovf;
+ wi::mul (wmin0, wmin1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmax1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ {
+ wi::mul (wmin0, wmax1, TYPE_SIGN (type), &min_ovf);
+ wi::mul (wmax0, wmin1, TYPE_SIGN (type), &max_ovf);
+ if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ overflowed = false;
+ }
+ }
+ }
+ (if (!overflowed)
+ @0))
+#endif
+ ))))
+
+(for op (negate abs)
+ /* Simplify cos(-x) and cos(|x|) -> cos(x). Similarly for cosh. */
+ (for coss (COS COSH)
+ (simplify
+ (coss (op @0))
+ (coss @0)))
+ /* Simplify pow(-x, y) and pow(|x|,y) -> pow(x,y) if y is an even integer. */
+ (for pows (POW)
+ (simplify
+ (pows (op @0) REAL_CST@1)
+ (with { HOST_WIDE_INT n; }
+ (if (real_isinteger (&TREE_REAL_CST (@1), &n) && (n & 1) == 0)
+ (pows @0 @1)))))
+ /* Likewise for powi. */
+ (for pows (POWI)
+ (simplify
+ (pows (op @0) INTEGER_CST@1)
+ (if ((wi::to_wide (@1) & 1) == 0)
+ (pows @0 @1))))
+ /* Strip negate and abs from both operands of hypot. */
+ (for hypots (HYPOT)
+ (simplify
+ (hypots (op @0) @1)
+ (hypots @0 @1))
+ (simplify
+ (hypots @0 (op @1))
+ (hypots @0 @1)))
+ /* copysign(-x, y) and copysign(abs(x), y) -> copysign(x, y). */
+ (for copysigns (COPYSIGN_ALL)
+ (simplify
+ (copysigns (op @0) @1)
+ (copysigns @0 @1))))
+
+/* abs(x)*abs(x) -> x*x. Should be valid for all types. */
+(simplify
+ (mult (abs@1 @0) @1)
+ (mult @0 @0))
+
+/* Convert absu(x)*absu(x) -> x*x. */
+(simplify
+ (mult (absu@1 @0) @1)
+ (mult (convert@2 @0) @2))
+
+/* cos(copysign(x, y)) -> cos(x). Similarly for cosh. */
+(for coss (COS COSH)
+ copysigns (COPYSIGN)
+ (simplify
+ (coss (copysigns @0 @1))
+ (coss @0)))
+
+/* pow(copysign(x, y), z) -> pow(x, z) if z is an even integer. */
+(for pows (POW)
+ copysigns (COPYSIGN)
+ (simplify
+ (pows (copysigns @0 @2) REAL_CST@1)
+ (with { HOST_WIDE_INT n; }
+ (if (real_isinteger (&TREE_REAL_CST (@1), &n) && (n & 1) == 0)
+ (pows @0 @1)))))
+/* Likewise for powi. */
+(for pows (POWI)
+ copysigns (COPYSIGN)
+ (simplify
+ (pows (copysigns @0 @2) INTEGER_CST@1)
+ (if ((wi::to_wide (@1) & 1) == 0)
+ (pows @0 @1))))
+
+(for hypots (HYPOT)
+ copysigns (COPYSIGN)
+ /* hypot(copysign(x, y), z) -> hypot(x, z). */
+ (simplify
+ (hypots (copysigns @0 @1) @2)
+ (hypots @0 @2))
+ /* hypot(x, copysign(y, z)) -> hypot(x, y). */
+ (simplify
+ (hypots @0 (copysigns @1 @2))
+ (hypots @0 @1)))
+
+/* copysign(x, CST) -> [-]abs (x). */
+(for copysigns (COPYSIGN_ALL)
+ (simplify
+ (copysigns @0 REAL_CST@1)
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+ (negate (abs @0))
+ (abs @0))))
+
+/* copysign(copysign(x, y), z) -> copysign(x, z). */
+(for copysigns (COPYSIGN_ALL)
+ (simplify
+ (copysigns (copysigns @0 @1) @2)
+ (copysigns @0 @2)))
+
+/* copysign(x,y)*copysign(x,y) -> x*x. */
+(for copysigns (COPYSIGN_ALL)
+ (simplify
+ (mult (copysigns@2 @0 @1) @2)
+ (mult @0 @0)))
+
+/* ccos(-x) -> ccos(x). Similarly for ccosh. */
+(for ccoss (CCOS CCOSH)
+ (simplify
+ (ccoss (negate @0))
+ (ccoss @0)))
+
+/* cabs(-x) and cos(conj(x)) -> cabs(x). */
+(for ops (conj negate)
+ (for cabss (CABS)
+ (simplify
+ (cabss (ops @0))
+ (cabss @0))))
+
+/* Fold (a * (1 << b)) into (a << b) */
+(simplify
+ (mult:c @0 (convert? (lshift integer_onep@1 @2)))
+ (if (! FLOAT_TYPE_P (type)
+ && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (lshift @0 @2)))
+
+/* Fold (1 << (C - x)) where C = precision(type) - 1
+ into ((1 << C) >> x). */
+(simplify
+ (lshift integer_onep@0 (minus@1 INTEGER_CST@2 @3))
+ (if (INTEGRAL_TYPE_P (type)
+ && wi::eq_p (wi::to_wide (@2), TYPE_PRECISION (type) - 1)
+ && single_use (@1))
+ (if (TYPE_UNSIGNED (type))
+ (rshift (lshift @0 @2) @3)
+ (with
+ { tree utype = unsigned_type_for (type); }
+ (convert (rshift (lshift (convert:utype @0) @2) @3))))))
+
+/* Fold ((type)(a<0)) << SIGNBITOFA into ((type)a) & signbit. */
+(simplify
+ (lshift (convert (lt @0 integer_zerop@1)) INTEGER_CST@2)
+ (if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED
+ && wi::eq_p (wi::to_wide (@2), TYPE_PRECISION (TREE_TYPE (@0)) - 1))
+ (with { wide_int wone = wi::one (TYPE_PRECISION (type)); }
+ (bit_and (convert @0)
+ { wide_int_to_tree (type,
+ wi::lshift (wone, wi::to_wide (@2))); }))))
+
+/* Fold (-x >> C) into -(x > 0) where C = precision(type) - 1. */
+(for cst (INTEGER_CST VECTOR_CST)
+ (simplify
+ (rshift (negate:s @0) cst@1)
+ (if (!TYPE_UNSIGNED (type)
+ && TYPE_OVERFLOW_UNDEFINED (type))
+ (with { tree stype = TREE_TYPE (@1);
+ tree bt = truth_type_for (type);
+ tree zeros = build_zero_cst (type);
+ tree cst = NULL_TREE; }
+ (switch
+ /* Handle scalar case. */
+ (if (INTEGRAL_TYPE_P (type)
+ /* If we apply the rule to the scalar type before vectorization
+ we will enforce the result of the comparison being a bool
+ which will require an extra AND on the result that will be
+ indistinguishable from when the user did actually want 0
+ or 1 as the result so it can't be removed. */
+ && canonicalize_math_after_vectorization_p ()
+ && wi::eq_p (wi::to_wide (@1), TYPE_PRECISION (type) - 1))
+ (negate (convert (gt @0 { zeros; }))))
+ /* Handle vector case. */
+ (if (VECTOR_INTEGER_TYPE_P (type)
+ /* First check whether the target has the same mode for vector
+ comparison results as it's operands do. */
+ && TYPE_MODE (bt) == TYPE_MODE (type)
+ /* Then check to see if the target is able to expand the comparison
+ with the given type later on, otherwise we may ICE. */
+ && expand_vec_cmp_expr_p (type, bt, GT_EXPR)
+ && (cst = uniform_integer_cst_p (@1)) != NULL
+ && wi::eq_p (wi::to_wide (cst), element_precision (type) - 1))
+ (view_convert (gt:bt @0 { zeros; }))))))))
+
+/* Fold (C1/X)*C2 into (C1*C2)/X. */
+(simplify
+ (mult (rdiv@3 REAL_CST@0 @1) REAL_CST@2)
+ (if (flag_associative_math
+ && single_use (@3))
+ (with
+ { tree tem = const_binop (MULT_EXPR, type, @0, @2); }
+ (if (tem)
+ (rdiv { tem; } @1)))))
+
+/* Simplify ~X & X as zero. */
+(simplify
+ (bit_and:c (convert? @0) (convert? (bit_not @0)))
+ { build_zero_cst (type); })
+
+/* PR71636: Transform x & ((1U << b) - 1) -> x & ~(~0U << b); */
+(simplify
+ (bit_and:c @0 (plus:s (lshift:s integer_onep @1) integer_minus_onep))
+ (if (TYPE_UNSIGNED (type))
+ (bit_and @0 (bit_not (lshift { build_all_ones_cst (type); } @1)))))
+
+(for bitop (bit_and bit_ior)
+ cmp (eq ne)
+ /* PR35691: Transform
+ (x == 0 & y == 0) -> (x | typeof(x)(y)) == 0.
+ (x != 0 | y != 0) -> (x | typeof(x)(y)) != 0. */
+ (simplify
+ (bitop (cmp @0 integer_zerop@2) (cmp @1 integer_zerop))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
+ (cmp (bit_ior @0 (convert @1)) @2)))
+ /* Transform:
+ (x == -1 & y == -1) -> (x & typeof(x)(y)) == -1.
+ (x != -1 | y != -1) -> (x & typeof(x)(y)) != -1. */
+ (simplify
+ (bitop (cmp @0 integer_all_onesp@2) (cmp @1 integer_all_onesp))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
+ (cmp (bit_and @0 (convert @1)) @2))))
+
+/* Fold (A & ~B) - (A & B) into (A ^ B) - B. */
+(simplify
+ (minus (bit_and:cs @0 (bit_not @1)) (bit_and:cs @0 @1))
+ (minus (bit_xor @0 @1) @1))
+(simplify
+ (minus (bit_and:s @0 INTEGER_CST@2) (bit_and:s @0 INTEGER_CST@1))
+ (if (~wi::to_wide (@2) == wi::to_wide (@1))
+ (minus (bit_xor @0 @1) @1)))
+
+/* Fold (A & B) - (A & ~B) into B - (A ^ B). */
+(simplify
+ (minus (bit_and:cs @0 @1) (bit_and:cs @0 (bit_not @1)))
+ (minus @1 (bit_xor @0 @1)))
+
+/* Simplify (X & ~Y) |^+ (~X & Y) -> X ^ Y. */
+(for op (bit_ior bit_xor plus)
+ (simplify
+ (op (bit_and:c @0 (bit_not @1)) (bit_and:c (bit_not @0) @1))
+ (bit_xor @0 @1))
+ (simplify
+ (op:c (bit_and @0 INTEGER_CST@2) (bit_and (bit_not @0) INTEGER_CST@1))
+ (if (~wi::to_wide (@2) == wi::to_wide (@1))
+ (bit_xor @0 @1))))
+
+/* PR53979: Transform ((a ^ b) | a) -> (a | b) */
+(simplify
+ (bit_ior:c (bit_xor:c @0 @1) @0)
+ (bit_ior @0 @1))
+
+/* (a & ~b) | (a ^ b) --> a ^ b */
+(simplify
+ (bit_ior:c (bit_and:c @0 (bit_not @1)) (bit_xor:c@2 @0 @1))
+ @2)
+
+/* (a & ~b) ^ ~a --> ~(a & b) */
+(simplify
+ (bit_xor:c (bit_and:cs @0 (bit_not @1)) (bit_not @0))
+ (bit_not (bit_and @0 @1)))
+
+/* (~a & b) ^ a --> (a | b) */
+(simplify
+ (bit_xor:c (bit_and:cs (bit_not @0) @1) @0)
+ (bit_ior @0 @1))
+
+/* (a | b) & ~(a ^ b) --> a & b */
+(simplify
+ (bit_and:c (bit_ior @0 @1) (bit_not (bit_xor:c @0 @1)))
+ (bit_and @0 @1))
+
+/* a | ~(a ^ b) --> a | ~b */
+(simplify
+ (bit_ior:c @0 (bit_not:s (bit_xor:c @0 @1)))
+ (bit_ior @0 (bit_not @1)))
+
+/* (a | b) | (a &^ b) --> a | b */
+(for op (bit_and bit_xor)
+ (simplify
+ (bit_ior:c (bit_ior@2 @0 @1) (op:c @0 @1))
+ @2))
+
+/* (a & b) | ~(a ^ b) --> ~(a ^ b) */
+(simplify
+ (bit_ior:c (bit_and:c @0 @1) (bit_not@2 (bit_xor @0 @1)))
+ @2)
+
+/* ~(~a & b) --> a | ~b */
+(simplify
+ (bit_not (bit_and:cs (bit_not @0) @1))
+ (bit_ior @0 (bit_not @1)))
+
+/* ~(~a | b) --> a & ~b */
+(simplify
+ (bit_not (bit_ior:cs (bit_not @0) @1))
+ (bit_and @0 (bit_not @1)))
+
+/* (a ^ b) & ((b ^ c) ^ a) --> (a ^ b) & ~c */
+(simplify
+ (bit_and:c (bit_xor:c@3 @0 @1) (bit_xor:cs (bit_xor:cs @1 @2) @0))
+ (bit_and @3 (bit_not @2)))
+
+/* (a ^ b) | ((b ^ c) ^ a) --> (a ^ b) | c */
+(simplify
+ (bit_ior:c (bit_xor:c@3 @0 @1) (bit_xor:c (bit_xor:c @1 @2) @0))
+ (bit_ior @3 @2))
+
+#if GIMPLE
+/* (~X | C) ^ D -> (X | C) ^ (~D ^ C) if (~D ^ C) can be simplified. */
+(simplify
+ (bit_xor:c (bit_ior:cs (bit_not:s @0) @1) @2)
+ (bit_xor (bit_ior @0 @1) (bit_xor! (bit_not! @2) @1)))
+
+/* (~X & C) ^ D -> (X & C) ^ (D ^ C) if (D ^ C) can be simplified. */
+(simplify
+ (bit_xor:c (bit_and:cs (bit_not:s @0) @1) @2)
+ (bit_xor (bit_and @0 @1) (bit_xor! @2 @1)))
+
+/* Simplify (~X & Y) to X ^ Y if we know that (X & ~Y) is 0. */
+(simplify
+ (bit_and (bit_not SSA_NAME@0) INTEGER_CST@1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
+ (bit_xor @0 @1)))
+#endif
+
+/* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
+ ((A & N) + B) & M -> (A + B) & M
+ Similarly if (N & M) == 0,
+ ((A | N) + B) & M -> (A + B) & M
+ and for - instead of + (or unary - instead of +)
+ and/or ^ instead of |.
+ If B is constant and (B & M) == 0, fold into A & M. */
+(for op (plus minus)
+ (for bitop (bit_and bit_ior bit_xor)
+ (simplify
+ (bit_and (op:s (bitop:s@0 @3 INTEGER_CST@4) @1) INTEGER_CST@2)
+ (with
+ { tree pmop[2];
+ tree utype = fold_bit_and_mask (TREE_TYPE (@0), @2, op, @0, bitop,
+ @3, @4, @1, ERROR_MARK, NULL_TREE,
+ NULL_TREE, pmop); }
+ (if (utype)
+ (convert (bit_and (op (convert:utype { pmop[0]; })
+ (convert:utype { pmop[1]; }))
+ (convert:utype @2))))))
+ (simplify
+ (bit_and (op:s @0 (bitop:s@1 @3 INTEGER_CST@4)) INTEGER_CST@2)
+ (with
+ { tree pmop[2];
+ tree utype = fold_bit_and_mask (TREE_TYPE (@0), @2, op, @0, ERROR_MARK,
+ NULL_TREE, NULL_TREE, @1, bitop, @3,
+ @4, pmop); }
+ (if (utype)
+ (convert (bit_and (op (convert:utype { pmop[0]; })
+ (convert:utype { pmop[1]; }))
+ (convert:utype @2)))))))
+ (simplify
+ (bit_and (op:s @0 @1) INTEGER_CST@2)
+ (with
+ { tree pmop[2];
+ tree utype = fold_bit_and_mask (TREE_TYPE (@0), @2, op, @0, ERROR_MARK,
+ NULL_TREE, NULL_TREE, @1, ERROR_MARK,
+ NULL_TREE, NULL_TREE, pmop); }
+ (if (utype)
+ (convert (bit_and (op (convert:utype { pmop[0]; })
+ (convert:utype { pmop[1]; }))
+ (convert:utype @2)))))))
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+ (bit_and (negate:s (bitop:s@0 @2 INTEGER_CST@3)) INTEGER_CST@1)
+ (with
+ { tree pmop[2];
+ tree utype = fold_bit_and_mask (TREE_TYPE (@0), @1, NEGATE_EXPR, @0,
+ bitop, @2, @3, NULL_TREE, ERROR_MARK,
+ NULL_TREE, NULL_TREE, pmop); }
+ (if (utype)
+ (convert (bit_and (negate (convert:utype { pmop[0]; }))
+ (convert:utype @1)))))))
+
+/* X % Y is smaller than Y. */
+(for cmp (lt ge)
+ (simplify
+ (cmp (trunc_mod @0 @1) @1)
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
+ { constant_boolean_node (cmp == LT_EXPR, type); })))
+(for cmp (gt le)
+ (simplify
+ (cmp @1 (trunc_mod @0 @1))
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
+ { constant_boolean_node (cmp == GT_EXPR, type); })))
+
+/* x | ~0 -> ~0 */
+(simplify
+ (bit_ior @0 integer_all_onesp@1)
+ @1)
+
+/* x | 0 -> x */
+(simplify
+ (bit_ior @0 integer_zerop)
+ @0)
+
+/* x & 0 -> 0 */
+(simplify
+ (bit_and @0 integer_zerop@1)
+ @1)
+
+/* ~x | x -> -1 */
+/* ~x ^ x -> -1 */
+/* ~x + x -> -1 */
+(for op (bit_ior bit_xor plus)
+ (simplify
+ (op:c (convert? @0) (convert? (bit_not @0)))
+ (convert { build_all_ones_cst (TREE_TYPE (@0)); })))
+
+/* x ^ x -> 0 */
+(simplify
+ (bit_xor @0 @0)
+ { build_zero_cst (type); })
+
+/* Canonicalize X ^ ~0 to ~X. */
+(simplify
+ (bit_xor @0 integer_all_onesp@1)
+ (bit_not @0))
+
+/* x & ~0 -> x */
+(simplify
+ (bit_and @0 integer_all_onesp)
+ (non_lvalue @0))
+
+/* x & x -> x, x | x -> x */
+(for bitop (bit_and bit_ior)
+ (simplify
+ (bitop @0 @0)
+ (non_lvalue @0)))
+
+/* x & C -> x if we know that x & ~C == 0. */
+#if GIMPLE
+(simplify
+ (bit_and SSA_NAME@0 INTEGER_CST@1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && wi::bit_and_not (get_nonzero_bits (@0), wi::to_wide (@1)) == 0)
+ @0))
+#endif
+
+/* ~(~X - Y) -> X + Y and ~(~X + Y) -> X - Y. */
+(simplify
+ (bit_not (minus (bit_not @0) @1))
+ (plus @0 @1))
+(simplify
+ (bit_not (plus:c (bit_not @0) @1))
+ (minus @0 @1))
+
+/* ~(X - Y) -> ~X + Y. */
+(simplify
+ (bit_not (minus:s @0 @1))
+ (plus (bit_not @0) @1))
+(simplify
+ (bit_not (plus:s @0 INTEGER_CST@1))
+ (if ((INTEGRAL_TYPE_P (type)
+ && TYPE_UNSIGNED (type))
+ || (!TYPE_OVERFLOW_SANITIZED (type)
+ && may_negate_without_overflow_p (@1)))
+ (plus (bit_not @0) { const_unop (NEGATE_EXPR, type, @1); })))
+
+#if GIMPLE
+/* ~X + Y -> (Y - X) - 1. */
+(simplify
+ (plus:c (bit_not @0) @1)
+ (if (ANY_INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type)
+ /* -1 - X is folded to ~X, so we'd recurse endlessly. */
+ && !integer_all_onesp (@1))
+ (plus (minus @1 @0) { build_minus_one_cst (type); })
+ (if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (@1) == INTEGER_CST
+ && wi::to_wide (@1) != wi::min_value (TYPE_PRECISION (type),
+ SIGNED))
+ (minus (plus @1 { build_minus_one_cst (type); }) @0))))
+
+/* ~(X >> Y) -> ~X >> Y if ~X can be simplified. */
+(simplify
+ (bit_not (rshift:s @0 @1))
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (rshift (bit_not! @0) @1)
+ /* For logical right shifts, this is possible only if @0 doesn't
+ have MSB set and the logical right shift is changed into
+ arithmetic shift. */
+ (if (!wi::neg_p (tree_nonzero_bits (@0)))
+ (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+ (convert (rshift (bit_not! (convert:stype @0)) @1))))))
+#endif
+
+/* x + (x & 1) -> (x + 1) & ~1 */
+(simplify
+ (plus:c @0 (bit_and:s @0 integer_onep@1))
+ (bit_and (plus @0 @1) (bit_not @1)))
+
+/* x & ~(x & y) -> x & ~y */
+/* x | ~(x | y) -> x | ~y */
+(for bitop (bit_and bit_ior)
+ (simplify
+ (bitop:c @0 (bit_not (bitop:cs @0 @1)))
+ (bitop @0 (bit_not @1))))
+
+/* (~x & y) | ~(x | y) -> ~x */
+(simplify
+ (bit_ior:c (bit_and:c (bit_not@2 @0) @1) (bit_not (bit_ior:c @0 @1)))
+ @2)
+
+/* (x | y) ^ (x | ~y) -> ~x */
+(simplify
+ (bit_xor:c (bit_ior:c @0 @1) (bit_ior:c @0 (bit_not @1)))
+ (bit_not @0))
+
+/* (x & y) | ~(x | y) -> ~(x ^ y) */
+(simplify
+ (bit_ior:c (bit_and:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+ (bit_not (bit_xor @0 @1)))
+
+/* (~x | y) ^ (x ^ y) -> x | ~y */
+(simplify
+ (bit_xor:c (bit_ior:cs (bit_not @0) @1) (bit_xor:s @0 @1))
+ (bit_ior @0 (bit_not @1)))
+
+/* (x ^ y) | ~(x | y) -> ~(x & y) */
+(simplify
+ (bit_ior:c (bit_xor:s @0 @1) (bit_not:s (bit_ior:s @0 @1)))
+ (bit_not (bit_and @0 @1)))
+
+/* (x | y) & ~x -> y & ~x */
+/* (x & y) | ~x -> y | ~x */
+(for bitop (bit_and bit_ior)
+ rbitop (bit_ior bit_and)
+ (simplify
+ (bitop:c (rbitop:c @0 @1) (bit_not@2 @0))
+ (bitop @1 @2)))
+
+/* (x & y) ^ (x | y) -> x ^ y */
+(simplify
+ (bit_xor:c (bit_and @0 @1) (bit_ior @0 @1))
+ (bit_xor @0 @1))
+
+/* (x ^ y) ^ (x | y) -> x & y */
+(simplify
+ (bit_xor:c (bit_xor @0 @1) (bit_ior @0 @1))
+ (bit_and @0 @1))
+
+/* (x & y) + (x ^ y) -> x | y */
+/* (x & y) | (x ^ y) -> x | y */
+/* (x & y) ^ (x ^ y) -> x | y */
+(for op (plus bit_ior bit_xor)
+ (simplify
+ (op:c (bit_and @0 @1) (bit_xor @0 @1))
+ (bit_ior @0 @1)))
+
+/* (x & y) + (x | y) -> x + y */
+(simplify
+ (plus:c (bit_and @0 @1) (bit_ior @0 @1))
+ (plus @0 @1))
+
+/* (x + y) - (x | y) -> x & y */
+(simplify
+ (minus (plus @0 @1) (bit_ior @0 @1))
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type))
+ (bit_and @0 @1)))
+
+/* (x + y) - (x & y) -> x | y */
+(simplify
+ (minus (plus @0 @1) (bit_and @0 @1))
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type))
+ (bit_ior @0 @1)))
+
+/* (x | y) - y -> (x & ~y) */
+(simplify
+ (minus (bit_ior:cs @0 @1) @1)
+ (bit_and @0 (bit_not @1)))
+
+/* (x | y) - (x ^ y) -> x & y */
+(simplify
+ (minus (bit_ior @0 @1) (bit_xor @0 @1))
+ (bit_and @0 @1))
+
+/* (x | y) - (x & y) -> x ^ y */
+(simplify
+ (minus (bit_ior @0 @1) (bit_and @0 @1))
+ (bit_xor @0 @1))
+
+/* (x | y) & ~(x & y) -> x ^ y */
+(simplify
+ (bit_and:c (bit_ior @0 @1) (bit_not (bit_and @0 @1)))
+ (bit_xor @0 @1))
+
+/* (x | y) & (~x ^ y) -> x & y */
+(simplify
+ (bit_and:c (bit_ior:c @0 @1) (bit_xor:c @1 (bit_not @0)))
+ (bit_and @0 @1))
+
+/* (~x | y) & (x | ~y) -> ~(x ^ y) */
+(simplify
+ (bit_and (bit_ior:cs (bit_not @0) @1) (bit_ior:cs @0 (bit_not @1)))
+ (bit_not (bit_xor @0 @1)))
+
+/* (~x | y) ^ (x | ~y) -> x ^ y */
+(simplify
+ (bit_xor (bit_ior:c (bit_not @0) @1) (bit_ior:c @0 (bit_not @1)))
+ (bit_xor @0 @1))
+
+/* ((x & y) - (x | y)) - 1 -> ~(x ^ y) */
+(simplify
+ (plus (nop_convert1? (minus@2 (nop_convert2? (bit_and:c @0 @1))
+ (nop_convert2? (bit_ior @0 @1))))
+ integer_all_onesp)
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2))
+ && !TYPE_SATURATING (TREE_TYPE (@2)))
+ (bit_not (convert (bit_xor @0 @1)))))
+(simplify
+ (minus (nop_convert1? (plus@2 (nop_convert2? (bit_and:c @0 @1))
+ integer_all_onesp))
+ (nop_convert3? (bit_ior @0 @1)))
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2))
+ && !TYPE_SATURATING (TREE_TYPE (@2)))
+ (bit_not (convert (bit_xor @0 @1)))))
+(simplify
+ (minus (nop_convert1? (bit_and @0 @1))
+ (nop_convert2? (plus@2 (nop_convert3? (bit_ior:c @0 @1))
+ integer_onep)))
+ (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2))
+ && !TYPE_SATURATING (TREE_TYPE (@2)))
+ (bit_not (convert (bit_xor @0 @1)))))
+
+/* ~x & ~y -> ~(x | y)
+ ~x | ~y -> ~(x & y) */
+(for op (bit_and bit_ior)
+ rop (bit_ior bit_and)
+ (simplify
+ (op (convert1? (bit_not @0)) (convert2? (bit_not @1)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+ && element_precision (type) <= element_precision (TREE_TYPE (@1)))
+ (bit_not (rop (convert @0) (convert @1))))))
+
+/* If we are XORing or adding two BIT_AND_EXPR's, both of which are and'ing
+ with a constant, and the two constants have no bits in common,
+ we should treat this as a BIT_IOR_EXPR since this may produce more
+ simplifications. */
+(for op (bit_xor plus)
+ (simplify
+ (op (convert1? (bit_and@4 @0 INTEGER_CST@1))
+ (convert2? (bit_and@5 @2 INTEGER_CST@3)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@2))
+ && (wi::to_wide (@1) & wi::to_wide (@3)) == 0)
+ (bit_ior (convert @4) (convert @5)))))
+
+/* (X | Y) ^ X -> Y & ~ X*/
+(simplify
+ (bit_xor:c (convert1? (bit_ior:c @@0 @1)) (convert2? @0))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (bit_and @1 (bit_not @0)))))
+
+/* Convert ~X ^ ~Y to X ^ Y. */
+(simplify
+ (bit_xor (convert1? (bit_not @0)) (convert2? (bit_not @1)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+ && element_precision (type) <= element_precision (TREE_TYPE (@1)))
+ (bit_xor (convert @0) (convert @1))))
+
+/* Convert ~X ^ C to X ^ ~C. */
+(simplify
+ (bit_xor (convert? (bit_not @0)) INTEGER_CST@1)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (bit_xor (convert @0) (bit_not @1))))
+
+/* Fold (X & Y) ^ Y and (X ^ Y) & Y as ~X & Y. */
+(for opo (bit_and bit_xor)
+ opi (bit_xor bit_and)
+ (simplify
+ (opo:c (opi:cs @0 @1) @1)
+ (bit_and (bit_not @0) @1)))
+
+/* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
+ operands are another bit-wise operation with a common input. If so,
+ distribute the bit operations to save an operation and possibly two if
+ constants are involved. For example, convert
+ (A | B) & (A | C) into A | (B & C)
+ Further simplification will occur if B and C are constants. */
+(for op (bit_and bit_ior bit_xor)
+ rop (bit_ior bit_and bit_and)
+ (simplify
+ (op (convert? (rop:c @@0 @1)) (convert? (rop:c @0 @2)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+ && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+ (rop (convert @0) (op (convert @1) (convert @2))))))
+
+/* Some simple reassociation for bit operations, also handled in reassoc. */
+/* (X & Y) & Y -> X & Y
+ (X | Y) | Y -> X | Y */
+(for op (bit_and bit_ior)
+ (simplify
+ (op:c (convert1?@2 (op:c @0 @@1)) (convert2? @1))
+ @2))
+/* (X ^ Y) ^ Y -> X */
+(simplify
+ (bit_xor:c (convert1? (bit_xor:c @0 @@1)) (convert2? @1))
+ (convert @0))
+/* (X & Y) & (X & Z) -> (X & Y) & Z
+ (X | Y) | (X | Z) -> (X | Y) | Z */
+(for op (bit_and bit_ior)
+ (simplify
+ (op (convert1?@3 (op:c@4 @0 @1)) (convert2?@5 (op:c@6 @0 @2)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+ && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+ (if (single_use (@5) && single_use (@6))
+ (op @3 (convert @2))
+ (if (single_use (@3) && single_use (@4))
+ (op (convert @1) @5))))))
+/* (X ^ Y) ^ (X ^ Z) -> Y ^ Z */
+(simplify
+ (bit_xor (convert1? (bit_xor:c @0 @1)) (convert2? (bit_xor:c @0 @2)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+ && tree_nop_conversion_p (type, TREE_TYPE (@2)))
+ (bit_xor (convert @1) (convert @2))))
+
+/* Convert abs (abs (X)) into abs (X).
+ also absu (absu (X)) into absu (X). */
+(simplify
+ (abs (abs@1 @0))
+ @1)
+
+(simplify
+ (absu (convert@2 (absu@1 @0)))
+ (if (tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@1)))
+ @1))
+
+/* Convert abs[u] (-X) -> abs[u] (X). */
+(simplify
+ (abs (negate @0))
+ (abs @0))
+
+(simplify
+ (absu (negate @0))
+ (absu @0))
+
+/* Convert abs[u] (X) where X is nonnegative -> (X). */
+(simplify
+ (abs tree_expr_nonnegative_p@0)
+ @0)
+
+(simplify
+ (absu tree_expr_nonnegative_p@0)
+ (convert @0))
+
+/* Simplify (-(X < 0) | 1) * X into abs (X) or absu(X). */
+(simplify
+ (mult:c (nop_convert1?
+ (bit_ior (nop_convert2? (negate (convert? (lt @0 integer_zerop))))
+ integer_onep))
+ (nop_convert3? @0))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (if (TYPE_UNSIGNED (type))
+ (absu @0)
+ (abs @0)
+ )
+ )
+)
+
+/* A few cases of fold-const.cc negate_expr_p predicate. */
+(match negate_expr_p
+ INTEGER_CST
+ (if ((INTEGRAL_TYPE_P (type)
+ && TYPE_UNSIGNED (type))
+ || (!TYPE_OVERFLOW_SANITIZED (type)
+ && may_negate_without_overflow_p (t)))))
+(match negate_expr_p
+ FIXED_CST)
+(match negate_expr_p
+ (negate @0)
+ (if (!TYPE_OVERFLOW_SANITIZED (type))))
+(match negate_expr_p
+ REAL_CST
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (t)))))
+/* VECTOR_CST handling of non-wrapping types would recurse in unsupported
+ ways. */
+(match negate_expr_p
+ VECTOR_CST
+ (if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))))
+(match negate_expr_p
+ (minus @0 @1)
+ (if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type))
+ || (FLOAT_TYPE_P (type)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && !HONOR_SIGNED_ZEROS (type)))))
+
+/* (-A) * (-B) -> A * B */
+(simplify
+ (mult:c (convert1? (negate @0)) (convert2? negate_expr_p@1))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (mult (convert @0) (convert (negate @1)))))
+
+/* -(A + B) -> (-B) - A. */
+(simplify
+ (negate (plus:c @0 negate_expr_p@1))
+ (if (!HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && !HONOR_SIGNED_ZEROS (type))
+ (minus (negate @1) @0)))
+
+/* -(A - B) -> B - A. */
+(simplify
+ (negate (minus @0 @1))
+ (if ((ANY_INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_SANITIZED (type))
+ || (FLOAT_TYPE_P (type)
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && !HONOR_SIGNED_ZEROS (type)))
+ (minus @1 @0)))
+(simplify
+ (negate (pointer_diff @0 @1))
+ (if (TYPE_OVERFLOW_UNDEFINED (type))
+ (pointer_diff @1 @0)))
+
+/* A - B -> A + (-B) if B is easily negatable. */
+(simplify
+ (minus @0 negate_expr_p@1)
+ (if (!FIXED_POINT_TYPE_P (type))
+ (plus @0 (negate @1))))
+
+/* Other simplifications of negation (c.f. fold_negate_expr_1). */
+(simplify
+ (negate (mult:c@0 @1 negate_expr_p@2))
+ (if (! TYPE_UNSIGNED (type)
+ && ! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (mult @1 (negate @2))))
+
+(simplify
+ (negate (rdiv@0 @1 negate_expr_p@2))
+ (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (rdiv @1 (negate @2))))
+
+(simplify
+ (negate (rdiv@0 negate_expr_p@1 @2))
+ (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type)
+ && single_use (@0))
+ (rdiv (negate @1) @2)))
+
+/* Fold -((int)x >> (prec - 1)) into (unsigned)x >> (prec - 1). */
+(simplify
+ (negate (convert? (rshift @0 INTEGER_CST@1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && wi::to_wide (@1) == element_precision (type) - 1)
+ (with { tree stype = TREE_TYPE (@0);
+ tree ntype = TYPE_UNSIGNED (stype) ? signed_type_for (stype)
+ : unsigned_type_for (stype); }
+ (if (VECTOR_TYPE_P (type))
+ (view_convert (rshift (view_convert:ntype @0) @1))
+ (convert (rshift (convert:ntype @0) @1))))))
+
+/* Try to fold (type) X op CST -> (type) (X op ((type-x) CST))
+ when profitable.
+ For bitwise binary operations apply operand conversions to the
+ binary operation result instead of to the operands. This allows
+ to combine successive conversions and bitwise binary operations.
+ We combine the above two cases by using a conditional convert. */
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+ (bitop (convert@2 @0) (convert?@3 @1))
+ (if (((TREE_CODE (@1) == INTEGER_CST
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && (int_fits_type_p (@1, TREE_TYPE (@0))
+ || tree_nop_conversion_p (TREE_TYPE (@0), type)))
+ || types_match (@0, @1))
+ /* ??? This transform conflicts with fold-const.cc doing
+ Convert (T)(x & c) into (T)x & (T)c, if c is an integer
+ constants (if x has signed type, the sign bit cannot be set
+ in c). This folds extension into the BIT_AND_EXPR.
+ Restrict it to GIMPLE to avoid endless recursions. */
+ && (bitop != BIT_AND_EXPR || GIMPLE)
+ && (/* That's a good idea if the conversion widens the operand, thus
+ after hoisting the conversion the operation will be narrower.
+ It is also a good if the conversion is a nop as moves the
+ conversion to one side; allowing for combining of the conversions. */
+ TYPE_PRECISION (TREE_TYPE (@0)) < TYPE_PRECISION (type)
+ /* The conversion check for being a nop can only be done at the gimple
+ level as fold_binary has some re-association code which can conflict
+ with this if there is a "constant" which is not a full INTEGER_CST. */
+ || (GIMPLE && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type))
+ /* It's also a good idea if the conversion is to a non-integer
+ mode. */
+ || GET_MODE_CLASS (TYPE_MODE (type)) != MODE_INT
+ /* Or if the precision of TO is not the same as the precision
+ of its mode. */
+ || !type_has_mode_precision_p (type)
+ /* In GIMPLE, getting rid of 2 conversions for one new results
+ in smaller IL. */
+ || (GIMPLE
+ && TREE_CODE (@1) != INTEGER_CST
+ && tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && single_use (@2)
+ && single_use (@3))))
+ (convert (bitop @0 (convert @1)))))
+ /* In GIMPLE, getting rid of 2 conversions for one new results
+ in smaller IL. */
+ (simplify
+ (convert (bitop:cs@2 (nop_convert:s @0) @1))
+ (if (GIMPLE
+ && TREE_CODE (@1) != INTEGER_CST
+ && tree_nop_conversion_p (type, TREE_TYPE (@2))
+ && types_match (type, @0))
+ (bitop @0 (convert @1)))))
+
+(for bitop (bit_and bit_ior)
+ rbitop (bit_ior bit_and)
+ /* (x | y) & x -> x */
+ /* (x & y) | x -> x */
+ (simplify
+ (bitop:c (rbitop:c @0 @1) @0)
+ @0)
+ /* (~x | y) & x -> x & y */
+ /* (~x & y) | x -> x | y */
+ (simplify
+ (bitop:c (rbitop:c (bit_not @0) @1) @0)
+ (bitop @0 @1)))
+
+/* ((x | y) & z) | x -> (z & y) | x */
+(simplify
+ (bit_ior:c (bit_and:cs (bit_ior:cs @0 @1) @2) @0)
+ (bit_ior (bit_and @2 @1) @0))
+
+/* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */
+(simplify
+ (bit_and (bit_ior @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
+ (bit_ior (bit_and @0 @2) (bit_and @1 @2)))
+
+/* Combine successive equal operations with constants. */
+(for bitop (bit_and bit_ior bit_xor)
+ (simplify
+ (bitop (bitop @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
+ (if (!CONSTANT_CLASS_P (@0))
+ /* This is the canonical form regardless of whether (bitop @1 @2) can be
+ folded to a constant. */
+ (bitop @0 (bitop @1 @2))
+ /* In this case we have three constants and (bitop @0 @1) doesn't fold
+ to a constant. This can happen if @0 or @1 is a POLY_INT_CST and if
+ the values involved are such that the operation can't be decided at
+ compile time. Try folding one of @0 or @1 with @2 to see whether
+ that combination can be decided at compile time.
+
+ Keep the existing form if both folds fail, to avoid endless
+ oscillation. */
+ (with { tree cst1 = const_binop (bitop, type, @0, @2); }
+ (if (cst1)
+ (bitop @1 { cst1; })
+ (with { tree cst2 = const_binop (bitop, type, @1, @2); }
+ (if (cst2)
+ (bitop @0 { cst2; }))))))))
+
+/* Try simple folding for X op !X, and X op X with the help
+ of the truth_valued_p and logical_inverted_value predicates. */
+(match truth_valued_p
+ @0
+ (if (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
+(for op (tcc_comparison truth_and truth_andif truth_or truth_orif truth_xor)
+ (match truth_valued_p
+ (op @0 @1)))
+(match truth_valued_p
+ (truth_not @0))
+
+(match (logical_inverted_value @0)
+ (truth_not @0))
+(match (logical_inverted_value @0)
+ (bit_not truth_valued_p@0))
+(match (logical_inverted_value @0)
+ (eq @0 integer_zerop))
+(match (logical_inverted_value @0)
+ (ne truth_valued_p@0 integer_truep))
+(match (logical_inverted_value @0)
+ (bit_xor truth_valued_p@0 integer_truep))
+
+/* X & !X -> 0. */
+(simplify
+ (bit_and:c @0 (logical_inverted_value @0))
+ { build_zero_cst (type); })
+/* X | !X and X ^ !X -> 1, , if X is truth-valued. */
+(for op (bit_ior bit_xor)
+ (simplify
+ (op:c truth_valued_p@0 (logical_inverted_value @0))
+ { constant_boolean_node (true, type); }))
+/* X ==/!= !X is false/true. */
+(for op (eq ne)
+ (simplify
+ (op:c truth_valued_p@0 (logical_inverted_value @0))
+ { constant_boolean_node (op == NE_EXPR ? true : false, type); }))
+
+/* ~~x -> x */
+(simplify
+ (bit_not (bit_not @0))
+ @0)
+
+/* Convert ~ (-A) to A - 1. */
+(simplify
+ (bit_not (convert? (negate @0)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+ || !TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (convert (minus @0 { build_each_one_cst (TREE_TYPE (@0)); }))))
+
+/* Convert - (~A) to A + 1. */
+(simplify
+ (negate (nop_convert? (bit_not @0)))
+ (plus (view_convert @0) { build_each_one_cst (type); }))
+
+/* (a & b) ^ (a == b) -> !(a | b) */
+/* (a & b) == (a ^ b) -> !(a | b) */
+(for first_op (bit_xor eq)
+ second_op (eq bit_xor)
+ (simplify
+ (first_op:c (bit_and:c truth_valued_p@0 truth_valued_p@1) (second_op:c @0 @1))
+ (bit_not (bit_ior @0 @1))))
+
+/* Convert ~ (A - 1) or ~ (A + -1) to -A. */
+(simplify
+ (bit_not (convert? (minus @0 integer_each_onep)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+ || !TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (convert (negate @0))))
+(simplify
+ (bit_not (convert? (plus @0 integer_all_onesp)))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@0))
+ || !TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (convert (negate @0))))
+
+/* Part of convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
+(simplify
+ (bit_not (convert? (bit_xor @0 INTEGER_CST@1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (bit_xor @0 (bit_not @1)))))
+(simplify
+ (bit_not (convert? (bit_xor:c (bit_not @0) @1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (convert (bit_xor @0 @1))))
+
+/* Otherwise prefer ~(X ^ Y) to ~X ^ Y as more canonical. */
+(simplify
+ (bit_xor:c (nop_convert?:s (bit_not:s @0)) @1)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (bit_not (bit_xor (view_convert @0) @1))))
+
+/* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */
+(simplify
+ (bit_ior:c (bit_and:cs @0 (bit_not @2)) (bit_and:cs @1 @2))
+ (bit_xor (bit_and (bit_xor @0 @1) @2) @0))
+
+/* Fold A - (A & B) into ~B & A. */
+(simplify
+ (minus (convert1? @0) (convert2?:s (bit_and:cs @@0 @1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@1)))
+ (convert (bit_and (bit_not @1) @0))))
+
+/* (m1 CMP m2) * d -> (m1 CMP m2) ? d : 0 */
+(if (!canonicalize_math_p ())
+ (for cmp (gt lt ge le)
+ (simplify
+ (mult (convert (cmp @0 @1)) @2)
+ (cond (cmp @0 @1) @2 { build_zero_cst (type); }))))
+
+/* For integral types with undefined overflow and C != 0 fold
+ x * C EQ/NE y * C into x EQ/NE y. */
+(for cmp (eq ne)
+ (simplify
+ (cmp (mult:c @0 @1) (mult:c @2 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && tree_expr_nonzero_p (@1))
+ (cmp @0 @2))))
+
+/* For integral types with wrapping overflow and C odd fold
+ x * C EQ/NE y * C into x EQ/NE y. */
+(for cmp (eq ne)
+ (simplify
+ (cmp (mult @0 INTEGER_CST@1) (mult @2 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
+ && (TREE_INT_CST_LOW (@1) & 1) != 0)
+ (cmp @0 @2))))
+
+/* For integral types with undefined overflow and C != 0 fold
+ x * C RELOP y * C into:
+
+ x RELOP y for nonnegative C
+ y RELOP x for negative C */
+(for cmp (lt gt le ge)
+ (simplify
+ (cmp (mult:c @0 @1) (mult:c @2 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (if (tree_expr_nonnegative_p (@1) && tree_expr_nonzero_p (@1))
+ (cmp @0 @2)
+ (if (TREE_CODE (@1) == INTEGER_CST
+ && wi::neg_p (wi::to_wide (@1), TYPE_SIGN (TREE_TYPE (@1))))
+ (cmp @2 @0))))))
+
+/* (X - 1U) <= INT_MAX-1U into (int) X > 0. */
+(for cmp (le gt)
+ icmp (gt le)
+ (simplify
+ (cmp (plus @0 integer_minus_onep@1) INTEGER_CST@2)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_UNSIGNED (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@0)) > 1
+ && (wi::to_wide (@2)
+ == wi::max_value (TYPE_PRECISION (TREE_TYPE (@0)), SIGNED) - 1))
+ (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+ (icmp (convert:stype @0) { build_int_cst (stype, 0); })))))
+
+/* X / 4 < Y / 4 iff X < Y when the division is known to be exact. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (convert?@3 (exact_div @0 INTEGER_CST@2)) (convert? (exact_div @1 @2)))
+ (if (element_precision (@3) >= element_precision (@0)
+ && types_match (@0, @1))
+ (if (wi::lt_p (wi::to_wide (@2), 0, TYPE_SIGN (TREE_TYPE (@2))))
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@3)))
+ (cmp @1 @0)
+ (if (tree_expr_nonzero_p (@0) && tree_expr_nonzero_p (@1))
+ (with
+ {
+ tree utype = unsigned_type_for (TREE_TYPE (@0));
+ }
+ (cmp (convert:utype @1) (convert:utype @0)))))
+ (if (wi::gt_p (wi::to_wide (@2), 1, TYPE_SIGN (TREE_TYPE (@2))))
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)) || !TYPE_UNSIGNED (TREE_TYPE (@3)))
+ (cmp @0 @1)
+ (with
+ {
+ tree utype = unsigned_type_for (TREE_TYPE (@0));
+ }
+ (cmp (convert:utype @0) (convert:utype @1)))))))))
+
+/* X / C1 op C2 into a simple range test. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (trunc_div:s @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && integer_nonzerop (@1)
+ && !TREE_OVERFLOW (@1)
+ && !TREE_OVERFLOW (@2))
+ (with { tree lo, hi; bool neg_overflow;
+ enum tree_code code = fold_div_compare (cmp, @1, @2, &lo, &hi,
+ &neg_overflow); }
+ (switch
+ (if (code == LT_EXPR || code == GE_EXPR)
+ (if (TREE_OVERFLOW (lo))
+ { build_int_cst (type, (code == LT_EXPR) ^ neg_overflow); }
+ (if (code == LT_EXPR)
+ (lt @0 { lo; })
+ (ge @0 { lo; }))))
+ (if (code == LE_EXPR || code == GT_EXPR)
+ (if (TREE_OVERFLOW (hi))
+ { build_int_cst (type, (code == LE_EXPR) ^ neg_overflow); }
+ (if (code == LE_EXPR)
+ (le @0 { hi; })
+ (gt @0 { hi; }))))
+ (if (!lo && !hi)
+ { build_int_cst (type, code == NE_EXPR); })
+ (if (code == EQ_EXPR && !hi)
+ (ge @0 { lo; }))
+ (if (code == EQ_EXPR && !lo)
+ (le @0 { hi; }))
+ (if (code == NE_EXPR && !hi)
+ (lt @0 { lo; }))
+ (if (code == NE_EXPR && !lo)
+ (gt @0 { hi; }))
+ (if (GENERIC)
+ { build_range_check (UNKNOWN_LOCATION, type, @0, code == EQ_EXPR,
+ lo, hi); })
+ (with
+ {
+ tree etype = range_check_type (TREE_TYPE (@0));
+ if (etype)
+ {
+ hi = fold_convert (etype, hi);
+ lo = fold_convert (etype, lo);
+ hi = const_binop (MINUS_EXPR, etype, hi, lo);
+ }
+ }
+ (if (etype && hi && !TREE_OVERFLOW (hi))
+ (if (code == EQ_EXPR)
+ (le (minus (convert:etype @0) { lo; }) { hi; })
+ (gt (minus (convert:etype @0) { lo; }) { hi; })))))))))
+
+/* X + Z < Y + Z is the same as X < Y when there is no overflow. */
+(for op (lt le ge gt)
+ (simplify
+ (op (plus:c @0 @2) (plus:c @1 @2))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (op @0 @1))))
+/* For equality and subtraction, this is also true with wrapping overflow. */
+(for op (eq ne minus)
+ (simplify
+ (op (plus:c @0 @2) (plus:c @1 @2))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
+ (op @0 @1))))
+
+/* X - Z < Y - Z is the same as X < Y when there is no overflow. */
+(for op (lt le ge gt)
+ (simplify
+ (op (minus @0 @2) (minus @1 @2))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (op @0 @1))))
+/* For equality and subtraction, this is also true with wrapping overflow. */
+(for op (eq ne minus)
+ (simplify
+ (op (minus @0 @2) (minus @1 @2))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
+ (op @0 @1))))
+/* And for pointers... */
+(for op (simple_comparison)
+ (simplify
+ (op (pointer_diff@3 @0 @2) (pointer_diff @1 @2))
+ (if (!TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)))
+ (op @0 @1))))
+(simplify
+ (minus (pointer_diff@3 @0 @2) (pointer_diff @1 @2))
+ (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@3))
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)))
+ (pointer_diff @0 @1)))
+
+/* Z - X < Z - Y is the same as Y < X when there is no overflow. */
+(for op (lt le ge gt)
+ (simplify
+ (op (minus @2 @0) (minus @2 @1))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (op @1 @0))))
+/* For equality and subtraction, this is also true with wrapping overflow. */
+(for op (eq ne minus)
+ (simplify
+ (op (minus @2 @0) (minus @2 @1))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
+ (op @1 @0))))
+/* And for pointers... */
+(for op (simple_comparison)
+ (simplify
+ (op (pointer_diff@3 @2 @0) (pointer_diff @2 @1))
+ (if (!TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)))
+ (op @1 @0))))
+(simplify
+ (minus (pointer_diff@3 @2 @0) (pointer_diff @2 @1))
+ (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@3))
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)))
+ (pointer_diff @1 @0)))
+
+/* X + Y < Y is the same as X < 0 when there is no overflow. */
+(for op (lt le gt ge)
+ (simplify
+ (op:c (plus:c@2 @0 @1) @1)
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
+ && (CONSTANT_CLASS_P (@0) || single_use (@2)))
+ (op @0 { build_zero_cst (TREE_TYPE (@0)); }))))
+/* For equality, this is also true with wrapping overflow. */
+(for op (eq ne)
+ (simplify
+ (op:c (nop_convert?@3 (plus:c@2 @0 (convert1? @1))) (convert2? @1))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ && (CONSTANT_CLASS_P (@0) || (single_use (@2) && single_use (@3)))
+ && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@2))
+ && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@1)))
+ (op @0 { build_zero_cst (TREE_TYPE (@0)); })))
+ (simplify
+ (op:c (nop_convert?@3 (pointer_plus@2 (convert1? @0) @1)) (convert2? @0))
+ (if (tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0))
+ && tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0))
+ && (CONSTANT_CLASS_P (@1) || (single_use (@2) && single_use (@3))))
+ (op @1 { build_zero_cst (TREE_TYPE (@1)); }))))
+
+/* X - Y < X is the same as Y > 0 when there is no overflow.
+ For equality, this is also true with wrapping overflow. */
+(for op (simple_comparison)
+ (simplify
+ (op:c @0 (minus@2 @0 @1))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ || ((op == EQ_EXPR || op == NE_EXPR)
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))))
+ && (CONSTANT_CLASS_P (@1) || single_use (@2)))
+ (op @1 { build_zero_cst (TREE_TYPE (@1)); }))))
+
+/* Transform:
+ (X / Y) == 0 -> X < Y if X, Y are unsigned.
+ (X / Y) != 0 -> X >= Y, if X, Y are unsigned. */
+(for cmp (eq ne)
+ ocmp (lt ge)
+ (simplify
+ (cmp (trunc_div @0 @1) integer_zerop)
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0))
+ /* Complex ==/!= is allowed, but not </>=. */
+ && TREE_CODE (TREE_TYPE (@0)) != COMPLEX_TYPE
+ && (VECTOR_TYPE_P (type) || !VECTOR_TYPE_P (TREE_TYPE (@0))))
+ (ocmp @0 @1))))
+
+/* X == C - X can never be true if C is odd. */
+(for cmp (eq ne)
+ (simplify
+ (cmp:c (convert? @0) (convert1? (minus INTEGER_CST@1 (convert2? @0))))
+ (if (TREE_INT_CST_LOW (@1) & 1)
+ { constant_boolean_node (cmp == NE_EXPR, type); })))
+
+/* Arguments on which one can call get_nonzero_bits to get the bits
+ possibly set. */
+(match with_possible_nonzero_bits
+ INTEGER_CST@0)
+(match with_possible_nonzero_bits
+ SSA_NAME@0
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))))
+/* Slightly extended version, do not make it recursive to keep it cheap. */
+(match (with_possible_nonzero_bits2 @0)
+ with_possible_nonzero_bits@0)
+(match (with_possible_nonzero_bits2 @0)
+ (bit_and:c with_possible_nonzero_bits@0 @2))
+
+/* Same for bits that are known to be set, but we do not have
+ an equivalent to get_nonzero_bits yet. */
+(match (with_certain_nonzero_bits2 @0)
+ INTEGER_CST@0)
+(match (with_certain_nonzero_bits2 @0)
+ (bit_ior @1 INTEGER_CST@0))
+
+/* X == C (or X & Z == Y | C) is impossible if ~nonzero(X) & C != 0. */
+(for cmp (eq ne)
+ (simplify
+ (cmp:c (with_possible_nonzero_bits2 @0) (with_certain_nonzero_bits2 @1))
+ (if (wi::bit_and_not (wi::to_wide (@1), get_nonzero_bits (@0)) != 0)
+ { constant_boolean_node (cmp == NE_EXPR, type); })))
+
+/* ((X inner_op C0) outer_op C1)
+ With X being a tree where value_range has reasoned certain bits to always be
+ zero throughout its computed value range,
+ inner_op = {|,^}, outer_op = {|,^} and inner_op != outer_op
+ where zero_mask has 1's for all bits that are sure to be 0 in
+ and 0's otherwise.
+ if (inner_op == '^') C0 &= ~C1;
+ if ((C0 & ~zero_mask) == 0) then emit (X outer_op (C0 outer_op C1)
+ if ((C1 & ~zero_mask) == 0) then emit (X inner_op (C0 outer_op C1)
+*/
+(for inner_op (bit_ior bit_xor)
+ outer_op (bit_xor bit_ior)
+(simplify
+ (outer_op
+ (inner_op:s @2 INTEGER_CST@0) INTEGER_CST@1)
+ (with
+ {
+ bool fail = false;
+ wide_int zero_mask_not;
+ wide_int C0;
+ wide_int cst_emit;
+
+ if (TREE_CODE (@2) == SSA_NAME)
+ zero_mask_not = get_nonzero_bits (@2);
+ else
+ fail = true;
+
+ if (inner_op == BIT_XOR_EXPR)
+ {
+ C0 = wi::bit_and_not (wi::to_wide (@0), wi::to_wide (@1));
+ cst_emit = C0 | wi::to_wide (@1);
+ }
+ else
+ {
+ C0 = wi::to_wide (@0);
+ cst_emit = C0 ^ wi::to_wide (@1);
+ }
+ }
+ (if (!fail && (C0 & zero_mask_not) == 0)
+ (outer_op @2 { wide_int_to_tree (type, cst_emit); })
+ (if (!fail && (wi::to_wide (@1) & zero_mask_not) == 0)
+ (inner_op @2 { wide_int_to_tree (type, cst_emit); }))))))
+
+/* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */
+(simplify
+ (pointer_plus (pointer_plus:s @0 @1) @3)
+ (pointer_plus @0 (plus @1 @3)))
+#if GENERIC
+(simplify
+ (pointer_plus (convert:s (pointer_plus:s @0 @1)) @3)
+ (convert:type (pointer_plus @0 (plus @1 @3))))
+#endif
+
+/* Pattern match
+ tem1 = (long) ptr1;
+ tem2 = (long) ptr2;
+ tem3 = tem2 - tem1;
+ tem4 = (unsigned long) tem3;
+ tem5 = ptr1 + tem4;
+ and produce
+ tem5 = ptr2; */
+(simplify
+ (pointer_plus @0 (convert?@2 (minus@3 (convert @1) (convert @0))))
+ /* Conditionally look through a sign-changing conversion. */
+ (if (TYPE_PRECISION (TREE_TYPE (@2)) == TYPE_PRECISION (TREE_TYPE (@3))
+ && ((GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@1)))
+ || (GENERIC && type == TREE_TYPE (@1))))
+ @1))
+(simplify
+ (pointer_plus @0 (convert?@2 (pointer_diff@3 @1 @@0)))
+ (if (TYPE_PRECISION (TREE_TYPE (@2)) >= TYPE_PRECISION (TREE_TYPE (@3)))
+ (convert @1)))
+
+/* Pattern match
+ tem = (sizetype) ptr;
+ tem = tem & algn;
+ tem = -tem;
+ ... = ptr p+ tem;
+ and produce the simpler and easier to analyze with respect to alignment
+ ... = ptr & ~algn; */
+(simplify
+ (pointer_plus @0 (negate (bit_and (convert @0) INTEGER_CST@1)))
+ (with { tree algn = wide_int_to_tree (TREE_TYPE (@0), ~wi::to_wide (@1)); }
+ (bit_and @0 { algn; })))
+
+/* Try folding difference of addresses. */
+(simplify
+ (minus (convert ADDR_EXPR@0) (convert @1))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (with { poly_int64 diff; }
+ (if (ptr_difference_const (@0, @1, &diff))
+ { build_int_cst_type (type, diff); }))))
+(simplify
+ (minus (convert @0) (convert ADDR_EXPR@1))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (with { poly_int64 diff; }
+ (if (ptr_difference_const (@0, @1, &diff))
+ { build_int_cst_type (type, diff); }))))
+(simplify
+ (pointer_diff (convert?@2 ADDR_EXPR@0) (convert1?@3 @1))
+ (if (tree_nop_conversion_p (TREE_TYPE(@2), TREE_TYPE (@0))
+ && tree_nop_conversion_p (TREE_TYPE(@3), TREE_TYPE (@1)))
+ (with { poly_int64 diff; }
+ (if (ptr_difference_const (@0, @1, &diff))
+ { build_int_cst_type (type, diff); }))))
+(simplify
+ (pointer_diff (convert?@2 @0) (convert1?@3 ADDR_EXPR@1))
+ (if (tree_nop_conversion_p (TREE_TYPE(@2), TREE_TYPE (@0))
+ && tree_nop_conversion_p (TREE_TYPE(@3), TREE_TYPE (@1)))
+ (with { poly_int64 diff; }
+ (if (ptr_difference_const (@0, @1, &diff))
+ { build_int_cst_type (type, diff); }))))
+
+/* (&a+b) - (&a[1] + c) -> sizeof(a[0]) + (b - c) */
+(simplify
+ (pointer_diff (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3))
+ (with { poly_int64 diff; }
+ (if (ptr_difference_const (@0, @2, &diff))
+ (plus { build_int_cst_type (type, diff); } (convert (minus @1 @3))))))
+
+/* (&a+b) !=/== (&a[1] + c) -> sizeof(a[0]) + b !=/== c */
+(for neeq (ne eq)
+ (simplify
+ (neeq (pointer_plus ADDR_EXPR@0 @1) (pointer_plus ADDR_EXPR@2 @3))
+ (with { poly_int64 diff; tree inner_type = TREE_TYPE (@1);}
+ (if (ptr_difference_const (@0, @2, &diff))
+ (neeq (plus { build_int_cst_type (inner_type, diff); } @1) @3)))))
+
+/* Canonicalize (T *)(ptr - ptr-cst) to &MEM[ptr + -ptr-cst]. */
+(simplify
+ (convert (pointer_diff @0 INTEGER_CST@1))
+ (if (POINTER_TYPE_P (type))
+ { build_fold_addr_expr_with_type
+ (build2 (MEM_REF, char_type_node, @0,
+ wide_int_to_tree (ptr_type_node, wi::neg (wi::to_wide (@1)))),
+ type); }))
+
+/* If arg0 is derived from the address of an object or function, we may
+ be able to fold this expression using the object or function's
+ alignment. */
+(simplify
+ (bit_and (convert? @0) INTEGER_CST@1)
+ (if (POINTER_TYPE_P (TREE_TYPE (@0))
+ && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (with
+ {
+ unsigned int align;
+ unsigned HOST_WIDE_INT bitpos;
+ get_pointer_alignment_1 (@0, &align, &bitpos);
+ }
+ (if (wi::ltu_p (wi::to_wide (@1), align / BITS_PER_UNIT))
+ { wide_int_to_tree (type, (wi::to_wide (@1)
+ & (bitpos / BITS_PER_UNIT))); }))))
+
+(match min_value
+ INTEGER_CST
+ (if (INTEGRAL_TYPE_P (type)
+ && wi::eq_p (wi::to_wide (t), wi::min_value (type)))))
+
+(match max_value
+ INTEGER_CST
+ (if (INTEGRAL_TYPE_P (type)
+ && wi::eq_p (wi::to_wide (t), wi::max_value (type)))))
+
+/* x > y && x != XXX_MIN --> x > y
+ x > y && x == XXX_MIN --> false . */
+(for eqne (eq ne)
+ (simplify
+ (bit_and:c (gt:c@2 @0 @1) (eqne @0 min_value))
+ (switch
+ (if (eqne == EQ_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (eqne == NE_EXPR)
+ @2)
+ )))
+
+/* x < y && x != XXX_MAX --> x < y
+ x < y && x == XXX_MAX --> false. */
+(for eqne (eq ne)
+ (simplify
+ (bit_and:c (lt:c@2 @0 @1) (eqne @0 max_value))
+ (switch
+ (if (eqne == EQ_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (eqne == NE_EXPR)
+ @2)
+ )))
+
+/* x <= y && x == XXX_MIN --> x == XXX_MIN. */
+(simplify
+ (bit_and:c (le:c @0 @1) (eq@2 @0 min_value))
+ @2)
+
+/* x >= y && x == XXX_MAX --> x == XXX_MAX. */
+(simplify
+ (bit_and:c (ge:c @0 @1) (eq@2 @0 max_value))
+ @2)
+
+/* x > y || x != XXX_MIN --> x != XXX_MIN. */
+(simplify
+ (bit_ior:c (gt:c @0 @1) (ne@2 @0 min_value))
+ @2)
+
+/* x <= y || x != XXX_MIN --> true. */
+(simplify
+ (bit_ior:c (le:c @0 @1) (ne @0 min_value))
+ { constant_boolean_node (true, type); })
+
+/* x <= y || x == XXX_MIN --> x <= y. */
+(simplify
+ (bit_ior:c (le:c@2 @0 @1) (eq @0 min_value))
+ @2)
+
+/* x < y || x != XXX_MAX --> x != XXX_MAX. */
+(simplify
+ (bit_ior:c (lt:c @0 @1) (ne@2 @0 max_value))
+ @2)
+
+/* x >= y || x != XXX_MAX --> true
+ x >= y || x == XXX_MAX --> x >= y. */
+(for eqne (eq ne)
+ (simplify
+ (bit_ior:c (ge:c@2 @0 @1) (eqne @0 max_value))
+ (switch
+ (if (eqne == EQ_EXPR)
+ @2)
+ (if (eqne == NE_EXPR)
+ { constant_boolean_node (true, type); }))))
+
+/* y == XXX_MIN || x < y --> x <= y - 1 */
+(simplify
+ (bit_ior:c (eq:s @1 min_value) (lt:s @0 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+ (le @0 (minus @1 { build_int_cst (TREE_TYPE (@1), 1); }))))
+
+/* y != XXX_MIN && x >= y --> x > y - 1 */
+(simplify
+ (bit_and:c (ne:s @1 min_value) (ge:s @0 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+ (gt @0 (minus @1 { build_int_cst (TREE_TYPE (@1), 1); }))))
+
+/* Convert (X == CST1) && (X OP2 CST2) to a known value
+ based on CST1 OP2 CST2. Similarly for (X != CST1). */
+
+(for code1 (eq ne)
+ (for code2 (eq ne lt gt le ge)
+ (simplify
+ (bit_and:c (code1@3 @0 INTEGER_CST@1) (code2@4 @0 INTEGER_CST@2))
+ (with
+ {
+ int cmp = tree_int_cst_compare (@1, @2);
+ bool val;
+ switch (code2)
+ {
+ case EQ_EXPR: val = (cmp == 0); break;
+ case NE_EXPR: val = (cmp != 0); break;
+ case LT_EXPR: val = (cmp < 0); break;
+ case GT_EXPR: val = (cmp > 0); break;
+ case LE_EXPR: val = (cmp <= 0); break;
+ case GE_EXPR: val = (cmp >= 0); break;
+ default: gcc_unreachable ();
+ }
+ }
+ (switch
+ (if (code1 == EQ_EXPR && val) @3)
+ (if (code1 == EQ_EXPR && !val) { constant_boolean_node (false, type); })
+ (if (code1 == NE_EXPR && !val) @4))))))
+
+/* Convert (X OP1 CST1) && (X OP2 CST2). */
+
+(for code1 (lt le gt ge)
+ (for code2 (lt le gt ge)
+ (simplify
+ (bit_and (code1:c@3 @0 INTEGER_CST@1) (code2:c@4 @0 INTEGER_CST@2))
+ (with
+ {
+ int cmp = tree_int_cst_compare (@1, @2);
+ }
+ (switch
+ /* Choose the more restrictive of two < or <= comparisons. */
+ (if ((code1 == LT_EXPR || code1 == LE_EXPR)
+ && (code2 == LT_EXPR || code2 == LE_EXPR))
+ (if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
+ @3
+ @4))
+ /* Likewise chose the more restrictive of two > or >= comparisons. */
+ (if ((code1 == GT_EXPR || code1 == GE_EXPR)
+ && (code2 == GT_EXPR || code2 == GE_EXPR))
+ (if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
+ @3
+ @4))
+ /* Check for singleton ranges. */
+ (if (cmp == 0
+ && ((code1 == LE_EXPR && code2 == GE_EXPR)
+ || (code1 == GE_EXPR && code2 == LE_EXPR)))
+ (eq @0 @1))
+ /* Check for disjoint ranges. */
+ (if (cmp <= 0
+ && (code1 == LT_EXPR || code1 == LE_EXPR)
+ && (code2 == GT_EXPR || code2 == GE_EXPR))
+ { constant_boolean_node (false, type); })
+ (if (cmp >= 0
+ && (code1 == GT_EXPR || code1 == GE_EXPR)
+ && (code2 == LT_EXPR || code2 == LE_EXPR))
+ { constant_boolean_node (false, type); })
+ )))))
+
+/* Convert (X == CST1) || (X OP2 CST2) to a known value
+ based on CST1 OP2 CST2. Similarly for (X != CST1). */
+
+(for code1 (eq ne)
+ (for code2 (eq ne lt gt le ge)
+ (simplify
+ (bit_ior:c (code1@3 @0 INTEGER_CST@1) (code2@4 @0 INTEGER_CST@2))
+ (with
+ {
+ int cmp = tree_int_cst_compare (@1, @2);
+ bool val;
+ switch (code2)
+ {
+ case EQ_EXPR: val = (cmp == 0); break;
+ case NE_EXPR: val = (cmp != 0); break;
+ case LT_EXPR: val = (cmp < 0); break;
+ case GT_EXPR: val = (cmp > 0); break;
+ case LE_EXPR: val = (cmp <= 0); break;
+ case GE_EXPR: val = (cmp >= 0); break;
+ default: gcc_unreachable ();
+ }
+ }
+ (switch
+ (if (code1 == EQ_EXPR && val) @4)
+ (if (code1 == NE_EXPR && val) { constant_boolean_node (true, type); })
+ (if (code1 == NE_EXPR && !val) @3))))))
+
+/* Convert (X OP1 CST1) || (X OP2 CST2). */
+
+(for code1 (lt le gt ge)
+ (for code2 (lt le gt ge)
+ (simplify
+ (bit_ior (code1@3 @0 INTEGER_CST@1) (code2@4 @0 INTEGER_CST@2))
+ (with
+ {
+ int cmp = tree_int_cst_compare (@1, @2);
+ }
+ (switch
+ /* Choose the more restrictive of two < or <= comparisons. */
+ (if ((code1 == LT_EXPR || code1 == LE_EXPR)
+ && (code2 == LT_EXPR || code2 == LE_EXPR))
+ (if ((cmp < 0) || (cmp == 0 && code1 == LT_EXPR))
+ @4
+ @3))
+ /* Likewise chose the more restrictive of two > or >= comparisons. */
+ (if ((code1 == GT_EXPR || code1 == GE_EXPR)
+ && (code2 == GT_EXPR || code2 == GE_EXPR))
+ (if ((cmp > 0) || (cmp == 0 && code1 == GT_EXPR))
+ @4
+ @3))
+ /* Check for singleton ranges. */
+ (if (cmp == 0
+ && ((code1 == LT_EXPR && code2 == GT_EXPR)
+ || (code1 == GT_EXPR && code2 == LT_EXPR)))
+ (ne @0 @2))
+ /* Check for disjoint ranges. */
+ (if (cmp >= 0
+ && (code1 == LT_EXPR || code1 == LE_EXPR)
+ && (code2 == GT_EXPR || code2 == GE_EXPR))
+ { constant_boolean_node (true, type); })
+ (if (cmp <= 0
+ && (code1 == GT_EXPR || code1 == GE_EXPR)
+ && (code2 == LT_EXPR || code2 == LE_EXPR))
+ { constant_boolean_node (true, type); })
+ )))))
+
+/* We can't reassociate at all for saturating types. */
+(if (!TYPE_SATURATING (type))
+
+ /* Contract negates. */
+ /* A + (-B) -> A - B */
+ (simplify
+ (plus:c @0 (convert? (negate @1)))
+ /* Apply STRIP_NOPS on the negate. */
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+ && !TYPE_OVERFLOW_SANITIZED (type))
+ (with
+ {
+ tree t1 = type;
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+ t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1);
+ }
+ (convert (minus (convert:t1 @0) (convert:t1 @1))))))
+ /* A - (-B) -> A + B */
+ (simplify
+ (minus @0 (convert? (negate @1)))
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
+ && !TYPE_OVERFLOW_SANITIZED (type))
+ (with
+ {
+ tree t1 = type;
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+ t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1);
+ }
+ (convert (plus (convert:t1 @0) (convert:t1 @1))))))
+ /* -(T)(-A) -> (T)A
+ Sign-extension is ok except for INT_MIN, which thankfully cannot
+ happen without overflow. */
+ (simplify
+ (negate (convert (negate @1)))
+ (if (INTEGRAL_TYPE_P (type)
+ && (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+ || (!TYPE_UNSIGNED (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
+ && !TYPE_OVERFLOW_SANITIZED (type)
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1)))
+ (convert @1)))
+ (simplify
+ (negate (convert negate_expr_p@1))
+ (if (SCALAR_FLOAT_TYPE_P (type)
+ && ((DECIMAL_FLOAT_TYPE_P (type)
+ == DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1))
+ && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (@1)))
+ || !HONOR_SIGN_DEPENDENT_ROUNDING (type)))
+ (convert (negate @1))))
+ (simplify
+ (negate (nop_convert? (negate @1)))
+ (if (!TYPE_OVERFLOW_SANITIZED (type)
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1)))
+ (view_convert @1)))
+
+ /* We can't reassociate floating-point unless -fassociative-math
+ or fixed-point plus or minus because of saturation to +-Inf. */
+ (if ((!FLOAT_TYPE_P (type) || flag_associative_math)
+ && !FIXED_POINT_TYPE_P (type))
+
+ /* Match patterns that allow contracting a plus-minus pair
+ irrespective of overflow issues. */
+ /* (A +- B) - A -> +- B */
+ /* (A +- B) -+ B -> A */
+ /* A - (A +- B) -> -+ B */
+ /* A +- (B -+ A) -> +- B */
+ (simplify
+ (minus (nop_convert1? (plus:c (nop_convert2? @0) @1)) @0)
+ (view_convert @1))
+ (simplify
+ (minus (nop_convert1? (minus (nop_convert2? @0) @1)) @0)
+ (if (!ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type))
+ (negate (view_convert @1))
+ (view_convert (negate @1))))
+ (simplify
+ (plus:c (nop_convert1? (minus @0 (nop_convert2? @1))) @1)
+ (view_convert @0))
+ (simplify
+ (minus @0 (nop_convert1? (plus:c (nop_convert2? @0) @1)))
+ (if (!ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type))
+ (negate (view_convert @1))
+ (view_convert (negate @1))))
+ (simplify
+ (minus @0 (nop_convert1? (minus (nop_convert2? @0) @1)))
+ (view_convert @1))
+ /* (A +- B) + (C - A) -> C +- B */
+ /* (A + B) - (A - C) -> B + C */
+ /* More cases are handled with comparisons. */
+ (simplify
+ (plus:c (plus:c @0 @1) (minus @2 @0))
+ (plus @2 @1))
+ (simplify
+ (plus:c (minus @0 @1) (minus @2 @0))
+ (minus @2 @1))
+ (simplify
+ (plus:c (pointer_diff @0 @1) (pointer_diff @2 @0))
+ (if (TYPE_OVERFLOW_UNDEFINED (type)
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0)))
+ (pointer_diff @2 @1)))
+ (simplify
+ (minus (plus:c @0 @1) (minus @0 @2))
+ (plus @1 @2))
+
+ /* (A +- CST1) +- CST2 -> A + CST3
+ Use view_convert because it is safe for vectors and equivalent for
+ scalars. */
+ (for outer_op (plus minus)
+ (for inner_op (plus minus)
+ neg_inner_op (minus plus)
+ (simplify
+ (outer_op (nop_convert? (inner_op @0 CONSTANT_CLASS_P@1))
+ CONSTANT_CLASS_P@2)
+ /* If one of the types wraps, use that one. */
+ (if (!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+ /* If all 3 captures are CONSTANT_CLASS_P, punt, as we might recurse
+ forever if something doesn't simplify into a constant. */
+ (if (!CONSTANT_CLASS_P (@0))
+ (if (outer_op == PLUS_EXPR)
+ (plus (view_convert @0) (inner_op @2 (view_convert @1)))
+ (minus (view_convert @0) (neg_inner_op @2 (view_convert @1)))))
+ (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ (if (outer_op == PLUS_EXPR)
+ (view_convert (plus @0 (inner_op (view_convert @2) @1)))
+ (view_convert (minus @0 (neg_inner_op (view_convert @2) @1))))
+ /* If the constant operation overflows we cannot do the transform
+ directly as we would introduce undefined overflow, for example
+ with (a - 1) + INT_MIN. */
+ (if (types_match (type, @0))
+ (with { tree cst = const_binop (outer_op == inner_op
+ ? PLUS_EXPR : MINUS_EXPR,
+ type, @1, @2); }
+ (if (cst && !TREE_OVERFLOW (cst))
+ (inner_op @0 { cst; } )
+ /* X+INT_MAX+1 is X-INT_MIN. */
+ (if (INTEGRAL_TYPE_P (type) && cst
+ && wi::to_wide (cst) == wi::min_value (type))
+ (neg_inner_op @0 { wide_int_to_tree (type, wi::to_wide (cst)); })
+ /* Last resort, use some unsigned type. */
+ (with { tree utype = unsigned_type_for (type); }
+ (if (utype)
+ (view_convert (inner_op
+ (view_convert:utype @0)
+ (view_convert:utype
+ { drop_tree_overflow (cst); }))))))))))))))
+
+ /* (CST1 - A) +- CST2 -> CST3 - A */
+ (for outer_op (plus minus)
+ (simplify
+ (outer_op (nop_convert? (minus CONSTANT_CLASS_P@1 @0)) CONSTANT_CLASS_P@2)
+ /* If one of the types wraps, use that one. */
+ (if (!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+ /* If all 3 captures are CONSTANT_CLASS_P, punt, as we might recurse
+ forever if something doesn't simplify into a constant. */
+ (if (!CONSTANT_CLASS_P (@0))
+ (minus (outer_op (view_convert @1) @2) (view_convert @0)))
+ (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ (view_convert (minus (outer_op @1 (view_convert @2)) @0))
+ (if (types_match (type, @0))
+ (with { tree cst = const_binop (outer_op, type, @1, @2); }
+ (if (cst && !TREE_OVERFLOW (cst))
+ (minus { cst; } @0))))))))
+
+ /* CST1 - (CST2 - A) -> CST3 + A
+ Use view_convert because it is safe for vectors and equivalent for
+ scalars. */
+ (simplify
+ (minus CONSTANT_CLASS_P@1 (nop_convert? (minus CONSTANT_CLASS_P@2 @0)))
+ /* If one of the types wraps, use that one. */
+ (if (!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+ /* If all 3 captures are CONSTANT_CLASS_P, punt, as we might recurse
+ forever if something doesn't simplify into a constant. */
+ (if (!CONSTANT_CLASS_P (@0))
+ (plus (view_convert @0) (minus @1 (view_convert @2))))
+ (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ (view_convert (plus @0 (minus (view_convert @1) @2)))
+ (if (types_match (type, @0))
+ (with { tree cst = const_binop (MINUS_EXPR, type, @1, @2); }
+ (if (cst && !TREE_OVERFLOW (cst))
+ (plus { cst; } @0)))))))
+
+/* ((T)(A)) + CST -> (T)(A + CST) */
+#if GIMPLE
+ (simplify
+ (plus (convert:s SSA_NAME@0) INTEGER_CST@1)
+ (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
+ && int_fits_type_p (@1, TREE_TYPE (@0)))
+ /* Perform binary operation inside the cast if the constant fits
+ and (A + CST)'s range does not overflow. */
+ (with
+ {
+ wi::overflow_type min_ovf = wi::OVF_OVERFLOW,
+ max_ovf = wi::OVF_OVERFLOW;
+ tree inner_type = TREE_TYPE (@0);
+
+ wide_int w1
+ = wide_int::from (wi::to_wide (@1), TYPE_PRECISION (inner_type),
+ TYPE_SIGN (inner_type));
+
+ value_range vr;
+ if (get_global_range_query ()->range_of_expr (vr, @0)
+ && vr.kind () == VR_RANGE)
+ {
+ wide_int wmin0 = vr.lower_bound ();
+ wide_int wmax0 = vr.upper_bound ();
+ wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf);
+ wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf);
+ }
+ }
+ (if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE)
+ (convert (plus @0 { wide_int_to_tree (TREE_TYPE (@0), w1); } )))
+ )))
+#endif
+
+/* ((T)(A + CST1)) + CST2 -> (T)(A) + (T)CST1 + CST2 */
+#if GIMPLE
+ (for op (plus minus)
+ (simplify
+ (plus (convert:s (op:s @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (TREE_CODE (TREE_TYPE (@0)) == INTEGER_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_WRAPS (type))
+ (plus (convert @0) (op @2 (convert @1))))))
+#endif
+
+/* (T)(A) +- (T)(B) -> (T)(A +- B) only when (A +- B) could be simplified
+ to a simple value. */
+#if GIMPLE
+ (for op (plus minus)
+ (simplify
+ (op (convert @0) (convert @1))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@1))
+ && !TYPE_OVERFLOW_TRAPS (type)
+ && !TYPE_OVERFLOW_SANITIZED (type))
+ (convert (op! @0 @1)))))
+#endif
+
+ /* ~A + A -> -1 */
+ (simplify
+ (plus:c (bit_not @0) @0)
+ (if (!TYPE_OVERFLOW_TRAPS (type))
+ { build_all_ones_cst (type); }))
+
+ /* ~A + 1 -> -A */
+ (simplify
+ (plus (convert? (bit_not @0)) integer_each_onep)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (negate (convert @0))))
+
+ /* -A - 1 -> ~A */
+ (simplify
+ (minus (convert? (negate @0)) integer_each_onep)
+ (if (!TYPE_OVERFLOW_TRAPS (type)
+ && TREE_CODE (type) != COMPLEX_TYPE
+ && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (bit_not (convert @0))))
+
+ /* -1 - A -> ~A */
+ (simplify
+ (minus integer_all_onesp @0)
+ (if (TREE_CODE (type) != COMPLEX_TYPE)
+ (bit_not @0)))
+
+ /* (T)(P + A) - (T)P -> (T) A */
+ (simplify
+ (minus (convert (plus:c @@0 @1))
+ (convert? @0))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
+ (convert @1)))
+ (simplify
+ (minus (convert (pointer_plus @@0 @1))
+ (convert @0))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@1) == INTEGER_CST
+ && tree_int_cst_sign_bit (@1) == 0))
+ (convert @1)))
+ (simplify
+ (pointer_diff (pointer_plus @@0 @1) @0)
+ /* The second argument of pointer_plus must be interpreted as signed, and
+ thus sign-extended if necessary. */
+ (with { tree stype = signed_type_for (TREE_TYPE (@1)); }
+ /* Use view_convert instead of convert here, as POINTER_PLUS_EXPR
+ second arg is unsigned even when we need to consider it as signed,
+ we don't want to diagnose overflow here. */
+ (convert (view_convert:stype @1))))
+
+ /* (T)P - (T)(P + A) -> -(T) A */
+ (simplify
+ (minus (convert? @0)
+ (convert (plus:c @@0 @1)))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && element_precision (type) <= element_precision (TREE_TYPE (@1)))
+ (with { tree utype = unsigned_type_for (type); }
+ (convert (negate (convert:utype @1))))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
+ (negate (convert @1)))))
+ (simplify
+ (minus (convert @0)
+ (convert (pointer_plus @@0 @1)))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && element_precision (type) <= element_precision (TREE_TYPE (@1)))
+ (with { tree utype = unsigned_type_for (type); }
+ (convert (negate (convert:utype @1))))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@1) == INTEGER_CST
+ && tree_int_cst_sign_bit (@1) == 0))
+ (negate (convert @1)))))
+ (simplify
+ (pointer_diff @0 (pointer_plus @@0 @1))
+ /* The second argument of pointer_plus must be interpreted as signed, and
+ thus sign-extended if necessary. */
+ (with { tree stype = signed_type_for (TREE_TYPE (@1)); }
+ /* Use view_convert instead of convert here, as POINTER_PLUS_EXPR
+ second arg is unsigned even when we need to consider it as signed,
+ we don't want to diagnose overflow here. */
+ (negate (convert (view_convert:stype @1)))))
+
+ /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
+ (simplify
+ (minus (convert (plus:c @@0 @1))
+ (convert (plus:c @0 @2)))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && element_precision (type) <= element_precision (TREE_TYPE (@1))
+ && element_precision (type) <= element_precision (TREE_TYPE (@2)))
+ (with { tree utype = unsigned_type_for (type); }
+ (convert (minus (convert:utype @1) (convert:utype @2))))
+ (if (((element_precision (type) <= element_precision (TREE_TYPE (@1)))
+ == (element_precision (type) <= element_precision (TREE_TYPE (@2))))
+ && (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For integer types, if A has a smaller type
+ than T the result depends on the possible
+ overflow in P + A.
+ E.g. T=size_t, A=(unsigned)429497295, P>0.
+ However, if an overflow in P + A would cause
+ undefined behavior, we can assume that there
+ is no overflow. */
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@2)))))
+ (minus (convert @1) (convert @2)))))
+ (simplify
+ (minus (convert (pointer_plus @@0 @1))
+ (convert (pointer_plus @0 @2)))
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type)
+ && element_precision (type) <= element_precision (TREE_TYPE (@1)))
+ (with { tree utype = unsigned_type_for (type); }
+ (convert (minus (convert:utype @1) (convert:utype @2))))
+ (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+ /* For pointer types, if the conversion of A to the
+ final type requires a sign- or zero-extension,
+ then we have to punt - it is not defined which
+ one is correct. */
+ || (POINTER_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@1) == INTEGER_CST
+ && tree_int_cst_sign_bit (@1) == 0
+ && TREE_CODE (@2) == INTEGER_CST
+ && tree_int_cst_sign_bit (@2) == 0))
+ (minus (convert @1) (convert @2)))))
+ (simplify
+ (pointer_diff (pointer_plus @0 @2) (pointer_plus @1 @2))
+ (pointer_diff @0 @1))
+ (simplify
+ (pointer_diff (pointer_plus @@0 @1) (pointer_plus @0 @2))
+ /* The second argument of pointer_plus must be interpreted as signed, and
+ thus sign-extended if necessary. */
+ (with { tree stype = signed_type_for (TREE_TYPE (@1)); }
+ /* Use view_convert instead of convert here, as POINTER_PLUS_EXPR
+ second arg is unsigned even when we need to consider it as signed,
+ we don't want to diagnose overflow here. */
+ (minus (convert (view_convert:stype @1))
+ (convert (view_convert:stype @2)))))))
+
+/* (A * C) +- (B * C) -> (A+-B) * C and (A * C) +- A -> A * (C+-1).
+ Modeled after fold_plusminus_mult_expr. */
+(if (!TYPE_SATURATING (type)
+ && (!FLOAT_TYPE_P (type) || flag_associative_math))
+ (for plusminus (plus minus)
+ (simplify
+ (plusminus (mult:cs@3 @0 @1) (mult:cs@4 @0 @2))
+ (if (!ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type)
+ || (INTEGRAL_TYPE_P (type)
+ && tree_expr_nonzero_p (@0)
+ && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+ (if (single_use (@3) || single_use (@4))
+ /* If @1 +- @2 is constant require a hard single-use on either
+ original operand (but not on both). */
+ (mult (plusminus @1 @2) @0)
+#if GIMPLE
+ (mult! (plusminus @1 @2) @0)
+#endif
+ )))
+ /* We cannot generate constant 1 for fract. */
+ (if (!ALL_FRACT_MODE_P (TYPE_MODE (type)))
+ (simplify
+ (plusminus @0 (mult:c@3 @0 @2))
+ (if ((!ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type)
+ /* For @0 + @0*@2 this transformation would introduce UB
+ (where there was none before) for @0 in [-1,0] and @2 max.
+ For @0 - @0*@2 this transformation would introduce UB
+ for @0 0 and @2 in [min,min+1] or @0 -1 and @2 min+1. */
+ || (INTEGRAL_TYPE_P (type)
+ && ((tree_expr_nonzero_p (@0)
+ && expr_not_equal_to (@0,
+ wi::minus_one (TYPE_PRECISION (type))))
+ || (plusminus == PLUS_EXPR
+ ? expr_not_equal_to (@2,
+ wi::max_value (TYPE_PRECISION (type), SIGNED))
+ /* Let's ignore the @0 -1 and @2 min case. */
+ : (expr_not_equal_to (@2,
+ wi::min_value (TYPE_PRECISION (type), SIGNED))
+ && expr_not_equal_to (@2,
+ wi::min_value (TYPE_PRECISION (type), SIGNED)
+ + 1))))))
+ && single_use (@3))
+ (mult (plusminus { build_one_cst (type); } @2) @0)))
+ (simplify
+ (plusminus (mult:c@3 @0 @2) @0)
+ (if ((!ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_WRAPS (type)
+ /* For @0*@2 + @0 this transformation would introduce UB
+ (where there was none before) for @0 in [-1,0] and @2 max.
+ For @0*@2 - @0 this transformation would introduce UB
+ for @0 0 and @2 min. */
+ || (INTEGRAL_TYPE_P (type)
+ && ((tree_expr_nonzero_p (@0)
+ && (plusminus == MINUS_EXPR
+ || expr_not_equal_to (@0,
+ wi::minus_one (TYPE_PRECISION (type)))))
+ || expr_not_equal_to (@2,
+ (plusminus == PLUS_EXPR
+ ? wi::max_value (TYPE_PRECISION (type), SIGNED)
+ : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
+ && single_use (@3))
+ (mult (plusminus @2 { build_one_cst (type); }) @0))))))
+
+#if GIMPLE
+/* Canonicalize X + (X << C) into X * (1 + (1 << C)) and
+ (X << C1) + (X << C2) into X * ((1 << C1) + (1 << C2)). */
+(simplify
+ (plus:c @0 (lshift:s @0 INTEGER_CST@1))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && tree_fits_uhwi_p (@1)
+ && tree_to_uhwi (@1) < element_precision (type)
+ && (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || optab_handler (smul_optab,
+ TYPE_MODE (type)) != CODE_FOR_nothing))
+ (with { tree t = type;
+ if (!TYPE_OVERFLOW_WRAPS (t)) t = unsigned_type_for (t);
+ wide_int w = wi::set_bit_in_zero (tree_to_uhwi (@1),
+ element_precision (type));
+ w += 1;
+ tree cst = wide_int_to_tree (VECTOR_TYPE_P (t) ? TREE_TYPE (t)
+ : t, w);
+ cst = build_uniform_cst (t, cst); }
+ (convert (mult (convert:t @0) { cst; })))))
+(simplify
+ (plus (lshift:s @0 INTEGER_CST@1) (lshift:s @0 INTEGER_CST@2))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && tree_fits_uhwi_p (@1)
+ && tree_to_uhwi (@1) < element_precision (type)
+ && tree_fits_uhwi_p (@2)
+ && tree_to_uhwi (@2) < element_precision (type)
+ && (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || optab_handler (smul_optab,
+ TYPE_MODE (type)) != CODE_FOR_nothing))
+ (with { tree t = type;
+ if (!TYPE_OVERFLOW_WRAPS (t)) t = unsigned_type_for (t);
+ unsigned int prec = element_precision (type);
+ wide_int w = wi::set_bit_in_zero (tree_to_uhwi (@1), prec);
+ w += wi::set_bit_in_zero (tree_to_uhwi (@2), prec);
+ tree cst = wide_int_to_tree (VECTOR_TYPE_P (t) ? TREE_TYPE (t)
+ : t, w);
+ cst = build_uniform_cst (t, cst); }
+ (convert (mult (convert:t @0) { cst; })))))
+#endif
+
+/* Canonicalize (X*C1)|(X*C2) and (X*C1)^(X*C2) to (C1+C2)*X when
+ tree_nonzero_bits allows IOR and XOR to be treated like PLUS.
+ Likewise, handle (X<<C3) and X as legitimate variants of X*C. */
+(for op (bit_ior bit_xor)
+ (simplify
+ (op (mult:s@0 @1 INTEGER_CST@2)
+ (mult:s@3 @1 INTEGER_CST@4))
+ (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)
+ && (tree_nonzero_bits (@0) & tree_nonzero_bits (@3)) == 0)
+ (mult @1
+ { wide_int_to_tree (type, wi::to_wide (@2) + wi::to_wide (@4)); })))
+ (simplify
+ (op:c (mult:s@0 @1 INTEGER_CST@2)
+ (lshift:s@3 @1 INTEGER_CST@4))
+ (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)
+ && tree_int_cst_sgn (@4) > 0
+ && (tree_nonzero_bits (@0) & tree_nonzero_bits (@3)) == 0)
+ (with { wide_int wone = wi::one (TYPE_PRECISION (type));
+ wide_int c = wi::add (wi::to_wide (@2),
+ wi::lshift (wone, wi::to_wide (@4))); }
+ (mult @1 { wide_int_to_tree (type, c); }))))
+ (simplify
+ (op:c (mult:s@0 @1 INTEGER_CST@2)
+ @1)
+ (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)
+ && (tree_nonzero_bits (@0) & tree_nonzero_bits (@1)) == 0)
+ (mult @1
+ { wide_int_to_tree (type,
+ wi::add (wi::to_wide (@2), 1)); })))
+ (simplify
+ (op (lshift:s@0 @1 INTEGER_CST@2)
+ (lshift:s@3 @1 INTEGER_CST@4))
+ (if (INTEGRAL_TYPE_P (type)
+ && tree_int_cst_sgn (@2) > 0
+ && tree_int_cst_sgn (@4) > 0
+ && (tree_nonzero_bits (@0) & tree_nonzero_bits (@3)) == 0)
+ (with { tree t = type;
+ if (!TYPE_OVERFLOW_WRAPS (t))
+ t = unsigned_type_for (t);
+ wide_int wone = wi::one (TYPE_PRECISION (t));
+ wide_int c = wi::add (wi::lshift (wone, wi::to_wide (@2)),
+ wi::lshift (wone, wi::to_wide (@4))); }
+ (convert (mult:t (convert:t @1) { wide_int_to_tree (t,c); })))))
+ (simplify
+ (op:c (lshift:s@0 @1 INTEGER_CST@2)
+ @1)
+ (if (INTEGRAL_TYPE_P (type)
+ && tree_int_cst_sgn (@2) > 0
+ && (tree_nonzero_bits (@0) & tree_nonzero_bits (@1)) == 0)
+ (with { tree t = type;
+ if (!TYPE_OVERFLOW_WRAPS (t))
+ t = unsigned_type_for (t);
+ wide_int wone = wi::one (TYPE_PRECISION (t));
+ wide_int c = wi::add (wi::lshift (wone, wi::to_wide (@2)), wone); }
+ (convert (mult:t (convert:t @1) { wide_int_to_tree (t, c); }))))))
+
+/* Simplifications of MIN_EXPR, MAX_EXPR, fmin() and fmax(). */
+
+(for minmax (min max FMIN_ALL FMAX_ALL)
+ (simplify
+ (minmax @0 @0)
+ @0))
+/* min(max(x,y),y) -> y. */
+(simplify
+ (min:c (max:c @0 @1) @1)
+ @1)
+/* max(min(x,y),y) -> y. */
+(simplify
+ (max:c (min:c @0 @1) @1)
+ @1)
+/* max(a,-a) -> abs(a). */
+(simplify
+ (max:c @0 (negate @0))
+ (if (TREE_CODE (type) != COMPLEX_TYPE
+ && (! ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_UNDEFINED (type)))
+ (abs @0)))
+/* min(a,-a) -> -abs(a). */
+(simplify
+ (min:c @0 (negate @0))
+ (if (TREE_CODE (type) != COMPLEX_TYPE
+ && (! ANY_INTEGRAL_TYPE_P (type)
+ || TYPE_OVERFLOW_UNDEFINED (type)))
+ (negate (abs @0))))
+(simplify
+ (min @0 @1)
+ (switch
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_MIN_VALUE (type)
+ && operand_equal_p (@1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
+ @1)
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_MAX_VALUE (type)
+ && operand_equal_p (@1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
+ @0)))
+(simplify
+ (max @0 @1)
+ (switch
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_MAX_VALUE (type)
+ && operand_equal_p (@1, TYPE_MAX_VALUE (type), OEP_ONLY_CONST))
+ @1)
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_MIN_VALUE (type)
+ && operand_equal_p (@1, TYPE_MIN_VALUE (type), OEP_ONLY_CONST))
+ @0)))
+
+/* max (a, a + CST) -> a + CST where CST is positive. */
+/* max (a, a + CST) -> a where CST is negative. */
+(simplify
+ (max:c @0 (plus@2 @0 INTEGER_CST@1))
+ (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (if (tree_int_cst_sgn (@1) > 0)
+ @2
+ @0)))
+
+/* min (a, a + CST) -> a where CST is positive. */
+/* min (a, a + CST) -> a + CST where CST is negative. */
+(simplify
+ (min:c @0 (plus@2 @0 INTEGER_CST@1))
+ (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (if (tree_int_cst_sgn (@1) > 0)
+ @0
+ @2)))
+
+/* Simplify min (&var[off0], &var[off1]) etc. depending on whether
+ the addresses are known to be less, equal or greater. */
+(for minmax (min max)
+ cmp (lt gt)
+ (simplify
+ (minmax (convert1?@2 addr@0) (convert2?@3 addr@1))
+ (with
+ {
+ poly_int64 off0, off1;
+ tree base0, base1;
+ int equal = address_compare (cmp, TREE_TYPE (@2), @0, @1, base0, base1,
+ off0, off1, GENERIC);
+ }
+ (if (equal == 1)
+ (if (minmax == MIN_EXPR)
+ (if (known_le (off0, off1))
+ @2
+ (if (known_gt (off0, off1))
+ @3))
+ (if (known_ge (off0, off1))
+ @2
+ (if (known_lt (off0, off1))
+ @3)))))))
+
+/* (convert (minmax ((convert (x) c)))) -> minmax (x c) if x is promoted
+ and the outer convert demotes the expression back to x's type. */
+(for minmax (min max)
+ (simplify
+ (convert (minmax@0 (convert @1) INTEGER_CST@2))
+ (if (INTEGRAL_TYPE_P (type)
+ && types_match (@1, type) && int_fits_type_p (@2, type)
+ && TYPE_SIGN (TREE_TYPE (@0)) == TYPE_SIGN (type)
+ && TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type))
+ (minmax @1 (convert @2)))))
+
+(for minmax (FMIN_ALL FMAX_ALL)
+ /* If either argument is NaN, return the other one. Avoid the
+ transformation if we get (and honor) a signalling NaN. */
+ (simplify
+ (minmax:c @0 REAL_CST@1)
+ (if (real_isnan (TREE_REAL_CST_PTR (@1))
+ && (!HONOR_SNANS (@1) || !TREE_REAL_CST (@1).signalling))
+ @0)))
+/* Convert fmin/fmax to MIN_EXPR/MAX_EXPR. C99 requires these
+ functions to return the numeric arg if the other one is NaN.
+ MIN and MAX don't honor that, so only transform if -ffinite-math-only
+ is set. C99 doesn't require -0.0 to be handled, so we don't have to
+ worry about it either. */
+(if (flag_finite_math_only)
+ (simplify
+ (FMIN_ALL @0 @1)
+ (min @0 @1))
+ (simplify
+ (FMAX_ALL @0 @1)
+ (max @0 @1)))
+/* min (-A, -B) -> -max (A, B) */
+(for minmax (min max FMIN_ALL FMAX_ALL)
+ maxmin (max min FMAX_ALL FMIN_ALL)
+ (simplify
+ (minmax (negate:s@2 @0) (negate:s@3 @1))
+ (if (FLOAT_TYPE_P (TREE_TYPE (@0))
+ || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+ (negate (maxmin @0 @1)))))
+/* MIN (~X, ~Y) -> ~MAX (X, Y)
+ MAX (~X, ~Y) -> ~MIN (X, Y) */
+(for minmax (min max)
+ maxmin (max min)
+ (simplify
+ (minmax (bit_not:s@2 @0) (bit_not:s@3 @1))
+ (bit_not (maxmin @0 @1))))
+
+/* MIN (X, Y) == X -> X <= Y */
+(for minmax (min min max max)
+ cmp (eq ne eq ne )
+ out (le gt ge lt )
+ (simplify
+ (cmp:c (minmax:c @0 @1) @0)
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+ (out @0 @1))))
+/* MIN (X, 5) == 0 -> X == 0
+ MIN (X, 5) == 7 -> false */
+(for cmp (eq ne)
+ (simplify
+ (cmp (min @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (wi::lt_p (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (TREE_TYPE (@0))))
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (if (wi::gt_p (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (TREE_TYPE (@0))))
+ (cmp @0 @2)))))
+(for cmp (eq ne)
+ (simplify
+ (cmp (max @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (wi::gt_p (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (TREE_TYPE (@0))))
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (if (wi::lt_p (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (TREE_TYPE (@0))))
+ (cmp @0 @2)))))
+/* MIN (X, C1) < C2 -> X < C2 || C1 < C2 */
+(for minmax (min min max max min min max max )
+ cmp (lt le gt ge gt ge lt le )
+ comb (bit_ior bit_ior bit_ior bit_ior bit_and bit_and bit_and bit_and)
+ (simplify
+ (cmp (minmax @0 INTEGER_CST@1) INTEGER_CST@2)
+ (comb (cmp @0 @2) (cmp @1 @2))))
+
+/* X <= MAX(X, Y) -> true
+ X > MAX(X, Y) -> false
+ X >= MIN(X, Y) -> true
+ X < MIN(X, Y) -> false */
+(for minmax (min min max max )
+ cmp (ge lt le gt )
+ (simplify
+ (cmp @0 (minmax:c @0 @1))
+ { constant_boolean_node (cmp == GE_EXPR || cmp == LE_EXPR, type); } ))
+
+/* Undo fancy way of writing max/min or other ?: expressions,
+ like a - ((a - b) & -(a < b)), in this case into (a < b) ? b : a.
+ People normally use ?: and that is what we actually try to optimize. */
+(for cmp (simple_comparison)
+ (simplify
+ (minus @0 (bit_and:c (minus @0 @1)
+ (convert? (negate@4 (convert? (cmp@5 @2 @3))))))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@4))
+ && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
+ && INTEGRAL_TYPE_P (TREE_TYPE (@5))
+ && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
+ || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+ && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+ (cond (cmp @2 @3) @1 @0)))
+ (simplify
+ (plus:c @0 (bit_and:c (minus @1 @0)
+ (convert? (negate@4 (convert? (cmp@5 @2 @3))))))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@4))
+ && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
+ && INTEGRAL_TYPE_P (TREE_TYPE (@5))
+ && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
+ || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+ && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+ (cond (cmp @2 @3) @1 @0)))
+ /* Similarly with ^ instead of - though in that case with :c. */
+ (simplify
+ (bit_xor:c @0 (bit_and:c (bit_xor:c @0 @1)
+ (convert? (negate@4 (convert? (cmp@5 @2 @3))))))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@4))
+ && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
+ && INTEGRAL_TYPE_P (TREE_TYPE (@5))
+ && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
+ || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+ && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
+ (cond (cmp @2 @3) @1 @0))))
+
+/* Simplifications of shift and rotates. */
+
+(for rotate (lrotate rrotate)
+ (simplify
+ (rotate integer_all_onesp@0 @1)
+ @0))
+
+/* Optimize -1 >> x for arithmetic right shifts. */
+(simplify
+ (rshift integer_all_onesp@0 @1)
+ (if (!TYPE_UNSIGNED (type))
+ @0))
+
+/* Optimize (x >> c) << c into x & (-1<<c). */
+(simplify
+ (lshift (nop_convert? (rshift @0 INTEGER_CST@1)) @1)
+ (if (wi::ltu_p (wi::to_wide (@1), element_precision (type)))
+ /* It doesn't matter if the right shift is arithmetic or logical. */
+ (bit_and (view_convert @0) (lshift { build_minus_one_cst (type); } @1))))
+
+(simplify
+ (lshift (convert (convert@2 (rshift @0 INTEGER_CST@1))) @1)
+ (if (wi::ltu_p (wi::to_wide (@1), element_precision (type))
+ /* Allow intermediate conversion to integral type with whatever sign, as
+ long as the low TYPE_PRECISION (type)
+ - TYPE_PRECISION (TREE_TYPE (@2)) bits are preserved. */
+ && INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0))
+ && (TYPE_PRECISION (TREE_TYPE (@2)) >= TYPE_PRECISION (type)
+ || wi::geu_p (wi::to_wide (@1),
+ TYPE_PRECISION (type)
+ - TYPE_PRECISION (TREE_TYPE (@2)))))
+ (bit_and (convert @0) (lshift { build_minus_one_cst (type); } @1))))
+
+/* Optimize (x << c) >> c into x & ((unsigned)-1 >> c) for unsigned
+ types. */
+(simplify
+ (rshift (lshift @0 INTEGER_CST@1) @1)
+ (if (TYPE_UNSIGNED (type)
+ && (wi::ltu_p (wi::to_wide (@1), element_precision (type))))
+ (bit_and @0 (rshift { build_minus_one_cst (type); } @1))))
+
+/* Optimize x >> x into 0 */
+(simplify
+ (rshift @0 @0)
+ { build_zero_cst (type); })
+
+(for shiftrotate (lrotate rrotate lshift rshift)
+ (simplify
+ (shiftrotate @0 integer_zerop)
+ (non_lvalue @0))
+ (simplify
+ (shiftrotate integer_zerop@0 @1)
+ @0)
+ /* Prefer vector1 << scalar to vector1 << vector2
+ if vector2 is uniform. */
+ (for vec (VECTOR_CST CONSTRUCTOR)
+ (simplify
+ (shiftrotate @0 vec@1)
+ (with { tree tem = uniform_vector_p (@1); }
+ (if (tem)
+ (shiftrotate @0 { tem; }))))))
+
+/* Simplify X << Y where Y's low width bits are 0 to X, as only valid
+ Y is 0. Similarly for X >> Y. */
+#if GIMPLE
+(for shift (lshift rshift)
+ (simplify
+ (shift @0 SSA_NAME@1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@1)))
+ (with {
+ int width = ceil_log2 (element_precision (TREE_TYPE (@0)));
+ int prec = TYPE_PRECISION (TREE_TYPE (@1));
+ }
+ (if ((get_nonzero_bits (@1) & wi::mask (width, false, prec)) == 0)
+ @0)))))
+#endif
+
+/* Rewrite an LROTATE_EXPR by a constant into an
+ RROTATE_EXPR by a new constant. */
+(simplify
+ (lrotate @0 INTEGER_CST@1)
+ (rrotate @0 { const_binop (MINUS_EXPR, TREE_TYPE (@1),
+ build_int_cst (TREE_TYPE (@1),
+ element_precision (type)), @1); }))
+
+/* Turn (a OP c1) OP c2 into a OP (c1+c2). */
+(for op (lrotate rrotate rshift lshift)
+ (simplify
+ (op (op @0 INTEGER_CST@1) INTEGER_CST@2)
+ (with { unsigned int prec = element_precision (type); }
+ (if (wi::ge_p (wi::to_wide (@1), 0, TYPE_SIGN (TREE_TYPE (@1)))
+ && wi::lt_p (wi::to_wide (@1), prec, TYPE_SIGN (TREE_TYPE (@1)))
+ && wi::ge_p (wi::to_wide (@2), 0, TYPE_SIGN (TREE_TYPE (@2)))
+ && wi::lt_p (wi::to_wide (@2), prec, TYPE_SIGN (TREE_TYPE (@2))))
+ (with { unsigned int low = (tree_to_uhwi (@1)
+ + tree_to_uhwi (@2)); }
+ /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
+ being well defined. */
+ (if (low >= prec)
+ (if (op == LROTATE_EXPR || op == RROTATE_EXPR)
+ (op @0 { build_int_cst (TREE_TYPE (@1), low % prec); })
+ (if (TYPE_UNSIGNED (type) || op == LSHIFT_EXPR)
+ { build_zero_cst (type); }
+ (op @0 { build_int_cst (TREE_TYPE (@1), prec - 1); })))
+ (op @0 { build_int_cst (TREE_TYPE (@1), low); })))))))
+
+
+/* Simplify (CST << x) & 1 to 0 if CST is even or to x == 0 if it is odd. */
+(simplify
+ (bit_and (lshift INTEGER_CST@1 @0) integer_onep)
+ (if ((wi::to_wide (@1) & 1) != 0)
+ (convert (eq:boolean_type_node @0 { build_zero_cst (TREE_TYPE (@0)); }))
+ { build_zero_cst (type); }))
+
+/* Simplify ((C << x) & D) != 0 where C and D are power of two constants,
+ either to false if D is smaller (unsigned comparison) than C, or to
+ x == log2 (D) - log2 (C). Similarly for right shifts. */
+(for cmp (ne eq)
+ icmp (eq ne)
+ (simplify
+ (cmp (bit_and (lshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
+ (with { int c1 = wi::clz (wi::to_wide (@1));
+ int c2 = wi::clz (wi::to_wide (@2)); }
+ (if (c1 < c2)
+ { constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
+ (icmp @0 { build_int_cst (TREE_TYPE (@0), c1 - c2); }))))
+ (simplify
+ (cmp (bit_and (rshift integer_pow2p@1 @0) integer_pow2p@2) integer_zerop)
+ (if (tree_int_cst_sgn (@1) > 0)
+ (with { int c1 = wi::clz (wi::to_wide (@1));
+ int c2 = wi::clz (wi::to_wide (@2)); }
+ (if (c1 > c2)
+ { constant_boolean_node (cmp == NE_EXPR ? false : true, type); }
+ (icmp @0 { build_int_cst (TREE_TYPE (@0), c2 - c1); }))))))
+
+/* (CST1 << A) == CST2 -> A == ctz (CST2) - ctz (CST1)
+ (CST1 << A) != CST2 -> A != ctz (CST2) - ctz (CST1)
+ if CST2 != 0. */
+(for cmp (ne eq)
+ (simplify
+ (cmp (lshift INTEGER_CST@0 @1) INTEGER_CST@2)
+ (with { int cand = wi::ctz (wi::to_wide (@2)) - wi::ctz (wi::to_wide (@0)); }
+ (if (cand < 0
+ || (!integer_zerop (@2)
+ && wi::lshift (wi::to_wide (@0), cand) != wi::to_wide (@2)))
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (if (!integer_zerop (@2)
+ && wi::lshift (wi::to_wide (@0), cand) == wi::to_wide (@2))
+ (cmp @1 { build_int_cst (TREE_TYPE (@1), cand); }))))))
+
+/* Fold (X << C1) & C2 into (X << C1) & (C2 | ((1 << C1) - 1))
+ (X >> C1) & C2 into (X >> C1) & (C2 | ~((type) -1 >> C1))
+ if the new mask might be further optimized. */
+(for shift (lshift rshift)
+ (simplify
+ (bit_and (convert?:s@4 (shift:s@5 (convert1?@3 @0) INTEGER_CST@1))
+ INTEGER_CST@2)
+ (if (tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@5))
+ && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT
+ && tree_fits_uhwi_p (@1)
+ && tree_to_uhwi (@1) > 0
+ && tree_to_uhwi (@1) < TYPE_PRECISION (type))
+ (with
+ {
+ unsigned int shiftc = tree_to_uhwi (@1);
+ unsigned HOST_WIDE_INT mask = TREE_INT_CST_LOW (@2);
+ unsigned HOST_WIDE_INT newmask, zerobits = 0;
+ tree shift_type = TREE_TYPE (@3);
+ unsigned int prec;
+
+ if (shift == LSHIFT_EXPR)
+ zerobits = ((HOST_WIDE_INT_1U << shiftc) - 1);
+ else if (shift == RSHIFT_EXPR
+ && type_has_mode_precision_p (shift_type))
+ {
+ prec = TYPE_PRECISION (TREE_TYPE (@3));
+ tree arg00 = @0;
+ /* See if more bits can be proven as zero because of
+ zero extension. */
+ if (@3 != @0
+ && TYPE_UNSIGNED (TREE_TYPE (@0)))
+ {
+ tree inner_type = TREE_TYPE (@0);
+ if (type_has_mode_precision_p (inner_type)
+ && TYPE_PRECISION (inner_type) < prec)
+ {
+ prec = TYPE_PRECISION (inner_type);
+ /* See if we can shorten the right shift. */
+ if (shiftc < prec)
+ shift_type = inner_type;
+ /* Otherwise X >> C1 is all zeros, so we'll optimize
+ it into (X, 0) later on by making sure zerobits
+ is all ones. */
+ }
+ }
+ zerobits = HOST_WIDE_INT_M1U;
+ if (shiftc < prec)
+ {
+ zerobits >>= HOST_BITS_PER_WIDE_INT - shiftc;
+ zerobits <<= prec - shiftc;
+ }
+ /* For arithmetic shift if sign bit could be set, zerobits
+ can contain actually sign bits, so no transformation is
+ possible, unless MASK masks them all away. In that
+ case the shift needs to be converted into logical shift. */
+ if (!TYPE_UNSIGNED (TREE_TYPE (@3))
+ && prec == TYPE_PRECISION (TREE_TYPE (@3)))
+ {
+ if ((mask & zerobits) == 0)
+ shift_type = unsigned_type_for (TREE_TYPE (@3));
+ else
+ zerobits = 0;
+ }
+ }
+ }
+ /* ((X << 16) & 0xff00) is (X, 0). */
+ (if ((mask & zerobits) == mask)
+ { build_int_cst (type, 0); }
+ (with { newmask = mask | zerobits; }
+ (if (newmask != mask && (newmask & (newmask + 1)) == 0)
+ (with
+ {
+ /* Only do the transformation if NEWMASK is some integer
+ mode's mask. */
+ for (prec = BITS_PER_UNIT;
+ prec < HOST_BITS_PER_WIDE_INT; prec <<= 1)
+ if (newmask == (HOST_WIDE_INT_1U << prec) - 1)
+ break;
+ }
+ (if (prec < HOST_BITS_PER_WIDE_INT
+ || newmask == HOST_WIDE_INT_M1U)
+ (with
+ { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); }
+ (if (!tree_int_cst_equal (newmaskt, @2))
+ (if (shift_type != TREE_TYPE (@3))
+ (bit_and (convert (shift:shift_type (convert @3) @1)) { newmaskt; })
+ (bit_and @4 { newmaskt; })))))))))))))
+
+/* ((1 << n) & M) != 0 -> n == log2 (M) */
+(for cmp (ne eq)
+ icmp (eq ne)
+ (simplify
+ (cmp
+ (bit_and
+ (nop_convert? (lshift integer_onep @0)) integer_pow2p@1) integer_zerop)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+ (icmp @0 { wide_int_to_tree (TREE_TYPE (@0),
+ wi::exact_log2 (wi::to_wide (@1))); }))))
+
+/* Fold (X {&,^,|} C2) << C1 into (X << C1) {&,^,|} (C2 << C1)
+ (X {&,^,|} C2) >> C1 into (X >> C1) & (C2 >> C1). */
+(for shift (lshift rshift)
+ (for bit_op (bit_and bit_xor bit_ior)
+ (simplify
+ (shift (convert?:s (bit_op:s @0 INTEGER_CST@2)) INTEGER_CST@1)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))
+ (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); }
+ (if (mask)
+ (bit_op (shift (convert @0) @1) { mask; })))))))
+
+/* ~(~X >> Y) -> X >> Y (for arithmetic shift). */
+(simplify
+ (bit_not (convert1?:s (rshift:s (convert2?@0 (bit_not @1)) @2)))
+ (if (!TYPE_UNSIGNED (TREE_TYPE (@0))
+ && (element_precision (TREE_TYPE (@0))
+ <= element_precision (TREE_TYPE (@1))
+ || !TYPE_UNSIGNED (TREE_TYPE (@1))))
+ (with
+ { tree shift_type = TREE_TYPE (@0); }
+ (convert (rshift (convert:shift_type @1) @2)))))
+
+/* ~(~X >>r Y) -> X >>r Y
+ ~(~X <<r Y) -> X <<r Y */
+(for rotate (lrotate rrotate)
+ (simplify
+ (bit_not (convert1?:s (rotate:s (convert2?@0 (bit_not @1)) @2)))
+ (if ((element_precision (TREE_TYPE (@0))
+ <= element_precision (TREE_TYPE (@1))
+ || !TYPE_UNSIGNED (TREE_TYPE (@1)))
+ && (element_precision (type) <= element_precision (TREE_TYPE (@0))
+ || !TYPE_UNSIGNED (TREE_TYPE (@0))))
+ (with
+ { tree rotate_type = TREE_TYPE (@0); }
+ (convert (rotate (convert:rotate_type @1) @2))))))
+
+(for cmp (eq ne)
+ (for rotate (lrotate rrotate)
+ invrot (rrotate lrotate)
+ /* (X >>r Y) cmp (Z >>r Y) may simplify to X cmp Y. */
+ (simplify
+ (cmp (rotate @1 @0) (rotate @2 @0))
+ (cmp @1 @2))
+ /* (X >>r C1) cmp C2 may simplify to X cmp C3. */
+ (simplify
+ (cmp (rotate @0 INTEGER_CST@1) INTEGER_CST@2)
+ (cmp @0 { const_binop (invrot, TREE_TYPE (@0), @2, @1); }))
+ /* (X >>r Y) cmp C where C is 0 or ~0, may simplify to X cmp C. */
+ (simplify
+ (cmp (rotate @0 @1) INTEGER_CST@2)
+ (if (integer_zerop (@2) || integer_all_onesp (@2))
+ (cmp @0 @2)))))
+
+/* Both signed and unsigned lshift produce the same result, so use
+ the form that minimizes the number of conversions. Postpone this
+ transformation until after shifts by zero have been folded. */
+(simplify
+ (convert (lshift:s@0 (convert:s@1 @2) INTEGER_CST@3))
+ (if (INTEGRAL_TYPE_P (type)
+ && tree_nop_conversion_p (type, TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && TYPE_PRECISION (TREE_TYPE (@2)) <= TYPE_PRECISION (type)
+ && !integer_zerop (@3))
+ (lshift (convert @2) @3)))
+
+/* Simplifications of conversions. */
+
+/* Basic strip-useless-type-conversions / strip_nops. */
+(for cvt (convert view_convert float fix_trunc)
+ (simplify
+ (cvt @0)
+ (if ((GIMPLE && useless_type_conversion_p (type, TREE_TYPE (@0)))
+ || (GENERIC && type == TREE_TYPE (@0)))
+ @0)))
+
+/* Contract view-conversions. */
+(simplify
+ (view_convert (view_convert @0))
+ (view_convert @0))
+
+/* For integral conversions with the same precision or pointer
+ conversions use a NOP_EXPR instead. */
+(simplify
+ (view_convert @0)
+ (if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
+ && (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
+ && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0)))
+ (convert @0)))
+
+/* Strip inner integral conversions that do not change precision or size, or
+ zero-extend while keeping the same size (for bool-to-char). */
+(simplify
+ (view_convert (convert@0 @1))
+ (if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
+ && (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
+ && TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1))
+ && (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))
+ || (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@1))
+ && TYPE_UNSIGNED (TREE_TYPE (@1)))))
+ (view_convert @1)))
+
+/* Simplify a view-converted empty constructor. */
+(simplify
+ (view_convert CONSTRUCTOR@0)
+ (if (TREE_CODE (@0) != SSA_NAME
+ && CONSTRUCTOR_NELTS (@0) == 0)
+ { build_zero_cst (type); }))
+
+/* Re-association barriers around constants and other re-association
+ barriers can be removed. */
+(simplify
+ (paren CONSTANT_CLASS_P@0)
+ @0)
+(simplify
+ (paren (paren@1 @0))
+ @1)
+
+/* Handle cases of two conversions in a row. */
+(for ocvt (convert float fix_trunc)
+ (for icvt (convert float)
+ (simplify
+ (ocvt (icvt@1 @0))
+ (with
+ {
+ tree inside_type = TREE_TYPE (@0);
+ tree inter_type = TREE_TYPE (@1);
+ int inside_int = INTEGRAL_TYPE_P (inside_type);
+ int inside_ptr = POINTER_TYPE_P (inside_type);
+ int inside_float = FLOAT_TYPE_P (inside_type);
+ int inside_vec = VECTOR_TYPE_P (inside_type);
+ unsigned int inside_prec = TYPE_PRECISION (inside_type);
+ int inside_unsignedp = TYPE_UNSIGNED (inside_type);
+ int inter_int = INTEGRAL_TYPE_P (inter_type);
+ int inter_ptr = POINTER_TYPE_P (inter_type);
+ int inter_float = FLOAT_TYPE_P (inter_type);
+ int inter_vec = VECTOR_TYPE_P (inter_type);
+ unsigned int inter_prec = TYPE_PRECISION (inter_type);
+ int inter_unsignedp = TYPE_UNSIGNED (inter_type);
+ int final_int = INTEGRAL_TYPE_P (type);
+ int final_ptr = POINTER_TYPE_P (type);
+ int final_float = FLOAT_TYPE_P (type);
+ int final_vec = VECTOR_TYPE_P (type);
+ unsigned int final_prec = TYPE_PRECISION (type);
+ int final_unsignedp = TYPE_UNSIGNED (type);
+ }
+ (switch
+ /* In addition to the cases of two conversions in a row
+ handled below, if we are converting something to its own
+ type via an object of identical or wider precision, neither
+ conversion is needed. */
+ (if (((GIMPLE && useless_type_conversion_p (type, inside_type))
+ || (GENERIC
+ && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
+ && (((inter_int || inter_ptr) && final_int)
+ || (inter_float && final_float))
+ && inter_prec >= final_prec)
+ (ocvt @0))
+
+ /* Likewise, if the intermediate and initial types are either both
+ float or both integer, we don't need the middle conversion if the
+ former is wider than the latter and doesn't change the signedness
+ (for integers). Avoid this if the final type is a pointer since
+ then we sometimes need the middle conversion. */
+ (if (((inter_int && inside_int) || (inter_float && inside_float))
+ && (final_int || final_float)
+ && inter_prec >= inside_prec
+ && (inter_float || inter_unsignedp == inside_unsignedp))
+ (ocvt @0))
+
+ /* If we have a sign-extension of a zero-extended value, we can
+ replace that by a single zero-extension. Likewise if the
+ final conversion does not change precision we can drop the
+ intermediate conversion. */
+ (if (inside_int && inter_int && final_int
+ && ((inside_prec < inter_prec && inter_prec < final_prec
+ && inside_unsignedp && !inter_unsignedp)
+ || final_prec == inter_prec))
+ (ocvt @0))
+
+ /* Two conversions in a row are not needed unless:
+ - some conversion is floating-point (overstrict for now), or
+ - some conversion is a vector (overstrict for now), or
+ - the intermediate type is narrower than both initial and
+ final, or
+ - the intermediate type and innermost type differ in signedness,
+ and the outermost type is wider than the intermediate, or
+ - the initial type is a pointer type and the precisions of the
+ intermediate and final types differ, or
+ - the final type is a pointer type and the precisions of the
+ initial and intermediate types differ. */
+ (if (! inside_float && ! inter_float && ! final_float
+ && ! inside_vec && ! inter_vec && ! final_vec
+ && (inter_prec >= inside_prec || inter_prec >= final_prec)
+ && ! (inside_int && inter_int
+ && inter_unsignedp != inside_unsignedp
+ && inter_prec < final_prec)
+ && ((inter_unsignedp && inter_prec > inside_prec)
+ == (final_unsignedp && final_prec > inter_prec))
+ && ! (inside_ptr && inter_prec != final_prec)
+ && ! (final_ptr && inside_prec != inter_prec))
+ (ocvt @0))
+
+ /* A truncation to an unsigned type (a zero-extension) should be
+ canonicalized as bitwise and of a mask. */
+ (if (GIMPLE /* PR70366: doing this in GENERIC breaks -Wconversion. */
+ && final_int && inter_int && inside_int
+ && final_prec == inside_prec
+ && final_prec > inter_prec
+ && inter_unsignedp)
+ (convert (bit_and @0 { wide_int_to_tree
+ (inside_type,
+ wi::mask (inter_prec, false,
+ TYPE_PRECISION (inside_type))); })))
+
+ /* If we are converting an integer to a floating-point that can
+ represent it exactly and back to an integer, we can skip the
+ floating-point conversion. */
+ (if (GIMPLE /* PR66211 */
+ && inside_int && inter_float && final_int &&
+ (unsigned) significand_size (TYPE_MODE (inter_type))
+ >= inside_prec - !inside_unsignedp)
+ (convert @0)))))))
+
+/* (float_type)(integer_type) x -> trunc (x) if the type of x matches
+ float_type. Only do the transformation if we do not need to preserve
+ trapping behaviour, so require !flag_trapping_math. */
+#if GIMPLE
+(simplify
+ (float (fix_trunc @0))
+ (if (!flag_trapping_math
+ && types_match (type, TREE_TYPE (@0))
+ && direct_internal_fn_supported_p (IFN_TRUNC, type,
+ OPTIMIZE_FOR_BOTH))
+ (IFN_TRUNC @0)))
+#endif
+
+/* If we have a narrowing conversion to an integral type that is fed by a
+ BIT_AND_EXPR, we might be able to remove the BIT_AND_EXPR if it merely
+ masks off bits outside the final type (and nothing else). */
+(simplify
+ (convert (bit_and @0 INTEGER_CST@1))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0))
+ && operand_equal_p (@1, build_low_bits_mask (TREE_TYPE (@1),
+ TYPE_PRECISION (type)), 0))
+ (convert @0)))
+
+
+/* (X /[ex] A) * A -> X. */
+(simplify
+ (mult (convert1? (exact_div @0 @@1)) (convert2? @1))
+ (convert @0))
+
+/* Simplify (A / B) * B + (A % B) -> A. */
+(for div (trunc_div ceil_div floor_div round_div)
+ mod (trunc_mod ceil_mod floor_mod round_mod)
+ (simplify
+ (plus:c (mult:c (div @0 @1) @1) (mod @0 @1))
+ @0))
+
+/* ((X /[ex] A) +- B) * A --> X +- A * B. */
+(for op (plus minus)
+ (simplify
+ (mult (convert1? (op (convert2? (exact_div @0 INTEGER_CST@@1)) INTEGER_CST@2)) @1)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@2))
+ && tree_nop_conversion_p (TREE_TYPE (@0), TREE_TYPE (@2)))
+ (with
+ {
+ wi::overflow_type overflow;
+ wide_int mul = wi::mul (wi::to_wide (@1), wi::to_wide (@2),
+ TYPE_SIGN (type), &overflow);
+ }
+ (if (types_match (type, TREE_TYPE (@2))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@2)) && !overflow)
+ (op @0 { wide_int_to_tree (type, mul); })
+ (with { tree utype = unsigned_type_for (type); }
+ (convert (op (convert:utype @0)
+ (mult (convert:utype @1) (convert:utype @2))))))))))
+
+/* Canonicalization of binary operations. */
+
+/* Convert X + -C into X - C. */
+(simplify
+ (plus @0 REAL_CST@1)
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+ (with { tree tem = const_unop (NEGATE_EXPR, type, @1); }
+ (if (!TREE_OVERFLOW (tem) || !flag_trapping_math)
+ (minus @0 { tem; })))))
+
+/* Convert x+x into x*2. */
+(simplify
+ (plus @0 @0)
+ (if (SCALAR_FLOAT_TYPE_P (type))
+ (mult @0 { build_real (type, dconst2); })
+ (if (INTEGRAL_TYPE_P (type))
+ (mult @0 { build_int_cst (type, 2); }))))
+
+/* 0 - X -> -X. */
+(simplify
+ (minus integer_zerop @1)
+ (negate @1))
+(simplify
+ (pointer_diff integer_zerop @1)
+ (negate (convert @1)))
+
+/* (ARG0 - ARG1) is the same as (-ARG1 + ARG0). So check whether
+ ARG0 is zero and X + ARG0 reduces to X, since that would mean
+ (-ARG1 + ARG0) reduces to -ARG1. */
+(simplify
+ (minus real_zerop@0 @1)
+ (if (fold_real_zero_addition_p (type, @1, @0, 0))
+ (negate @1)))
+
+/* Transform x * -1 into -x. */
+(simplify
+ (mult @0 integer_minus_onep)
+ (negate @0))
+
+/* Reassociate (X * CST) * Y to (X * Y) * CST. This does not introduce
+ signed overflow for CST != 0 && CST != -1. */
+(simplify
+ (mult:c (mult:s@3 @0 INTEGER_CST@1) @2)
+ (if (TREE_CODE (@2) != INTEGER_CST
+ && single_use (@3)
+ && !integer_zerop (@1) && !integer_minus_onep (@1))
+ (mult (mult @0 @2) @1)))
+
+/* True if we can easily extract the real and imaginary parts of a complex
+ number. */
+(match compositional_complex
+ (convert? (complex @0 @1)))
+
+/* COMPLEX_EXPR and REALPART/IMAGPART_EXPR cancellations. */
+(simplify
+ (complex (realpart @0) (imagpart @0))
+ @0)
+(simplify
+ (realpart (complex @0 @1))
+ @0)
+(simplify
+ (imagpart (complex @0 @1))
+ @1)
+
+/* Sometimes we only care about half of a complex expression. */
+(simplify
+ (realpart (convert?:s (conj:s @0)))
+ (convert (realpart @0)))
+(simplify
+ (imagpart (convert?:s (conj:s @0)))
+ (convert (negate (imagpart @0))))
+(for part (realpart imagpart)
+ (for op (plus minus)
+ (simplify
+ (part (convert?:s@2 (op:s @0 @1)))
+ (convert (op (part @0) (part @1))))))
+(simplify
+ (realpart (convert?:s (CEXPI:s @0)))
+ (convert (COS @0)))
+(simplify
+ (imagpart (convert?:s (CEXPI:s @0)))
+ (convert (SIN @0)))
+
+/* conj(conj(x)) -> x */
+(simplify
+ (conj (convert? (conj @0)))
+ (if (tree_nop_conversion_p (TREE_TYPE (@0), type))
+ (convert @0)))
+
+/* conj({x,y}) -> {x,-y} */
+(simplify
+ (conj (convert?:s (complex:s @0 @1)))
+ (with { tree itype = TREE_TYPE (type); }
+ (complex (convert:itype @0) (negate (convert:itype @1)))))
+
+/* BSWAP simplifications, transforms checked by gcc.dg/builtin-bswap-8.c. */
+(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32
+ BUILT_IN_BSWAP64 BUILT_IN_BSWAP128)
+ (simplify
+ (bswap (bswap @0))
+ @0)
+ (simplify
+ (bswap (bit_not (bswap @0)))
+ (bit_not @0))
+ (for bitop (bit_xor bit_ior bit_and)
+ (simplify
+ (bswap (bitop:c (bswap @0) @1))
+ (bitop @0 (bswap @1))))
+ (for cmp (eq ne)
+ (simplify
+ (cmp (bswap@2 @0) (bswap @1))
+ (with { tree ctype = TREE_TYPE (@2); }
+ (cmp (convert:ctype @0) (convert:ctype @1))))
+ (simplify
+ (cmp (bswap @0) INTEGER_CST@1)
+ (with { tree ctype = TREE_TYPE (@1); }
+ (cmp (convert:ctype @0) (bswap! @1)))))
+ /* (bswap(x) >> C1) & C2 can sometimes be simplified to (x >> C3) & C2. */
+ (simplify
+ (bit_and (convert1? (rshift@0 (convert2? (bswap@4 @1)) INTEGER_CST@2))
+ INTEGER_CST@3)
+ (if (BITS_PER_UNIT == 8
+ && tree_fits_uhwi_p (@2)
+ && tree_fits_uhwi_p (@3))
+ (with
+ {
+ unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@4));
+ unsigned HOST_WIDE_INT bits = tree_to_uhwi (@2);
+ unsigned HOST_WIDE_INT mask = tree_to_uhwi (@3);
+ unsigned HOST_WIDE_INT lo = bits & 7;
+ unsigned HOST_WIDE_INT hi = bits - lo;
+ }
+ (if (bits < prec
+ && mask < (256u>>lo)
+ && bits < TYPE_PRECISION (TREE_TYPE(@0)))
+ (with { unsigned HOST_WIDE_INT ns = (prec - (hi + 8)) + lo; }
+ (if (ns == 0)
+ (bit_and (convert @1) @3)
+ (with
+ {
+ tree utype = unsigned_type_for (TREE_TYPE (@1));
+ tree nst = build_int_cst (integer_type_node, ns);
+ }
+ (bit_and (convert (rshift:utype (convert:utype @1) {nst;})) @3))))))))
+ /* bswap(x) >> C1 can sometimes be simplified to (T)x >> C2. */
+ (simplify
+ (rshift (convert? (bswap@2 @0)) INTEGER_CST@1)
+ (if (BITS_PER_UNIT == 8
+ && CHAR_TYPE_SIZE == 8
+ && tree_fits_uhwi_p (@1))
+ (with
+ {
+ unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@2));
+ unsigned HOST_WIDE_INT bits = tree_to_uhwi (@1);
+ /* If the bswap was extended before the original shift, this
+ byte (shift) has the sign of the extension, not the sign of
+ the original shift. */
+ tree st = TYPE_PRECISION (type) > prec ? TREE_TYPE (@2) : type;
+ }
+ /* Special case: logical right shift of sign-extended bswap.
+ (unsigned)(short)bswap16(x)>>12 is (unsigned)((short)x<<8)>>12. */
+ (if (TYPE_PRECISION (type) > prec
+ && !TYPE_UNSIGNED (TREE_TYPE (@2))
+ && TYPE_UNSIGNED (type)
+ && bits < prec && bits + 8 >= prec)
+ (with { tree nst = build_int_cst (integer_type_node, prec - 8); }
+ (rshift (convert (lshift:st (convert:st @0) {nst;})) @1))
+ (if (bits + 8 == prec)
+ (if (TYPE_UNSIGNED (st))
+ (convert (convert:unsigned_char_type_node @0))
+ (convert (convert:signed_char_type_node @0)))
+ (if (bits < prec && bits + 8 > prec)
+ (with
+ {
+ tree nst = build_int_cst (integer_type_node, bits & 7);
+ tree bt = TYPE_UNSIGNED (st) ? unsigned_char_type_node
+ : signed_char_type_node;
+ }
+ (convert (rshift:bt (convert:bt @0) {nst;})))))))))
+ /* bswap(x) & C1 can sometimes be simplified to (x >> C2) & C1. */
+ (simplify
+ (bit_and (convert? (bswap@2 @0)) INTEGER_CST@1)
+ (if (BITS_PER_UNIT == 8
+ && tree_fits_uhwi_p (@1)
+ && tree_to_uhwi (@1) < 256)
+ (with
+ {
+ unsigned HOST_WIDE_INT prec = TYPE_PRECISION (TREE_TYPE (@2));
+ tree utype = unsigned_type_for (TREE_TYPE (@0));
+ tree nst = build_int_cst (integer_type_node, prec - 8);
+ }
+ (bit_and (convert (rshift:utype (convert:utype @0) {nst;})) @1)))))
+
+
+/* Combine COND_EXPRs and VEC_COND_EXPRs. */
+
+/* Simplify constant conditions.
+ Only optimize constant conditions when the selected branch
+ has the same type as the COND_EXPR. This avoids optimizing
+ away "c ? x : throw", where the throw has a void type.
+ Note that we cannot throw away the fold-const.cc variant nor
+ this one as we depend on doing this transform before possibly
+ A ? B : B -> B triggers and the fold-const.cc one can optimize
+ 0 ? A : B to B even if A has side-effects. Something
+ genmatch cannot handle. */
+(simplify
+ (cond INTEGER_CST@0 @1 @2)
+ (if (integer_zerop (@0))
+ (if (!VOID_TYPE_P (TREE_TYPE (@2)) || VOID_TYPE_P (type))
+ @2)
+ (if (!VOID_TYPE_P (TREE_TYPE (@1)) || VOID_TYPE_P (type))
+ @1)))
+(simplify
+ (vec_cond VECTOR_CST@0 @1 @2)
+ (if (integer_all_onesp (@0))
+ @1
+ (if (integer_zerop (@0))
+ @2)))
+
+#if GIMPLE
+/* Sink unary operations to branches, but only if we do fold both. */
+(for op (negate bit_not abs absu)
+ (simplify
+ (op (vec_cond:s @0 @1 @2))
+ (vec_cond @0 (op! @1) (op! @2))))
+
+/* Sink binary operation to branches, but only if we can fold it. */
+(for op (tcc_comparison plus minus mult bit_and bit_ior bit_xor
+ lshift rshift rdiv trunc_div ceil_div floor_div round_div
+ trunc_mod ceil_mod floor_mod round_mod min max)
+/* (c ? a : b) op (c ? d : e) --> c ? (a op d) : (b op e) */
+ (simplify
+ (op (vec_cond:s @0 @1 @2) (vec_cond:s @0 @3 @4))
+ (vec_cond @0 (op! @1 @3) (op! @2 @4)))
+
+/* (c ? a : b) op d --> c ? (a op d) : (b op d) */
+ (simplify
+ (op (vec_cond:s @0 @1 @2) @3)
+ (vec_cond @0 (op! @1 @3) (op! @2 @3)))
+ (simplify
+ (op @3 (vec_cond:s @0 @1 @2))
+ (vec_cond @0 (op! @3 @1) (op! @3 @2))))
+#endif
+
+#if GIMPLE
+(match (nop_atomic_bit_test_and_p @0 @1 @4)
+ (bit_and (convert?@4 (ATOMIC_FETCH_OR_XOR_N @2 INTEGER_CST@0 @3))
+ INTEGER_CST@1)
+ (with {
+ int ibit = tree_log2 (@0);
+ int ibit2 = tree_log2 (@1);
+ }
+ (if (ibit == ibit2
+ && ibit >= 0
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0))))))
+
+(match (nop_atomic_bit_test_and_p @0 @1 @3)
+ (bit_and (convert?@3 (SYNC_FETCH_OR_XOR_N @2 INTEGER_CST@0))
+ INTEGER_CST@1)
+ (with {
+ int ibit = tree_log2 (@0);
+ int ibit2 = tree_log2 (@1);
+ }
+ (if (ibit == ibit2
+ && ibit >= 0
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0))))))
+
+(match (nop_atomic_bit_test_and_p @0 @0 @4)
+ (bit_and:c
+ (convert1?@4
+ (ATOMIC_FETCH_OR_XOR_N @2 (nop_convert? (lshift@0 integer_onep@5 @6)) @3))
+ (convert2? @0))
+ (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0)))))
+
+(match (nop_atomic_bit_test_and_p @0 @0 @4)
+ (bit_and:c
+ (convert1?@4
+ (SYNC_FETCH_OR_XOR_N @2 (nop_convert? (lshift@0 integer_onep@3 @5))))
+ (convert2? @0))
+ (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0)))))
+
+(match (nop_atomic_bit_test_and_p @0 @1 @3)
+ (bit_and@4 (convert?@3 (ATOMIC_FETCH_AND_N @2 INTEGER_CST@0 @5))
+ INTEGER_CST@1)
+ (with {
+ int ibit = wi::exact_log2 (wi::zext (wi::bit_not (wi::to_wide (@0)),
+ TYPE_PRECISION(type)));
+ int ibit2 = tree_log2 (@1);
+ }
+ (if (ibit == ibit2
+ && ibit >= 0
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0))))))
+
+(match (nop_atomic_bit_test_and_p @0 @1 @3)
+ (bit_and@4
+ (convert?@3 (SYNC_FETCH_AND_AND_N @2 INTEGER_CST@0))
+ INTEGER_CST@1)
+ (with {
+ int ibit = wi::exact_log2 (wi::zext (wi::bit_not (wi::to_wide (@0)),
+ TYPE_PRECISION(type)));
+ int ibit2 = tree_log2 (@1);
+ }
+ (if (ibit == ibit2
+ && ibit >= 0
+ && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@0))))))
+
+(match (nop_atomic_bit_test_and_p @4 @0 @3)
+ (bit_and:c
+ (convert1?@3
+ (ATOMIC_FETCH_AND_N @2 (nop_convert?@4 (bit_not (lshift@0 integer_onep@6 @7))) @5))
+ (convert2? @0))
+ (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@4)))))
+
+(match (nop_atomic_bit_test_and_p @4 @0 @3)
+ (bit_and:c
+ (convert1?@3
+ (SYNC_FETCH_AND_AND_N @2 (nop_convert?@4 (bit_not (lshift@0 integer_onep@6 @7)))))
+ (convert2? @0))
+ (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@4)))))
+
+#endif
+
+/* (v ? w : 0) ? a : b is just (v & w) ? a : b
+ Currently disabled after pass lvec because ARM understands
+ VEC_COND_EXPR<v==w,-1,0> but not a plain v==w fed to BIT_IOR_EXPR. */
+(simplify
+ (vec_cond (vec_cond:s @0 @3 integer_zerop) @1 @2)
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @3))
+ (vec_cond (bit_and @0 @3) @1 @2)))
+(simplify
+ (vec_cond (vec_cond:s @0 integer_all_onesp @3) @1 @2)
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @3))
+ (vec_cond (bit_ior @0 @3) @1 @2)))
+(simplify
+ (vec_cond (vec_cond:s @0 integer_zerop @3) @1 @2)
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @3))
+ (vec_cond (bit_ior @0 (bit_not @3)) @2 @1)))
+(simplify
+ (vec_cond (vec_cond:s @0 @3 integer_all_onesp) @1 @2)
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @3))
+ (vec_cond (bit_and @0 (bit_not @3)) @2 @1)))
+
+/* c1 ? c2 ? a : b : b --> (c1 & c2) ? a : b */
+(simplify
+ (vec_cond @0 (vec_cond:s @1 @2 @3) @3)
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @1))
+ (vec_cond (bit_and @0 @1) @2 @3)))
+(simplify
+ (vec_cond @0 @2 (vec_cond:s @1 @2 @3))
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @1))
+ (vec_cond (bit_ior @0 @1) @2 @3)))
+(simplify
+ (vec_cond @0 (vec_cond:s @1 @2 @3) @2)
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @1))
+ (vec_cond (bit_ior (bit_not @0) @1) @2 @3)))
+(simplify
+ (vec_cond @0 @3 (vec_cond:s @1 @2 @3))
+ (if (optimize_vectors_before_lowering_p () && types_match (@0, @1))
+ (vec_cond (bit_and (bit_not @0) @1) @2 @3)))
+
+/* Canonicalize mask ? { 0, ... } : { -1, ...} to ~mask if the mask
+ types are compatible. */
+(simplify
+ (vec_cond @0 VECTOR_CST@1 VECTOR_CST@2)
+ (if (VECTOR_BOOLEAN_TYPE_P (type)
+ && types_match (type, TREE_TYPE (@0)))
+ (if (integer_zerop (@1) && integer_all_onesp (@2))
+ (bit_not @0)
+ (if (integer_all_onesp (@1) && integer_zerop (@2))
+ @0))))
+
+/* A few simplifications of "a ? CST1 : CST2". */
+/* NOTE: Only do this on gimple as the if-chain-to-switch
+ optimization depends on the gimple to have if statements in it. */
+#if GIMPLE
+(simplify
+ (cond @0 INTEGER_CST@1 INTEGER_CST@2)
+ (switch
+ (if (integer_zerop (@2))
+ (switch
+ /* a ? 1 : 0 -> a if 0 and 1 are integral types. */
+ (if (integer_onep (@1))
+ (convert (convert:boolean_type_node @0)))
+ /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */
+ (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1))
+ (with {
+ tree shift = build_int_cst (integer_type_node, tree_log2 (@1));
+ }
+ (lshift (convert (convert:boolean_type_node @0)) { shift; })))
+ /* a ? -1 : 0 -> -a. No need to check the TYPE_PRECISION not being 1
+ here as the powerof2cst case above will handle that case correctly. */
+ (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
+ (negate (convert (convert:boolean_type_node @0))))))
+ (if (integer_zerop (@1))
+ (with {
+ tree booltrue = constant_boolean_node (true, boolean_type_node);
+ }
+ (switch
+ /* a ? 0 : 1 -> !a. */
+ (if (integer_onep (@2))
+ (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))
+ /* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */
+ (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@2))
+ (with {
+ tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
+ }
+ (lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))
+ { shift; })))
+ /* a ? -1 : 0 -> -(!a). No need to check the TYPE_PRECISION not being 1
+ here as the powerof2cst case above will handle that case correctly. */
+ (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
+ (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
+ )
+ )
+ )
+ )
+)
+#endif
+
+/* Simplification moved from fold_cond_expr_with_comparison. It may also
+ be extended. */
+/* This pattern implements two kinds simplification:
+
+ Case 1)
+ (cond (cmp (convert1? x) c1) (convert2? x) c2) -> (minmax (x c)) if:
+ 1) Conversions are type widening from smaller type.
+ 2) Const c1 equals to c2 after canonicalizing comparison.
+ 3) Comparison has tree code LT, LE, GT or GE.
+ This specific pattern is needed when (cmp (convert x) c) may not
+ be simplified by comparison patterns because of multiple uses of
+ x. It also makes sense here because simplifying across multiple
+ referred var is always benefitial for complicated cases.
+
+ Case 2)
+ (cond (eq (convert1? x) c1) (convert2? x) c2) -> (cond (eq x c1) c1 c2). */
+(for cmp (lt le gt ge eq)
+ (simplify
+ (cond (cmp (convert1? @1) INTEGER_CST@3) (convert2? @1) INTEGER_CST@2)
+ (with
+ {
+ tree from_type = TREE_TYPE (@1);
+ tree c1_type = TREE_TYPE (@3), c2_type = TREE_TYPE (@2);
+ enum tree_code code = ERROR_MARK;
+
+ if (INTEGRAL_TYPE_P (from_type)
+ && int_fits_type_p (@2, from_type)
+ && (types_match (c1_type, from_type)
+ || (TYPE_PRECISION (c1_type) > TYPE_PRECISION (from_type)
+ && (TYPE_UNSIGNED (from_type)
+ || TYPE_SIGN (c1_type) == TYPE_SIGN (from_type))))
+ && (types_match (c2_type, from_type)
+ || (TYPE_PRECISION (c2_type) > TYPE_PRECISION (from_type)
+ && (TYPE_UNSIGNED (from_type)
+ || TYPE_SIGN (c2_type) == TYPE_SIGN (from_type)))))
+ {
+ if (cmp != EQ_EXPR)
+ {
+ if (wi::to_widest (@3) == (wi::to_widest (@2) - 1))
+ {
+ /* X <= Y - 1 equals to X < Y. */
+ if (cmp == LE_EXPR)
+ code = LT_EXPR;
+ /* X > Y - 1 equals to X >= Y. */
+ if (cmp == GT_EXPR)
+ code = GE_EXPR;
+ }
+ if (wi::to_widest (@3) == (wi::to_widest (@2) + 1))
+ {
+ /* X < Y + 1 equals to X <= Y. */
+ if (cmp == LT_EXPR)
+ code = LE_EXPR;
+ /* X >= Y + 1 equals to X > Y. */
+ if (cmp == GE_EXPR)
+ code = GT_EXPR;
+ }
+ if (code != ERROR_MARK
+ || wi::to_widest (@2) == wi::to_widest (@3))
+ {
+ if (cmp == LT_EXPR || cmp == LE_EXPR)
+ code = MIN_EXPR;
+ if (cmp == GT_EXPR || cmp == GE_EXPR)
+ code = MAX_EXPR;
+ }
+ }
+ /* Can do A == C1 ? A : C2 -> A == C1 ? C1 : C2? */
+ else if (int_fits_type_p (@3, from_type))
+ code = EQ_EXPR;
+ }
+ }
+ (if (code == MAX_EXPR)
+ (convert (max @1 (convert @2)))
+ (if (code == MIN_EXPR)
+ (convert (min @1 (convert @2)))
+ (if (code == EQ_EXPR)
+ (convert (cond (eq @1 (convert @3))
+ (convert:from_type @3) (convert:from_type @2)))))))))
+
+/* (cond (cmp (convert? x) c1) (op x c2) c3) -> (op (minmax x c1) c2) if:
+
+ 1) OP is PLUS or MINUS.
+ 2) CMP is LT, LE, GT or GE.
+ 3) C3 == (C1 op C2), and computation doesn't have undefined behavior.
+
+ This pattern also handles special cases like:
+
+ A) Operand x is a unsigned to signed type conversion and c1 is
+ integer zero. In this case,
+ (signed type)x < 0 <=> x > MAX_VAL(signed type)
+ (signed type)x >= 0 <=> x <= MAX_VAL(signed type)
+ B) Const c1 may not equal to (C3 op' C2). In this case we also
+ check equality for (c1+1) and (c1-1) by adjusting comparison
+ code.
+
+ TODO: Though signed type is handled by this pattern, it cannot be
+ simplified at the moment because C standard requires additional
+ type promotion. In order to match&simplify it here, the IR needs
+ to be cleaned up by other optimizers, i.e, VRP. */
+(for op (plus minus)
+ (for cmp (lt le gt ge)
+ (simplify
+ (cond (cmp (convert? @X) INTEGER_CST@1) (op @X INTEGER_CST@2) INTEGER_CST@3)
+ (with { tree from_type = TREE_TYPE (@X), to_type = TREE_TYPE (@1); }
+ (if (types_match (from_type, to_type)
+ /* Check if it is special case A). */
+ || (TYPE_UNSIGNED (from_type)
+ && !TYPE_UNSIGNED (to_type)
+ && TYPE_PRECISION (from_type) == TYPE_PRECISION (to_type)
+ && integer_zerop (@1)
+ && (cmp == LT_EXPR || cmp == GE_EXPR)))
+ (with
+ {
+ wi::overflow_type overflow = wi::OVF_NONE;
+ enum tree_code code, cmp_code = cmp;
+ wide_int real_c1;
+ wide_int c1 = wi::to_wide (@1);
+ wide_int c2 = wi::to_wide (@2);
+ wide_int c3 = wi::to_wide (@3);
+ signop sgn = TYPE_SIGN (from_type);
+
+ /* Handle special case A), given x of unsigned type:
+ ((signed type)x < 0) <=> (x > MAX_VAL(signed type))
+ ((signed type)x >= 0) <=> (x <= MAX_VAL(signed type)) */
+ if (!types_match (from_type, to_type))
+ {
+ if (cmp_code == LT_EXPR)
+ cmp_code = GT_EXPR;
+ if (cmp_code == GE_EXPR)
+ cmp_code = LE_EXPR;
+ c1 = wi::max_value (to_type);
+ }
+ /* To simplify this pattern, we require c3 = (c1 op c2). Here we
+ compute (c3 op' c2) and check if it equals to c1 with op' being
+ the inverted operator of op. Make sure overflow doesn't happen
+ if it is undefined. */
+ if (op == PLUS_EXPR)
+ real_c1 = wi::sub (c3, c2, sgn, &overflow);
+ else
+ real_c1 = wi::add (c3, c2, sgn, &overflow);
+
+ code = cmp_code;
+ if (!overflow || !TYPE_OVERFLOW_UNDEFINED (from_type))
+ {
+ /* Check if c1 equals to real_c1. Boundary condition is handled
+ by adjusting comparison operation if necessary. */
+ if (!wi::cmp (wi::sub (real_c1, 1, sgn, &overflow), c1, sgn)
+ && !overflow)
+ {
+ /* X <= Y - 1 equals to X < Y. */
+ if (cmp_code == LE_EXPR)
+ code = LT_EXPR;
+ /* X > Y - 1 equals to X >= Y. */
+ if (cmp_code == GT_EXPR)
+ code = GE_EXPR;
+ }
+ if (!wi::cmp (wi::add (real_c1, 1, sgn, &overflow), c1, sgn)
+ && !overflow)
+ {
+ /* X < Y + 1 equals to X <= Y. */
+ if (cmp_code == LT_EXPR)
+ code = LE_EXPR;
+ /* X >= Y + 1 equals to X > Y. */
+ if (cmp_code == GE_EXPR)
+ code = GT_EXPR;
+ }
+ if (code != cmp_code || !wi::cmp (real_c1, c1, sgn))
+ {
+ if (cmp_code == LT_EXPR || cmp_code == LE_EXPR)
+ code = MIN_EXPR;
+ if (cmp_code == GT_EXPR || cmp_code == GE_EXPR)
+ code = MAX_EXPR;
+ }
+ }
+ }
+ (if (code == MAX_EXPR)
+ (op (max @X { wide_int_to_tree (from_type, real_c1); })
+ { wide_int_to_tree (from_type, c2); })
+ (if (code == MIN_EXPR)
+ (op (min @X { wide_int_to_tree (from_type, real_c1); })
+ { wide_int_to_tree (from_type, c2); })))))))))
+
+/* X != C1 ? -X : C2 simplifies to -X when -C1 == C2. */
+(simplify
+ (cond (ne @0 INTEGER_CST@1) (negate@3 @0) INTEGER_CST@2)
+ (if (!TYPE_SATURATING (type)
+ && (TYPE_OVERFLOW_WRAPS (type)
+ || !wi::only_sign_bit_p (wi::to_wide (@1)))
+ && wi::eq_p (wi::neg (wi::to_wide (@1)), wi::to_wide (@2)))
+ @3))
+
+/* X != C1 ? ~X : C2 simplifies to ~X when ~C1 == C2. */
+(simplify
+ (cond (ne @0 INTEGER_CST@1) (bit_not@3 @0) INTEGER_CST@2)
+ (if (wi::eq_p (wi::bit_not (wi::to_wide (@1)), wi::to_wide (@2)))
+ @3))
+
+/* (X + 1) > Y ? -X : 1 simplifies to X >= Y ? -X : 1 when
+ X is unsigned, as when X + 1 overflows, X is -1, so -X == 1. */
+(simplify
+ (cond (gt (plus @0 integer_onep) @1) (negate @0) integer_onep@2)
+ (if (TYPE_UNSIGNED (type))
+ (cond (ge @0 @1) (negate @0) @2)))
+
+(for cnd (cond vec_cond)
+ /* A ? B : (A ? X : C) -> A ? B : C. */
+ (simplify
+ (cnd @0 (cnd @0 @1 @2) @3)
+ (cnd @0 @1 @3))
+ (simplify
+ (cnd @0 @1 (cnd @0 @2 @3))
+ (cnd @0 @1 @3))
+ /* A ? B : (!A ? C : X) -> A ? B : C. */
+ /* ??? This matches embedded conditions open-coded because genmatch
+ would generate matching code for conditions in separate stmts only.
+ The following is still important to merge then and else arm cases
+ from if-conversion. */
+ (simplify
+ (cnd @0 @1 (cnd @2 @3 @4))
+ (if (inverse_conditions_p (@0, @2))
+ (cnd @0 @1 @3)))
+ (simplify
+ (cnd @0 (cnd @1 @2 @3) @4)
+ (if (inverse_conditions_p (@0, @1))
+ (cnd @0 @3 @4)))
+
+ /* A ? B : B -> B. */
+ (simplify
+ (cnd @0 @1 @1)
+ @1)
+
+ /* !A ? B : C -> A ? C : B. */
+ (simplify
+ (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
+ (cnd @0 @2 @1)))
+
+/* abs/negative simplifications moved from fold_cond_expr_with_comparison,
+ Need to handle (A - B) case as fold_cond_expr_with_comparison does.
+ Need to handle UN* comparisons.
+
+ None of these transformations work for modes with signed
+ zeros. If A is +/-0, the first two transformations will
+ change the sign of the result (from +0 to -0, or vice
+ versa). The last four will fix the sign of the result,
+ even though the original expressions could be positive or
+ negative, depending on the sign of A.
+
+ Note that all these transformations are correct if A is
+ NaN, since the two alternatives (A and -A) are also NaNs. */
+
+(for cnd (cond vec_cond)
+ /* A == 0 ? A : -A same as -A */
+ (for cmp (eq uneq)
+ (simplify
+ (cnd (cmp @0 zerop) @0 (negate@1 @0))
+ (if (!HONOR_SIGNED_ZEROS (type))
+ @1))
+ (simplify
+ (cnd (cmp @0 zerop) integer_zerop (negate@1 @0))
+ (if (!HONOR_SIGNED_ZEROS (type))
+ @1))
+ )
+ /* A != 0 ? A : -A same as A */
+ (for cmp (ne ltgt)
+ (simplify
+ (cnd (cmp @0 zerop) @0 (negate @0))
+ (if (!HONOR_SIGNED_ZEROS (type))
+ @0))
+ (simplify
+ (cnd (cmp @0 zerop) @0 integer_zerop)
+ (if (!HONOR_SIGNED_ZEROS (type))
+ @0))
+ )
+ /* A >=/> 0 ? A : -A same as abs (A) */
+ (for cmp (ge gt)
+ (simplify
+ (cnd (cmp @0 zerop) @0 (negate @0))
+ (if (!HONOR_SIGNED_ZEROS (type)
+ && !TYPE_UNSIGNED (type))
+ (abs @0))))
+ /* A <=/< 0 ? A : -A same as -abs (A) */
+ (for cmp (le lt)
+ (simplify
+ (cnd (cmp @0 zerop) @0 (negate @0))
+ (if (!HONOR_SIGNED_ZEROS (type)
+ && !TYPE_UNSIGNED (type))
+ (if (ANY_INTEGRAL_TYPE_P (type)
+ && !TYPE_OVERFLOW_WRAPS (type))
+ (with {
+ tree utype = unsigned_type_for (type);
+ }
+ (convert (negate (absu:utype @0))))
+ (negate (abs @0)))))
+ )
+)
+
+/* -(type)!A -> (type)A - 1. */
+(simplify
+ (negate (convert?:s (logical_inverted_value:s @0)))
+ (if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (type) != BOOLEAN_TYPE
+ && TYPE_PRECISION (type) > 1
+ && TREE_CODE (@0) == SSA_NAME
+ && ssa_name_has_boolean_range (@0))
+ (plus (convert:type @0) { build_all_ones_cst (type); })))
+
+/* A + (B vcmp C ? 1 : 0) -> A - (B vcmp C ? -1 : 0), since vector comparisons
+ return all -1 or all 0 results. */
+/* ??? We could instead convert all instances of the vec_cond to negate,
+ but that isn't necessarily a win on its own. */
+(simplify
+ (plus:c @3 (view_convert? (vec_cond:s @0 integer_each_onep@1 integer_zerop@2)))
+ (if (VECTOR_TYPE_P (type)
+ && known_eq (TYPE_VECTOR_SUBPARTS (type),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (@1)))
+ && (TYPE_MODE (TREE_TYPE (type))
+ == TYPE_MODE (TREE_TYPE (TREE_TYPE (@1)))))
+ (minus @3 (view_convert (vec_cond @0 (negate @1) @2)))))
+
+/* ... likewise A - (B vcmp C ? 1 : 0) -> A + (B vcmp C ? -1 : 0). */
+(simplify
+ (minus @3 (view_convert? (vec_cond:s @0 integer_each_onep@1 integer_zerop@2)))
+ (if (VECTOR_TYPE_P (type)
+ && known_eq (TYPE_VECTOR_SUBPARTS (type),
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (@1)))
+ && (TYPE_MODE (TREE_TYPE (type))
+ == TYPE_MODE (TREE_TYPE (TREE_TYPE (@1)))))
+ (plus @3 (view_convert (vec_cond @0 (negate @1) @2)))))
+
+
+/* Simplifications of comparisons. */
+
+/* See if we can reduce the magnitude of a constant involved in a
+ comparison by changing the comparison code. This is a canonicalization
+ formerly done by maybe_canonicalize_comparison_1. */
+(for cmp (le gt)
+ acmp (lt ge)
+ (simplify
+ (cmp @0 uniform_integer_cst_p@1)
+ (with { tree cst = uniform_integer_cst_p (@1); }
+ (if (tree_int_cst_sgn (cst) == -1)
+ (acmp @0 { build_uniform_cst (TREE_TYPE (@1),
+ wide_int_to_tree (TREE_TYPE (cst),
+ wi::to_wide (cst)
+ + 1)); })))))
+(for cmp (ge lt)
+ acmp (gt le)
+ (simplify
+ (cmp @0 uniform_integer_cst_p@1)
+ (with { tree cst = uniform_integer_cst_p (@1); }
+ (if (tree_int_cst_sgn (cst) == 1)
+ (acmp @0 { build_uniform_cst (TREE_TYPE (@1),
+ wide_int_to_tree (TREE_TYPE (cst),
+ wi::to_wide (cst) - 1)); })))))
+
+/* We can simplify a logical negation of a comparison to the
+ inverted comparison. As we cannot compute an expression
+ operator using invert_tree_comparison we have to simulate
+ that with expression code iteration. */
+(for cmp (tcc_comparison)
+ icmp (inverted_tcc_comparison)
+ ncmp (inverted_tcc_comparison_with_nans)
+ /* Ideally we'd like to combine the following two patterns
+ and handle some more cases by using
+ (logical_inverted_value (cmp @0 @1))
+ here but for that genmatch would need to "inline" that.
+ For now implement what forward_propagate_comparison did. */
+ (simplify
+ (bit_not (cmp @0 @1))
+ (if (VECTOR_TYPE_P (type)
+ || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1))
+ /* Comparison inversion may be impossible for trapping math,
+ invert_tree_comparison will tell us. But we can't use
+ a computed operator in the replacement tree thus we have
+ to play the trick below. */
+ (with { enum tree_code ic = invert_tree_comparison
+ (cmp, HONOR_NANS (@0)); }
+ (if (ic == icmp)
+ (icmp @0 @1)
+ (if (ic == ncmp)
+ (ncmp @0 @1))))))
+ (simplify
+ (bit_xor (cmp @0 @1) integer_truep)
+ (with { enum tree_code ic = invert_tree_comparison
+ (cmp, HONOR_NANS (@0)); }
+ (if (ic == icmp)
+ (icmp @0 @1)
+ (if (ic == ncmp)
+ (ncmp @0 @1))))))
+
+/* Transform comparisons of the form X - Y CMP 0 to X CMP Y.
+ ??? The transformation is valid for the other operators if overflow
+ is undefined for the type, but performing it here badly interacts
+ with the transformation in fold_cond_expr_with_comparison which
+ attempts to synthetize ABS_EXPR. */
+(for cmp (eq ne)
+ (for sub (minus pointer_diff)
+ (simplify
+ (cmp (sub@2 @0 @1) integer_zerop)
+ (if (single_use (@2))
+ (cmp @0 @1)))))
+
+/* Simplify (x < 0) ^ (y < 0) to (x ^ y) < 0 and
+ (x >= 0) ^ (y >= 0) to (x ^ y) < 0. */
+(for cmp (lt ge)
+ (simplify
+ (bit_xor (cmp:s @0 integer_zerop) (cmp:s @1 integer_zerop))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (lt (bit_xor @0 @1) { build_zero_cst (TREE_TYPE (@0)); }))))
+/* Simplify (x < 0) ^ (y >= 0) to (x ^ y) >= 0 and
+ (x >= 0) ^ (y < 0) to (x ^ y) >= 0. */
+(simplify
+ (bit_xor:c (lt:s @0 integer_zerop) (ge:s @1 integer_zerop))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (ge (bit_xor @0 @1) { build_zero_cst (TREE_TYPE (@0)); })))
+
+/* Transform comparisons of the form X * C1 CMP 0 to X CMP 0 in the
+ signed arithmetic case. That form is created by the compiler
+ often enough for folding it to be of value. One example is in
+ computing loop trip counts after Operator Strength Reduction. */
+(for cmp (simple_comparison)
+ scmp (swapped_simple_comparison)
+ (simplify
+ (cmp (mult@3 @0 INTEGER_CST@1) integer_zerop@2)
+ /* Handle unfolded multiplication by zero. */
+ (if (integer_zerop (@1))
+ (cmp @1 @2)
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && single_use (@3))
+ /* If @1 is negative we swap the sense of the comparison. */
+ (if (tree_int_cst_sgn (@1) < 0)
+ (scmp @0 @2)
+ (cmp @0 @2))))))
+
+/* For integral types with undefined overflow fold
+ x * C1 == C2 into x == C2 / C1 or false.
+ If overflow wraps and C1 is odd, simplify to x == C2 / C1 in the ring
+ Z / 2^n Z. */
+(for cmp (eq ne)
+ (simplify
+ (cmp (mult @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && wi::to_wide (@1) != 0)
+ (with { widest_int quot; }
+ (if (wi::multiple_of_p (wi::to_widest (@2), wi::to_widest (@1),
+ TYPE_SIGN (TREE_TYPE (@0)), &quot))
+ (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), quot); })
+ { constant_boolean_node (cmp == NE_EXPR, type); }))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))
+ && (wi::bit_and (wi::to_wide (@1), 1) == 1))
+ (cmp @0
+ {
+ tree itype = TREE_TYPE (@0);
+ int p = TYPE_PRECISION (itype);
+ wide_int m = wi::one (p + 1) << p;
+ wide_int a = wide_int::from (wi::to_wide (@1), p + 1, UNSIGNED);
+ wide_int i = wide_int::from (wi::mod_inv (a, m),
+ p, TYPE_SIGN (itype));
+ wide_int_to_tree (itype, wi::mul (i, wi::to_wide (@2)));
+ })))))
+
+/* Simplify comparison of something with itself. For IEEE
+ floating-point, we can only do some of these simplifications. */
+(for cmp (eq ge le)
+ (simplify
+ (cmp @0 @0)
+ (if (! FLOAT_TYPE_P (TREE_TYPE (@0))
+ || ! tree_expr_maybe_nan_p (@0))
+ { constant_boolean_node (true, type); }
+ (if (cmp != EQ_EXPR
+ /* With -ftrapping-math conversion to EQ loses an exception. */
+ && (! FLOAT_TYPE_P (TREE_TYPE (@0))
+ || ! flag_trapping_math))
+ (eq @0 @0)))))
+(for cmp (ne gt lt)
+ (simplify
+ (cmp @0 @0)
+ (if (cmp != NE_EXPR
+ || ! FLOAT_TYPE_P (TREE_TYPE (@0))
+ || ! tree_expr_maybe_nan_p (@0))
+ { constant_boolean_node (false, type); })))
+(for cmp (unle unge uneq)
+ (simplify
+ (cmp @0 @0)
+ { constant_boolean_node (true, type); }))
+(for cmp (unlt ungt)
+ (simplify
+ (cmp @0 @0)
+ (unordered @0 @0)))
+(simplify
+ (ltgt @0 @0)
+ (if (!flag_trapping_math || !tree_expr_maybe_nan_p (@0))
+ { constant_boolean_node (false, type); }))
+
+/* x == ~x -> false */
+/* x != ~x -> true */
+(for cmp (eq ne)
+ (simplify
+ (cmp:c @0 (bit_not @0))
+ { constant_boolean_node (cmp == NE_EXPR, type); }))
+
+/* Fold ~X op ~Y as Y op X. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (bit_not@2 @0) (bit_not@3 @1))
+ (if (single_use (@2) && single_use (@3))
+ (cmp @1 @0))))
+
+/* Fold ~X op C as X op' ~C, where op' is the swapped comparison. */
+(for cmp (simple_comparison)
+ scmp (swapped_simple_comparison)
+ (simplify
+ (cmp (bit_not@2 @0) CONSTANT_CLASS_P@1)
+ (if (single_use (@2)
+ && (TREE_CODE (@1) == INTEGER_CST || TREE_CODE (@1) == VECTOR_CST))
+ (scmp @0 (bit_not @1)))))
+
+(for cmp (simple_comparison)
+ /* Fold (double)float1 CMP (double)float2 into float1 CMP float2. */
+ (simplify
+ (cmp (convert@2 @0) (convert? @1))
+ (if (FLOAT_TYPE_P (TREE_TYPE (@0))
+ && (DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@2))
+ == DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@0)))
+ && (DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@2))
+ == DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1))))
+ (with
+ {
+ tree type1 = TREE_TYPE (@1);
+ if (TREE_CODE (@1) == REAL_CST && !DECIMAL_FLOAT_TYPE_P (type1))
+ {
+ REAL_VALUE_TYPE orig = TREE_REAL_CST (@1);
+ if (TYPE_PRECISION (type1) > TYPE_PRECISION (float_type_node)
+ && exact_real_truncate (TYPE_MODE (float_type_node), &orig))
+ type1 = float_type_node;
+ if (TYPE_PRECISION (type1) > TYPE_PRECISION (double_type_node)
+ && exact_real_truncate (TYPE_MODE (double_type_node), &orig))
+ type1 = double_type_node;
+ }
+ tree newtype
+ = (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type1)
+ ? TREE_TYPE (@0) : type1);
+ }
+ (if (TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (newtype))
+ (cmp (convert:newtype @0) (convert:newtype @1))))))
+
+ (simplify
+ (cmp @0 REAL_CST@1)
+ /* IEEE doesn't distinguish +0 and -0 in comparisons. */
+ (switch
+ /* a CMP (-0) -> a CMP 0 */
+ (if (REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@1)))
+ (cmp @0 { build_real (TREE_TYPE (@1), dconst0); }))
+ /* (-0) CMP b -> 0 CMP b. */
+ (if (TREE_CODE (@0) == REAL_CST
+ && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (@0)))
+ (cmp { build_real (TREE_TYPE (@0), dconst0); } @1))
+ /* x != NaN is always true, other ops are always false. */
+ (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
+ && !tree_expr_signaling_nan_p (@1)
+ && !tree_expr_maybe_signaling_nan_p (@0))
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+ /* NaN != y is always true, other ops are always false. */
+ (if (TREE_CODE (@0) == REAL_CST
+ && REAL_VALUE_ISNAN (TREE_REAL_CST (@0))
+ && !tree_expr_signaling_nan_p (@0)
+ && !tree_expr_signaling_nan_p (@1))
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+ /* Fold comparisons against infinity. */
+ (if (REAL_VALUE_ISINF (TREE_REAL_CST (@1))
+ && MODE_HAS_INFINITIES (TYPE_MODE (TREE_TYPE (@1))))
+ (with
+ {
+ REAL_VALUE_TYPE max;
+ enum tree_code code = cmp;
+ bool neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1));
+ if (neg)
+ code = swap_tree_comparison (code);
+ }
+ (switch
+ /* x > +Inf is always false, if we ignore NaNs or exceptions. */
+ (if (code == GT_EXPR
+ && !(HONOR_NANS (@0) && flag_trapping_math))
+ { constant_boolean_node (false, type); })
+ (if (code == LE_EXPR)
+ /* x <= +Inf is always true, if we don't care about NaNs. */
+ (if (! HONOR_NANS (@0))
+ { constant_boolean_node (true, type); }
+ /* x <= +Inf is the same as x == x, i.e. !isnan(x), but this loses
+ an "invalid" exception. */
+ (if (!flag_trapping_math)
+ (eq @0 @0))))
+ /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX, but
+ for == this introduces an exception for x a NaN. */
+ (if ((code == EQ_EXPR && !(HONOR_NANS (@0) && flag_trapping_math))
+ || code == GE_EXPR)
+ (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
+ (if (neg)
+ (lt @0 { build_real (TREE_TYPE (@0), max); })
+ (gt @0 { build_real (TREE_TYPE (@0), max); }))))
+ /* x < +Inf is always equal to x <= DBL_MAX. */
+ (if (code == LT_EXPR)
+ (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
+ (if (neg)
+ (ge @0 { build_real (TREE_TYPE (@0), max); })
+ (le @0 { build_real (TREE_TYPE (@0), max); }))))
+ /* x != +Inf is always equal to !(x > DBL_MAX), but this introduces
+ an exception for x a NaN so use an unordered comparison. */
+ (if (code == NE_EXPR)
+ (with { real_maxval (&max, neg, TYPE_MODE (TREE_TYPE (@0))); }
+ (if (! HONOR_NANS (@0))
+ (if (neg)
+ (ge @0 { build_real (TREE_TYPE (@0), max); })
+ (le @0 { build_real (TREE_TYPE (@0), max); }))
+ (if (neg)
+ (unge @0 { build_real (TREE_TYPE (@0), max); })
+ (unle @0 { build_real (TREE_TYPE (@0), max); }))))))))))
+
+ /* If this is a comparison of a real constant with a PLUS_EXPR
+ or a MINUS_EXPR of a real constant, we can convert it into a
+ comparison with a revised real constant as long as no overflow
+ occurs when unsafe_math_optimizations are enabled. */
+ (if (flag_unsafe_math_optimizations)
+ (for op (plus minus)
+ (simplify
+ (cmp (op @0 REAL_CST@1) REAL_CST@2)
+ (with
+ {
+ tree tem = const_binop (op == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR,
+ TREE_TYPE (@1), @2, @1);
+ }
+ (if (tem && !TREE_OVERFLOW (tem))
+ (cmp @0 { tem; }))))))
+
+ /* Likewise, we can simplify a comparison of a real constant with
+ a MINUS_EXPR whose first operand is also a real constant, i.e.
+ (c1 - x) < c2 becomes x > c1-c2. Reordering is allowed on
+ floating-point types only if -fassociative-math is set. */
+ (if (flag_associative_math)
+ (simplify
+ (cmp (minus REAL_CST@0 @1) REAL_CST@2)
+ (with { tree tem = const_binop (MINUS_EXPR, TREE_TYPE (@1), @0, @2); }
+ (if (tem && !TREE_OVERFLOW (tem))
+ (cmp { tem; } @1)))))
+
+ /* Fold comparisons against built-in math functions. */
+ (if (flag_unsafe_math_optimizations && ! flag_errno_math)
+ (for sq (SQRT)
+ (simplify
+ (cmp (sq @0) REAL_CST@1)
+ (switch
+ (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+ (switch
+ /* sqrt(x) < y is always false, if y is negative. */
+ (if (cmp == EQ_EXPR || cmp == LT_EXPR || cmp == LE_EXPR)
+ { constant_boolean_node (false, type); })
+ /* sqrt(x) > y is always true, if y is negative and we
+ don't care about NaNs, i.e. negative values of x. */
+ (if (cmp == NE_EXPR || !HONOR_NANS (@0))
+ { constant_boolean_node (true, type); })
+ /* sqrt(x) > y is the same as x >= 0, if y is negative. */
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })))
+ (if (real_equal (TREE_REAL_CST_PTR (@1), &dconst0))
+ (switch
+ /* sqrt(x) < 0 is always false. */
+ (if (cmp == LT_EXPR)
+ { constant_boolean_node (false, type); })
+ /* sqrt(x) >= 0 is always true if we don't care about NaNs. */
+ (if (cmp == GE_EXPR && !HONOR_NANS (@0))
+ { constant_boolean_node (true, type); })
+ /* sqrt(x) <= 0 -> x == 0. */
+ (if (cmp == LE_EXPR)
+ (eq @0 @1))
+ /* Otherwise sqrt(x) cmp 0 -> x cmp 0. Here cmp can be >=, >,
+ == or !=. In the last case:
+
+ (sqrt(x) != 0) == (NaN != 0) == true == (x != 0)
+
+ if x is negative or NaN. Due to -funsafe-math-optimizations,
+ the results for other x follow from natural arithmetic. */
+ (cmp @0 @1)))
+ (if ((cmp == LT_EXPR
+ || cmp == LE_EXPR
+ || cmp == GT_EXPR
+ || cmp == GE_EXPR)
+ && !REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
+ /* Give up for -frounding-math. */
+ && !HONOR_SIGN_DEPENDENT_ROUNDING (TREE_TYPE (@0)))
+ (with
+ {
+ REAL_VALUE_TYPE c2;
+ enum tree_code ncmp = cmp;
+ const real_format *fmt
+ = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@0)));
+ real_arithmetic (&c2, MULT_EXPR,
+ &TREE_REAL_CST (@1), &TREE_REAL_CST (@1));
+ real_convert (&c2, fmt, &c2);
+ /* See PR91734: if c2 is inexact and sqrt(c2) < c (or sqrt(c2) >= c),
+ then change LT_EXPR into LE_EXPR or GE_EXPR into GT_EXPR. */
+ if (!REAL_VALUE_ISINF (c2))
+ {
+ tree c3 = fold_const_call (CFN_SQRT, TREE_TYPE (@0),
+ build_real (TREE_TYPE (@0), c2));
+ if (c3 == NULL_TREE || TREE_CODE (c3) != REAL_CST)
+ ncmp = ERROR_MARK;
+ else if ((cmp == LT_EXPR || cmp == GE_EXPR)
+ && real_less (&TREE_REAL_CST (c3), &TREE_REAL_CST (@1)))
+ ncmp = cmp == LT_EXPR ? LE_EXPR : GT_EXPR;
+ else if ((cmp == LE_EXPR || cmp == GT_EXPR)
+ && real_less (&TREE_REAL_CST (@1), &TREE_REAL_CST (c3)))
+ ncmp = cmp == LE_EXPR ? LT_EXPR : GE_EXPR;
+ else
+ {
+ /* With rounding to even, sqrt of up to 3 different values
+ gives the same normal result, so in some cases c2 needs
+ to be adjusted. */
+ REAL_VALUE_TYPE c2alt, tow;
+ if (cmp == LT_EXPR || cmp == GE_EXPR)
+ tow = dconst0;
+ else
+ real_inf (&tow);
+ real_nextafter (&c2alt, fmt, &c2, &tow);
+ real_convert (&c2alt, fmt, &c2alt);
+ if (REAL_VALUE_ISINF (c2alt))
+ ncmp = ERROR_MARK;
+ else
+ {
+ c3 = fold_const_call (CFN_SQRT, TREE_TYPE (@0),
+ build_real (TREE_TYPE (@0), c2alt));
+ if (c3 == NULL_TREE || TREE_CODE (c3) != REAL_CST)
+ ncmp = ERROR_MARK;
+ else if (real_equal (&TREE_REAL_CST (c3),
+ &TREE_REAL_CST (@1)))
+ c2 = c2alt;
+ }
+ }
+ }
+ }
+ (if (cmp == GT_EXPR || cmp == GE_EXPR)
+ (if (REAL_VALUE_ISINF (c2))
+ /* sqrt(x) > y is x == +Inf, when y is very large. */
+ (if (HONOR_INFINITIES (@0))
+ (eq @0 { build_real (TREE_TYPE (@0), c2); })
+ { constant_boolean_node (false, type); })
+ /* sqrt(x) > c is the same as x > c*c. */
+ (if (ncmp != ERROR_MARK)
+ (if (ncmp == GE_EXPR)
+ (ge @0 { build_real (TREE_TYPE (@0), c2); })
+ (gt @0 { build_real (TREE_TYPE (@0), c2); }))))
+ /* else if (cmp == LT_EXPR || cmp == LE_EXPR) */
+ (if (REAL_VALUE_ISINF (c2))
+ (switch
+ /* sqrt(x) < y is always true, when y is a very large
+ value and we don't care about NaNs or Infinities. */
+ (if (! HONOR_NANS (@0) && ! HONOR_INFINITIES (@0))
+ { constant_boolean_node (true, type); })
+ /* sqrt(x) < y is x != +Inf when y is very large and we
+ don't care about NaNs. */
+ (if (! HONOR_NANS (@0))
+ (ne @0 { build_real (TREE_TYPE (@0), c2); }))
+ /* sqrt(x) < y is x >= 0 when y is very large and we
+ don't care about Infinities. */
+ (if (! HONOR_INFINITIES (@0))
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); }))
+ /* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
+ (if (GENERIC)
+ (truth_andif
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+ (ne @0 { build_real (TREE_TYPE (@0), c2); }))))
+ /* sqrt(x) < c is the same as x < c*c, if we ignore NaNs. */
+ (if (ncmp != ERROR_MARK && ! HONOR_NANS (@0))
+ (if (ncmp == LT_EXPR)
+ (lt @0 { build_real (TREE_TYPE (@0), c2); })
+ (le @0 { build_real (TREE_TYPE (@0), c2); }))
+ /* sqrt(x) < c is the same as x >= 0 && x < c*c. */
+ (if (ncmp != ERROR_MARK && GENERIC)
+ (if (ncmp == LT_EXPR)
+ (truth_andif
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+ (lt @0 { build_real (TREE_TYPE (@0), c2); }))
+ (truth_andif
+ (ge @0 { build_real (TREE_TYPE (@0), dconst0); })
+ (le @0 { build_real (TREE_TYPE (@0), c2); })))))))))))
+ /* Transform sqrt(x) cmp sqrt(y) -> x cmp y. */
+ (simplify
+ (cmp (sq @0) (sq @1))
+ (if (! HONOR_NANS (@0))
+ (cmp @0 @1))))))
+
+/* Optimize various special cases of (FTYPE) N CMP (FTYPE) M. */
+(for cmp (lt le eq ne ge gt unordered ordered unlt unle ungt unge uneq ltgt)
+ icmp (lt le eq ne ge gt unordered ordered lt le gt ge eq ne)
+ (simplify
+ (cmp (float@0 @1) (float @2))
+ (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@0))
+ && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@0)))
+ (with
+ {
+ format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@0))));
+ tree type1 = TREE_TYPE (@1);
+ bool type1_signed_p = TYPE_SIGN (type1) == SIGNED;
+ tree type2 = TREE_TYPE (@2);
+ bool type2_signed_p = TYPE_SIGN (type2) == SIGNED;
+ }
+ (if (fmt.can_represent_integral_type_p (type1)
+ && fmt.can_represent_integral_type_p (type2))
+ (if (cmp == ORDERED_EXPR || cmp == UNORDERED_EXPR)
+ { constant_boolean_node (cmp == ORDERED_EXPR, type); }
+ (if (TYPE_PRECISION (type1) > TYPE_PRECISION (type2)
+ && type1_signed_p >= type2_signed_p)
+ (icmp @1 (convert @2))
+ (if (TYPE_PRECISION (type1) < TYPE_PRECISION (type2)
+ && type1_signed_p <= type2_signed_p)
+ (icmp (convert:type2 @1) @2)
+ (if (TYPE_PRECISION (type1) == TYPE_PRECISION (type2)
+ && type1_signed_p == type2_signed_p)
+ (icmp @1 @2))))))))))
+
+/* Optimize various special cases of (FTYPE) N CMP CST. */
+(for cmp (lt le eq ne ge gt)
+ icmp (le le eq ne ge ge)
+ (simplify
+ (cmp (float @0) REAL_CST@1)
+ (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@1))
+ && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1)))
+ (with
+ {
+ tree itype = TREE_TYPE (@0);
+ format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1))));
+ const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1);
+ /* Be careful to preserve any potential exceptions due to
+ NaNs. qNaNs are ok in == or != context.
+ TODO: relax under -fno-trapping-math or
+ -fno-signaling-nans. */
+ bool exception_p
+ = real_isnan (cst) && (cst->signalling
+ || (cmp != EQ_EXPR && cmp != NE_EXPR));
+ }
+ /* TODO: allow non-fitting itype and SNaNs when
+ -fno-trapping-math. */
+ (if (fmt.can_represent_integral_type_p (itype) && ! exception_p)
+ (with
+ {
+ signop isign = TYPE_SIGN (itype);
+ REAL_VALUE_TYPE imin, imax;
+ real_from_integer (&imin, fmt, wi::min_value (itype), isign);
+ real_from_integer (&imax, fmt, wi::max_value (itype), isign);
+
+ REAL_VALUE_TYPE icst;
+ if (cmp == GT_EXPR || cmp == GE_EXPR)
+ real_ceil (&icst, fmt, cst);
+ else if (cmp == LT_EXPR || cmp == LE_EXPR)
+ real_floor (&icst, fmt, cst);
+ else
+ real_trunc (&icst, fmt, cst);
+
+ bool cst_int_p = !real_isnan (cst) && real_identical (&icst, cst);
+
+ bool overflow_p = false;
+ wide_int icst_val
+ = real_to_integer (&icst, &overflow_p, TYPE_PRECISION (itype));
+ }
+ (switch
+ /* Optimize cases when CST is outside of ITYPE's range. */
+ (if (real_compare (LT_EXPR, cst, &imin))
+ { constant_boolean_node (cmp == GT_EXPR || cmp == GE_EXPR || cmp == NE_EXPR,
+ type); })
+ (if (real_compare (GT_EXPR, cst, &imax))
+ { constant_boolean_node (cmp == LT_EXPR || cmp == LE_EXPR || cmp == NE_EXPR,
+ type); })
+ /* Remove cast if CST is an integer representable by ITYPE. */
+ (if (cst_int_p)
+ (cmp @0 { gcc_assert (!overflow_p);
+ wide_int_to_tree (itype, icst_val); })
+ )
+ /* When CST is fractional, optimize
+ (FTYPE) N == CST -> 0
+ (FTYPE) N != CST -> 1. */
+ (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+ /* Otherwise replace with sensible integer constant. */
+ (with
+ {
+ gcc_checking_assert (!overflow_p);
+ }
+ (icmp @0 { wide_int_to_tree (itype, icst_val); })))))))))
+
+/* Fold A /[ex] B CMP C to A CMP B * C. */
+(for cmp (eq ne)
+ (simplify
+ (cmp (exact_div @0 @1) INTEGER_CST@2)
+ (if (!integer_zerop (@1))
+ (if (wi::to_wide (@2) == 0)
+ (cmp @0 @2)
+ (if (TREE_CODE (@1) == INTEGER_CST)
+ (with
+ {
+ wi::overflow_type ovf;
+ wide_int prod = wi::mul (wi::to_wide (@2), wi::to_wide (@1),
+ TYPE_SIGN (TREE_TYPE (@1)), &ovf);
+ }
+ (if (ovf)
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))))
+(for cmp (lt le gt ge)
+ (simplify
+ (cmp (exact_div @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (wi::gt_p (wi::to_wide (@1), 0, TYPE_SIGN (TREE_TYPE (@1))))
+ (with
+ {
+ wi::overflow_type ovf;
+ wide_int prod = wi::mul (wi::to_wide (@2), wi::to_wide (@1),
+ TYPE_SIGN (TREE_TYPE (@1)), &ovf);
+ }
+ (if (ovf)
+ { constant_boolean_node (wi::lt_p (wi::to_wide (@2), 0,
+ TYPE_SIGN (TREE_TYPE (@2)))
+ != (cmp == LT_EXPR || cmp == LE_EXPR), type); }
+ (cmp @0 { wide_int_to_tree (TREE_TYPE (@0), prod); }))))))
+
+/* Fold (size_t)(A /[ex] B) CMP C to (size_t)A CMP (size_t)B * C or A CMP' 0.
+
+ For small C (less than max/B), this is (size_t)A CMP (size_t)B * C.
+ For large C (more than min/B+2^size), this is also true, with the
+ multiplication computed modulo 2^size.
+ For intermediate C, this just tests the sign of A. */
+(for cmp (lt le gt ge)
+ cmp2 (ge ge lt lt)
+ (simplify
+ (cmp (convert (exact_div @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (tree_nop_conversion_p (TREE_TYPE (@0), TREE_TYPE (@2))
+ && TYPE_UNSIGNED (TREE_TYPE (@2)) && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && wi::gt_p (wi::to_wide (@1), 0, TYPE_SIGN (TREE_TYPE (@1))))
+ (with
+ {
+ tree utype = TREE_TYPE (@2);
+ wide_int denom = wi::to_wide (@1);
+ wide_int right = wi::to_wide (@2);
+ wide_int smax = wi::sdiv_trunc (wi::max_value (TREE_TYPE (@0)), denom);
+ wide_int smin = wi::sdiv_trunc (wi::min_value (TREE_TYPE (@0)), denom);
+ bool small = wi::leu_p (right, smax);
+ bool large = wi::geu_p (right, smin);
+ }
+ (if (small || large)
+ (cmp (convert:utype @0) (mult @2 (convert @1)))
+ (cmp2 @0 { build_zero_cst (TREE_TYPE (@0)); }))))))
+
+/* Unordered tests if either argument is a NaN. */
+(simplify
+ (bit_ior (unordered @0 @0) (unordered @1 @1))
+ (if (types_match (@0, @1))
+ (unordered @0 @1)))
+(simplify
+ (bit_and (ordered @0 @0) (ordered @1 @1))
+ (if (types_match (@0, @1))
+ (ordered @0 @1)))
+(simplify
+ (bit_ior:c (unordered @0 @0) (unordered:c@2 @0 @1))
+ @2)
+(simplify
+ (bit_and:c (ordered @0 @0) (ordered:c@2 @0 @1))
+ @2)
+
+/* Simple range test simplifications. */
+/* A < B || A >= B -> true. */
+(for test1 (lt le le le ne ge)
+ test2 (ge gt ge ne eq ne)
+ (simplify
+ (bit_ior:c (test1 @0 @1) (test2 @0 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
+ { constant_boolean_node (true, type); })))
+/* A < B && A >= B -> false. */
+(for test1 (lt lt lt le ne eq)
+ test2 (ge gt eq gt eq gt)
+ (simplify
+ (bit_and:c (test1 @0 @1) (test2 @0 @1))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
+ { constant_boolean_node (false, type); })))
+
+/* A & (2**N - 1) <= 2**K - 1 -> A & (2**N - 2**K) == 0
+ A & (2**N - 1) > 2**K - 1 -> A & (2**N - 2**K) != 0
+
+ Note that comparisons
+ A & (2**N - 1) < 2**K -> A & (2**N - 2**K) == 0
+ A & (2**N - 1) >= 2**K -> A & (2**N - 2**K) != 0
+ will be canonicalized to above so there's no need to
+ consider them here.
+ */
+
+(for cmp (le gt)
+ eqcmp (eq ne)
+ (simplify
+ (cmp (bit_and@0 @1 INTEGER_CST@2) INTEGER_CST@3)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+ (with
+ {
+ tree ty = TREE_TYPE (@0);
+ unsigned prec = TYPE_PRECISION (ty);
+ wide_int mask = wi::to_wide (@2, prec);
+ wide_int rhs = wi::to_wide (@3, prec);
+ signop sgn = TYPE_SIGN (ty);
+ }
+ (if ((mask & (mask + 1)) == 0 && wi::gt_p (rhs, 0, sgn)
+ && (rhs & (rhs + 1)) == 0 && wi::ge_p (mask, rhs, sgn))
+ (eqcmp (bit_and @1 { wide_int_to_tree (ty, mask - rhs); })
+ { build_zero_cst (ty); }))))))
+
+/* -A CMP -B -> B CMP A. */
+(for cmp (tcc_comparison)
+ scmp (swapped_tcc_comparison)
+ (simplify
+ (cmp (negate @0) (negate @1))
+ (if (FLOAT_TYPE_P (TREE_TYPE (@0))
+ || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+ (scmp @0 @1)))
+ (simplify
+ (cmp (negate @0) CONSTANT_CLASS_P@1)
+ (if (FLOAT_TYPE_P (TREE_TYPE (@0))
+ || (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))))
+ (with { tree tem = const_unop (NEGATE_EXPR, TREE_TYPE (@0), @1); }
+ (if (tem && !TREE_OVERFLOW (tem))
+ (scmp @0 { tem; }))))))
+
+/* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */
+(for op (eq ne)
+ (simplify
+ (op (abs @0) zerop@1)
+ (op @0 @1)))
+
+/* From fold_sign_changed_comparison and fold_widened_comparison.
+ FIXME: the lack of symmetry is disturbing. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (convert@0 @00) (convert?@1 @10))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ /* Disable this optimization if we're casting a function pointer
+ type on targets that require function pointer canonicalization. */
+ && !(targetm.have_canonicalize_funcptr_for_compare ()
+ && ((POINTER_TYPE_P (TREE_TYPE (@00))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@00))))
+ || (POINTER_TYPE_P (TREE_TYPE (@10))
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@10))))))
+ && single_use (@0))
+ (if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0))
+ && (TREE_CODE (@10) == INTEGER_CST
+ || @1 != @10)
+ && (TYPE_UNSIGNED (TREE_TYPE (@00)) == TYPE_UNSIGNED (TREE_TYPE (@0))
+ || cmp == NE_EXPR
+ || cmp == EQ_EXPR)
+ && !POINTER_TYPE_P (TREE_TYPE (@00)))
+ /* ??? The special-casing of INTEGER_CST conversion was in the original
+ code and here to avoid a spurious overflow flag on the resulting
+ constant which fold_convert produces. */
+ (if (TREE_CODE (@1) == INTEGER_CST)
+ (cmp @00 { force_fit_type (TREE_TYPE (@00), wi::to_widest (@1), 0,
+ TREE_OVERFLOW (@1)); })
+ (cmp @00 (convert @1)))
+
+ (if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@00)))
+ /* If possible, express the comparison in the shorter mode. */
+ (if ((cmp == EQ_EXPR || cmp == NE_EXPR
+ || TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (TREE_TYPE (@00))
+ || (!TYPE_UNSIGNED (TREE_TYPE (@0))
+ && TYPE_UNSIGNED (TREE_TYPE (@00))))
+ && (types_match (TREE_TYPE (@10), TREE_TYPE (@00))
+ || ((TYPE_PRECISION (TREE_TYPE (@00))
+ >= TYPE_PRECISION (TREE_TYPE (@10)))
+ && (TYPE_UNSIGNED (TREE_TYPE (@00))
+ == TYPE_UNSIGNED (TREE_TYPE (@10))))
+ || (TREE_CODE (@10) == INTEGER_CST
+ && INTEGRAL_TYPE_P (TREE_TYPE (@00))
+ && int_fits_type_p (@10, TREE_TYPE (@00)))))
+ (cmp @00 (convert @10))
+ (if (TREE_CODE (@10) == INTEGER_CST
+ && INTEGRAL_TYPE_P (TREE_TYPE (@00))
+ && !int_fits_type_p (@10, TREE_TYPE (@00)))
+ (with
+ {
+ tree min = lower_bound_in_type (TREE_TYPE (@10), TREE_TYPE (@00));
+ tree max = upper_bound_in_type (TREE_TYPE (@10), TREE_TYPE (@00));
+ bool above = integer_nonzerop (const_binop (LT_EXPR, type, max, @10));
+ bool below = integer_nonzerop (const_binop (LT_EXPR, type, @10, min));
+ }
+ (if (above || below)
+ (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+ { constant_boolean_node (cmp == EQ_EXPR ? false : true, type); }
+ (if (cmp == LT_EXPR || cmp == LE_EXPR)
+ { constant_boolean_node (above ? true : false, type); }
+ (if (cmp == GT_EXPR || cmp == GE_EXPR)
+ { constant_boolean_node (above ? false : true, type); }))))))))))))
+
+(for cmp (eq ne)
+ (simplify
+ /* SSA names are canonicalized to 2nd place. */
+ (cmp addr@0 SSA_NAME@1)
+ (with
+ { poly_int64 off; tree base; }
+ /* A local variable can never be pointed to by
+ the default SSA name of an incoming parameter. */
+ (if (SSA_NAME_IS_DEFAULT_DEF (@1)
+ && TREE_CODE (SSA_NAME_VAR (@1)) == PARM_DECL
+ && (base = get_base_address (TREE_OPERAND (@0, 0)))
+ && TREE_CODE (base) == VAR_DECL
+ && auto_var_in_fn_p (base, current_function_decl))
+ (if (cmp == NE_EXPR)
+ { constant_boolean_node (true, type); }
+ { constant_boolean_node (false, type); })
+ /* If the address is based on @1 decide using the offset. */
+ (if ((base = get_addr_base_and_unit_offset (TREE_OPERAND (@0, 0), &off))
+ && TREE_CODE (base) == MEM_REF
+ && TREE_OPERAND (base, 0) == @1)
+ (with { off += mem_ref_offset (base).force_shwi (); }
+ (if (known_ne (off, 0))
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (if (known_eq (off, 0))
+ { constant_boolean_node (cmp == EQ_EXPR, type); }))))))))
+
+/* Equality compare simplifications from fold_binary */
+(for cmp (eq ne)
+
+ /* If we have (A | C) == D where C & ~D != 0, convert this into 0.
+ Similarly for NE_EXPR. */
+ (simplify
+ (cmp (convert?@3 (bit_ior @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0))
+ && wi::bit_and_not (wi::to_wide (@1), wi::to_wide (@2)) != 0)
+ { constant_boolean_node (cmp == NE_EXPR, type); }))
+
+ /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y. */
+ (simplify
+ (cmp (bit_xor @0 @1) integer_zerop)
+ (cmp @0 @1))
+
+ /* (X ^ Y) == Y becomes X == 0.
+ Likewise (X ^ Y) == X becomes Y == 0. */
+ (simplify
+ (cmp:c (bit_xor:c @0 @1) @0)
+ (cmp @1 { build_zero_cst (TREE_TYPE (@1)); }))
+
+#if GIMPLE
+ /* (X & Y) == X becomes (X & ~Y) == 0. */
+ (simplify
+ (cmp:c (bit_and:c @0 @1) @0)
+ (cmp (bit_and @0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); }))
+ (simplify
+ (cmp:c (convert@3 (bit_and (convert@2 @0) INTEGER_CST@1)) (convert @0))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@3))
+ && TYPE_PRECISION (TREE_TYPE (@2)) == TYPE_PRECISION (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@3)) > TYPE_PRECISION (TREE_TYPE (@2))
+ && !wi::neg_p (wi::to_wide (@1)))
+ (cmp (bit_and @0 (convert (bit_not @1)))
+ { build_zero_cst (TREE_TYPE (@0)); })))
+
+ /* (X | Y) == Y becomes (X & ~Y) == 0. */
+ (simplify
+ (cmp:c (bit_ior:c @0 @1) @1)
+ (cmp (bit_and @0 (bit_not! @1)) { build_zero_cst (TREE_TYPE (@0)); }))
+#endif
+
+ /* (X ^ C1) op C2 can be rewritten as X op (C1 ^ C2). */
+ (simplify
+ (cmp (convert?@3 (bit_xor @0 INTEGER_CST@1)) INTEGER_CST@2)
+ (if (tree_nop_conversion_p (TREE_TYPE (@3), TREE_TYPE (@0)))
+ (cmp @0 (bit_xor @1 (convert @2)))))
+
+ (simplify
+ (cmp (convert? addr@0) integer_zerop)
+ (if (tree_single_nonzero_warnv_p (@0, NULL))
+ { constant_boolean_node (cmp == NE_EXPR, type); }))
+
+ /* (X & C) op (Y & C) into (X ^ Y) & C op 0. */
+ (simplify
+ (cmp (bit_and:cs @0 @2) (bit_and:cs @1 @2))
+ (cmp (bit_and (bit_xor @0 @1) @2) { build_zero_cst (TREE_TYPE (@2)); })))
+
+/* (X < 0) != (Y < 0) into (X ^ Y) < 0.
+ (X >= 0) != (Y >= 0) into (X ^ Y) < 0.
+ (X < 0) == (Y < 0) into (X ^ Y) >= 0.
+ (X >= 0) == (Y >= 0) into (X ^ Y) >= 0. */
+(for cmp (eq ne)
+ ncmp (ge lt)
+ (for sgncmp (ge lt)
+ (simplify
+ (cmp (sgncmp @0 integer_zerop@2) (sgncmp @1 integer_zerop))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && types_match (@0, @1))
+ (ncmp (bit_xor @0 @1) @2)))))
+/* (X < 0) == (Y >= 0) into (X ^ Y) < 0.
+ (X < 0) != (Y >= 0) into (X ^ Y) >= 0. */
+(for cmp (eq ne)
+ ncmp (lt ge)
+ (simplify
+ (cmp:c (lt @0 integer_zerop@2) (ge @1 integer_zerop))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && types_match (@0, @1))
+ (ncmp (bit_xor @0 @1) @2))))
+
+/* If we have (A & C) == C where C is a power of 2, convert this into
+ (A & C) != 0. Similarly for NE_EXPR. */
+(for cmp (eq ne)
+ icmp (ne eq)
+ (simplify
+ (cmp (bit_and@2 @0 integer_pow2p@1) @1)
+ (icmp @2 { build_zero_cst (TREE_TYPE (@0)); })))
+
+(for cmp (ge lt)
+/* x < 0 ? ~y : y into (x >> (prec-1)) ^ y. */
+/* x >= 0 ? ~y : y into ~((x >> (prec-1)) ^ y). */
+ (simplify
+ (cond (cmp @0 integer_zerop) (bit_not @1) @1)
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type))
+ (with
+ {
+ tree shifter = build_int_cst (integer_type_node, TYPE_PRECISION (type) - 1);
+ }
+ (if (cmp == LT_EXPR)
+ (bit_xor (convert (rshift @0 {shifter;})) @1)
+ (bit_not (bit_xor (convert (rshift @0 {shifter;})) @1))))))
+/* x < 0 ? y : ~y into ~((x >> (prec-1)) ^ y). */
+/* x >= 0 ? y : ~y into (x >> (prec-1)) ^ y. */
+ (simplify
+ (cond (cmp @0 integer_zerop) @1 (bit_not @1))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && !TYPE_UNSIGNED (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type))
+ (with
+ {
+ tree shifter = build_int_cst (integer_type_node, TYPE_PRECISION (type) - 1);
+ }
+ (if (cmp == GE_EXPR)
+ (bit_xor (convert (rshift @0 {shifter;})) @1)
+ (bit_not (bit_xor (convert (rshift @0 {shifter;})) @1)))))))
+
+/* If we have (A & C) != 0 ? D : 0 where C and D are powers of 2,
+ convert this into a shift followed by ANDing with D. */
+(simplify
+ (cond
+ (ne (bit_and @0 integer_pow2p@1) integer_zerop)
+ INTEGER_CST@2 integer_zerop)
+ (if (!POINTER_TYPE_P (type) && integer_pow2p (@2))
+ (with {
+ int shift = (wi::exact_log2 (wi::to_wide (@2))
+ - wi::exact_log2 (wi::to_wide (@1)));
+ }
+ (if (shift > 0)
+ (bit_and
+ (lshift (convert @0) { build_int_cst (integer_type_node, shift); }) @2)
+ (bit_and
+ (convert (rshift @0 { build_int_cst (integer_type_node, -shift); }))
+ @2)))))
+
+/* If we have (A & C) != 0 where C is the sign bit of A, convert
+ this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
+(for cmp (eq ne)
+ ncmp (ge lt)
+ (simplify
+ (cmp (bit_and (convert?@2 @0) integer_pow2p@1) integer_zerop)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && type_has_mode_precision_p (TREE_TYPE (@0))
+ && element_precision (@2) >= element_precision (@0)
+ && wi::only_sign_bit_p (wi::to_wide (@1), element_precision (@0)))
+ (with { tree stype = signed_type_for (TREE_TYPE (@0)); }
+ (ncmp (convert:stype @0) { build_zero_cst (stype); })))))
+
+/* If we have A < 0 ? C : 0 where C is a power of 2, convert
+ this into a right shift or sign extension followed by ANDing with C. */
+(simplify
+ (cond
+ (lt @0 integer_zerop)
+ INTEGER_CST@1 integer_zerop)
+ (if (integer_pow2p (@1)
+ && !TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (with {
+ int shift = element_precision (@0) - wi::exact_log2 (wi::to_wide (@1)) - 1;
+ }
+ (if (shift >= 0)
+ (bit_and
+ (convert (rshift @0 { build_int_cst (integer_type_node, shift); }))
+ @1)
+ /* Otherwise ctype must be wider than TREE_TYPE (@0) and pure
+ sign extension followed by AND with C will achieve the effect. */
+ (bit_and (convert @0) @1)))))
+
+/* When the addresses are not directly of decls compare base and offset.
+ This implements some remaining parts of fold_comparison address
+ comparisons but still no complete part of it. Still it is good
+ enough to make fold_stmt not regress when not dispatching to fold_binary. */
+(for cmp (simple_comparison)
+ (simplify
+ (cmp (convert1?@2 addr@0) (convert2? addr@1))
+ (with
+ {
+ poly_int64 off0, off1;
+ tree base0, base1;
+ int equal = address_compare (cmp, TREE_TYPE (@2), @0, @1, base0, base1,
+ off0, off1, GENERIC);
+ }
+ (if (equal == 1)
+ (switch
+ (if (cmp == EQ_EXPR && (known_eq (off0, off1) || known_ne (off0, off1)))
+ { constant_boolean_node (known_eq (off0, off1), type); })
+ (if (cmp == NE_EXPR && (known_eq (off0, off1) || known_ne (off0, off1)))
+ { constant_boolean_node (known_ne (off0, off1), type); })
+ (if (cmp == LT_EXPR && (known_lt (off0, off1) || known_ge (off0, off1)))
+ { constant_boolean_node (known_lt (off0, off1), type); })
+ (if (cmp == LE_EXPR && (known_le (off0, off1) || known_gt (off0, off1)))
+ { constant_boolean_node (known_le (off0, off1), type); })
+ (if (cmp == GE_EXPR && (known_ge (off0, off1) || known_lt (off0, off1)))
+ { constant_boolean_node (known_ge (off0, off1), type); })
+ (if (cmp == GT_EXPR && (known_gt (off0, off1) || known_le (off0, off1)))
+ { constant_boolean_node (known_gt (off0, off1), type); }))
+ (if (equal == 0)
+ (switch
+ (if (cmp == EQ_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (cmp == NE_EXPR)
+ { constant_boolean_node (true, type); })))))))
+
+/* Simplify pointer equality compares using PTA. */
+(for neeq (ne eq)
+ (simplify
+ (neeq @0 @1)
+ (if (POINTER_TYPE_P (TREE_TYPE (@0))
+ && ptrs_compare_unequal (@0, @1))
+ { constant_boolean_node (neeq != EQ_EXPR, type); })))
+
+/* PR70920: Transform (intptr_t)x eq/ne CST to x eq/ne (typeof x) CST.
+ and (typeof ptr_cst) x eq/ne ptr_cst to x eq/ne (typeof x) CST.
+ Disable the transform if either operand is pointer to function.
+ This broke pr22051-2.c for arm where function pointer
+ canonicalizaion is not wanted. */
+
+(for cmp (ne eq)
+ (simplify
+ (cmp (convert @0) INTEGER_CST@1)
+ (if (((POINTER_TYPE_P (TREE_TYPE (@0))
+ && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@0)))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ /* Don't perform this optimization in GENERIC if @0 has reference
+ type when sanitizing. See PR101210. */
+ && !(GENERIC
+ && TREE_CODE (TREE_TYPE (@0)) == REFERENCE_TYPE
+ && (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))))
+ || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && POINTER_TYPE_P (TREE_TYPE (@1))
+ && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@1)))))
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
+ (cmp @0 (convert @1)))))
+
+/* Non-equality compare simplifications from fold_binary */
+(for cmp (lt gt le ge)
+ /* Comparisons with the highest or lowest possible integer of
+ the specified precision will have known values. */
+ (simplify
+ (cmp (convert?@2 @0) uniform_integer_cst_p@1)
+ (if ((INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ || POINTER_TYPE_P (TREE_TYPE (@1))
+ || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@1)))
+ && tree_nop_conversion_p (TREE_TYPE (@2), TREE_TYPE (@0)))
+ (with
+ {
+ tree cst = uniform_integer_cst_p (@1);
+ tree arg1_type = TREE_TYPE (cst);
+ unsigned int prec = TYPE_PRECISION (arg1_type);
+ wide_int max = wi::max_value (arg1_type);
+ wide_int signed_max = wi::max_value (prec, SIGNED);
+ wide_int min = wi::min_value (arg1_type);
+ }
+ (switch
+ (if (wi::to_wide (cst) == max)
+ (switch
+ (if (cmp == GT_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (cmp == GE_EXPR)
+ (eq @2 @1))
+ (if (cmp == LE_EXPR)
+ { constant_boolean_node (true, type); })
+ (if (cmp == LT_EXPR)
+ (ne @2 @1))))
+ (if (wi::to_wide (cst) == min)
+ (switch
+ (if (cmp == LT_EXPR)
+ { constant_boolean_node (false, type); })
+ (if (cmp == LE_EXPR)
+ (eq @2 @1))
+ (if (cmp == GE_EXPR)
+ { constant_boolean_node (true, type); })
+ (if (cmp == GT_EXPR)
+ (ne @2 @1))))
+ (if (wi::to_wide (cst) == max - 1)
+ (switch
+ (if (cmp == GT_EXPR)
+ (eq @2 { build_uniform_cst (TREE_TYPE (@1),
+ wide_int_to_tree (TREE_TYPE (cst),
+ wi::to_wide (cst)
+ + 1)); }))
+ (if (cmp == LE_EXPR)
+ (ne @2 { build_uniform_cst (TREE_TYPE (@1),
+ wide_int_to_tree (TREE_TYPE (cst),
+ wi::to_wide (cst)
+ + 1)); }))))
+ (if (wi::to_wide (cst) == min + 1)
+ (switch
+ (if (cmp == GE_EXPR)
+ (ne @2 { build_uniform_cst (TREE_TYPE (@1),
+ wide_int_to_tree (TREE_TYPE (cst),
+ wi::to_wide (cst)
+ - 1)); }))
+ (if (cmp == LT_EXPR)
+ (eq @2 { build_uniform_cst (TREE_TYPE (@1),
+ wide_int_to_tree (TREE_TYPE (cst),
+ wi::to_wide (cst)
+ - 1)); }))))
+ (if (wi::to_wide (cst) == signed_max
+ && TYPE_UNSIGNED (arg1_type)
+ /* We will flip the signedness of the comparison operator
+ associated with the mode of @1, so the sign bit is
+ specified by this mode. Check that @1 is the signed
+ max associated with this sign bit. */
+ && prec == GET_MODE_PRECISION (SCALAR_INT_TYPE_MODE (arg1_type))
+ /* signed_type does not work on pointer types. */
+ && INTEGRAL_TYPE_P (arg1_type))
+ /* The following case also applies to X < signed_max+1
+ and X >= signed_max+1 because previous transformations. */
+ (if (cmp == LE_EXPR || cmp == GT_EXPR)
+ (with { tree st = signed_type_for (TREE_TYPE (@1)); }
+ (switch
+ (if (cst == @1 && cmp == LE_EXPR)
+ (ge (convert:st @0) { build_zero_cst (st); }))
+ (if (cst == @1 && cmp == GT_EXPR)
+ (lt (convert:st @0) { build_zero_cst (st); }))
+ (if (cmp == LE_EXPR)
+ (ge (view_convert:st @0) { build_zero_cst (st); }))
+ (if (cmp == GT_EXPR)
+ (lt (view_convert:st @0) { build_zero_cst (st); })))))))))))
+
+(for cmp (unordered ordered unlt unle ungt unge uneq ltgt)
+ /* If the second operand is NaN, the result is constant. */
+ (simplify
+ (cmp @0 REAL_CST@1)
+ (if (REAL_VALUE_ISNAN (TREE_REAL_CST (@1))
+ && (cmp != LTGT_EXPR || ! flag_trapping_math))
+ { constant_boolean_node (cmp == ORDERED_EXPR || cmp == LTGT_EXPR
+ ? false : true, type); })))
+
+/* Fold UNORDERED if either operand must be NaN, or neither can be. */
+(simplify
+ (unordered @0 @1)
+ (switch
+ (if (tree_expr_nan_p (@0) || tree_expr_nan_p (@1))
+ { constant_boolean_node (true, type); })
+ (if (!tree_expr_maybe_nan_p (@0) && !tree_expr_maybe_nan_p (@1))
+ { constant_boolean_node (false, type); })))
+
+/* Fold ORDERED if either operand must be NaN, or neither can be. */
+(simplify
+ (ordered @0 @1)
+ (switch
+ (if (tree_expr_nan_p (@0) || tree_expr_nan_p (@1))
+ { constant_boolean_node (false, type); })
+ (if (!tree_expr_maybe_nan_p (@0) && !tree_expr_maybe_nan_p (@1))
+ { constant_boolean_node (true, type); })))
+
+/* bool_var != 0 becomes bool_var. */
+(simplify
+ (ne @0 integer_zerop)
+ (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE
+ && types_match (type, TREE_TYPE (@0)))
+ (non_lvalue @0)))
+/* bool_var == 1 becomes bool_var. */
+(simplify
+ (eq @0 integer_onep)
+ (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE
+ && types_match (type, TREE_TYPE (@0)))
+ (non_lvalue @0)))
+/* Do not handle
+ bool_var == 0 becomes !bool_var or
+ bool_var != 1 becomes !bool_var
+ here because that only is good in assignment context as long
+ as we require a tcc_comparison in GIMPLE_CONDs where we'd
+ replace if (x == 0) with tem = ~x; if (tem != 0) which is
+ clearly less optimal and which we'll transform again in forwprop. */
+
+/* Transform comparisons of the form (X & Y) CMP 0 to X CMP2 Z
+ where ~Y + 1 == pow2 and Z = ~Y. */
+(for cst (VECTOR_CST INTEGER_CST)
+ (for cmp (eq ne)
+ icmp (le gt)
+ (simplify
+ (cmp (bit_and:c@2 @0 cst@1) integer_zerop)
+ (with { tree csts = bitmask_inv_cst_vector_p (@1); }
+ (if (csts && (VECTOR_TYPE_P (TREE_TYPE (@1)) || single_use (@2)))
+ (if (TYPE_UNSIGNED (TREE_TYPE (@1)))
+ (icmp @0 { csts; })
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@1)); }
+ (icmp (view_convert:utype @0) { csts; }))))))))
+
+/* When one argument is a constant, overflow detection can be simplified.
+ Currently restricted to single use so as not to interfere too much with
+ ADD_OVERFLOW detection in tree-ssa-math-opts.cc.
+ CONVERT?(CONVERT?(A) + CST) CMP A -> A CMP' CST' */
+(for cmp (lt le ge gt)
+ out (gt gt le le)
+ (simplify
+ (cmp:c (convert?@3 (plus@2 (convert?@4 @0) INTEGER_CST@1)) @0)
+ (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@2))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@3))
+ && tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@0))
+ && wi::to_wide (@1) != 0
+ && single_use (@2))
+ (with {
+ unsigned int prec = TYPE_PRECISION (TREE_TYPE (@0));
+ signop sign = TYPE_SIGN (TREE_TYPE (@0));
+ }
+ (out @0 { wide_int_to_tree (TREE_TYPE (@0),
+ wi::max_value (prec, sign)
+ - wi::to_wide (@1)); })))))
+
+/* To detect overflow in unsigned A - B, A < B is simpler than A - B > A.
+ However, the detection logic for SUB_OVERFLOW in tree-ssa-math-opts.cc
+ expects the long form, so we restrict the transformation for now. */
+(for cmp (gt le)
+ (simplify
+ (cmp:c (minus@2 @0 @1) @0)
+ (if (single_use (@2)
+ && ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (cmp @1 @0))))
+
+/* Optimize A - B + -1 >= A into B >= A for unsigned comparisons. */
+(for cmp (ge lt)
+ (simplify
+ (cmp:c (plus (minus @0 @1) integer_minus_onep) @0)
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (cmp @1 @0))))
+
+/* Testing for overflow is unnecessary if we already know the result. */
+/* A - B > A */
+(for cmp (gt le)
+ out (ne eq)
+ (simplify
+ (cmp:c (realpart (IFN_SUB_OVERFLOW@2 @0 @1)) @0)
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
+/* A + B < A */
+(for cmp (lt ge)
+ out (ne eq)
+ (simplify
+ (cmp:c (realpart (IFN_ADD_OVERFLOW:c@2 @0 @1)) @0)
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0))
+ && types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
+ (out (imagpart @2) { build_zero_cst (TREE_TYPE (@0)); }))))
+
+/* For unsigned operands, -1 / B < A checks whether A * B would overflow.
+ Simplify it to __builtin_mul_overflow (A, B, <unused>). */
+(for cmp (lt ge)
+ out (ne eq)
+ (simplify
+ (cmp:c (trunc_div:s integer_all_onesp @1) @0)
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)) && !VECTOR_TYPE_P (TREE_TYPE (@0)))
+ (with { tree t = TREE_TYPE (@0), cpx = build_complex_type (t); }
+ (out (imagpart (IFN_MUL_OVERFLOW:cpx @0 @1)) { build_zero_cst (t); })))))
+
+/* Similarly, for unsigned operands, (((type) A * B) >> prec) != 0 where type
+ is at least twice as wide as type of A and B, simplify to
+ __builtin_mul_overflow (A, B, <unused>). */
+(for cmp (eq ne)
+ (simplify
+ (cmp (rshift (mult:s (convert@3 @0) (convert @1)) INTEGER_CST@2)
+ integer_zerop)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@3))
+ && TYPE_UNSIGNED (TREE_TYPE (@0))
+ && (TYPE_PRECISION (TREE_TYPE (@3))
+ >= 2 * TYPE_PRECISION (TREE_TYPE (@0)))
+ && tree_fits_uhwi_p (@2)
+ && tree_to_uhwi (@2) == TYPE_PRECISION (TREE_TYPE (@0))
+ && types_match (@0, @1)
+ && type_has_mode_precision_p (TREE_TYPE (@0))
+ && (optab_handler (umulv4_optab, TYPE_MODE (TREE_TYPE (@0)))
+ != CODE_FOR_nothing))
+ (with { tree t = TREE_TYPE (@0), cpx = build_complex_type (t); }
+ (cmp (imagpart (IFN_MUL_OVERFLOW:cpx @0 @1)) { build_zero_cst (t); })))))
+
+/* Demote operands of IFN_{ADD,SUB,MUL}_OVERFLOW. */
+(for ovf (IFN_ADD_OVERFLOW IFN_SUB_OVERFLOW IFN_MUL_OVERFLOW)
+ (simplify
+ (ovf (convert@2 @0) @1)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && (!TYPE_UNSIGNED (TREE_TYPE (@2)) || TYPE_UNSIGNED (TREE_TYPE (@0))))
+ (ovf @0 @1)))
+ (simplify
+ (ovf @1 (convert@2 @0))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && (!TYPE_UNSIGNED (TREE_TYPE (@2)) || TYPE_UNSIGNED (TREE_TYPE (@0))))
+ (ovf @1 @0))))
+
+/* Simplification of math builtins. These rules must all be optimizations
+ as well as IL simplifications. If there is a possibility that the new
+ form could be a pessimization, the rule should go in the canonicalization
+ section that follows this one.
+
+ Rules can generally go in this section if they satisfy one of
+ the following:
+
+ - the rule describes an identity
+
+ - the rule replaces calls with something as simple as addition or
+ multiplication
+
+ - the rule contains unary calls only and simplifies the surrounding
+ arithmetic. (The idea here is to exclude non-unary calls in which
+ one operand is constant and in which the call is known to be cheap
+ when the operand has that value.) */
+
+(if (flag_unsafe_math_optimizations)
+ /* Simplify sqrt(x) * sqrt(x) -> x. */
+ (simplify
+ (mult (SQRT_ALL@1 @0) @1)
+ (if (!tree_expr_maybe_signaling_nan_p (@0))
+ @0))
+
+ (for op (plus minus)
+ /* Simplify (A / C) +- (B / C) -> (A +- B) / C. */
+ (simplify
+ (op (rdiv @0 @1)
+ (rdiv @2 @1))
+ (rdiv (op @0 @2) @1)))
+
+ (for cmp (lt le gt ge)
+ neg_cmp (gt ge lt le)
+ /* Simplify (x * C1) cmp C2 -> x cmp (C2 / C1), where C1 != 0. */
+ (simplify
+ (cmp (mult @0 REAL_CST@1) REAL_CST@2)
+ (with
+ { tree tem = const_binop (RDIV_EXPR, type, @2, @1); }
+ (if (tem
+ && !(REAL_VALUE_ISINF (TREE_REAL_CST (tem))
+ || (real_zerop (tem) && !real_zerop (@1))))
+ (switch
+ (if (real_less (&dconst0, TREE_REAL_CST_PTR (@1)))
+ (cmp @0 { tem; }))
+ (if (real_less (TREE_REAL_CST_PTR (@1), &dconst0))
+ (neg_cmp @0 { tem; })))))))
+
+ /* Simplify sqrt(x) * sqrt(y) -> sqrt(x*y). */
+ (for root (SQRT CBRT)
+ (simplify
+ (mult (root:s @0) (root:s @1))
+ (root (mult @0 @1))))
+
+ /* Simplify expN(x) * expN(y) -> expN(x+y). */
+ (for exps (EXP EXP2 EXP10 POW10)
+ (simplify
+ (mult (exps:s @0) (exps:s @1))
+ (exps (plus @0 @1))))
+
+ /* Simplify a/root(b/c) into a*root(c/b). */
+ (for root (SQRT CBRT)
+ (simplify
+ (rdiv @0 (root:s (rdiv:s @1 @2)))
+ (mult @0 (root (rdiv @2 @1)))))
+
+ /* Simplify x/expN(y) into x*expN(-y). */
+ (for exps (EXP EXP2 EXP10 POW10)
+ (simplify
+ (rdiv @0 (exps:s @1))
+ (mult @0 (exps (negate @1)))))
+
+ (for logs (LOG LOG2 LOG10 LOG10)
+ exps (EXP EXP2 EXP10 POW10)
+ /* logN(expN(x)) -> x. */
+ (simplify
+ (logs (exps @0))
+ @0)
+ /* expN(logN(x)) -> x. */
+ (simplify
+ (exps (logs @0))
+ @0))
+
+ /* Optimize logN(func()) for various exponential functions. We
+ want to determine the value "x" and the power "exponent" in
+ order to transform logN(x**exponent) into exponent*logN(x). */
+ (for logs (LOG LOG LOG LOG2 LOG2 LOG2 LOG10 LOG10)
+ exps (EXP2 EXP10 POW10 EXP EXP10 POW10 EXP EXP2)
+ (simplify
+ (logs (exps @0))
+ (if (SCALAR_FLOAT_TYPE_P (type))
+ (with {
+ tree x;
+ switch (exps)
+ {
+ CASE_CFN_EXP:
+ /* Prepare to do logN(exp(exponent)) -> exponent*logN(e). */
+ x = build_real_truncate (type, dconst_e ());
+ break;
+ CASE_CFN_EXP2:
+ /* Prepare to do logN(exp2(exponent)) -> exponent*logN(2). */
+ x = build_real (type, dconst2);
+ break;
+ CASE_CFN_EXP10:
+ CASE_CFN_POW10:
+ /* Prepare to do logN(exp10(exponent)) -> exponent*logN(10). */
+ {
+ REAL_VALUE_TYPE dconst10;
+ real_from_integer (&dconst10, VOIDmode, 10, SIGNED);
+ x = build_real (type, dconst10);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ (mult (logs { x; }) @0)))))
+
+ (for logs (LOG LOG
+ LOG2 LOG2
+ LOG10 LOG10)
+ exps (SQRT CBRT)
+ (simplify
+ (logs (exps @0))
+ (if (SCALAR_FLOAT_TYPE_P (type))
+ (with {
+ tree x;
+ switch (exps)
+ {
+ CASE_CFN_SQRT:
+ /* Prepare to do logN(sqrt(x)) -> 0.5*logN(x). */
+ x = build_real (type, dconsthalf);
+ break;
+ CASE_CFN_CBRT:
+ /* Prepare to do logN(cbrt(x)) -> (1/3)*logN(x). */
+ x = build_real_truncate (type, dconst_third ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ (mult { x; } (logs @0))))))
+
+ /* logN(pow(x,exponent)) -> exponent*logN(x). */
+ (for logs (LOG LOG2 LOG10)
+ pows (POW)
+ (simplify
+ (logs (pows @0 @1))
+ (mult @1 (logs @0))))
+
+ /* pow(C,x) -> exp(log(C)*x) if C > 0,
+ or if C is a positive power of 2,
+ pow(C,x) -> exp2(log2(C)*x). */
+#if GIMPLE
+ (for pows (POW)
+ exps (EXP)
+ logs (LOG)
+ exp2s (EXP2)
+ log2s (LOG2)
+ (simplify
+ (pows REAL_CST@0 @1)
+ (if (real_compare (GT_EXPR, TREE_REAL_CST_PTR (@0), &dconst0)
+ && real_isfinite (TREE_REAL_CST_PTR (@0))
+ /* As libmvec doesn't have a vectorized exp2, defer optimizing
+ the use_exp2 case until after vectorization. It seems actually
+ beneficial for all constants to postpone this until later,
+ because exp(log(C)*x), while faster, will have worse precision
+ and if x folds into a constant too, that is unnecessary
+ pessimization. */
+ && canonicalize_math_after_vectorization_p ())
+ (with {
+ const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (@0);
+ bool use_exp2 = false;
+ if (targetm.libc_has_function (function_c99_misc, TREE_TYPE (@0))
+ && value->cl == rvc_normal)
+ {
+ REAL_VALUE_TYPE frac_rvt = *value;
+ SET_REAL_EXP (&frac_rvt, 1);
+ if (real_equal (&frac_rvt, &dconst1))
+ use_exp2 = true;
+ }
+ }
+ (if (!use_exp2)
+ (if (optimize_pow_to_exp (@0, @1))
+ (exps (mult (logs @0) @1)))
+ (exp2s (mult (log2s @0) @1)))))))
+#endif
+
+ /* pow(C,x)*expN(y) -> expN(logN(C)*x+y) if C > 0. */
+ (for pows (POW)
+ exps (EXP EXP2 EXP10 POW10)
+ logs (LOG LOG2 LOG10 LOG10)
+ (simplify
+ (mult:c (pows:s REAL_CST@0 @1) (exps:s @2))
+ (if (real_compare (GT_EXPR, TREE_REAL_CST_PTR (@0), &dconst0)
+ && real_isfinite (TREE_REAL_CST_PTR (@0)))
+ (exps (plus (mult (logs @0) @1) @2)))))
+
+ (for sqrts (SQRT)
+ cbrts (CBRT)
+ pows (POW)
+ exps (EXP EXP2 EXP10 POW10)
+ /* sqrt(expN(x)) -> expN(x*0.5). */
+ (simplify
+ (sqrts (exps @0))
+ (exps (mult @0 { build_real (type, dconsthalf); })))
+ /* cbrt(expN(x)) -> expN(x/3). */
+ (simplify
+ (cbrts (exps @0))
+ (exps (mult @0 { build_real_truncate (type, dconst_third ()); })))
+ /* pow(expN(x), y) -> expN(x*y). */
+ (simplify
+ (pows (exps @0) @1)
+ (exps (mult @0 @1))))
+
+ /* tan(atan(x)) -> x. */
+ (for tans (TAN)
+ atans (ATAN)
+ (simplify
+ (tans (atans @0))
+ @0)))
+
+ /* Simplify sin(atan(x)) -> x / sqrt(x*x + 1). */
+ (for sins (SIN)
+ atans (ATAN)
+ sqrts (SQRT)
+ copysigns (COPYSIGN)
+ (simplify
+ (sins (atans:s @0))
+ (with
+ {
+ REAL_VALUE_TYPE r_cst;
+ build_sinatan_real (&r_cst, type);
+ tree t_cst = build_real (type, r_cst);
+ tree t_one = build_one_cst (type);
+ }
+ (if (SCALAR_FLOAT_TYPE_P (type))
+ (cond (lt (abs @0) { t_cst; })
+ (rdiv @0 (sqrts (plus (mult @0 @0) { t_one; })))
+ (copysigns { t_one; } @0))))))
+
+/* Simplify cos(atan(x)) -> 1 / sqrt(x*x + 1). */
+ (for coss (COS)
+ atans (ATAN)
+ sqrts (SQRT)
+ copysigns (COPYSIGN)
+ (simplify
+ (coss (atans:s @0))
+ (with
+ {
+ REAL_VALUE_TYPE r_cst;
+ build_sinatan_real (&r_cst, type);
+ tree t_cst = build_real (type, r_cst);
+ tree t_one = build_one_cst (type);
+ tree t_zero = build_zero_cst (type);
+ }
+ (if (SCALAR_FLOAT_TYPE_P (type))
+ (cond (lt (abs @0) { t_cst; })
+ (rdiv { t_one; } (sqrts (plus (mult @0 @0) { t_one; })))
+ (copysigns { t_zero; } @0))))))
+
+ (if (!flag_errno_math)
+ /* Simplify sinh(atanh(x)) -> x / sqrt((1 - x)*(1 + x)). */
+ (for sinhs (SINH)
+ atanhs (ATANH)
+ sqrts (SQRT)
+ (simplify
+ (sinhs (atanhs:s @0))
+ (with { tree t_one = build_one_cst (type); }
+ (rdiv @0 (sqrts (mult (minus { t_one; } @0) (plus { t_one; } @0)))))))
+
+ /* Simplify cosh(atanh(x)) -> 1 / sqrt((1 - x)*(1 + x)) */
+ (for coshs (COSH)
+ atanhs (ATANH)
+ sqrts (SQRT)
+ (simplify
+ (coshs (atanhs:s @0))
+ (with { tree t_one = build_one_cst (type); }
+ (rdiv { t_one; } (sqrts (mult (minus { t_one; } @0) (plus { t_one; } @0))))))))
+
+/* cabs(x+0i) or cabs(0+xi) -> abs(x). */
+(simplify
+ (CABS (complex:C @0 real_zerop@1))
+ (abs @0))
+
+/* trunc(trunc(x)) -> trunc(x), etc. */
+(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL NEARBYINT_ALL RINT_ALL)
+ (simplify
+ (fns (fns @0))
+ (fns @0)))
+/* f(x) -> x if x is integer valued and f does nothing for such values. */
+(for fns (TRUNC_ALL FLOOR_ALL CEIL_ALL ROUND_ALL NEARBYINT_ALL RINT_ALL)
+ (simplify
+ (fns integer_valued_real_p@0)
+ @0))
+
+/* hypot(x,0) and hypot(0,x) -> abs(x). */
+(simplify
+ (HYPOT:c @0 real_zerop@1)
+ (abs @0))
+
+/* pow(1,x) -> 1. */
+(simplify
+ (POW real_onep@0 @1)
+ @0)
+
+(simplify
+ /* copysign(x,x) -> x. */
+ (COPYSIGN_ALL @0 @0)
+ @0)
+
+(simplify
+ /* copysign(x,-x) -> -x. */
+ (COPYSIGN_ALL @0 (negate@1 @0))
+ @1)
+
+(simplify
+ /* copysign(x,y) -> fabs(x) if y is nonnegative. */
+ (COPYSIGN_ALL @0 tree_expr_nonnegative_p@1)
+ (abs @0))
+
+(for scale (LDEXP SCALBN SCALBLN)
+ /* ldexp(0, x) -> 0. */
+ (simplify
+ (scale real_zerop@0 @1)
+ @0)
+ /* ldexp(x, 0) -> x. */
+ (simplify
+ (scale @0 integer_zerop@1)
+ @0)
+ /* ldexp(x, y) -> x if x is +-Inf or NaN. */
+ (simplify
+ (scale REAL_CST@0 @1)
+ (if (!real_isfinite (TREE_REAL_CST_PTR (@0)))
+ @0)))
+
+/* Canonicalization of sequences of math builtins. These rules represent
+ IL simplifications but are not necessarily optimizations.
+
+ The sincos pass is responsible for picking "optimal" implementations
+ of math builtins, which may be more complicated and can sometimes go
+ the other way, e.g. converting pow into a sequence of sqrts.
+ We only want to do these canonicalizations before the pass has run. */
+
+(if (flag_unsafe_math_optimizations && canonicalize_math_p ())
+ /* Simplify tan(x) * cos(x) -> sin(x). */
+ (simplify
+ (mult:c (TAN:s @0) (COS:s @0))
+ (SIN @0))
+
+ /* Simplify x * pow(x,c) -> pow(x,c+1). */
+ (simplify
+ (mult:c @0 (POW:s @0 REAL_CST@1))
+ (if (!TREE_OVERFLOW (@1))
+ (POW @0 (plus @1 { build_one_cst (type); }))))
+
+ /* Simplify sin(x) / cos(x) -> tan(x). */
+ (simplify
+ (rdiv (SIN:s @0) (COS:s @0))
+ (TAN @0))
+
+ /* Simplify sinh(x) / cosh(x) -> tanh(x). */
+ (simplify
+ (rdiv (SINH:s @0) (COSH:s @0))
+ (TANH @0))
+
+ /* Simplify tanh (x) / sinh (x) -> 1.0 / cosh (x). */
+ (simplify
+ (rdiv (TANH:s @0) (SINH:s @0))
+ (rdiv {build_one_cst (type);} (COSH @0)))
+
+ /* Simplify cos(x) / sin(x) -> 1 / tan(x). */
+ (simplify
+ (rdiv (COS:s @0) (SIN:s @0))
+ (rdiv { build_one_cst (type); } (TAN @0)))
+
+ /* Simplify sin(x) / tan(x) -> cos(x). */
+ (simplify
+ (rdiv (SIN:s @0) (TAN:s @0))
+ (if (! HONOR_NANS (@0)
+ && ! HONOR_INFINITIES (@0))
+ (COS @0)))
+
+ /* Simplify tan(x) / sin(x) -> 1.0 / cos(x). */
+ (simplify
+ (rdiv (TAN:s @0) (SIN:s @0))
+ (if (! HONOR_NANS (@0)
+ && ! HONOR_INFINITIES (@0))
+ (rdiv { build_one_cst (type); } (COS @0))))
+
+ /* Simplify pow(x,y) * pow(x,z) -> pow(x,y+z). */
+ (simplify
+ (mult (POW:s @0 @1) (POW:s @0 @2))
+ (POW @0 (plus @1 @2)))
+
+ /* Simplify pow(x,y) * pow(z,y) -> pow(x*z,y). */
+ (simplify
+ (mult (POW:s @0 @1) (POW:s @2 @1))
+ (POW (mult @0 @2) @1))
+
+ /* Simplify powi(x,y) * powi(z,y) -> powi(x*z,y). */
+ (simplify
+ (mult (POWI:s @0 @1) (POWI:s @2 @1))
+ (POWI (mult @0 @2) @1))
+
+ /* Simplify pow(x,c) / x -> pow(x,c-1). */
+ (simplify
+ (rdiv (POW:s @0 REAL_CST@1) @0)
+ (if (!TREE_OVERFLOW (@1))
+ (POW @0 (minus @1 { build_one_cst (type); }))))
+
+ /* Simplify x / pow (y,z) -> x * pow(y,-z). */
+ (simplify
+ (rdiv @0 (POW:s @1 @2))
+ (mult @0 (POW @1 (negate @2))))
+
+ (for sqrts (SQRT)
+ cbrts (CBRT)
+ pows (POW)
+ /* sqrt(sqrt(x)) -> pow(x,1/4). */
+ (simplify
+ (sqrts (sqrts @0))
+ (pows @0 { build_real (type, dconst_quarter ()); }))
+ /* sqrt(cbrt(x)) -> pow(x,1/6). */
+ (simplify
+ (sqrts (cbrts @0))
+ (pows @0 { build_real_truncate (type, dconst_sixth ()); }))
+ /* cbrt(sqrt(x)) -> pow(x,1/6). */
+ (simplify
+ (cbrts (sqrts @0))
+ (pows @0 { build_real_truncate (type, dconst_sixth ()); }))
+ /* cbrt(cbrt(x)) -> pow(x,1/9), iff x is nonnegative. */
+ (simplify
+ (cbrts (cbrts tree_expr_nonnegative_p@0))
+ (pows @0 { build_real_truncate (type, dconst_ninth ()); }))
+ /* sqrt(pow(x,y)) -> pow(|x|,y*0.5). */
+ (simplify
+ (sqrts (pows @0 @1))
+ (pows (abs @0) (mult @1 { build_real (type, dconsthalf); })))
+ /* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative. */
+ (simplify
+ (cbrts (pows tree_expr_nonnegative_p@0 @1))
+ (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))
+ /* pow(sqrt(x),y) -> pow(x,y*0.5). */
+ (simplify
+ (pows (sqrts @0) @1)
+ (pows @0 (mult @1 { build_real (type, dconsthalf); })))
+ /* pow(cbrt(x),y) -> pow(x,y/3) iff x is nonnegative. */
+ (simplify
+ (pows (cbrts tree_expr_nonnegative_p@0) @1)
+ (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))
+ /* pow(pow(x,y),z) -> pow(x,y*z) iff x is nonnegative. */
+ (simplify
+ (pows (pows tree_expr_nonnegative_p@0 @1) @2)
+ (pows @0 (mult @1 @2))))
+
+ /* cabs(x+xi) -> fabs(x)*sqrt(2). */
+ (simplify
+ (CABS (complex @0 @0))
+ (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))
+
+ /* hypot(x,x) -> fabs(x)*sqrt(2). */
+ (simplify
+ (HYPOT @0 @0)
+ (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); }))
+
+ /* cexp(x+yi) -> exp(x)*cexpi(y). */
+ (for cexps (CEXP)
+ exps (EXP)
+ cexpis (CEXPI)
+ (simplify
+ (cexps compositional_complex@0)
+ (if (targetm.libc_has_function (function_c99_math_complex, TREE_TYPE (@0)))
+ (complex
+ (mult (exps@1 (realpart @0)) (realpart (cexpis:type@2 (imagpart @0))))
+ (mult @1 (imagpart @2)))))))
+
+(if (canonicalize_math_p ())
+ /* floor(x) -> trunc(x) if x is nonnegative. */
+ (for floors (FLOOR_ALL)
+ truncs (TRUNC_ALL)
+ (simplify
+ (floors tree_expr_nonnegative_p@0)
+ (truncs @0))))
+
+(match double_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == double_type_node)))
+(for froms (BUILT_IN_TRUNCL
+ BUILT_IN_FLOORL
+ BUILT_IN_CEILL
+ BUILT_IN_ROUNDL
+ BUILT_IN_NEARBYINTL
+ BUILT_IN_RINTL)
+ tos (BUILT_IN_TRUNC
+ BUILT_IN_FLOOR
+ BUILT_IN_CEIL
+ BUILT_IN_ROUND
+ BUILT_IN_NEARBYINT
+ BUILT_IN_RINT)
+ /* truncl(extend(x)) -> extend(trunc(x)), etc., if x is a double. */
+ (if (optimize && canonicalize_math_p ())
+ (simplify
+ (froms (convert double_value_p@0))
+ (convert (tos @0)))))
+
+(match float_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == float_type_node)))
+(for froms (BUILT_IN_TRUNCL BUILT_IN_TRUNC
+ BUILT_IN_FLOORL BUILT_IN_FLOOR
+ BUILT_IN_CEILL BUILT_IN_CEIL
+ BUILT_IN_ROUNDL BUILT_IN_ROUND
+ BUILT_IN_NEARBYINTL BUILT_IN_NEARBYINT
+ BUILT_IN_RINTL BUILT_IN_RINT)
+ tos (BUILT_IN_TRUNCF BUILT_IN_TRUNCF
+ BUILT_IN_FLOORF BUILT_IN_FLOORF
+ BUILT_IN_CEILF BUILT_IN_CEILF
+ BUILT_IN_ROUNDF BUILT_IN_ROUNDF
+ BUILT_IN_NEARBYINTF BUILT_IN_NEARBYINTF
+ BUILT_IN_RINTF BUILT_IN_RINTF)
+ /* truncl(extend(x)) and trunc(extend(x)) -> extend(truncf(x)), etc.,
+ if x is a float. */
+ (if (optimize && canonicalize_math_p ()
+ && targetm.libc_has_function (function_c99_misc, NULL_TREE))
+ (simplify
+ (froms (convert float_value_p@0))
+ (convert (tos @0)))))
+
+#if GIMPLE
+(match float16_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == float16_type_node)))
+(for froms (BUILT_IN_TRUNCL BUILT_IN_TRUNC BUILT_IN_TRUNCF
+ BUILT_IN_FLOORL BUILT_IN_FLOOR BUILT_IN_FLOORF
+ BUILT_IN_CEILL BUILT_IN_CEIL BUILT_IN_CEILF
+ BUILT_IN_ROUNDEVENL BUILT_IN_ROUNDEVEN BUILT_IN_ROUNDEVENF
+ BUILT_IN_ROUNDL BUILT_IN_ROUND BUILT_IN_ROUNDF
+ BUILT_IN_NEARBYINTL BUILT_IN_NEARBYINT BUILT_IN_NEARBYINTF
+ BUILT_IN_RINTL BUILT_IN_RINT BUILT_IN_RINTF
+ BUILT_IN_SQRTL BUILT_IN_SQRT BUILT_IN_SQRTF)
+ tos (IFN_TRUNC IFN_TRUNC IFN_TRUNC
+ IFN_FLOOR IFN_FLOOR IFN_FLOOR
+ IFN_CEIL IFN_CEIL IFN_CEIL
+ IFN_ROUNDEVEN IFN_ROUNDEVEN IFN_ROUNDEVEN
+ IFN_ROUND IFN_ROUND IFN_ROUND
+ IFN_NEARBYINT IFN_NEARBYINT IFN_NEARBYINT
+ IFN_RINT IFN_RINT IFN_RINT
+ IFN_SQRT IFN_SQRT IFN_SQRT)
+ /* (_Float16) round ((doube) x) -> __built_in_roundf16 (x), etc.,
+ if x is a _Float16. */
+ (simplify
+ (convert (froms (convert float16_value_p@0)))
+ (if (optimize
+ && types_match (type, TREE_TYPE (@0))
+ && direct_internal_fn_supported_p (as_internal_fn (tos),
+ type, OPTIMIZE_FOR_BOTH))
+ (tos @0))))
+
+/* Simplify (trunc)copysign ((extend)x, (extend)y) to copysignf (x, y),
+ x,y is float value, similar for _Float16/double. */
+(for copysigns (COPYSIGN_ALL)
+ (simplify
+ (convert (copysigns (convert@2 @0) (convert @1)))
+ (if (optimize
+ && !HONOR_SNANS (@2)
+ && types_match (type, TREE_TYPE (@0))
+ && types_match (type, TREE_TYPE (@1))
+ && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@2))
+ && direct_internal_fn_supported_p (IFN_COPYSIGN,
+ type, OPTIMIZE_FOR_BOTH))
+ (IFN_COPYSIGN @0 @1))))
+
+(for froms (BUILT_IN_FMAF BUILT_IN_FMA BUILT_IN_FMAL)
+ tos (IFN_FMA IFN_FMA IFN_FMA)
+ (simplify
+ (convert (froms (convert@3 @0) (convert @1) (convert @2)))
+ (if (flag_unsafe_math_optimizations
+ && optimize
+ && FLOAT_TYPE_P (type)
+ && FLOAT_TYPE_P (TREE_TYPE (@3))
+ && types_match (type, TREE_TYPE (@0))
+ && types_match (type, TREE_TYPE (@1))
+ && types_match (type, TREE_TYPE (@2))
+ && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@3))
+ && direct_internal_fn_supported_p (as_internal_fn (tos),
+ type, OPTIMIZE_FOR_BOTH))
+ (tos @0 @1 @2))))
+
+(for maxmin (max min)
+ (simplify
+ (convert (maxmin (convert@2 @0) (convert @1)))
+ (if (optimize
+ && FLOAT_TYPE_P (type)
+ && FLOAT_TYPE_P (TREE_TYPE (@2))
+ && types_match (type, TREE_TYPE (@0))
+ && types_match (type, TREE_TYPE (@1))
+ && element_precision (type) < element_precision (TREE_TYPE (@2)))
+ (maxmin @0 @1))))
+#endif
+
+(for froms (XFLOORL XCEILL XROUNDL XRINTL)
+ tos (XFLOOR XCEIL XROUND XRINT)
+ /* llfloorl(extend(x)) -> llfloor(x), etc., if x is a double. */
+ (if (optimize && canonicalize_math_p ())
+ (simplify
+ (froms (convert double_value_p@0))
+ (tos @0))))
+
+(for froms (XFLOORL XCEILL XROUNDL XRINTL
+ XFLOOR XCEIL XROUND XRINT)
+ tos (XFLOORF XCEILF XROUNDF XRINTF)
+ /* llfloorl(extend(x)) and llfloor(extend(x)) -> llfloorf(x), etc.,
+ if x is a float. */
+ (if (optimize && canonicalize_math_p ())
+ (simplify
+ (froms (convert float_value_p@0))
+ (tos @0))))
+
+(if (canonicalize_math_p ())
+ /* xfloor(x) -> fix_trunc(x) if x is nonnegative. */
+ (for floors (IFLOOR LFLOOR LLFLOOR)
+ (simplify
+ (floors tree_expr_nonnegative_p@0)
+ (fix_trunc @0))))
+
+(if (canonicalize_math_p ())
+ /* xfloor(x) -> fix_trunc(x), etc., if x is integer valued. */
+ (for fns (IFLOOR LFLOOR LLFLOOR
+ ICEIL LCEIL LLCEIL
+ IROUND LROUND LLROUND)
+ (simplify
+ (fns integer_valued_real_p@0)
+ (fix_trunc @0)))
+ (if (!flag_errno_math)
+ /* xrint(x) -> fix_trunc(x), etc., if x is integer valued. */
+ (for rints (IRINT LRINT LLRINT)
+ (simplify
+ (rints integer_valued_real_p@0)
+ (fix_trunc @0)))))
+
+(if (canonicalize_math_p ())
+ (for ifn (IFLOOR ICEIL IROUND IRINT)
+ lfn (LFLOOR LCEIL LROUND LRINT)
+ llfn (LLFLOOR LLCEIL LLROUND LLRINT)
+ /* Canonicalize iround (x) to lround (x) on ILP32 targets where
+ sizeof (int) == sizeof (long). */
+ (if (TYPE_PRECISION (integer_type_node)
+ == TYPE_PRECISION (long_integer_type_node))
+ (simplify
+ (ifn @0)
+ (lfn:long_integer_type_node @0)))
+ /* Canonicalize llround (x) to lround (x) on LP64 targets where
+ sizeof (long long) == sizeof (long). */
+ (if (TYPE_PRECISION (long_long_integer_type_node)
+ == TYPE_PRECISION (long_integer_type_node))
+ (simplify
+ (llfn @0)
+ (lfn:long_integer_type_node @0)))))
+
+/* cproj(x) -> x if we're ignoring infinities. */
+(simplify
+ (CPROJ @0)
+ (if (!HONOR_INFINITIES (type))
+ @0))
+
+/* If the real part is inf and the imag part is known to be
+ nonnegative, return (inf + 0i). */
+(simplify
+ (CPROJ (complex REAL_CST@0 tree_expr_nonnegative_p@1))
+ (if (real_isinf (TREE_REAL_CST_PTR (@0)))
+ { build_complex_inf (type, false); }))
+
+/* If the imag part is inf, return (inf+I*copysign(0,imag)). */
+(simplify
+ (CPROJ (complex @0 REAL_CST@1))
+ (if (real_isinf (TREE_REAL_CST_PTR (@1)))
+ { build_complex_inf (type, TREE_REAL_CST_PTR (@1)->sign); }))
+
+(for pows (POW)
+ sqrts (SQRT)
+ cbrts (CBRT)
+ (simplify
+ (pows @0 REAL_CST@1)
+ (with {
+ const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (@1);
+ REAL_VALUE_TYPE tmp;
+ }
+ (switch
+ /* pow(x,0) -> 1. */
+ (if (real_equal (value, &dconst0))
+ { build_real (type, dconst1); })
+ /* pow(x,1) -> x. */
+ (if (real_equal (value, &dconst1))
+ @0)
+ /* pow(x,-1) -> 1/x. */
+ (if (real_equal (value, &dconstm1))
+ (rdiv { build_real (type, dconst1); } @0))
+ /* pow(x,0.5) -> sqrt(x). */
+ (if (flag_unsafe_math_optimizations
+ && canonicalize_math_p ()
+ && real_equal (value, &dconsthalf))
+ (sqrts @0))
+ /* pow(x,1/3) -> cbrt(x). */
+ (if (flag_unsafe_math_optimizations
+ && canonicalize_math_p ()
+ && (tmp = real_value_truncate (TYPE_MODE (type), dconst_third ()),
+ real_equal (value, &tmp)))
+ (cbrts @0))))))
+
+/* powi(1,x) -> 1. */
+(simplify
+ (POWI real_onep@0 @1)
+ @0)
+
+(simplify
+ (POWI @0 INTEGER_CST@1)
+ (switch
+ /* powi(x,0) -> 1. */
+ (if (wi::to_wide (@1) == 0)
+ { build_real (type, dconst1); })
+ /* powi(x,1) -> x. */
+ (if (wi::to_wide (@1) == 1)
+ @0)
+ /* powi(x,-1) -> 1/x. */
+ (if (wi::to_wide (@1) == -1)
+ (rdiv { build_real (type, dconst1); } @0))))
+
+/* Narrowing of arithmetic and logical operations.
+
+ These are conceptually similar to the transformations performed for
+ the C/C++ front-ends by shorten_binary_op and shorten_compare. Long
+ term we want to move all that code out of the front-ends into here. */
+
+/* Convert (outertype)((innertype0)a+(innertype1)b)
+ into ((newtype)a+(newtype)b) where newtype
+ is the widest mode from all of these. */
+(for op (plus minus mult rdiv)
+ (simplify
+ (convert (op:s@0 (convert1?@3 @1) (convert2?@4 @2)))
+ /* If we have a narrowing conversion of an arithmetic operation where
+ both operands are widening conversions from the same type as the outer
+ narrowing conversion. Then convert the innermost operands to a
+ suitable unsigned type (to avoid introducing undefined behavior),
+ perform the operation and convert the result to the desired type. */
+ (if (INTEGRAL_TYPE_P (type)
+ && op != MULT_EXPR
+ && op != RDIV_EXPR
+ /* We check for type compatibility between @0 and @1 below,
+ so there's no need to check that @2/@4 are integral types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@3))
+ /* The precision of the type of each operand must match the
+ precision of the mode of each operand, similarly for the
+ result. */
+ && type_has_mode_precision_p (TREE_TYPE (@1))
+ && type_has_mode_precision_p (TREE_TYPE (@2))
+ && type_has_mode_precision_p (type)
+ /* The inner conversion must be a widening conversion. */
+ && TYPE_PRECISION (TREE_TYPE (@3)) > TYPE_PRECISION (TREE_TYPE (@1))
+ && types_match (@1, type)
+ && (types_match (@1, @2)
+ /* Or the second operand is const integer or converted const
+ integer from valueize. */
+ || poly_int_tree_p (@4)))
+ (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
+ (op @1 (convert @2))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@1)); }
+ (convert (op (convert:utype @1)
+ (convert:utype @2)))))
+ (if (FLOAT_TYPE_P (type)
+ && DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@0))
+ == DECIMAL_FLOAT_TYPE_P (type))
+ (with { tree arg0 = strip_float_extensions (@1);
+ tree arg1 = strip_float_extensions (@2);
+ tree itype = TREE_TYPE (@0);
+ tree ty1 = TREE_TYPE (arg0);
+ tree ty2 = TREE_TYPE (arg1);
+ enum tree_code code = TREE_CODE (itype); }
+ (if (FLOAT_TYPE_P (ty1)
+ && FLOAT_TYPE_P (ty2))
+ (with { tree newtype = type;
+ if (TYPE_MODE (ty1) == SDmode
+ || TYPE_MODE (ty2) == SDmode
+ || TYPE_MODE (type) == SDmode)
+ newtype = dfloat32_type_node;
+ if (TYPE_MODE (ty1) == DDmode
+ || TYPE_MODE (ty2) == DDmode
+ || TYPE_MODE (type) == DDmode)
+ newtype = dfloat64_type_node;
+ if (TYPE_MODE (ty1) == TDmode
+ || TYPE_MODE (ty2) == TDmode
+ || TYPE_MODE (type) == TDmode)
+ newtype = dfloat128_type_node; }
+ (if ((newtype == dfloat32_type_node
+ || newtype == dfloat64_type_node
+ || newtype == dfloat128_type_node)
+ && newtype == type
+ && types_match (newtype, type))
+ (op (convert:newtype @1) (convert:newtype @2))
+ (with { if (TYPE_PRECISION (ty1) > TYPE_PRECISION (newtype))
+ newtype = ty1;
+ if (TYPE_PRECISION (ty2) > TYPE_PRECISION (newtype))
+ newtype = ty2; }
+ /* Sometimes this transformation is safe (cannot
+ change results through affecting double rounding
+ cases) and sometimes it is not. If NEWTYPE is
+ wider than TYPE, e.g. (float)((long double)double
+ + (long double)double) converted to
+ (float)(double + double), the transformation is
+ unsafe regardless of the details of the types
+ involved; double rounding can arise if the result
+ of NEWTYPE arithmetic is a NEWTYPE value half way
+ between two representable TYPE values but the
+ exact value is sufficiently different (in the
+ right direction) for this difference to be
+ visible in ITYPE arithmetic. If NEWTYPE is the
+ same as TYPE, however, the transformation may be
+ safe depending on the types involved: it is safe
+ if the ITYPE has strictly more than twice as many
+ mantissa bits as TYPE, can represent infinities
+ and NaNs if the TYPE can, and has sufficient
+ exponent range for the product or ratio of two
+ values representable in the TYPE to be within the
+ range of normal values of ITYPE. */
+ (if (TYPE_PRECISION (newtype) < TYPE_PRECISION (itype)
+ && (flag_unsafe_math_optimizations
+ || (TYPE_PRECISION (newtype) == TYPE_PRECISION (type)
+ && real_can_shorten_arithmetic (TYPE_MODE (itype),
+ TYPE_MODE (type))
+ && !excess_precision_type (newtype)))
+ && !types_match (itype, newtype))
+ (convert:type (op (convert:newtype @1)
+ (convert:newtype @2)))
+ )))) )
+ ))
+)))
+
+/* This is another case of narrowing, specifically when there's an outer
+ BIT_AND_EXPR which masks off bits outside the type of the innermost
+ operands. Like the previous case we have to convert the operands
+ to unsigned types to avoid introducing undefined behavior for the
+ arithmetic operation. */
+(for op (minus plus)
+ (simplify
+ (bit_and (op:s (convert@2 @0) (convert@3 @1)) INTEGER_CST@4)
+ (if (INTEGRAL_TYPE_P (type)
+ /* We check for type compatibility between @0 and @1 below,
+ so there's no need to check that @1/@3 are integral types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ /* The precision of the type of each operand must match the
+ precision of the mode of each operand, similarly for the
+ result. */
+ && type_has_mode_precision_p (TREE_TYPE (@0))
+ && type_has_mode_precision_p (TREE_TYPE (@1))
+ && type_has_mode_precision_p (type)
+ /* The inner conversion must be a widening conversion. */
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && types_match (@0, @1)
+ && (tree_int_cst_min_precision (@4, TYPE_SIGN (TREE_TYPE (@0)))
+ <= TYPE_PRECISION (TREE_TYPE (@0)))
+ && (wi::to_wide (@4)
+ & wi::mask (TYPE_PRECISION (TREE_TYPE (@0)),
+ true, TYPE_PRECISION (type))) == 0)
+ (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ (with { tree ntype = TREE_TYPE (@0); }
+ (convert (bit_and (op @0 @1) (convert:ntype @4))))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (convert (bit_and (op (convert:utype @0) (convert:utype @1))
+ (convert:utype @4))))))))
+
+/* Transform (@0 < @1 and @0 < @2) to use min,
+ (@0 > @1 and @0 > @2) to use max */
+(for logic (bit_and bit_and bit_and bit_and bit_ior bit_ior bit_ior bit_ior)
+ op (lt le gt ge lt le gt ge )
+ ext (min min max max max max min min )
+ (simplify
+ (logic (op:cs @0 @1) (op:cs @0 @2))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && TREE_CODE (@0) != INTEGER_CST)
+ (op @0 (ext @1 @2)))))
+
+(simplify
+ /* signbit(x) -> 0 if x is nonnegative. */
+ (SIGNBIT tree_expr_nonnegative_p@0)
+ { integer_zero_node; })
+
+(simplify
+ /* signbit(x) -> x<0 if x doesn't have signed zeros. */
+ (SIGNBIT @0)
+ (if (!HONOR_SIGNED_ZEROS (@0))
+ (convert (lt @0 { build_real (TREE_TYPE (@0), dconst0); }))))
+
+/* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 -+ C1. */
+(for cmp (eq ne)
+ (for op (plus minus)
+ rop (minus plus)
+ (simplify
+ (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
+ && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@0))
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@0))
+ && !TYPE_SATURATING (TREE_TYPE (@0)))
+ (with { tree res = int_const_binop (rop, @2, @1); }
+ (if (TREE_OVERFLOW (res)
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ { constant_boolean_node (cmp == NE_EXPR, type); }
+ (if (single_use (@3))
+ (cmp @0 { TREE_OVERFLOW (res)
+ ? drop_tree_overflow (res) : res; }))))))))
+(for cmp (lt le gt ge)
+ (for op (plus minus)
+ rop (minus plus)
+ (simplify
+ (cmp (op@3 @0 INTEGER_CST@1) INTEGER_CST@2)
+ (if (!TREE_OVERFLOW (@1) && !TREE_OVERFLOW (@2)
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+ (with { tree res = int_const_binop (rop, @2, @1); }
+ (if (TREE_OVERFLOW (res))
+ {
+ fold_overflow_warning (("assuming signed overflow does not occur "
+ "when simplifying conditional to constant"),
+ WARN_STRICT_OVERFLOW_CONDITIONAL);
+ bool less = cmp == LE_EXPR || cmp == LT_EXPR;
+ /* wi::ges_p (@2, 0) should be sufficient for a signed type. */
+ bool ovf_high = wi::lt_p (wi::to_wide (@1), 0,
+ TYPE_SIGN (TREE_TYPE (@1)))
+ != (op == MINUS_EXPR);
+ constant_boolean_node (less == ovf_high, type);
+ }
+ (if (single_use (@3))
+ (with
+ {
+ fold_overflow_warning (("assuming signed overflow does not occur "
+ "when changing X +- C1 cmp C2 to "
+ "X cmp C2 -+ C1"),
+ WARN_STRICT_OVERFLOW_COMPARISON);
+ }
+ (cmp @0 { res; })))))))))
+
+/* Canonicalizations of BIT_FIELD_REFs. */
+
+(simplify
+ (BIT_FIELD_REF (BIT_FIELD_REF @0 @1 @2) @3 @4)
+ (BIT_FIELD_REF @0 @3 { const_binop (PLUS_EXPR, bitsizetype, @2, @4); }))
+
+(simplify
+ (BIT_FIELD_REF (view_convert @0) @1 @2)
+ (BIT_FIELD_REF @0 @1 @2))
+
+(simplify
+ (BIT_FIELD_REF @0 @1 integer_zerop)
+ (if (tree_int_cst_equal (@1, TYPE_SIZE (TREE_TYPE (@0))))
+ (view_convert @0)))
+
+(simplify
+ (BIT_FIELD_REF @0 @1 @2)
+ (switch
+ (if (TREE_CODE (TREE_TYPE (@0)) == COMPLEX_TYPE
+ && tree_int_cst_equal (@1, TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0)))))
+ (switch
+ (if (integer_zerop (@2))
+ (view_convert (realpart @0)))
+ (if (tree_int_cst_equal (@2, TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0)))))
+ (view_convert (imagpart @0)))))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (type)
+ /* On GIMPLE this should only apply to register arguments. */
+ && (! GIMPLE || is_gimple_reg (@0))
+ /* A bit-field-ref that referenced the full argument can be stripped. */
+ && ((compare_tree_int (@1, TYPE_PRECISION (TREE_TYPE (@0))) == 0
+ && integer_zerop (@2))
+ /* Low-parts can be reduced to integral conversions.
+ ??? The following doesn't work for PDP endian. */
+ || (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN
+ /* But only do this after vectorization. */
+ && canonicalize_math_after_vectorization_p ()
+ /* Don't even think about BITS_BIG_ENDIAN. */
+ && TYPE_PRECISION (TREE_TYPE (@0)) % BITS_PER_UNIT == 0
+ && TYPE_PRECISION (type) % BITS_PER_UNIT == 0
+ && compare_tree_int (@2, (BYTES_BIG_ENDIAN
+ ? (TYPE_PRECISION (TREE_TYPE (@0))
+ - TYPE_PRECISION (type))
+ : 0)) == 0)))
+ (convert @0))))
+
+/* Simplify vector extracts. */
+
+(simplify
+ (BIT_FIELD_REF CONSTRUCTOR@0 @1 @2)
+ (if (VECTOR_TYPE_P (TREE_TYPE (@0))
+ && tree_fits_uhwi_p (TYPE_SIZE (type))
+ && ((tree_to_uhwi (TYPE_SIZE (type))
+ == tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0)))))
+ || (VECTOR_TYPE_P (type)
+ && (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)))
+ == tree_to_uhwi (TYPE_SIZE (TREE_TYPE (TREE_TYPE (@0))))))))
+ (with
+ {
+ tree ctor = (TREE_CODE (@0) == SSA_NAME
+ ? gimple_assign_rhs1 (SSA_NAME_DEF_STMT (@0)) : @0);
+ tree eltype = TREE_TYPE (TREE_TYPE (ctor));
+ unsigned HOST_WIDE_INT width = tree_to_uhwi (TYPE_SIZE (eltype));
+ unsigned HOST_WIDE_INT n = tree_to_uhwi (@1);
+ unsigned HOST_WIDE_INT idx = tree_to_uhwi (@2);
+ }
+ (if (n != 0
+ && (idx % width) == 0
+ && (n % width) == 0
+ && known_le ((idx + n) / width,
+ TYPE_VECTOR_SUBPARTS (TREE_TYPE (ctor))))
+ (with
+ {
+ idx = idx / width;
+ n = n / width;
+ /* Constructor elements can be subvectors. */
+ poly_uint64 k = 1;
+ if (CONSTRUCTOR_NELTS (ctor) != 0)
+ {
+ tree cons_elem = TREE_TYPE (CONSTRUCTOR_ELT (ctor, 0)->value);
+ if (TREE_CODE (cons_elem) == VECTOR_TYPE)
+ k = TYPE_VECTOR_SUBPARTS (cons_elem);
+ }
+ unsigned HOST_WIDE_INT elt, count, const_k;
+ }
+ (switch
+ /* We keep an exact subset of the constructor elements. */
+ (if (multiple_p (idx, k, &elt) && multiple_p (n, k, &count))
+ (if (CONSTRUCTOR_NELTS (ctor) == 0)
+ { build_zero_cst (type); }
+ (if (count == 1)
+ (if (elt < CONSTRUCTOR_NELTS (ctor))
+ (view_convert { CONSTRUCTOR_ELT (ctor, elt)->value; })
+ { build_zero_cst (type); })
+ /* We don't want to emit new CTORs unless the old one goes away.
+ ??? Eventually allow this if the CTOR ends up constant or
+ uniform. */
+ (if (single_use (@0))
+ (with
+ {
+ vec<constructor_elt, va_gc> *vals;
+ vec_alloc (vals, count);
+ bool constant_p = true;
+ tree res;
+ for (unsigned i = 0;
+ i < count && elt + i < CONSTRUCTOR_NELTS (ctor); ++i)
+ {
+ tree e = CONSTRUCTOR_ELT (ctor, elt + i)->value;
+ CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE, e);
+ if (!CONSTANT_CLASS_P (e))
+ constant_p = false;
+ }
+ tree evtype = (types_match (TREE_TYPE (type),
+ TREE_TYPE (TREE_TYPE (ctor)))
+ ? type
+ : build_vector_type (TREE_TYPE (TREE_TYPE (ctor)),
+ count * k));
+ res = (constant_p ? build_vector_from_ctor (evtype, vals)
+ : build_constructor (evtype, vals));
+ }
+ (view_convert { res; }))))))
+ /* The bitfield references a single constructor element. */
+ (if (k.is_constant (&const_k)
+ && idx + n <= (idx / const_k + 1) * const_k)
+ (switch
+ (if (CONSTRUCTOR_NELTS (ctor) <= idx / const_k)
+ { build_zero_cst (type); })
+ (if (n == const_k)
+ (view_convert { CONSTRUCTOR_ELT (ctor, idx / const_k)->value; }))
+ (BIT_FIELD_REF { CONSTRUCTOR_ELT (ctor, idx / const_k)->value; }
+ @1 { bitsize_int ((idx % const_k) * width); })))))))))
+
+/* Simplify a bit extraction from a bit insertion for the cases with
+ the inserted element fully covering the extraction or the insertion
+ not touching the extraction. */
+(simplify
+ (BIT_FIELD_REF (bit_insert @0 @1 @ipos) @rsize @rpos)
+ (with
+ {
+ unsigned HOST_WIDE_INT isize;
+ if (INTEGRAL_TYPE_P (TREE_TYPE (@1)))
+ isize = TYPE_PRECISION (TREE_TYPE (@1));
+ else
+ isize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (@1)));
+ }
+ (switch
+ (if (wi::leu_p (wi::to_wide (@ipos), wi::to_wide (@rpos))
+ && wi::leu_p (wi::to_wide (@rpos) + wi::to_wide (@rsize),
+ wi::to_wide (@ipos) + isize))
+ (BIT_FIELD_REF @1 @rsize { wide_int_to_tree (bitsizetype,
+ wi::to_wide (@rpos)
+ - wi::to_wide (@ipos)); }))
+ (if (wi::geu_p (wi::to_wide (@ipos),
+ wi::to_wide (@rpos) + wi::to_wide (@rsize))
+ || wi::geu_p (wi::to_wide (@rpos),
+ wi::to_wide (@ipos) + isize))
+ (BIT_FIELD_REF @0 @rsize @rpos)))))
+
+(if (canonicalize_math_after_vectorization_p ())
+ (for fmas (FMA)
+ (simplify
+ (fmas:c (negate @0) @1 @2)
+ (IFN_FNMA @0 @1 @2))
+ (simplify
+ (fmas @0 @1 (negate @2))
+ (IFN_FMS @0 @1 @2))
+ (simplify
+ (fmas:c (negate @0) @1 (negate @2))
+ (IFN_FNMS @0 @1 @2))
+ (simplify
+ (negate (fmas@3 @0 @1 @2))
+ (if (single_use (@3))
+ (IFN_FNMS @0 @1 @2))))
+
+ (simplify
+ (IFN_FMS:c (negate @0) @1 @2)
+ (IFN_FNMS @0 @1 @2))
+ (simplify
+ (IFN_FMS @0 @1 (negate @2))
+ (IFN_FMA @0 @1 @2))
+ (simplify
+ (IFN_FMS:c (negate @0) @1 (negate @2))
+ (IFN_FNMA @0 @1 @2))
+ (simplify
+ (negate (IFN_FMS@3 @0 @1 @2))
+ (if (single_use (@3))
+ (IFN_FNMA @0 @1 @2)))
+
+ (simplify
+ (IFN_FNMA:c (negate @0) @1 @2)
+ (IFN_FMA @0 @1 @2))
+ (simplify
+ (IFN_FNMA @0 @1 (negate @2))
+ (IFN_FNMS @0 @1 @2))
+ (simplify
+ (IFN_FNMA:c (negate @0) @1 (negate @2))
+ (IFN_FMS @0 @1 @2))
+ (simplify
+ (negate (IFN_FNMA@3 @0 @1 @2))
+ (if (single_use (@3))
+ (IFN_FMS @0 @1 @2)))
+
+ (simplify
+ (IFN_FNMS:c (negate @0) @1 @2)
+ (IFN_FMS @0 @1 @2))
+ (simplify
+ (IFN_FNMS @0 @1 (negate @2))
+ (IFN_FNMA @0 @1 @2))
+ (simplify
+ (IFN_FNMS:c (negate @0) @1 (negate @2))
+ (IFN_FMA @0 @1 @2))
+ (simplify
+ (negate (IFN_FNMS@3 @0 @1 @2))
+ (if (single_use (@3))
+ (IFN_FMA @0 @1 @2))))
+
+/* CLZ simplifications. */
+(for clz (CLZ)
+ (for op (eq ne)
+ cmp (lt ge)
+ (simplify
+ (op (clz:s@2 @0) INTEGER_CST@1)
+ (if (integer_zerop (@1) && single_use (@2))
+ /* clz(X) == 0 is (int)X < 0 and clz(X) != 0 is (int)X >= 0. */
+ (with { tree type0 = TREE_TYPE (@0);
+ tree stype = signed_type_for (type0);
+ HOST_WIDE_INT val = 0;
+ /* Punt on hypothetical weird targets. */
+ if (clz == CFN_CLZ
+ && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (type0),
+ val) == 2
+ && val == 0)
+ stype = NULL_TREE;
+ }
+ (if (stype)
+ (cmp (convert:stype @0) { build_zero_cst (stype); })))
+ /* clz(X) == (prec-1) is X == 1 and clz(X) != (prec-1) is X != 1. */
+ (with { bool ok = true;
+ HOST_WIDE_INT val = 0;
+ tree type0 = TREE_TYPE (@0);
+ /* Punt on hypothetical weird targets. */
+ if (clz == CFN_CLZ
+ && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (type0),
+ val) == 2
+ && val == TYPE_PRECISION (type0) - 1)
+ ok = false;
+ }
+ (if (ok && wi::to_wide (@1) == (TYPE_PRECISION (type0) - 1))
+ (op @0 { build_one_cst (type0); })))))))
+
+/* CTZ simplifications. */
+(for ctz (CTZ)
+ (for op (ge gt le lt)
+ cmp (eq eq ne ne)
+ (simplify
+ /* __builtin_ctz (x) >= C -> (x & ((1 << C) - 1)) == 0. */
+ (op (ctz:s @0) INTEGER_CST@1)
+ (with { bool ok = true;
+ HOST_WIDE_INT val = 0;
+ if (!tree_fits_shwi_p (@1))
+ ok = false;
+ else
+ {
+ val = tree_to_shwi (@1);
+ /* Canonicalize to >= or <. */
+ if (op == GT_EXPR || op == LE_EXPR)
+ {
+ if (val == HOST_WIDE_INT_MAX)
+ ok = false;
+ else
+ val++;
+ }
+ }
+ bool zero_res = false;
+ HOST_WIDE_INT zero_val = 0;
+ tree type0 = TREE_TYPE (@0);
+ int prec = TYPE_PRECISION (type0);
+ if (ctz == CFN_CTZ
+ && CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (type0),
+ zero_val) == 2)
+ zero_res = true;
+ }
+ (if (val <= 0)
+ (if (ok && (!zero_res || zero_val >= val))
+ { constant_boolean_node (cmp == EQ_EXPR ? true : false, type); })
+ (if (val >= prec)
+ (if (ok && (!zero_res || zero_val < val))
+ { constant_boolean_node (cmp == EQ_EXPR ? false : true, type); })
+ (if (ok && (!zero_res || zero_val < 0 || zero_val >= prec))
+ (cmp (bit_and @0 { wide_int_to_tree (type0,
+ wi::mask (val, false, prec)); })
+ { build_zero_cst (type0); })))))))
+ (for op (eq ne)
+ (simplify
+ /* __builtin_ctz (x) == C -> (x & ((1 << (C + 1)) - 1)) == (1 << C). */
+ (op (ctz:s @0) INTEGER_CST@1)
+ (with { bool zero_res = false;
+ HOST_WIDE_INT zero_val = 0;
+ tree type0 = TREE_TYPE (@0);
+ int prec = TYPE_PRECISION (type0);
+ if (ctz == CFN_CTZ
+ && CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (type0),
+ zero_val) == 2)
+ zero_res = true;
+ }
+ (if (tree_int_cst_sgn (@1) < 0 || wi::to_widest (@1) >= prec)
+ (if (!zero_res || zero_val != wi::to_widest (@1))
+ { constant_boolean_node (op == EQ_EXPR ? false : true, type); })
+ (if (!zero_res || zero_val < 0 || zero_val >= prec)
+ (op (bit_and @0 { wide_int_to_tree (type0,
+ wi::mask (tree_to_uhwi (@1) + 1,
+ false, prec)); })
+ { wide_int_to_tree (type0,
+ wi::shifted_mask (tree_to_uhwi (@1), 1,
+ false, prec)); })))))))
+
+/* POPCOUNT simplifications. */
+/* popcount(X) + popcount(Y) is popcount(X|Y) when X&Y must be zero. */
+(simplify
+ (plus (POPCOUNT:s @0) (POPCOUNT:s @1))
+ (if (wi::bit_and (tree_nonzero_bits (@0), tree_nonzero_bits (@1)) == 0)
+ (POPCOUNT (bit_ior @0 @1))))
+
+/* popcount(X) == 0 is X == 0, and related (in)equalities. */
+(for popcount (POPCOUNT)
+ (for cmp (le eq ne gt)
+ rep (eq eq ne ne)
+ (simplify
+ (cmp (popcount @0) integer_zerop)
+ (rep @0 { build_zero_cst (TREE_TYPE (@0)); }))))
+
+/* Canonicalize POPCOUNT(x)&1 as PARITY(X). */
+(simplify
+ (bit_and (POPCOUNT @0) integer_onep)
+ (PARITY @0))
+
+/* PARITY simplifications. */
+/* parity(~X) is parity(X). */
+(simplify
+ (PARITY (bit_not @0))
+ (PARITY @0))
+
+/* parity(X)^parity(Y) is parity(X^Y). */
+(simplify
+ (bit_xor (PARITY:s @0) (PARITY:s @1))
+ (PARITY (bit_xor @0 @1)))
+
+/* Common POPCOUNT/PARITY simplifications. */
+/* popcount(X&C1) is (X>>C2)&1 when C1 == 1<<C2. Same for parity(X&C1). */
+(for pfun (POPCOUNT PARITY)
+ (simplify
+ (pfun @0)
+ (with { wide_int nz = tree_nonzero_bits (@0); }
+ (switch
+ (if (nz == 1)
+ (convert @0))
+ (if (wi::popcount (nz) == 1)
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (convert (rshift:utype (convert:utype @0)
+ { build_int_cst (integer_type_node,
+ wi::ctz (nz)); }))))))))
+
+#if GIMPLE
+/* 64- and 32-bits branchless implementations of popcount are detected:
+
+ int popcount64c (uint64_t x)
+ {
+ x -= (x >> 1) & 0x5555555555555555ULL;
+ x = (x & 0x3333333333333333ULL) + ((x >> 2) & 0x3333333333333333ULL);
+ x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
+ return (x * 0x0101010101010101ULL) >> 56;
+ }
+
+ int popcount32c (uint32_t x)
+ {
+ x -= (x >> 1) & 0x55555555;
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0f0f0f0f;
+ return (x * 0x01010101) >> 24;
+ } */
+(simplify
+ (rshift
+ (mult
+ (bit_and
+ (plus:c
+ (rshift @8 INTEGER_CST@5)
+ (plus:c@8
+ (bit_and @6 INTEGER_CST@7)
+ (bit_and
+ (rshift
+ (minus@6 @0
+ (bit_and (rshift @0 INTEGER_CST@4) INTEGER_CST@11))
+ INTEGER_CST@10)
+ INTEGER_CST@9)))
+ INTEGER_CST@3)
+ INTEGER_CST@2)
+ INTEGER_CST@1)
+ /* Check constants and optab. */
+ (with { unsigned prec = TYPE_PRECISION (type);
+ int shift = (64 - prec) & 63;
+ unsigned HOST_WIDE_INT c1
+ = HOST_WIDE_INT_UC (0x0101010101010101) >> shift;
+ unsigned HOST_WIDE_INT c2
+ = HOST_WIDE_INT_UC (0x0F0F0F0F0F0F0F0F) >> shift;
+ unsigned HOST_WIDE_INT c3
+ = HOST_WIDE_INT_UC (0x3333333333333333) >> shift;
+ unsigned HOST_WIDE_INT c4
+ = HOST_WIDE_INT_UC (0x5555555555555555) >> shift;
+ }
+ (if (prec >= 16
+ && prec <= 64
+ && pow2p_hwi (prec)
+ && TYPE_UNSIGNED (type)
+ && integer_onep (@4)
+ && wi::to_widest (@10) == 2
+ && wi::to_widest (@5) == 4
+ && wi::to_widest (@1) == prec - 8
+ && tree_to_uhwi (@2) == c1
+ && tree_to_uhwi (@3) == c2
+ && tree_to_uhwi (@9) == c3
+ && tree_to_uhwi (@7) == c3
+ && tree_to_uhwi (@11) == c4)
+ (if (direct_internal_fn_supported_p (IFN_POPCOUNT, type,
+ OPTIMIZE_FOR_BOTH))
+ (convert (IFN_POPCOUNT:type @0))
+ /* Try to do popcount in two halves. PREC must be at least
+ five bits for this to work without extension before adding. */
+ (with {
+ tree half_type = NULL_TREE;
+ opt_machine_mode m = mode_for_size ((prec + 1) / 2, MODE_INT, 1);
+ int half_prec = 8;
+ if (m.exists ()
+ && m.require () != TYPE_MODE (type))
+ {
+ half_prec = GET_MODE_PRECISION (as_a <scalar_int_mode> (m));
+ half_type = build_nonstandard_integer_type (half_prec, 1);
+ }
+ gcc_assert (half_prec > 2);
+ }
+ (if (half_type != NULL_TREE
+ && direct_internal_fn_supported_p (IFN_POPCOUNT, half_type,
+ OPTIMIZE_FOR_BOTH))
+ (convert (plus
+ (IFN_POPCOUNT:half_type (convert @0))
+ (IFN_POPCOUNT:half_type (convert (rshift @0
+ { build_int_cst (integer_type_node, half_prec); } )))))))))))
+
+/* __builtin_ffs needs to deal on many targets with the possible zero
+ argument. If we know the argument is always non-zero, __builtin_ctz + 1
+ should lead to better code. */
+(simplify
+ (FFS tree_expr_nonzero_p@0)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && direct_internal_fn_supported_p (IFN_CTZ, TREE_TYPE (@0),
+ OPTIMIZE_FOR_SPEED))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (plus (CTZ:type (convert:utype @0)) { build_one_cst (type); }))))
+#endif
+
+(for ffs (BUILT_IN_FFS BUILT_IN_FFSL BUILT_IN_FFSLL
+ BUILT_IN_FFSIMAX)
+ /* __builtin_ffs (X) == 0 -> X == 0.
+ __builtin_ffs (X) == 6 -> (X & 63) == 32. */
+ (for cmp (eq ne)
+ (simplify
+ (cmp (ffs@2 @0) INTEGER_CST@1)
+ (with { int prec = TYPE_PRECISION (TREE_TYPE (@0)); }
+ (switch
+ (if (integer_zerop (@1))
+ (cmp @0 { build_zero_cst (TREE_TYPE (@0)); }))
+ (if (tree_int_cst_sgn (@1) < 0 || wi::to_widest (@1) > prec)
+ { constant_boolean_node (cmp == NE_EXPR ? true : false, type); })
+ (if (single_use (@2))
+ (cmp (bit_and @0 { wide_int_to_tree (TREE_TYPE (@0),
+ wi::mask (tree_to_uhwi (@1),
+ false, prec)); })
+ { wide_int_to_tree (TREE_TYPE (@0),
+ wi::shifted_mask (tree_to_uhwi (@1) - 1, 1,
+ false, prec)); }))))))
+
+ /* __builtin_ffs (X) > 6 -> X != 0 && (X & 63) == 0. */
+ (for cmp (gt le)
+ cmp2 (ne eq)
+ cmp3 (eq ne)
+ bit_op (bit_and bit_ior)
+ (simplify
+ (cmp (ffs@2 @0) INTEGER_CST@1)
+ (with { int prec = TYPE_PRECISION (TREE_TYPE (@0)); }
+ (switch
+ (if (integer_zerop (@1))
+ (cmp2 @0 { build_zero_cst (TREE_TYPE (@0)); }))
+ (if (tree_int_cst_sgn (@1) < 0)
+ { constant_boolean_node (cmp == GT_EXPR ? true : false, type); })
+ (if (wi::to_widest (@1) >= prec)
+ { constant_boolean_node (cmp == GT_EXPR ? false : true, type); })
+ (if (wi::to_widest (@1) == prec - 1)
+ (cmp3 @0 { wide_int_to_tree (TREE_TYPE (@0),
+ wi::shifted_mask (prec - 1, 1,
+ false, prec)); }))
+ (if (single_use (@2))
+ (bit_op (cmp2 @0 { build_zero_cst (TREE_TYPE (@0)); })
+ (cmp3 (bit_and @0
+ { wide_int_to_tree (TREE_TYPE (@0),
+ wi::mask (tree_to_uhwi (@1),
+ false, prec)); })
+ { build_zero_cst (TREE_TYPE (@0)); }))))))))
+
+#if GIMPLE
+
+/* Simplify:
+ a = op a1
+ r = cond ? a : b
+ --> r = .COND_FN (cond, a, b)
+and,
+ a = op a1
+ r = cond ? b : a
+ --> r = .COND_FN (~cond, b, a). */
+
+(for uncond_op (UNCOND_UNARY)
+ cond_op (COND_UNARY)
+ (simplify
+ (vec_cond @0 (view_convert? (uncond_op@3 @1)) @2)
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
+ (cond_op @0 @1 @2))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (uncond_op@3 @2)))
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0)))
+ (cond_op (bit_not @0) @2 @1)))))
+
+/* Simplify:
+
+ a = a1 op a2
+ r = c ? a : b;
+
+ to:
+
+ r = c ? a1 op a2 : b;
+
+ if the target can do it in one go. This makes the operation conditional
+ on c, so could drop potentially-trapping arithmetic, but that's a valid
+ simplification if the result of the operation isn't needed.
+
+ Avoid speculatively generating a stand-alone vector comparison
+ on targets that might not support them. Any target implementing
+ conditional internal functions must support the same comparisons
+ inside and outside a VEC_COND_EXPR. */
+
+(for uncond_op (UNCOND_BINARY)
+ cond_op (COND_BINARY)
+ (simplify
+ (vec_cond @0 (view_convert? (uncond_op@4 @1 @2)) @3)
+ (with { tree op_type = TREE_TYPE (@4); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0))
+ && single_use (@4))
+ (view_convert (cond_op @0 @1 @2 (view_convert:op_type @3))))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (uncond_op@4 @2 @3)))
+ (with { tree op_type = TREE_TYPE (@4); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0))
+ && single_use (@4))
+ (view_convert (cond_op (bit_not @0) @2 @3 (view_convert:op_type @1)))))))
+
+/* Same for ternary operations. */
+(for uncond_op (UNCOND_TERNARY)
+ cond_op (COND_TERNARY)
+ (simplify
+ (vec_cond @0 (view_convert? (uncond_op@5 @1 @2 @3)) @4)
+ (with { tree op_type = TREE_TYPE (@5); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0))
+ && single_use (@5))
+ (view_convert (cond_op @0 @1 @2 @3 (view_convert:op_type @4))))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (uncond_op@5 @2 @3 @4)))
+ (with { tree op_type = TREE_TYPE (@5); }
+ (if (vectorized_internal_fn_supported_p (as_internal_fn (cond_op), op_type)
+ && is_truth_type_for (op_type, TREE_TYPE (@0))
+ && single_use (@5))
+ (view_convert (cond_op (bit_not @0) @2 @3 @4
+ (view_convert:op_type @1)))))))
+#endif
+
+/* Detect cases in which a VEC_COND_EXPR effectively replaces the
+ "else" value of an IFN_COND_*. */
+(for cond_op (COND_BINARY)
+ (simplify
+ (vec_cond @0 (view_convert? (cond_op @0 @1 @2 @3)) @4)
+ (with { tree op_type = TREE_TYPE (@3); }
+ (if (element_precision (type) == element_precision (op_type))
+ (view_convert (cond_op @0 @1 @2 (view_convert:op_type @4))))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (cond_op @2 @3 @4 @5)))
+ (with { tree op_type = TREE_TYPE (@5); }
+ (if (inverse_conditions_p (@0, @2)
+ && element_precision (type) == element_precision (op_type))
+ (view_convert (cond_op @2 @3 @4 (view_convert:op_type @1)))))))
+
+/* Same for ternary operations. */
+(for cond_op (COND_TERNARY)
+ (simplify
+ (vec_cond @0 (view_convert? (cond_op @0 @1 @2 @3 @4)) @5)
+ (with { tree op_type = TREE_TYPE (@4); }
+ (if (element_precision (type) == element_precision (op_type))
+ (view_convert (cond_op @0 @1 @2 @3 (view_convert:op_type @5))))))
+ (simplify
+ (vec_cond @0 @1 (view_convert? (cond_op @2 @3 @4 @5 @6)))
+ (with { tree op_type = TREE_TYPE (@6); }
+ (if (inverse_conditions_p (@0, @2)
+ && element_precision (type) == element_precision (op_type))
+ (view_convert (cond_op @2 @3 @4 @5 (view_convert:op_type @1)))))))
+
+/* Detect simplication for a conditional reduction where
+
+ a = mask1 ? b : 0
+ c = mask2 ? d + a : d
+
+ is turned into
+
+ c = mask1 && mask2 ? d + b : d. */
+(simplify
+ (IFN_COND_ADD @0 @1 (vec_cond @2 @3 integer_zerop) @1)
+ (IFN_COND_ADD (bit_and @0 @2) @1 @3 @1))
+
+/* For pointers @0 and @2 and nonnegative constant offset @1, look for
+ expressions like:
+
+ A: (@0 + @1 < @2) | (@2 + @1 < @0)
+ B: (@0 + @1 <= @2) | (@2 + @1 <= @0)
+
+ If pointers are known not to wrap, B checks whether @1 bytes starting
+ at @0 and @2 do not overlap, while A tests the same thing for @1 + 1
+ bytes. A is more efficiently tested as:
+
+ A: (sizetype) (@0 + @1 - @2) > @1 * 2
+
+ The equivalent expression for B is given by replacing @1 with @1 - 1:
+
+ B: (sizetype) (@0 + (@1 - 1) - @2) > (@1 - 1) * 2
+
+ @0 and @2 can be swapped in both expressions without changing the result.
+
+ The folds rely on sizetype's being unsigned (which is always true)
+ and on its being the same width as the pointer (which we have to check).
+
+ The fold replaces two pointer_plus expressions, two comparisons and
+ an IOR with a pointer_plus, a pointer_diff, and a comparison, so in
+ the best case it's a saving of two operations. The A fold retains one
+ of the original pointer_pluses, so is a win even if both pointer_pluses
+ are used elsewhere. The B fold is a wash if both pointer_pluses are
+ used elsewhere, since all we end up doing is replacing a comparison with
+ a pointer_plus. We do still apply the fold under those circumstances
+ though, in case applying it to other conditions eventually makes one of the
+ pointer_pluses dead. */
+(for ior (truth_orif truth_or bit_ior)
+ (for cmp (le lt)
+ (simplify
+ (ior (cmp:cs (pointer_plus@3 @0 INTEGER_CST@1) @2)
+ (cmp:cs (pointer_plus@4 @2 @1) @0))
+ (if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))
+ && TYPE_OVERFLOW_WRAPS (sizetype)
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (sizetype))
+ /* Calculate the rhs constant. */
+ (with { offset_int off = wi::to_offset (@1) - (cmp == LE_EXPR ? 1 : 0);
+ offset_int rhs = off * 2; }
+ /* Always fails for negative values. */
+ (if (wi::min_precision (rhs, UNSIGNED) <= TYPE_PRECISION (sizetype))
+ /* Since the order of @0 and @2 doesn't matter, let tree_swap_operands_p
+ pick a canonical order. This increases the chances of using the
+ same pointer_plus in multiple checks. */
+ (with { bool swap_p = tree_swap_operands_p (@0, @2);
+ tree rhs_tree = wide_int_to_tree (sizetype, rhs); }
+ (if (cmp == LT_EXPR)
+ (gt (convert:sizetype
+ (pointer_diff:ssizetype { swap_p ? @4 : @3; }
+ { swap_p ? @0 : @2; }))
+ { rhs_tree; })
+ (gt (convert:sizetype
+ (pointer_diff:ssizetype
+ (pointer_plus { swap_p ? @2 : @0; }
+ { wide_int_to_tree (sizetype, off); })
+ { swap_p ? @0 : @2; }))
+ { rhs_tree; })))))))))
+
+/* Fold REDUC (@0 & @1) -> @0[I] & @1[I] if element I is the only nonzero
+ element of @1. */
+(for reduc (IFN_REDUC_PLUS IFN_REDUC_IOR IFN_REDUC_XOR)
+ (simplify (reduc (view_convert? (bit_and @0 VECTOR_CST@1)))
+ (with { int i = single_nonzero_element (@1); }
+ (if (i >= 0)
+ (with { tree elt = vector_cst_elt (@1, i);
+ tree elt_type = TREE_TYPE (elt);
+ unsigned int elt_bits = tree_to_uhwi (TYPE_SIZE (elt_type));
+ tree size = bitsize_int (elt_bits);
+ tree pos = bitsize_int (elt_bits * i); }
+ (view_convert
+ (bit_and:elt_type
+ (BIT_FIELD_REF:elt_type @0 { size; } { pos; })
+ { elt; })))))))
+
+/* Fold reduction of a single nonzero element constructor. */
+(for reduc (IFN_REDUC_PLUS IFN_REDUC_IOR IFN_REDUC_XOR)
+ (simplify (reduc (CONSTRUCTOR@0))
+ (with { tree ctor = (TREE_CODE (@0) == SSA_NAME
+ ? gimple_assign_rhs1 (SSA_NAME_DEF_STMT (@0)) : @0);
+ tree elt = ctor_single_nonzero_element (ctor); }
+ (if (elt
+ && !HONOR_SNANS (type)
+ && !HONOR_SIGNED_ZEROS (type))
+ { elt; }))))
+
+/* Fold REDUC (@0 op VECTOR_CST) as REDUC (@0) op REDUC (VECTOR_CST). */
+(for reduc (IFN_REDUC_PLUS IFN_REDUC_MAX IFN_REDUC_MIN IFN_REDUC_FMAX
+ IFN_REDUC_FMIN IFN_REDUC_AND IFN_REDUC_IOR IFN_REDUC_XOR)
+ op (plus max min IFN_FMAX IFN_FMIN bit_and bit_ior bit_xor)
+ (simplify (reduc (op @0 VECTOR_CST@1))
+ (op (reduc:type @0) (reduc:type @1))))
+
+(simplify
+ (vec_perm @0 @1 VECTOR_CST@2)
+ (with
+ {
+ tree op0 = @0, op1 = @1, op2 = @2;
+
+ /* Build a vector of integers from the tree mask. */
+ vec_perm_builder builder;
+ if (!tree_to_vec_perm_builder (&builder, op2))
+ return NULL_TREE;
+
+ /* Create a vec_perm_indices for the integer vector. */
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (type);
+ bool single_arg = (op0 == op1);
+ vec_perm_indices sel (builder, single_arg ? 1 : 2, nelts);
+ }
+ (if (sel.series_p (0, 1, 0, 1))
+ { op0; }
+ (if (sel.series_p (0, 1, nelts, 1))
+ { op1; }
+ (with
+ {
+ if (!single_arg)
+ {
+ if (sel.all_from_input_p (0))
+ op1 = op0;
+ else if (sel.all_from_input_p (1))
+ {
+ op0 = op1;
+ sel.rotate_inputs (1);
+ }
+ else if (known_ge (poly_uint64 (sel[0]), nelts))
+ {
+ std::swap (op0, op1);
+ sel.rotate_inputs (1);
+ }
+ }
+ gassign *def;
+ tree cop0 = op0, cop1 = op1;
+ if (TREE_CODE (op0) == SSA_NAME
+ && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0)))
+ && gimple_assign_rhs_code (def) == CONSTRUCTOR)
+ cop0 = gimple_assign_rhs1 (def);
+ if (TREE_CODE (op1) == SSA_NAME
+ && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op1)))
+ && gimple_assign_rhs_code (def) == CONSTRUCTOR)
+ cop1 = gimple_assign_rhs1 (def);
+
+ tree t;
+ }
+ (if ((TREE_CODE (cop0) == VECTOR_CST
+ || TREE_CODE (cop0) == CONSTRUCTOR)
+ && (TREE_CODE (cop1) == VECTOR_CST
+ || TREE_CODE (cop1) == CONSTRUCTOR)
+ && (t = fold_vec_perm (type, cop0, cop1, sel)))
+ { t; }
+ (with
+ {
+ bool changed = (op0 == op1 && !single_arg);
+ tree ins = NULL_TREE;
+ unsigned at = 0;
+
+ /* See if the permutation is performing a single element
+ insert from a CONSTRUCTOR or constant and use a BIT_INSERT_EXPR
+ in that case. But only if the vector mode is supported,
+ otherwise this is invalid GIMPLE. */
+ if (TYPE_MODE (type) != BLKmode
+ && (TREE_CODE (cop0) == VECTOR_CST
+ || TREE_CODE (cop0) == CONSTRUCTOR
+ || TREE_CODE (cop1) == VECTOR_CST
+ || TREE_CODE (cop1) == CONSTRUCTOR))
+ {
+ bool insert_first_p = sel.series_p (1, 1, nelts + 1, 1);
+ if (insert_first_p)
+ {
+ /* After canonicalizing the first elt to come from the
+ first vector we only can insert the first elt from
+ the first vector. */
+ at = 0;
+ if ((ins = fold_read_from_vector (cop0, sel[0])))
+ op0 = op1;
+ }
+ /* The above can fail for two-element vectors which always
+ appear to insert the first element, so try inserting
+ into the second lane as well. For more than two
+ elements that's wasted time. */
+ if (!insert_first_p || (!ins && maybe_eq (nelts, 2u)))
+ {
+ unsigned int encoded_nelts = sel.encoding ().encoded_nelts ();
+ for (at = 0; at < encoded_nelts; ++at)
+ if (maybe_ne (sel[at], at))
+ break;
+ if (at < encoded_nelts
+ && (known_eq (at + 1, nelts)
+ || sel.series_p (at + 1, 1, at + 1, 1)))
+ {
+ if (known_lt (poly_uint64 (sel[at]), nelts))
+ ins = fold_read_from_vector (cop0, sel[at]);
+ else
+ ins = fold_read_from_vector (cop1, sel[at] - nelts);
+ }
+ }
+ }
+
+ /* Generate a canonical form of the selector. */
+ if (!ins && sel.encoding () != builder)
+ {
+ /* Some targets are deficient and fail to expand a single
+ argument permutation while still allowing an equivalent
+ 2-argument version. */
+ tree oldop2 = op2;
+ if (sel.ninputs () == 2
+ || can_vec_perm_const_p (TYPE_MODE (type), sel, false))
+ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
+ else
+ {
+ vec_perm_indices sel2 (builder, 2, nelts);
+ if (can_vec_perm_const_p (TYPE_MODE (type), sel2, false))
+ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel2);
+ else
+ /* Not directly supported with either encoding,
+ so use the preferred form. */
+ op2 = vec_perm_indices_to_tree (TREE_TYPE (op2), sel);
+ }
+ if (!operand_equal_p (op2, oldop2, 0))
+ changed = true;
+ }
+ }
+ (if (ins)
+ (bit_insert { op0; } { ins; }
+ { bitsize_int (at * vector_element_bits (type)); })
+ (if (changed)
+ (vec_perm { op0; } { op1; } { op2; }))))))))))
+
+/* VEC_PERM_EXPR (v, v, mask) -> v where v contains same element. */
+
+(match vec_same_elem_p
+ (vec_duplicate @0))
+
+(match vec_same_elem_p
+ CONSTRUCTOR@0
+ (if (TREE_CODE (@0) == SSA_NAME
+ && uniform_vector_p (gimple_assign_rhs1 (SSA_NAME_DEF_STMT (@0))))))
+
+(match vec_same_elem_p
+ @0
+ (if (uniform_vector_p (@0))))
+
+
+(simplify
+ (vec_perm vec_same_elem_p@0 @0 @1)
+ @0)
+
+/* Push VEC_PERM earlier if that may help FMA perception (PR101895). */
+(simplify
+ (plus:c (vec_perm:s (mult:c@0 @1 vec_same_elem_p@2) @0 @3) @4)
+ (if (TREE_CODE (@0) == SSA_NAME && num_imm_uses (@0) == 2)
+ (plus (mult (vec_perm @1 @1 @3) @2) @4)))
+(simplify
+ (minus (vec_perm:s (mult:c@0 @1 vec_same_elem_p@2) @0 @3) @4)
+ (if (TREE_CODE (@0) == SSA_NAME && num_imm_uses (@0) == 2)
+ (minus (mult (vec_perm @1 @1 @3) @2) @4)))
+
+
+/* Match count trailing zeroes for simplify_count_trailing_zeroes in fwprop.
+ The canonical form is array[((x & -x) * C) >> SHIFT] where C is a magic
+ constant which when multiplied by a power of 2 contains a unique value
+ in the top 5 or 6 bits. This is then indexed into a table which maps it
+ to the number of trailing zeroes. */
+(match (ctz_table_index @1 @2 @3)
+ (rshift (mult (bit_and:c (negate @1) @1) INTEGER_CST@2) INTEGER_CST@3))
+
+(match (cond_expr_convert_p @0 @2 @3 @6)
+ (cond (simple_comparison@6 @0 @1) (convert@4 @2) (convert@5 @3))
+ (if (INTEGRAL_TYPE_P (type)
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@3))
+ && TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (@0))
+ && TYPE_PRECISION (TREE_TYPE (@0))
+ == TYPE_PRECISION (TREE_TYPE (@2))
+ && TYPE_PRECISION (TREE_TYPE (@0))
+ == TYPE_PRECISION (TREE_TYPE (@3))
+ /* For vect_recog_cond_expr_convert_pattern, @2 and @3 can differ in
+ signess when convert is truncation, but not ok for extension since
+ it's sign_extend vs zero_extend. */
+ && (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type)
+ || (TYPE_UNSIGNED (TREE_TYPE (@2))
+ == TYPE_UNSIGNED (TREE_TYPE (@3))))
+ && single_use (@4)
+ && single_use (@5))))
diff --git a/support/cpp/gcc/mem-stats-traits.h b/support/cpp/gcc/mem-stats-traits.h
new file mode 100644
index 000000000..40df2ac18
--- /dev/null
+++ b/support/cpp/gcc/mem-stats-traits.h
@@ -0,0 +1,41 @@
+/* A memory statistics traits.
+ Copyright (C) 2015-2022 Free Software Foundation, Inc.
+ Contributed by Martin Liska <mliska@suse.cz>
+
+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_MEM_STATS_TRAITS_H
+#define GCC_MEM_STATS_TRAITS_H
+
+/* Memory allocation origin. */
+enum mem_alloc_origin
+{
+ HASH_TABLE_ORIGIN,
+ HASH_MAP_ORIGIN,
+ HASH_SET_ORIGIN,
+ VEC_ORIGIN,
+ BITMAP_ORIGIN,
+ GGC_ORIGIN,
+ ALLOC_POOL_ORIGIN,
+ MEM_ALLOC_ORIGIN_LENGTH
+};
+
+/* Verbose names of the memory allocation origin. */
+static const char * mem_alloc_origin_names[] = { "Hash tables", "Hash maps",
+ "Hash sets", "Heap vectors", "Bitmaps", "GGC memory", "Allocation pool" };
+
+#endif // GCC_MEM_STATS_TRAITS_H
diff --git a/support/cpp/gcc/mem-stats.h b/support/cpp/gcc/mem-stats.h
new file mode 100644
index 000000000..35ceb984d
--- /dev/null
+++ b/support/cpp/gcc/mem-stats.h
@@ -0,0 +1,658 @@
+/* A memory statistics tracking infrastructure.
+ Copyright (C) 2015-2022 Free Software Foundation, Inc.
+ Contributed by Martin Liska <mliska@suse.cz>
+
+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_MEM_STATS_H
+#define GCC_MEM_STATS_H
+
+/* Forward declaration. */
+template<typename Key, typename Value,
+ typename Traits = simple_hashmap_traits<default_hash_traits<Key>,
+ Value> >
+class hash_map;
+
+#define LOCATION_LINE_EXTRA_SPACE 30
+#define LOCATION_LINE_WIDTH 48
+
+/* Memory allocation location. */
+class mem_location
+{
+public:
+ /* Default constructor. */
+ inline
+ mem_location () {}
+
+ /* Constructor. */
+ inline
+ mem_location (mem_alloc_origin origin, bool ggc,
+ const char *filename = NULL, int line = 0,
+ const char *function = NULL):
+ m_filename (filename), m_function (function), m_line (line), m_origin
+ (origin), m_ggc (ggc) {}
+
+ /* Copy constructor. */
+ inline
+ mem_location (mem_location &other): m_filename (other.m_filename),
+ m_function (other.m_function), m_line (other.m_line),
+ m_origin (other.m_origin), m_ggc (other.m_ggc) {}
+
+ /* Compute hash value based on file name, function name and line in
+ source code. As there is just a single pointer registered for every
+ constant that points to e.g. the same file name, we can use hash
+ of the pointer. */
+ hashval_t
+ hash ()
+ {
+ inchash::hash hash;
+
+ hash.add_ptr (m_filename);
+ hash.add_ptr (m_function);
+ hash.add_int (m_line);
+
+ return hash.end ();
+ }
+
+ /* Return true if the memory location is equal to OTHER. */
+ int
+ equal (const mem_location &other)
+ {
+ return m_filename == other.m_filename && m_function == other.m_function
+ && m_line == other.m_line;
+ }
+
+ /* Return trimmed filename for the location. */
+ inline const char *
+ get_trimmed_filename ()
+ {
+ const char *s1 = m_filename;
+ const char *s2;
+
+ while ((s2 = strstr (s1, "gcc/")))
+ s1 = s2 + 4;
+
+ return s1;
+ }
+
+ inline char *
+ to_string ()
+ {
+ unsigned l = strlen (get_trimmed_filename ()) + strlen (m_function)
+ + LOCATION_LINE_EXTRA_SPACE;
+
+ char *s = XNEWVEC (char, l);
+ sprintf (s, "%s:%i (%s)", get_trimmed_filename (),
+ m_line, m_function);
+
+ s[MIN (LOCATION_LINE_WIDTH, l - 1)] = '\0';
+
+ return s;
+ }
+
+ /* Return display name associated to ORIGIN type. */
+ static const char *
+ get_origin_name (mem_alloc_origin origin)
+ {
+ return mem_alloc_origin_names[(unsigned) origin];
+ }
+
+ /* File name of source code. */
+ const char *m_filename;
+ /* Funcation name. */
+ const char *m_function;
+ /* Line number in source code. */
+ int m_line;
+ /* Origin type. */
+ mem_alloc_origin m_origin;
+ /* Flag if used by GGC allocation. */
+ bool m_ggc;
+};
+
+/* Memory usage register to a memory location. */
+class mem_usage
+{
+public:
+ /* Default constructor. */
+ mem_usage (): m_allocated (0), m_times (0), m_peak (0), m_instances (1) {}
+
+ /* Constructor. */
+ mem_usage (size_t allocated, size_t times, size_t peak, size_t instances = 0):
+ m_allocated (allocated), m_times (times), m_peak (peak),
+ m_instances (instances) {}
+
+ /* Register overhead of SIZE bytes. */
+ inline void
+ register_overhead (size_t size)
+ {
+ m_allocated += size;
+ m_times++;
+
+ if (m_peak < m_allocated)
+ m_peak = m_allocated;
+ }
+
+ /* Release overhead of SIZE bytes. */
+ inline void
+ release_overhead (size_t size)
+ {
+ gcc_assert (size <= m_allocated);
+
+ m_allocated -= size;
+ }
+
+ /* Sum the usage with SECOND usage. */
+ mem_usage
+ operator+ (const mem_usage &second)
+ {
+ return mem_usage (m_allocated + second.m_allocated,
+ m_times + second.m_times,
+ m_peak + second.m_peak,
+ m_instances + second.m_instances);
+ }
+
+ /* Equality operator. */
+ inline bool
+ operator== (const mem_usage &second) const
+ {
+ return (m_allocated == second.m_allocated
+ && m_peak == second.m_peak
+ && m_times == second.m_times);
+ }
+
+ /* Comparison operator. */
+ inline bool
+ operator< (const mem_usage &second) const
+ {
+ if (*this == second)
+ return false;
+
+ return (m_allocated == second.m_allocated ?
+ (m_peak == second.m_peak ? m_times < second.m_times
+ : m_peak < second.m_peak) : m_allocated < second.m_allocated);
+ }
+
+ /* Compare wrapper used by qsort method. */
+ static int
+ compare (const void *first, const void *second)
+ {
+ typedef std::pair<mem_location *, mem_usage *> mem_pair_t;
+
+ const mem_pair_t f = *(const mem_pair_t *)first;
+ const mem_pair_t s = *(const mem_pair_t *)second;
+
+ if (*f.second == *s.second)
+ return 0;
+
+ return *f.second < *s.second ? 1 : -1;
+ }
+
+ /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
+ inline void
+ dump (mem_location *loc, const mem_usage &total) const
+ {
+ char *location_string = loc->to_string ();
+
+ fprintf (stderr, "%-48s " PRsa (9) ":%5.1f%%"
+ PRsa (9) PRsa (9) ":%5.1f%%%10s\n",
+ location_string, SIZE_AMOUNT (m_allocated),
+ get_percent (m_allocated, total.m_allocated),
+ SIZE_AMOUNT (m_peak), SIZE_AMOUNT (m_times),
+ get_percent (m_times, total.m_times), loc->m_ggc ? "ggc" : "heap");
+
+ free (location_string);
+ }
+
+ /* Dump footer. */
+ inline void
+ dump_footer () const
+ {
+ fprintf (stderr, "%s" PRsa (53) PRsa (26) "\n", "Total",
+ SIZE_AMOUNT (m_allocated), SIZE_AMOUNT (m_times));
+ }
+
+ /* Return fraction of NOMINATOR and DENOMINATOR in percent. */
+ static inline float
+ get_percent (size_t nominator, size_t denominator)
+ {
+ return denominator == 0 ? 0.0f : nominator * 100.0 / denominator;
+ }
+
+ /* Print line made of dashes. */
+ static inline void
+ print_dash_line (size_t count = 140)
+ {
+ while (count--)
+ fputc ('-', stderr);
+ fputc ('\n', stderr);
+ }
+
+ /* Dump header with NAME. */
+ static inline void
+ dump_header (const char *name)
+ {
+ fprintf (stderr, "%-48s %11s%16s%10s%17s\n", name, "Leak", "Peak",
+ "Times", "Type");
+ }
+
+ /* Current number of allocated bytes. */
+ size_t m_allocated;
+ /* Number of allocations. */
+ size_t m_times;
+ /* Peak allocation in bytes. */
+ size_t m_peak;
+ /* Number of container instances. */
+ size_t m_instances;
+};
+
+/* Memory usage pair that connectes memory usage and number
+ of allocated bytes. */
+template <class T>
+class mem_usage_pair
+{
+public:
+ mem_usage_pair (T *usage_, size_t allocated_): usage (usage_),
+ allocated (allocated_) {}
+
+ T *usage;
+ size_t allocated;
+};
+
+/* Memory allocation description. */
+template <class T>
+class mem_alloc_description
+{
+public:
+ struct mem_location_hash : nofree_ptr_hash <mem_location>
+ {
+ static hashval_t
+ hash (value_type l)
+ {
+ inchash::hash hstate;
+
+ hstate.add_ptr ((const void *)l->m_filename);
+ hstate.add_ptr (l->m_function);
+ hstate.add_int (l->m_line);
+
+ return hstate.end ();
+ }
+
+ static bool
+ equal (value_type l1, value_type l2)
+ {
+ return (l1->m_filename == l2->m_filename
+ && l1->m_function == l2->m_function
+ && l1->m_line == l2->m_line);
+ }
+ };
+
+ /* Internal class type definitions. */
+ typedef hash_map <mem_location_hash, T *> mem_map_t;
+ typedef hash_map <const void *, mem_usage_pair<T> > reverse_mem_map_t;
+ typedef hash_map <const void *, std::pair<T *, size_t> > reverse_object_map_t;
+ typedef std::pair <mem_location *, T *> mem_list_t;
+
+ /* Default contructor. */
+ mem_alloc_description ();
+
+ /* Default destructor. */
+ ~mem_alloc_description ();
+
+ /* Returns true if instance PTR is registered by the memory description. */
+ bool contains_descriptor_for_instance (const void *ptr);
+
+ /* Return descriptor for instance PTR. */
+ T *get_descriptor_for_instance (const void *ptr);
+
+ /* Register memory allocation descriptor for container PTR which is
+ described by a memory LOCATION. */
+ T *register_descriptor (const void *ptr, mem_location *location);
+
+ /* Register memory allocation descriptor for container PTR. ORIGIN identifies
+ type of container and GGC identifes if the allocation is handled in GGC
+ memory. Each location is identified by file NAME, LINE in source code and
+ FUNCTION name. */
+ T *register_descriptor (const void *ptr, mem_alloc_origin origin,
+ bool ggc, const char *name, int line,
+ const char *function);
+
+ /* Register instance overhead identified by PTR pointer. Allocation takes
+ SIZE bytes. */
+ T *register_instance_overhead (size_t size, const void *ptr);
+
+ /* For containers (and GGC) where we want to track every instance object,
+ we register allocation of SIZE bytes, identified by PTR pointer, belonging
+ to USAGE descriptor. */
+ void register_object_overhead (T *usage, size_t size, const void *ptr);
+
+ /* Release PTR pointer of SIZE bytes. If REMOVE_FROM_MAP is set to true,
+ remove the instance from reverse map. Return memory usage that belongs
+ to this memory description. */
+ T *release_instance_overhead (void *ptr, size_t size,
+ bool remove_from_map = false);
+
+ /* Release instance object identified by PTR pointer. */
+ void release_object_overhead (void *ptr);
+
+ /* Unregister a memory allocation descriptor registered with
+ register_descriptor (remove from reverse map), unless it is
+ unregistered through release_instance_overhead with
+ REMOVE_FROM_MAP = true. */
+ void unregister_descriptor (void *ptr);
+
+ /* Get sum value for ORIGIN type of allocation for the descriptor. */
+ T get_sum (mem_alloc_origin origin);
+
+ /* Get all tracked instances registered by the description. Items
+ are filtered by ORIGIN type, LENGTH is return value where we register
+ the number of elements in the list. If we want to process custom order,
+ CMP comparator can be provided. */
+ mem_list_t *get_list (mem_alloc_origin origin, unsigned *length);
+
+ /* Dump all tracked instances of type ORIGIN. If we want to process custom
+ order, CMP comparator can be provided. */
+ void dump (mem_alloc_origin origin);
+
+ /* Reverse object map used for every object allocation mapping. */
+ reverse_object_map_t *m_reverse_object_map;
+
+private:
+ /* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
+ in NAME source file, at LINE in source code, in FUNCTION. */
+ T *register_overhead (size_t size, mem_alloc_origin origin, const char *name,
+ int line, const char *function, const void *ptr);
+
+ /* Allocation location coupled to the description. */
+ mem_location m_location;
+
+ /* Location to usage mapping. */
+ mem_map_t *m_map;
+
+ /* Reverse pointer to usage mapping. */
+ reverse_mem_map_t *m_reverse_map;
+};
+
+/* Returns true if instance PTR is registered by the memory description. */
+
+template <class T>
+inline bool
+mem_alloc_description<T>::contains_descriptor_for_instance (const void *ptr)
+{
+ return m_reverse_map->get (ptr);
+}
+
+/* Return descriptor for instance PTR. */
+
+template <class T>
+inline T*
+mem_alloc_description<T>::get_descriptor_for_instance (const void *ptr)
+{
+ return m_reverse_map->get (ptr) ? (*m_reverse_map->get (ptr)).usage : NULL;
+}
+
+/* Register memory allocation descriptor for container PTR which is
+ described by a memory LOCATION. */
+
+template <class T>
+inline T*
+mem_alloc_description<T>::register_descriptor (const void *ptr,
+ mem_location *location)
+{
+ T *usage = NULL;
+
+ T **slot = m_map->get (location);
+ if (slot)
+ {
+ delete location;
+ usage = *slot;
+ usage->m_instances++;
+ }
+ else
+ {
+ usage = new T ();
+ m_map->put (location, usage);
+ }
+
+ if (!m_reverse_map->get (ptr))
+ m_reverse_map->put (ptr, mem_usage_pair<T> (usage, 0));
+
+ return usage;
+}
+
+/* Register memory allocation descriptor for container PTR. ORIGIN identifies
+ type of container and GGC identifes if the allocation is handled in GGC
+ memory. Each location is identified by file NAME, LINE in source code and
+ FUNCTION name. */
+
+template <class T>
+inline T*
+mem_alloc_description<T>::register_descriptor (const void *ptr,
+ mem_alloc_origin origin,
+ bool ggc,
+ const char *filename,
+ int line,
+ const char *function)
+{
+ mem_location *l = new mem_location (origin, ggc, filename, line, function);
+ return register_descriptor (ptr, l);
+}
+
+/* Register instance overhead identified by PTR pointer. Allocation takes
+ SIZE bytes. */
+
+template <class T>
+inline T*
+mem_alloc_description<T>::register_instance_overhead (size_t size,
+ const void *ptr)
+{
+ mem_usage_pair <T> *slot = m_reverse_map->get (ptr);
+ if (!slot)
+ {
+ /* Due to PCH, it can really happen. */
+ return NULL;
+ }
+
+ T *usage = (*slot).usage;
+ usage->register_overhead (size);
+
+ return usage;
+}
+
+/* For containers (and GGC) where we want to track every instance object,
+ we register allocation of SIZE bytes, identified by PTR pointer, belonging
+ to USAGE descriptor. */
+
+template <class T>
+void
+mem_alloc_description<T>::register_object_overhead (T *usage, size_t size,
+ const void *ptr)
+{
+ /* In case of GGC, it is possible to have already occupied the memory
+ location. */
+ m_reverse_object_map->put (ptr, std::pair<T *, size_t> (usage, size));
+}
+
+/* Register overhead of SIZE bytes of ORIGIN type. PTR pointer is allocated
+ in NAME source file, at LINE in source code, in FUNCTION. */
+
+template <class T>
+inline T*
+mem_alloc_description<T>::register_overhead (size_t size,
+ mem_alloc_origin origin,
+ const char *filename,
+ int line,
+ const char *function,
+ const void *ptr)
+{
+ T *usage = register_descriptor (ptr, origin, filename, line, function);
+ usage->register_overhead (size);
+
+ return usage;
+}
+
+/* Release PTR pointer of SIZE bytes. */
+
+template <class T>
+inline T *
+mem_alloc_description<T>::release_instance_overhead (void *ptr, size_t size,
+ bool remove_from_map)
+{
+ mem_usage_pair<T> *slot = m_reverse_map->get (ptr);
+
+ if (!slot)
+ {
+ /* Due to PCH, it can really happen. */
+ return NULL;
+ }
+
+ T *usage = (*slot).usage;
+ usage->release_overhead (size);
+
+ if (remove_from_map)
+ m_reverse_map->remove (ptr);
+
+ return usage;
+}
+
+/* Release instance object identified by PTR pointer. */
+
+template <class T>
+inline void
+mem_alloc_description<T>::release_object_overhead (void *ptr)
+{
+ std::pair <T *, size_t> *entry = m_reverse_object_map->get (ptr);
+ entry->first->release_overhead (entry->second);
+ m_reverse_object_map->remove (ptr);
+}
+
+/* Unregister a memory allocation descriptor registered with
+ register_descriptor (remove from reverse map), unless it is
+ unregistered through release_instance_overhead with
+ REMOVE_FROM_MAP = true. */
+template <class T>
+inline void
+mem_alloc_description<T>::unregister_descriptor (void *ptr)
+{
+ m_reverse_map->remove (ptr);
+}
+
+/* Default contructor. */
+
+template <class T>
+inline
+mem_alloc_description<T>::mem_alloc_description ()
+{
+ m_map = new mem_map_t (13, false, false, false);
+ m_reverse_map = new reverse_mem_map_t (13, false, false, false);
+ m_reverse_object_map = new reverse_object_map_t (13, false, false, false);
+}
+
+/* Default destructor. */
+
+template <class T>
+inline
+mem_alloc_description<T>::~mem_alloc_description ()
+{
+ for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
+ ++it)
+ {
+ delete (*it).first;
+ delete (*it).second;
+ }
+
+ delete m_map;
+ delete m_reverse_map;
+ delete m_reverse_object_map;
+}
+
+/* Get all tracked instances registered by the description. Items are filtered
+ by ORIGIN type, LENGTH is return value where we register the number of
+ elements in the list. If we want to process custom order, CMP comparator
+ can be provided. */
+
+template <class T>
+inline
+typename mem_alloc_description<T>::mem_list_t *
+mem_alloc_description<T>::get_list (mem_alloc_origin origin, unsigned *length)
+{
+ /* vec data structure is not used because all vectors generate memory
+ allocation info a it would create a cycle. */
+ size_t element_size = sizeof (mem_list_t);
+ mem_list_t *list = XCNEWVEC (mem_list_t, m_map->elements ());
+ unsigned i = 0;
+
+ for (typename mem_map_t::iterator it = m_map->begin (); it != m_map->end ();
+ ++it)
+ if ((*it).first->m_origin == origin)
+ list[i++] = std::pair<mem_location*, T*> (*it);
+
+ qsort (list, i, element_size, T::compare);
+ *length = i;
+
+ return list;
+}
+
+/* Get sum value for ORIGIN type of allocation for the descriptor. */
+
+template <class T>
+inline T
+mem_alloc_description<T>::get_sum (mem_alloc_origin origin)
+{
+ unsigned length;
+ mem_list_t *list = get_list (origin, &length);
+ T sum;
+
+ for (unsigned i = 0; i < length; i++)
+ sum = sum + *list[i].second;
+
+ XDELETEVEC (list);
+
+ return sum;
+}
+
+/* Dump all tracked instances of type ORIGIN. If we want to process custom
+ order, CMP comparator can be provided. */
+
+template <class T>
+inline void
+mem_alloc_description<T>::dump (mem_alloc_origin origin)
+{
+ unsigned length;
+
+ fprintf (stderr, "\n");
+
+ mem_list_t *list = get_list (origin, &length);
+ T total = get_sum (origin);
+
+ T::print_dash_line ();
+ T::dump_header (mem_location::get_origin_name (origin));
+ T::print_dash_line ();
+ for (int i = length - 1; i >= 0; i--)
+ list[i].second->dump (list[i].first, total);
+ T::print_dash_line ();
+
+ T::dump_header (mem_location::get_origin_name (origin));
+ T::print_dash_line ();
+ total.dump_footer ();
+ T::print_dash_line ();
+
+ XDELETEVEC (list);
+
+ fprintf (stderr, "\n");
+}
+
+#endif // GCC_MEM_STATS_H
diff --git a/support/cpp/gcc/memmodel.h b/support/cpp/gcc/memmodel.h
new file mode 100644
index 000000000..01ac7aab8
--- /dev/null
+++ b/support/cpp/gcc/memmodel.h
@@ -0,0 +1,116 @@
+/* Prototypes of memory model helper functions.
+ 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/>. */
+
+#ifndef GCC_MEMMODEL_H
+#define GCC_MEMMODEL_H
+
+/* Suppose that higher bits are target dependent. */
+#define MEMMODEL_MASK ((1<<16)-1)
+
+/* Legacy sync operations set this upper flag in the memory model. This allows
+ targets that need to do something stronger for sync operations to
+ differentiate with their target patterns and issue a more appropriate insn
+ sequence. See bugzilla 65697 for background. */
+#define MEMMODEL_SYNC (1<<15)
+
+/* Memory model without SYNC bit for targets/operations that do not care. */
+#define MEMMODEL_BASE_MASK (MEMMODEL_SYNC-1)
+
+/* Memory model types for the __atomic* builtins.
+ This must match the order in libstdc++-v3/include/bits/atomic_base.h. */
+enum memmodel
+{
+ MEMMODEL_RELAXED = 0,
+ MEMMODEL_CONSUME = 1,
+ MEMMODEL_ACQUIRE = 2,
+ MEMMODEL_RELEASE = 3,
+ MEMMODEL_ACQ_REL = 4,
+ MEMMODEL_SEQ_CST = 5,
+ MEMMODEL_LAST = 6,
+ MEMMODEL_SYNC_ACQUIRE = MEMMODEL_ACQUIRE | MEMMODEL_SYNC,
+ MEMMODEL_SYNC_RELEASE = MEMMODEL_RELEASE | MEMMODEL_SYNC,
+ MEMMODEL_SYNC_SEQ_CST = MEMMODEL_SEQ_CST | MEMMODEL_SYNC,
+ /* Say that all the higher bits are valid target extensions. */
+ MEMMODEL_MAX = INTTYPE_MAXIMUM (int)
+};
+
+/* Return the memory model from a host integer. */
+static inline enum memmodel
+memmodel_from_int (unsigned HOST_WIDE_INT val)
+{
+ return (enum memmodel) (val & MEMMODEL_MASK);
+}
+
+/* Return the base memory model from a host integer. */
+static inline enum memmodel
+memmodel_base (unsigned HOST_WIDE_INT val)
+{
+ return (enum memmodel) (val & MEMMODEL_BASE_MASK);
+}
+
+/* Return TRUE if the memory model is RELAXED. */
+static inline bool
+is_mm_relaxed (enum memmodel model)
+{
+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELAXED;
+}
+
+/* Return TRUE if the memory model is CONSUME. */
+static inline bool
+is_mm_consume (enum memmodel model)
+{
+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_CONSUME;
+}
+
+/* Return TRUE if the memory model is ACQUIRE. */
+static inline bool
+is_mm_acquire (enum memmodel model)
+{
+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQUIRE;
+}
+
+/* Return TRUE if the memory model is RELEASE. */
+static inline bool
+is_mm_release (enum memmodel model)
+{
+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_RELEASE;
+}
+
+/* Return TRUE if the memory model is ACQ_REL. */
+static inline bool
+is_mm_acq_rel (enum memmodel model)
+{
+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_ACQ_REL;
+}
+
+/* Return TRUE if the memory model is SEQ_CST. */
+static inline bool
+is_mm_seq_cst (enum memmodel model)
+{
+ return (model & MEMMODEL_BASE_MASK) == MEMMODEL_SEQ_CST;
+}
+
+/* Return TRUE if the memory model is a SYNC variant. */
+static inline bool
+is_mm_sync (enum memmodel model)
+{
+ return (model & MEMMODEL_SYNC);
+}
+
+#endif /* GCC_MEMMODEL_H */
diff --git a/support/cpp/gcc/memory-block.cc b/support/cpp/gcc/memory-block.cc
new file mode 100644
index 000000000..3aa68e34d
--- /dev/null
+++ b/support/cpp/gcc/memory-block.cc
@@ -0,0 +1,86 @@
+/* Shared pool of memory blocks for pool allocators.
+ Copyright (C) 2015-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 "memory-block.h"
+#include "obstack.h"
+
+/* Global singleton-like instance. */
+memory_block_pool memory_block_pool::instance;
+
+memory_block_pool::memory_block_pool () : m_blocks (NULL) {}
+
+/* Reduce free list to NUM blocks and return remaining to malloc. */
+void
+memory_block_pool::reduce_free_list (int num)
+{
+ block_list **blocks = &m_blocks;
+
+ /* First skip NUM blocks. */
+
+ for (;num > 0 && *blocks; num--)
+ blocks = &(*blocks)->m_next;
+
+ if (!*blocks)
+ return;
+
+ /* And free the remainder of them. */
+
+ block_list *to_free = *blocks;
+ *blocks = NULL;
+
+ while (to_free)
+ {
+ block_list *next = to_free->m_next;
+ XDELETEVEC (to_free);
+ to_free = next;
+ }
+}
+
+/* Allocate a chunk for obstack. Use the pool if requested chunk size matches
+ the size of blocks in the pool. */
+void *
+mempool_obstack_chunk_alloc (size_t size)
+{
+ if (size == memory_block_pool::block_size)
+ return memory_block_pool::allocate ();
+ else
+ return XNEWVEC (char, size);
+}
+
+/* Free previously allocated obstack chunk. */
+void
+mempool_obstack_chunk_free (void *chunk)
+{
+ size_t size = (reinterpret_cast<_obstack_chunk *> (chunk)->limit
+ - reinterpret_cast<char *> (chunk));
+ if (size == memory_block_pool::block_size)
+ memory_block_pool::release (chunk);
+ else
+ XDELETEVEC (chunk);
+}
+
+/* Return allocated memory back to malloc (and to system). */
+void
+memory_block_pool::trim (int num)
+{
+ instance.reduce_free_list (num);
+}
diff --git a/support/cpp/gcc/memory-block.h b/support/cpp/gcc/memory-block.h
new file mode 100644
index 000000000..2b6ec1e38
--- /dev/null
+++ b/support/cpp/gcc/memory-block.h
@@ -0,0 +1,84 @@
+/* Shared pool of memory blocks for pool allocators.
+ Copyright (C) 2015-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 MEMORY_BLOCK_H
+#define MEMORY_BLOCK_H
+
+/* Shared pool which allows other memory pools to reuse each others' allocated
+ memory blocks instead of calling free/malloc again. */
+class memory_block_pool
+{
+public:
+ /* Blocks have fixed size. This is necessary for sharing. */
+ static const size_t block_size = 64 * 1024;
+ /* Number of blocks we keep in the freelists. */
+ static const size_t freelist_size = 1024 * 1024 / block_size;
+
+ memory_block_pool ();
+
+ static inline void *allocate () ATTRIBUTE_MALLOC;
+ static inline void release (void *);
+ static void trim (int nblocks = freelist_size);
+ void reduce_free_list (int);
+
+private:
+ /* memory_block_pool singleton instance, defined in memory-block.cc. */
+ static memory_block_pool instance;
+
+ struct block_list
+ {
+ block_list *m_next;
+ };
+
+ /* Free list. */
+ block_list *m_blocks;
+};
+
+/* Allocate a single block. Reuse a previously returned block, if possible. */
+inline void *
+memory_block_pool::allocate ()
+{
+ if (instance.m_blocks == NULL)
+ return XNEWVEC (char, block_size);
+
+ void *result = instance.m_blocks;
+ instance.m_blocks = instance.m_blocks->m_next;
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (result, block_size));
+ return result;
+}
+
+/* Return UNCAST_BLOCK to the pool. */
+inline void
+memory_block_pool::release (void *uncast_block)
+{
+ block_list *block = new (uncast_block) block_list;
+ block->m_next = instance.m_blocks;
+ instance.m_blocks = block;
+
+ VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)uncast_block
+ + sizeof (block_list),
+ block_size
+ - sizeof (block_list)));
+}
+
+extern void *mempool_obstack_chunk_alloc (size_t) ATTRIBUTE_MALLOC;
+extern void mempool_obstack_chunk_free (void *);
+
+#endif /* MEMORY_BLOCK_H */
diff --git a/support/cpp/gcc/min-insn-modes.cc b/support/cpp/gcc/min-insn-modes.cc
new file mode 100644
index 000000000..13544c1e7
--- /dev/null
+++ b/support/cpp/gcc/min-insn-modes.cc
@@ -0,0 +1,53 @@
+/* Generated automatically from machmode.def and config/i386/i386-modes.def
+ by genmodes. */
+
+#include "bconfig.h"
+#include "system.h"
+#include "coretypes.h"
+
+const char *const mode_name[NUM_MACHINE_MODES] =
+{
+ "VOID",
+ "BLK",
+// "CC",
+// "CCGC",
+// "CCGOC",
+};
+
+const unsigned char mode_class[NUM_MACHINE_MODES] =
+{
+ MODE_RANDOM, /* VOID */
+ MODE_RANDOM, /* BLK */
+};
+
+#if 0 // sdcpp
+const poly_uint16_pod mode_nunits[NUM_MACHINE_MODES] =
+{
+ { 0 }, /* VOID */
+ { 0 }, /* BLK */
+};
+#endif
+
+const unsigned char mode_wider[NUM_MACHINE_MODES] =
+{
+ E_VOIDmode, /* VOID */
+ E_VOIDmode, /* BLK */
+};
+
+const unsigned char mode_2xwider[NUM_MACHINE_MODES] =
+{
+ E_VOIDmode, /* VOID */
+ E_BLKmode, /* BLK */
+};
+
+const unsigned char mode_inner[NUM_MACHINE_MODES] =
+{
+ E_VOIDmode, /* VOID */
+ E_BLKmode, /* BLK */
+};
+
+const unsigned char class_narrowest_mode[MAX_MODE_CLASS] =
+{
+ MODE_RANDOM, /* VOID */
+ MODE_CC, /* CC */
+};
diff --git a/support/cpp/gcc/mkconfig.sh b/support/cpp/gcc/mkconfig.sh
new file mode 100644
index 000000000..91cc43f69
--- /dev/null
+++ b/support/cpp/gcc/mkconfig.sh
@@ -0,0 +1,125 @@
+#! /bin/sh
+
+# Copyright (C) 2001-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/>.
+
+
+# Generate gcc's various configuration headers:
+# config.h, tconfig.h, bconfig.h, tm.h, libgcc_tm.h, and tm_p.h.
+# $1 is the file to generate. DEFINES, HEADERS, and possibly
+# TARGET_CPU_DEFAULT are expected to be set in the environment.
+
+if [ -z "$1" ]; then
+ echo "Usage: DEFINES='list' HEADERS='list' \\" >&2
+ echo " [TARGET_CPU_DEFAULT='default'] mkconfig.sh FILE" >&2
+ exit 1
+fi
+
+output=$1
+rm -f ${output}T
+
+# This converts a file name into header guard macro format.
+hg_sed_expr='y,abcdefghijklmnopqrstuvwxyz./,ABCDEFGHIJKLMNOPQRSTUVWXYZ__,'
+header_guard=GCC_`echo ${output} | sed -e ${hg_sed_expr}`
+
+# Add multiple inclusion protection guard, part one.
+echo "#ifndef ${header_guard}" >> ${output}T
+echo "#define ${header_guard}" >> ${output}T
+
+# A special test to ensure that build-time files don't blindly use
+# config.h.
+if test x"$output" = x"config.h"; then
+ echo "#ifdef GENERATOR_FILE" >> ${output}T
+ echo "#error config.h is for the host, not build, machine." >> ${output}T
+ echo "#endif" >> ${output}T
+fi
+
+# Define TARGET_CPU_DEFAULT if the system wants one.
+# This substitutes for lots of *.h files.
+if [ "$TARGET_CPU_DEFAULT" != "" ]; then
+ echo "#define TARGET_CPU_DEFAULT ($TARGET_CPU_DEFAULT)" >> ${output}T
+fi
+
+# Provide defines for other macros set in config.gcc for this file.
+for def in $DEFINES; do
+ echo "#ifndef $def" | sed 's/=.*//' >> ${output}T
+ echo "# define $def" | sed 's/=/ /' >> ${output}T
+ echo "#endif" >> ${output}T
+done
+
+# The first entry in HEADERS may be auto-FOO.h ;
+# it wants to be included even when not -DIN_GCC.
+# Postpone including defaults.h until after the insn-*
+# headers, so that the HAVE_* flags are available
+# when defaults.h gets included.
+postpone_defaults_h="no"
+if [ -n "$HEADERS" ]; then
+ set $HEADERS
+ case "$1" in auto-* )
+ echo "#include \"$1\"" >> ${output}T
+ shift
+ ;;
+ esac
+ if [ $# -ge 1 ]; then
+ echo '#ifdef IN_GCC' >> ${output}T
+ for file in "$@"; do
+ if test x"$file" = x"defaults.h"; then
+ postpone_defaults_h="yes"
+ else
+ echo "# include \"$file\"" >> ${output}T
+ fi
+ done
+ echo '#endif' >> ${output}T
+ fi
+fi
+
+# If this is tm.h, now include insn-flags.h only if IN_GCC is defined
+# but neither GENERATOR_FILE nor USED_FOR_TARGET is defined. (Much of this
+# is temporary.)
+
+case $output in
+ tm.h )
+ cat >> ${output}T <<EOF
+#if defined IN_GCC && !defined GENERATOR_FILE && !defined USED_FOR_TARGET
+# include "insn-flags.h"
+#endif
+#if defined IN_GCC && !defined GENERATOR_FILE
+# include "insn-modes.h"
+#endif
+EOF
+ ;;
+esac
+
+# If we postponed including defaults.h, add the #include now.
+if test x"$postpone_defaults_h" = x"yes"; then
+ echo "# include \"defaults.h\"" >> ${output}T
+fi
+
+# Add multiple inclusion protection guard, part two.
+echo "#endif /* ${header_guard} */" >> ${output}T
+
+# Avoid changing the actual file if possible.
+if [ -f $output ] && cmp ${output}T $output >/dev/null 2>&1; then
+ echo $output is unchanged >&2
+ rm -f ${output}T
+else
+ mv -f ${output}T $output
+fi
+
+# Touch a stamp file for Make's benefit.
+rm -f cs-$output
+echo timestamp > cs-$output
diff --git a/support/cpp/gcc/mode-classes.def b/support/cpp/gcc/mode-classes.def
new file mode 100644
index 000000000..7df5ad287
--- /dev/null
+++ b/support/cpp/gcc/mode-classes.def
@@ -0,0 +1,40 @@
+/* Machine mode class definitions for GCC.
+ Copyright (C) 2003-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/>. */
+
+#define MODE_CLASSES \
+ DEF_MODE_CLASS (MODE_RANDOM), /* other */ \
+ DEF_MODE_CLASS (MODE_CC), /* condition code in a register */ \
+ DEF_MODE_CLASS (MODE_INT), /* integer */ \
+ DEF_MODE_CLASS (MODE_PARTIAL_INT), /* integer with padding bits */ \
+ DEF_MODE_CLASS (MODE_FRACT), /* signed fractional number */ \
+ DEF_MODE_CLASS (MODE_UFRACT), /* unsigned fractional number */ \
+ DEF_MODE_CLASS (MODE_ACCUM), /* signed accumulator */ \
+ DEF_MODE_CLASS (MODE_UACCUM), /* unsigned accumulator */ \
+ DEF_MODE_CLASS (MODE_FLOAT), /* floating point */ \
+ DEF_MODE_CLASS (MODE_DECIMAL_FLOAT), /* decimal floating point */ \
+ DEF_MODE_CLASS (MODE_COMPLEX_INT), /* complex numbers */ \
+ DEF_MODE_CLASS (MODE_COMPLEX_FLOAT), \
+ DEF_MODE_CLASS (MODE_VECTOR_BOOL), /* vectors of single bits */ \
+ DEF_MODE_CLASS (MODE_VECTOR_INT), /* SIMD vectors */ \
+ DEF_MODE_CLASS (MODE_VECTOR_FRACT), /* SIMD vectors */ \
+ DEF_MODE_CLASS (MODE_VECTOR_UFRACT), /* SIMD vectors */ \
+ DEF_MODE_CLASS (MODE_VECTOR_ACCUM), /* SIMD vectors */ \
+ DEF_MODE_CLASS (MODE_VECTOR_UACCUM), /* SIMD vectors */ \
+ DEF_MODE_CLASS (MODE_VECTOR_FLOAT), \
+ DEF_MODE_CLASS (MODE_OPAQUE) /* opaque modes */
diff --git a/support/cpp/gcc/omp-builtins.def b/support/cpp/gcc/omp-builtins.def
new file mode 100644
index 000000000..cfa6483c7
--- /dev/null
+++ b/support/cpp/gcc/omp-builtins.def
@@ -0,0 +1,469 @@
+/* This file contains the definitions and documentation for the
+ Offloading and Multi Processing builtins used in the GNU compiler.
+ Copyright (C) 2005-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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_GOACC_BUILTIN (ENUM, NAME, TYPE, ATTRS)
+ DEF_GOACC_BUILTIN_COMPILER (ENUM, NAME, TYPE, ATTRS)
+ DEF_GOMP_BUILTIN (ENUM, NAME, TYPE, ATTRS)
+
+ See builtins.def for details. */
+
+/* The reason why they aren't in gcc/builtins.def is that the Fortran front end
+ doesn't source those. */
+
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DATA_START, "GOACC_data_start",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DATA_END, "GOACC_data_end",
+ BT_FN_VOID, ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_ENTER_DATA, "GOACC_enter_data",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_INT_INT_VAR,
+ ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_EXIT_DATA, "GOACC_exit_data",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_INT_INT_VAR,
+ ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_PARALLEL, "GOACC_parallel_keyed",
+ BT_FN_VOID_INT_OMPFN_SIZE_PTR_PTR_PTR_VAR,
+ ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_UPDATE, "GOACC_update",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_INT_INT_VAR,
+ ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_WAIT, "GOACC_wait",
+ BT_FN_VOID_INT_INT_VAR,
+ ATTR_NOTHROW_LIST)
+DEF_GOACC_BUILTIN (BUILT_IN_GOACC_DECLARE, "GOACC_declare",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
+
+DEF_GOACC_BUILTIN_COMPILER (BUILT_IN_ACC_ON_DEVICE, "acc_on_device",
+ BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+
+DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_PARLEVEL_ID, "goacc_parlevel_id",
+ BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_PARLEVEL_SIZE, "goacc_parlevel_size",
+ BT_FN_INT_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_BARRIER, "GOACC_barrier",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_SINGLE_START, "GOACC_single_start",
+ BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_SINGLE_COPY_START, "GOACC_single_copy_start",
+ BT_FN_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOACC_BUILTIN_ONLY (BUILT_IN_GOACC_SINGLE_COPY_END, "GOACC_single_copy_end",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_THREAD_NUM, "omp_get_thread_num",
+ BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_NUM_THREADS, "omp_get_num_threads",
+ BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_TEAM_NUM, "omp_get_team_num",
+ BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_OMP_GET_NUM_TEAMS, "omp_get_num_teams",
+ BT_FN_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
+
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ATOMIC_START, "GOMP_atomic_start",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ATOMIC_END, "GOMP_atomic_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER, "GOMP_barrier",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER_CANCEL, "GOMP_barrier_cancel",
+ BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT, "GOMP_taskwait",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKWAIT_DEPEND, "GOMP_taskwait_depend",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKYIELD, "GOMP_taskyield",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKGROUP_START, "GOMP_taskgroup_start",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKGROUP_END, "GOMP_taskgroup_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CANCEL, "GOMP_cancel",
+ BT_FN_BOOL_INT_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CANCELLATION_POINT, "GOMP_cancellation_point",
+ BT_FN_BOOL_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_START, "GOMP_critical_start",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_END, "GOMP_critical_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_NAME_START,
+ "GOMP_critical_name_start",
+ BT_FN_VOID_PTRPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_CRITICAL_NAME_END,
+ "GOMP_critical_name_end",
+ BT_FN_VOID_PTRPTR, ATTR_NOTHROW_LEAF_LIST)
+/* NOTE: Do not change the order of BUILT_IN_GOMP_LOOP_*_START. They
+ are used in index arithmetic with enum omp_clause_schedule_kind
+ in omp-low.cc. */
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_STATIC_START,
+ "GOMP_loop_static_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DYNAMIC_START,
+ "GOMP_loop_dynamic_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_GUIDED_START,
+ "GOMP_loop_guided_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_RUNTIME_START,
+ "GOMP_loop_runtime_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_DYNAMIC_START,
+ "GOMP_loop_nonmonotonic_dynamic_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_GUIDED_START,
+ "GOMP_loop_nonmonotonic_guided_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_RUNTIME_START,
+ "GOMP_loop_nonmonotonic_runtime_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_MAYBE_NONMONOTONIC_RUNTIME_START,
+ "GOMP_loop_maybe_nonmonotonic_runtime_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_STATIC_START,
+ "GOMP_loop_ordered_static_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_DYNAMIC_START,
+ "GOMP_loop_ordered_dynamic_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_GUIDED_START,
+ "GOMP_loop_ordered_guided_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_RUNTIME_START,
+ "GOMP_loop_ordered_runtime_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START,
+ "GOMP_loop_doacross_static_start",
+ BT_FN_BOOL_UINT_LONGPTR_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DOACROSS_DYNAMIC_START,
+ "GOMP_loop_doacross_dynamic_start",
+ BT_FN_BOOL_UINT_LONGPTR_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DOACROSS_GUIDED_START,
+ "GOMP_loop_doacross_guided_start",
+ BT_FN_BOOL_UINT_LONGPTR_LONG_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DOACROSS_RUNTIME_START,
+ "GOMP_loop_doacross_runtime_start",
+ BT_FN_BOOL_UINT_LONGPTR_LONGPTR_LONGPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_START,
+ "GOMP_loop_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_START,
+ "GOMP_loop_ordered_start",
+ BT_FN_BOOL_LONG_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DOACROSS_START,
+ "GOMP_loop_doacross_start",
+ BT_FN_BOOL_UINT_LONGPTR_LONG_LONG_LONGPTR_LONGPTR_PTR_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_STATIC_NEXT, "GOMP_loop_static_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_DYNAMIC_NEXT, "GOMP_loop_dynamic_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_GUIDED_NEXT, "GOMP_loop_guided_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_RUNTIME_NEXT, "GOMP_loop_runtime_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_DYNAMIC_NEXT,
+ "GOMP_loop_nonmonotonic_dynamic_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_GUIDED_NEXT,
+ "GOMP_loop_nonmonotonic_guided_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_NONMONOTONIC_RUNTIME_NEXT,
+ "GOMP_loop_nonmonotonic_runtime_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_MAYBE_NONMONOTONIC_RUNTIME_NEXT,
+ "GOMP_loop_maybe_nonmonotonic_runtime_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_STATIC_NEXT,
+ "GOMP_loop_ordered_static_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_DYNAMIC_NEXT,
+ "GOMP_loop_ordered_dynamic_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_GUIDED_NEXT,
+ "GOMP_loop_ordered_guided_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ORDERED_RUNTIME_NEXT,
+ "GOMP_loop_ordered_runtime_next",
+ BT_FN_BOOL_LONGPTR_LONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_STATIC_START,
+ "GOMP_loop_ull_static_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_START,
+ "GOMP_loop_ull_dynamic_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_GUIDED_START,
+ "GOMP_loop_ull_guided_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_RUNTIME_START,
+ "GOMP_loop_ull_runtime_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_START,
+ "GOMP_loop_ull_nonmonotonic_dynamic_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_START,
+ "GOMP_loop_ull_nonmonotonic_guided_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_RUNTIME_START,
+ "GOMP_loop_ull_nonmonotonic_runtime_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_MAYBE_NONMONOTONIC_RUNTIME_START,
+ "GOMP_loop_ull_maybe_nonmonotonic_runtime_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_START,
+ "GOMP_loop_ull_ordered_static_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_DYNAMIC_START,
+ "GOMP_loop_ull_ordered_dynamic_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_START,
+ "GOMP_loop_ull_ordered_guided_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_RUNTIME_START,
+ "GOMP_loop_ull_ordered_runtime_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DOACROSS_STATIC_START,
+ "GOMP_loop_ull_doacross_static_start",
+ BT_FN_BOOL_UINT_ULLPTR_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DOACROSS_DYNAMIC_START,
+ "GOMP_loop_ull_doacross_dynamic_start",
+ BT_FN_BOOL_UINT_ULLPTR_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DOACROSS_GUIDED_START,
+ "GOMP_loop_ull_doacross_guided_start",
+ BT_FN_BOOL_UINT_ULLPTR_ULL_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DOACROSS_RUNTIME_START,
+ "GOMP_loop_ull_doacross_runtime_start",
+ BT_FN_BOOL_UINT_ULLPTR_ULLPTR_ULLPTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_START,
+ "GOMP_loop_ull_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_START,
+ "GOMP_loop_ull_ordered_start",
+ BT_FN_BOOL_BOOL_ULL_ULL_ULL_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DOACROSS_START,
+ "GOMP_loop_ull_doacross_start",
+ BT_FN_BOOL_UINT_ULLPTR_LONG_ULL_ULLPTR_ULLPTR_PTR_PTR,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT,
+ "GOMP_loop_ull_static_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_DYNAMIC_NEXT,
+ "GOMP_loop_ull_dynamic_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_GUIDED_NEXT,
+ "GOMP_loop_ull_guided_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_RUNTIME_NEXT,
+ "GOMP_loop_ull_runtime_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_DYNAMIC_NEXT,
+ "GOMP_loop_ull_nonmonotonic_dynamic_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_GUIDED_NEXT,
+ "GOMP_loop_ull_nonmonotonic_guided_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_NONMONOTONIC_RUNTIME_NEXT,
+ "GOMP_loop_ull_nonmonotonic_runtime_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_MAYBE_NONMONOTONIC_RUNTIME_NEXT,
+ "GOMP_loop_ull_maybe_nonmonotonic_runtime_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_STATIC_NEXT,
+ "GOMP_loop_ull_ordered_static_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_DYNAMIC_NEXT,
+ "GOMP_loop_ull_ordered_dynamic_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_GUIDED_NEXT,
+ "GOMP_loop_ull_ordered_guided_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_ULL_ORDERED_RUNTIME_NEXT,
+ "GOMP_loop_ull_ordered_runtime_next",
+ BT_FN_BOOL_ULONGLONGPTR_ULONGLONGPTR, ATTR_NOTHROW_LEAF_LIST)
+/* NOTE: Do not change the order of BUILT_IN_GOMP_PARALLEL_LOOP_*.
+ They are used in index arithmetic with enum omp_clause_schedule_kind
+ in omp-low.cc. */
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_STATIC,
+ "GOMP_parallel_loop_static",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_DYNAMIC,
+ "GOMP_parallel_loop_dynamic",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_GUIDED,
+ "GOMP_parallel_loop_guided",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_RUNTIME,
+ "GOMP_parallel_loop_runtime",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_DYNAMIC,
+ "GOMP_parallel_loop_nonmonotonic_dynamic",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_GUIDED,
+ "GOMP_parallel_loop_nonmonotonic_guided",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_NONMONOTONIC_RUNTIME,
+ "GOMP_parallel_loop_nonmonotonic_runtime",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_LOOP_MAYBE_NONMONOTONIC_RUNTIME,
+ "GOMP_parallel_loop_maybe_nonmonotonic_runtime",
+ BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_UINT,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_END, "GOMP_loop_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_END_CANCEL, "GOMP_loop_end_cancel",
+ BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_END_NOWAIT, "GOMP_loop_end_nowait",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ORDERED_START, "GOMP_ordered_start",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ORDERED_END, "GOMP_ordered_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_POST, "GOMP_doacross_post",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_WAIT, "GOMP_doacross_wait",
+ BT_FN_VOID_LONG_VAR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_POST, "GOMP_doacross_ull_post",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DOACROSS_ULL_WAIT, "GOMP_doacross_ull_wait",
+ BT_FN_VOID_ULL_VAR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL, "GOMP_parallel",
+ BT_FN_VOID_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_REDUCTIONS,
+ "GOMP_parallel_reductions",
+ BT_FN_UINT_OMPFN_PTR_UINT_UINT, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK, "GOMP_task",
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_BOOL_UINT_PTR_INT_PTR,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKLOOP, "GOMP_taskloop",
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_LONG_LONG_LONG,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKLOOP_ULL, "GOMP_taskloop_ull",
+ BT_FN_VOID_OMPFN_PTR_OMPCPYFN_LONG_LONG_UINT_LONG_INT_ULL_ULL_ULL,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_START, "GOMP_sections_start",
+ BT_FN_UINT_UINT, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS2_START, "GOMP_sections2_start",
+ BT_FN_UINT_UINT_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_NEXT, "GOMP_sections_next",
+ BT_FN_UINT, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_PARALLEL_SECTIONS,
+ "GOMP_parallel_sections",
+ BT_FN_VOID_OMPFN_PTR_UINT_UINT_UINT, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_END, "GOMP_sections_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_END_CANCEL,
+ "GOMP_sections_end_cancel",
+ BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SECTIONS_END_NOWAIT,
+ "GOMP_sections_end_nowait",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_START, "GOMP_single_start",
+ BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_START, "GOMP_single_copy_start",
+ BT_FN_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SCOPE_START, "GOMP_scope_start",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_OFFLOAD_REGISTER, "GOMP_offload_register_ver",
+ BT_FN_VOID_UINT_PTR_INT_PTR, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_OFFLOAD_UNREGISTER,
+ "GOMP_offload_unregister_ver",
+ BT_FN_VOID_UINT_PTR_INT_PTR, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TARGET, "GOMP_target_ext",
+ BT_FN_VOID_INT_OMPFN_SIZE_PTR_PTR_PTR_UINT_PTR_PTR,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TARGET_DATA, "GOMP_target_data_ext",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TARGET_END_DATA, "GOMP_target_end_data",
+ BT_FN_VOID, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TARGET_UPDATE, "GOMP_target_update_ext",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_UINT_PTR,
+ ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA,
+ "GOMP_target_enter_exit_data",
+ BT_FN_VOID_INT_SIZE_PTR_PTR_PTR_UINT_PTR, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TEAMS4, "GOMP_teams4",
+ BT_FN_BOOL_UINT_UINT_UINT_BOOL, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TEAMS_REG, "GOMP_teams_reg",
+ BT_FN_VOID_OMPFN_PTR_UINT_UINT_UINT, ATTR_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKGROUP_REDUCTION_REGISTER,
+ "GOMP_taskgroup_reduction_register",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASKGROUP_REDUCTION_UNREGISTER,
+ "GOMP_taskgroup_reduction_unregister",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_TASK_REDUCTION_REMAP,
+ "GOMP_task_reduction_remap",
+ BT_FN_VOID_SIZE_SIZE_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER,
+ "GOMP_workshare_task_reduction_unregister",
+ BT_FN_VOID_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ALLOC,
+ "GOMP_alloc", BT_FN_PTR_SIZE_SIZE_PTRMODE,
+ ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_FREE,
+ "GOMP_free", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_WARNING, "GOMP_warning",
+ BT_FN_VOID_CONST_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ERROR, "GOMP_error",
+ BT_FN_VOID_CONST_PTR_SIZE, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
diff --git a/support/cpp/gcc/omp-general.h b/support/cpp/gcc/omp-general.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/support/cpp/gcc/omp-general.h
diff --git a/support/cpp/gcc/omp-offload.h b/support/cpp/gcc/omp-offload.h
new file mode 100644
index 000000000..ea8ff1f81
--- /dev/null
+++ b/support/cpp/gcc/omp-offload.h
@@ -0,0 +1,35 @@
+/* Bits of OpenMP and OpenACC handling that is specific to device offloading
+ and a lowering pass for OpenACC device directives.
+
+ Copyright (C) 2005-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_OMP_DEVICE_H
+#define GCC_OMP_DEVICE_H
+
+extern int oacc_get_default_dim (int dim);
+extern int oacc_get_min_dim (int dim);
+extern int oacc_fn_attrib_level (tree attr);
+
+extern GTY(()) vec<tree, va_gc> *offload_funcs;
+extern GTY(()) vec<tree, va_gc> *offload_vars;
+
+extern void omp_finish_file (void);
+extern void omp_discover_implicit_declare_target (void);
+
+#endif /* GCC_OMP_DEVICE_H */
diff --git a/support/cpp/gcc/opt-functions.awk b/support/cpp/gcc/opt-functions.awk
new file mode 100644
index 000000000..2aee0b9f1
--- /dev/null
+++ b/support/cpp/gcc/opt-functions.awk
@@ -0,0 +1,389 @@
+# Copyright (C) 2003-2022 Free Software Foundation, Inc.
+# Contributed by Kelley Cook, June 2004.
+# Original code from Neil Booth, May 2003.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Some common subroutines for use by opt[ch]-gen.awk.
+
+# Define some helpful character classes, for portability.
+BEGIN {
+ lower = "abcdefghijklmnopqrstuvwxyz"
+ upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ digit = "0123456789"
+ alnum = lower "" upper "" digit
+}
+
+# Return nonzero if FLAGS contains a flag matching REGEX.
+function flag_set_p(regex, flags)
+{
+ # Ignore the arguments of flags with arguments.
+ gsub ("\\([^)]+\\)", "", flags);
+ return (" " flags " ") ~ (" " regex " ")
+}
+
+# Return STRING if FLAGS contains a flag matching regexp REGEX,
+# otherwise return the empty string.
+function test_flag(regex, flags, string)
+{
+ if (flag_set_p(regex, flags))
+ return string
+ return ""
+}
+
+# Return a field initializer, with trailing comma, for a field that is
+# 1 if FLAGS contains a flag matching REGEX and 0 otherwise.
+function flag_init(regex, flags)
+{
+ if (flag_set_p(regex, flags))
+ return "1 /* " regex " */, "
+ else
+ return "0, "
+}
+
+# If FLAGS contains a "NAME(...argument...)" flag, return the value
+# of the argument. Return the empty string otherwise.
+function opt_args(name, flags)
+{
+ flags = " " flags
+ if (flags !~ " " name "\\(")
+ return ""
+ sub(".* " name "\\(", "", flags)
+ if (flags ~ "^[{]")
+ {
+ sub ("^[{]", "", flags)
+ sub ("}\\).*", "", flags)
+ }
+ else
+ sub("\\).*", "", flags)
+
+ return flags
+}
+
+# If FLAGS contains a "NAME(...argument...)" flag, return the value
+# of the argument. Print error message otherwise.
+function opt_args_non_empty(name, flags, description)
+{
+ args = opt_args(name, flags)
+ if (args == "")
+ print "#error Empty option argument '" name "' during parsing of: " flags
+ return args
+}
+
+# Return the number of comma-separated element of S.
+function n_args(s)
+{
+ n = 1
+ while (s ~ ",") {
+ n++
+ sub("[^,]*, *", "", s)
+ }
+ return n
+}
+
+# Return the Nth comma-separated element of S. Return the empty string
+# if S does not contain N elements.
+function nth_arg(n, s)
+{
+ while (n-- > 0) {
+ if (s !~ ",")
+ return ""
+ sub("[^,]*, *", "", s)
+ }
+ sub(",.*", "", s)
+ return s
+}
+
+# Return a bitmask of CL_* values for option flags FLAGS.
+function switch_flags (flags)
+{
+ result = "0"
+ for (j = 0; j < n_langs; j++) {
+ regex = langs[j]
+ gsub ( "\\+", "\\+", regex )
+ result = result test_flag(regex, flags, " | " macros[j])
+ }
+ result = result \
+ test_flag("Common", flags, " | CL_COMMON") \
+ test_flag("Target", flags, " | CL_TARGET") \
+ test_flag("PchIgnore", flags, " | CL_PCH_IGNORE") \
+ test_flag("Driver", flags, " | CL_DRIVER") \
+ test_flag("Joined", flags, " | CL_JOINED") \
+ test_flag("JoinedOrMissing", flags, " | CL_JOINED") \
+ test_flag("Separate", flags, " | CL_SEPARATE") \
+ test_flag("Undocumented", flags, " | CL_UNDOCUMENTED") \
+ test_flag("NoDWARFRecord", flags, " | CL_NO_DWARF_RECORD") \
+ test_flag("Warning", flags, " | CL_WARNING") \
+ test_flag("(Optimization|PerFunction)", flags, " | CL_OPTIMIZATION") \
+ test_flag("Param", flags, " | CL_PARAMS")
+ sub( "^0 \\| ", "", result )
+ return result
+}
+
+# Return bit-field initializers for option flags FLAGS.
+function switch_bit_fields (flags)
+{
+ uinteger_flag = ""
+ vn = var_name(flags);
+ if (host_wide_int[vn] == "yes")
+ hwi = "Host_Wide_Int"
+ else if (flag_set_p("Host_Wide_Int", flags)) {
+ hwi = "Host_Wide_Int"
+ uinteger_flag = flag_init("UInteger", flags)
+ }
+ else
+ hwi = ""
+ result = ""
+ sep_args = opt_args("Args", flags)
+ if (sep_args == "")
+ sep_args = 0
+ else
+ sep_args--
+ result = result sep_args ", "
+
+ if (uinteger_flag == "")
+ uinteger_flag = flag_init("UInteger", flags)
+
+ hwi_flag = flag_init("Host_Wide_Int", hwi)
+ byte_size_flag = flag_init("ByteSize", flags)
+
+ if (substr(byte_size_flag, 1, 1) != "0" \
+ && substr(uinteger_flag, 1, 1) == "0" \
+ && substr(hwi_flag, 1, 1) == "0")
+ print "#error only UInteger amd Host_Wide_Int options can specify a ByteSize suffix"
+
+ # The following flags need to be in the same order as
+ # the corresponding members of struct cl_option defined
+ # in gcc/opts.h.
+ result = result \
+ flag_init("SeparateAlias", flags) \
+ flag_init("NegativeAlias", flags) \
+ flag_init("NoDriverArg", flags) \
+ flag_init("RejectDriver", flags) \
+ flag_init("RejectNegative", flags) \
+ flag_init("JoinedOrMissing", flags) \
+ uinteger_flag \
+ hwi_flag \
+ flag_init("ToLower", flags) \
+ byte_size_flag
+
+ if (flag_set_p("Report", flags))
+ print "#error Report option property is dropped"
+
+ sub(", $", "", result)
+ return result
+}
+
+# If FLAGS includes a Var flag, return the name of the variable it specifies.
+# Return the empty string otherwise.
+function var_name(flags)
+{
+ return nth_arg(0, opt_args("Var", flags))
+}
+
+# Return the name of the variable if FLAGS has a HOST_WIDE_INT variable.
+# Return the empty string otherwise.
+function host_wide_int_var_name(flags)
+{
+ split (flags, array, "[ \t]+")
+ if (array[1] == "HOST_WIDE_INT")
+ return array[2]
+ else
+ return ""
+}
+
+# Return true if the option described by FLAGS has a globally-visible state.
+function global_state_p(flags)
+{
+ return (var_name(flags) != "" \
+ || opt_args("Mask", flags) != "" \
+ || opt_args("InverseMask", flags) != "")
+}
+
+# Return true if the option described by FLAGS must have some state
+# associated with it.
+function needs_state_p(flags)
+{
+ return (flag_set_p("Target", flags) \
+ && !flag_set_p("Alias.*", flags) \
+ && !flag_set_p("Ignore", flags))
+}
+
+# If FLAGS describes an option that needs state without a public
+# variable name, return the name of that field, minus the initial
+# "x_", otherwise return "". NAME is the name of the option.
+function static_var(name, flags)
+{
+ if (global_state_p(flags) || !needs_state_p(flags))
+ return ""
+ gsub ("[^" alnum "]", "_", name)
+ return "VAR_" name
+}
+
+# Return the type of variable that should be associated with the given flags.
+function var_type(flags)
+{
+ if (flag_set_p("Defer", flags))
+ return "void *"
+ else if (flag_set_p("Enum.*", flags)) {
+ en = opt_args("Enum", flags);
+ return enum_type[en] " "
+ }
+ else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags))
+ return "int "
+ else if (flag_set_p("Host_Wide_Int", flags))
+ return "HOST_WIDE_INT "
+ else if (flag_set_p("UInteger", flags))
+ return "int "
+ else
+ return "const char *"
+}
+
+# Return the type of variable that should be associated with the given flags
+# for use within a structure. Simple variables are changed to signed char
+# type instead of int to save space.
+function var_type_struct(flags)
+{
+ if (flag_set_p("UInteger", flags)) {
+ if (host_wide_int[var_name(flags)] == "yes")
+ return "HOST_WIDE_INT ";
+ if (flag_set_p("ByteSize", flags))
+ return "HOST_WIDE_INT "
+ return "int "
+ }
+ else if (flag_set_p("Enum.*", flags)) {
+ en = opt_args("Enum", flags);
+ return enum_type[en] " "
+ }
+ else if (!flag_set_p("Joined.*", flags) && !flag_set_p("Separate", flags)) {
+ if (flag_set_p(".*Mask.*", flags)) {
+ if (host_wide_int[var_name(flags)] == "yes")
+ return "HOST_WIDE_INT "
+ else
+ return "/* - */ int "
+ }
+ else
+ return "signed char "
+ }
+ else
+ return "const char *"
+}
+
+# Given that an option has flags FLAGS, return an initializer for the
+# "var_enum", "var_type" and "var_value" fields of its cl_options[] entry.
+function var_set(flags)
+{
+ if (flag_set_p("Defer", flags))
+ return "0, CLVC_DEFER, 0"
+ s = nth_arg(1, opt_args("Var", flags))
+ if (s != "")
+ return "0, CLVC_EQUAL, " s
+ s = opt_args("Mask", flags);
+ if (s != "") {
+ vn = var_name(flags);
+ if (vn)
+ return "0, CLVC_BIT_SET, OPTION_MASK_" s
+ else
+ return "0, CLVC_BIT_SET, MASK_" s
+ }
+ s = nth_arg(0, opt_args("InverseMask", flags));
+ if (s != "") {
+ vn = var_name(flags);
+ if (vn)
+ return "0, CLVC_BIT_CLEAR, OPTION_MASK_" s
+ else
+ return "0, CLVC_BIT_CLEAR, MASK_" s
+ }
+ if (flag_set_p("Enum.*", flags)) {
+ en = opt_args("Enum", flags);
+ if (flag_set_p("EnumSet", flags))
+ return enum_index[en] ", CLVC_ENUM, CLEV_SET"
+ else if (flag_set_p("EnumBitSet", flags))
+ return enum_index[en] ", CLVC_ENUM, CLEV_BITSET"
+ else
+ return enum_index[en] ", CLVC_ENUM, CLEV_NORMAL"
+ }
+ if (var_type(flags) == "const char *")
+ return "0, CLVC_STRING, 0"
+ if (flag_set_p("ByteSize", flags))
+ return "0, CLVC_SIZE, 0"
+ return "0, CLVC_INTEGER, 0"
+}
+
+# Given that an option called NAME has flags FLAGS, return an initializer
+# for the "flag_var" field of its cl_options[] entry.
+function var_ref(name, flags)
+{
+ name = var_name(flags) static_var(name, flags)
+ if (name != "")
+ return "offsetof (struct gcc_options, x_" name ")"
+ if (opt_args("Mask", flags) != "")
+ return "offsetof (struct gcc_options, x_target_flags)"
+ if (opt_args("InverseMask", flags) != "")
+ return "offsetof (struct gcc_options, x_target_flags)"
+ return "(unsigned short) -1"
+}
+
+# Given the option called NAME return a sanitized version of its name.
+function opt_sanitized_name(name)
+{
+ gsub ("[^" alnum "]", "_", name)
+ return name
+}
+
+# Given the option called NAME return the appropriate enum for it.
+function opt_enum(name)
+{
+ return "OPT_" opt_sanitized_name(name)
+}
+
+# Given the language called NAME return a sanitized version of its name.
+function lang_sanitized_name(name)
+{
+ gsub( "[^" alnum "_]", "X", name )
+ return name
+}
+
+# Search for a valid var_name among all OPTS equal to option NAME.
+# If not found, return "".
+function search_var_name(name, opt_numbers, opts, flags, n_opts)
+{
+ opt_var_name = var_name(flags[opt_numbers[name]]);
+ if (opt_var_name != "") {
+ return opt_var_name;
+ }
+ for (k = 0; k < n_opts; k++) {
+ if (opts[k] == name && var_name(flags[k]) != "") {
+ return var_name(flags[k]);
+ }
+ }
+ return ""
+}
+
+function integer_range_info(range_option, init, option, uinteger_used)
+{
+ if (range_option != "") {
+ ival = init + 0;
+ start = nth_arg(0, range_option) + 0;
+ end = nth_arg(1, range_option) + 0;
+ if (init != "" && init != "-1" && (ival < start || ival > end))
+ print "#error initial value " init " of '" option "' must be in range [" start "," end "]"
+ if (uinteger_used && start < 0)
+ print "#error '" option"': negative IntegerRange (" start ", " end ") cannot be combined with UInteger"
+ return start ", " end
+ }
+ else
+ return "-1, -1"
+}
diff --git a/support/cpp/gcc/opt-gather.awk b/support/cpp/gcc/opt-gather.awk
new file mode 100644
index 000000000..1a4c66ceb
--- /dev/null
+++ b/support/cpp/gcc/opt-gather.awk
@@ -0,0 +1,54 @@
+# Copyright (C) 2003-2022 Free Software Foundation, Inc.
+# Contributed by Kelley Cook, June 2004.
+# Original code from Neil Booth, May 2003.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script takes a list of *.opt files and combines them into
+# a three-field sorted list suitable for input into opt[ch]-gen.awk.
+#
+# Usage: awk -f opt-gather.awk file1.opt [...] > outputfile
+
+function sort(ARRAY, ELEMENTS)
+{
+ for (i = 2; i <= ELEMENTS; ++i) {
+ for (j = i; ARRAY[j-1] > ARRAY[j]; --j) {
+ temp = ARRAY[j]
+ ARRAY[j] = ARRAY[j-1]
+ ARRAY[j-1] = temp
+ }
+ }
+ return
+}
+
+BEGIN { numrec = 0 }
+
+# Ignore comments and blank lines
+/^[ \t]*(;|$)/ { flag = 0; next }
+/^[^ \t]/ { if (flag == 0) {
+ record[++numrec] = $0
+ flag = 1 }
+ else {
+ record[numrec] = record[numrec] SUBSEP $0
+ }
+}
+
+# Sort it and output it
+END {
+ sort(record,numrec)
+
+ for (i = 1; i <= numrec; i++) {
+ print record[i] }
+}
diff --git a/support/cpp/gcc/opt-include.awk b/support/cpp/gcc/opt-include.awk
new file mode 100644
index 000000000..4b8898291
--- /dev/null
+++ b/support/cpp/gcc/opt-include.awk
@@ -0,0 +1,29 @@
+# Copyright (C) 2010-2022 Free Software Foundation, Inc.
+# Contributed by Michael Meissner (meissner@linux.vnet.ibm.com)
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records and emits the include files
+# listed by the HeaderInclude directive.
+
+BEGIN {
+ h_next = 0
+ c_next = 0
+}
+
+(h_next != 0) { print "OPTIONS_H_EXTRA += $(srcdir)/" $1; h_next = 0 }
+(c_next != 0) { print "OPTIONS_C_EXTRA += $(srcdir)/" $1; c_next = 0 }
+/^HeaderInclude$/ { h_next = 1; c_next = 0 }
+/^SourceInclude$/ { h_next = 0; c_next = 1 }
diff --git a/support/cpp/gcc/opt-read.awk b/support/cpp/gcc/opt-read.awk
new file mode 100644
index 000000000..ce3617c8d
--- /dev/null
+++ b/support/cpp/gcc/opt-read.awk
@@ -0,0 +1,128 @@
+# Copyright (C) 2003-2022 Free Software Foundation, Inc.
+# Contributed by Kelley Cook, June 2004.
+# Original code from Neil Booth, May 2003.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Read in the option records generated from opt-gather.awk.
+
+BEGIN {
+ n_opts = 0
+ n_langs = 0
+ n_target_save = 0
+ n_extra_vars = 0
+ n_extra_target_vars = 0
+ n_extra_masks = 0
+ n_extra_c_includes = 0
+ n_extra_h_includes = 0
+ n_enums = 0
+ have_save = 0;
+ quote = "\042"
+ comma = ","
+ FS=SUBSEP
+ # Default the name of header created from opth-gen.awk to options.h
+ if (header_name == "") header_name="options.h"
+}
+
+# Collect the text and flags of each option into an array
+ {
+ if ($1 == "Language") {
+ langs[n_langs] = $2
+ lang_numbers[$2] = n_langs
+ n_langs++;
+ }
+ else if ($1 == "TargetSave") {
+ # Make sure the declarations are put in source order
+ target_save_decl[n_target_save] = $2
+ n_target_save++
+ }
+ else if ($1 == "Variable") {
+ extra_vars[n_extra_vars] = $2
+ n_extra_vars++
+ name = host_wide_int_var_name($2)
+ if (name != "")
+ host_wide_int[name] = "yes"
+ }
+ else if ($1 == "TargetVariable") {
+ # Combination of TargetSave and Variable
+ extra_vars[n_extra_vars] = $2
+ n_extra_vars++
+
+ var = $2
+ sub(" *=.*", "", var)
+ orig_var = var
+ name = var
+ type = var
+ sub("^.*[ *]", "", name)
+ sub(" *" name "$", "", type)
+ target_save_decl[n_target_save] = type " x_" name
+ n_target_save++
+
+ extra_target_vars[n_extra_target_vars] = name
+ extra_target_var_types[n_extra_target_vars] = type
+ n_extra_target_vars++
+ }
+ else if ($1 == "HeaderInclude") {
+ extra_h_includes[n_extra_h_includes++] = $2;
+ }
+ else if ($1 == "SourceInclude") {
+ extra_c_includes[n_extra_c_includes++] = $2;
+ }
+ else if ($1 == "Enum") {
+ props = $2
+ name = opt_args_non_empty("Name", props)
+ type = opt_args_non_empty("Type", props)
+ unknown_error = opt_args("UnknownError", props)
+ enum_names[n_enums] = name
+ enum_type[name] = type
+ enum_index[name] = n_enums
+ enum_unknown_error[name] = unknown_error
+ enum_help[name] = $3
+ n_enums++
+ }
+ else if ($1 == "EnumValue") {
+ props = $2
+ enum_name = opt_args_non_empty("Enum", props)
+ string = opt_args_non_empty("String", props)
+ value = opt_args_non_empty("Value", props)
+ set = opt_args("Set", props)
+ val_flags = "0"
+ val_flags = val_flags \
+ test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \
+ test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY")
+ if (set != "")
+ val_flags = val_flags "| ((" set \
+ ") << CL_ENUM_SET_SHIFT)"
+ enum_data[enum_name] = enum_data[enum_name] \
+ " { " quote string quote ", " value ", " val_flags \
+ " },\n"
+ }
+ else {
+ name = opt_args("Mask", $1)
+ if (name == "") {
+ opts[n_opts] = $1
+ opt_numbers[$1] = n_opts
+ flags[n_opts] = $2
+ help[n_opts] = $3
+ for (i = 4; i <= NF; i++)
+ help[n_opts] = help[n_opts] " " $i
+ n_opts++;
+ }
+ else {
+ extra_masks[n_extra_masks++] = name
+ }
+ }
+ }
+
diff --git a/support/cpp/gcc/opt-suggestions.h b/support/cpp/gcc/opt-suggestions.h
new file mode 100644
index 000000000..1071a76dd
--- /dev/null
+++ b/support/cpp/gcc/opt-suggestions.h
@@ -0,0 +1,71 @@
+/* Provide suggestions to handle misspelled options, and implement the
+ --complete option for auto-completing options from a prefix.
+ Copyright (C) 2016-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_OPT_PROPOSER_H
+#define GCC_OPT_PROPOSER_H
+
+/* Option proposer is class used by driver in order to provide hints
+ for wrong options provided. And it's used by --complete option that's
+ intended to be invoked by BASH in order to provide better option
+ completion support. */
+
+class option_proposer
+{
+public:
+ /* Default constructor. */
+ option_proposer (): m_option_suggestions (NULL)
+ {}
+
+ /* Default destructor. */
+ ~option_proposer ();
+
+ /* Helper function for driver::handle_unrecognized_options.
+
+ Given an unrecognized option BAD_OPT (without the leading dash),
+ locate the closest reasonable matching option (again, without the
+ leading dash), or NULL.
+
+ The returned string is owned by the option_proposer instance. */
+ const char *suggest_option (const char *bad_opt);
+
+ /* Print on stdout a list of valid options that begin with OPTION_PREFIX,
+ one per line, suitable for use by Bash completion.
+
+ Implementation of the "-completion=" option. */
+ void suggest_completion (const char *option_prefix);
+
+ /* Populate RESULTS with valid completions of options that begin
+ with OPTION_PREFIX. */
+ void get_completions (const char *option_prefix, auto_string_vec &results);
+
+private:
+ /* Helper function for option_proposer::suggest_option. Populate
+ m_option_suggestions with candidate strings for misspelled options.
+ The strings will be freed by the option_proposer's dtor.
+ PREFIX is used for bash completion suggestions, otherwise
+ it's set to NULL. */
+ void build_option_suggestions (const char *prefix);
+
+private:
+ /* Cache with all suggestions. */
+ auto_string_vec *m_option_suggestions;
+};
+
+#endif /* GCC_OPT_PROPOSER_H */
diff --git a/support/cpp/gcc/optabs-query.h b/support/cpp/gcc/optabs-query.h
new file mode 100644
index 000000000..b9c9fd6f6
--- /dev/null
+++ b/support/cpp/gcc/optabs-query.h
@@ -0,0 +1,216 @@
+/* IR-agnostic target query functions relating to optabs
+ Copyright (C) 2001-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_OPTABS_QUERY_H
+#define GCC_OPTABS_QUERY_H
+
+#include "insn-opinit.h"
+#include "target.h"
+
+/* Return true if OP is a conversion optab. */
+
+inline bool
+convert_optab_p (optab op)
+{
+ return op > unknown_optab && op <= LAST_CONV_OPTAB;
+}
+
+/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
+ if the target does not have such an insn. */
+
+inline enum insn_code
+optab_handler (optab op, machine_mode mode)
+{
+ unsigned scode = (op << 16) | mode;
+ gcc_assert (op > LAST_CONV_OPTAB);
+ return raw_optab_handler (scode);
+}
+
+/* Return the insn used to perform conversion OP from mode FROM_MODE
+ to mode TO_MODE; return CODE_FOR_nothing if the target does not have
+ such an insn. */
+
+inline enum insn_code
+convert_optab_handler (convert_optab op, machine_mode to_mode,
+ machine_mode from_mode)
+{
+ unsigned scode = (op << 16) | (from_mode << 8) | to_mode;
+ gcc_assert (convert_optab_p (op));
+ return raw_optab_handler (scode);
+}
+
+enum insn_code convert_optab_handler (convert_optab, machine_mode,
+ machine_mode, optimization_type);
+
+/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
+ if the target does not have such an insn. */
+
+inline enum insn_code
+direct_optab_handler (direct_optab op, machine_mode mode)
+{
+ return optab_handler (op, mode);
+}
+
+enum insn_code direct_optab_handler (convert_optab, machine_mode,
+ optimization_type);
+
+/* Return true if UNOPTAB is for a trapping-on-overflow operation. */
+
+inline bool
+trapv_unoptab_p (optab unoptab)
+{
+ return (unoptab == negv_optab
+ || unoptab == absv_optab);
+}
+
+/* Return true if BINOPTAB is for a trapping-on-overflow operation. */
+
+inline bool
+trapv_binoptab_p (optab binoptab)
+{
+ return (binoptab == addv_optab
+ || binoptab == subv_optab
+ || binoptab == smulv_optab);
+}
+
+/* Return insn code for a comparison operator with VMODE
+ resultin MASK_MODE, unsigned if UNS is true. */
+
+static inline enum insn_code
+get_vec_cmp_icode (machine_mode vmode, machine_mode mask_mode, bool uns)
+{
+ optab tab = uns ? vec_cmpu_optab : vec_cmp_optab;
+ return convert_optab_handler (tab, vmode, mask_mode);
+}
+
+/* Return insn code for a comparison operator with VMODE
+ resultin MASK_MODE (only for EQ/NE). */
+
+static inline enum insn_code
+get_vec_cmp_eq_icode (machine_mode vmode, machine_mode mask_mode)
+{
+ return convert_optab_handler (vec_cmpeq_optab, vmode, mask_mode);
+}
+
+/* Return insn code for a conditional operator with a comparison in
+ mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
+
+inline enum insn_code
+get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
+{
+ enum insn_code icode = CODE_FOR_nothing;
+ if (uns)
+ icode = convert_optab_handler (vcondu_optab, vmode, cmode);
+ else
+ icode = convert_optab_handler (vcond_optab, vmode, cmode);
+ return icode;
+}
+
+/* Return insn code for a conditional operator with a mask mode
+ MMODE resulting in a value of mode VMODE. */
+
+static inline enum insn_code
+get_vcond_mask_icode (machine_mode vmode, machine_mode mmode)
+{
+ return convert_optab_handler (vcond_mask_optab, vmode, mmode);
+}
+
+/* Return insn code for a conditional operator with a comparison in
+ mode CMODE (only EQ/NE), resulting in a value of mode VMODE. */
+
+static inline enum insn_code
+get_vcond_eq_icode (machine_mode vmode, machine_mode cmode)
+{
+ return convert_optab_handler (vcondeq_optab, vmode, cmode);
+}
+
+/* Enumerates the possible extraction_insn operations. */
+enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
+
+/* Describes an instruction that inserts or extracts a bitfield. */
+class extraction_insn
+{
+public:
+ /* The code of the instruction. */
+ enum insn_code icode;
+
+ /* The mode that the structure operand should have. This is byte_mode
+ when using the legacy insv, extv and extzv patterns to access memory.
+ If no mode is given, the structure is a BLKmode memory. */
+ opt_scalar_int_mode struct_mode;
+
+ /* The mode of the field to be inserted or extracted, and by extension
+ the mode of the insertion or extraction itself. */
+ scalar_int_mode field_mode;
+
+ /* The mode of the field's bit position. This is only important
+ when the position is variable rather than constant. */
+ scalar_int_mode pos_mode;
+};
+
+bool get_best_reg_extraction_insn (extraction_insn *,
+ enum extraction_pattern,
+ unsigned HOST_WIDE_INT, machine_mode);
+bool get_best_mem_extraction_insn (extraction_insn *,
+ enum extraction_pattern,
+ HOST_WIDE_INT, HOST_WIDE_INT, machine_mode);
+
+enum insn_code can_extend_p (machine_mode, machine_mode, int);
+enum insn_code can_float_p (machine_mode, machine_mode, int);
+enum insn_code can_fix_p (machine_mode, machine_mode, int, bool *);
+bool can_conditionally_move_p (machine_mode mode);
+opt_machine_mode qimode_for_vec_perm (machine_mode);
+bool selector_fits_mode_p (machine_mode, const vec_perm_indices &);
+bool can_vec_perm_var_p (machine_mode);
+bool can_vec_perm_const_p (machine_mode, const vec_perm_indices &,
+ bool = true);
+/* Find a widening optab even if it doesn't widen as much as we want. */
+#define find_widening_optab_handler(A, B, C) \
+ find_widening_optab_handler_and_mode (A, B, C, NULL)
+enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode,
+ machine_mode,
+ machine_mode *);
+int can_mult_highpart_p (machine_mode, bool);
+bool can_vec_mask_load_store_p (machine_mode, machine_mode, bool);
+opt_machine_mode get_len_load_store_mode (machine_mode, bool);
+bool can_compare_and_swap_p (machine_mode, bool);
+bool can_atomic_exchange_p (machine_mode, bool);
+bool can_atomic_load_p (machine_mode);
+bool lshift_cheap_p (bool);
+bool supports_vec_gather_load_p (machine_mode = E_VOIDmode);
+bool supports_vec_scatter_store_p (machine_mode = E_VOIDmode);
+bool can_vec_extract (machine_mode, machine_mode);
+
+/* Version of find_widening_optab_handler_and_mode that operates on
+ specific mode types. */
+
+template<typename T>
+inline enum insn_code
+find_widening_optab_handler_and_mode (optab op, const T &to_mode,
+ const T &from_mode, T *found_mode)
+{
+ machine_mode tmp;
+ enum insn_code icode = find_widening_optab_handler_and_mode
+ (op, machine_mode (to_mode), machine_mode (from_mode), &tmp);
+ if (icode != CODE_FOR_nothing && found_mode)
+ *found_mode = as_a <T> (tmp);
+ return icode;
+}
+
+#endif
diff --git a/support/cpp/gcc/optabs-tree.h b/support/cpp/gcc/optabs-tree.h
new file mode 100644
index 000000000..307d9014b
--- /dev/null
+++ b/support/cpp/gcc/optabs-tree.h
@@ -0,0 +1,51 @@
+/* Tree-based target query functions relating to optabs
+ Copyright (C) 2001-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_OPTABS_TREE_H
+#define GCC_OPTABS_TREE_H
+
+#include "optabs-query.h"
+
+/* An extra flag to control optab_for_tree_code's behavior. This is needed to
+ distinguish between machines with a vector shift that takes a scalar for the
+ shift amount vs. machines that take a vector for the shift amount. */
+enum optab_subtype
+{
+ optab_default,
+ optab_scalar,
+ optab_vector,
+ optab_vector_mixed_sign
+};
+
+/* Return the optab used for computing the given operation on the type given by
+ the second argument. The third argument distinguishes between the types of
+ vector shifts and rotates. */
+optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
+bool
+supportable_half_widening_operation (enum tree_code, tree, tree,
+ enum tree_code *);
+bool supportable_convert_operation (enum tree_code, tree, tree,
+ enum tree_code *);
+bool expand_vec_cmp_expr_p (tree, tree, enum tree_code);
+bool expand_vec_cond_expr_p (tree, tree, enum tree_code);
+void init_tree_optimization_optabs (tree);
+bool target_supports_op_p (tree, enum tree_code,
+ enum optab_subtype = optab_default);
+
+#endif
diff --git a/support/cpp/gcc/optabs.def b/support/cpp/gcc/optabs.def
new file mode 100644
index 000000000..801310eba
--- /dev/null
+++ b/support/cpp/gcc/optabs.def
@@ -0,0 +1,475 @@
+/* Definitions for operation tables, or "optabs".
+ 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/>. */
+
+/* The entries in optabs.def are categorized:
+ C: A "conversion" optab, which uses two modes; has libcall data.
+ N: A "normal" optab, which uses one mode; has libcall data.
+ D: A "direct" optab, which uses one mode; does not have libcall data.
+ V: An "oVerflow" optab. Like N, but does not record its code in
+ code_to_optab.
+
+ CX, NX, VX: An extra pattern entry for a conversion or normal optab.
+
+ These patterns may be present in the MD file with names that contain
+ the mode(s) used and the name of the operation. This array contains
+ a list of optabs that need to be initialized. Within each name,
+ $a and $b are used to match a short mode name (the part of the mode
+ name not including `mode' and converted to lower-case).
+
+ $I means that only full integer modes should be considered for the
+ next mode, and $F means that only float modes should be considered.
+ $P means that both full and partial integer modes should be considered.
+ $Q means that only fixed-point modes should be considered.
+
+ The pattern may be NULL if the optab exists only for the libcalls
+ that we plan to attach to it, and there are no named patterns in
+ the md files. */
+
+/* The extension libcalls are used for float extension. */
+OPTAB_CL(sext_optab, "extend$b$a2", SIGN_EXTEND, "extend", gen_extend_conv_libfunc)
+OPTAB_CL(trunc_optab, "trunc$b$a2", TRUNCATE, "trunc", gen_trunc_conv_libfunc)
+OPTAB_CL(zext_optab, "zero_extend$b$a2", ZERO_EXTEND, NULL, NULL)
+
+OPTAB_CL(sfix_optab, "fix$F$b$I$a2", FIX, "fix", gen_fp_to_int_conv_libfunc)
+OPTAB_CL(ufix_optab, "fixuns$F$b$a2", UNSIGNED_FIX, "fixuns", gen_fp_to_int_conv_libfunc)
+OPTAB_CL(sfloat_optab, "float$I$b$F$a2", FLOAT, "float", gen_int_to_fp_conv_libfunc)
+OPTAB_CL(ufloat_optab, "floatuns$I$b$F$a2", UNSIGNED_FLOAT, NULL, gen_ufloat_conv_libfunc)
+
+OPTAB_CL(lrint_optab, "lrint$F$b$I$a2", UNKNOWN, "lrint", gen_int_to_fp_nondecimal_conv_libfunc)
+OPTAB_CL(lround_optab, "lround$F$b$I$a2", UNKNOWN, "lround", gen_int_to_fp_nondecimal_conv_libfunc)
+OPTAB_CL(lfloor_optab, "lfloor$F$b$I$a2", UNKNOWN, "lfloor", gen_int_to_fp_nondecimal_conv_libfunc)
+OPTAB_CL(lceil_optab, "lceil$F$b$I$a2", UNKNOWN, "lceil", gen_int_to_fp_nondecimal_conv_libfunc)
+
+/* Conversions for fixed-point modes and other modes. */
+OPTAB_CL(fract_optab, "fract$b$a2", FRACT_CONVERT, "fract", gen_fract_conv_libfunc)
+OPTAB_CL(fractuns_optab, "fractuns$I$b$Q$a2", UNSIGNED_FRACT_CONVERT, "fractuns", gen_fractuns_conv_libfunc)
+OPTAB_CX(fractuns_optab, "fractuns$Q$b$I$a2")
+OPTAB_CL(satfract_optab, "satfract$b$Q$a2", SAT_FRACT, "satfract", gen_satfract_conv_libfunc)
+OPTAB_CL(satfractuns_optab, "satfractuns$I$b$Q$a2", UNSIGNED_SAT_FRACT, "satfractuns", gen_satfractuns_conv_libfunc)
+
+OPTAB_CD(sfixtrunc_optab, "fix_trunc$F$b$I$a2")
+OPTAB_CD(ufixtrunc_optab, "fixuns_trunc$F$b$I$a2")
+
+/* Misc optabs that use two modes; model them as "conversions". */
+OPTAB_CD(smul_widen_optab, "mul$b$a3")
+OPTAB_CD(umul_widen_optab, "umul$b$a3")
+OPTAB_CD(usmul_widen_optab, "usmul$b$a3")
+OPTAB_CD(smadd_widen_optab, "madd$b$a4")
+OPTAB_CD(umadd_widen_optab, "umadd$b$a4")
+OPTAB_CD(ssmadd_widen_optab, "ssmadd$b$a4")
+OPTAB_CD(usmadd_widen_optab, "usmadd$b$a4")
+OPTAB_CD(smsub_widen_optab, "msub$b$a4")
+OPTAB_CD(umsub_widen_optab, "umsub$b$a4")
+OPTAB_CD(ssmsub_widen_optab, "ssmsub$b$a4")
+OPTAB_CD(usmsub_widen_optab, "usmsub$a$b4")
+OPTAB_CD(vec_load_lanes_optab, "vec_load_lanes$a$b")
+OPTAB_CD(vec_store_lanes_optab, "vec_store_lanes$a$b")
+OPTAB_CD(vec_mask_load_lanes_optab, "vec_mask_load_lanes$a$b")
+OPTAB_CD(vec_mask_store_lanes_optab, "vec_mask_store_lanes$a$b")
+OPTAB_CD(vcond_optab, "vcond$a$b")
+OPTAB_CD(vcondu_optab, "vcondu$a$b")
+OPTAB_CD(vcondeq_optab, "vcondeq$a$b")
+OPTAB_CD(vcond_mask_optab, "vcond_mask_$a$b")
+OPTAB_CD(vec_cmp_optab, "vec_cmp$a$b")
+OPTAB_CD(vec_cmpu_optab, "vec_cmpu$a$b")
+OPTAB_CD(vec_cmpeq_optab, "vec_cmpeq$a$b")
+OPTAB_CD(maskload_optab, "maskload$a$b")
+OPTAB_CD(maskstore_optab, "maskstore$a$b")
+OPTAB_CD(gather_load_optab, "gather_load$a$b")
+OPTAB_CD(mask_gather_load_optab, "mask_gather_load$a$b")
+OPTAB_CD(scatter_store_optab, "scatter_store$a$b")
+OPTAB_CD(mask_scatter_store_optab, "mask_scatter_store$a$b")
+OPTAB_CD(vec_extract_optab, "vec_extract$a$b")
+OPTAB_CD(vec_init_optab, "vec_init$a$b")
+
+OPTAB_CD (while_ult_optab, "while_ult$a$b")
+
+OPTAB_NL(add_optab, "add$P$a3", PLUS, "add", '3', gen_int_fp_fixed_libfunc)
+OPTAB_NX(add_optab, "add$F$a3")
+OPTAB_NX(add_optab, "add$Q$a3")
+OPTAB_VL(addv_optab, "addv$I$a3", PLUS, "add", '3', gen_intv_fp_libfunc)
+OPTAB_VX(addv_optab, "add$F$a3")
+OPTAB_NL(ssadd_optab, "ssadd$Q$a3", SS_PLUS, "ssadd", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(usadd_optab, "usadd$Q$a3", US_PLUS, "usadd", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(sub_optab, "sub$P$a3", MINUS, "sub", '3', gen_int_fp_fixed_libfunc)
+OPTAB_NX(sub_optab, "sub$F$a3")
+OPTAB_NX(sub_optab, "sub$Q$a3")
+OPTAB_VL(subv_optab, "subv$I$a3", MINUS, "sub", '3', gen_intv_fp_libfunc)
+OPTAB_VX(subv_optab, "sub$F$a3")
+OPTAB_NL(sssub_optab, "sssub$Q$a3", SS_MINUS, "sssub", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(ussub_optab, "ussub$Q$a3", US_MINUS, "ussub", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(smul_optab, "mul$Q$a3", MULT, "mul", '3', gen_int_fp_fixed_libfunc)
+OPTAB_NX(smul_optab, "mul$P$a3")
+OPTAB_NX(smul_optab, "mul$F$a3")
+OPTAB_VL(smulv_optab, "mulv$I$a3", MULT, "mul", '3', gen_intv_fp_libfunc)
+OPTAB_VX(smulv_optab, "mul$F$a3")
+OPTAB_NL(ssmul_optab, "ssmul$Q$a3", SS_MULT, "ssmul", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(usmul_optab, "usmul$Q$a3", US_MULT, "usmul", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(sdiv_optab, "div$a3", DIV, "div", '3', gen_int_fp_signed_fixed_libfunc)
+OPTAB_VL(sdivv_optab, "divv$I$a3", DIV, "divv", '3', gen_int_libfunc)
+OPTAB_VX(sdivv_optab, "div$F$a3")
+OPTAB_NL(ssdiv_optab, "ssdiv$Q$a3", SS_DIV, "ssdiv", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(udiv_optab, "udiv$I$a3", UDIV, "udiv", '3', gen_int_unsigned_fixed_libfunc)
+OPTAB_NX(udiv_optab, "udiv$Q$a3")
+OPTAB_NL(usdiv_optab, "usdiv$Q$a3", US_DIV, "usdiv", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NC(sdivmod_optab, "divmod$a4", UNKNOWN)
+OPTAB_NC(udivmod_optab, "udivmod$a4", UNKNOWN)
+OPTAB_NL(smod_optab, "mod$a3", MOD, "mod", '3', gen_int_libfunc)
+OPTAB_NL(umod_optab, "umod$a3", UMOD, "umod", '3', gen_int_libfunc)
+OPTAB_NL(ftrunc_optab, "ftrunc$F$a2", UNKNOWN, "ftrunc", '2', gen_fp_libfunc)
+OPTAB_NL(and_optab, "and$a3", AND, "and", '3', gen_int_libfunc)
+OPTAB_NL(ior_optab, "ior$a3", IOR, "ior", '3', gen_int_libfunc)
+OPTAB_NL(xor_optab, "xor$a3", XOR, "xor", '3', gen_int_libfunc)
+OPTAB_NL(ashl_optab, "ashl$a3", ASHIFT, "ashl", '3', gen_int_fixed_libfunc)
+OPTAB_NL(ssashl_optab, "ssashl$Q$a3", SS_ASHIFT, "ssashl", '3', gen_signed_fixed_libfunc)
+OPTAB_NL(usashl_optab, "usashl$Q$a3", US_ASHIFT, "usashl", '3', gen_unsigned_fixed_libfunc)
+OPTAB_NL(ashr_optab, "ashr$a3", ASHIFTRT, "ashr", '3', gen_int_signed_fixed_libfunc)
+OPTAB_NL(lshr_optab, "lshr$a3", LSHIFTRT, "lshr", '3', gen_int_unsigned_fixed_libfunc)
+OPTAB_NC(rotl_optab, "rotl$a3", ROTATE)
+OPTAB_NC(rotr_optab, "rotr$a3", ROTATERT)
+OPTAB_VC(vashl_optab, "vashl$a3", ASHIFT)
+OPTAB_VC(vashr_optab, "vashr$a3", ASHIFTRT)
+OPTAB_VC(vlshr_optab, "vlshr$a3", LSHIFTRT)
+OPTAB_VC(vrotl_optab, "vrotl$a3", ROTATE)
+OPTAB_VC(vrotr_optab, "vrotr$a3", ROTATERT)
+OPTAB_NL(smin_optab, "smin$a3", SMIN, "min", '3', gen_int_fp_libfunc)
+OPTAB_NL(smax_optab, "smax$a3", SMAX, "max", '3', gen_int_fp_libfunc)
+OPTAB_NL(umin_optab, "umin$I$a3", UMIN, "umin", '3', gen_int_libfunc)
+OPTAB_NL(umax_optab, "umax$I$a3", UMAX, "umax", '3', gen_int_libfunc)
+
+OPTAB_NL(neg_optab, "neg$P$a2", NEG, "neg", '2', gen_int_fp_fixed_libfunc)
+OPTAB_NX(neg_optab, "neg$F$a2")
+OPTAB_NX(neg_optab, "neg$Q$a2")
+OPTAB_VL(negv_optab, "negv$I$a2", NEG, "neg", '2', gen_intv_fp_libfunc)
+OPTAB_VX(negv_optab, "neg$F$a2")
+OPTAB_NL(ssneg_optab, "ssneg$Q$a2", SS_NEG, "ssneg", '2', gen_signed_fixed_libfunc)
+OPTAB_NL(usneg_optab, "usneg$Q$a2", US_NEG, "usneg", '2', gen_unsigned_fixed_libfunc)
+OPTAB_NC(abs_optab, "abs$P$a2", ABS)
+OPTAB_NX(abs_optab, "abs$F$a2")
+OPTAB_VC(absv_optab, "absv$I$a2", ABS)
+OPTAB_VX(absv_optab, "abs$F$a2")
+OPTAB_NL(one_cmpl_optab, "one_cmpl$a2", NOT, "one_cmpl", '2', gen_int_libfunc)
+OPTAB_NC(bswap_optab, "bswap$a2", BSWAP)
+OPTAB_NL(ffs_optab, "ffs$a2", FFS, "ffs", '2', gen_int_libfunc)
+OPTAB_NL(clz_optab, "clz$a2", CLZ, "clz", '2', gen_int_libfunc)
+OPTAB_NL(ctz_optab, "ctz$a2", CTZ, "ctz", '2', gen_int_libfunc)
+OPTAB_NL(clrsb_optab, "clrsb$a2", CLRSB, "clrsb", '2', gen_int_libfunc)
+OPTAB_NL(popcount_optab, "popcount$a2", POPCOUNT, "popcount", '2', gen_int_libfunc)
+OPTAB_NL(parity_optab, "parity$a2", PARITY, "parity", '2', gen_int_libfunc)
+
+/* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
+OPTAB_NL(cmp_optab, NULL, UNKNOWN, "cmp", '2', gen_int_fp_fixed_libfunc)
+OPTAB_NL(ucmp_optab, NULL, UNKNOWN, "ucmp", '2', gen_int_libfunc)
+
+/* EQ etc are floating point comparisons. */
+OPTAB_NL(eq_optab, NULL, EQ, "eq", '2', gen_fp_libfunc)
+OPTAB_NL(ne_optab, NULL, NE, "ne", '2', gen_fp_libfunc)
+OPTAB_NL(gt_optab, NULL, GT, "gt", '2', gen_fp_libfunc)
+OPTAB_NL(ge_optab, NULL, GE, "ge", '2', gen_fp_libfunc)
+OPTAB_NL(lt_optab, NULL, LT, "lt", '2', gen_fp_libfunc)
+OPTAB_NL(le_optab, NULL, LE, "le", '2', gen_fp_libfunc)
+OPTAB_NL(unord_optab, NULL, UNORDERED, "unord", '2', gen_fp_libfunc)
+
+OPTAB_NL(powi_optab, NULL, UNKNOWN, "powi", '2', gen_fp_libfunc)
+
+/* These are all initialized individually, on a per-host basis. */
+OPTAB_NC(sqrt_optab, "sqrt$a2", SQRT)
+OPTAB_NC(sync_old_add_optab, "sync_old_add$I$a", UNKNOWN)
+OPTAB_NC(sync_old_sub_optab, "sync_old_sub$I$a", UNKNOWN)
+OPTAB_NC(sync_old_ior_optab, "sync_old_ior$I$a", UNKNOWN)
+OPTAB_NC(sync_old_and_optab, "sync_old_and$I$a", UNKNOWN)
+OPTAB_NC(sync_old_xor_optab, "sync_old_xor$I$a", UNKNOWN)
+OPTAB_NC(sync_old_nand_optab, "sync_old_nand$I$a", UNKNOWN)
+OPTAB_NC(sync_new_add_optab, "sync_new_add$I$a", UNKNOWN)
+OPTAB_NC(sync_new_sub_optab, "sync_new_sub$I$a", UNKNOWN)
+OPTAB_NC(sync_new_ior_optab, "sync_new_ior$I$a", UNKNOWN)
+OPTAB_NC(sync_new_and_optab, "sync_new_and$I$a", UNKNOWN)
+OPTAB_NC(sync_new_xor_optab, "sync_new_xor$I$a", UNKNOWN)
+OPTAB_NC(sync_new_nand_optab, "sync_new_nand$I$a", UNKNOWN)
+OPTAB_NC(sync_compare_and_swap_optab, "sync_compare_and_swap$I$a", UNKNOWN)
+OPTAB_NC(sync_lock_test_and_set_optab, "sync_lock_test_and_set$I$a", UNKNOWN)
+
+OPTAB_DC(mov_optab, "mov$a", SET)
+OPTAB_DC(movstrict_optab, "movstrict$a", STRICT_LOW_PART)
+OPTAB_D (movmisalign_optab, "movmisalign$a")
+OPTAB_D (storent_optab, "storent$a")
+OPTAB_D (insv_optab, "insv$a")
+OPTAB_D (extv_optab, "extv$a")
+OPTAB_D (extzv_optab, "extzv$a")
+OPTAB_D (insvmisalign_optab, "insvmisalign$a")
+OPTAB_D (extvmisalign_optab, "extvmisalign$a")
+OPTAB_D (extzvmisalign_optab, "extzvmisalign$a")
+OPTAB_D (push_optab, "push$a1")
+OPTAB_D (reload_in_optab, "reload_in$a")
+OPTAB_D (reload_out_optab, "reload_out$a")
+
+OPTAB_DC(cbranch_optab, "cbranch$a4", COMPARE)
+OPTAB_D (addcc_optab, "add$acc")
+OPTAB_D (negcc_optab, "neg$acc")
+OPTAB_D (notcc_optab, "not$acc")
+OPTAB_D (movcc_optab, "mov$acc")
+OPTAB_D (cond_add_optab, "cond_add$a")
+OPTAB_D (cond_sub_optab, "cond_sub$a")
+OPTAB_D (cond_smul_optab, "cond_mul$a")
+OPTAB_D (cond_sdiv_optab, "cond_div$a")
+OPTAB_D (cond_smod_optab, "cond_mod$a")
+OPTAB_D (cond_udiv_optab, "cond_udiv$a")
+OPTAB_D (cond_umod_optab, "cond_umod$a")
+OPTAB_D (cond_and_optab, "cond_and$a")
+OPTAB_D (cond_ior_optab, "cond_ior$a")
+OPTAB_D (cond_xor_optab, "cond_xor$a")
+OPTAB_D (cond_ashl_optab, "cond_ashl$a")
+OPTAB_D (cond_ashr_optab, "cond_ashr$a")
+OPTAB_D (cond_lshr_optab, "cond_lshr$a")
+OPTAB_D (cond_smin_optab, "cond_smin$a")
+OPTAB_D (cond_smax_optab, "cond_smax$a")
+OPTAB_D (cond_umin_optab, "cond_umin$a")
+OPTAB_D (cond_umax_optab, "cond_umax$a")
+OPTAB_D (cond_fmin_optab, "cond_fmin$a")
+OPTAB_D (cond_fmax_optab, "cond_fmax$a")
+OPTAB_D (cond_fma_optab, "cond_fma$a")
+OPTAB_D (cond_fms_optab, "cond_fms$a")
+OPTAB_D (cond_fnma_optab, "cond_fnma$a")
+OPTAB_D (cond_fnms_optab, "cond_fnms$a")
+OPTAB_D (cond_neg_optab, "cond_neg$a")
+OPTAB_D (cmov_optab, "cmov$a6")
+OPTAB_D (cstore_optab, "cstore$a4")
+OPTAB_D (ctrap_optab, "ctrap$a4")
+OPTAB_D (addv4_optab, "addv$I$a4")
+OPTAB_D (subv4_optab, "subv$I$a4")
+OPTAB_D (mulv4_optab, "mulv$I$a4")
+OPTAB_D (uaddv4_optab, "uaddv$I$a4")
+OPTAB_D (usubv4_optab, "usubv$I$a4")
+OPTAB_D (umulv4_optab, "umulv$I$a4")
+OPTAB_D (negv3_optab, "negv$I$a3")
+OPTAB_D (addptr3_optab, "addptr$a3")
+OPTAB_D (spaceship_optab, "spaceship$a3")
+
+OPTAB_D (smul_highpart_optab, "smul$a3_highpart")
+OPTAB_D (umul_highpart_optab, "umul$a3_highpart")
+
+OPTAB_D (cmpmem_optab, "cmpmem$a")
+OPTAB_D (cmpstr_optab, "cmpstr$a")
+OPTAB_D (cmpstrn_optab, "cmpstrn$a")
+OPTAB_D (cpymem_optab, "cpymem$a")
+OPTAB_D (movmem_optab, "movmem$a")
+OPTAB_D (setmem_optab, "setmem$a")
+OPTAB_D (strlen_optab, "strlen$a")
+OPTAB_D (rawmemchr_optab, "rawmemchr$a")
+
+OPTAB_DC(fma_optab, "fma$a4", FMA)
+OPTAB_D (fms_optab, "fms$a4")
+OPTAB_D (fnma_optab, "fnma$a4")
+OPTAB_D (fnms_optab, "fnms$a4")
+
+OPTAB_D (rint_optab, "rint$a2")
+OPTAB_D (round_optab, "round$a2")
+OPTAB_D (roundeven_optab, "roundeven$a2")
+OPTAB_D (floor_optab, "floor$a2")
+OPTAB_D (ceil_optab, "ceil$a2")
+OPTAB_D (btrunc_optab, "btrunc$a2")
+OPTAB_D (nearbyint_optab, "nearbyint$a2")
+
+OPTAB_D (acos_optab, "acos$a2")
+OPTAB_D (acosh_optab, "acosh$a2")
+OPTAB_D (asin_optab, "asin$a2")
+OPTAB_D (asinh_optab, "asinh$a2")
+OPTAB_D (atan2_optab, "atan2$a3")
+OPTAB_D (atan_optab, "atan$a2")
+OPTAB_D (atanh_optab, "atanh$a2")
+OPTAB_D (copysign_optab, "copysign$F$a3")
+OPTAB_D (xorsign_optab, "xorsign$F$a3")
+OPTAB_D (cadd90_optab, "cadd90$a3")
+OPTAB_D (cadd270_optab, "cadd270$a3")
+OPTAB_D (cmul_optab, "cmul$a3")
+OPTAB_D (cmul_conj_optab, "cmul_conj$a3")
+OPTAB_D (cmla_optab, "cmla$a4")
+OPTAB_D (cmla_conj_optab, "cmla_conj$a4")
+OPTAB_D (cmls_optab, "cmls$a4")
+OPTAB_D (cmls_conj_optab, "cmls_conj$a4")
+OPTAB_D (cos_optab, "cos$a2")
+OPTAB_D (cosh_optab, "cosh$a2")
+OPTAB_D (exp10_optab, "exp10$a2")
+OPTAB_D (exp2_optab, "exp2$a2")
+OPTAB_D (exp_optab, "exp$a2")
+OPTAB_D (expm1_optab, "expm1$a2")
+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 (ldexp_optab, "ldexp$a3")
+OPTAB_D (log10_optab, "log10$a2")
+OPTAB_D (log1p_optab, "log1p$a2")
+OPTAB_D (log2_optab, "log2$a2")
+OPTAB_D (log_optab, "log$a2")
+OPTAB_D (logb_optab, "logb$a2")
+OPTAB_D (pow_optab, "pow$a3")
+OPTAB_D (remainder_optab, "remainder$a3")
+OPTAB_D (rsqrt_optab, "rsqrt$a2")
+OPTAB_D (scalb_optab, "scalb$a3")
+OPTAB_D (signbit_optab, "signbit$F$a2")
+OPTAB_D (significand_optab, "significand$a2")
+OPTAB_D (sin_optab, "sin$a2")
+OPTAB_D (sincos_optab, "sincos$a3")
+OPTAB_D (sinh_optab, "sinh$a2")
+OPTAB_D (tan_optab, "tan$a2")
+OPTAB_D (tanh_optab, "tanh$a2")
+
+OPTAB_D (fegetround_optab, "fegetround$a")
+OPTAB_D (feclearexcept_optab, "feclearexcept$a")
+OPTAB_D (feraiseexcept_optab, "feraiseexcept$a")
+
+/* C99 implementations of fmax/fmin. */
+OPTAB_D (fmax_optab, "fmax$a3")
+OPTAB_D (fmin_optab, "fmin$a3")
+
+/* Vector reduction to a scalar. */
+OPTAB_D (reduc_fmax_scal_optab, "reduc_fmax_scal_$a")
+OPTAB_D (reduc_fmin_scal_optab, "reduc_fmin_scal_$a")
+OPTAB_D (reduc_smax_scal_optab, "reduc_smax_scal_$a")
+OPTAB_D (reduc_smin_scal_optab, "reduc_smin_scal_$a")
+OPTAB_D (reduc_plus_scal_optab, "reduc_plus_scal_$a")
+OPTAB_D (reduc_umax_scal_optab, "reduc_umax_scal_$a")
+OPTAB_D (reduc_umin_scal_optab, "reduc_umin_scal_$a")
+OPTAB_D (reduc_and_scal_optab, "reduc_and_scal_$a")
+OPTAB_D (reduc_ior_scal_optab, "reduc_ior_scal_$a")
+OPTAB_D (reduc_xor_scal_optab, "reduc_xor_scal_$a")
+OPTAB_D (fold_left_plus_optab, "fold_left_plus_$a")
+OPTAB_D (mask_fold_left_plus_optab, "mask_fold_left_plus_$a")
+
+OPTAB_D (extract_last_optab, "extract_last_$a")
+OPTAB_D (fold_extract_last_optab, "fold_extract_last_$a")
+
+OPTAB_D (savg_floor_optab, "avg$a3_floor")
+OPTAB_D (uavg_floor_optab, "uavg$a3_floor")
+OPTAB_D (savg_ceil_optab, "avg$a3_ceil")
+OPTAB_D (uavg_ceil_optab, "uavg$a3_ceil")
+OPTAB_D (sdot_prod_optab, "sdot_prod$I$a")
+OPTAB_D (ssum_widen_optab, "widen_ssum$I$a3")
+OPTAB_D (udot_prod_optab, "udot_prod$I$a")
+OPTAB_D (usdot_prod_optab, "usdot_prod$I$a")
+OPTAB_D (usum_widen_optab, "widen_usum$I$a3")
+OPTAB_D (usad_optab, "usad$I$a")
+OPTAB_D (ssad_optab, "ssad$I$a")
+OPTAB_D (smulhs_optab, "smulhs$a3")
+OPTAB_D (smulhrs_optab, "smulhrs$a3")
+OPTAB_D (umulhs_optab, "umulhs$a3")
+OPTAB_D (umulhrs_optab, "umulhrs$a3")
+OPTAB_D (sdiv_pow2_optab, "sdiv_pow2$a3")
+OPTAB_D (vec_pack_sfix_trunc_optab, "vec_pack_sfix_trunc_$a")
+OPTAB_D (vec_pack_ssat_optab, "vec_pack_ssat_$a")
+OPTAB_D (vec_pack_trunc_optab, "vec_pack_trunc_$a")
+OPTAB_D (vec_pack_ufix_trunc_optab, "vec_pack_ufix_trunc_$a")
+OPTAB_D (vec_pack_sbool_trunc_optab, "vec_pack_sbool_trunc_$a")
+OPTAB_D (vec_pack_usat_optab, "vec_pack_usat_$a")
+OPTAB_D (vec_packs_float_optab, "vec_packs_float_$a")
+OPTAB_D (vec_packu_float_optab, "vec_packu_float_$a")
+OPTAB_D (vec_perm_optab, "vec_perm$a")
+OPTAB_D (vec_realign_load_optab, "vec_realign_load_$a")
+OPTAB_D (vec_set_optab, "vec_set$a")
+OPTAB_D (vec_shl_optab, "vec_shl_$a")
+OPTAB_D (vec_shr_optab, "vec_shr_$a")
+OPTAB_D (vec_unpack_sfix_trunc_hi_optab, "vec_unpack_sfix_trunc_hi_$a")
+OPTAB_D (vec_unpack_sfix_trunc_lo_optab, "vec_unpack_sfix_trunc_lo_$a")
+OPTAB_D (vec_unpack_ufix_trunc_hi_optab, "vec_unpack_ufix_trunc_hi_$a")
+OPTAB_D (vec_unpack_ufix_trunc_lo_optab, "vec_unpack_ufix_trunc_lo_$a")
+OPTAB_D (vec_unpacks_float_hi_optab, "vec_unpacks_float_hi_$a")
+OPTAB_D (vec_unpacks_float_lo_optab, "vec_unpacks_float_lo_$a")
+OPTAB_D (vec_unpacks_hi_optab, "vec_unpacks_hi_$a")
+OPTAB_D (vec_unpacks_lo_optab, "vec_unpacks_lo_$a")
+OPTAB_D (vec_unpacks_sbool_hi_optab, "vec_unpacks_sbool_hi_$a")
+OPTAB_D (vec_unpacks_sbool_lo_optab, "vec_unpacks_sbool_lo_$a")
+OPTAB_D (vec_unpacku_float_hi_optab, "vec_unpacku_float_hi_$a")
+OPTAB_D (vec_unpacku_float_lo_optab, "vec_unpacku_float_lo_$a")
+OPTAB_D (vec_unpacku_hi_optab, "vec_unpacku_hi_$a")
+OPTAB_D (vec_unpacku_lo_optab, "vec_unpacku_lo_$a")
+OPTAB_D (vec_widen_smult_even_optab, "vec_widen_smult_even_$a")
+OPTAB_D (vec_widen_smult_hi_optab, "vec_widen_smult_hi_$a")
+OPTAB_D (vec_widen_smult_lo_optab, "vec_widen_smult_lo_$a")
+OPTAB_D (vec_widen_smult_odd_optab, "vec_widen_smult_odd_$a")
+OPTAB_D (vec_widen_ssubl_hi_optab, "vec_widen_ssubl_hi_$a")
+OPTAB_D (vec_widen_ssubl_lo_optab, "vec_widen_ssubl_lo_$a")
+OPTAB_D (vec_widen_saddl_hi_optab, "vec_widen_saddl_hi_$a")
+OPTAB_D (vec_widen_saddl_lo_optab, "vec_widen_saddl_lo_$a")
+OPTAB_D (vec_widen_sshiftl_hi_optab, "vec_widen_sshiftl_hi_$a")
+OPTAB_D (vec_widen_sshiftl_lo_optab, "vec_widen_sshiftl_lo_$a")
+OPTAB_D (vec_widen_umult_even_optab, "vec_widen_umult_even_$a")
+OPTAB_D (vec_widen_umult_hi_optab, "vec_widen_umult_hi_$a")
+OPTAB_D (vec_widen_umult_lo_optab, "vec_widen_umult_lo_$a")
+OPTAB_D (vec_widen_umult_odd_optab, "vec_widen_umult_odd_$a")
+OPTAB_D (vec_widen_ushiftl_hi_optab, "vec_widen_ushiftl_hi_$a")
+OPTAB_D (vec_widen_ushiftl_lo_optab, "vec_widen_ushiftl_lo_$a")
+OPTAB_D (vec_widen_usubl_hi_optab, "vec_widen_usubl_hi_$a")
+OPTAB_D (vec_widen_usubl_lo_optab, "vec_widen_usubl_lo_$a")
+OPTAB_D (vec_widen_uaddl_hi_optab, "vec_widen_uaddl_hi_$a")
+OPTAB_D (vec_widen_uaddl_lo_optab, "vec_widen_uaddl_lo_$a")
+OPTAB_D (vec_addsub_optab, "vec_addsub$a3")
+OPTAB_D (vec_fmaddsub_optab, "vec_fmaddsub$a4")
+OPTAB_D (vec_fmsubadd_optab, "vec_fmsubadd$a4")
+
+OPTAB_D (sync_add_optab, "sync_add$I$a")
+OPTAB_D (sync_and_optab, "sync_and$I$a")
+OPTAB_D (sync_ior_optab, "sync_ior$I$a")
+OPTAB_D (sync_lock_release_optab, "sync_lock_release$I$a")
+OPTAB_D (sync_nand_optab, "sync_nand$I$a")
+OPTAB_D (sync_sub_optab, "sync_sub$I$a")
+OPTAB_D (sync_xor_optab, "sync_xor$I$a")
+
+OPTAB_D (atomic_add_fetch_optab, "atomic_add_fetch$I$a")
+OPTAB_D (atomic_add_optab, "atomic_add$I$a")
+OPTAB_D (atomic_and_fetch_optab, "atomic_and_fetch$I$a")
+OPTAB_D (atomic_and_optab, "atomic_and$I$a")
+OPTAB_D (atomic_bit_test_and_set_optab, "atomic_bit_test_and_set$I$a")
+OPTAB_D (atomic_bit_test_and_complement_optab, "atomic_bit_test_and_complement$I$a")
+OPTAB_D (atomic_bit_test_and_reset_optab, "atomic_bit_test_and_reset$I$a")
+OPTAB_D (atomic_compare_and_swap_optab, "atomic_compare_and_swap$I$a")
+OPTAB_D (atomic_exchange_optab, "atomic_exchange$I$a")
+OPTAB_D (atomic_fetch_add_optab, "atomic_fetch_add$I$a")
+OPTAB_D (atomic_fetch_and_optab, "atomic_fetch_and$I$a")
+OPTAB_D (atomic_fetch_nand_optab, "atomic_fetch_nand$I$a")
+OPTAB_D (atomic_fetch_or_optab, "atomic_fetch_or$I$a")
+OPTAB_D (atomic_fetch_sub_optab, "atomic_fetch_sub$I$a")
+OPTAB_D (atomic_fetch_xor_optab, "atomic_fetch_xor$I$a")
+OPTAB_D (atomic_load_optab, "atomic_load$I$a")
+OPTAB_D (atomic_nand_fetch_optab, "atomic_nand_fetch$I$a")
+OPTAB_D (atomic_nand_optab, "atomic_nand$I$a")
+OPTAB_D (atomic_or_fetch_optab, "atomic_or_fetch$I$a")
+OPTAB_D (atomic_or_optab, "atomic_or$I$a")
+OPTAB_D (atomic_store_optab, "atomic_store$I$a")
+OPTAB_D (atomic_sub_fetch_optab, "atomic_sub_fetch$I$a")
+OPTAB_D (atomic_sub_optab, "atomic_sub$I$a")
+OPTAB_D (atomic_xor_fetch_optab, "atomic_xor_fetch$I$a")
+OPTAB_D (atomic_xor_optab, "atomic_xor$I$a")
+OPTAB_D (atomic_add_fetch_cmp_0_optab, "atomic_add_fetch_cmp_0$I$a")
+OPTAB_D (atomic_sub_fetch_cmp_0_optab, "atomic_sub_fetch_cmp_0$I$a")
+OPTAB_D (atomic_and_fetch_cmp_0_optab, "atomic_and_fetch_cmp_0$I$a")
+OPTAB_D (atomic_or_fetch_cmp_0_optab, "atomic_or_fetch_cmp_0$I$a")
+OPTAB_D (atomic_xor_fetch_cmp_0_optab, "atomic_xor_fetch_cmp_0$I$a")
+
+OPTAB_D (get_thread_pointer_optab, "get_thread_pointer$I$a")
+OPTAB_D (set_thread_pointer_optab, "set_thread_pointer$I$a")
+
+OPTAB_D (check_raw_ptrs_optab, "check_raw_ptrs$a")
+OPTAB_D (check_war_ptrs_optab, "check_war_ptrs$a")
+
+OPTAB_DC (vec_duplicate_optab, "vec_duplicate$a", VEC_DUPLICATE)
+OPTAB_DC (vec_series_optab, "vec_series$a", VEC_SERIES)
+OPTAB_D (vec_shl_insert_optab, "vec_shl_insert_$a")
+OPTAB_D (len_load_optab, "len_load_$a")
+OPTAB_D (len_store_optab, "len_store_$a")
diff --git a/support/cpp/gcc/optabs.h b/support/cpp/gcc/optabs.h
new file mode 100644
index 000000000..cfd7c742d
--- /dev/null
+++ b/support/cpp/gcc/optabs.h
@@ -0,0 +1,383 @@
+/* Definitions for code generation pass of GNU compiler.
+ Copyright (C) 2001-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_OPTABS_H
+#define GCC_OPTABS_H
+
+#include "optabs-query.h"
+#include "optabs-libfuncs.h"
+#include "vec-perm-indices.h"
+
+/* Generate code for a widening multiply. */
+extern rtx expand_widening_mult (machine_mode, rtx, rtx, rtx, int, optab);
+
+/* Describes the type of an expand_operand. Each value is associated
+ with a create_*_operand function; see the comments above those
+ functions for details. */
+enum expand_operand_type {
+ EXPAND_FIXED,
+ EXPAND_OUTPUT,
+ EXPAND_INPUT,
+ EXPAND_CONVERT_TO,
+ EXPAND_CONVERT_FROM,
+ EXPAND_ADDRESS,
+ EXPAND_INTEGER
+};
+
+/* Information about an operand for instruction expansion. */
+class expand_operand {
+public:
+ /* The type of operand. */
+ ENUM_BITFIELD (expand_operand_type) type : 8;
+
+ /* True if any conversion should treat VALUE as being unsigned
+ rather than signed. Only meaningful for certain types. */
+ unsigned int unsigned_p : 1;
+
+ /* Is the target operand. */
+ unsigned int target : 1;
+
+ /* Unused; available for future use. */
+ unsigned int unused : 6;
+
+ /* The mode passed to the convert_*_operand function. It has a
+ type-dependent meaning. */
+ ENUM_BITFIELD (machine_mode) mode : 16;
+
+ /* The value of the operand. */
+ rtx value;
+
+ /* The value of an EXPAND_INTEGER operand. */
+ poly_int64 int_value;
+};
+
+/* Initialize OP with the given fields. Initialise the other fields
+ to their default values. */
+
+static inline void
+create_expand_operand (class expand_operand *op,
+ enum expand_operand_type type,
+ rtx value, machine_mode mode,
+ bool unsigned_p, poly_int64 int_value = 0)
+{
+ op->type = type;
+ op->unsigned_p = unsigned_p;
+ op->target = 0;
+ op->unused = 0;
+ op->mode = mode;
+ op->value = value;
+ op->int_value = int_value;
+}
+
+/* Make OP describe an operand that must use rtx X, even if X is volatile. */
+
+static inline void
+create_fixed_operand (class expand_operand *op, rtx x)
+{
+ create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false);
+}
+
+/* Make OP describe an output operand that must have mode MODE.
+ X, if nonnull, is a suggestion for where the output should be stored.
+ It is OK for VALUE to be inconsistent with MODE, although it will just
+ be ignored in that case. */
+
+static inline void
+create_output_operand (class expand_operand *op, rtx x,
+ machine_mode mode)
+{
+ create_expand_operand (op, EXPAND_OUTPUT, x, mode, false);
+}
+
+/* Make OP describe an input operand that must have mode MODE and
+ value VALUE; MODE cannot be VOIDmode. The backend may request that
+ VALUE be copied into a different kind of rtx before being passed
+ as an operand. */
+
+static inline void
+create_input_operand (class expand_operand *op, rtx value,
+ machine_mode mode)
+{
+ create_expand_operand (op, EXPAND_INPUT, value, mode, false);
+}
+
+/* Like create_input_operand, except that VALUE must first be converted
+ to mode MODE. UNSIGNED_P says whether VALUE is unsigned. */
+
+static inline void
+create_convert_operand_to (class expand_operand *op, rtx value,
+ machine_mode mode, bool unsigned_p)
+{
+ create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p);
+}
+
+/* Make OP describe an input operand that should have the same value
+ as VALUE, after any mode conversion that the backend might request.
+ If VALUE is a CONST_INT, it should be treated as having mode MODE.
+ UNSIGNED_P says whether VALUE is unsigned.
+
+ The conversion of VALUE can include a combination of numerical
+ conversion (as for convert_modes) and duplicating a scalar to fill
+ a vector (if VALUE is a scalar but the operand is a vector). */
+
+static inline void
+create_convert_operand_from (class expand_operand *op, rtx value,
+ machine_mode mode, bool unsigned_p)
+{
+ create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p);
+}
+
+
+/* Make OP describe an input Pmode address operand. VALUE is the value
+ of the address, but it may need to be converted to Pmode first. */
+
+static inline void
+create_address_operand (class expand_operand *op, rtx value)
+{
+ create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false);
+}
+
+extern void create_integer_operand (class expand_operand *, poly_int64);
+
+/* Passed to expand_simple_binop and expand_binop to say which options
+ to try to use if the requested operation can't be open-coded on the
+ requisite mode. Either OPTAB_LIB or OPTAB_LIB_WIDEN says try using
+ a library call. Either OPTAB_WIDEN or OPTAB_LIB_WIDEN says try
+ using a wider mode. OPTAB_MUST_WIDEN says try widening and don't
+ try anything else. */
+
+enum optab_methods
+{
+ OPTAB_DIRECT,
+ OPTAB_LIB,
+ OPTAB_WIDEN,
+ OPTAB_LIB_WIDEN,
+ OPTAB_MUST_WIDEN
+};
+
+extern rtx expand_widen_pattern_expr (struct separate_ops *, rtx , rtx , rtx,
+ rtx, int);
+extern rtx expand_ternary_op (machine_mode mode, optab ternary_optab,
+ rtx op0, rtx op1, rtx op2, rtx target,
+ int unsignedp);
+extern rtx simplify_expand_binop (machine_mode mode, optab binoptab,
+ rtx op0, rtx op1, rtx target, int unsignedp,
+ enum optab_methods methods);
+extern bool force_expand_binop (machine_mode, optab, rtx, rtx, rtx, int,
+ enum optab_methods);
+extern rtx expand_vector_broadcast (machine_mode, rtx);
+
+extern rtx expand_doubleword_divmod (machine_mode, rtx, rtx, rtx *, bool);
+
+/* Generate code for a simple binary or unary operation. "Simple" in
+ this case means "can be unambiguously described by a (mode, code)
+ pair and mapped to a single optab." */
+extern rtx expand_simple_binop (machine_mode, enum rtx_code, rtx,
+ rtx, rtx, int, enum optab_methods);
+
+/* Expand a binary operation given optab and rtx operands. */
+extern rtx expand_binop (machine_mode, optab, rtx, rtx, rtx, int,
+ enum optab_methods);
+
+/* Expand a binary operation with both signed and unsigned forms. */
+extern rtx sign_expand_binop (machine_mode, optab, optab, rtx, rtx,
+ rtx, int, enum optab_methods);
+
+/* Generate code to perform an operation on one operand with two results. */
+extern int expand_twoval_unop (optab, rtx, rtx, rtx, int);
+
+/* Generate code to perform an operation on two operands with two results. */
+extern int expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int);
+
+/* Generate code to perform an operation on two operands with two
+ results, using a library function. */
+extern bool expand_twoval_binop_libfunc (optab, rtx, rtx, rtx, rtx,
+ enum rtx_code);
+extern rtx expand_simple_unop (machine_mode, enum rtx_code, rtx, rtx,
+ int);
+
+/* Expand a unary arithmetic operation given optab rtx operand. */
+extern rtx expand_unop (machine_mode, optab, rtx, rtx, int);
+
+/* Expand the absolute value operation. */
+extern rtx expand_abs_nojump (machine_mode, rtx, rtx, int);
+extern rtx expand_abs (machine_mode, rtx, rtx, int, int);
+
+/* Expand the one's complement absolute value operation. */
+extern rtx expand_one_cmpl_abs_nojump (machine_mode, rtx, rtx);
+
+/* Expand the copysign operation. */
+extern rtx expand_copysign (rtx, rtx, rtx);
+/* Generate an instruction with a given INSN_CODE with an output and
+ an input. */
+extern bool maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
+extern void emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
+
+/* Emit code to make a call to a constant function or a library call. */
+extern void emit_libcall_block (rtx_insn *, rtx, rtx, rtx);
+
+/* The various uses that a comparison can have; used by can_compare_p:
+ jumps, conditional moves, store flag operations. */
+enum can_compare_purpose
+{
+ ccp_jump,
+ ccp_cmov,
+ ccp_store_flag
+};
+
+/* Nonzero if a compare of mode MODE can be done straightforwardly
+ (without splitting it into pieces). */
+extern int can_compare_p (enum rtx_code, machine_mode,
+ enum can_compare_purpose);
+
+/* Return whether the backend can emit a vector comparison (vec_cmp/vec_cmpu)
+ for code CODE, comparing operands of mode VALUE_MODE and producing a result
+ with MASK_MODE. */
+extern bool can_vec_cmp_compare_p (enum rtx_code, machine_mode, machine_mode);
+
+/* Return whether the backend can emit a vector comparison (vcond/vcondu) for
+ code CODE, comparing operands of mode CMP_OP_MODE and producing a result
+ with VALUE_MODE. */
+extern bool can_vcond_compare_p (enum rtx_code, machine_mode, machine_mode);
+
+/* Return whether the backend can emit vector set instructions for inserting
+ element into vector at variable index position. */
+extern bool can_vec_set_var_idx_p (machine_mode);
+
+extern rtx prepare_operand (enum insn_code, rtx, int, machine_mode,
+ machine_mode, int);
+/* Emit a pair of rtl insns to compare two rtx's and to jump
+ to a label if the comparison is true. */
+extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx,
+ machine_mode, int, rtx,
+ profile_probability prob
+ = profile_probability::uninitialized ());
+
+/* Generate code to indirectly jump to a location given in the rtx LOC. */
+extern void emit_indirect_jump (rtx);
+
+#include "insn-config.h"
+
+#ifndef GCC_INSN_CONFIG_H
+#error "insn-config.h must be included before optabs.h"
+#endif
+
+/* Emit a conditional move operation. */
+rtx emit_conditional_move (rtx, rtx_comparison, rtx, rtx, machine_mode, int);
+rtx emit_conditional_move (rtx, rtx, rtx, rtx, rtx, machine_mode);
+
+/* Emit a conditional negate or bitwise complement operation. */
+rtx emit_conditional_neg_or_complement (rtx, rtx_code, machine_mode, rtx,
+ rtx, rtx);
+
+rtx emit_conditional_add (rtx, enum rtx_code, rtx, rtx, machine_mode,
+ rtx, rtx, machine_mode, int);
+
+/* Create but don't emit one rtl instruction to perform certain operations.
+ Modes must match; operands must meet the operation's predicates.
+ Likewise for subtraction and for just copying. */
+extern rtx_insn *gen_add2_insn (rtx, rtx);
+extern rtx_insn *gen_add3_insn (rtx, rtx, rtx);
+extern int have_add2_insn (rtx, rtx);
+extern rtx_insn *gen_addptr3_insn (rtx, rtx, rtx);
+extern int have_addptr3_insn (rtx, rtx, rtx);
+extern rtx_insn *gen_sub2_insn (rtx, rtx);
+extern rtx_insn *gen_sub3_insn (rtx, rtx, rtx);
+extern int have_sub2_insn (rtx, rtx);
+
+/* Generate the body of an insn to extend Y (with mode MFROM)
+ into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
+extern rtx_insn *gen_extend_insn (rtx, rtx, machine_mode, machine_mode, int);
+
+/* Generate code for a FLOAT_EXPR. */
+extern void expand_float (rtx, rtx, int);
+
+/* Generate code for a FIX_EXPR. */
+extern void expand_fix (rtx, rtx, int);
+
+/* Generate code for a FIXED_CONVERT_EXPR. */
+extern void expand_fixed_convert (rtx, rtx, int, int);
+
+/* Generate code for float to integral conversion. */
+extern bool expand_sfix_optab (rtx, rtx, convert_optab);
+
+/* Report whether the machine description contains an insn which can
+ perform the operation described by CODE and MODE. */
+extern int have_insn_for (enum rtx_code, machine_mode);
+
+/* Generate a conditional trap instruction. */
+extern rtx_insn *gen_cond_trap (enum rtx_code, rtx, rtx, rtx);
+
+/* Generate code for VEC_PERM_EXPR. */
+extern rtx expand_vec_perm_var (machine_mode, rtx, rtx, rtx, rtx);
+extern rtx expand_vec_perm_const (machine_mode, rtx, rtx,
+ const vec_perm_builder &, machine_mode, rtx);
+
+/* Generate code for vector comparison. */
+extern rtx expand_vec_cmp_expr (tree, tree, rtx);
+
+/* Generate code for VEC_SERIES_EXPR. */
+extern rtx expand_vec_series_expr (machine_mode, rtx, rtx, rtx);
+
+/* Generate code for MULT_HIGHPART_EXPR. */
+extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool);
+
+extern rtx expand_sync_lock_test_and_set (rtx, rtx, rtx);
+extern rtx expand_atomic_test_and_set (rtx, rtx, enum memmodel);
+extern rtx expand_atomic_exchange (rtx, rtx, rtx, enum memmodel);
+extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
+ enum memmodel, enum memmodel);
+/* Generate memory barriers. */
+extern void expand_mem_thread_fence (enum memmodel);
+extern void expand_mem_signal_fence (enum memmodel);
+
+rtx expand_atomic_load (rtx, rtx, enum memmodel);
+rtx expand_atomic_store (rtx, rtx, enum memmodel, bool);
+rtx expand_atomic_fetch_op (rtx, rtx, rtx, enum rtx_code, enum memmodel,
+ bool);
+
+extern void expand_asm_reg_clobber_mem_blockage (HARD_REG_SET);
+
+extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
+ rtx operand);
+extern bool valid_multiword_target_p (rtx);
+extern void create_convert_operand_from_type (class expand_operand *op,
+ rtx value, tree type);
+extern bool maybe_legitimize_operands (enum insn_code icode,
+ unsigned int opno, unsigned int nops,
+ class expand_operand *ops);
+extern rtx_insn *maybe_gen_insn (enum insn_code icode, unsigned int nops,
+ class expand_operand *ops);
+extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops,
+ class expand_operand *ops);
+extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
+ class expand_operand *ops);
+extern void expand_insn (enum insn_code icode, unsigned int nops,
+ class expand_operand *ops);
+extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
+ class expand_operand *ops);
+
+extern enum rtx_code get_rtx_code_1 (enum tree_code tcode, bool unsignedp);
+extern enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp);
+extern rtx vector_compare_rtx (machine_mode cmp_mode, enum tree_code tcode,
+ tree t_op0, tree t_op1, bool unsignedp,
+ enum insn_code icode, unsigned int opno);
+
+
+#endif /* GCC_OPTABS_H */
diff --git a/support/cpp/gcc/optc-gen.awk b/support/cpp/gcc/optc-gen.awk
new file mode 100644
index 000000000..2bd58a17c
--- /dev/null
+++ b/support/cpp/gcc/optc-gen.awk
@@ -0,0 +1,674 @@
+# Copyright (C) 2003-2022 Free Software Foundation, Inc.
+# Contributed by Kelley Cook, June 2004.
+# Original code from Neil Booth, May 2003.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records generated from
+# opt-gather.awk, combines the flags of duplicate options and generates a
+# C file.
+#
+
+# This program uses functions from opt-functions.awk and code from
+# opt-read.awk.
+#
+# Usage: awk -f opt-functions.awk -f opt-read.awk -f optc-gen.awk \
+# [-v header_name=header.h] < inputfile > options.cc
+
+# Dump that array of options into a C file.
+END {
+
+
+# Combine the flags of identical switches. Switches
+# appear many times if they are handled by many front
+# ends, for example.
+for (i = 0; i < n_opts; i++) {
+ merged_flags[i] = flags[i]
+}
+for (i = 0; i < n_opts; i++) {
+ while(i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ merged_flags[i + 1] = merged_flags[i] " " merged_flags[i + 1];
+ i++;
+ }
+}
+
+# Record EnabledBy and LangEnabledBy uses.
+n_enabledby = 0;
+for (i = 0; i < n_langs; i++) {
+ n_enabledby_lang[i] = 0;
+}
+for (i = 0; i < n_opts; i++) {
+ enabledby_arg = opt_args("EnabledBy", flags[i]);
+ if (enabledby_arg != "") {
+ logical_and = index(enabledby_arg, " && ");
+ if (logical_and != 0) {
+ # EnabledBy(arg1 && arg2)
+ split_sep = " && ";
+ } else {
+ # EnabledBy(arg) or EnabledBy(arg1 || arg2 || arg3)
+ split_sep = " \\|\\| ";
+ }
+ n_enabledby_names = split(enabledby_arg, enabledby_names, split_sep);
+ if (logical_and != 0 && n_enabledby_names > 2) {
+ print "#error " opts[i] " EnabledBy(Wfoo && Wbar && Wbaz) currently not supported"
+ }
+ for (j = 1; j <= n_enabledby_names; j++) {
+ enabledby_name = enabledby_names[j];
+ enabledby_index = opt_numbers[enabledby_name];
+ if (enabledby_index == "") {
+ print "#error " opts[i] " Enabledby(" enabledby_name "), unknown option '" enabledby_name "'"
+ } else if (!flag_set_p("Common", merged_flags[enabledby_index])) {
+ print "#error " opts[i] " Enabledby(" enabledby_name "), '" \
+ enabledby_name "' must have flag 'Common'" \
+ " to use Enabledby(), otherwise use LangEnabledBy()"
+ } else {
+ condition = "";
+ if (logical_and != 0) {
+ opt_var_name_1 = search_var_name(enabledby_names[1], opt_numbers, opts, flags, n_opts);
+ opt_var_name_2 = search_var_name(enabledby_names[2], opt_numbers, opts, flags, n_opts);
+ if (opt_var_name_1 == "") {
+ print "#error " enabledby_names[1] " does not have a Var() flag"
+ }
+ if (opt_var_name_2 == "") {
+ print "#error " enabledby_names[2] " does not have a Var() flag"
+ }
+ condition = "opts->x_" opt_var_name_1 " && opts->x_" opt_var_name_2;
+ }
+ if (enables[enabledby_name] == "") {
+ enabledby[n_enabledby] = enabledby_name;
+ n_enabledby++;
+ }
+ enables[enabledby_name] = enables[enabledby_name] opts[i] ";";
+ enablesif[enabledby_name] = enablesif[enabledby_name] condition ";";
+ }
+ }
+ }
+
+ enabledby_arg = opt_args("LangEnabledBy", flags[i]);
+ if (enabledby_arg != "") {
+ enabledby_n_args = n_args(enabledby_arg)
+ if (enabledby_n_args != 2 \
+ && enabledby_n_args != 4) {
+ print "#error " opts[i] " LangEnabledBy(" enabledby_arg ") must specify two or four arguments"
+ }
+
+ enabledby_langs = nth_arg(0, enabledby_arg);
+ if (enabledby_langs == "")
+ print "#error " opts[i] " LangEnabledBy(" enabledby_arg ") must specify LANGUAGE"
+ enabledby_opt = nth_arg(1, enabledby_arg);
+ if (enabledby_opt == "")
+ print "#error " opts[i] " LangEnabledBy(" enabledby_arg ") must specify OPT"
+
+ enabledby_posarg_negarg = ""
+ if (enabledby_n_args == 4) {
+ enabledby_posarg = nth_arg(2, enabledby_arg);
+ enabledby_negarg = nth_arg(3, enabledby_arg);
+ if (enabledby_posarg == "" \
+ || enabledby_negarg == "")
+ print "#error " opts[i] " LangEnabledBy(" enabledby_arg ") with four arguments must specify POSARG and NEGARG"
+ else
+ enabledby_posarg_negarg = "," enabledby_posarg "," enabledby_negarg
+ }
+
+ n_enabledby_arg_langs = split(enabledby_langs, enabledby_arg_langs, " ");
+ n_enabledby_array = split(enabledby_opt, enabledby_array, " \\|\\| ");
+ for (k = 1; k <= n_enabledby_array; k++) {
+ enabledby_index = opt_numbers[enabledby_array[k]];
+ if (enabledby_index == "") {
+ print "#error " opts[i] " LangEnabledBy(" enabledby_arg "), unknown option '" enabledby_opt "'"
+ continue
+ }
+
+ for (j = 1; j <= n_enabledby_arg_langs; j++) {
+ lang_name = enabledby_arg_langs[j]
+ lang_index = lang_numbers[lang_name];
+ if (lang_index == "") {
+ print "// #error " opts[i] " LangEnabledBy(" enabledby_arg "), unknown language '" lang_name "'"
+ continue
+ }
+
+ lang_name = lang_sanitized_name(lang_name);
+
+ if (enables[lang_name,enabledby_array[k]] == "") {
+ enabledby[lang_name,n_enabledby_lang[lang_index]] = enabledby_array[k];
+ n_enabledby_lang[lang_index]++;
+ }
+ enables[lang_name,enabledby_array[k]] \
+ = enables[lang_name,enabledby_array[k]] opts[i] enabledby_posarg_negarg ";";
+ }
+ }
+ }
+
+ if (flag_set_p("Param", flags[i]) && !(opts[i] ~ "^-param="))
+ print "#error Parameter option name '" opts[i] "' must start with '-param='"
+}
+
+
+print "/* This file is auto-generated by optc-gen.awk. */"
+print ""
+n_headers = split(header_name, headers, " ")
+for (i = 1; i <= n_headers; i++)
+ print "#include " quote headers[i] quote
+print "#include " quote "opts.h" quote
+print "#include " quote "intl.h" quote
+print "#include " quote "insn-attr-common.h" quote
+print ""
+
+if (n_extra_c_includes > 0) {
+ for (i = 0; i < n_extra_c_includes; i++) {
+ print "#include " quote extra_c_includes[i] quote
+ }
+ print ""
+}
+
+for (i = 0; i < n_enums; i++) {
+ name = enum_names[i]
+ type = enum_type[name]
+ print "static const struct cl_enum_arg cl_enum_" name \
+ "_data[] = "
+ print "{"
+ print enum_data[name] " { NULL, 0, 0 }"
+ print "};"
+ print ""
+ print "static void"
+ print "cl_enum_" name "_set (void *var, int value)"
+ print "{"
+ print " *((" type " *) var) = (" type ") value;"
+ print "}"
+ print ""
+ print "static int"
+ print "cl_enum_" name "_get (const void *var)"
+ print "{"
+ print " return (int) *((const " type " *) var);"
+ print "}"
+ print ""
+}
+
+print "const struct cl_enum cl_enums[] ="
+print "{"
+for (i = 0; i < n_enums; i++) {
+ name = enum_names[i]
+ ehelp = enum_help[name]
+ if (ehelp == "")
+ ehelp = "NULL"
+ else
+ ehelp = quote ehelp quote
+ unknown_error = enum_unknown_error[name]
+ if (unknown_error == "")
+ unknown_error = "NULL"
+ else
+ unknown_error = quote unknown_error quote
+ print " {"
+ print " " ehelp ","
+ print " " unknown_error ","
+ print " cl_enum_" name "_data,"
+ print " sizeof (" enum_type[name] "),"
+ print " cl_enum_" name "_set,"
+ print " cl_enum_" name "_get"
+ print " },"
+}
+print "};"
+print "const unsigned int cl_enums_count = " n_enums ";"
+print ""
+
+print "const struct gcc_options global_options_init =\n{"
+for (i = 0; i < n_extra_vars; i++) {
+ var = extra_vars[i]
+ init = extra_vars[i]
+ if (var ~ "=" ) {
+ sub(".*= *", "", init)
+ } else {
+ init = "0"
+ }
+ sub(" *=.*", "", var)
+ name = var
+ sub("^.*[ *]", "", name)
+ sub("\\[.*\\]$", "", name)
+ var_seen[name] = 1
+ print " " init ", /* " name " */"
+}
+for (i = 0; i < n_opts; i++) {
+ name = var_name(flags[i]);
+ init = opt_args("Init", flags[i])
+
+ if (name == "") {
+ if (init != "")
+ print "#error " opts[i] " must specify Var to use Init"
+ continue;
+ }
+
+ if (init != "") {
+ if (name in var_init && var_init[name] != init)
+ print "#error multiple initializers for " name
+ var_init[name] = init
+ }
+}
+for (i = 0; i < n_opts; i++) {
+ name = var_name(flags[i]);
+ if (name == "")
+ continue;
+
+ if (name in var_seen)
+ continue;
+
+ if (name in var_init)
+ init = var_init[name]
+ else
+ init = "0"
+
+ print " " init ", /* " name " */"
+
+ var_seen[name] = 1;
+}
+for (i = 0; i < n_opts; i++) {
+ name = static_var(opts[i], flags[i]);
+ if (name != "") {
+ print " 0, /* " name " (private state) */"
+ print "#undef x_" name
+ }
+}
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("SetByCombined", flags[i]))
+ print " false, /* frontend_set_" var_name(flags[i]) " */"
+}
+print "};"
+print ""
+print "struct gcc_options global_options;"
+print "struct gcc_options global_options_set;"
+print ""
+
+print "const char * const lang_names[] =\n{"
+for (i = 0; i < n_langs; i++) {
+ macros[i] = "CL_" lang_sanitized_name(langs[i])
+ s = substr(" ", length (macros[i]))
+ print " " quote langs[i] quote ","
+ }
+
+print " 0\n};\n"
+print "const unsigned int cl_options_count = N_OPTS;\n"
+print "#if (1U << " n_langs ") > CL_MIN_OPTION_CLASS"
+print " #error the number of languages exceeds the implementation limit"
+print "#endif"
+print "const unsigned int cl_lang_count = " n_langs ";\n"
+
+print "const struct cl_option cl_options[] =\n{"
+
+j = 0
+for (i = 0; i < n_opts; i++) {
+ back_chain[i] = "N_OPTS";
+ indices[opts[i]] = j;
+ # Combine the flags of identical switches. Switches
+ # appear many times if they are handled by many front
+ # ends, for example.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ flags[i + 1] = flags[i] " " flags[i + 1];
+ if (help[i + 1] == "")
+ help[i + 1] = help[i]
+ else if (help[i] != "" && help[i + 1] != help[i]) {
+ print "#error Multiple different help strings for " \
+ opts[i] ":"
+ print "#error " help[i]
+ print "#error " help[i + 1]
+ }
+
+ i++;
+ back_chain[i] = "N_OPTS";
+ indices[opts[i]] = j;
+ }
+ j++;
+}
+
+optindex = 0
+for (i = 0; i < n_opts; i++) {
+ # With identical flags, pick only the last one. The
+ # earlier loop ensured that it has all flags merged,
+ # and a nonempty help text if one of the texts was nonempty.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ i++;
+ }
+
+ len = length (opts[i]);
+ enum = opt_enum(opts[i])
+
+ # If this switch takes joined arguments, back-chain all
+ # subsequent switches to it for which it is a prefix. If
+ # a later switch S is a longer prefix of a switch T, T
+ # will be back-chained to S in a later iteration of this
+ # for() loop, which is what we want.
+ if (flag_set_p("Joined.*", flags[i])) {
+ for (j = i + 1; j < n_opts; j++) {
+ if (substr (opts[j], 1, len) != opts[i])
+ break;
+ back_chain[j] = enum;
+ }
+ }
+
+ s = substr(" ", length (opts[i]))
+ if (i + 1 == n_opts)
+ comma = ""
+
+ if (help[i] == "")
+ hlp = "NULL"
+ else
+ hlp = quote help[i] quote;
+
+ missing_arg_error = opt_args("MissingArgError", flags[i])
+ if (missing_arg_error == "")
+ missing_arg_error = "NULL"
+ else
+ missing_arg_error = quote missing_arg_error quote
+
+
+ warn_message = opt_args("Warn", flags[i])
+ if (warn_message == "")
+ warn_message = "NULL"
+ else
+ warn_message = quote warn_message quote
+
+ alias_arg = opt_args("Alias", flags[i])
+ if (alias_arg == "") {
+ if (flag_set_p("Ignore", flags[i])) {
+ alias_data = "NULL, NULL, OPT_SPECIAL_ignore"
+ if (warn_message != "NULL")
+ print "#error Ignored option with Warn"
+ if (var_name(flags[i]) != "")
+ print "#error Ignored option with Var"
+ }
+ else if (flag_set_p("Deprecated", flags[i]))
+ print "#error Deprecated was replaced with WarnRemoved"
+ else if (flag_set_p("WarnRemoved", flags[i])) {
+ alias_data = "NULL, NULL, OPT_SPECIAL_warn_removed"
+ if (warn_message != "NULL")
+ print "#error WarnRemoved option with Warn"
+ }
+ else
+ alias_data = "NULL, NULL, N_OPTS"
+ if (flag_set_p("Enum.*", flags[i])) {
+ if (!flag_set_p("RejectNegative", flags[i]) \
+ && !flag_set_p("EnumSet", flags[i]) \
+ && !flag_set_p("EnumBitSet", flags[i]) \
+ && opts[i] ~ "^[Wfgm]")
+ print "#error Enum allowing negative form"
+ }
+ } else {
+ alias_opt = nth_arg(0, alias_arg)
+ alias_posarg = nth_arg(1, alias_arg)
+ alias_negarg = nth_arg(2, alias_arg)
+
+ if (var_ref(opts[i], flags[i]) != "(unsigned short) -1")
+ print "#error Alias setting variable"
+
+ if (alias_posarg != "" && alias_negarg == "") {
+ if (!flag_set_p("RejectNegative", flags[i]) \
+ && opts[i] ~ "^[Wfm]")
+ print "#error Alias with single argument " \
+ "allowing negative form"
+ }
+ if (alias_posarg != "" \
+ && flag_set_p("NegativeAlias", flags[i])) {
+ print "#error Alias with multiple arguments " \
+ "used with NegativeAlias"
+ }
+
+ alias_opt = opt_enum(alias_opt)
+ if (alias_posarg == "")
+ alias_posarg = "NULL"
+ else
+ alias_posarg = quote alias_posarg quote
+ if (alias_negarg == "")
+ alias_negarg = "NULL"
+ else
+ alias_negarg = quote alias_negarg quote
+ alias_data = alias_posarg ", " alias_negarg ", " alias_opt
+ }
+
+ neg = opt_args("Negative", flags[i]);
+ if (neg != "")
+ idx = indices[neg]
+ else {
+ if (flag_set_p("RejectNegative", flags[i]))
+ idx = -1;
+ else {
+ if (opts[i] ~ "^[Wfgm]")
+ idx = indices[opts[i]];
+ else
+ idx = -1;
+ }
+ }
+ # Split the printf after %u to work around an ia64-hp-hpux11.23
+ # awk bug.
+ printf(" /* [%i] = */ {\n", optindex)
+ printf(" %c-%s%c,\n %s,\n %s,\n %s,\n %s, %s, %u,",
+ quote, opts[i], quote, hlp, missing_arg_error, warn_message,
+ alias_data, back_chain[i], len)
+ printf(" /* .neg_idx = */ %d,\n", idx)
+ condition = opt_args("Condition", flags[i])
+ cl_flags = switch_flags(flags[i])
+ cl_bit_fields = switch_bit_fields(flags[i])
+ cl_zero_bit_fields = switch_bit_fields("")
+ if (condition != "")
+ printf("#if %s\n" \
+ " %s,\n" \
+ " 0, %s,\n" \
+ "#else\n" \
+ " 0,\n" \
+ " 1 /* Disabled. */, %s,\n" \
+ "#endif\n",
+ condition, cl_flags, cl_bit_fields, cl_zero_bit_fields)
+ else
+ printf(" %s,\n" \
+ " 0, %s,\n",
+ cl_flags, cl_bit_fields)
+ printf(" %s, %s, %s }%s\n", var_ref(opts[i], flags[i]),
+ var_set(flags[i]), integer_range_info(opt_args("IntegerRange", flags[i]),
+ opt_args("Init", flags[i]), opts[i], flag_set_p("UInteger", flags[i])), comma)
+
+ # Bump up the informational option index.
+ ++optindex
+ }
+
+print "};"
+
+print "\n\n"
+print "bool "
+print "common_handle_option_auto (struct gcc_options *opts, "
+print " struct gcc_options *opts_set, "
+print " const struct cl_decoded_option *decoded, "
+print " unsigned int lang_mask, int kind, "
+print " location_t loc, "
+print " const struct cl_option_handlers *handlers, "
+print " diagnostic_context *dc) "
+print "{ "
+print " size_t scode = decoded->opt_index; "
+print " HOST_WIDE_INT value = decoded->value; "
+print " enum opt_code code = (enum opt_code) scode; "
+print " "
+print " gcc_assert (decoded->canonical_option_num_elements <= 2); "
+print " "
+print " switch (code) "
+print " { "
+# Handle EnabledBy
+for (i = 0; i < n_enabledby; i++) {
+ enabledby_name = enabledby[i];
+ print " case " opt_enum(enabledby_name) ":"
+ n_enables = split(enables[enabledby_name], thisenable, ";");
+ n_enablesif = split(enablesif[enabledby_name], thisenableif, ";");
+ if (n_enables != n_enablesif) {
+ print "#error n_enables != n_enablesif: Something went wrong!"
+ }
+ for (j = 1; j < n_enables; j++) {
+ opt_var_name = var_name(flags[opt_numbers[thisenable[j]]]);
+ if (opt_var_name != "") {
+ condition = "!opts_set->x_" opt_var_name
+ if (thisenableif[j] != "") {
+ value = "(" thisenableif[j] ")"
+ } else {
+ value = "value"
+ }
+ print " if (" condition ")"
+ print " handle_generated_option (opts, opts_set,"
+ print " " opt_enum(thisenable[j]) ", NULL, " value ","
+ print " lang_mask, kind, loc, handlers, true, dc);"
+ } else {
+ print "#error " thisenable[j] " does not have a Var() flag"
+ }
+ }
+ print " break;\n"
+}
+print " default: "
+print " break; "
+print " } "
+print " return true; "
+print "} "
+
+# Handle LangEnabledBy
+for (i = 0; i < n_langs; i++) {
+ lang_name = lang_sanitized_name(langs[i]);
+ mark_unused = " ATTRIBUTE_UNUSED";
+
+ print "\n\n"
+ print "bool "
+ print lang_name "_handle_option_auto (struct gcc_options *opts" mark_unused ", "
+ print " struct gcc_options *opts_set" mark_unused ", "
+ print " size_t scode" mark_unused ", const char *arg" mark_unused ", HOST_WIDE_INT value" mark_unused ", "
+ print " unsigned int lang_mask" mark_unused ", int kind" mark_unused ", "
+ print " location_t loc" mark_unused ", "
+ print " const struct cl_option_handlers *handlers" mark_unused ", "
+ print " diagnostic_context *dc" mark_unused ") "
+ print "{ "
+ print " enum opt_code code = (enum opt_code) scode; "
+ print " "
+ print " switch (code) "
+ print " { "
+
+ for (k = 0; k < n_enabledby_lang[i]; k++) {
+ enabledby_name = enabledby[lang_name,k];
+ print " case " opt_enum(enabledby_name) ":"
+ n_thisenable = split(enables[lang_name,enabledby_name], thisenable, ";");
+ for (j = 1; j < n_thisenable; j++) {
+ n_thisenable_args = split(thisenable[j], thisenable_args, ",");
+ if (n_thisenable_args == 1) {
+ thisenable_opt = thisenable[j];
+ value = "value";
+ } else {
+ thisenable_opt = thisenable_args[1];
+ with_posarg = thisenable_args[2];
+ with_negarg = thisenable_args[3];
+ value = "value ? " with_posarg " : " with_negarg;
+ }
+ opt_var_name = var_name(flags[opt_numbers[thisenable_opt]]);
+ if (opt_var_name != "") {
+ print " if (!opts_set->x_" opt_var_name ")"
+ print " handle_generated_option (opts, opts_set,"
+ print " " opt_enum(thisenable_opt) ", NULL, " value ","
+ print " lang_mask, kind, loc, handlers, true, dc);"
+ } else {
+ print "#error " thisenable_opt " does not have a Var() flag"
+ }
+ }
+ print " break;\n"
+ }
+ print " default: "
+ print " break; "
+ print " } "
+ print " return true; "
+ print "} "
+}
+
+#Handle CPP()
+print "\n"
+print "#include " quote "cpplib.h" quote;
+print "void"
+print "cpp_handle_option_auto (const struct gcc_options * opts, "
+print " size_t scode, struct cpp_options * cpp_opts)"
+print "{ "
+print " enum opt_code code = (enum opt_code) scode; "
+print " "
+print " switch (code) "
+print " { "
+for (i = 0; i < n_opts; i++) {
+ # With identical flags, pick only the last one. The
+ # earlier loop ensured that it has all flags merged,
+ # and a nonempty help text if one of the texts was nonempty.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ i++;
+ }
+
+ cpp_option = nth_arg(0, opt_args("CPP", flags[i]));
+ if (cpp_option != "") {
+ opt_var_name = var_name(flags[i]);
+ init = opt_args("Init", flags[i])
+ if (opt_var_name != "" && init != "") {
+ print " case " opt_enum(opts[i]) ":"
+ print " cpp_opts->" cpp_option " = opts->x_" opt_var_name ";"
+ print " break;"
+ } else if (opt_var_name == "" && init == "") {
+ print "#error CPP() requires setting Init() and Var() for " opts[i]
+ } else if (opt_var_name != "") {
+ print "#error CPP() requires setting Init() for " opts[i]
+ } else {
+ print "#error CPP() requires setting Var() for " opts[i]
+ }
+ }
+}
+print " default: "
+print " break; "
+print " } "
+print "}\n"
+print "void"
+print "init_global_opts_from_cpp(struct gcc_options * opts, "
+print " const struct cpp_options * cpp_opts)"
+print "{ "
+for (i = 0; i < n_opts; i++) {
+ # With identical flags, pick only the last one. The
+ # earlier loop ensured that it has all flags merged,
+ # and a nonempty help text if one of the texts was nonempty.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ i++;
+ }
+ cpp_option = nth_arg(0, opt_args("CPP", flags[i]));
+ opt_var_name = var_name(flags[i]);
+ if (cpp_option != "" && opt_var_name != "") {
+ print " opts->x_" opt_var_name " = cpp_opts->" cpp_option ";"
+ }
+}
+print "} "
+
+split("", var_seen, ":")
+print "\n#if !defined(GENERATOR_FILE) && defined(ENABLE_PLUGIN)"
+print "DEBUG_VARIABLE const struct cl_var cl_vars[] =\n{"
+
+for (i = 0; i < n_opts; i++) {
+ name = var_name(flags[i]);
+ if (name == "")
+ continue;
+ var_seen[name] = 1;
+}
+
+for (i = 0; i < n_extra_vars; i++) {
+ var = extra_vars[i]
+ sub(" *=.*", "", var)
+ name = var
+ sub("^.*[ *]", "", name)
+ sub("\\[.*\\]$", "", name)
+ if (name in var_seen)
+ continue;
+ print " { " quote name quote ", offsetof (struct gcc_options, x_" name ") },"
+ var_seen[name] = 1
+}
+
+print " { NULL, (unsigned short) -1 }\n};\n#endif"
+
+}
diff --git a/support/cpp/gcc/optc-save-gen.awk b/support/cpp/gcc/optc-save-gen.awk
new file mode 100644
index 000000000..0b1801eed
--- /dev/null
+++ b/support/cpp/gcc/optc-save-gen.awk
@@ -0,0 +1,1471 @@
+# Copyright (C) 2003-2022 Free Software Foundation, Inc.
+# Contributed by Kelley Cook, June 2004.
+# Original code from Neil Booth, May 2003.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records generated from
+# opt-gather.awk, combines the flags of duplicate options and generates a
+# C file.
+#
+
+# This program uses functions from opt-functions.awk and code from
+# opt-read.awk.
+#
+# Usage: awk -f opt-functions.awk -f opt-read.awk -f optc-save-gen.awk \
+# [-v header_name=header.h] < inputfile > options-save.cc
+
+# Dump that array of options into a C file.
+END {
+print "/* This file is auto-generated by optc-save-gen.awk. */"
+print ""
+n_headers = split(header_name, headers, " ")
+for (i = 1; i <= n_headers; i++)
+ print "#include " quote headers[i] quote
+print "#include " quote "opts.h" quote
+print "#include " quote "intl.h" quote
+print ""
+print "#include " quote "flags.h" quote
+print "#include " quote "target.h" quote
+print "#include " quote "inchash.h" quote
+print "#include " quote "hash-set.h" quote
+print "#include " quote "vec.h" quote
+print "#include " quote "input.h" quote
+print "#include " quote "alias.h" quote
+print "#include " quote "symtab.h" quote
+print "#include " quote "inchash.h" quote
+print "#include " quote "tree.h" quote
+print "#include " quote "fold-const.h" quote
+print "#include " quote "tree-ssa-alias.h" quote
+print "#include " quote "is-a.h" quote
+print "#include " quote "predict.h" quote
+print "#include " quote "function.h" quote
+print "#include " quote "basic-block.h" quote
+# sdcpp print "#include " quote "gimple-expr.h" quote
+# sdcpp print "#include " quote "gimple.h" quote
+print "#include " quote "data-streamer.h" quote
+# sdcpp print "#include " quote "ipa-ref.h" quote
+print "#include " quote "cgraph.h" quote
+print ""
+
+if (n_extra_c_includes > 0) {
+ for (i = 0; i < n_extra_c_includes; i++) {
+ print "#include " quote extra_c_includes[i] quote
+ }
+ print ""
+}
+
+have_save = 0;
+if (n_extra_target_vars)
+ have_save = 1
+
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("Save", flags[i]))
+ have_save = 1;
+}
+
+print "/* Save optimization variables into a structure. */"
+print "void";
+print "cl_optimization_save (struct cl_optimization *ptr, struct gcc_options *opts,";
+print " struct gcc_options *opts_set)";
+print "{";
+
+n_opt_char = 4;
+n_opt_short = 0;
+n_opt_int = 0;
+n_opt_enum = 0;
+n_opt_string = 0;
+n_opt_other = 0;
+var_opt_char[0] = "optimize";
+var_opt_char[1] = "optimize_size";
+var_opt_char[2] = "optimize_debug";
+var_opt_char[3] = "optimize_fast";
+var_opt_range["optimize"] = "0, 255";
+var_opt_range["optimize_size"] = "0, 2";
+var_opt_range["optimize_debug"] = "0, 1";
+var_opt_range["optimize_fast"] = "0, 1";
+
+# Sort by size to mimic how the structure is laid out to be friendlier to the
+# cache.
+
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("(Optimization|PerFunction)", flags[i])) {
+ name = var_name(flags[i])
+ if(name == "")
+ continue;
+
+ if(name in var_opt_seen)
+ continue;
+
+ var_opt_seen[name]++;
+ otype = var_type_struct(flags[i]);
+ if (otype ~ "^((un)?signed +)?int *$")
+ var_opt_int[n_opt_int++] = name;
+
+ else if (otype ~ "^((un)?signed +)?short *$")
+ var_opt_short[n_opt_short++] = name;
+
+ else if (otype ~ ("^enum +[_" alnum "]+ *")) {
+ var_opt_enum_type[n_opt_enum] = otype;
+ var_opt_enum[n_opt_enum++] = name;
+ }
+ else if (otype ~ "^((un)?signed +)?char *$") {
+ var_opt_char[n_opt_char++] = name;
+ if (otype ~ "^unsigned +char *$")
+ var_opt_range[name] = "0, 255"
+ else if (otype ~ "^signed +char *$")
+ var_opt_range[name] = "-128, 127"
+ }
+ else if (otype ~ "^const char \\**$") {
+ var_opt_string[n_opt_string++] = name;
+ string_options_names[name]++
+ }
+ else
+ var_opt_other[n_opt_other++] = name;
+ }
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ name = var_opt_char[i];
+ if (var_opt_range[name] != "")
+ print " gcc_assert (IN_RANGE (opts->x_" name ", " var_opt_range[name] "));";
+}
+
+print "";
+for (i = 0; i < n_opt_other; i++) {
+ print " ptr->x_" var_opt_other[i] " = opts->x_" var_opt_other[i] ";";
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ print " ptr->x_" var_opt_int[i] " = opts->x_" var_opt_int[i] ";";
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ print " ptr->x_" var_opt_enum[i] " = opts->x_" var_opt_enum[i] ";";
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ print " ptr->x_" var_opt_short[i] " = opts->x_" var_opt_short[i] ";";
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ print " ptr->x_" var_opt_char[i] " = opts->x_" var_opt_char[i] ";";
+}
+
+for (i = 0; i < n_opt_string; i++) {
+ print " ptr->x_" var_opt_string[i] " = opts->x_" var_opt_string[i] ";";
+}
+
+print "";
+print " unsigned HOST_WIDE_INT mask = 0;";
+
+j = 0;
+k = 0;
+for (i = 0; i < n_opt_other; i++) {
+ print " if (opts_set->x_" var_opt_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ print " if (opts_set->x_" var_opt_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ print " if (opts_set->x_" var_opt_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ print " if (opts_set->x_" var_opt_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ print " if (opts_set->x_" var_opt_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_opt_string; i++) {
+ print " if (opts_set->x_" var_opt_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+if (j != 0) {
+ print " ptr->explicit_mask[" k "] = mask;";
+}
+
+print "}";
+
+print "";
+print "/* Restore optimization options from a structure. */";
+print "void";
+print "cl_optimization_restore (struct gcc_options *opts, struct gcc_options *opts_set,";
+print " struct cl_optimization *ptr)";
+print "{";
+
+for (i = 0; i < n_opt_other; i++) {
+ print " opts->x_" var_opt_other[i] " = ptr->x_" var_opt_other[i] ";";
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ print " opts->x_" var_opt_int[i] " = ptr->x_" var_opt_int[i] ";";
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ print " opts->x_" var_opt_enum[i] " = ptr->x_" var_opt_enum[i] ";";
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ print " opts->x_" var_opt_short[i] " = ptr->x_" var_opt_short[i] ";";
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ print " opts->x_" var_opt_char[i] " = ptr->x_" var_opt_char[i] ";";
+}
+
+for (i = 0; i < n_opt_string; i++) {
+ print " opts->x_" var_opt_string[i] " = ptr->x_" var_opt_string[i] ";";
+}
+
+print "";
+print " unsigned HOST_WIDE_INT mask;";
+
+j = 64;
+k = 0;
+for (i = 0; i < n_opt_other; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_opt_other[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_opt_int[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_opt_enum[i] " = static_cast<" var_opt_enum_type[i] ">((mask & 1) != 0);";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_opt_short[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_opt_char[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_opt_string; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_opt_string[i] " = (mask & 1) ? \"\" : nullptr;";
+ print " mask >>= 1;"
+ j++;
+}
+
+# sdcpp print " targetm.override_options_after_change ();";
+print "}";
+
+print "";
+print "/* Print optimization options from a structure. */";
+print "void";
+print "cl_optimization_print (FILE *file,";
+print " int indent_to,";
+print " struct cl_optimization *ptr)";
+print "{";
+
+print " fputs (\"\\n\", file);";
+for (i = 0; i < n_opt_other; i++) {
+ print " if (ptr->x_" var_opt_other[i] ")";
+ print " fprintf (file, \"%*s%s (%#lx)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_other[i] "\",";
+ print " (unsigned long)ptr->x_" var_opt_other[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ print " if (ptr->x_" var_opt_int[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_int[i] "\",";
+ print " ptr->x_" var_opt_int[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_enum[i] "\",";
+ print " (int) ptr->x_" var_opt_enum[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ print " if (ptr->x_" var_opt_short[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_short[i] "\",";
+ print " ptr->x_" var_opt_short[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ print " if (ptr->x_" var_opt_char[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_char[i] "\",";
+ print " ptr->x_" var_opt_char[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_string; i++) {
+ print " if (ptr->x_" var_opt_string[i] ")";
+ print " fprintf (file, \"%*s%s (%s)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_string[i] "\",";
+ print " ptr->x_" var_opt_string[i] ");";
+ print "";
+}
+
+print "}";
+
+print "";
+print "/* Print different optimization variables from structures provided as arguments. */";
+print "void";
+print "cl_optimization_print_diff (FILE *file,";
+print " int indent_to,";
+print " struct cl_optimization *ptr1,";
+print " struct cl_optimization *ptr2)";
+print "{";
+
+print " fputs (\"\\n\", file);";
+for (i = 0; i < n_opt_other; i++) {
+ print " if (ptr1->x_" var_opt_other[i] " != ptr2->x_" var_opt_other[i] ")";
+ print " fprintf (file, \"%*s%s (%#lx/%#lx)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_other[i] "\",";
+ print " (unsigned long)ptr1->x_" var_opt_other[i] ",";
+ print " (unsigned long)ptr2->x_" var_opt_other[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ print " if (ptr1->x_" var_opt_int[i] " != ptr2->x_" var_opt_int[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_int[i] "\",";
+ print " ptr1->x_" var_opt_int[i] ",";
+ print " ptr2->x_" var_opt_int[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ print " if (ptr1->x_" var_opt_enum[i] " != ptr2->x_" var_opt_enum[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_enum[i] "\",";
+ print " (int) ptr1->x_" var_opt_enum[i] ",";
+ print " (int) ptr2->x_" var_opt_enum[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ print " if (ptr1->x_" var_opt_short[i] " != ptr2->x_" var_opt_short[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_short[i] "\",";
+ print " ptr1->x_" var_opt_short[i] ",";
+ print " ptr2->x_" var_opt_short[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ print " if (ptr1->x_" var_opt_char[i] " != ptr2->x_" var_opt_char[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" var_opt_char[i] "\",";
+ print " ptr1->x_" var_opt_char[i] ",";
+ print " ptr2->x_" var_opt_char[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_opt_string; i++) {
+ name = var_opt_string[i]
+ print " if (ptr1->x_" name " != ptr2->x_" name "";
+ print " && (!ptr1->x_" name" || !ptr2->x_" name
+ print " || strcmp (ptr1->x_" name", ptr2->x_" name ")))";
+ print " fprintf (file, \"%*s%s (%s/%s)\\n\",";
+ print " indent_to, \"\",";
+ print " \"" name "\",";
+ print " ptr1->x_" name " ? ptr1->x_" name " : \"(null)\",";
+ print " ptr2->x_" name " ? ptr2->x_" name " : \"(null)\");";
+ print "";
+}
+
+print "}";
+
+
+print "";
+print "/* Save selected option variables into a structure. */"
+print "void";
+print "cl_target_option_save (struct cl_target_option *ptr, struct gcc_options *opts,";
+print " struct gcc_options *opts_set)";
+print "{";
+
+n_target_char = 0;
+n_target_short = 0;
+n_target_int = 0;
+n_target_enum = 0;
+n_target_string = 0;
+n_target_other = 0;
+
+if (have_save) {
+ for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("Save", flags[i])) {
+ name = var_name(flags[i])
+ if(name == "")
+ name = "target_flags";
+
+ if(name in var_save_seen)
+ continue;
+
+ var_save_seen[name]++;
+ otype = var_type_struct(flags[i])
+ if (opt_args("Mask", flags[i]) != "" \
+ || opt_args("InverseMask", flags[i]))
+ var_target_explicit_mask[name] = 1;
+
+ if (otype ~ "^((un)?signed +)?int *$")
+ var_target_int[n_target_int++] = name;
+
+ else if (otype ~ "^((un)?signed +)?short *$")
+ var_target_short[n_target_short++] = name;
+
+ else if (otype ~ ("^enum +[_" alnum "]+ *$")) {
+ var_target_enum_type[n_target_enum] = otype;
+ var_target_enum[n_target_enum++] = name;
+ }
+ else if (otype ~ "^((un)?signed +)?char *$") {
+ var_target_char[n_target_char++] = name;
+ if (otype ~ "^unsigned +char *$")
+ var_target_range[name] = "0, 255"
+ else if (otype ~ "^signed +char *$")
+ var_target_range[name] = "-128, 127"
+ if (otype == var_type(flags[i]))
+ var_target_range[name] = ""
+ }
+ else if (otype ~ "^const char \\**$") {
+ var_target_string[n_target_string++] = name;
+ string_options_names[name]++
+ }
+ else
+ var_target_other[n_target_other++] = name;
+ }
+ }
+} else {
+ var_target_int[n_target_int++] = "target_flags";
+ var_target_explicit_mask["target_flags"] = 1;
+}
+
+have_assert = 0;
+for (i = 0; i < n_target_char; i++) {
+ name = var_target_char[i];
+ if (var_target_range[name] != "") {
+ have_assert = 1;
+ print " gcc_assert (IN_RANGE (opts->x_" name ", " var_target_range[name] "));";
+ }
+}
+
+if (have_assert)
+ print "";
+
+# sdcpp print " if (targetm.target_option.save)";
+# sdcpp print " targetm.target_option.save (ptr, opts, opts_set);";
+print "";
+
+for (i = 0; i < n_extra_target_vars; i++) {
+ print " ptr->x_" extra_target_vars[i] " = opts->x_" extra_target_vars[i] ";";
+}
+
+for (i = 0; i < n_target_other; i++) {
+ print " ptr->x_" var_target_other[i] " = opts->x_" var_target_other[i] ";";
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ print " ptr->x_" var_target_enum[i] " = opts->x_" var_target_enum[i] ";";
+}
+
+for (i = 0; i < n_target_int; i++) {
+ print " ptr->x_" var_target_int[i] " = opts->x_" var_target_int[i] ";";
+}
+
+for (i = 0; i < n_target_short; i++) {
+ print " ptr->x_" var_target_short[i] " = opts->x_" var_target_short[i] ";";
+}
+
+for (i = 0; i < n_target_char; i++) {
+ print " ptr->x_" var_target_char[i] " = opts->x_" var_target_char[i] ";";
+}
+
+for (i = 0; i < n_target_string; i++) {
+ print " ptr->x_" var_target_string[i] " = opts->x_" var_target_string[i] ";";
+}
+
+print "";
+
+j = 0;
+k = 0;
+for (i = 0; i < n_extra_target_vars; i++) {
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" extra_target_vars[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_target_other; i++) {
+ if (var_target_other[i] in var_target_explicit_mask) {
+ print " ptr->explicit_mask_" var_target_other[i] " = opts_set->x_" var_target_other[i] ";";
+ continue;
+ }
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" var_target_other[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" var_target_enum[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_target_int; i++) {
+ if (var_target_int[i] in var_target_explicit_mask) {
+ print " ptr->explicit_mask_" var_target_int[i] " = opts_set->x_" var_target_int[i] ";";
+ continue;
+ }
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" var_target_int[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_target_short; i++) {
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" var_target_short[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_target_char; i++) {
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" var_target_char[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+for (i = 0; i < n_target_string; i++) {
+ if (j == 0 && k == 0) {
+ print " unsigned HOST_WIDE_INT mask = 0;";
+ }
+ print " if (opts_set->x_" var_target_string[i] ") mask |= HOST_WIDE_INT_1U << " j ";";
+ j++;
+ if (j == 64) {
+ print " ptr->explicit_mask[" k "] = mask;";
+ print " mask = 0;";
+ j = 0;
+ k++;
+ }
+}
+
+if (j != 0) {
+ print " ptr->explicit_mask[" k "] = mask;";
+}
+has_target_explicit_mask = 0;
+if (j != 0 || k != 0) {
+ has_target_explicit_mask = 1;
+}
+
+print "}";
+
+print "";
+print "/* Restore selected current options from a structure. */";
+print "void";
+print "cl_target_option_restore (struct gcc_options *opts, struct gcc_options *opts_set,";
+print " struct cl_target_option *ptr)";
+print "{";
+
+for (i = 0; i < n_extra_target_vars; i++) {
+ print " opts->x_" extra_target_vars[i] " = ptr->x_" extra_target_vars[i] ";";
+}
+
+for (i = 0; i < n_target_other; i++) {
+ print " opts->x_" var_target_other[i] " = ptr->x_" var_target_other[i] ";";
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ print " opts->x_" var_target_enum[i] " = ptr->x_" var_target_enum[i] ";";
+}
+
+for (i = 0; i < n_target_int; i++) {
+ print " opts->x_" var_target_int[i] " = ptr->x_" var_target_int[i] ";";
+}
+
+for (i = 0; i < n_target_short; i++) {
+ print " opts->x_" var_target_short[i] " = ptr->x_" var_target_short[i] ";";
+}
+
+for (i = 0; i < n_target_char; i++) {
+ print " opts->x_" var_target_char[i] " = ptr->x_" var_target_char[i] ";";
+}
+
+for (i = 0; i < n_target_string; i++) {
+ print " opts->x_" var_target_string[i] " = ptr->x_" var_target_string[i] ";";
+}
+
+print "";
+if (has_target_explicit_mask) {
+ print " unsigned HOST_WIDE_INT mask;";
+}
+
+j = 64;
+k = 0;
+for (i = 0; i < n_extra_target_vars; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ if (extra_target_var_types[i] ~ ("^enum +[_" alnum "]+ *$")) {
+ print " opts_set->x_" extra_target_vars[i] " = static_cast<" extra_target_var_types[i] ">((mask & 1) != 0);";
+ }
+ else if (extra_target_var_types[i] ~ "^const char \\**$") {
+ print " opts_set->x_" extra_target_vars[i] " = (mask & 1) ? \"\" : nullptr;";
+ }
+ else {
+ print " opts_set->x_" extra_target_vars[i] " = (mask & 1) != 0;";
+ }
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_target_other; i++) {
+ if (var_target_other[i] in var_target_explicit_mask) {
+ print " opts_set->x_" var_target_other[i] " = ptr->explicit_mask_" var_target_other[i] ";";
+ continue;
+ }
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_target_other[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_target_enum[i] " = static_cast<" var_target_enum_type[i] ">((mask & 1) != 0);";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_target_int; i++) {
+ if (var_target_int[i] in var_target_explicit_mask) {
+ print " opts_set->x_" var_target_int[i] " = ptr->explicit_mask_" var_target_int[i] ";";
+ continue;
+ }
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_target_int[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_target_short; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_target_short[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_target_char; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_target_char[i] " = (mask & 1) != 0;";
+ print " mask >>= 1;"
+ j++;
+}
+
+for (i = 0; i < n_target_string; i++) {
+ if (j == 64) {
+ print " mask = ptr->explicit_mask[" k "];";
+ k++;
+ j = 0;
+ }
+ print " opts_set->x_" var_target_string[i] " = (mask & 1) ? \"\" : nullptr;";
+ print " mask >>= 1;"
+ j++;
+}
+
+# This must occur after the normal variables in case the code depends on those
+# variables.
+print "";
+# sdcpp print " if (targetm.target_option.restore)";
+# sdcpp print " targetm.target_option.restore (opts, opts_set, ptr);";
+
+print "}";
+
+print "";
+print "/* Print optimization options from a structure. */";
+print "void";
+print "cl_target_option_print (FILE *file,";
+print " int indent,";
+print " struct cl_target_option *ptr)";
+print "{";
+
+print " fputs (\"\\n\", file);";
+for (i = 0; i < n_target_other; i++) {
+ print " if (ptr->x_" var_target_other[i] ")";
+ hwi = host_wide_int[var_target_other[i]]
+ if (hwi == "yes")
+ print " fprintf (file, \"%*s%s (%#\" HOST_WIDE_INT_PRINT \"x)\\n\",";
+ else
+ print " fprintf (file, \"%*s%s (%#lx)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_other[i] "\",";
+ if (hwi == "yes")
+ print " ptr->x_" var_target_other[i] ");";
+ else
+ print " (unsigned long)ptr->x_" var_target_other[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ print " if (ptr->x_" var_target_enum[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_enum[i] "\",";
+ print " ptr->x_" var_target_enum[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_int; i++) {
+ print " if (ptr->x_" var_target_int[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_int[i] "\",";
+ print " ptr->x_" var_target_int[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_short; i++) {
+ print " if (ptr->x_" var_target_short[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_short[i] "\",";
+ print " ptr->x_" var_target_short[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_char; i++) {
+ print " if (ptr->x_" var_target_char[i] ")";
+ print " fprintf (file, \"%*s%s (%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_char[i] "\",";
+ print " ptr->x_" var_target_char[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_string; i++) {
+ print " if (ptr->x_" var_target_string[i] ")";
+ print " fprintf (file, \"%*s%s (%s)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_string[i] "\",";
+ print " ptr->x_" var_target_string[i] ");";
+ print "";
+}
+
+print "";
+# sdcpp print " if (targetm.target_option.print)";
+# sdcpp print " targetm.target_option.print (file, indent, ptr);";
+print "}";
+
+print "";
+print "/* Print different target option variables from structures provided as arguments. */";
+print "void";
+print "cl_target_option_print_diff (FILE *file,";
+print " int indent ATTRIBUTE_UNUSED,";
+print " struct cl_target_option *ptr1 ATTRIBUTE_UNUSED,";
+print " struct cl_target_option *ptr2 ATTRIBUTE_UNUSED)";
+print "{";
+
+print " fputs (\"\\n\", file);";
+for (i = 0; i < n_target_other; i++) {
+ print " if (ptr1->x_" var_target_other[i] " != ptr2->x_" var_target_other[i] ")";
+ hwi = host_wide_int[var_target_other[i]]
+ if (hwi == "yes")
+ print " fprintf (file, \"%*s%s (%#\" HOST_WIDE_INT_PRINT \"x/%#\" HOST_WIDE_INT_PRINT \"x)\\n\",";
+ else
+ print " fprintf (file, \"%*s%s (%#lx/%#lx)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_other[i] "\",";
+ if (hwi == "yes") {
+ print " ptr1->x_" var_target_other[i] ",";
+ print " ptr2->x_" var_target_other[i] ");";
+ }
+ else {
+ print " (unsigned long)ptr1->x_" var_target_other[i] ",";
+ print " (unsigned long)ptr2->x_" var_target_other[i] ");";
+ }
+ print "";
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ print " if (ptr1->x_" var_target_enum[i] " != ptr2->x_" var_target_enum[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_enum[i] "\",";
+ print " ptr1->x_" var_target_enum[i] ",";
+ print " ptr2->x_" var_target_enum[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_int; i++) {
+ print " if (ptr1->x_" var_target_int[i] " != ptr2->x_" var_target_int[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_int[i] "\",";
+ print " ptr1->x_" var_target_int[i] ",";
+ print " ptr2->x_" var_target_int[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_short; i++) {
+ print " if (ptr1->x_" var_target_short[i] " != ptr2->x_" var_target_short[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_short[i] "\",";
+ print " ptr1->x_" var_target_short[i] ",";
+ print " ptr2->x_" var_target_short[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_char; i++) {
+ print " if (ptr1->x_" var_target_char[i] " != ptr2->x_" var_target_char[i] ")";
+ print " fprintf (file, \"%*s%s (%#x/%#x)\\n\",";
+ print " indent, \"\",";
+ print " \"" var_target_char[i] "\",";
+ print " ptr1->x_" var_target_char[i] ",";
+ print " ptr2->x_" var_target_char[i] ");";
+ print "";
+}
+
+for (i = 0; i < n_target_string; i++) {
+ name = var_target_string[i]
+ print " if (ptr1->x_" name " != ptr2->x_" name "";
+ print " && (!ptr1->x_" name" || !ptr2->x_" name
+ print " || strcmp (ptr1->x_" name", ptr2->x_" name ")))";
+ print " fprintf (file, \"%*s%s (%s/%s)\\n\",";
+ print " indent, \"\",";
+ print " \"" name "\",";
+ print " ptr1->x_" name " ? ptr1->x_" name " : \"(null)\",";
+ print " ptr2->x_" name " ? ptr1->x_" name " : \"(null)\");";
+ print "";
+}
+
+print "}";
+
+print "";
+print "/* Compare two target options */";
+print "bool";
+print "cl_target_option_eq (struct cl_target_option const *ptr1 ATTRIBUTE_UNUSED,";
+print " struct cl_target_option const *ptr2 ATTRIBUTE_UNUSED)";
+print "{";
+n_target_val = 0;
+n_target_str = 0;
+n_target_array = 0;
+
+for (i = 0; i < n_target_save; i++) {
+ var = target_save_decl[i];
+ sub (" *=.*", "", var);
+ name = var;
+ type = var;
+ sub("^.*[ *]", "", name)
+ sub(" *" name "$", "", type)
+ if (target_save_decl[i] ~ "^const char \\*+[_" alnum "]+$") {
+ var_target_str[n_target_str++] = name;
+ string_options_names[name]++
+ }
+ else {
+ if (target_save_decl[i] ~ " .*\\[.+\\]+$") {
+ size = name;
+ sub("[^\\[]+\\[", "", size);
+ sub("\\]$", "", size);
+ sub("\\[.+", "", name)
+ sub(" [^ ]+$", "", type)
+ var_target_array[n_target_array] = name
+ var_target_array_type[n_target_array] = type
+ var_target_array_size[n_target_array++] = size
+ }
+ else {
+ var_target_val_type[n_target_val] = type;
+ var_target_val[n_target_val++] = name;
+ }
+ }
+}
+if (have_save) {
+ for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("Save", flags[i])) {
+ name = var_name(flags[i])
+ if(name == "")
+ name = "target_flags";
+
+ if(name in var_list_seen)
+ continue;
+
+ var_list_seen[name]++;
+ otype = var_type_struct(flags[i])
+ if (otype ~ "^const char \\**$")
+ var_target_str[n_target_str++] = "x_" name;
+ else {
+ var_target_val_type[n_target_val] = otype;
+ var_target_val[n_target_val++] = "x_" name;
+ }
+ }
+ }
+} else {
+ var_target_val_type[n_target_val] = "int";
+ var_target_val[n_target_val++] = "x_target_flags";
+}
+
+for (i = 0; i < n_target_str; i++) {
+ name = var_target_str[i]
+ print " if (ptr1->" name" != ptr2->" name;
+ print " && (!ptr1->" name" || !ptr2->" name
+ print " || strcmp (ptr1->" name", ptr2->" name ")))";
+ print " return false;";
+}
+for (i = 0; i < n_target_array; i++) {
+ name = var_target_array[i]
+ size = var_target_array_size[i]
+ type = var_target_array_type[i]
+ print " if (ptr1->" name" != ptr2->" name "";
+ print " || memcmp (ptr1->" name ", ptr2->" name ", " size " * sizeof(" type ")))"
+ print " return false;";
+}
+for (i = 0; i < n_target_val; i++) {
+ name = var_target_val[i]
+ print " if (ptr1->" name" != ptr2->" name ")";
+ print " return false;";
+}
+
+if (has_target_explicit_mask) {
+ print " for (size_t i = 0; i < sizeof (ptr1->explicit_mask) / sizeof (ptr1->explicit_mask[0]); i++)";
+ print " if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
+ print " return false;"
+}
+
+for (i = 0; i < n_target_other; i++) {
+ if (var_target_other[i] in var_target_explicit_mask) {
+ print " if (ptr1->explicit_mask_" var_target_other[i] " != ptr2->explicit_mask_" var_target_other[i] ")";
+ print " return false;";
+ }
+}
+
+for (i = 0; i < n_target_int; i++) {
+ if (var_target_int[i] in var_target_explicit_mask) {
+ print " if (ptr1->explicit_mask_" var_target_int[i] " != ptr2->explicit_mask_" var_target_int[i] ")";
+ print " return false;";
+ }
+}
+
+print " return true;";
+
+print "}";
+
+print "";
+print "/* Hash target options */";
+print "hashval_t";
+print "cl_target_option_hash (struct cl_target_option const *ptr ATTRIBUTE_UNUSED)";
+print "{";
+print " inchash::hash hstate;";
+for (i = 0; i < n_target_str; i++) {
+ name = var_target_str[i]
+ print " if (ptr->" name")";
+ print " hstate.add (ptr->" name", strlen (ptr->" name"));";
+ print " else";
+ print " hstate.add_int (0);";
+}
+for (i = 0; i < n_target_array; i++) {
+ name= var_target_array[i]
+ size = var_target_array_size[i]
+ type = var_target_array_type[i]
+ print " hstate.add_int (" size ");";
+ print " hstate.add (ptr->" name ", sizeof (" type ") * " size ");";
+}
+for (i = 0; i < n_target_val; i++) {
+ name = var_target_val[i]
+ print " hstate.add_hwi (ptr->" name");";
+}
+if (has_target_explicit_mask) {
+ print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+ print " hstate.add_hwi (ptr->explicit_mask[i]);";
+}
+
+for (i = 0; i < n_target_other; i++) {
+ if (var_target_other[i] in var_target_explicit_mask)
+ print " hstate.add_hwi (ptr->explicit_mask_" var_target_other[i] ");";
+}
+
+for (i = 0; i < n_target_int; i++) {
+ if (var_target_int[i] in var_target_explicit_mask)
+ print " hstate.add_hwi (ptr->explicit_mask_" var_target_int[i] ");";
+}
+
+print " return hstate.end ();";
+print "}";
+
+print "";
+print "/* Stream out target options */";
+print "void";
+print "cl_target_option_stream_out (struct output_block *ob ATTRIBUTE_UNUSED,";
+print " struct bitpack_d *bp ATTRIBUTE_UNUSED,";
+print " struct cl_target_option *ptr ATTRIBUTE_UNUSED)";
+print "{";
+for (i = 0; i < n_target_str; i++) {
+ name = var_target_str[i]
+ print " bp_pack_string (ob, bp, ptr->" name", true);";
+}
+for (i = 0; i < n_target_array; i++) {
+ name = var_target_array[i]
+ size = var_target_array_size[i]
+ print " for (unsigned i = 0; i < " size "; i++)"
+ print " bp_pack_value (bp, ptr->" name "[i], 64);";
+}
+for (i = 0; i < n_target_val; i++) {
+ name = var_target_val[i]
+ print " bp_pack_value (bp, ptr->" name", 64);";
+}
+
+if (has_target_explicit_mask) {
+ print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+ print " bp_pack_value (bp, ptr->explicit_mask[i], 64);";
+}
+
+for (i = 0; i < n_target_other; i++) {
+ if (var_target_other[i] in var_target_explicit_mask) {
+ print " bp_pack_value (bp, ptr->explicit_mask_" var_target_other[i] ", 64);";
+ }
+}
+
+for (i = 0; i < n_target_int; i++) {
+ if (var_target_int[i] in var_target_explicit_mask) {
+ print " bp_pack_value (bp, ptr->explicit_mask_" var_target_int[i] ", 64);";
+ }
+}
+
+print "}";
+
+print "";
+print "/* Stream in target options */";
+print "void";
+print "cl_target_option_stream_in (struct data_in *data_in ATTRIBUTE_UNUSED,";
+print " struct bitpack_d *bp ATTRIBUTE_UNUSED,";
+print " struct cl_target_option *ptr ATTRIBUTE_UNUSED)";
+print "{";
+for (i = 0; i < n_target_str; i++) {
+ name = var_target_str[i]
+ print " ptr->" name" = bp_unpack_string (data_in, bp);";
+ print " if (ptr->" name")";
+ print " ptr->" name" = xstrdup (ptr->" name");";
+}
+for (i = 0; i < n_target_array; i++) {
+ name = var_target_array[i]
+ size = var_target_array_size[i]
+ print " for (int i = " size " - 1; i >= 0; i--)"
+ print " ptr->" name "[i] = (" var_target_array_type[i] ") bp_unpack_value (bp, 64);";
+}
+for (i = 0; i < n_target_val; i++) {
+ name = var_target_val[i]
+ print " ptr->" name" = (" var_target_val_type[i] ") bp_unpack_value (bp, 64);";
+}
+
+if (has_target_explicit_mask) {
+ print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+ print " ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";
+}
+
+for (i = 0; i < n_target_other; i++) {
+ if (var_target_other[i] in var_target_explicit_mask) {
+ print " ptr->explicit_mask_" var_target_other[i] " = bp_unpack_value (bp, 64);";
+ }
+}
+
+for (i = 0; i < n_target_int; i++) {
+ if (var_target_int[i] in var_target_explicit_mask) {
+ print " ptr->explicit_mask_" var_target_int[i] " = bp_unpack_value (bp, 64);";
+ }
+}
+
+print "}";
+
+print "/* free heap memory used by target options */";
+print "void";
+print "cl_target_option_free (struct cl_target_option *ptr ATTRIBUTE_UNUSED)";
+print "{";
+for (i = 0; i < n_target_str; i++) {
+ name = var_target_str[i]
+ print " if (ptr->" name")";
+ print " free (const_cast <char *>(ptr->" name"));";
+}
+print "}";
+
+n_opt_val = 4;
+var_opt_val[0] = "x_optimize"
+var_opt_val_type[0] = "char "
+var_opt_hash[0] = 1;
+var_opt_val[1] = "x_optimize_size"
+var_opt_val_type[1] = "char "
+var_opt_hash[1] = 1;
+var_opt_val[2] = "x_optimize_debug"
+var_opt_val_type[2] = "char "
+var_opt_hash[2] = 1;
+var_opt_val[3] = "x_optimize_fast"
+var_opt_val_type[3] = "char "
+var_opt_hash[3] = 1;
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("(Optimization|PerFunction)", flags[i])) {
+ name = var_name(flags[i])
+ if(name == "")
+ continue;
+
+ if(name in var_opt_list_seen)
+ continue;
+
+ var_opt_list_seen[name]++;
+
+ otype = var_type_struct(flags[i])
+ var_opt_val_type[n_opt_val] = otype;
+ var_opt_val[n_opt_val] = "x_" name;
+ var_opt_hash[n_opt_val] = flag_set_p("Optimization", flags[i]);
+ var_opt_init[n_opt_val] = opt_args("Init", flags[i]);
+ n_opt_val++;
+ }
+}
+print "";
+print "/* Hash optimization options */";
+print "hashval_t";
+print "cl_optimization_hash (struct cl_optimization const *ptr ATTRIBUTE_UNUSED)";
+print "{";
+print " inchash::hash hstate;";
+for (i = 0; i < n_opt_val; i++) {
+ if (!var_opt_hash[i])
+ continue;
+ name = var_opt_val[i]
+ otype = var_opt_val_type[i];
+ if (otype ~ "^const char \\**$")
+ {
+ print " if (ptr->" name")";
+ print " hstate.add (ptr->" name", strlen (ptr->" name"));";
+ print " else";
+ print " hstate.add_int (0);";
+ }
+ else
+ print " hstate.add_hwi (ptr->" name");";
+}
+print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+print " hstate.add_hwi (ptr->explicit_mask[i]);";
+print " return hstate.end ();";
+print "}";
+
+print "";
+print "/* Compare two optimization options */";
+print "bool";
+print "cl_optimization_option_eq (cl_optimization const *ptr1,";
+print " cl_optimization const *ptr2)";
+print "{";
+for (i = 0; i < n_opt_val; i++) {
+ if (!var_opt_hash[i])
+ continue;
+ name = var_opt_val[i]
+ otype = var_opt_val_type[i];
+ if (otype ~ "^const char \\**$")
+ {
+ print " if (ptr1->" name" != ptr2->" name;
+ print " && (!ptr1->" name" || !ptr2->" name
+ print " || strcmp (ptr1->" name", ptr2->" name ")))";
+ print " return false;";
+ }
+ else
+ {
+ print " if (ptr1->" name" != ptr2->" name ")";
+ print " return false;";
+ }
+}
+print " for (size_t i = 0; i < sizeof (ptr1->explicit_mask) / sizeof (ptr1->explicit_mask[0]); i++)";
+print " if (ptr1->explicit_mask[i] != ptr2->explicit_mask[i])";
+print " return false;"
+print " return true;";
+print "}";
+
+print "";
+print "/* Stream out optimization options */";
+print "void";
+print "cl_optimization_stream_out (struct output_block *ob,";
+print " struct bitpack_d *bp,";
+print " struct cl_optimization *ptr)";
+print "{";
+for (i = 0; i < n_opt_val; i++) {
+ name = var_opt_val[i]
+ otype = var_opt_val_type[i];
+ if (otype ~ "^const char \\**$")
+ print " bp_pack_string (ob, bp, ptr->" name", true);";
+ else {
+ if (otype ~ "^unsigned") {
+ sgn = "unsigned";
+ } else {
+ sgn = "int";
+ }
+ if (name ~ "^x_param" && !(otype ~ "^enum ") && var_opt_init[i]) {
+ print " if (" var_opt_init[i] " > (" var_opt_val_type[i] ") 10)";
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name" ^ " var_opt_init[i] ");";
+ print " else";
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name");";
+ } else {
+ print " bp_pack_var_len_" sgn " (bp, ptr->" name");";
+ }
+ }
+}
+print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+print " bp_pack_value (bp, ptr->explicit_mask[i], 64);";
+print "}";
+
+print "";
+print "/* Stream in optimization options */";
+print "void";
+print "cl_optimization_stream_in (struct data_in *data_in ATTRIBUTE_UNUSED,";
+print " struct bitpack_d *bp ATTRIBUTE_UNUSED,";
+print " struct cl_optimization *ptr ATTRIBUTE_UNUSED)";
+print "{";
+for (i = 0; i < n_opt_val; i++) {
+ name = var_opt_val[i]
+ otype = var_opt_val_type[i];
+ if (otype ~ "^const char \\**$") {
+ print " ptr->" name" = bp_unpack_string (data_in, bp);";
+ print " if (ptr->" name")";
+ print " ptr->" name" = xstrdup (ptr->" name");";
+ }
+ else {
+ if (otype ~ "^unsigned") {
+ sgn = "unsigned";
+ } else {
+ sgn = "int";
+ }
+ print " ptr->" name" = (" var_opt_val_type[i] ") bp_unpack_var_len_" sgn " (bp);";
+ if (name ~ "^x_param" && !(otype ~ "^enum ") && var_opt_init[i]) {
+ print " if (" var_opt_init[i] " > (" var_opt_val_type[i] ") 10)";
+ print " ptr->" name" ^= " var_opt_init[i] ";";
+ }
+ }
+}
+print " for (size_t i = 0; i < sizeof (ptr->explicit_mask) / sizeof (ptr->explicit_mask[0]); i++)";
+print " ptr->explicit_mask[i] = bp_unpack_value (bp, 64);";
+print "}";
+print "/* Free heap memory used by optimization options */";
+print "void";
+print "cl_optimization_option_free (struct cl_optimization *ptr ATTRIBUTE_UNUSED)";
+print "{";
+for (i = 0; i < n_opt_val; i++) {
+ name = var_opt_val[i]
+ otype = var_opt_val_type[i];
+ if (otype ~ "^const char \\**$")
+ {
+ print " if (ptr->" name")";
+ print " free (const_cast <char *>(ptr->" name"));";
+ }
+}
+print "}";
+
+print "void";
+print "cl_optimization_compare (gcc_options *ptr1, gcc_options *ptr2)"
+print "{"
+
+# all these options are mentioned in PR92860
+checked_options["flag_merge_constants"]++
+checked_options["param_max_fields_for_field_sensitive"]++
+checked_options["flag_omit_frame_pointer"]++
+# arc exceptions
+checked_options["TARGET_ALIGN_CALL"]++
+checked_options["TARGET_CASE_VECTOR_PC_RELATIVE"]++
+checked_options["arc_size_opt_level"]++
+# arm exceptions
+checked_options["arm_fp16_format"]++
+
+
+for (i = 0; i < n_opts; i++) {
+ name = var_name(flags[i]);
+ if (name == "")
+ continue;
+
+ if (name in checked_options)
+ continue;
+ checked_options[name]++
+
+ if (name in string_options_names || ("x_" name) in string_options_names) {
+ print " if (ptr1->x_" name " != ptr2->x_" name "";
+ print " && (!ptr1->x_" name" || !ptr2->x_" name
+ print " || strcmp (ptr1->x_" name", ptr2->x_" name ")))";
+ print " internal_error (\"%<global_options%> are modified in local context\");";
+ }
+ else {
+ print " if (ptr1->x_" name " != ptr2->x_" name ")"
+ print " internal_error (\"%<global_options%> are modified in local context\");";
+ }
+}
+
+print "}";
+}
diff --git a/support/cpp/gcc/opth-gen.awk b/support/cpp/gcc/opth-gen.awk
new file mode 100644
index 000000000..8bba8ec45
--- /dev/null
+++ b/support/cpp/gcc/opth-gen.awk
@@ -0,0 +1,575 @@
+# Copyright (C) 2003-2022 Free Software Foundation, Inc.
+# Contributed by Kelley Cook, June 2004.
+# Original code from Neil Booth, May 2003.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This Awk script reads in the option records generated from
+# opt-gather.awk, combines the flags of duplicate options and generates a
+# C header file.
+#
+# This program uses functions from opt-functions.awk and code from
+# opt-read.awk.
+# Usage: awk -f opt-functions.awk -f opt-read.awk -f opth-gen.awk \
+# < inputfile > options.h
+
+# Dump out an enumeration into a .h file.
+# Combine the flags of duplicate options.
+END {
+print "/* This file is auto-generated by opth-gen.awk. */"
+print ""
+print "#ifndef OPTIONS_H"
+print "#define OPTIONS_H"
+print ""
+print "#include \"flag-types.h\""
+print ""
+
+if (n_extra_h_includes > 0) {
+ for (i = 0; i < n_extra_h_includes; i++) {
+ print "#include " quote extra_h_includes[i] quote
+ }
+ print ""
+}
+
+print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
+print "#ifndef GENERATOR_FILE"
+print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS)"
+print "struct GTY(()) gcc_options"
+print "#else"
+print "struct gcc_options"
+print "#endif"
+print "{"
+print "#endif"
+
+for (i = 0; i < n_extra_vars; i++) {
+ var = extra_vars[i]
+ sub(" *=.*", "", var)
+ orig_var = var
+ name = var
+ type = var
+ type_after = var
+ sub("^.*[ *]", "", name)
+ sub("\\[.*\\]$", "", name)
+ sub("\\[.*\\]$", "", type)
+ sub(" *" name "$", "", type)
+ sub("^.*" name, "", type_after)
+ var_seen[name] = 1
+ print "#ifdef GENERATOR_FILE"
+ print "extern " orig_var ";"
+ print "#else"
+ print " " type " x_" name type_after ";"
+ print "#define " name " global_options.x_" name
+ print "#endif"
+}
+
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("Save", flags[i]))
+ have_save = 1;
+
+ name = var_name(flags[i]);
+ if (name == "")
+ continue;
+
+ if (name in var_seen)
+ continue;
+
+ var_seen[name] = 1;
+ print "#ifdef GENERATOR_FILE"
+ print "extern " var_type(flags[i]) name ";"
+ print "#else"
+ print " " var_type(flags[i]) "x_" name ";"
+ print "#define " name " global_options.x_" name
+ print "#endif"
+}
+for (i = 0; i < n_opts; i++) {
+ name = static_var(opts[i], flags[i]);
+ if (name != "") {
+ print "#ifndef GENERATOR_FILE"
+ print " " var_type(flags[i]) "x_" name ";"
+ print "#define x_" name " do_not_use"
+ print "#endif"
+ }
+}
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("SetByCombined", flags[i])) {
+ print "#ifndef GENERATOR_FILE"
+ print " bool frontend_set_" var_name(flags[i]) ";"
+ print "#endif"
+ }
+}
+print "#ifndef GENERATOR_FILE"
+print "};"
+print "extern struct gcc_options global_options;"
+print "extern const struct gcc_options global_options_init;"
+print "extern struct gcc_options global_options_set;"
+print "#define target_flags_explicit global_options_set.x_target_flags"
+print "#endif"
+print "#endif"
+print ""
+
+# All of the optimization switches gathered together so they can be saved and restored.
+# This will allow attribute((cold)) to turn on space optimization.
+
+# Change the type of normal switches from int to unsigned char to save space.
+# Also, order the structure so that pointer fields occur first, then int
+# fields, and then char fields to provide the best packing.
+
+print "#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)"
+print ""
+print "/* Structure to save/restore optimization and target specific options. */";
+print "struct GTY(()) cl_optimization";
+print "{";
+
+n_opt_char = 4;
+n_opt_short = 0;
+n_opt_int = 0;
+n_opt_enum = 0;
+n_opt_other = 0;
+n_opt_explicit = 4;
+var_opt_char[0] = "unsigned char x_optimize";
+var_opt_char[1] = "unsigned char x_optimize_size";
+var_opt_char[2] = "unsigned char x_optimize_debug";
+var_opt_char[3] = "unsigned char x_optimize_fast";
+
+for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("(Optimization|PerFunction)", flags[i])) {
+ name = var_name(flags[i])
+ if(name == "")
+ continue;
+
+ if(name in var_opt_seen)
+ continue;
+
+ var_opt_seen[name]++;
+ n_opt_explicit++;
+ otype = var_type_struct(flags[i]);
+ if (otype ~ "^((un)?signed +)?int *$")
+ var_opt_int[n_opt_int++] = otype "x_" name;
+
+ else if (otype ~ "^((un)?signed +)?short *$")
+ var_opt_short[n_opt_short++] = otype "x_" name;
+
+ else if (otype ~ "^((un)?signed +)?char *$")
+ var_opt_char[n_opt_char++] = otype "x_" name;
+
+ else if (otype ~ ("^enum +[_" alnum "]+ *$"))
+ var_opt_enum[n_opt_enum++] = otype "x_" name;
+
+ else
+ var_opt_other[n_opt_other++] = otype "x_" name;
+ }
+}
+
+for (i = 0; i < n_opt_other; i++) {
+ print " " var_opt_other[i] ";";
+}
+
+for (i = 0; i < n_opt_int; i++) {
+ print " " var_opt_int[i] ";";
+}
+
+for (i = 0; i < n_opt_enum; i++) {
+ print " " var_opt_enum[i] ";";
+}
+
+for (i = 0; i < n_opt_short; i++) {
+ print " " var_opt_short[i] ";";
+}
+
+for (i = 0; i < n_opt_char; i++) {
+ print " " var_opt_char[i] ";";
+}
+
+print " /* " n_opt_explicit " members */";
+print " unsigned HOST_WIDE_INT explicit_mask[" int ((n_opt_explicit + 63) / 64) "];";
+
+print "};";
+print "";
+
+# Target and optimization save/restore/print functions.
+print "/* Structure to save/restore selected target specific options. */";
+print "struct GTY(()) cl_target_option";
+print "{";
+
+n_target_char = 0;
+n_target_short = 0;
+n_target_int = 0;
+n_target_enum = 0;
+n_target_other = 0;
+n_target_explicit = n_extra_target_vars;
+n_target_explicit_mask = 0;
+
+for (i = 0; i < n_target_save; i++) {
+ if (target_save_decl[i] ~ "^((un)?signed +)?int +[_" alnum "]+$")
+ var_target_int[n_target_int++] = target_save_decl[i];
+
+ else if (target_save_decl[i] ~ "^((un)?signed +)?short +[_" alnum "]+$")
+ var_target_short[n_target_short++] = target_save_decl[i];
+
+ else if (target_save_decl[i] ~ "^((un)?signed +)?char +[_ " alnum "]+$")
+ var_target_char[n_target_char++] = target_save_decl[i];
+
+ else if (target_save_decl[i] ~ ("^enum +[_" alnum "]+ +[_" alnum "]+$")) {
+ var_target_enum[n_target_enum++] = target_save_decl[i];
+ }
+ else
+ var_target_other[n_target_other++] = target_save_decl[i];
+}
+
+if (have_save) {
+ for (i = 0; i < n_opts; i++) {
+ if (flag_set_p("Save", flags[i])) {
+ name = var_name(flags[i])
+ if(name == "")
+ name = "target_flags";
+
+ if(name in var_save_seen)
+ continue;
+
+ var_save_seen[name]++;
+ n_target_explicit++;
+ otype = var_type_struct(flags[i])
+
+ if (opt_args("Mask", flags[i]) != "" \
+ || opt_args("InverseMask", flags[i]))
+ var_target_explicit_mask[n_target_explicit_mask++] \
+ = otype "explicit_mask_" name;
+
+ if (otype ~ "^((un)?signed +)?int *$")
+ var_target_int[n_target_int++] = otype "x_" name;
+
+ else if (otype ~ "^((un)?signed +)?short *$")
+ var_target_short[n_target_short++] = otype "x_" name;
+
+ else if (otype ~ "^((un)?signed +)?char *$")
+ var_target_char[n_target_char++] = otype "x_" name;
+
+ else if (otype ~ ("^enum +[_" alnum "]+ +[_" alnum "]+"))
+ var_target_enum[n_target_enum++] = otype "x_" name;
+
+ else
+ var_target_other[n_target_other++] = otype "x_" name;
+ }
+ }
+} else {
+ var_target_int[n_target_int++] = "int x_target_flags";
+ n_target_explicit++;
+ var_target_explicit_mask[n_target_explicit_mask++] \
+ = "int explicit_mask_target_flags";
+}
+
+for (i = 0; i < n_target_other; i++) {
+ print " " var_target_other[i] ";";
+}
+
+for (i = 0; i < n_target_enum; i++) {
+ print " " var_target_enum[i] ";";
+}
+
+for (i = 0; i < n_target_int; i++) {
+ print " " var_target_int[i] ";";
+}
+
+for (i = 0; i < n_target_short; i++) {
+ print " " var_target_short[i] ";";
+}
+
+for (i = 0; i < n_target_char; i++) {
+ print " " var_target_char[i] ";";
+}
+
+print " /* " n_target_explicit - n_target_explicit_mask " members */";
+if (n_target_explicit > n_target_explicit_mask) {
+ print " unsigned HOST_WIDE_INT explicit_mask[" \
+ int ((n_target_explicit - n_target_explicit_mask + 63) / 64) "];";
+}
+
+for (i = 0; i < n_target_explicit_mask; i++) {
+ print " " var_target_explicit_mask[i] ";";
+}
+
+print "};";
+print "";
+print "";
+print "/* Save optimization variables into a structure. */"
+print "extern void cl_optimization_save (struct cl_optimization *, struct gcc_options *, struct gcc_options *);";
+print "";
+print "/* Restore optimization variables from a structure. */";
+print "extern void cl_optimization_restore (struct gcc_options *, struct gcc_options *, struct cl_optimization *);";
+print "";
+print "/* Print optimization variables from a structure. */";
+print "extern void cl_optimization_print (FILE *, int, struct cl_optimization *);";
+print "";
+print "/* Print different optimization variables from structures provided as arguments. */";
+print "extern void cl_optimization_print_diff (FILE *, int, cl_optimization *ptr1, cl_optimization *ptr2);";
+print "";
+print "/* Save selected option variables into a structure. */"
+print "extern void cl_target_option_save (struct cl_target_option *, struct gcc_options *, struct gcc_options *);";
+print "";
+print "/* Restore selected option variables from a structure. */"
+print "extern void cl_target_option_restore (struct gcc_options *, struct gcc_options *, struct cl_target_option *);";
+print "";
+print "/* Print target option variables from a structure. */";
+print "extern void cl_target_option_print (FILE *, int, struct cl_target_option *);";
+print "";
+print "/* Print different target option variables from structures provided as arguments. */";
+print "extern void cl_target_option_print_diff (FILE *, int, cl_target_option *ptr1, cl_target_option *ptr2);";
+print "";
+print "/* Compare two target option variables from a structure. */";
+print "extern bool cl_target_option_eq (const struct cl_target_option *, const struct cl_target_option *);";
+print "";
+print "/* Free heap memory used by target option variables. */";
+print "extern void cl_target_option_free (struct cl_target_option *);";
+print "";
+print "/* Hash option variables from a structure. */";
+print "extern hashval_t cl_target_option_hash (const struct cl_target_option *);";
+print "";
+print "/* Hash optimization from a structure. */";
+print "extern hashval_t cl_optimization_hash (const struct cl_optimization *);";
+print "";
+print "/* Compare two optimization options. */";
+print "extern bool cl_optimization_option_eq (cl_optimization const *ptr1, cl_optimization const *ptr2);"
+print "";
+print "/* Free heap memory used by optimization options. */";
+print "extern void cl_optimization_option_free (cl_optimization *ptr1);"
+print "";
+print "/* Compare and report difference for a part of cl_optimization options. */";
+print "extern void cl_optimization_compare (gcc_options *ptr1, gcc_options *ptr2);";
+print "";
+print "/* Generator files may not have access to location_t, and don't need these. */"
+print "#if defined(UNKNOWN_LOCATION)"
+print "bool "
+print "common_handle_option_auto (struct gcc_options *opts, "
+print " struct gcc_options *opts_set, "
+print " const struct cl_decoded_option *decoded, "
+print " unsigned int lang_mask, int kind, "
+print " location_t loc, "
+print " const struct cl_option_handlers *handlers, "
+print " diagnostic_context *dc); "
+for (i = 0; i < n_langs; i++) {
+ lang_name = lang_sanitized_name(langs[i]);
+ print "bool"
+ print lang_name "_handle_option_auto (struct gcc_options *opts,"
+ print " struct gcc_options *opts_set,"
+ print " size_t scode, const char *arg,"
+ print " HOST_WIDE_INT value,"
+ print " unsigned int lang_mask, int kind,"
+ print " location_t loc,"
+ print " const struct cl_option_handlers *handlers,"
+ print " diagnostic_context *dc);"
+}
+print "void cpp_handle_option_auto (const struct gcc_options * opts, size_t scode,"
+print " struct cpp_options * cpp_opts);"
+print "void init_global_opts_from_cpp(struct gcc_options * opts, "
+print " const struct cpp_options * cpp_opts);"
+print "#endif";
+print "#endif";
+print "";
+
+for (i = 0; i < n_opts; i++) {
+ name = opt_args("Mask", flags[i])
+ if (name == "") {
+ opt = opt_args("InverseMask", flags[i])
+ if (opt ~ ",")
+ name = nth_arg(0, opt)
+ else
+ name = opt
+ }
+ if (name != "" && mask_bits[name] == 0) {
+ mask_bits[name] = 1
+ vname = var_name(flags[i])
+ mask = "MASK_"
+ mask_1 = "1U"
+ if (vname != "") {
+ mask = "OPTION_MASK_"
+ if (host_wide_int[vname] == "yes")
+ mask_1 = "HOST_WIDE_INT_1U"
+ } else
+ extra_mask_bits[name] = 1
+ print "#define " mask name " (" mask_1 " << " masknum[vname]++ ")"
+ }
+}
+for (i = 0; i < n_extra_masks; i++) {
+ if (extra_mask_bits[extra_masks[i]] == 0)
+ print "#define MASK_" extra_masks[i] " (1U << " masknum[""]++ ")"
+}
+
+for (var in masknum) {
+ if (var != "" && host_wide_int[var] == "yes") {
+ print "#if defined(HOST_BITS_PER_WIDE_INT) && " masknum[var] " > HOST_BITS_PER_WIDE_INT"
+ print "#error too many masks for " var
+ print "#endif"
+ }
+ else if (masknum[var] > 32) {
+ if (var == "")
+ print "#error too many target masks"
+ else
+ print "#error too many masks for " var
+ }
+}
+print ""
+
+for (i = 0; i < n_opts; i++) {
+ name = opt_args("Mask", flags[i])
+ if (name == "") {
+ opt = opt_args("InverseMask", flags[i])
+ if (opt ~ ",")
+ name = nth_arg(0, opt)
+ else
+ name = opt
+ }
+ if (name != "" && mask_macros[name] == 0) {
+ mask_macros[name] = 1
+ vname = var_name(flags[i])
+ mask = "OPTION_MASK_"
+ if (vname == "") {
+ vname = "target_flags"
+ mask = "MASK_"
+ extra_mask_macros[name] = 1
+ }
+ original_name = name
+ gsub("ISA_", "", name)
+ gsub("ISA2_", "", name)
+ print "/* " original_name " mask */"
+ print "#define TARGET_" name \
+ " ((" vname " & " mask original_name ") != 0)"
+ print "#define TARGET_" name "_P(" vname ")" \
+ " (((" vname ") & " mask original_name ") != 0)"
+ print "#define TARGET_EXPLICIT_" name "_P(opts)" \
+ " ((opts->x_" vname "_explicit & " mask original_name ") != 0)"
+ print "#define SET_TARGET_" name "(opts) opts->x_" vname " |= " mask original_name
+ }
+}
+for (i = 0; i < n_extra_masks; i++) {
+ if (extra_mask_macros[extra_masks[i]] == 0)
+ print "#define TARGET_" extra_masks[i] \
+ " ((target_flags & MASK_" extra_masks[i] ") != 0)"
+}
+print ""
+
+for (i = 0; i < n_opts; i++) {
+ opt = opt_args("InverseMask", flags[i])
+ if (opt ~ ",") {
+ vname = var_name(flags[i])
+ mask = "OPTION_MASK_"
+ if (vname == "") {
+ vname = "target_flags"
+ mask = "MASK_"
+ }
+ print "#define TARGET_" nth_arg(1, opt) \
+ " ((" vname " & " mask nth_arg(0, opt) ") == 0)"
+ }
+}
+print ""
+
+for (i = 0; i < n_langs; i++) {
+ macros[i] = "CL_" lang_sanitized_name(langs[i])
+ s = substr(" ", length (macros[i]))
+ print "#define " macros[i] s " (1U << " i ")"
+ }
+print "#define CL_LANG_ALL ((1U << " n_langs ") - 1)"
+
+print ""
+print "enum opt_code"
+print "{"
+
+for (i = 0; i < n_opts; i++)
+ back_chain[i] = "N_OPTS";
+
+enum_value = 0
+for (i = 0; i < n_opts; i++) {
+ # Combine the flags of identical switches. Switches
+ # appear many times if they are handled by many front
+ # ends, for example.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ flags[i + 1] = flags[i] " " flags[i + 1];
+ i++;
+ }
+
+ len = length (opts[i]);
+ enum = opt_enum(opts[i])
+ enum_string = enum " = " enum_value ","
+
+ # Aliases do not get enumeration names.
+ if ((flag_set_p("Alias.*", flags[i]) \
+ && !flag_set_p("SeparateAlias", flags[i])) \
+ || flag_set_p("Ignore", flags[i])) {
+ enum_string = "/* " enum_string " */"
+ }
+
+ # If this switch takes joined arguments, back-chain all
+ # subsequent switches to it for which it is a prefix. If
+ # a later switch S is a longer prefix of a switch T, T
+ # will be back-chained to S in a later iteration of this
+ # for() loop, which is what we want.
+ if (flag_set_p("Joined.*", flags[i])) {
+ for (j = i + 1; j < n_opts; j++) {
+ if (substr (opts[j], 1, len) != opts[i])
+ break;
+ back_chain[j] = enum;
+ }
+ }
+
+ s = substr(" ",
+ length (enum_string))
+
+ if (help[i] == "")
+ hlp = "0"
+ else
+ hlp = "N_(\"" help[i] "\")";
+
+ print " " enum_string s "/* -" opts[i] " */"
+ enum_value++
+}
+
+print " N_OPTS,"
+print " OPT_SPECIAL_unknown,"
+print " OPT_SPECIAL_ignore,"
+print " OPT_SPECIAL_warn_removed,"
+print " OPT_SPECIAL_program_name,"
+print " OPT_SPECIAL_input_file"
+print "};"
+print ""
+print "#ifdef GCC_C_COMMON_C"
+print "/* Mapping from cpp message reasons to the options that enable them. */"
+print "#include <cpplib.h>"
+print "struct cpp_reason_option_codes_t"
+print "{"
+print " /* cpplib message reason. */"
+print " const enum cpp_warning_reason reason;"
+print " /* gcc option that controls this message. */"
+print " const int option_code;"
+print "};"
+print ""
+print "static const struct cpp_reason_option_codes_t cpp_reason_option_codes[] = {"
+for (i = 0; i < n_opts; i++) {
+ # With identical flags, pick only the last one. The
+ # earlier loop ensured that it has all flags merged,
+ # and a nonempty help text if one of the texts was nonempty.
+ while( i + 1 != n_opts && opts[i] == opts[i + 1] ) {
+ i++;
+ }
+ cpp_reason = nth_arg(0, opt_args("CppReason", flags[i]));
+ if (cpp_reason != "") {
+ cpp_reason = cpp_reason ",";
+ printf(" {%-40s %s},\n", cpp_reason, opt_enum(opts[i]))
+ }
+}
+printf(" {%-40s 0},\n", "CPP_W_NONE,")
+print "};"
+print "#endif"
+print ""
+print "#endif /* OPTIONS_H */"
+}
diff --git a/support/cpp/gcc/optinfo.h b/support/cpp/gcc/optinfo.h
new file mode 100644
index 000000000..4585f2e20
--- /dev/null
+++ b/support/cpp/gcc/optinfo.h
@@ -0,0 +1,170 @@
+/* Optimization information.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.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.
+
+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_OPTINFO_H
+#define GCC_OPTINFO_H
+
+/* An "optinfo" is a bundle of information describing part of an
+ optimization, which can be emitted to zero or more of several
+ destinations, such as:
+
+ * saved to a file as an "optimization record"
+
+ They are generated in response to calls to the "dump_*" API in
+ dumpfile.h; repeated calls to the "dump_*" API are consolidated
+ into a pending optinfo instance, with a "dump_*_loc" starting a new
+ optinfo instance.
+
+ The data sent to the dump calls are captured within the pending optinfo
+ instance as a sequence of optinfo_items. For example, given:
+
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "not vectorized: live stmt not supported: ");
+ dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, stmt, 0);
+ }
+
+ the "dump_printf_loc" call begins a new optinfo containing two items:
+ (1) a text item containing "not vectorized: live stmt not supported: "
+ (2) a gimple item for "stmt"
+
+ Dump destinations are thus able to access rich metadata about the
+ items when the optinfo is emitted to them, rather than just having plain
+ text. For example, when saving the above optinfo to a file as an
+ "optimization record", the record could capture the source location of
+ "stmt" above, rather than just its textual form.
+
+ The currently pending optinfo is emitted and deleted:
+ * each time a "dump_*_loc" call occurs (which starts the next optinfo), or
+ * when the dump files are changed (at the end of a pass)
+
+ Dumping to an optinfo instance is non-trivial (due to building optinfo_item
+ instances), so all usage should be guarded by
+
+ if (optinfo_enabled_p ())
+
+ which is off by default. */
+
+
+/* Forward decls. */
+class opt_pass;
+class optinfo_item;
+
+/* Return true if any of the active optinfo destinations make use
+ of inlining information.
+ (if true, then the information is preserved). */
+
+extern bool optinfo_wants_inlining_info_p ();
+
+/* The various kinds of optinfo. */
+
+enum optinfo_kind
+{
+ OPTINFO_KIND_SUCCESS,
+ OPTINFO_KIND_FAILURE,
+ OPTINFO_KIND_NOTE,
+ OPTINFO_KIND_SCOPE
+};
+
+extern const char *optinfo_kind_to_string (enum optinfo_kind kind);
+
+class dump_context;
+
+/* A bundle of information describing part of an optimization. */
+
+class optinfo
+{
+ friend class dump_context;
+
+ public:
+ optinfo (const dump_location_t &loc,
+ enum optinfo_kind kind,
+ opt_pass *pass)
+ : m_loc (loc), m_kind (kind), m_pass (pass), m_items ()
+ {}
+ ~optinfo ();
+
+ const dump_location_t &
+ get_dump_location () const { return m_loc; }
+
+ const dump_user_location_t &
+ get_user_location () const { return m_loc.get_user_location (); }
+
+ const dump_impl_location_t &
+ get_impl_location () const { return m_loc.get_impl_location (); }
+
+ enum optinfo_kind get_kind () const { return m_kind; }
+ opt_pass *get_pass () const { return m_pass; }
+ unsigned int num_items () const { return m_items.length (); }
+ const optinfo_item *get_item (unsigned int i) const { return m_items[i]; }
+
+ location_t get_location_t () const { return m_loc.get_location_t (); }
+ profile_count get_count () const { return m_loc.get_count (); }
+
+ void add_item (optinfo_item *item);
+
+ void emit_for_opt_problem () const;
+
+ private:
+ /* Pre-canned ways of manipulating the optinfo, for use by friend class
+ dump_context. */
+ void handle_dump_file_kind (dump_flags_t);
+
+ private:
+ dump_location_t m_loc;
+ enum optinfo_kind m_kind;
+ opt_pass *m_pass;
+ auto_vec <optinfo_item *> m_items;
+};
+
+/* An enum for discriminating between different kinds of optinfo_item. */
+
+enum optinfo_item_kind
+{
+ OPTINFO_ITEM_KIND_TEXT,
+ OPTINFO_ITEM_KIND_TREE,
+ OPTINFO_ITEM_KIND_GIMPLE,
+ OPTINFO_ITEM_KIND_SYMTAB_NODE
+};
+
+/* An item within an optinfo. */
+
+class optinfo_item
+{
+ public:
+ optinfo_item (enum optinfo_item_kind kind, location_t location,
+ char *text);
+ ~optinfo_item ();
+
+ enum optinfo_item_kind get_kind () const { return m_kind; }
+ location_t get_location () const { return m_location; }
+ const char *get_text () const { return m_text; }
+
+ private:
+ /* Metadata (e.g. for optimization records). */
+ enum optinfo_item_kind m_kind;
+ location_t m_location;
+
+ /* The textual form of the item, owned by the item. */
+ char *m_text;
+};
+
+#endif /* #ifndef GCC_OPTINFO_H */
diff --git a/support/cpp/gcc/opts-common.cc b/support/cpp/gcc/opts-common.cc
new file mode 100644
index 000000000..19ef1889b
--- /dev/null
+++ b/support/cpp/gcc/opts-common.cc
@@ -0,0 +1,2017 @@
+/* Command line option handling.
+ Copyright (C) 2006-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 <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ <<":" << __func__ << "\n" )
+
+#include "config.h"
+#include "system.h"
+#include "intl.h"
+#include "coretypes.h"
+#include "opts.h"
+#include "options.h"
+#include "diagnostic.h"
+#include "spellcheck.h"
+
+static void prune_options (struct cl_decoded_option **, unsigned int *);
+
+/* An option that is undocumented, that takes a joined argument, and
+ that doesn't fit any of the classes of uses (language/common,
+ driver, target) is assumed to be a prefix used to catch
+ e.g. negated options, and stop them from being further shortened to
+ a prefix that could use the negated option as an argument. For
+ example, we want -gno-statement-frontiers to be taken as a negation
+ of -gstatement-frontiers, but without catching the gno- prefix and
+ signaling it's to be used for option remapping, it would end up
+ backtracked to g with no-statemnet-frontiers as the debug level. */
+
+static bool
+remapping_prefix_p (const struct cl_option *opt)
+{
+ return opt->flags & CL_UNDOCUMENTED
+ && opt->flags & CL_JOINED
+ && !(opt->flags & (CL_DRIVER | CL_TARGET | CL_COMMON | CL_LANG_ALL));
+}
+
+/* Perform a binary search to find which option the command-line INPUT
+ matches. Returns its index in the option array, and
+ OPT_SPECIAL_unknown on failure.
+
+ This routine is quite subtle. A normal binary search is not good
+ enough because some options can be suffixed with an argument, and
+ multiple sub-matches can occur, e.g. input of "-pedantic" matching
+ the initial substring of "-pedantic-errors".
+
+ A more complicated example is -gstabs. It should match "-g" with
+ an argument of "stabs". Suppose, however, that the number and list
+ of switches are such that the binary search tests "-gen-decls"
+ before having tested "-g". This doesn't match, and as "-gen-decls"
+ is less than "-gstabs", it will become the lower bound of the
+ binary search range, and "-g" will never be seen. To resolve this
+ issue, 'optc-gen.awk' makes "-gen-decls" point, via the back_chain member,
+ to "-g" so that failed searches that end between "-gen-decls" and
+ the lexicographically subsequent switch know to go back and see if
+ "-g" causes a match (which it does in this example).
+
+ This search is done in such a way that the longest match for the
+ front end in question wins. If there is no match for the current
+ front end, the longest match for a different front end is returned
+ (or N_OPTS if none) and the caller emits an error message. */
+size_t
+find_opt (const char *input, unsigned int lang_mask)
+{
+ size_t mn, mn_orig, mx, md, opt_len;
+ size_t match_wrong_lang;
+ int comp;
+
+ mn = 0;
+ mx = cl_options_count;
+
+ /* Find mn such this lexicographical inequality holds:
+ cl_options[mn] <= input < cl_options[mn + 1]. */
+ while (mx - mn > 1)
+ {
+ md = (mn + mx) / 2;
+ opt_len = cl_options[md].opt_len;
+ comp = strncmp (input, cl_options[md].opt_text + 1, opt_len);
+
+ if (comp < 0)
+ mx = md;
+ else
+ mn = md;
+ }
+
+ mn_orig = mn;
+
+ /* This is the switch that is the best match but for a different
+ front end, or OPT_SPECIAL_unknown if there is no match at all. */
+ match_wrong_lang = OPT_SPECIAL_unknown;
+
+ /* Backtrace the chain of possible matches, returning the longest
+ one, if any, that fits best. With current GCC switches, this
+ loop executes at most twice. */
+ do
+ {
+ const struct cl_option *opt = &cl_options[mn];
+
+ /* Is the input either an exact match or a prefix that takes a
+ joined argument? */
+ if (!strncmp (input, opt->opt_text + 1, opt->opt_len)
+ && (input[opt->opt_len] == '\0' || (opt->flags & CL_JOINED)))
+ {
+ /* If language is OK, return it. */
+ if (opt->flags & lang_mask){
+ return mn;
+ }else if (remapping_prefix_p (opt)) {untested();
+ return OPT_SPECIAL_unknown;
+
+ /* If we haven't remembered a prior match, remember this
+ one. Any prior match is necessarily better. */
+ }else if (match_wrong_lang == OPT_SPECIAL_unknown){
+ match_wrong_lang = mn;
+ }else{ untested();
+ }
+ }
+
+ /* Try the next possibility. This is cl_options_count if there
+ are no more. */
+ mn = opt->back_chain;
+ }
+ while (mn != cl_options_count);
+
+ if (match_wrong_lang == OPT_SPECIAL_unknown && input[0] == '-')
+ { untested();
+ /* Long options, starting "--", may be abbreviated if the
+ abbreviation is unambiguous. This only applies to options
+ not taking a joined argument, and abbreviations of "--option"
+ are permitted even if there is a variant "--option=". */
+ size_t mnc = mn_orig + 1;
+ size_t cmp_len = strlen (input);
+ while (mnc < cl_options_count
+ && strncmp (input, cl_options[mnc].opt_text + 1, cmp_len) == 0)
+ { untested();
+ /* Option matching this abbreviation. OK if it is the first
+ match and that does not take a joined argument, or the
+ second match, taking a joined argument and with only '='
+ added to the first match; otherwise considered
+ ambiguous. */
+ if (mnc == mn_orig + 1
+ && !(cl_options[mnc].flags & CL_JOINED))
+ match_wrong_lang = mnc;
+ else if (mnc == mn_orig + 2
+ && match_wrong_lang == mn_orig + 1
+ && (cl_options[mnc].flags & CL_JOINED)
+ && (cl_options[mnc].opt_len
+ == cl_options[mn_orig + 1].opt_len + 1)
+ && strncmp (cl_options[mnc].opt_text + 1,
+ cl_options[mn_orig + 1].opt_text + 1,
+ cl_options[mn_orig + 1].opt_len) == 0)
+ ; /* OK, as long as there are no more matches. */
+ else
+ return OPT_SPECIAL_unknown;
+ mnc++;
+ }
+ }
+
+ /* Return the best wrong match, or OPT_SPECIAL_unknown if none. */
+ return match_wrong_lang;
+}
+
+/* If ARG is a non-negative decimal or hexadecimal integer representable
+ in HOST_WIDE_INT return its value, otherwise return -1. If ERR is not
+ null set *ERR to zero on success or to EINVAL or to the value of errno
+ otherwise. */
+
+HOST_WIDE_INT
+integral_argument (const char *arg, int *err, bool byte_size_suffix)
+{ untested();
+ if (!err)
+ err = &errno;
+
+ if (!ISDIGIT (*arg))
+ { untested();
+ *err = EINVAL;
+ return -1;
+ }
+
+ *err = 0;
+ errno = 0;
+
+ char *end = NULL;
+ unsigned HOST_WIDE_INT unit = 1;
+ unsigned HOST_WIDE_INT value = strtoull (arg, &end, 10);
+
+ /* If the value is too large to be represented use the maximum
+ representable value that strtoull sets VALUE to (setting
+ errno to ERANGE). */
+
+ if (end && *end)
+ { untested();
+ if (!byte_size_suffix)
+ { untested();
+ errno = 0;
+ value = strtoull (arg, &end, 0);
+ if (*end)
+ { untested();
+ if (errno)
+ *err = errno;
+ else
+ *err = EINVAL;
+ return -1;
+ }
+
+ return value;
+ }
+
+ /* Numeric option arguments are at most INT_MAX. Make it
+ possible to specify a larger value by accepting common
+ suffixes. */
+ if (!strcmp (end, "kB"))
+ unit = 1000;
+ else if (!strcasecmp (end, "KiB") || !strcmp (end, "KB"))
+ unit = 1024;
+ else if (!strcmp (end, "MB"))
+ unit = HOST_WIDE_INT_UC (1000) * 1000;
+ else if (!strcasecmp (end, "MiB"))
+ unit = HOST_WIDE_INT_UC (1024) * 1024;
+ else if (!strcasecmp (end, "GB"))
+ unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000;
+ else if (!strcasecmp (end, "GiB"))
+ unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024;
+ else if (!strcasecmp (end, "TB"))
+ unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000;
+ else if (!strcasecmp (end, "TiB"))
+ unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024;
+ else if (!strcasecmp (end, "PB"))
+ unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000;
+ else if (!strcasecmp (end, "PiB"))
+ unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024;
+ else if (!strcasecmp (end, "EB"))
+ unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000
+ * 1000;
+ else if (!strcasecmp (end, "EiB"))
+ unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024
+ * 1024;
+ else
+ { untested();
+ /* This could mean an unknown suffix or a bad prefix, like
+ "+-1". */
+ *err = EINVAL;
+ return -1;
+ }
+ }
+
+ if (unit)
+ { untested();
+ unsigned HOST_WIDE_INT prod = value * unit;
+ value = prod < value ? HOST_WIDE_INT_M1U : prod;
+ }
+
+ return value;
+}
+
+/* Return whether OPTION is OK for the language given by
+ LANG_MASK. */
+static bool
+option_ok_for_language (const struct cl_option *option,
+ unsigned int lang_mask)
+{
+ if (!(option->flags & lang_mask))
+ return false;
+ else if ((option->flags & CL_TARGET)
+ && (option->flags & (CL_LANG_ALL | CL_DRIVER))
+ && !(option->flags & (lang_mask & ~CL_COMMON & ~CL_TARGET)))
+ /* Complain for target flag language mismatches if any languages
+ are specified. */
+ return false;
+ return true;
+}
+
+/* Return whether ENUM_ARG is OK for the language given by
+ LANG_MASK. */
+
+static bool
+enum_arg_ok_for_language (const struct cl_enum_arg *enum_arg,
+ unsigned int lang_mask)
+{ untested();
+ return (lang_mask & CL_DRIVER) || !(enum_arg->flags & CL_ENUM_DRIVER_ONLY);
+}
+
+/* Look up ARG in ENUM_ARGS for language LANG_MASK, returning the cl_enum_arg
+ index and storing the value in *VALUE if found, and returning -1 without
+ modifying *VALUE if not found. */
+
+static int
+enum_arg_to_value (const struct cl_enum_arg *enum_args,
+ const char *arg, size_t len, HOST_WIDE_INT *value,
+ unsigned int lang_mask)
+{ untested();
+ unsigned int i;
+
+ for (i = 0; enum_args[i].arg != NULL; i++)
+ if ((len
+ ? (strncmp (arg, enum_args[i].arg, len) == 0
+ && enum_args[i].arg[len] == '\0')
+ : strcmp (arg, enum_args[i].arg) == 0)
+ && enum_arg_ok_for_language (&enum_args[i], lang_mask))
+ { untested();
+ *value = enum_args[i].value;
+ return i;
+ }
+
+ return -1;
+}
+
+/* Look up ARG in the enum used by option OPT_INDEX for language
+ LANG_MASK, returning true and storing the value in *VALUE if found,
+ and returning false without modifying *VALUE if not found. */
+
+bool
+opt_enum_arg_to_value (size_t opt_index, const char *arg,
+ int *value, unsigned int lang_mask)
+{ untested();
+ const struct cl_option *option = &cl_options[opt_index];
+
+ gcc_assert (option->var_type == CLVC_ENUM);
+
+ HOST_WIDE_INT wideval;
+ if (enum_arg_to_value (cl_enums[option->var_enum].values, arg, 0,
+ &wideval, lang_mask) >= 0)
+ { untested();
+ *value = wideval;
+ return true;
+ }
+
+ return false;
+}
+
+/* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the
+ corresponding string in *ARGP, returning true if the found string
+ was marked as canonical, false otherwise. If VALUE is not found
+ (which may be the case for uninitialized values if the relevant
+ option has not been passed), set *ARGP to NULL and return
+ false. */
+
+bool
+enum_value_to_arg (const struct cl_enum_arg *enum_args,
+ const char **argp, int value, unsigned int lang_mask)
+{ untested();
+ unsigned int i;
+
+ for (i = 0; enum_args[i].arg != NULL; i++)
+ if (enum_args[i].value == value
+ && (enum_args[i].flags & CL_ENUM_CANONICAL)
+ && enum_arg_ok_for_language (&enum_args[i], lang_mask))
+ { untested();
+ *argp = enum_args[i].arg;
+ return true;
+ }
+
+ for (i = 0; enum_args[i].arg != NULL; i++)
+ if (enum_args[i].value == value
+ && enum_arg_ok_for_language (&enum_args[i], lang_mask))
+ { untested();
+ *argp = enum_args[i].arg;
+ return false;
+ }
+
+ *argp = NULL;
+ return false;
+}
+
+/* Fill in the canonical option part of *DECODED with an option
+ described by OPT_INDEX, ARG and VALUE. */
+
+static void
+generate_canonical_option (size_t opt_index, const char *arg,
+ HOST_WIDE_INT value,
+ struct cl_decoded_option *decoded)
+{
+ const struct cl_option *option = &cl_options[opt_index];
+ const char *opt_text = option->opt_text;
+
+ if (value == 0
+ && !option->cl_reject_negative
+ && (opt_text[1] == 'W' || opt_text[1] == 'f'
+ || opt_text[1] == 'g' || opt_text[1] == 'm'))
+ {
+ char *t = XOBNEWVEC (&opts_obstack, char, option->opt_len + 5);
+ t[0] = '-';
+ t[1] = opt_text[1];
+ t[2] = 'n';
+ t[3] = 'o';
+ t[4] = '-';
+ memcpy (t + 5, opt_text + 2, option->opt_len);
+ opt_text = t;
+ }
+
+ decoded->canonical_option[2] = NULL;
+ decoded->canonical_option[3] = NULL;
+
+ if (arg)
+ {
+ if ((option->flags & CL_SEPARATE)
+ && !option->cl_separate_alias)
+ {
+ decoded->canonical_option[0] = opt_text;
+ decoded->canonical_option[1] = arg;
+ decoded->canonical_option_num_elements = 2;
+ }
+ else
+ {
+ gcc_assert (option->flags & CL_JOINED);
+ decoded->canonical_option[0] = opts_concat (opt_text, arg, NULL);
+ decoded->canonical_option[1] = NULL;
+ decoded->canonical_option_num_elements = 1;
+ }
+ }
+ else
+ {
+ decoded->canonical_option[0] = opt_text;
+ decoded->canonical_option[1] = NULL;
+ decoded->canonical_option_num_elements = 1;
+ }
+}
+
+/* Structure describing mappings from options on the command line to
+ options to look up with find_opt. */
+struct option_map
+{
+ /* Prefix of the option on the command line. */
+ const char *opt0;
+ /* If two argv elements are considered to be merged into one option,
+ prefix for the second element, otherwise NULL. */
+ const char *opt1;
+ /* The new prefix to map to. */
+ const char *new_prefix;
+ /* Whether at least one character is needed following opt1 or opt0
+ for this mapping to be used. (--optimize= is valid for -O, but
+ --warn- is not valid for -W.) */
+ bool another_char_needed;
+ /* Whether the original option is a negated form of the option
+ resulting from this map. */
+ bool negated;
+};
+static const struct option_map option_map[] =
+ {
+ { "-Wno-", NULL, "-W", false, true },
+ { "-fno-", NULL, "-f", false, true },
+ { "-gno-", NULL, "-g", false, true },
+ { "-mno-", NULL, "-m", false, true },
+ { "--debug=", NULL, "-g", false, false },
+ { "--machine-", NULL, "-m", true, false },
+ { "--machine-no-", NULL, "-m", false, true },
+ { "--machine=", NULL, "-m", false, false },
+ { "--machine=no-", NULL, "-m", false, true },
+ { "--machine", "", "-m", false, false },
+ { "--machine", "no-", "-m", false, true },
+ { "--optimize=", NULL, "-O", false, false },
+ { "--std=", NULL, "-std=", false, false },
+ { "--std", "", "-std=", false, false },
+ { "--warn-", NULL, "-W", true, false },
+ { "--warn-no-", NULL, "-W", false, true },
+ { "--", NULL, "-f", true, false },
+ { "--no-", NULL, "-f", false, true }
+ };
+
+/* Helper function for gcc.cc's driver::suggest_option, for populating the
+ vec of suggestions for misspelled options.
+
+ option_map above provides various prefixes for spelling command-line
+ options, which decode_cmdline_option uses to map spellings of options
+ to specific options. We want to do the reverse: to find all the ways
+ that a user could validly spell an option.
+
+ Given valid OPT_TEXT (with a leading dash) for OPTION, add it and all
+ of its valid variant spellings to CANDIDATES, each without a leading
+ dash.
+
+ For example, given "-Wabi-tag", the following are added to CANDIDATES:
+ "Wabi-tag"
+ "Wno-abi-tag"
+ "-warn-abi-tag"
+ "-warn-no-abi-tag".
+
+ The added strings must be freed using free. */
+
+void
+add_misspelling_candidates (auto_vec<char *> *candidates,
+ const struct cl_option *option,
+ const char *opt_text)
+{ untested();
+ gcc_assert (candidates);
+ gcc_assert (option);
+ gcc_assert (opt_text);
+ if (remapping_prefix_p (option))
+ return;
+ candidates->safe_push (xstrdup (opt_text + 1));
+ for (unsigned i = 0; i < ARRAY_SIZE (option_map); i++)
+ { untested();
+ const char *opt0 = option_map[i].opt0;
+ const char *new_prefix = option_map[i].new_prefix;
+ size_t new_prefix_len = strlen (new_prefix);
+
+ if (option->cl_reject_negative && option_map[i].negated)
+ continue;
+
+ if (strncmp (opt_text, new_prefix, new_prefix_len) == 0)
+ { untested();
+ char *alternative = concat (opt0 + 1, opt_text + new_prefix_len,
+ NULL);
+ candidates->safe_push (alternative);
+ }
+ }
+
+ /* For all params (e.g. --param=key=value),
+ include also '--param key=value'. */
+ const char *prefix = "--param=";
+ if (strstr (opt_text, prefix) == opt_text)
+ { untested();
+ char *param = xstrdup (opt_text + 1);
+ gcc_assert (param[6] == '=');
+ param[6] = ' ';
+ candidates->safe_push (param);
+ }
+}
+
+/* Decode the switch beginning at ARGV for the language indicated by
+ LANG_MASK (including CL_COMMON and CL_TARGET if applicable), into
+ the structure *DECODED. Returns the number of switches
+ consumed. */
+
+static unsigned int
+decode_cmdline_option (const char *const *argv, unsigned int lang_mask,
+ struct cl_decoded_option *decoded)
+{
+ size_t opt_index;
+ const char *arg = 0;
+ HOST_WIDE_INT value = 1, mask = 0;
+ unsigned int result = 1, i, extra_args, separate_args = 0;
+ int adjust_len = 0;
+ size_t total_len;
+ char *p;
+ const struct cl_option *option;
+ int errors = 0;
+ const char *warn_message = NULL;
+ bool separate_arg_flag;
+ bool joined_arg_flag;
+ bool have_separate_arg = false;
+
+ extra_args = 0;
+
+ const char *opt_value = argv[0] + 1;
+ opt_index = find_opt (opt_value, lang_mask);
+ i = 0;
+ while (opt_index == OPT_SPECIAL_unknown
+ && i < ARRAY_SIZE (option_map))
+ {
+ const char *opt0 = option_map[i].opt0;
+ const char *opt1 = option_map[i].opt1;
+ const char *new_prefix = option_map[i].new_prefix;
+ bool another_char_needed = option_map[i].another_char_needed;
+ size_t opt0_len = strlen (opt0);
+ size_t opt1_len = (opt1 == NULL ? 0 : strlen (opt1));
+ size_t optn_len = (opt1 == NULL ? opt0_len : opt1_len);
+ size_t new_prefix_len = strlen (new_prefix);
+
+ extra_args = (opt1 == NULL ? 0 : 1);
+ value = !option_map[i].negated;
+
+ if (strncmp (argv[0], opt0, opt0_len) == 0
+ && (opt1 == NULL
+ || (argv[1] != NULL && strncmp (argv[1], opt1, opt1_len) == 0))
+ && (!another_char_needed
+ || argv[extra_args][optn_len] != 0))
+ { untested();
+ size_t arglen = strlen (argv[extra_args]);
+ char *dup;
+
+ adjust_len = (int) optn_len - (int) new_prefix_len;
+ dup = XNEWVEC (char, arglen + 1 - adjust_len);
+ memcpy (dup, new_prefix, new_prefix_len);
+ memcpy (dup + new_prefix_len, argv[extra_args] + optn_len,
+ arglen - optn_len + 1);
+ opt_index = find_opt (dup + 1, lang_mask);
+ free (dup);
+ }
+ i++;
+ }
+
+ if (opt_index == OPT_SPECIAL_unknown)
+ {
+ arg = argv[0];
+ extra_args = 0;
+ value = 1;
+ goto done;
+ }
+
+ option = &cl_options[opt_index];
+
+ /* Reject negative form of switches that don't take negatives as
+ unrecognized. */
+ if (!value && option->cl_reject_negative)
+ { untested();
+ opt_index = OPT_SPECIAL_unknown;
+ errors |= CL_ERR_NEGATIVE;
+ arg = argv[0];
+ goto done;
+ }
+
+ /* Clear the initial value for size options (it will be overwritten
+ later based on the Init(value) specification in the opt file. */
+ if (option->var_type == CLVC_SIZE)
+ value = 0;
+
+ result = extra_args + 1;
+ warn_message = option->warn_message;
+
+ /* Check to see if the option is disabled for this configuration. */
+ if (option->cl_disabled)
+ errors |= CL_ERR_DISABLED;
+
+ /* Determine whether there may be a separate argument based on
+ whether this option is being processed for the driver, and, if
+ so, how many such arguments. */
+ separate_arg_flag = ((option->flags & CL_SEPARATE)
+ && !(option->cl_no_driver_arg
+ && (lang_mask & CL_DRIVER)));
+ separate_args = (separate_arg_flag
+ ? option->cl_separate_nargs + 1
+ : 0);
+ joined_arg_flag = (option->flags & CL_JOINED) != 0;
+
+ /* Sort out any argument the switch takes. */
+ if (joined_arg_flag)
+ {
+ /* Have arg point to the original switch. This is because
+ some code, such as disable_builtin_function, expects its
+ argument to be persistent until the program exits. */
+ arg = argv[extra_args] + cl_options[opt_index].opt_len + 1 + adjust_len;
+
+ if (*arg == '\0' && !option->cl_missing_ok)
+ {
+ if (separate_arg_flag)
+ {
+ arg = argv[extra_args + 1];
+ result = extra_args + 2;
+ if (arg == NULL)
+ result = extra_args + 1;
+ else
+ have_separate_arg = true;
+ }
+ else
+ /* Missing argument. */
+ arg = NULL;
+ }
+ }
+ else if (separate_arg_flag)
+ {
+ arg = argv[extra_args + 1];
+ for (i = 0; i < separate_args; i++)
+ if (argv[extra_args + 1 + i] == NULL)
+ { untested();
+ errors |= CL_ERR_MISSING_ARG;
+ break;
+ }
+ result = extra_args + 1 + i;
+ if (arg != NULL)
+ have_separate_arg = true;
+ }
+
+ if (arg == NULL && (separate_arg_flag || joined_arg_flag))
+ errors |= CL_ERR_MISSING_ARG;
+
+ /* Is this option an alias (or an ignored option, marked as an alias
+ of OPT_SPECIAL_ignore)? */
+ if (option->alias_target != N_OPTS
+ && (!option->cl_separate_alias || have_separate_arg))
+ {
+ size_t new_opt_index = option->alias_target;
+
+ if (new_opt_index == OPT_SPECIAL_ignore
+ || new_opt_index == OPT_SPECIAL_warn_removed)
+ { untested();
+ gcc_assert (option->alias_arg == NULL);
+ gcc_assert (option->neg_alias_arg == NULL);
+ opt_index = new_opt_index;
+ arg = NULL;
+ }
+ else
+ {
+ const struct cl_option *new_option = &cl_options[new_opt_index];
+
+ /* The new option must not be an alias itself. */
+ gcc_assert (new_option->alias_target == N_OPTS
+ || new_option->cl_separate_alias);
+
+ if (option->neg_alias_arg)
+ { untested();
+ gcc_assert (option->alias_arg != NULL);
+ gcc_assert (arg == NULL);
+ gcc_assert (!option->cl_negative_alias);
+ if (value)
+ arg = option->alias_arg;
+ else
+ arg = option->neg_alias_arg;
+ value = 1;
+ }
+ else if (option->alias_arg)
+ { untested();
+ gcc_assert (value == 1);
+ gcc_assert (arg == NULL);
+ gcc_assert (!option->cl_negative_alias);
+ arg = option->alias_arg;
+ }
+
+ if (option->cl_negative_alias)
+ value = !value;
+
+ opt_index = new_opt_index;
+ option = new_option;
+
+ if (value == 0)
+ gcc_assert (!option->cl_reject_negative);
+
+ /* Recompute what arguments are allowed. */
+ separate_arg_flag = ((option->flags & CL_SEPARATE)
+ && !(option->cl_no_driver_arg
+ && (lang_mask & CL_DRIVER)));
+ joined_arg_flag = (option->flags & CL_JOINED) != 0;
+
+ if (separate_args > 1 || option->cl_separate_nargs)
+ gcc_assert (separate_args
+ == (unsigned int) option->cl_separate_nargs + 1);
+
+ if (!(errors & CL_ERR_MISSING_ARG))
+ {
+ if (separate_arg_flag || joined_arg_flag)
+ {
+ if (option->cl_missing_ok && arg == NULL)
+ arg = "";
+ gcc_assert (arg != NULL);
+ }
+ else
+ gcc_assert (arg == NULL);
+ }
+
+ /* Recheck for warnings and disabled options. */
+ if (option->warn_message)
+ { untested();
+ gcc_assert (warn_message == NULL);
+ warn_message = option->warn_message;
+ }
+ if (option->cl_disabled)
+ errors |= CL_ERR_DISABLED;
+ }
+ }
+
+ /* Check if this is a switch for a different front end. */
+ if (!option_ok_for_language (option, lang_mask))
+ errors |= CL_ERR_WRONG_LANG;
+ else if (strcmp (option->opt_text, "-Werror=") == 0
+ && strchr (opt_value, ',') == NULL)
+ { untested();
+ /* Verify that -Werror argument is a valid warning
+ for a language. */
+ char *werror_arg = xstrdup (opt_value + 6);
+ werror_arg[0] = 'W';
+
+ size_t warning_index = find_opt (werror_arg, lang_mask);
+ free (werror_arg);
+ if (warning_index != OPT_SPECIAL_unknown)
+ { untested();
+ const struct cl_option *warning_option
+ = &cl_options[warning_index];
+ if (!option_ok_for_language (warning_option, lang_mask))
+ errors |= CL_ERR_WRONG_LANG;
+ }
+ }
+
+ /* Convert the argument to lowercase if appropriate. */
+ if (arg && option->cl_tolower)
+ { untested();
+ size_t j;
+ size_t len = strlen (arg);
+ char *arg_lower = XOBNEWVEC (&opts_obstack, char, len + 1);
+
+ for (j = 0; j < len; j++)
+ arg_lower[j] = TOLOWER ((unsigned char) arg[j]);
+ arg_lower[len] = 0;
+ arg = arg_lower;
+ }
+
+ /* If the switch takes an integer argument, convert it. */
+ if (arg && (option->cl_uinteger || option->cl_host_wide_int))
+ { untested();
+ int error = 0;
+ value = *arg ? integral_argument (arg, &error, option->cl_byte_size) : 0;
+ if (error)
+ errors |= CL_ERR_UINT_ARG;
+
+ /* Reject value out of a range. */
+ if (option->range_max != -1
+ && (value < option->range_min || value > option->range_max))
+ errors |= CL_ERR_INT_RANGE_ARG;
+ }
+
+ /* If the switch takes an enumerated argument, convert it. */
+ if (arg && (option->var_type == CLVC_ENUM))
+ { untested();
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+
+ gcc_assert (option->var_value != CLEV_NORMAL || value == 1);
+ if (option->var_value != CLEV_NORMAL)
+ { untested();
+ const char *p = arg;
+ HOST_WIDE_INT sum_value = 0;
+ unsigned HOST_WIDE_INT used_sets = 0;
+ do
+ { untested();
+ const char *q = strchr (p, ',');
+ HOST_WIDE_INT this_value = 0;
+ if (q && q == p)
+ { untested();
+ errors |= CL_ERR_ENUM_SET_ARG;
+ break;
+ }
+ int idx = enum_arg_to_value (e->values, p, q ? q - p : 0,
+ &this_value, lang_mask);
+ if (idx < 0)
+ { untested();
+ errors |= CL_ERR_ENUM_SET_ARG;
+ break;
+ }
+
+ HOST_WIDE_INT this_mask = 0;
+ if (option->var_value == CLEV_SET)
+ { untested();
+ unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT;
+ gcc_checking_assert (set >= 1
+ && set <= HOST_BITS_PER_WIDE_INT);
+ if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0)
+ { untested();
+ errors |= CL_ERR_ENUM_SET_ARG;
+ break;
+ }
+ used_sets |= HOST_WIDE_INT_1U << (set - 1);
+
+ for (int i = 0; e->values[i].arg != NULL; i++)
+ if (set == (e->values[i].flags >> CL_ENUM_SET_SHIFT))
+ this_mask |= e->values[i].value;
+ }
+ else
+ { untested();
+ gcc_assert (option->var_value == CLEV_BITSET
+ && ((e->values[idx].flags >> CL_ENUM_SET_SHIFT)
+ == 0));
+ this_mask = this_value;
+ }
+
+ sum_value |= this_value;
+ mask |= this_mask;
+ if (q == NULL)
+ break;
+ p = q + 1;
+ }
+ while (1);
+ if (value == 1)
+ value = sum_value;
+ else
+ gcc_checking_assert (value == 0);
+ }
+ else if (enum_arg_to_value (e->values, arg, 0, &value, lang_mask) >= 0)
+ { untested();
+ const char *carg = NULL;
+
+ if (enum_value_to_arg (e->values, &carg, value, lang_mask))
+ arg = carg;
+ gcc_assert (carg != NULL);
+ }
+ else
+ errors |= CL_ERR_ENUM_ARG;
+ }
+
+ done:
+ decoded->opt_index = opt_index;
+ decoded->arg = arg;
+ decoded->value = value;
+ decoded->mask = mask;
+ decoded->errors = errors;
+ decoded->warn_message = warn_message;
+
+ if (opt_index == OPT_SPECIAL_unknown)
+ gcc_assert (result == 1);
+
+ gcc_assert (result >= 1 && result <= ARRAY_SIZE (decoded->canonical_option));
+ decoded->canonical_option_num_elements = result;
+ total_len = 0;
+ for (i = 0; i < ARRAY_SIZE (decoded->canonical_option); i++)
+ {
+ if (i < result)
+ {
+ size_t len;
+ if (opt_index == OPT_SPECIAL_unknown)
+ decoded->canonical_option[i] = argv[i];
+ else
+ decoded->canonical_option[i] = NULL;
+ len = strlen (argv[i]);
+ /* If the argument is an empty string, we will print it as "" in
+ orig_option_with_args_text. */
+ total_len += (len != 0 ? len : 2) + 1;
+ }
+ else
+ decoded->canonical_option[i] = NULL;
+ }
+ if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore
+ && opt_index != OPT_SPECIAL_warn_removed)
+ {
+ generate_canonical_option (opt_index, arg, value, decoded);
+ if (separate_args > 1)
+ { untested();
+ for (i = 0; i < separate_args; i++)
+ { untested();
+ if (argv[extra_args + 1 + i] == NULL)
+ break;
+ else
+ decoded->canonical_option[1 + i] = argv[extra_args + 1 + i];
+ }
+ gcc_assert (result == 1 + i);
+ decoded->canonical_option_num_elements = result;
+ }
+ }
+ decoded->orig_option_with_args_text
+ = p = XOBNEWVEC (&opts_obstack, char, total_len);
+ for (i = 0; i < result; i++)
+ {
+ size_t len = strlen (argv[i]);
+
+ /* Print the empty string verbally. */
+ if (len == 0)
+ { untested();
+ *p++ = '"';
+ *p++ = '"';
+ }
+ else
+ memcpy (p, argv[i], len);
+ p += len;
+ if (i == result - 1)
+ *p++ = 0;
+ else
+ *p++ = ' ';
+ }
+
+ return result;
+}
+
+/* Obstack for option strings. */
+
+struct obstack opts_obstack;
+
+/* Like libiberty concat, but allocate using opts_obstack. */
+
+char *
+opts_concat (const char *first, ...)
+{
+ char *newstr, *end;
+ size_t length = 0;
+ const char *arg;
+ va_list ap;
+
+ /* First compute the size of the result and get sufficient memory. */
+ va_start (ap, first);
+ for (arg = first; arg; arg = va_arg (ap, const char *))
+ length += strlen (arg);
+ newstr = XOBNEWVEC (&opts_obstack, char, length + 1);
+ va_end (ap);
+
+ /* Now copy the individual pieces to the result string. */
+ va_start (ap, first);
+ for (arg = first, end = newstr; arg; arg = va_arg (ap, const char *))
+ {
+ length = strlen (arg);
+ memcpy (end, arg, length);
+ end += length;
+ }
+ *end = '\0';
+ va_end (ap);
+ return newstr;
+}
+
+/* Decode command-line options (ARGC and ARGV being the arguments of
+ main) into an array, setting *DECODED_OPTIONS to a pointer to that
+ array and *DECODED_OPTIONS_COUNT to the number of entries in the
+ array. The first entry in the array is always one for the program
+ name (OPT_SPECIAL_program_name). LANG_MASK indicates the language
+ flags applicable for decoding (including CL_COMMON and CL_TARGET if
+ those options should be considered applicable). Do not produce any
+ diagnostics or set state outside of these variables. */
+
+void
+decode_cmdline_options_to_array (unsigned int argc, const char **argv,
+ unsigned int lang_mask,
+ struct cl_decoded_option **decoded_options,
+ unsigned int *decoded_options_count)
+{
+ unsigned int n, i;
+ struct cl_decoded_option *opt_array;
+ unsigned int num_decoded_options;
+
+ int opt_array_len = argc;
+ opt_array = XNEWVEC (struct cl_decoded_option, opt_array_len);
+
+ opt_array[0].opt_index = OPT_SPECIAL_program_name;
+ opt_array[0].warn_message = NULL;
+ opt_array[0].arg = argv[0];
+ opt_array[0].orig_option_with_args_text = argv[0];
+ opt_array[0].canonical_option_num_elements = 1;
+ opt_array[0].canonical_option[0] = argv[0];
+ opt_array[0].canonical_option[1] = NULL;
+ opt_array[0].canonical_option[2] = NULL;
+ opt_array[0].canonical_option[3] = NULL;
+ opt_array[0].value = 1;
+ opt_array[0].mask = 0;
+ opt_array[0].errors = 0;
+ num_decoded_options = 1;
+
+ for (i = 1; i < argc; i += n)
+ {
+ const char *opt = argv[i];
+
+ /* Interpret "-" or a non-switch as a file name. */
+ if (opt[0] != '-' || opt[1] == '\0')
+ {
+ generate_option_input_file (opt, &opt_array[num_decoded_options]);
+ num_decoded_options++;
+ n = 1;
+ continue;
+ }
+
+ /* Interpret "--param" "key=name" as "--param=key=name". */
+ const char *needle = "--param";
+ if (i + 1 < argc && strcmp (opt, needle) == 0)
+ { untested();
+ const char *replacement
+ = opts_concat (needle, "=", argv[i + 1], NULL);
+ argv[++i] = replacement;
+ }
+
+ /* Expand -fdiagnostics-plain-output to its constituents. This needs
+ to happen here so that prune_options can handle -fdiagnostics-color
+ specially. */
+ if (!strcmp (opt, "-fdiagnostics-plain-output"))
+ { untested();
+ /* If you have changed the default diagnostics output, and this new
+ output is not appropriately "plain" (e.g., the change needs to be
+ undone in order for the testsuite to work properly), then please do
+ the following:
+ 1. Add the necessary option to undo the new behavior to
+ the array below.
+ 2. Update the documentation for -fdiagnostics-plain-output
+ in invoke.texi. */
+ const char *const expanded_args[] = {
+ "-fno-diagnostics-show-caret",
+ "-fno-diagnostics-show-line-numbers",
+ "-fdiagnostics-color=never",
+ "-fdiagnostics-urls=never",
+ "-fdiagnostics-path-format=separate-events",
+ };
+ const int num_expanded = ARRAY_SIZE (expanded_args);
+ opt_array_len += num_expanded - 1;
+ opt_array = XRESIZEVEC (struct cl_decoded_option,
+ opt_array, opt_array_len);
+ for (int j = 0, nj; j < num_expanded; j += nj)
+ { untested();
+ nj = decode_cmdline_option (expanded_args + j, lang_mask,
+ &opt_array[num_decoded_options]);
+ num_decoded_options++;
+ }
+
+ n = 1;
+ continue;
+ }
+
+ n = decode_cmdline_option (argv + i, lang_mask,
+ &opt_array[num_decoded_options]);
+ num_decoded_options++;
+ }
+
+ *decoded_options = opt_array;
+ *decoded_options_count = num_decoded_options;
+ prune_options (decoded_options, decoded_options_count);
+}
+
+/* Return true if NEXT_OPT_IDX cancels OPT_IDX. Return false if the
+ next one is the same as ORIG_NEXT_OPT_IDX. */
+
+static bool
+cancel_option (int opt_idx, int next_opt_idx, int orig_next_opt_idx)
+{
+ /* An option can be canceled by the same option or an option with
+ Negative. */
+ if (cl_options [next_opt_idx].neg_index == opt_idx)
+ return true;
+
+ if (cl_options [next_opt_idx].neg_index != orig_next_opt_idx)
+ return cancel_option (opt_idx, cl_options [next_opt_idx].neg_index,
+ orig_next_opt_idx);
+
+ return false;
+}
+
+/* Filter out options canceled by the ones after them. */
+
+static void
+prune_options (struct cl_decoded_option **decoded_options,
+ unsigned int *decoded_options_count)
+{
+ unsigned int old_decoded_options_count = *decoded_options_count;
+ struct cl_decoded_option *old_decoded_options = *decoded_options;
+ unsigned int new_decoded_options_count;
+ struct cl_decoded_option *new_decoded_options
+ = XNEWVEC (struct cl_decoded_option, old_decoded_options_count);
+ unsigned int i;
+ const struct cl_option *option;
+ unsigned int fdiagnostics_color_idx = 0;
+
+ /* Remove arguments which are negated by others after them. */
+ new_decoded_options_count = 0;
+ for (i = 0; i < old_decoded_options_count; i++)
+ {
+ unsigned int j, opt_idx, next_opt_idx;
+
+ if (old_decoded_options[i].errors & ~CL_ERR_WRONG_LANG)
+ goto keep;
+
+ opt_idx = old_decoded_options[i].opt_index;
+ switch (opt_idx)
+ {
+ case OPT_SPECIAL_unknown:
+ case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_warn_removed:
+ case OPT_SPECIAL_program_name:
+ case OPT_SPECIAL_input_file:
+ goto keep;
+
+ /* Do not save OPT_fdiagnostics_color_, just remember the last one. */
+ case OPT_fdiagnostics_color_:
+ fdiagnostics_color_idx = i;
+ continue;
+
+ default:
+ gcc_assert (opt_idx < cl_options_count);
+ option = &cl_options[opt_idx];
+ if (option->neg_index < 0)
+ goto keep;
+
+ /* Skip joined switches. */
+ if ((option->flags & CL_JOINED)
+ && (!option->cl_reject_negative
+ || (unsigned int) option->neg_index != opt_idx))
+ goto keep;
+
+ for (j = i + 1; j < old_decoded_options_count; j++)
+ {
+ if (old_decoded_options[j].errors & ~CL_ERR_WRONG_LANG)
+ continue;
+ next_opt_idx = old_decoded_options[j].opt_index;
+ if (next_opt_idx >= cl_options_count)
+ continue;
+ if (cl_options[next_opt_idx].neg_index < 0)
+ continue;
+ if ((cl_options[next_opt_idx].flags & CL_JOINED)
+ && (!cl_options[next_opt_idx].cl_reject_negative
+ || ((unsigned int) cl_options[next_opt_idx].neg_index
+ != next_opt_idx)))
+ continue;
+ if (cancel_option (opt_idx, next_opt_idx, next_opt_idx))
+ break;
+ }
+ if (j == old_decoded_options_count)
+ {
+keep:
+ new_decoded_options[new_decoded_options_count]
+ = old_decoded_options[i];
+ new_decoded_options_count++;
+ }
+ break;
+ }
+ }
+
+ if (fdiagnostics_color_idx >= 1)
+ { untested();
+ /* We put the last -fdiagnostics-color= at the first position
+ after argv[0] so it can take effect immediately. */
+ memmove (new_decoded_options + 2, new_decoded_options + 1,
+ sizeof (struct cl_decoded_option)
+ * (new_decoded_options_count - 1));
+ new_decoded_options[1] = old_decoded_options[fdiagnostics_color_idx];
+ new_decoded_options_count++;
+ }
+
+ free (old_decoded_options);
+ new_decoded_options = XRESIZEVEC (struct cl_decoded_option,
+ new_decoded_options,
+ new_decoded_options_count);
+ *decoded_options = new_decoded_options;
+ *decoded_options_count = new_decoded_options_count;
+}
+
+/* Handle option DECODED for the language indicated by LANG_MASK,
+ using the handlers in HANDLERS and setting fields in OPTS and
+ OPTS_SET. KIND is the diagnostic_t if this is a diagnostics
+ option, DK_UNSPECIFIED otherwise, and LOC is the location of the
+ option for options from the source file, UNKNOWN_LOCATION
+ otherwise. GENERATED_P is true for an option generated as part of
+ processing another option or otherwise generated internally, false
+ for one explicitly passed by the user. control_warning_option
+ generated options are considered explicitly passed by the user.
+ Returns false if the switch was invalid. DC is the diagnostic
+ context for options affecting diagnostics state, or NULL. */
+
+static bool
+handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask, int kind, location_t loc,
+ const struct cl_option_handlers *handlers,
+ bool generated_p, diagnostic_context *dc)
+{
+ size_t opt_index = decoded->opt_index;
+ const char *arg = decoded->arg;
+ HOST_WIDE_INT value = decoded->value;
+ HOST_WIDE_INT mask = decoded->mask;
+ const struct cl_option *option = &cl_options[opt_index];
+ void *flag_var = option_flag_var (opt_index, opts);
+ size_t i;
+
+ if (flag_var)
+ set_option (opts, (generated_p ? NULL : opts_set),
+ opt_index, value, arg, kind, loc, dc, mask);
+
+ for (i = 0; i < handlers->num_handlers; i++)
+ if (option->flags & handlers->handlers[i].mask)
+ {
+ if(!handlers->handlers[i].handler){
+ return false;
+ }else if (!handlers->handlers[i].handler (opts, opts_set, decoded,
+ lang_mask, kind, loc,
+ handlers, dc,
+ handlers->target_option_override_hook))
+ return false;
+ }
+
+ return true;
+}
+
+/* Like handle_option, but OPT_INDEX, ARG and VALUE describe the
+ option instead of DECODED. This is used for callbacks when one
+ option implies another instead of an option being decoded from the
+ command line. */
+
+bool
+handle_generated_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ size_t opt_index, const char *arg, HOST_WIDE_INT value,
+ unsigned int lang_mask, int kind, location_t loc,
+ const struct cl_option_handlers *handlers,
+ bool generated_p, diagnostic_context *dc)
+{
+ struct cl_decoded_option decoded;
+
+ generate_option (opt_index, arg, value, lang_mask, &decoded);
+ return handle_option (opts, opts_set, &decoded, lang_mask, kind, loc,
+ handlers, generated_p, dc);
+}
+
+/* Fill in *DECODED with an option described by OPT_INDEX, ARG and
+ VALUE for a front end using LANG_MASK. This is used when the
+ compiler generates options internally. */
+
+void
+generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
+ unsigned int lang_mask, struct cl_decoded_option *decoded)
+{
+ const struct cl_option *option = &cl_options[opt_index];
+
+ decoded->opt_index = opt_index;
+ decoded->warn_message = NULL;
+ decoded->arg = arg;
+ decoded->value = value;
+ decoded->mask = 0;
+ decoded->errors = (option_ok_for_language (option, lang_mask)
+ ? 0
+ : CL_ERR_WRONG_LANG);
+
+ generate_canonical_option (opt_index, arg, value, decoded);
+ switch (decoded->canonical_option_num_elements)
+ {
+ case 1:
+ decoded->orig_option_with_args_text = decoded->canonical_option[0];
+ break;
+
+ case 2:
+ decoded->orig_option_with_args_text
+ = opts_concat (decoded->canonical_option[0], " ",
+ decoded->canonical_option[1], NULL);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Fill in *DECODED with an option for input file FILE. */
+
+void
+generate_option_input_file (const char *file,
+ struct cl_decoded_option *decoded)
+{
+ decoded->opt_index = OPT_SPECIAL_input_file;
+ decoded->warn_message = NULL;
+ decoded->arg = file;
+ decoded->orig_option_with_args_text = file;
+ decoded->canonical_option_num_elements = 1;
+ decoded->canonical_option[0] = file;
+ decoded->canonical_option[1] = NULL;
+ decoded->canonical_option[2] = NULL;
+ decoded->canonical_option[3] = NULL;
+ decoded->value = 1;
+ decoded->mask = 0;
+ decoded->errors = 0;
+}
+
+/* Helper function for listing valid choices and hint for misspelled
+ value. CANDIDATES is a vector containing all valid strings,
+ STR is set to a heap allocated string that contains all those
+ strings concatenated, separated by spaces, and the return value
+ is the closest string from those to ARG, or NULL if nothing is
+ close enough. Callers should XDELETEVEC (STR) after using it
+ to avoid memory leaks. */
+
+const char *
+candidates_list_and_hint (const char *arg, char *&str,
+ const auto_vec <const char *> &candidates)
+{ untested();
+ size_t len = 0;
+ int i;
+ const char *candidate;
+ char *p;
+
+ FOR_EACH_VEC_ELT (candidates, i, candidate)
+ len += strlen (candidate) + 1;
+
+ str = p = XNEWVEC (char, len);
+ FOR_EACH_VEC_ELT (candidates, i, candidate)
+ { untested();
+ len = strlen (candidate);
+ memcpy (p, candidate, len);
+ p[len] = ' ';
+ p += len + 1;
+ }
+ p[-1] = '\0';
+ return find_closest_string (arg, &candidates);
+}
+
+/* Perform diagnostics for read_cmdline_option and control_warning_option
+ functions. Returns true if an error has been diagnosed.
+ LOC and LANG_MASK arguments like in read_cmdline_option.
+ OPTION is the option to report diagnostics for, OPT the name
+ of the option as text, ARG the argument of the option (for joined
+ options), ERRORS is bitmask of CL_ERR_* values. */
+
+static bool
+cmdline_handle_error (location_t loc, const struct cl_option *option,
+ const char *opt, const char *arg, int errors,
+ unsigned int lang_mask)
+{
+ if (errors & CL_ERR_DISABLED)
+ { untested();
+ error_at (loc, "command-line option %qs"
+ " is not supported by this configuration", opt);
+ return true;
+ }
+
+ if (errors & CL_ERR_MISSING_ARG)
+ { untested();
+ if (option->missing_argument_error)
+ error_at (loc, option->missing_argument_error, opt);
+ else
+ error_at (loc, "missing argument to %qs", opt);
+ return true;
+ }
+
+ if (errors & CL_ERR_UINT_ARG)
+ { untested();
+ if (option->cl_byte_size)
+ error_at (loc, "argument to %qs should be a non-negative integer "
+ "optionally followed by a size unit",
+ option->opt_text);
+ else
+ error_at (loc, "argument to %qs should be a non-negative integer",
+ option->opt_text);
+ return true;
+ }
+
+ if (errors & CL_ERR_INT_RANGE_ARG)
+ { untested();
+ error_at (loc, "argument to %qs is not between %d and %d",
+ option->opt_text, option->range_min, option->range_max);
+ return true;
+ }
+
+ if (errors & CL_ERR_ENUM_SET_ARG)
+ { untested();
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+ const char *p = arg;
+ unsigned HOST_WIDE_INT used_sets = 0;
+ const char *second_opt = NULL;
+ size_t second_opt_len = 0;
+ errors = 0;
+ do
+ { untested();
+ const char *q = strchr (p, ',');
+ HOST_WIDE_INT this_value = 0;
+ if (q && q == p)
+ { untested();
+ arg = "";
+ errors = CL_ERR_ENUM_ARG;
+ break;
+ }
+ int idx = enum_arg_to_value (e->values, p, q ? q - p : 0,
+ &this_value, lang_mask);
+ if (idx < 0)
+ { untested();
+ if (q == NULL)
+ q = strchr (p, '\0');
+ char *narg = XALLOCAVEC (char, (q - p) + 1);
+ memcpy (narg, p, q - p);
+ narg[q - p] = '\0';
+ arg = narg;
+ errors = CL_ERR_ENUM_ARG;
+ break;
+ }
+
+ if (option->var_value == CLEV_BITSET)
+ { untested();
+ if (q == NULL)
+ break;
+ p = q + 1;
+ continue;
+ }
+
+ unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT;
+ gcc_checking_assert (set >= 1 && set <= HOST_BITS_PER_WIDE_INT);
+ if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0)
+ { untested();
+ if (q == NULL)
+ q = strchr (p, '\0');
+ if (second_opt == NULL)
+ { untested();
+ used_sets = HOST_WIDE_INT_1U << (set - 1);
+ second_opt = p;
+ second_opt_len = q - p;
+ p = arg;
+ continue;
+ }
+ char *args = XALLOCAVEC (char, (q - p) + 1 + second_opt_len + 1);
+ memcpy (args, p, q - p);
+ args[q - p] = '\0';
+ memcpy (args + (q - p) + 1, second_opt, second_opt_len);
+ args[(q - p) + 1 + second_opt_len] = '\0';
+ error_at (loc, "invalid argument in option %qs", opt);
+ if (strcmp (args, args + (q - p) + 1) == 0)
+ inform (loc, "%qs specified multiple times in the same option",
+ args);
+ else
+ inform (loc, "%qs is mutually exclusive with %qs and cannot be"
+ " specified together", args, args + (q - p) + 1);
+ return true;
+ }
+ used_sets |= HOST_WIDE_INT_1U << (set - 1);
+ if (q == NULL)
+ break;
+ p = q + 1;
+ }
+ while (1);
+ }
+
+ if (errors & CL_ERR_ENUM_ARG)
+ { untested();
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+ unsigned int i;
+ char *s;
+
+ auto_diagnostic_group d;
+ if (e->unknown_error)
+ error_at (loc, e->unknown_error, arg);
+ else
+ error_at (loc, "unrecognized argument in option %qs", opt);
+
+ auto_vec <const char *> candidates;
+ for (i = 0; e->values[i].arg != NULL; i++)
+ { untested();
+ if (!enum_arg_ok_for_language (&e->values[i], lang_mask))
+ continue;
+ candidates.safe_push (e->values[i].arg);
+ }
+ const char *hint = candidates_list_and_hint (arg, s, candidates);
+ if (hint)
+ inform (loc, "valid arguments to %qs are: %s; did you mean %qs?",
+ option->opt_text, s, hint);
+ else
+ inform (loc, "valid arguments to %qs are: %s", option->opt_text, s);
+ XDELETEVEC (s);
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Handle the switch DECODED (location LOC) for the language indicated
+ by LANG_MASK, using the handlers in *HANDLERS and setting fields in
+ OPTS and OPTS_SET and using diagnostic context DC (if not NULL) for
+ diagnostic options. */
+
+void
+read_cmdline_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded,
+ location_t loc,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc)
+{
+ const struct cl_option *option;
+ const char *opt = decoded->orig_option_with_args_text;
+
+ if (decoded->warn_message)
+ warning_at (loc, 0, decoded->warn_message, opt);
+
+ if (decoded->opt_index == OPT_SPECIAL_unknown)
+ {
+ if (handlers->unknown_option_callback (decoded)){ untested();
+ error_at (loc, "unrecognized command-line option %qs", decoded->arg);
+ }else{
+ }
+ return;
+ }else{
+ }
+
+ if (decoded->opt_index == OPT_SPECIAL_ignore)
+ return;
+
+ if (decoded->opt_index == OPT_SPECIAL_warn_removed)
+ { untested();
+ /* Warn only about positive ignored options. */
+ if (decoded->value)
+ warning_at (loc, 0, "switch %qs is no longer supported", opt);
+ return;
+ }else{
+ }
+
+ option = &cl_options[decoded->opt_index];
+
+ if (decoded->errors
+ && cmdline_handle_error (loc, option, opt, decoded->arg,
+ decoded->errors, lang_mask))
+ return;
+
+ if (decoded->errors & CL_ERR_WRONG_LANG)
+ {
+ handlers->wrong_lang_callback (decoded, lang_mask);
+ return;
+ }
+
+ gcc_assert (!decoded->errors);
+
+ if (!handle_option (opts, opts_set, decoded, lang_mask, DK_UNSPECIFIED,
+ loc, handlers, false, dc))
+ error_at (loc, "unrecognized command-line option %qs", opt);
+}
+
+/* Set any field in OPTS, and OPTS_SET if not NULL, for option
+ OPT_INDEX according to VALUE and ARG, diagnostic kind KIND,
+ location LOC, using diagnostic context DC if not NULL for
+ diagnostic classification. */
+
+void
+set_option (struct gcc_options *opts, struct gcc_options *opts_set,
+ int opt_index, HOST_WIDE_INT value, const char *arg, int kind,
+ location_t loc, diagnostic_context *dc,
+ HOST_WIDE_INT mask /* = 0 */)
+{
+ const struct cl_option *option = &cl_options[opt_index];
+ void *flag_var = option_flag_var (opt_index, opts);
+ void *set_flag_var = NULL;
+
+ if (!flag_var)
+ return;
+
+ if ((diagnostic_t) kind != DK_UNSPECIFIED && dc != NULL)
+ diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc);
+
+ if (opts_set != NULL)
+ set_flag_var = option_flag_var (opt_index, opts_set);
+
+ switch (option->var_type)
+ {
+ case CLVC_INTEGER:
+ if (option->cl_host_wide_int)
+ { untested();
+ *(HOST_WIDE_INT *) flag_var = value;
+ if (set_flag_var)
+ *(HOST_WIDE_INT *) set_flag_var = 1;
+ }
+ else
+ {
+ if (value > INT_MAX)
+ error_at (loc, "argument to %qs is bigger than %d",
+ option->opt_text, INT_MAX);
+ else
+ {
+ *(int *) flag_var = value;
+ if (set_flag_var)
+ *(int *) set_flag_var = 1;
+ }
+ }
+
+ break;
+
+ case CLVC_SIZE:
+ if (option->cl_host_wide_int)
+ { untested();
+ *(HOST_WIDE_INT *) flag_var = value;
+ if (set_flag_var)
+ *(HOST_WIDE_INT *) set_flag_var = value;
+ }
+ else
+ { untested();
+ *(int *) flag_var = value;
+ if (set_flag_var)
+ *(int *) set_flag_var = value;
+ }
+
+ break;
+
+ case CLVC_EQUAL:
+ if (option->cl_host_wide_int)
+ { untested();
+ *(HOST_WIDE_INT *) flag_var = (value
+ ? option->var_value
+ : !option->var_value);
+ if (set_flag_var)
+ *(HOST_WIDE_INT *) set_flag_var = 1;
+ }
+ else
+ { untested();
+ *(int *) flag_var = (value
+ ? option->var_value
+ : !option->var_value);
+ if (set_flag_var)
+ *(int *) set_flag_var = 1;
+ }
+ break;
+
+ case CLVC_BIT_CLEAR:
+ case CLVC_BIT_SET:
+ if ((value != 0) == (option->var_type == CLVC_BIT_SET))
+ { untested();
+ if (option->cl_host_wide_int)
+ *(HOST_WIDE_INT *) flag_var |= option->var_value;
+ else
+ *(int *) flag_var |= option->var_value;
+ }
+ else
+ { untested();
+ if (option->cl_host_wide_int)
+ *(HOST_WIDE_INT *) flag_var &= ~option->var_value;
+ else
+ *(int *) flag_var &= ~option->var_value;
+ }
+ if (set_flag_var)
+ { untested();
+ if (option->cl_host_wide_int)
+ *(HOST_WIDE_INT *) set_flag_var |= option->var_value;
+ else
+ *(int *) set_flag_var |= option->var_value;
+ }
+ break;
+
+ case CLVC_STRING:
+ *(const char **) flag_var = arg;
+ if (set_flag_var)
+ *(const char **) set_flag_var = "";
+ break;
+
+ case CLVC_ENUM:
+ { untested();
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+
+ if (mask)
+ e->set (flag_var, value | (e->get (flag_var) & ~mask));
+ else
+ e->set (flag_var, value);
+ if (set_flag_var)
+ e->set (set_flag_var, 1);
+ }
+ break;
+
+ case CLVC_DEFER:
+ { untested();
+ vec<cl_deferred_option> *v
+ = (vec<cl_deferred_option> *) *(void **) flag_var;
+ cl_deferred_option p = {opt_index, arg, value};
+ if (!v)
+ v = XCNEW (vec<cl_deferred_option>);
+ v->safe_push (p);
+ *(void **) flag_var = v;
+ if (set_flag_var)
+ *(void **) set_flag_var = v;
+ }
+ break;
+ }
+}
+
+/* Return the address of the flag variable for option OPT_INDEX in
+ options structure OPTS, or NULL if there is no flag variable. */
+
+void *
+option_flag_var (int opt_index, struct gcc_options *opts)
+{
+ const struct cl_option *option = &cl_options[opt_index];
+
+ if (option->flag_var_offset == (unsigned short) -1)
+ return NULL;
+ return (void *)(((char *) opts) + option->flag_var_offset);
+}
+
+/* Return 1 if option OPT_IDX is enabled in OPTS, 0 if it is disabled,
+ or -1 if it isn't a simple on-off switch
+ (or if the value is unknown, typically set later in target). */
+
+int
+option_enabled (int opt_idx, unsigned lang_mask, void *opts)
+{
+ const struct cl_option *option = &(cl_options[opt_idx]);
+
+ /* A language-specific option can only be considered enabled when it's
+ valid for the current language. */
+ if (!(option->flags & CL_COMMON)
+ && (option->flags & CL_LANG_ALL)
+ && !(option->flags & lang_mask))
+ return 0;
+
+ struct gcc_options *optsg = (struct gcc_options *) opts;
+ void *flag_var = option_flag_var (opt_idx, optsg);
+
+ if (flag_var)
+ switch (option->var_type)
+ {
+ case CLVC_INTEGER:
+ if (option->cl_host_wide_int)
+ { untested();
+ HOST_WIDE_INT v = *(HOST_WIDE_INT *) flag_var;
+ return v != 0 ? (v < 0 ? -1 : 1) : 0;
+ }
+ else
+ {
+ int v = *(int *) flag_var;
+ return v != 0 ? (v < 0 ? -1 : 1) : 0;
+ }
+
+ case CLVC_EQUAL:
+ if (option->cl_host_wide_int)
+ return *(HOST_WIDE_INT *) flag_var == option->var_value;
+ else
+ return *(int *) flag_var == option->var_value;
+
+ case CLVC_BIT_CLEAR:
+ if (option->cl_host_wide_int)
+ return (*(HOST_WIDE_INT *) flag_var & option->var_value) == 0;
+ else
+ return (*(int *) flag_var & option->var_value) == 0;
+
+ case CLVC_BIT_SET:
+ if (option->cl_host_wide_int)
+ return (*(HOST_WIDE_INT *) flag_var & option->var_value) != 0;
+ else
+ return (*(int *) flag_var & option->var_value) != 0;
+
+ case CLVC_SIZE:
+ if (option->cl_host_wide_int)
+ return *(HOST_WIDE_INT *) flag_var != -1;
+ else
+ return *(int *) flag_var != -1;
+
+ case CLVC_STRING:
+ case CLVC_ENUM:
+ case CLVC_DEFER:
+ break;
+ }
+ return -1;
+}
+
+/* Fill STATE with the current state of option OPTION in OPTS. Return
+ true if there is some state to store. */
+
+bool
+get_option_state (struct gcc_options *opts, int option,
+ struct cl_option_state *state)
+{ untested();
+ void *flag_var = option_flag_var (option, opts);
+
+ if (flag_var == 0)
+ return false;
+
+ switch (cl_options[option].var_type)
+ {
+ case CLVC_INTEGER:
+ case CLVC_EQUAL:
+ case CLVC_SIZE:
+ state->data = flag_var;
+ state->size = (cl_options[option].cl_host_wide_int
+ ? sizeof (HOST_WIDE_INT)
+ : sizeof (int));
+ break;
+
+ case CLVC_BIT_CLEAR:
+ case CLVC_BIT_SET:
+ state->ch = option_enabled (option, -1, opts);
+ state->data = &state->ch;
+ state->size = 1;
+ break;
+
+ case CLVC_STRING:
+ state->data = *(const char **) flag_var;
+ if (state->data == 0)
+ state->data = "";
+ state->size = strlen ((const char *) state->data) + 1;
+ break;
+
+ case CLVC_ENUM:
+ state->data = flag_var;
+ state->size = cl_enums[cl_options[option].var_enum].var_size;
+ break;
+
+ case CLVC_DEFER:
+ return false;
+ }
+ return true;
+}
+
+/* Set a warning option OPT_INDEX (language mask LANG_MASK, option
+ handlers HANDLERS) to have diagnostic kind KIND for option
+ structures OPTS and OPTS_SET and diagnostic context DC (possibly
+ NULL), at location LOC (UNKNOWN_LOCATION for -Werror=). ARG is the
+ argument of the option for joined options, or NULL otherwise. If IMPLY,
+ the warning option in question is implied at this point. This is
+ used by -Werror= and #pragma GCC diagnostic. */
+
+void
+control_warning_option (unsigned int opt_index, int kind, const char *arg,
+ bool imply, location_t loc, unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ diagnostic_context *dc)
+{ untested();
+ if (cl_options[opt_index].alias_target != N_OPTS)
+ { untested();
+ gcc_assert (!cl_options[opt_index].cl_separate_alias
+ && !cl_options[opt_index].cl_negative_alias);
+ if (cl_options[opt_index].alias_arg)
+ arg = cl_options[opt_index].alias_arg;
+ opt_index = cl_options[opt_index].alias_target;
+ }
+ if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_warn_removed)
+ return;
+ if (dc)
+ diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc);
+ if (imply)
+ { untested();
+ const struct cl_option *option = &cl_options[opt_index];
+
+ /* -Werror=foo implies -Wfoo. */
+ if (option->var_type == CLVC_INTEGER
+ || option->var_type == CLVC_ENUM
+ || option->var_type == CLVC_SIZE)
+ { untested();
+ HOST_WIDE_INT value = 1;
+
+ if (arg && *arg == '\0' && !option->cl_missing_ok)
+ arg = NULL;
+
+ if ((option->flags & CL_JOINED) && arg == NULL)
+ { untested();
+ cmdline_handle_error (loc, option, option->opt_text, arg,
+ CL_ERR_MISSING_ARG, lang_mask);
+ return;
+ }
+
+ /* If the switch takes an integer argument, convert it. */
+ if (arg && (option->cl_uinteger || option->cl_host_wide_int))
+ { untested();
+ int error = 0;
+ value = *arg ? integral_argument (arg, &error,
+ option->cl_byte_size) : 0;
+ if (error)
+ { untested();
+ cmdline_handle_error (loc, option, option->opt_text, arg,
+ CL_ERR_UINT_ARG, lang_mask);
+ return;
+ }
+ }
+
+ /* If the switch takes an enumerated argument, convert it. */
+ if (arg && option->var_type == CLVC_ENUM)
+ { untested();
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+
+ if (enum_arg_to_value (e->values, arg, 0, &value,
+ lang_mask) >= 0)
+ { untested();
+ const char *carg = NULL;
+
+ if (enum_value_to_arg (e->values, &carg, value, lang_mask))
+ arg = carg;
+ gcc_assert (carg != NULL);
+ }
+ else
+ { untested();
+ cmdline_handle_error (loc, option, option->opt_text, arg,
+ CL_ERR_ENUM_ARG, lang_mask);
+ return;
+ }
+ }
+
+ handle_generated_option (opts, opts_set,
+ opt_index, arg, value, lang_mask,
+ kind, loc, handlers, false, dc);
+ }
+ }
+}
+
+/* Parse options in COLLECT_GCC_OPTIONS and push them on ARGV_OBSTACK.
+ Store number of arguments into ARGC_P. */
+
+void
+parse_options_from_collect_gcc_options (const char *collect_gcc_options,
+ obstack *argv_obstack,
+ int *argc_p)
+{ untested();
+ char *argv_storage = xstrdup (collect_gcc_options);
+ int j, k;
+
+ for (j = 0, k = 0; argv_storage[j] != '\0'; ++j)
+ { untested();
+ if (argv_storage[j] == '\'')
+ { untested();
+ obstack_ptr_grow (argv_obstack, &argv_storage[k]);
+ ++j;
+ do
+ { untested();
+ if (argv_storage[j] == '\0')
+ fatal_error (input_location,
+ "malformed %<COLLECT_GCC_OPTIONS%>");
+ else if (startswith (&argv_storage[j], "'\\''"))
+ { untested();
+ argv_storage[k++] = '\'';
+ j += 4;
+ }
+ else if (argv_storage[j] == '\'')
+ break;
+ else
+ argv_storage[k++] = argv_storage[j++];
+ }
+ while (1);
+ argv_storage[k++] = '\0';
+ }
+ }
+
+ obstack_ptr_grow (argv_obstack, NULL);
+ *argc_p = obstack_object_size (argv_obstack) / sizeof (void *) - 1;
+}
+
+/* Prepend -Xassembler for each option in COLLECT_AS_OPTIONS,
+ and push on O. */
+
+#if 0 //sdcpp
+void prepend_xassembler_to_collect_as_options (const char *collect_as_options,
+ obstack *o)
+{ untested();
+ obstack opts_obstack;
+ int opts_count;
+
+ obstack_init (&opts_obstack);
+ parse_options_from_collect_gcc_options (collect_as_options,
+ &opts_obstack, &opts_count);
+ const char **assembler_opts = XOBFINISH (&opts_obstack, const char **);
+
+ for (int i = 0; i < opts_count; i++)
+ { untested();
+ obstack_grow (o, " '-Xassembler' ",
+ strlen (" '-Xassembler' "));
+ const char *opt = assembler_opts[i];
+ obstack_1grow (o, '\'');
+ obstack_grow (o, opt, strlen (opt));
+ obstack_1grow (o, '\'');
+ }
+}
+#endif
diff --git a/support/cpp/gcc/opts-diagnostic.h b/support/cpp/gcc/opts-diagnostic.h
new file mode 100644
index 000000000..ced633a38
--- /dev/null
+++ b/support/cpp/gcc/opts-diagnostic.h
@@ -0,0 +1,28 @@
+/* Command line option handling. Interactions with diagnostics code.
+ Copyright (C) 2010-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_OPTS_DIAGNOSTIC_H
+#define GCC_OPTS_DIAGNOSTIC_H
+
+extern char *option_name (diagnostic_context *context, int option_index,
+ diagnostic_t orig_diag_kind, diagnostic_t diag_kind);
+
+extern char *get_option_url (diagnostic_context *context, int option_index);
+
+#endif
diff --git a/support/cpp/gcc/opts-global.cc b/support/cpp/gcc/opts-global.cc
new file mode 100644
index 000000000..20fbfcf8e
--- /dev/null
+++ b/support/cpp/gcc/opts-global.cc
@@ -0,0 +1,496 @@
+/* Command line option handling. Code involving global state that
+ should not be shared with the driver.
+ Copyright (C) 2002-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 <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ <<":" << __func__ << "\n" )
+#include <cassert>
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "rtl.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "diagnostic.h"
+#include "opts.h"
+#include "flags.h"
+#include "langhooks.h"
+#include "dbgcnt.h"
+#include "debug.h"
+#include "output.h"
+#include "plugin.h"
+#include "toplev.h"
+#include "context.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "asan.h"
+#include "file-prefix-map.h" /* add_*_prefix_map() */
+
+typedef const char *const_char_p; /* For DEF_VEC_P. */
+
+static vec<const_char_p> ignored_options;
+
+/* Input file names. */
+const char **in_fnames;
+unsigned num_in_fnames;
+
+/* Return a malloced slash-separated list of languages in MASK. */
+
+char *
+write_langs (unsigned int mask)
+{
+ unsigned int n = 0, len = 0;
+ const char *lang_name;
+ char *result;
+
+ for (n = 0; (lang_name = lang_names[n]) != 0; n++)
+ if (mask & (1U << n))
+ len += strlen (lang_name) + 1;
+
+ result = XNEWVEC (char, len);
+ len = 0;
+ for (n = 0; (lang_name = lang_names[n]) != 0; n++)
+ if (mask & (1U << n))
+ {
+ if (len)
+ result[len++] = '/';
+ strcpy (result + len, lang_name);
+ len += strlen (lang_name);
+ }
+
+ result[len] = 0;
+
+ return result;
+}
+
+/* Complain that switch DECODED does not apply to this front end (mask
+ LANG_MASK). */
+
+static void
+complain_wrong_lang (const struct cl_decoded_option *decoded,
+ unsigned int lang_mask)
+{
+ const struct cl_option *option = &cl_options[decoded->opt_index];
+ const char *text = decoded->orig_option_with_args_text;
+ char *ok_langs = NULL, *bad_lang = NULL;
+ unsigned int opt_flags = option->flags;
+
+ if (!lang_hooks.complain_wrong_lang_p (option))
+ return;
+
+ opt_flags &= ((1U << cl_lang_count) - 1) | CL_DRIVER;
+ if (opt_flags != CL_DRIVER)
+ ok_langs = write_langs (opt_flags);
+ if (lang_mask != CL_DRIVER)
+ bad_lang = write_langs (lang_mask);
+
+ if (opt_flags == CL_DRIVER)
+ error ("command-line option %qs is valid for the driver but not for %s",
+ text, bad_lang);
+ else if (lang_mask == CL_DRIVER)
+ gcc_unreachable ();
+ else if (ok_langs[0] != '\0')
+ /* Eventually this should become a hard error IMO. */
+ warning (0, "command-line option %qs is valid for %s but not for %s",
+ text, ok_langs, bad_lang);
+ else
+ /* Happens for -Werror=warning_name. */
+ warning (0, "%<-Werror=%> argument %qs is not valid for %s",
+ text, bad_lang);
+
+ free (ok_langs);
+ free (bad_lang);
+}
+
+/* Buffer the unknown option described by the string OPT. Currently,
+ we only complain about unknown -Wno-* options if they may have
+ prevented a diagnostic. Otherwise, we just ignore them. Note that
+ if we do complain, it is only as a warning, not an error; passing
+ the compiler an unrecognized -Wno-* option should never change
+ whether the compilation succeeds or fails. */
+
+static void
+postpone_unknown_option_warning (const char *opt)
+{
+ ignored_options.safe_push (opt);
+}
+
+/* Produce a warning for each option previously buffered. */
+
+void
+print_ignored_options (void)
+{
+ while (!ignored_options.is_empty ())
+ {
+ const char *opt;
+
+ opt = ignored_options.pop ();
+ /* Use inform, not warning_at, to avoid promoting these to errors. */
+ inform (UNKNOWN_LOCATION,
+ "unrecognized command-line option %qs may have been intended "
+ "to silence earlier diagnostics", opt);
+ }
+}
+
+/* Handle an unknown option DECODED, returning true if an error should
+ be given. */
+
+static bool
+unknown_option_callback (const struct cl_decoded_option *decoded)
+{
+ const char *opt = decoded->arg;
+
+ if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
+ && !(decoded->errors & CL_ERR_NEGATIVE))
+ {
+ /* We don't generate warnings for unknown -Wno-* options unless
+ we issue diagnostics. */
+ postpone_unknown_option_warning (opt);
+ return false;
+ }
+ else
+ return true;
+}
+
+/* Handle a front-end option; arguments and return value as for
+ handle_option. */
+
+static bool
+lang_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
+ location_t loc,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc,
+ void (*) (void))
+{
+ gcc_assert (opts == &global_options);
+ gcc_assert (opts_set == &global_options_set);
+ gcc_assert (dc == global_dc);
+ gcc_assert (decoded->canonical_option_num_elements <= 2);
+ return lang_hooks.handle_option (decoded->opt_index, decoded->arg,
+ decoded->value, kind, loc, handlers);
+}
+
+/* Handle FILENAME from the command line. */
+
+static void
+add_input_filename (const char *filename)
+{
+ num_in_fnames++;
+ in_fnames = XRESIZEVEC (const char *, in_fnames, num_in_fnames);
+ in_fnames[num_in_fnames - 1] = filename;
+}
+
+/* Handle the vector of command line options (located at LOC), storing
+ the results of processing DECODED_OPTIONS and DECODED_OPTIONS_COUNT
+ in OPTS and OPTS_SET and using DC for diagnostic state. LANG_MASK
+ contains has a single bit set representing the current language.
+ HANDLERS describes what functions to call for the options. */
+
+static void
+read_cmdline_options (struct gcc_options *opts, struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded_options,
+ unsigned int decoded_options_count,
+ location_t loc,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc)
+{
+ unsigned int i;
+
+ for (i = 1; i < decoded_options_count; i++)
+ {
+ if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
+ {
+ /* Input files should only ever appear on the main command
+ line. */
+ gcc_assert (opts == &global_options);
+ gcc_assert (opts_set == &global_options_set);
+
+ if (opts->x_main_input_filename == NULL)
+ {
+ opts->x_main_input_filename = decoded_options[i].arg;
+ opts->x_main_input_baselength
+ = base_of_path (opts->x_main_input_filename,
+ &opts->x_main_input_basename);
+ }
+ add_input_filename (decoded_options[i].arg);
+ continue;
+ }
+
+ read_cmdline_option (opts, opts_set,
+ decoded_options + i, loc, lang_mask, handlers,
+ dc);
+ }
+}
+
+/* Language mask determined at initialization. */
+static unsigned int initial_lang_mask;
+
+/* Initialize global options-related settings at start-up. */
+
+void
+init_options_once (void)
+{
+ /* Perform language-specific options initialization. */
+ initial_lang_mask = lang_hooks.option_lang_mask ();
+
+ lang_hooks.initialize_diagnostics (global_dc);
+ /* ??? Ideally, we should do this earlier and the FEs will override
+ it if desired (none do it so far). However, the way the FEs
+ construct their pretty-printers means that all previous settings
+ are overriden. */
+ diagnostic_color_init (global_dc);
+ diagnostic_urls_init (global_dc);
+}
+
+/* Decode command-line options to an array, like
+ decode_cmdline_options_to_array and with the same arguments but
+ using the default lang_mask. */
+
+void
+decode_cmdline_options_to_array_default_mask (unsigned int argc,
+ const char **argv,
+ struct cl_decoded_option **decoded_options,
+ unsigned int *decoded_options_count)
+{
+ decode_cmdline_options_to_array (argc, argv,
+ initial_lang_mask | CL_COMMON | CL_TARGET,
+ decoded_options, decoded_options_count);
+}
+
+/* Set *HANDLERS to the default set of option handlers for use in the
+ compilers proper (not the driver). */
+void
+set_default_handlers (struct cl_option_handlers *handlers,
+ void (*target_option_override_hook) (void))
+{
+ handlers->unknown_option_callback = unknown_option_callback;
+ handlers->wrong_lang_callback = complain_wrong_lang;
+ assert(target_option_override_hook);
+ handlers->target_option_override_hook = target_option_override_hook;
+ handlers->num_handlers = 3;
+ handlers->handlers[0].handler = lang_handle_option;
+ handlers->handlers[0].mask = initial_lang_mask;
+ handlers->handlers[1].handler = common_handle_option;
+ handlers->handlers[1].mask = CL_COMMON;
+ handlers->handlers[2].handler = NULL; // sdcpp target_handle_option;
+ handlers->handlers[2].mask = CL_TARGET;
+}
+
+/* Parse command line options and set default flag values. Do minimal
+ options processing. The decoded options are in *DECODED_OPTIONS
+ and *DECODED_OPTIONS_COUNT; settings go in OPTS, OPTS_SET and DC;
+ the options are located at LOC. */
+void
+decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded_options,
+ unsigned int decoded_options_count,
+ location_t loc, diagnostic_context *dc,
+ void (*target_option_override_hook) (void))
+{
+ struct cl_option_handlers handlers;
+
+ unsigned int lang_mask;
+
+ lang_mask = initial_lang_mask;
+
+ assert(target_option_override_hook);
+ set_default_handlers (&handlers, target_option_override_hook);
+
+ default_options_optimization (opts, opts_set,
+ decoded_options, decoded_options_count,
+ loc, lang_mask, &handlers, dc);
+
+ read_cmdline_options (opts, opts_set,
+ decoded_options, decoded_options_count,
+ loc, lang_mask,
+ &handlers, dc);
+
+ finish_options (opts, opts_set, loc);
+
+ /* Print --help=* if used. */
+ unsigned i;
+ const char *arg;
+
+ if (!help_option_arguments.is_empty ())
+ {
+ /* Make sure --help=* sees the overridden values. */
+ target_option_override_hook ();
+
+ FOR_EACH_VEC_ELT (help_option_arguments, i, arg)
+ print_help (opts, lang_mask, arg);
+ }
+}
+
+/* Hold command-line options associated with stack limitation. */
+const char *opt_fstack_limit_symbol_arg = NULL;
+int opt_fstack_limit_register_no = -1;
+
+/* Process common options that have been deferred until after the
+ handlers have been called for all options. */
+
+void
+handle_common_deferred_options (void)
+{
+ // TODO
+ // gcc_assert(0 && "handle_common_deferred_options");
+#if 0 // sdcpp
+ unsigned int i;
+ cl_deferred_option *opt;
+ vec<cl_deferred_option> v;
+
+ if (common_deferred_options)
+ v = *((vec<cl_deferred_option> *) common_deferred_options);
+ else
+ v = vNULL;
+
+ if (flag_dump_all_passed)
+ enable_rtl_dump_file ();
+
+ if (flag_opt_info)
+ opt_info_switch_p (NULL);
+
+ FOR_EACH_VEC_ELT (v, i, opt)
+ {
+ switch (opt->opt_index)
+ {
+ case OPT_fcall_used_:
+ fix_register (opt->arg, 0, 1);
+ break;
+
+ case OPT_fcall_saved_:
+ fix_register (opt->arg, 0, 0);
+ break;
+
+ case OPT_fdbg_cnt_:
+ dbg_cnt_process_opt (opt->arg);
+ break;
+
+ case OPT_fdebug_prefix_map_:
+ add_debug_prefix_map (opt->arg);
+ break;
+
+ case OPT_ffile_prefix_map_:
+ add_file_prefix_map (opt->arg);
+ break;
+
+ case OPT_fprofile_prefix_map_:
+ add_profile_prefix_map (opt->arg);
+ break;
+
+ case OPT_fdump_:
+ g->get_dumps ()->dump_switch_p (opt->arg);
+ break;
+
+ case OPT_fopt_info_:
+ if (!opt_info_switch_p (opt->arg))
+ error ("unrecognized command-line option %<-fopt-info-%s%>",
+ opt->arg);
+ break;
+
+ case OPT_fenable_:
+ case OPT_fdisable_:
+ if (opt->opt_index == OPT_fenable_)
+ enable_pass (opt->arg);
+ else
+ disable_pass (opt->arg);
+ break;
+
+ case OPT_ffixed_:
+ /* Deferred. */
+ fix_register (opt->arg, 1, 1);
+ break;
+
+ case OPT_fplugin_:
+#ifdef ENABLE_PLUGIN
+ add_new_plugin (opt->arg);
+#else
+ error ("plugin support is disabled; configure with "
+ "%<--enable-plugin%>");
+#endif
+ break;
+
+ case OPT_fplugin_arg_:
+#ifdef ENABLE_PLUGIN
+ parse_plugin_arg_opt (opt->arg);
+#else
+ error ("plugin support is disabled; configure with "
+ "%<--enable-plugin%>");
+#endif
+ break;
+
+ case OPT_frandom_seed:
+ /* The real switch is -fno-random-seed. */
+ if (!opt->value)
+ set_random_seed (NULL);
+ break;
+
+ case OPT_frandom_seed_:
+ set_random_seed (opt->arg);
+ break;
+
+ case OPT_fstack_limit:
+ /* The real switch is -fno-stack-limit. */
+ if (!opt->value)
+ stack_limit_rtx = NULL_RTX;
+ break;
+
+ case OPT_fstack_limit_register_:
+ {
+ int reg = decode_reg_name (opt->arg);
+ if (reg < 0)
+ error ("unrecognized register name %qs", opt->arg);
+ else
+ {
+ /* Deactivate previous OPT_fstack_limit_symbol_ options. */
+ opt_fstack_limit_symbol_arg = NULL;
+ opt_fstack_limit_register_no = reg;
+ }
+ }
+ break;
+
+ case OPT_fstack_limit_symbol_:
+ /* Deactivate previous OPT_fstack_limit_register_ options. */
+ opt_fstack_limit_register_no = -1;
+ opt_fstack_limit_symbol_arg = opt->arg;
+ break;
+
+ case OPT_fasan_shadow_offset_:
+ if (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS))
+ error ("%<-fasan-shadow-offset%> should only be used "
+ "with %<-fsanitize=kernel-address%>");
+ if (!set_asan_shadow_offset (opt->arg))
+ error ("unrecognized shadow offset %qs", opt->arg);
+ break;
+
+ case OPT_fsanitize_sections_:
+ set_sanitized_sections (opt->arg);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+#endif
+}
diff --git a/support/cpp/gcc/opts-sdcc.h b/support/cpp/gcc/opts-sdcc.h
new file mode 100644
index 000000000..72114374a
--- /dev/null
+++ b/support/cpp/gcc/opts-sdcc.h
@@ -0,0 +1,110 @@
+/* Command line option handling.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
+ 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_OPTS_H
+#define GCC_OPTS_H
+
+/* Specifies how a switch's VAR_VALUE relates to its FLAG_VAR. */
+enum cl_var_type {
+ /* The switch is enabled when FLAG_VAR is nonzero. */
+ CLVC_BOOLEAN,
+
+ /* The switch is enabled when FLAG_VAR == VAR_VALUE. */
+ CLVC_EQUAL,
+
+ /* The switch is enabled when VAR_VALUE is not set in FLAG_VAR. */
+ CLVC_BIT_CLEAR,
+
+ /* The switch is enabled when VAR_VALUE is set in FLAG_VAR. */
+ CLVC_BIT_SET,
+
+ /* The switch takes a string argument and FLAG_VAR points to that
+ argument. */
+ CLVC_STRING
+};
+
+struct cl_option
+{
+ const char *opt_text;
+ const char *help;
+ unsigned short back_chain;
+ unsigned char opt_len;
+ int neg_index;
+ unsigned int flags;
+ void *flag_var;
+ enum cl_var_type var_type;
+ int var_value;
+};
+
+/* Records that the state of an option consists of SIZE bytes starting
+ at DATA. DATA might point to CH in some cases. */
+struct cl_option_state {
+ const void *data;
+ size_t size;
+ char ch;
+};
+
+extern const struct cl_option cl_options[];
+extern const unsigned int cl_options_count;
+extern const char *const lang_names[];
+extern const unsigned int cl_lang_count;
+
+#define CL_PARAMS (1 << 17) /* Fake entry. Used to display --param info with --help. */
+#define CL_WARNING (1 << 18) /* Enables an (optional) warning message. */
+#define CL_OPTIMIZATION (1 << 19) /* Enables an (optional) optimization. */
+#define CL_TARGET (1 << 20) /* Target-specific option. */
+#define CL_COMMON (1 << 21) /* Language-independent. */
+
+#define CL_MIN_OPTION_CLASS CL_PARAMS
+#define CL_MAX_OPTION_CLASS CL_COMMON
+
+/* From here on the bits describe attributes of the options.
+ Before this point the bits have described the class of the option.
+ This distinction is important because --help will not list options
+ which only have these higher bits set. */
+
+#define CL_SAVE (1 << 22) /* Target-specific option for attribute. */
+#define CL_DISABLED (1 << 23) /* Disabled in this configuration. */
+#define CL_REPORT (1 << 24) /* Report argument with -fverbose-asm */
+#define CL_JOINED (1 << 25) /* If takes joined argument. */
+#define CL_SEPARATE (1 << 26) /* If takes a separate argument. */
+#define CL_REJECT_NEGATIVE (1 << 27) /* Reject no- form. */
+#define CL_MISSING_OK (1 << 28) /* Missing argument OK (joined). */
+#define CL_UINTEGER (1 << 29) /* Argument is an integer >=0. */
+#define CL_UNDOCUMENTED (1 << 30) /* Do not output with --help. */
+
+/* Input file names. */
+
+extern const char **in_fnames;
+
+/* The count of input filenames. */
+
+extern unsigned num_in_fnames;
+
+size_t find_opt (const char *input, int lang_mask);
+extern void prune_options (int *argcp, char ***argvp);
+extern void decode_options (unsigned int argc, const char **argv);
+extern int option_enabled (int opt_idx);
+extern bool get_option_state (int, struct cl_option_state *);
+
+extern void enable_warning_as_error (const char *arg, int value,
+ unsigned int lang_mask);
+extern void print_ignored_options (void);
+#endif
diff --git a/support/cpp/gcc/opts.cc b/support/cpp/gcc/opts.cc
new file mode 100644
index 000000000..9b04ab48a
--- /dev/null
+++ b/support/cpp/gcc/opts.cc
@@ -0,0 +1,3798 @@
+/* Command line option handling.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Contributed by Neil Booth.
+
+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 <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ <<":" << __func__ << "\n" )
+
+#include "config.h"
+#include "system.h"
+#include "intl.h"
+#include "coretypes.h"
+#include "opts.h"
+#include "tm.h"
+#include "flags.h"
+#include "diagnostic.h"
+#include "opts-diagnostic.h"
+#include "insn-attr-common.h"
+#include "common/common-target.h"
+#include "spellcheck.h"
+#include "opt-suggestions.h"
+#include "diagnostic-color.h"
+#include "version.h"
+#include "selftest.h"
+
+// sdcc hack?
+// #include "defaults.h"
+
+static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
+
+/* Names of fundamental debug info formats indexed by enum
+ debug_info_type. */
+
+const char *const debug_type_names[] =
+{
+ "none", "stabs", "dwarf-2", "xcoff", "vms", "ctf", "btf"
+};
+
+/* Bitmasks of fundamental debug info formats indexed by enum
+ debug_info_type. */
+
+static uint32_t debug_type_masks[] =
+{
+ NO_DEBUG, DBX_DEBUG, DWARF2_DEBUG, XCOFF_DEBUG, VMS_DEBUG,
+ CTF_DEBUG, BTF_DEBUG
+};
+
+/* Names of the set of debug formats requested by user. Updated and accessed
+ via debug_set_names. */
+
+static char df_set_names[sizeof "none stabs dwarf-2 xcoff vms ctf btf"];
+
+/* Get enum debug_info_type of the specified debug format, for error messages.
+ Can be used only for individual debug format types. */
+
+enum debug_info_type
+debug_set_to_format (uint32_t debug_info_set)
+{
+ int idx = 0;
+ enum debug_info_type dinfo_type = DINFO_TYPE_NONE;
+ /* Find first set bit. */
+ if (debug_info_set)
+ idx = exact_log2 (debug_info_set & - debug_info_set);
+ /* Check that only one bit is set, if at all. This function is meant to be
+ used only for vanilla debug_info_set bitmask values, i.e. for individual
+ debug format types upto DINFO_TYPE_MAX. */
+ gcc_assert ((debug_info_set & (debug_info_set - 1)) == 0);
+ dinfo_type = (enum debug_info_type)idx;
+ gcc_assert (dinfo_type <= DINFO_TYPE_MAX);
+ return dinfo_type;
+}
+
+/* Get the number of debug formats enabled for output. */
+
+unsigned int
+debug_set_count (uint32_t w_symbols)
+{
+ unsigned int count = 0;
+ while (w_symbols)
+ {
+ ++ count;
+ w_symbols &= ~ (w_symbols & - w_symbols);
+ }
+ return count;
+}
+
+/* Get the names of the debug formats enabled for output. */
+
+const char *
+debug_set_names (uint32_t w_symbols)
+{
+ uint32_t df_mask = 0;
+ /* Reset the string to be returned. */
+ memset (df_set_names, 0, sizeof (df_set_names));
+ /* Get the popcount. */
+ int num_set_df = debug_set_count (w_symbols);
+ /* Iterate over the debug formats. Add name string for those enabled. */
+ for (int i = DINFO_TYPE_NONE; i <= DINFO_TYPE_MAX; i++)
+ {
+ df_mask = debug_type_masks[i];
+ if (w_symbols & df_mask)
+ {
+ strcat (df_set_names, debug_type_names[i]);
+ num_set_df--;
+ if (num_set_df)
+ strcat (df_set_names, " ");
+ else
+ break;
+ }
+ else if (!w_symbols)
+ {
+ /* No debug formats enabled. */
+ gcc_assert (i == DINFO_TYPE_NONE);
+ strcat (df_set_names, debug_type_names[i]);
+ break;
+ }
+ }
+ return df_set_names;
+}
+
+/* Return TRUE iff BTF debug info is enabled. */
+
+bool
+btf_debuginfo_p ()
+{
+ return (write_symbols & BTF_DEBUG);
+}
+
+/* Return TRUE iff BTF with CO-RE debug info is enabled. */
+
+bool
+btf_with_core_debuginfo_p ()
+{
+ return (write_symbols & BTF_WITH_CORE_DEBUG);
+}
+
+/* Return TRUE iff CTF debug info is enabled. */
+
+bool
+ctf_debuginfo_p ()
+{
+ return (write_symbols & CTF_DEBUG);
+}
+
+/* Return TRUE iff dwarf2 debug info is enabled. */
+
+bool
+dwarf_debuginfo_p ()
+{
+ return (write_symbols & DWARF2_DEBUG);
+}
+
+/* Return true iff the debug info format is to be generated based on DWARF
+ DIEs (like CTF and BTF debug info formats). */
+
+bool dwarf_based_debuginfo_p ()
+{
+ return ((write_symbols & CTF_DEBUG)
+ || (write_symbols & BTF_DEBUG));
+}
+
+/* Parse the -femit-struct-debug-detailed option value
+ and set the flag variables. */
+
+#define MATCH( prefix, string ) \
+ ((strncmp (prefix, string, sizeof prefix - 1) == 0) \
+ ? ((string += sizeof prefix - 1), 1) : 0)
+
+void
+set_struct_debug_option (struct gcc_options *opts, location_t loc,
+ const char *spec)
+{
+ /* various labels for comparison */
+ static const char dfn_lbl[] = "dfn:", dir_lbl[] = "dir:", ind_lbl[] = "ind:";
+ static const char ord_lbl[] = "ord:", gen_lbl[] = "gen:";
+ static const char none_lbl[] = "none", any_lbl[] = "any";
+ static const char base_lbl[] = "base", sys_lbl[] = "sys";
+
+ enum debug_struct_file files = DINFO_STRUCT_FILE_ANY;
+ /* Default is to apply to as much as possible. */
+ enum debug_info_usage usage = DINFO_USAGE_NUM_ENUMS;
+ int ord = 1, gen = 1;
+
+ /* What usage? */
+ if (MATCH (dfn_lbl, spec))
+ usage = DINFO_USAGE_DFN;
+ else if (MATCH (dir_lbl, spec))
+ usage = DINFO_USAGE_DIR_USE;
+ else if (MATCH (ind_lbl, spec))
+ usage = DINFO_USAGE_IND_USE;
+
+ /* Generics or not? */
+ if (MATCH (ord_lbl, spec))
+ gen = 0;
+ else if (MATCH (gen_lbl, spec))
+ ord = 0;
+
+ /* What allowable environment? */
+ if (MATCH (none_lbl, spec))
+ files = DINFO_STRUCT_FILE_NONE;
+ else if (MATCH (any_lbl, spec))
+ files = DINFO_STRUCT_FILE_ANY;
+ else if (MATCH (sys_lbl, spec))
+ files = DINFO_STRUCT_FILE_SYS;
+ else if (MATCH (base_lbl, spec))
+ files = DINFO_STRUCT_FILE_BASE;
+ else
+ error_at (loc,
+ "argument %qs to %<-femit-struct-debug-detailed%> "
+ "not recognized",
+ spec);
+
+ /* Effect the specification. */
+ if (usage == DINFO_USAGE_NUM_ENUMS)
+ {
+ if (ord)
+ {
+ opts->x_debug_struct_ordinary[DINFO_USAGE_DFN] = files;
+ opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE] = files;
+ opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE] = files;
+ }
+ if (gen)
+ {
+ opts->x_debug_struct_generic[DINFO_USAGE_DFN] = files;
+ opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE] = files;
+ opts->x_debug_struct_generic[DINFO_USAGE_IND_USE] = files;
+ }
+ }
+ else
+ {
+ if (ord)
+ opts->x_debug_struct_ordinary[usage] = files;
+ if (gen)
+ opts->x_debug_struct_generic[usage] = files;
+ }
+
+ if (*spec == ',')
+ set_struct_debug_option (opts, loc, spec+1);
+ else
+ {
+ /* No more -femit-struct-debug-detailed specifications.
+ Do final checks. */
+ if (*spec != '\0')
+ error_at (loc,
+ "argument %qs to %<-femit-struct-debug-detailed%> unknown",
+ spec);
+ if (opts->x_debug_struct_ordinary[DINFO_USAGE_DIR_USE]
+ < opts->x_debug_struct_ordinary[DINFO_USAGE_IND_USE]
+ || opts->x_debug_struct_generic[DINFO_USAGE_DIR_USE]
+ < opts->x_debug_struct_generic[DINFO_USAGE_IND_USE])
+ error_at (loc,
+ "%<-femit-struct-debug-detailed=dir:...%> must allow "
+ "at least as much as "
+ "%<-femit-struct-debug-detailed=ind:...%>");
+ }
+}
+
+/* Strip off a legitimate source ending from the input string NAME of
+ length LEN. Rather than having to know the names used by all of
+ our front ends, we strip off an ending of a period followed by
+ up to fource characters. (C++ uses ".cpp".) */
+
+void
+strip_off_ending (char *name, int len)
+{
+ int i;
+ for (i = 2; i < 5 && len > i; i++)
+ {
+ if (name[len - i] == '.')
+ {
+ name[len - i] = '\0';
+ break;
+ }
+ }
+}
+
+/* Find the base name of a path, stripping off both directories and
+ a single final extension. */
+int
+base_of_path (const char *path, const char **base_out)
+{
+ const char *base = path;
+ const char *dot = 0;
+ const char *p = path;
+ char c = *p;
+ while (c)
+ {
+ if (IS_DIR_SEPARATOR (c))
+ {
+ base = p + 1;
+ dot = 0;
+ }
+ else if (c == '.')
+ dot = p;
+ c = *++p;
+ }
+ if (!dot)
+ dot = p;
+ *base_out = base;
+ return dot - base;
+}
+
+/* What to print when a switch has no documentation. */
+static const char undocumented_msg[] = N_("This option lacks documentation.");
+static const char use_diagnosed_msg[] = N_("Uses of this option are diagnosed.");
+
+typedef char *char_p; /* For DEF_VEC_P. */
+
+static void set_debug_level (uint32_t dinfo, int extended,
+ const char *arg, struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ location_t loc);
+static void set_fast_math_flags (struct gcc_options *opts, int set);
+static void decode_d_option (const char *arg, struct gcc_options *opts,
+ location_t loc, diagnostic_context *dc);
+static void set_unsafe_math_optimizations_flags (struct gcc_options *opts,
+ int set);
+static void enable_warning_as_error (const char *arg, int value,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ location_t loc,
+ diagnostic_context *dc);
+
+/* Handle a back-end option; arguments and return value as for
+ handle_option. */
+
+#if 0 // sdcpp
+bool
+target_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
+ location_t loc,
+ const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED,
+ diagnostic_context *dc, void (*) (void))
+{
+ gcc_assert (dc == global_dc);
+ gcc_assert (kind == DK_UNSPECIFIED);
+ return targetm_common.handle_option (opts, opts_set, decoded, loc);
+}
+#endif // sdcpp
+
+/* Add comma-separated strings to a char_p vector. */
+
+static void
+add_comma_separated_to_vector (void **pvec, const char *arg)
+{
+ char *tmp;
+ char *r;
+ char *w;
+ char *token_start;
+ vec<char_p> *v = (vec<char_p> *) *pvec;
+
+ vec_check_alloc (v, 1);
+
+ /* We never free this string. */
+ tmp = xstrdup (arg);
+
+ r = tmp;
+ w = tmp;
+ token_start = tmp;
+
+ while (*r != '\0')
+ {
+ if (*r == ',')
+ {
+ *w++ = '\0';
+ ++r;
+ v->safe_push (token_start);
+ token_start = w;
+ }
+ if (*r == '\\' && r[1] == ',')
+ {
+ *w++ = ',';
+ r += 2;
+ }
+ else
+ *w++ = *r++;
+ }
+
+ *w = '\0';
+ if (*token_start != '\0')
+ v->safe_push (token_start);
+
+ *pvec = v;
+}
+
+/* Initialize opts_obstack. */
+
+void
+init_opts_obstack (void)
+{
+ gcc_obstack_init (&opts_obstack);
+}
+
+/* Initialize OPTS and OPTS_SET before using them in parsing options. */
+
+void
+init_options_struct (struct gcc_options *opts, struct gcc_options *opts_set)
+{
+ /* Ensure that opts_obstack has already been initialized by the time
+ that we initialize any gcc_options instances (PR jit/68446). */
+ gcc_assert (opts_obstack.chunk_size > 0);
+
+ *opts = global_options_init;
+
+ if (opts_set)
+ memset (opts_set, 0, sizeof (*opts_set));
+
+ /* Initialize whether `char' is signed. */
+ opts->x_flag_signed_char = DEFAULT_SIGNED_CHAR;
+ /* Set this to a special "uninitialized" value. The actual default
+ is set after target options have been processed. */
+ opts->x_flag_short_enums = 2;
+
+#if 0 // sdcpp
+ /* Initialize target_flags before default_options_optimization
+ so the latter can modify it. */
+ opts->x_target_flags = targetm_common.default_target_flags;
+
+ /* Some targets have ABI-specified unwind tables. */
+ opts->x_flag_unwind_tables = targetm_common.unwind_tables_default;
+
+ /* Some targets have other target-specific initialization. */
+ targetm_common.option_init_struct (opts);
+#endif // sdcpp
+}
+
+/* If indicated by the optimization level LEVEL (-Os if SIZE is set,
+ -Ofast if FAST is set, -Og if DEBUG is set), apply the option DEFAULT_OPT
+ to OPTS and OPTS_SET, diagnostic context DC, location LOC, with language
+ mask LANG_MASK and option handlers HANDLERS. */
+
+#if 0 // sdcpp
+static void
+maybe_default_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct default_options *default_opt,
+ int level, bool size, bool fast, bool debug,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ location_t loc,
+ diagnostic_context *dc)
+{
+ const struct cl_option *option = &cl_options[default_opt->opt_index];
+ bool enabled;
+
+ if (size)
+ gcc_assert (level == 2);
+ if (fast)
+ gcc_assert (level == 3);
+ if (debug)
+ gcc_assert (level == 1);
+
+ switch (default_opt->levels)
+ {
+ case OPT_LEVELS_ALL:
+ enabled = true;
+ break;
+
+ case OPT_LEVELS_0_ONLY:
+ enabled = (level == 0);
+ break;
+
+ case OPT_LEVELS_1_PLUS:
+ enabled = (level >= 1);
+ break;
+
+ case OPT_LEVELS_1_PLUS_SPEED_ONLY:
+ enabled = (level >= 1 && !size && !debug);
+ break;
+
+ case OPT_LEVELS_1_PLUS_NOT_DEBUG:
+ enabled = (level >= 1 && !debug);
+ break;
+
+ case OPT_LEVELS_2_PLUS:
+ enabled = (level >= 2);
+ break;
+
+ case OPT_LEVELS_2_PLUS_SPEED_ONLY:
+ enabled = (level >= 2 && !size && !debug);
+ break;
+
+ case OPT_LEVELS_3_PLUS:
+ enabled = (level >= 3);
+ break;
+
+ case OPT_LEVELS_3_PLUS_AND_SIZE:
+ enabled = (level >= 3 || size);
+ break;
+
+ case OPT_LEVELS_SIZE:
+ enabled = size;
+ break;
+
+ case OPT_LEVELS_FAST:
+ enabled = fast;
+ break;
+
+ case OPT_LEVELS_NONE:
+ default:
+ gcc_unreachable ();
+ }
+
+ if (enabled)
+ handle_generated_option (opts, opts_set, default_opt->opt_index,
+ default_opt->arg, default_opt->value,
+ lang_mask, DK_UNSPECIFIED, loc,
+ handlers, true, dc);
+ else if (default_opt->arg == NULL
+ && !option->cl_reject_negative
+ && !(option->flags & CL_PARAMS))
+ handle_generated_option (opts, opts_set, default_opt->opt_index,
+ default_opt->arg, !default_opt->value,
+ lang_mask, DK_UNSPECIFIED, loc,
+ handlers, true, dc);
+}
+
+/* As indicated by the optimization level LEVEL (-Os if SIZE is set,
+ -Ofast if FAST is set), apply the options in array DEFAULT_OPTS to
+ OPTS and OPTS_SET, diagnostic context DC, location LOC, with
+ language mask LANG_MASK and option handlers HANDLERS. */
+
+static void
+maybe_default_options (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct default_options *default_opts,
+ int level, bool size, bool fast, bool debug,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ location_t loc,
+ diagnostic_context *dc)
+{
+ size_t i;
+
+ for (i = 0; default_opts[i].levels != OPT_LEVELS_NONE; i++)
+ maybe_default_option (opts, opts_set, &default_opts[i],
+ level, size, fast, debug,
+ lang_mask, handlers, loc, dc);
+}
+#endif // sdcpp
+
+/* Table of options enabled by default at different levels.
+ Please keep this list sorted by level and alphabetized within
+ each level; this makes it easier to keep the documentation
+ in sync. */
+
+static const struct default_options default_options_table[] =
+ {
+ /* -O1 and -Og optimizations. */
+ { OPT_LEVELS_1_PLUS, OPT_fcombine_stack_adjustments, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fcompare_elim, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fcprop_registers, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fforward_propagate, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fguess_branch_probability, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fipa_profile, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fipa_pure_const, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fipa_reference, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fipa_reference_addressable, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fmerge_constants, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_freorder_blocks, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fshrink_wrap, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fsplit_wide_types, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fthread_jumps, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_builtin_call_dce, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_ccp, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_ch, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_coalesce_vars, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_copy_prop, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_dce, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_dominator_opts, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_fre, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_sink, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_slsr, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_ftree_ter, NULL, 1 },
+ { OPT_LEVELS_1_PLUS, OPT_fvar_tracking, NULL, 1 },
+
+ /* -O1 (and not -Og) optimizations. */
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fbranch_count_reg, NULL, 1 },
+#if DELAY_SLOTS
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fdelayed_branch, NULL, 1 },
+#endif
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fdse, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fif_conversion2, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_finline_functions_called_once, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_invariants, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fmove_loop_stores, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fssa_phiopt, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_fipa_modref, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_bit_ccp, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_dse, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_pta, NULL, 1 },
+ { OPT_LEVELS_1_PLUS_NOT_DEBUG, OPT_ftree_sra, NULL, 1 },
+
+ /* -O2 and -Os optimizations. */
+ { OPT_LEVELS_2_PLUS, OPT_fcaller_saves, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fcode_hoisting, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fcrossjumping, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fcse_follow_jumps, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fexpensive_optimizations, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fgcse, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fhoist_adjacent_loads, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_findirect_inlining, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_finline_small_functions, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_bit_cp, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_icf, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_ra, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_vrp, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fisolate_erroneous_paths_dereference, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_flra_remat, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_foptimize_sibling_calls, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fpartial_inlining, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fpeephole2, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_freorder_functions, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_frerun_cse_after_loop, NULL, 1 },
+#ifdef INSN_SCHEDULING
+ { OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 },
+#endif
+ { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fstore_merging, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ftree_tail_merge, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ftree_vrp, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fvect_cost_model_, NULL,
+ VECT_COST_MODEL_VERY_CHEAP },
+ { OPT_LEVELS_2_PLUS, OPT_finline_functions, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
+
+ /* -O2 and above optimizations, but not -Os or -Og. */
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_functions, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_jumps, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_labels, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_falign_loops, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_foptimize_strlen, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_freorder_blocks_algorithm_, NULL,
+ REORDER_BLOCKS_ALGORITHM_STC },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_ftree_loop_vectorize, NULL, 1 },
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_ftree_slp_vectorize, NULL, 1 },
+#ifdef INSN_SCHEDULING
+ /* Only run the pre-regalloc scheduling pass if optimizing for speed. */
+ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 },
+#endif
+
+ /* -O3 and -Os optimizations. */
+
+ /* -O3 optimizations. */
+ { OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_floop_interchange, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_floop_unroll_and_jam, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fpeel_loops, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fsplit_loops, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fsplit_paths, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribution, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_ftree_partial_pre, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
+ { OPT_LEVELS_3_PLUS, OPT_fvect_cost_model_, NULL, VECT_COST_MODEL_DYNAMIC },
+ { OPT_LEVELS_3_PLUS, OPT_fversion_loops_for_strides, NULL, 1 },
+
+ /* -O3 parameters. */
+ { OPT_LEVELS_3_PLUS, OPT__param_max_inline_insns_auto_, NULL, 30 },
+ { OPT_LEVELS_3_PLUS, OPT__param_early_inlining_insns_, NULL, 14 },
+ { OPT_LEVELS_3_PLUS, OPT__param_inline_heuristics_hint_percent_, NULL, 600 },
+ { OPT_LEVELS_3_PLUS, OPT__param_inline_min_speedup_, NULL, 15 },
+ { OPT_LEVELS_3_PLUS, OPT__param_max_inline_insns_single_, NULL, 200 },
+
+ /* -Ofast adds optimizations to -O3. */
+ { OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 },
+ { OPT_LEVELS_FAST, OPT_fallow_store_data_races, NULL, 1 },
+ { OPT_LEVELS_FAST, OPT_fsemantic_interposition, NULL, 0 },
+
+ { OPT_LEVELS_NONE, 0, NULL, 0 }
+ };
+
+#if 0 //sdcpp
+/* Default the options in OPTS and OPTS_SET based on the optimization
+ settings in DECODED_OPTIONS and DECODED_OPTIONS_COUNT. */
+void
+default_options_optimization (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded_options,
+ unsigned int decoded_options_count,
+ location_t loc,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc)
+{
+ unsigned int i;
+ int opt2;
+ bool openacc_mode = false;
+
+ /* Scan to see what optimization level has been specified. That will
+ determine the default value of many flags. */
+ for (i = 1; i < decoded_options_count; i++)
+ {
+ struct cl_decoded_option *opt = &decoded_options[i];
+ switch (opt->opt_index)
+ {
+ case OPT_O:
+ if (*opt->arg == '\0')
+ {
+ opts->x_optimize = 1;
+ opts->x_optimize_size = 0;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
+ }
+ else
+ {
+ const int optimize_val = integral_argument (opt->arg);
+ if (optimize_val == -1)
+ error_at (loc, "argument to %<-O%> should be a non-negative "
+ "integer, %<g%>, %<s%>, %<z%> or %<fast%>");
+ else
+ {
+ opts->x_optimize = optimize_val;
+ if ((unsigned int) opts->x_optimize > 255)
+ opts->x_optimize = 255;
+ opts->x_optimize_size = 0;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
+ }
+ }
+ break;
+
+ case OPT_Os:
+ opts->x_optimize_size = 1;
+
+ /* Optimizing for size forces optimize to be 2. */
+ opts->x_optimize = 2;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
+ break;
+
+ case OPT_Oz:
+ opts->x_optimize_size = 2;
+
+ /* Optimizing for size forces optimize to be 2. */
+ opts->x_optimize = 2;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 0;
+ break;
+
+ case OPT_Ofast:
+ /* -Ofast only adds flags to -O3. */
+ opts->x_optimize_size = 0;
+ opts->x_optimize = 3;
+ opts->x_optimize_fast = 1;
+ opts->x_optimize_debug = 0;
+ break;
+
+ case OPT_Og:
+ /* -Og selects optimization level 1. */
+ opts->x_optimize_size = 0;
+ opts->x_optimize = 1;
+ opts->x_optimize_fast = 0;
+ opts->x_optimize_debug = 1;
+ break;
+
+ case OPT_fopenacc:
+ if (opt->value)
+ openacc_mode = true;
+ break;
+
+ default:
+ /* Ignore other options in this prescan. */
+ break;
+ }
+ }
+
+ maybe_default_options (opts, opts_set, default_options_table,
+ opts->x_optimize, opts->x_optimize_size,
+ opts->x_optimize_fast, opts->x_optimize_debug,
+ lang_mask, handlers, loc, dc);
+
+ /* -O2 param settings. */
+ opt2 = (opts->x_optimize >= 2);
+
+ if (openacc_mode)
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_pta, true);
+
+ /* Track fields in field-sensitive alias analysis. */
+ if (opt2)
+ SET_OPTION_IF_UNSET (opts, opts_set, param_max_fields_for_field_sensitive,
+ 100);
+
+ if (opts->x_optimize_size)
+ /* We want to crossjump as much as possible. */
+ SET_OPTION_IF_UNSET (opts, opts_set, param_min_crossjump_insns, 1);
+
+ /* Restrict the amount of work combine does at -Og while retaining
+ most of its useful transforms. */
+ if (opts->x_optimize_debug)
+ SET_OPTION_IF_UNSET (opts, opts_set, param_max_combine_insns, 2);
+
+ /* Allow default optimizations to be specified on a per-machine basis. */
+ maybe_default_options (opts, opts_set,
+ targetm_common.option_optimization_table,
+ opts->x_optimize, opts->x_optimize_size,
+ opts->x_optimize_fast, opts->x_optimize_debug,
+ lang_mask, handlers, loc, dc);
+}
+#endif
+
+/* Control IPA optimizations based on different live patching LEVEL. */
+static void
+control_options_for_live_patching (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ enum live_patching_level level,
+ location_t loc)
+{
+ gcc_assert (level > LIVE_PATCHING_NONE);
+
+ switch (level)
+ {
+ case LIVE_PATCHING_INLINE_ONLY_STATIC:
+#define LIVE_PATCHING_OPTION "-flive-patching=inline-only-static"
+ if (opts_set->x_flag_ipa_cp_clone && opts->x_flag_ipa_cp_clone)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-cp-clone", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_cp_clone = 0;
+
+ if (opts_set->x_flag_ipa_sra && opts->x_flag_ipa_sra)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-sra", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_sra = 0;
+
+ if (opts_set->x_flag_partial_inlining && opts->x_flag_partial_inlining)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fpartial-inlining", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_partial_inlining = 0;
+
+ if (opts_set->x_flag_ipa_cp && opts->x_flag_ipa_cp)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-cp", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_cp = 0;
+
+ /* FALLTHROUGH. */
+ case LIVE_PATCHING_INLINE_CLONE:
+#undef LIVE_PATCHING_OPTION
+#define LIVE_PATCHING_OPTION "-flive-patching=inline-only-static|inline-clone"
+ /* live patching should disable whole-program optimization. */
+ if (opts_set->x_flag_whole_program && opts->x_flag_whole_program)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fwhole-program", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_whole_program = 0;
+
+ /* visibility change should be excluded by !flag_whole_program
+ && !in_lto_p && !flag_ipa_cp_clone && !flag_ipa_sra
+ && !flag_partial_inlining. */
+
+ if (opts_set->x_flag_ipa_pta && opts->x_flag_ipa_pta)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-pta", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_pta = 0;
+
+ if (opts_set->x_flag_ipa_reference && opts->x_flag_ipa_reference)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-reference", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_reference = 0;
+
+ if (opts_set->x_flag_ipa_ra && opts->x_flag_ipa_ra)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-ra", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_ra = 0;
+
+ if (opts_set->x_flag_ipa_icf && opts->x_flag_ipa_icf)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-icf", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_icf = 0;
+
+ if (opts_set->x_flag_ipa_icf_functions && opts->x_flag_ipa_icf_functions)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-icf-functions", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_icf_functions = 0;
+
+ if (opts_set->x_flag_ipa_icf_variables && opts->x_flag_ipa_icf_variables)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-icf-variables", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_icf_variables = 0;
+
+ if (opts_set->x_flag_ipa_bit_cp && opts->x_flag_ipa_bit_cp)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-bit-cp", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_bit_cp = 0;
+
+ if (opts_set->x_flag_ipa_vrp && opts->x_flag_ipa_vrp)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-vrp", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_vrp = 0;
+
+ if (opts_set->x_flag_ipa_pure_const && opts->x_flag_ipa_pure_const)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-pure-const", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_pure_const = 0;
+
+ if (opts_set->x_flag_ipa_modref && opts->x_flag_ipa_modref)
+ error_at (loc,
+ "%<-fipa-modref%> is incompatible with %qs",
+ LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_modref = 0;
+
+ /* FIXME: disable unreachable code removal. */
+
+ /* discovery of functions/variables with no address taken. */
+ if (opts_set->x_flag_ipa_reference_addressable
+ && opts->x_flag_ipa_reference_addressable)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-reference-addressable", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_reference_addressable = 0;
+
+ /* ipa stack alignment propagation. */
+ if (opts_set->x_flag_ipa_stack_alignment
+ && opts->x_flag_ipa_stack_alignment)
+ error_at (loc, "%qs is incompatible with %qs",
+ "-fipa-stack-alignment", LIVE_PATCHING_OPTION);
+ else
+ opts->x_flag_ipa_stack_alignment = 0;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+#undef LIVE_PATCHING_OPTION
+}
+
+/* --help option argument if set. */
+vec<const char *> help_option_arguments;
+
+/* Return the string name describing a sanitizer argument which has been
+ provided on the command line and has set this particular flag. */
+const char *
+find_sanitizer_argument (struct gcc_options *opts, unsigned int flags)
+{
+ for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
+ {
+ /* Need to find the sanitizer_opts element which:
+ a) Could have set the flags requested.
+ b) Has been set on the command line.
+
+ Can have (a) without (b) if the flag requested is e.g.
+ SANITIZE_ADDRESS, since both -fsanitize=address and
+ -fsanitize=kernel-address set this flag.
+
+ Can have (b) without (a) by requesting more than one sanitizer on the
+ command line. */
+ if ((sanitizer_opts[i].flag & opts->x_flag_sanitize)
+ != sanitizer_opts[i].flag)
+ continue;
+ if ((sanitizer_opts[i].flag & flags) != flags)
+ continue;
+ return sanitizer_opts[i].name;
+ }
+ return NULL;
+}
+
+
+/* Report an error to the user about sanitizer options they have requested
+ which have set conflicting flags.
+
+ LEFT and RIGHT indicate sanitizer flags which conflict with each other, this
+ function reports an error if both have been set in OPTS->x_flag_sanitize and
+ ensures the error identifies the requested command line options that have
+ set these flags. */
+static void
+report_conflicting_sanitizer_options (struct gcc_options *opts, location_t loc,
+ unsigned int left, unsigned int right)
+{
+ unsigned int left_seen = (opts->x_flag_sanitize & left);
+ unsigned int right_seen = (opts->x_flag_sanitize & right);
+ if (left_seen && right_seen)
+ {
+ const char* left_arg = find_sanitizer_argument (opts, left_seen);
+ const char* right_arg = find_sanitizer_argument (opts, right_seen);
+ gcc_assert (left_arg && right_arg);
+ error_at (loc,
+ "%<-fsanitize=%s%> is incompatible with %<-fsanitize=%s%>",
+ left_arg, right_arg);
+ }
+}
+
+/* After all options at LOC have been read into OPTS and OPTS_SET,
+ finalize settings of those options and diagnose incompatible
+ combinations. */
+void
+finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
+ location_t loc)
+{
+ if (opts->x_dump_base_name
+ && ! opts->x_dump_base_name_prefixed)
+ {
+ const char *sep = opts->x_dump_base_name;
+
+ for (; *sep; sep++)
+ if (IS_DIR_SEPARATOR (*sep))
+ break;
+
+ if (*sep)
+ /* If dump_base_path contains subdirectories, don't prepend
+ anything. */;
+ else if (opts->x_dump_dir_name)
+ /* We have a DUMP_DIR_NAME, prepend that. */
+ opts->x_dump_base_name = opts_concat (opts->x_dump_dir_name,
+ opts->x_dump_base_name, NULL);
+
+ /* It is definitely prefixed now. */
+ opts->x_dump_base_name_prefixed = true;
+ }
+
+ /* Handle related options for unit-at-a-time, toplevel-reorder, and
+ section-anchors. */
+ if (!opts->x_flag_unit_at_a_time)
+ {
+ if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
+ error_at (loc, "section anchors must be disabled when unit-at-a-time "
+ "is disabled");
+ opts->x_flag_section_anchors = 0;
+ if (opts->x_flag_toplevel_reorder == 1)
+ error_at (loc, "toplevel reorder must be disabled when unit-at-a-time "
+ "is disabled");
+ opts->x_flag_toplevel_reorder = 0;
+ }
+
+ /* -fself-test depends on the state of the compiler prior to
+ compiling anything. Ideally it should be run on an empty source
+ file. However, in case we get run with actual source, assume
+ -fsyntax-only which will inhibit any compiler initialization
+ which may confuse the self tests. */
+ if (opts->x_flag_self_test)
+ opts->x_flag_syntax_only = 1;
+
+ if (opts->x_flag_tm && opts->x_flag_non_call_exceptions)
+ sorry ("transactional memory is not supported with non-call exceptions");
+
+ /* Unless the user has asked for section anchors, we disable toplevel
+ reordering at -O0 to disable transformations that might be surprising
+ to end users and to get -fno-toplevel-reorder tested. */
+ if (!opts->x_optimize
+ && opts->x_flag_toplevel_reorder == 2
+ && !(opts->x_flag_section_anchors && opts_set->x_flag_section_anchors))
+ {
+ opts->x_flag_toplevel_reorder = 0;
+ opts->x_flag_section_anchors = 0;
+ }
+ if (!opts->x_flag_toplevel_reorder)
+ {
+ if (opts->x_flag_section_anchors && opts_set->x_flag_section_anchors)
+ error_at (loc, "section anchors must be disabled when toplevel reorder"
+ " is disabled");
+ opts->x_flag_section_anchors = 0;
+ }
+
+ if (!opts->x_flag_opts_finished)
+ {
+ /* We initialize opts->x_flag_pie to -1 so that targets can set a
+ default value. */
+ if (opts->x_flag_pie == -1)
+ {
+ /* We initialize opts->x_flag_pic to -1 so that we can tell if
+ -fpic, -fPIC, -fno-pic or -fno-PIC is used. */
+ if (opts->x_flag_pic == -1)
+ opts->x_flag_pie = DEFAULT_FLAG_PIE;
+ else
+ opts->x_flag_pie = 0;
+ }
+ /* If -fPIE or -fpie is used, turn on PIC. */
+ if (opts->x_flag_pie)
+ opts->x_flag_pic = opts->x_flag_pie;
+ else if (opts->x_flag_pic == -1)
+ opts->x_flag_pic = 0;
+ if (opts->x_flag_pic && !opts->x_flag_pie)
+ opts->x_flag_shlib = 1;
+ opts->x_flag_opts_finished = true;
+ }
+
+ /* We initialize opts->x_flag_stack_protect to -1 so that targets
+ can set a default value. */
+ if (opts->x_flag_stack_protect == -1)
+ opts->x_flag_stack_protect = DEFAULT_FLAG_SSP;
+
+ if (opts->x_optimize == 0)
+ {
+ /* Inlining does not work if not optimizing,
+ so force it not to be done. */
+ opts->x_warn_inline = 0;
+ opts->x_flag_no_inline = 1;
+ }
+
+ /* Pipelining of outer loops is only possible when general pipelining
+ capabilities are requested. */
+ if (!opts->x_flag_sel_sched_pipelining)
+ opts->x_flag_sel_sched_pipelining_outer_loops = 0;
+
+ if (opts->x_flag_conserve_stack)
+ {
+ SET_OPTION_IF_UNSET (opts, opts_set, param_large_stack_frame, 100);
+ SET_OPTION_IF_UNSET (opts, opts_set, param_stack_frame_growth, 40);
+ }
+
+ if (opts->x_flag_lto)
+ {
+#ifdef ENABLE_LTO
+ opts->x_flag_generate_lto = 1;
+
+ /* When generating IL, do not operate in whole-program mode.
+ Otherwise, symbols will be privatized too early, causing link
+ errors later. */
+ opts->x_flag_whole_program = 0;
+#else
+ error_at (loc, "LTO support has not been enabled in this configuration");
+#endif
+ if (!opts->x_flag_fat_lto_objects
+ && (!HAVE_LTO_PLUGIN
+ || (opts_set->x_flag_use_linker_plugin
+ && !opts->x_flag_use_linker_plugin)))
+ {
+ if (opts_set->x_flag_fat_lto_objects)
+ error_at (loc, "%<-fno-fat-lto-objects%> are supported only with "
+ "linker plugin");
+ opts->x_flag_fat_lto_objects = 1;
+ }
+
+ /* -gsplit-dwarf isn't compatible with LTO, see PR88389. */
+ if (opts->x_dwarf_split_debug_info)
+ {
+ inform (loc, "%<-gsplit-dwarf%> is not supported with LTO,"
+ " disabling");
+ opts->x_dwarf_split_debug_info = 0;
+ }
+ }
+
+ /* We initialize opts->x_flag_split_stack to -1 so that targets can set a
+ default value if they choose based on other options. */
+ if (opts->x_flag_split_stack == -1)
+ opts->x_flag_split_stack = 0;
+ else if (opts->x_flag_split_stack)
+ {
+ // sdcpp if (!targetm_common.supports_split_stack (true, opts))
+ {
+ error_at (loc, "%<-fsplit-stack%> is not supported by "
+ "this compiler configuration");
+ opts->x_flag_split_stack = 0;
+ }
+ }
+
+ /* If stack splitting is turned on, and the user did not explicitly
+ request function partitioning, turn off partitioning, as it
+ confuses the linker when trying to handle partitioned split-stack
+ code that calls a non-split-stack functions. But if partitioning
+ was turned on explicitly just hope for the best. */
+ if (opts->x_flag_split_stack
+ && opts->x_flag_reorder_blocks_and_partition)
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_blocks_and_partition, 0);
+
+ if (opts->x_flag_reorder_blocks_and_partition)
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_functions, 1);
+
+ /* The -gsplit-dwarf option requires -ggnu-pubnames. */
+ if (opts->x_dwarf_split_debug_info)
+ opts->x_debug_generate_pub_sections = 2;
+
+ if ((opts->x_flag_sanitize
+ & (SANITIZE_USER_ADDRESS | SANITIZE_KERNEL_ADDRESS)) == 0)
+ {
+ if (opts->x_flag_sanitize & SANITIZE_POINTER_COMPARE)
+ error_at (loc,
+ "%<-fsanitize=pointer-compare%> must be combined with "
+ "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
+ if (opts->x_flag_sanitize & SANITIZE_POINTER_SUBTRACT)
+ error_at (loc,
+ "%<-fsanitize=pointer-subtract%> must be combined with "
+ "%<-fsanitize=address%> or %<-fsanitize=kernel-address%>");
+ }
+
+ /* Address sanitizers conflict with the thread sanitizer. */
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_THREAD,
+ SANITIZE_ADDRESS | SANITIZE_HWADDRESS);
+ /* The leak sanitizer conflicts with the thread sanitizer. */
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_LEAK,
+ SANITIZE_THREAD);
+
+ /* No combination of HWASAN and ASAN work together. */
+ report_conflicting_sanitizer_options (opts, loc,
+ SANITIZE_HWADDRESS, SANITIZE_ADDRESS);
+
+ /* The userspace and kernel address sanitizers conflict with each other. */
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_USER_HWADDRESS,
+ SANITIZE_KERNEL_HWADDRESS);
+ report_conflicting_sanitizer_options (opts, loc, SANITIZE_USER_ADDRESS,
+ SANITIZE_KERNEL_ADDRESS);
+
+ /* Check error recovery for -fsanitize-recover option. */
+ for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
+ if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
+ && !sanitizer_opts[i].can_recover)
+ error_at (loc, "%<-fsanitize-recover=%s%> is not supported",
+ sanitizer_opts[i].name);
+
+ /* When instrumenting the pointers, we don't want to remove
+ the null pointer checks. */
+ if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
+ | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
+ opts->x_flag_delete_null_pointer_checks = 0;
+
+ /* Aggressive compiler optimizations may cause false negatives. */
+ if (opts->x_flag_sanitize & ~(SANITIZE_LEAK | SANITIZE_UNREACHABLE))
+ opts->x_flag_aggressive_loop_optimizations = 0;
+
+ /* Enable -fsanitize-address-use-after-scope if either address sanitizer is
+ enabled. */
+ if (opts->x_flag_sanitize
+ & (SANITIZE_USER_ADDRESS | SANITIZE_USER_HWADDRESS))
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_sanitize_address_use_after_scope,
+ true);
+
+ /* Force -fstack-reuse=none in case -fsanitize-address-use-after-scope
+ is enabled. */
+ if (opts->x_flag_sanitize_address_use_after_scope)
+ {
+ if (opts->x_flag_stack_reuse != SR_NONE
+ && opts_set->x_flag_stack_reuse != SR_NONE)
+ error_at (loc,
+ "%<-fsanitize-address-use-after-scope%> requires "
+ "%<-fstack-reuse=none%> option");
+
+ opts->x_flag_stack_reuse = SR_NONE;
+ }
+
+ if ((opts->x_flag_sanitize & SANITIZE_USER_ADDRESS) && opts->x_flag_tm)
+ sorry ("transactional memory is not supported with %<-fsanitize=address%>");
+
+ if ((opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS) && opts->x_flag_tm)
+ sorry ("transactional memory is not supported with "
+ "%<-fsanitize=kernel-address%>");
+
+ /* Currently live patching is not support for LTO. */
+ if (opts->x_flag_live_patching && opts->x_flag_lto)
+ sorry ("live patching is not supported with LTO");
+
+ /* Currently vtable verification is not supported for LTO */
+ if (opts->x_flag_vtable_verify && opts->x_flag_lto)
+ sorry ("vtable verification is not supported with LTO");
+
+ /* Control IPA optimizations based on different -flive-patching level. */
+ if (opts->x_flag_live_patching)
+ control_options_for_live_patching (opts, opts_set,
+ opts->x_flag_live_patching,
+ loc);
+
+ /* Allow cunroll to grow size accordingly. */
+ if (!opts_set->x_flag_cunroll_grow_size)
+ opts->x_flag_cunroll_grow_size
+ = (opts->x_flag_unroll_loops
+ || opts->x_flag_peel_loops
+ || opts->x_optimize >= 3);
+
+ /* With -fcx-limited-range, we do cheap and quick complex arithmetic. */
+ if (opts->x_flag_cx_limited_range)
+ opts->x_flag_complex_method = 0;
+ else if (opts_set->x_flag_cx_limited_range)
+ opts->x_flag_complex_method = opts->x_flag_default_complex_method;
+
+ /* With -fcx-fortran-rules, we do something in-between cheap and C99. */
+ if (opts->x_flag_cx_fortran_rules)
+ opts->x_flag_complex_method = 1;
+ else if (opts_set->x_flag_cx_fortran_rules)
+ opts->x_flag_complex_method = opts->x_flag_default_complex_method;
+
+ /* Use -fvect-cost-model=cheap instead of -fvect-cost-mode=very-cheap
+ by default with explicit -ftree-{loop,slp}-vectorize. */
+ if (opts->x_optimize == 2
+ && (opts_set->x_flag_tree_loop_vectorize
+ || opts_set->x_flag_tree_vectorize))
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_vect_cost_model,
+ VECT_COST_MODEL_CHEAP);
+
+ if (flag_gtoggle)
+ {
+ /* Make sure to process -gtoggle only once. */
+ flag_gtoggle = false;
+ if (debug_info_level == DINFO_LEVEL_NONE)
+ {
+ debug_info_level = DINFO_LEVEL_NORMAL;
+
+ if (write_symbols == NO_DEBUG)
+ write_symbols = PREFERRED_DEBUGGING_TYPE;
+ }
+ else
+ debug_info_level = DINFO_LEVEL_NONE;
+ }
+
+ if (!OPTION_SET_P (debug_nonbind_markers_p))
+ debug_nonbind_markers_p
+ = (optimize
+ && debug_info_level >= DINFO_LEVEL_NORMAL
+ && dwarf_debuginfo_p ()
+ && !(flag_selective_scheduling || flag_selective_scheduling2));
+
+ /* Note -fvar-tracking is enabled automatically with OPT_LEVELS_1_PLUS and
+ so we need to drop it if we are called from optimize attribute. */
+ if (debug_info_level == DINFO_LEVEL_NONE
+ && !OPTION_SET_P (flag_var_tracking))
+ flag_var_tracking = false;
+
+ /* One could use EnabledBy, but it would lead to a circular dependency. */
+ if (!OPTION_SET_P (flag_var_tracking_uninit))
+ flag_var_tracking_uninit = flag_var_tracking;
+
+ if (!OPTION_SET_P (flag_var_tracking_assignments))
+ flag_var_tracking_assignments
+ = (flag_var_tracking
+ && !(flag_selective_scheduling || flag_selective_scheduling2));
+
+ if (flag_var_tracking_assignments_toggle)
+ flag_var_tracking_assignments = !flag_var_tracking_assignments;
+
+ if (flag_var_tracking_assignments && !flag_var_tracking)
+ flag_var_tracking = flag_var_tracking_assignments = -1;
+
+ if (flag_var_tracking_assignments
+ && (flag_selective_scheduling || flag_selective_scheduling2))
+ warning_at (loc, 0,
+ "var-tracking-assignments changes selective scheduling");
+
+ if (flag_syntax_only)
+ {
+ write_symbols = NO_DEBUG;
+ profile_flag = 0;
+ }
+
+
+ diagnose_options (opts, opts_set, loc);
+}
+
+/* The function diagnoses incompatible combinations for provided options
+ (OPTS and OPTS_SET) at a given LOCation. The function is called both
+ when command line is parsed (after the target optimization hook) and
+ when an optimize/target attribute (or pragma) is used. */
+
+void diagnose_options (gcc_options *opts, gcc_options *opts_set,
+ location_t loc)
+{
+ /* The optimization to partition hot and cold basic blocks into separate
+ sections of the .o and executable files does not work (currently)
+ with exception handling. This is because there is no support for
+ generating unwind info. If opts->x_flag_exceptions is turned on
+ we need to turn off the partitioning optimization. */
+
+ enum unwind_info_type ui_except
+ = unwind_info_type(); // sdcpp targetm_common.except_unwind_info (opts);
+
+ if (opts->x_flag_exceptions
+ && opts->x_flag_reorder_blocks_and_partition
+ && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))
+ {
+ if (opts_set->x_flag_reorder_blocks_and_partition)
+ inform (loc,
+ "%<-freorder-blocks-and-partition%> does not work "
+ "with exceptions on this architecture");
+ opts->x_flag_reorder_blocks_and_partition = 0;
+ opts->x_flag_reorder_blocks = 1;
+ }
+
+ /* If user requested unwind info, then turn off the partitioning
+ optimization. */
+
+ if (opts->x_flag_unwind_tables
+ // sdcpp && !targetm_common.unwind_tables_default
+ && opts->x_flag_reorder_blocks_and_partition
+ && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))
+ {
+ if (opts_set->x_flag_reorder_blocks_and_partition)
+ inform (loc,
+ "%<-freorder-blocks-and-partition%> does not support "
+ "unwind info on this architecture");
+ opts->x_flag_reorder_blocks_and_partition = 0;
+ opts->x_flag_reorder_blocks = 1;
+ }
+
+ /* If the target requested unwind info, then turn off the partitioning
+ optimization with a different message. Likewise, if the target does not
+ support named sections. */
+
+ if (opts->x_flag_reorder_blocks_and_partition
+ && (0 // sdcpp !targetm_common.have_named_sections
+ || (opts->x_flag_unwind_tables
+ // sdcpp && targetm_common.unwind_tables_default
+ && (ui_except == UI_SJLJ || ui_except >= UI_TARGET))))
+ {
+ if (opts_set->x_flag_reorder_blocks_and_partition)
+ inform (loc,
+ "%<-freorder-blocks-and-partition%> does not work "
+ "on this architecture");
+ opts->x_flag_reorder_blocks_and_partition = 0;
+ opts->x_flag_reorder_blocks = 1;
+ }
+
+
+}
+
+#define LEFT_COLUMN 27
+
+/* Output ITEM, of length ITEM_WIDTH, in the left column,
+ followed by word-wrapped HELP in a second column. */
+static void
+wrap_help (const char *help,
+ const char *item,
+ unsigned int item_width,
+ unsigned int columns)
+{
+ unsigned int col_width = LEFT_COLUMN;
+ unsigned int remaining, room, len;
+
+ remaining = strlen (help);
+
+ do
+ {
+ room = columns - 3 - MAX (col_width, item_width);
+ if (room > columns)
+ room = 0;
+ len = remaining;
+
+ if (room < len)
+ {
+ unsigned int i;
+
+ for (i = 0; help[i]; i++)
+ {
+ if (i >= room && len != remaining)
+ break;
+ if (help[i] == ' ')
+ len = i;
+ else if ((help[i] == '-' || help[i] == '/')
+ && help[i + 1] != ' '
+ && i > 0 && ISALPHA (help[i - 1]))
+ len = i + 1;
+ }
+ }
+
+ printf (" %-*.*s %.*s\n", col_width, item_width, item, len, help);
+ item_width = 0;
+ while (help[len] == ' ')
+ len++;
+ help += len;
+ remaining -= len;
+ }
+ while (remaining);
+}
+
+/* Data structure used to print list of valid option values. */
+
+class option_help_tuple
+{
+public:
+ option_help_tuple (int code, vec<const char *> values):
+ m_code (code), m_values (values)
+ {}
+
+ /* Code of an option. */
+ int m_code;
+
+ /* List of possible values. */
+ vec<const char *> m_values;
+};
+
+/* Print help for a specific front-end, etc. */
+static void
+print_filtered_help (unsigned int include_flags,
+ unsigned int exclude_flags,
+ unsigned int any_flags,
+ unsigned int columns,
+ struct gcc_options *opts,
+ unsigned int lang_mask)
+{
+ unsigned int i;
+ const char *help;
+ bool found = false;
+ bool displayed = false;
+ char new_help[256];
+
+ if (!opts->x_help_printed)
+ opts->x_help_printed = XCNEWVAR (char, cl_options_count);
+
+ if (!opts->x_help_enum_printed)
+ opts->x_help_enum_printed = XCNEWVAR (char, cl_enums_count);
+
+ auto_vec<option_help_tuple> help_tuples;
+
+ for (i = 0; i < cl_options_count; i++)
+ {
+ const struct cl_option *option = cl_options + i;
+ unsigned int len;
+ const char *opt;
+ const char *tab;
+
+ if (include_flags == 0
+ || ((option->flags & include_flags) != include_flags))
+ {
+ if ((option->flags & any_flags) == 0)
+ continue;
+ }
+
+ /* Skip unwanted switches. */
+ if ((option->flags & exclude_flags) != 0)
+ continue;
+
+ /* The driver currently prints its own help text. */
+ if ((option->flags & CL_DRIVER) != 0
+ && (option->flags & (((1U << cl_lang_count) - 1)
+ | CL_COMMON | CL_TARGET)) == 0)
+ continue;
+
+ /* If an option contains a language specification,
+ exclude it from common unless all languages are present. */
+ if ((include_flags & CL_COMMON)
+ && !(option->flags & CL_DRIVER)
+ && (option->flags & CL_LANG_ALL)
+ && (option->flags & CL_LANG_ALL) != CL_LANG_ALL)
+ continue;
+
+ found = true;
+ /* Skip switches that have already been printed. */
+ if (opts->x_help_printed[i])
+ continue;
+
+ opts->x_help_printed[i] = true;
+
+ help = option->help;
+ if (help == NULL)
+ {
+ if (exclude_flags & CL_UNDOCUMENTED)
+ continue;
+
+ help = undocumented_msg;
+ }
+
+ /* Get the translation. */
+ help = _(help);
+
+ if (option->alias_target < N_OPTS
+ && cl_options [option->alias_target].help)
+ {
+ const struct cl_option *target = cl_options + option->alias_target;
+ if (option->help == NULL)
+ {
+ /* The option is undocumented but is an alias for an option that
+ is documented. If the option has alias arguments, then its
+ purpose is to provide certain arguments to the other option, so
+ inform the reader of this. Otherwise, point the reader to the
+ other option in preference to the former. */
+
+ if (option->alias_arg)
+ {
+ if (option->neg_alias_arg)
+ snprintf (new_help, sizeof new_help,
+ _("Same as %s%s (or, in negated form, %s%s)."),
+ target->opt_text, option->alias_arg,
+ target->opt_text, option->neg_alias_arg);
+ else
+ snprintf (new_help, sizeof new_help,
+ _("Same as %s%s."),
+ target->opt_text, option->alias_arg);
+ }
+ else
+ snprintf (new_help, sizeof new_help,
+ _("Same as %s."),
+ target->opt_text);
+ }
+ else
+ {
+ /* For documented options with aliases, mention the aliased
+ option's name for reference. */
+ snprintf (new_help, sizeof new_help,
+ _("%s Same as %s."),
+ help, cl_options [option->alias_target].opt_text);
+ }
+
+ help = new_help;
+ }
+
+ if (option->warn_message)
+ {
+ /* Mention that the use of the option will trigger a warning. */
+ if (help == new_help)
+ snprintf (new_help + strlen (new_help),
+ sizeof new_help - strlen (new_help),
+ " %s", _(use_diagnosed_msg));
+ else
+ snprintf (new_help, sizeof new_help,
+ "%s %s", help, _(use_diagnosed_msg));
+
+ help = new_help;
+ }
+
+ /* Find the gap between the name of the
+ option and its descriptive text. */
+ tab = strchr (help, '\t');
+ if (tab)
+ {
+ len = tab - help;
+ opt = help;
+ help = tab + 1;
+ }
+ else
+ {
+ opt = option->opt_text;
+ len = strlen (opt);
+ }
+
+ /* With the -Q option enabled we change the descriptive text associated
+ with an option to be an indication of its current setting. */
+ if (!opts->x_quiet_flag)
+ {
+ void *flag_var = option_flag_var (i, opts);
+
+ if (len < (LEFT_COLUMN + 2))
+ strcpy (new_help, "\t\t");
+ else
+ strcpy (new_help, "\t");
+
+ /* Set to print whether the option is enabled or disabled,
+ or, if it's an alias for another option, the name of
+ the aliased option. */
+ bool print_state = false;
+
+ if (flag_var != NULL
+ && option->var_type != CLVC_DEFER)
+ {
+ /* If OPTION is only available for a specific subset
+ of languages other than this one, mention them. */
+ bool avail_for_lang = true;
+ if (unsigned langset = option->flags & CL_LANG_ALL)
+ {
+ if (!(langset & lang_mask))
+ {
+ avail_for_lang = false;
+ strcat (new_help, _("[available in "));
+ for (unsigned i = 0, n = 0; (1U << i) < CL_LANG_ALL; ++i)
+ if (langset & (1U << i))
+ {
+ if (n++)
+ strcat (new_help, ", ");
+ strcat (new_help, lang_names[i]);
+ }
+ strcat (new_help, "]");
+ }
+ }
+ if (!avail_for_lang)
+ ; /* Print nothing else if the option is not available
+ in the current language. */
+ else if (option->flags & CL_JOINED)
+ {
+ if (option->var_type == CLVC_STRING)
+ {
+ if (* (const char **) flag_var != NULL)
+ snprintf (new_help + strlen (new_help),
+ sizeof (new_help) - strlen (new_help),
+ "%s", * (const char **) flag_var);
+ }
+ else if (option->var_type == CLVC_ENUM)
+ {
+ const struct cl_enum *e = &cl_enums[option->var_enum];
+ int value;
+ const char *arg = NULL;
+
+ value = e->get (flag_var);
+ enum_value_to_arg (e->values, &arg, value, lang_mask);
+ if (arg == NULL)
+ arg = _("[default]");
+ snprintf (new_help + strlen (new_help),
+ sizeof (new_help) - strlen (new_help),
+ "%s", arg);
+ }
+ else
+ {
+ if (option->cl_host_wide_int)
+ sprintf (new_help + strlen (new_help),
+ _("%llu bytes"), (unsigned long long)
+ *(unsigned HOST_WIDE_INT *) flag_var);
+ else
+ sprintf (new_help + strlen (new_help),
+ "%i", * (int *) flag_var);
+ }
+ }
+ else
+ print_state = true;
+ }
+ else
+ /* When there is no argument, print the option state only
+ if the option takes no argument. */
+ print_state = !(option->flags & CL_JOINED);
+
+ if (print_state)
+ {
+ if (option->alias_target < N_OPTS
+ && option->alias_target != OPT_SPECIAL_warn_removed
+ && option->alias_target != OPT_SPECIAL_ignore
+ && option->alias_target != OPT_SPECIAL_input_file
+ && option->alias_target != OPT_SPECIAL_program_name
+ && option->alias_target != OPT_SPECIAL_unknown)
+ {
+ const struct cl_option *target
+ = &cl_options[option->alias_target];
+ sprintf (new_help + strlen (new_help), "%s%s",
+ target->opt_text,
+ option->alias_arg ? option->alias_arg : "");
+ }
+ else if (option->alias_target == OPT_SPECIAL_ignore)
+ strcat (new_help, ("[ignored]"));
+ else
+ {
+ /* Print the state for an on/off option. */
+ int ena = option_enabled (i, lang_mask, opts);
+ if (ena > 0)
+ strcat (new_help, _("[enabled]"));
+ else if (ena == 0)
+ strcat (new_help, _("[disabled]"));
+ }
+ }
+
+ help = new_help;
+ }
+
+ if (option->range_max != -1)
+ {
+ char b[128];
+ snprintf (b, sizeof (b), "<%d,%d>", option->range_min,
+ option->range_max);
+ opt = concat (opt, b, NULL);
+ len += strlen (b);
+ }
+
+ wrap_help (help, opt, len, columns);
+ displayed = true;
+
+ if (option->var_type == CLVC_ENUM
+ && opts->x_help_enum_printed[option->var_enum] != 2)
+ opts->x_help_enum_printed[option->var_enum] = 1;
+ else
+ {
+ vec<const char *> option_values
+ ; // sdcpp = targetm_common.get_valid_option_values (i, NULL);
+ if (!option_values.is_empty ())
+ help_tuples.safe_push (option_help_tuple (i, option_values));
+ }
+ }
+
+ if (! found)
+ {
+ unsigned int langs = include_flags & CL_LANG_ALL;
+
+ if (langs == 0)
+ printf (_(" No options with the desired characteristics were found\n"));
+ else
+ {
+ unsigned int i;
+
+ /* PR 31349: Tell the user how to see all of the
+ options supported by a specific front end. */
+ for (i = 0; (1U << i) < CL_LANG_ALL; i ++)
+ if ((1U << i) & langs)
+ printf (_(" None found. Use --help=%s to show *all* the options supported by the %s front-end.\n"),
+ lang_names[i], lang_names[i]);
+ }
+
+ }
+ else if (! displayed)
+ printf (_(" All options with the desired characteristics have already been displayed\n"));
+
+ putchar ('\n');
+
+ /* Print details of enumerated option arguments, if those
+ enumerations have help text headings provided. If no help text
+ is provided, presume that the possible values are listed in the
+ help text for the relevant options. */
+ for (i = 0; i < cl_enums_count; i++)
+ {
+ unsigned int j, pos;
+
+ if (opts->x_help_enum_printed[i] != 1)
+ continue;
+ if (cl_enums[i].help == NULL)
+ continue;
+ printf (" %s\n ", _(cl_enums[i].help));
+ pos = 4;
+ for (j = 0; cl_enums[i].values[j].arg != NULL; j++)
+ {
+ unsigned int len = strlen (cl_enums[i].values[j].arg);
+
+ if (pos > 4 && pos + 1 + len <= columns)
+ {
+ printf (" %s", cl_enums[i].values[j].arg);
+ pos += 1 + len;
+ }
+ else
+ {
+ if (pos > 4)
+ {
+ printf ("\n ");
+ pos = 4;
+ }
+ printf ("%s", cl_enums[i].values[j].arg);
+ pos += len;
+ }
+ }
+ printf ("\n\n");
+ opts->x_help_enum_printed[i] = 2;
+ }
+
+ for (unsigned i = 0; i < help_tuples.length (); i++)
+ {
+ const struct cl_option *option = cl_options + help_tuples[i].m_code;
+ printf (_(" Known valid arguments for %s option:\n "),
+ option->opt_text);
+ for (unsigned j = 0; j < help_tuples[i].m_values.length (); j++)
+ printf (" %s", help_tuples[i].m_values[j]);
+ printf ("\n\n");
+ }
+}
+
+/* Display help for a specified type of option.
+ The options must have ALL of the INCLUDE_FLAGS set
+ ANY of the flags in the ANY_FLAGS set
+ and NONE of the EXCLUDE_FLAGS set. The current option state is in
+ OPTS; LANG_MASK is used for interpreting enumerated option state. */
+static void
+print_specific_help (unsigned int include_flags,
+ unsigned int exclude_flags,
+ unsigned int any_flags,
+ struct gcc_options *opts,
+ unsigned int lang_mask)
+{
+ unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
+ const char * description = NULL;
+ const char * descrip_extra = "";
+ size_t i;
+ unsigned int flag;
+
+ /* Sanity check: Make sure that we do not have more
+ languages than we have bits available to enumerate them. */
+ gcc_assert ((1U << cl_lang_count) <= CL_MIN_OPTION_CLASS);
+
+ /* If we have not done so already, obtain
+ the desired maximum width of the output. */
+ if (opts->x_help_columns == 0)
+ {
+ opts->x_help_columns = get_terminal_width ();
+ if (opts->x_help_columns == INT_MAX)
+ /* Use a reasonable default. */
+ opts->x_help_columns = 80;
+ }
+
+ /* Decide upon the title for the options that we are going to display. */
+ for (i = 0, flag = 1; flag <= CL_MAX_OPTION_CLASS; flag <<= 1, i ++)
+ {
+ switch (flag & include_flags)
+ {
+ case 0:
+ case CL_DRIVER:
+ break;
+
+ case CL_TARGET:
+ description = _("The following options are target specific");
+ break;
+ case CL_WARNING:
+ description = _("The following options control compiler warning messages");
+ break;
+ case CL_OPTIMIZATION:
+ description = _("The following options control optimizations");
+ break;
+ case CL_COMMON:
+ description = _("The following options are language-independent");
+ break;
+ case CL_PARAMS:
+ description = _("The following options control parameters");
+ break;
+ default:
+ if (i >= cl_lang_count)
+ break;
+ if (exclude_flags & all_langs_mask)
+ description = _("The following options are specific to just the language ");
+ else
+ description = _("The following options are supported by the language ");
+ descrip_extra = lang_names [i];
+ break;
+ }
+ }
+
+ if (description == NULL)
+ {
+ if (any_flags == 0)
+ {
+ if (include_flags & CL_UNDOCUMENTED)
+ description = _("The following options are not documented");
+ else if (include_flags & CL_SEPARATE)
+ description = _("The following options take separate arguments");
+ else if (include_flags & CL_JOINED)
+ description = _("The following options take joined arguments");
+ else
+ {
+ internal_error ("unrecognized %<include_flags 0x%x%> passed "
+ "to %<print_specific_help%>",
+ include_flags);
+ return;
+ }
+ }
+ else
+ {
+ if (any_flags & all_langs_mask)
+ description = _("The following options are language-related");
+ else
+ description = _("The following options are language-independent");
+ }
+ }
+
+ printf ("%s%s:\n", description, descrip_extra);
+ print_filtered_help (include_flags, exclude_flags, any_flags,
+ opts->x_help_columns, opts, lang_mask);
+}
+
+/* Enable FDO-related flags. */
+
+static void
+enable_fdo_optimizations (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ int value)
+{
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_branch_probabilities, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_unroll_loops, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_peel_loops, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_tracer, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_value_profile_transformations,
+ value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_cp, value);
+ if (value)
+ {
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_cp_clone, 1);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, 1);
+ }
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_predictive_commoning, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_split_loops, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_unswitch_loops, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_gcse_after_reload, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_vectorize, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_slp_vectorize, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_version_loops_for_strides, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_vect_cost_model,
+ VECT_COST_MODEL_DYNAMIC);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribute_patterns,
+ value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_loop_interchange, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_unroll_jam, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_tree_loop_distribution, value);
+}
+
+/* -f{,no-}sanitize{,-recover}= suboptions. */
+const struct sanitizer_opts_s sanitizer_opts[] =
+{
+#define SANITIZER_OPT(name, flags, recover) \
+ { #name, flags, sizeof #name - 1, recover }
+ SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true),
+ SANITIZER_OPT (hwaddress, (SANITIZE_HWADDRESS | SANITIZE_USER_HWADDRESS),
+ true),
+ SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
+ true),
+ SANITIZER_OPT (kernel-hwaddress,
+ (SANITIZE_HWADDRESS | SANITIZE_KERNEL_HWADDRESS),
+ true),
+ SANITIZER_OPT (pointer-compare, SANITIZE_POINTER_COMPARE, true),
+ SANITIZER_OPT (pointer-subtract, SANITIZE_POINTER_SUBTRACT, true),
+ SANITIZER_OPT (thread, SANITIZE_THREAD, false),
+ SANITIZER_OPT (leak, SANITIZE_LEAK, false),
+ SANITIZER_OPT (shift, SANITIZE_SHIFT, true),
+ SANITIZER_OPT (shift-base, SANITIZE_SHIFT_BASE, true),
+ SANITIZER_OPT (shift-exponent, SANITIZE_SHIFT_EXPONENT, true),
+ SANITIZER_OPT (integer-divide-by-zero, SANITIZE_DIVIDE, true),
+ SANITIZER_OPT (undefined, SANITIZE_UNDEFINED, true),
+ SANITIZER_OPT (unreachable, SANITIZE_UNREACHABLE, false),
+ SANITIZER_OPT (vla-bound, SANITIZE_VLA, true),
+ SANITIZER_OPT (return, SANITIZE_RETURN, false),
+ SANITIZER_OPT (null, SANITIZE_NULL, true),
+ SANITIZER_OPT (signed-integer-overflow, SANITIZE_SI_OVERFLOW, true),
+ SANITIZER_OPT (bool, SANITIZE_BOOL, true),
+ SANITIZER_OPT (enum, SANITIZE_ENUM, true),
+ SANITIZER_OPT (float-divide-by-zero, SANITIZE_FLOAT_DIVIDE, true),
+ SANITIZER_OPT (float-cast-overflow, SANITIZE_FLOAT_CAST, true),
+ SANITIZER_OPT (bounds, SANITIZE_BOUNDS, true),
+ SANITIZER_OPT (bounds-strict, SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT, true),
+ SANITIZER_OPT (alignment, SANITIZE_ALIGNMENT, true),
+ SANITIZER_OPT (nonnull-attribute, SANITIZE_NONNULL_ATTRIBUTE, true),
+ SANITIZER_OPT (returns-nonnull-attribute, SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
+ true),
+ SANITIZER_OPT (object-size, SANITIZE_OBJECT_SIZE, true),
+ SANITIZER_OPT (vptr, SANITIZE_VPTR, true),
+ SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true),
+ SANITIZER_OPT (builtin, SANITIZE_BUILTIN, true),
+ SANITIZER_OPT (shadow-call-stack, SANITIZE_SHADOW_CALL_STACK, false),
+ SANITIZER_OPT (all, ~0U, true),
+#undef SANITIZER_OPT
+ { NULL, 0U, 0UL, false }
+};
+
+/* -fzero-call-used-regs= suboptions. */
+const struct zero_call_used_regs_opts_s zero_call_used_regs_opts[] =
+{
+#define ZERO_CALL_USED_REGS_OPT(name, flags) \
+ { #name, flags }
+ ZERO_CALL_USED_REGS_OPT (skip, zero_regs_flags::SKIP),
+ ZERO_CALL_USED_REGS_OPT (used-gpr-arg, zero_regs_flags::USED_GPR_ARG),
+ ZERO_CALL_USED_REGS_OPT (used-gpr, zero_regs_flags::USED_GPR),
+ ZERO_CALL_USED_REGS_OPT (used-arg, zero_regs_flags::USED_ARG),
+ ZERO_CALL_USED_REGS_OPT (used, zero_regs_flags::USED),
+ ZERO_CALL_USED_REGS_OPT (all-gpr-arg, zero_regs_flags::ALL_GPR_ARG),
+ ZERO_CALL_USED_REGS_OPT (all-gpr, zero_regs_flags::ALL_GPR),
+ ZERO_CALL_USED_REGS_OPT (all-arg, zero_regs_flags::ALL_ARG),
+ ZERO_CALL_USED_REGS_OPT (all, zero_regs_flags::ALL),
+#undef ZERO_CALL_USED_REGS_OPT
+ {NULL, 0U}
+};
+
+/* A struct for describing a run of chars within a string. */
+
+class string_fragment
+{
+public:
+ string_fragment (const char *start, size_t len)
+ : m_start (start), m_len (len) {}
+
+ const char *m_start;
+ size_t m_len;
+};
+
+/* Specialization of edit_distance_traits for string_fragment,
+ for use by get_closest_sanitizer_option. */
+
+template <>
+struct edit_distance_traits<const string_fragment &>
+{
+ static size_t get_length (const string_fragment &fragment)
+ {
+ return fragment.m_len;
+ }
+
+ static const char *get_string (const string_fragment &fragment)
+ {
+ return fragment.m_start;
+ }
+};
+
+/* Given ARG, an unrecognized sanitizer option, return the best
+ matching sanitizer option, or NULL if there isn't one.
+ OPTS is array of candidate sanitizer options.
+ CODE is OPT_fsanitize_ or OPT_fsanitize_recover_.
+ VALUE is non-zero for the regular form of the option, zero
+ for the "no-" form (e.g. "-fno-sanitize-recover="). */
+
+static const char *
+get_closest_sanitizer_option (const string_fragment &arg,
+ const struct sanitizer_opts_s *opts,
+ enum opt_code code, int value)
+{
+ best_match <const string_fragment &, const char*> bm (arg);
+ for (int i = 0; opts[i].name != NULL; ++i)
+ {
+ /* -fsanitize=all is not valid, so don't offer it. */
+ if (code == OPT_fsanitize_
+ && opts[i].flag == ~0U
+ && value)
+ continue;
+
+ /* For -fsanitize-recover= (and not -fno-sanitize-recover=),
+ don't offer the non-recoverable options. */
+ if (code == OPT_fsanitize_recover_
+ && !opts[i].can_recover
+ && value)
+ continue;
+
+ bm.consider (opts[i].name);
+ }
+ return bm.get_best_meaningful_candidate ();
+}
+
+/* Parse comma separated sanitizer suboptions from P for option SCODE,
+ adjust previous FLAGS and return new ones. If COMPLAIN is false,
+ don't issue diagnostics. */
+
+unsigned int
+parse_sanitizer_options (const char *p, location_t loc, int scode,
+ unsigned int flags, int value, bool complain)
+{
+ enum opt_code code = (enum opt_code) scode;
+
+ while (*p != 0)
+ {
+ size_t len, i;
+ bool found = false;
+ const char *comma = strchr (p, ',');
+
+ if (comma == NULL)
+ len = strlen (p);
+ else
+ len = comma - p;
+ if (len == 0)
+ {
+ p = comma + 1;
+ continue;
+ }
+
+ /* Check to see if the string matches an option class name. */
+ for (i = 0; sanitizer_opts[i].name != NULL; ++i)
+ if (len == sanitizer_opts[i].len
+ && memcmp (p, sanitizer_opts[i].name, len) == 0)
+ {
+ /* Handle both -fsanitize and -fno-sanitize cases. */
+ if (value && sanitizer_opts[i].flag == ~0U)
+ {
+ if (code == OPT_fsanitize_)
+ {
+ if (complain)
+ error_at (loc, "%<-fsanitize=all%> option is not valid");
+ }
+ else
+ flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK
+ | SANITIZE_UNREACHABLE | SANITIZE_RETURN
+ | SANITIZE_SHADOW_CALL_STACK);
+ }
+ else if (value)
+ {
+ /* Do not enable -fsanitize-recover=unreachable and
+ -fsanitize-recover=return if -fsanitize-recover=undefined
+ is selected. */
+ if (code == OPT_fsanitize_recover_
+ && sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
+ flags |= (SANITIZE_UNDEFINED
+ & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN));
+ else
+ flags |= sanitizer_opts[i].flag;
+ }
+ else
+ flags &= ~sanitizer_opts[i].flag;
+ found = true;
+ break;
+ }
+
+ if (! found && complain)
+ {
+ const char *hint
+ = get_closest_sanitizer_option (string_fragment (p, len),
+ sanitizer_opts, code, value);
+
+ const char *suffix;
+ if (code == OPT_fsanitize_recover_)
+ suffix = "-recover";
+ else
+ suffix = "";
+
+ if (hint)
+ error_at (loc,
+ "unrecognized argument to %<-f%ssanitize%s=%> "
+ "option: %q.*s; did you mean %qs?",
+ value ? "" : "no-",
+ suffix, (int) len, p, hint);
+ else
+ error_at (loc,
+ "unrecognized argument to %<-f%ssanitize%s=%> option: "
+ "%q.*s", value ? "" : "no-",
+ suffix, (int) len, p);
+ }
+
+ if (comma == NULL)
+ break;
+ p = comma + 1;
+ }
+ return flags;
+}
+
+/* Parse string values of no_sanitize attribute passed in VALUE.
+ Values are separated with comma. */
+
+unsigned int
+parse_no_sanitize_attribute (char *value)
+{
+ unsigned int flags = 0;
+ unsigned int i;
+ char *q = strtok (value, ",");
+
+ while (q != NULL)
+ {
+ for (i = 0; sanitizer_opts[i].name != NULL; ++i)
+ if (strcmp (sanitizer_opts[i].name, q) == 0)
+ {
+ flags |= sanitizer_opts[i].flag;
+ if (sanitizer_opts[i].flag == SANITIZE_UNDEFINED)
+ flags |= SANITIZE_UNDEFINED_NONDEFAULT;
+ break;
+ }
+
+ if (sanitizer_opts[i].name == NULL)
+ warning (OPT_Wattributes,
+ "%qs attribute directive ignored", q);
+
+ q = strtok (NULL, ",");
+ }
+
+ return flags;
+}
+
+/* Parse -fzero-call-used-regs suboptions from ARG, return the FLAGS. */
+
+unsigned int
+parse_zero_call_used_regs_options (const char *arg)
+{
+ unsigned int flags = 0;
+
+ /* Check to see if the string matches a sub-option name. */
+ for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
+ if (strcmp (arg, zero_call_used_regs_opts[i].name) == 0)
+ {
+ flags = zero_call_used_regs_opts[i].flag;
+ break;
+ }
+
+ if (!flags)
+ error ("unrecognized argument to %<-fzero-call-used-regs=%>: %qs", arg);
+
+ return flags;
+}
+
+/* Parse -falign-NAME format for a FLAG value. Return individual
+ parsed integer values into RESULT_VALUES array. If REPORT_ERROR is
+ set, print error message at LOC location. */
+
+bool
+parse_and_check_align_values (const char *flag,
+ const char *name,
+ auto_vec<unsigned> &result_values,
+ bool report_error,
+ location_t loc)
+{
+ char *str = xstrdup (flag);
+ for (char *p = strtok (str, ":"); p; p = strtok (NULL, ":"))
+ {
+ char *end;
+ int v = strtol (p, &end, 10);
+ if (*end != '\0' || v < 0)
+ {
+ if (report_error)
+ error_at (loc, "invalid arguments for %<-falign-%s%> option: %qs",
+ name, flag);
+
+ return false;
+ }
+
+ result_values.safe_push ((unsigned)v);
+ }
+
+ free (str);
+
+ /* Check that we have a correct number of values. */
+ if (result_values.is_empty () || result_values.length () > 4)
+ {
+ if (report_error)
+ error_at (loc, "invalid number of arguments for %<-falign-%s%> "
+ "option: %qs", name, flag);
+ return false;
+ }
+
+ for (unsigned i = 0; i < result_values.length (); i++)
+ if (result_values[i] > MAX_CODE_ALIGN_VALUE)
+ {
+ if (report_error)
+ error_at (loc, "%<-falign-%s%> is not between 0 and %d",
+ name, MAX_CODE_ALIGN_VALUE);
+ return false;
+ }
+
+ return true;
+}
+
+/* Check that alignment value FLAG for -falign-NAME is valid at a given
+ location LOC. OPT_STR points to the stored -falign-NAME=argument and
+ OPT_FLAG points to the associated -falign-NAME on/off flag. */
+
+static void
+check_alignment_argument (location_t loc, const char *flag, const char *name,
+ int *opt_flag, const char **opt_str)
+{
+ auto_vec<unsigned> align_result;
+ parse_and_check_align_values (flag, name, align_result, true, loc);
+
+ if (align_result.length() >= 1 && align_result[0] == 0)
+ {
+ *opt_flag = 1;
+ *opt_str = NULL;
+ }
+}
+
+/* Parse argument of -fpatchable-function-entry option ARG and store
+ corresponding values to PATCH_AREA_SIZE and PATCH_AREA_START.
+ If REPORT_ERROR is set to true, generate error for a problematic
+ option arguments. */
+
+void
+parse_and_check_patch_area (const char *arg, bool report_error,
+ HOST_WIDE_INT *patch_area_size,
+ HOST_WIDE_INT *patch_area_start)
+{
+ *patch_area_size = 0;
+ *patch_area_start = 0;
+
+ if (arg == NULL)
+ return;
+
+ char *patch_area_arg = xstrdup (arg);
+ char *comma = strchr (patch_area_arg, ',');
+ if (comma)
+ {
+ *comma = '\0';
+ *patch_area_size = integral_argument (patch_area_arg);
+ *patch_area_start = integral_argument (comma + 1);
+ }
+ else
+ *patch_area_size = integral_argument (patch_area_arg);
+
+ if (*patch_area_size < 0
+ || *patch_area_size > USHRT_MAX
+ || *patch_area_start < 0
+ || *patch_area_start > USHRT_MAX
+ || *patch_area_size < *patch_area_start)
+ if (report_error)
+ error ("invalid arguments for %<-fpatchable-function-entry%>");
+
+ free (patch_area_arg);
+}
+
+/* Print help when OPT__help_ is set. */
+
+void
+print_help (struct gcc_options *opts, unsigned int lang_mask,
+ const char *help_option_argument)
+{
+ const char *a = help_option_argument;
+ unsigned int include_flags = 0;
+ /* Note - by default we include undocumented options when listing
+ specific classes. If you only want to see documented options
+ then add ",^undocumented" to the --help= option. E.g.:
+
+ --help=target,^undocumented */
+ unsigned int exclude_flags = 0;
+
+ if (lang_mask == CL_DRIVER)
+ return;
+
+ /* Walk along the argument string, parsing each word in turn.
+ The format is:
+ arg = [^]{word}[,{arg}]
+ word = {optimizers|target|warnings|undocumented|
+ params|common|<language>} */
+ while (*a != 0)
+ {
+ static const struct
+ {
+ const char *string;
+ unsigned int flag;
+ }
+ specifics[] =
+ {
+ { "optimizers", CL_OPTIMIZATION },
+ { "target", CL_TARGET },
+ { "warnings", CL_WARNING },
+ { "undocumented", CL_UNDOCUMENTED },
+ { "params", CL_PARAMS },
+ { "joined", CL_JOINED },
+ { "separate", CL_SEPARATE },
+ { "common", CL_COMMON },
+ { NULL, 0 }
+ };
+ unsigned int *pflags;
+ const char *comma;
+ unsigned int lang_flag, specific_flag;
+ unsigned int len;
+ unsigned int i;
+
+ if (*a == '^')
+ {
+ ++a;
+ if (*a == '\0')
+ {
+ error ("missing argument to %qs", "--help=^");
+ break;
+ }
+ pflags = &exclude_flags;
+ }
+ else
+ pflags = &include_flags;
+
+ comma = strchr (a, ',');
+ if (comma == NULL)
+ len = strlen (a);
+ else
+ len = comma - a;
+ if (len == 0)
+ {
+ a = comma + 1;
+ continue;
+ }
+
+ /* Check to see if the string matches an option class name. */
+ for (i = 0, specific_flag = 0; specifics[i].string != NULL; i++)
+ if (strncasecmp (a, specifics[i].string, len) == 0)
+ {
+ specific_flag = specifics[i].flag;
+ break;
+ }
+
+ /* Check to see if the string matches a language name.
+ Note - we rely upon the alpha-sorted nature of the entries in
+ the lang_names array, specifically that shorter names appear
+ before their longer variants. (i.e. C before C++). That way
+ when we are attempting to match --help=c for example we will
+ match with C first and not C++. */
+ for (i = 0, lang_flag = 0; i < cl_lang_count; i++)
+ if (strncasecmp (a, lang_names[i], len) == 0)
+ {
+ lang_flag = 1U << i;
+ break;
+ }
+
+ if (specific_flag != 0)
+ {
+ if (lang_flag == 0)
+ *pflags |= specific_flag;
+ else
+ {
+ /* The option's argument matches both the start of a
+ language name and the start of an option class name.
+ We have a special case for when the user has
+ specified "--help=c", but otherwise we have to issue
+ a warning. */
+ if (strncasecmp (a, "c", len) == 0)
+ *pflags |= lang_flag;
+ else
+ warning (0,
+ "%<--help%> argument %q.*s is ambiguous, "
+ "please be more specific",
+ len, a);
+ }
+ }
+ else if (lang_flag != 0)
+ *pflags |= lang_flag;
+ else
+ warning (0,
+ "unrecognized argument to %<--help=%> option: %q.*s",
+ len, a);
+
+ if (comma == NULL)
+ break;
+ a = comma + 1;
+ }
+
+ /* We started using PerFunction/Optimization for parameters and
+ a warning. We should exclude these from optimization options. */
+ if (include_flags & CL_OPTIMIZATION)
+ exclude_flags |= CL_WARNING;
+ if (!(include_flags & CL_PARAMS))
+ exclude_flags |= CL_PARAMS;
+
+ if (include_flags)
+ print_specific_help (include_flags, exclude_flags, 0, opts,
+ lang_mask);
+}
+
+/* Handle target- and language-independent options. Return zero to
+ generate an "unknown option" message. Only options that need
+ extra handling need to be listed here; if you simply want
+ DECODED->value assigned to a variable, it happens automatically. */
+
+bool
+common_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask, int kind ATTRIBUTE_UNUSED,
+ location_t loc,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc,
+ void (*target_option_override_hook) (void))
+{
+ size_t scode = decoded->opt_index;
+ const char *arg = decoded->arg;
+ HOST_WIDE_INT value = decoded->value;
+ enum opt_code code = (enum opt_code) scode;
+
+ gcc_assert (decoded->canonical_option_num_elements <= 2);
+
+ switch (code)
+ {
+ case OPT__help:
+ {
+ unsigned int all_langs_mask = (1U << cl_lang_count) - 1;
+ unsigned int undoc_mask;
+ unsigned int i;
+
+ if (lang_mask == CL_DRIVER)
+ break;
+
+ undoc_mask = ((opts->x_verbose_flag | opts->x_extra_warnings)
+ ? 0
+ : CL_UNDOCUMENTED);
+ target_option_override_hook ();
+ /* First display any single language specific options. */
+ for (i = 0; i < cl_lang_count; i++)
+ print_specific_help
+ (1U << i, (all_langs_mask & (~ (1U << i))) | undoc_mask, 0, opts,
+ lang_mask);
+ /* Next display any multi language specific options. */
+ print_specific_help (0, undoc_mask, all_langs_mask, opts, lang_mask);
+ /* Then display any remaining, non-language options. */
+ for (i = CL_MIN_OPTION_CLASS; i <= CL_MAX_OPTION_CLASS; i <<= 1)
+ if (i != CL_DRIVER)
+ print_specific_help (i, undoc_mask, 0, opts, lang_mask);
+ opts->x_exit_after_options = true;
+ break;
+ }
+
+ case OPT__target_help:
+ if (lang_mask == CL_DRIVER)
+ break;
+
+ target_option_override_hook ();
+ print_specific_help (CL_TARGET, 0, 0, opts, lang_mask);
+ opts->x_exit_after_options = true;
+ break;
+
+ case OPT__help_:
+ {
+ help_option_arguments.safe_push (arg);
+ opts->x_exit_after_options = true;
+ break;
+ }
+
+ case OPT__version:
+ if (lang_mask == CL_DRIVER)
+ break;
+
+ opts->x_exit_after_options = true;
+ break;
+
+ case OPT__completion_:
+ break;
+
+ case OPT_fsanitize_:
+ opts->x_flag_sanitize
+ = parse_sanitizer_options (arg, loc, code,
+ opts->x_flag_sanitize, value, true);
+
+ /* Kernel ASan implies normal ASan but does not yet support
+ all features. */
+ if (opts->x_flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+ {
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_asan_instrumentation_with_call_threshold,
+ 0);
+ SET_OPTION_IF_UNSET (opts, opts_set, param_asan_globals, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set, param_asan_stack, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set, param_asan_protect_allocas, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set, param_asan_use_after_return, 0);
+ }
+ if (opts->x_flag_sanitize & SANITIZE_KERNEL_HWADDRESS)
+ {
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_hwasan_instrument_stack, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_hwasan_random_frame_tag, 0);
+ SET_OPTION_IF_UNSET (opts, opts_set,
+ param_hwasan_instrument_allocas, 0);
+ }
+ break;
+
+ case OPT_fsanitize_recover_:
+ opts->x_flag_sanitize_recover
+ = parse_sanitizer_options (arg, loc, code,
+ opts->x_flag_sanitize_recover, value, true);
+ break;
+
+ case OPT_fasan_shadow_offset_:
+ /* Deferred. */
+ break;
+
+ case OPT_fsanitize_address_use_after_scope:
+ opts->x_flag_sanitize_address_use_after_scope = value;
+ break;
+
+ case OPT_fsanitize_recover:
+ if (value)
+ opts->x_flag_sanitize_recover
+ |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT)
+ & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN);
+ else
+ opts->x_flag_sanitize_recover
+ &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
+ break;
+
+ case OPT_O:
+ case OPT_Os:
+ case OPT_Ofast:
+ case OPT_Og:
+ case OPT_Oz:
+ /* Currently handled in a prescan. */
+ break;
+
+ case OPT_Wattributes_:
+ if (lang_mask == CL_DRIVER)
+ break;
+
+ if (value)
+ {
+ error_at (loc, "arguments ignored for %<-Wattributes=%>; use "
+ "%<-Wno-attributes=%> instead");
+ break;
+ }
+ else if (arg[strlen (arg) - 1] == ',')
+ {
+ error_at (loc, "trailing %<,%> in arguments for "
+ "%<-Wno-attributes=%>");
+ break;
+ }
+
+ add_comma_separated_to_vector (&opts->x_flag_ignored_attributes, arg);
+ break;
+
+ case OPT_Werror:
+ dc->warning_as_error_requested = value;
+ break;
+
+ case OPT_Werror_:
+ if (lang_mask == CL_DRIVER)
+ break;
+
+ enable_warning_as_error (arg, value, lang_mask, handlers,
+ opts, opts_set, loc, dc);
+ break;
+
+ case OPT_Wfatal_errors:
+ dc->fatal_errors = value;
+ break;
+
+ case OPT_Wstack_usage_:
+ opts->x_flag_stack_usage_info = value != -1;
+ break;
+
+ case OPT_Wstrict_aliasing:
+ set_Wstrict_aliasing (opts, value);
+ break;
+
+ case OPT_Wstrict_overflow:
+ opts->x_warn_strict_overflow = (value
+ ? (int) WARN_STRICT_OVERFLOW_CONDITIONAL
+ : 0);
+ break;
+
+ case OPT_Wsystem_headers:
+ dc->dc_warn_system_headers = value;
+ break;
+
+ case OPT_aux_info:
+ opts->x_flag_gen_aux_info = 1;
+ break;
+
+ case OPT_d:
+ decode_d_option (arg, opts, loc, dc);
+ break;
+
+ case OPT_fcall_used_:
+ case OPT_fcall_saved_:
+ /* Deferred. */
+ break;
+
+ case OPT_fdbg_cnt_:
+ /* Deferred. */
+ break;
+
+ case OPT_fdebug_prefix_map_:
+ case OPT_ffile_prefix_map_:
+ case OPT_fprofile_prefix_map_:
+ /* Deferred. */
+ break;
+
+ case OPT_fcallgraph_info:
+ opts->x_flag_callgraph_info = CALLGRAPH_INFO_NAKED;
+ break;
+
+ case OPT_fcallgraph_info_:
+ {
+ char *my_arg, *p;
+ my_arg = xstrdup (arg);
+ p = strtok (my_arg, ",");
+ while (p)
+ {
+ if (strcmp (p, "su") == 0)
+ {
+ opts->x_flag_callgraph_info |= CALLGRAPH_INFO_STACK_USAGE;
+ opts->x_flag_stack_usage_info = true;
+ }
+ else if (strcmp (p, "da") == 0)
+ opts->x_flag_callgraph_info |= CALLGRAPH_INFO_DYNAMIC_ALLOC;
+ else
+ return 0;
+ p = strtok (NULL, ",");
+ }
+ free (my_arg);
+ }
+ break;
+
+ case OPT_fdiagnostics_show_location_:
+ diagnostic_prefixing_rule (dc) = (diagnostic_prefixing_rule_t) value;
+ break;
+
+ case OPT_fdiagnostics_show_caret:
+ dc->show_caret = value;
+ break;
+
+ case OPT_fdiagnostics_show_labels:
+ dc->show_labels_p = value;
+ break;
+
+ case OPT_fdiagnostics_show_line_numbers:
+ dc->show_line_numbers_p = value;
+ break;
+
+ case OPT_fdiagnostics_color_:
+ diagnostic_color_init (dc, value);
+ break;
+
+ case OPT_fdiagnostics_urls_:
+ diagnostic_urls_init (dc, value);
+ break;
+
+ case OPT_fdiagnostics_format_:
+ diagnostic_output_format_init (dc,
+ (enum diagnostics_output_format)value);
+ break;
+
+ case OPT_fdiagnostics_parseable_fixits:
+ dc->extra_output_kind = (value
+ ? EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
+ : EXTRA_DIAGNOSTIC_OUTPUT_none);
+ break;
+
+ case OPT_fdiagnostics_column_unit_:
+ dc->column_unit = (enum diagnostics_column_unit)value;
+ break;
+
+ case OPT_fdiagnostics_column_origin_:
+ dc->column_origin = value;
+ break;
+
+ case OPT_fdiagnostics_escape_format_:
+ dc->escape_format = (enum diagnostics_escape_format)value;
+ break;
+
+ case OPT_fdiagnostics_show_cwe:
+ dc->show_cwe = value;
+ break;
+
+ case OPT_fdiagnostics_path_format_:
+ dc->path_format = (enum diagnostic_path_format)value;
+ break;
+
+ case OPT_fdiagnostics_show_path_depths:
+ dc->show_path_depths = value;
+ break;
+
+ case OPT_fdiagnostics_show_option:
+ dc->show_option_requested = value;
+ break;
+
+ case OPT_fdiagnostics_minimum_margin_width_:
+ dc->min_margin_width = value;
+ break;
+
+ case OPT_fdump_:
+ /* Deferred. */
+ break;
+
+ case OPT_ffast_math:
+ set_fast_math_flags (opts, value);
+ break;
+
+ case OPT_funsafe_math_optimizations:
+ set_unsafe_math_optimizations_flags (opts, value);
+ break;
+
+ case OPT_ffixed_:
+ /* Deferred. */
+ break;
+
+ case OPT_finline_limit_:
+ SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_single,
+ value / 2);
+ SET_OPTION_IF_UNSET (opts, opts_set, param_max_inline_insns_auto,
+ value / 2);
+ break;
+
+ case OPT_finstrument_functions_exclude_function_list_:
+ add_comma_separated_to_vector
+ (&opts->x_flag_instrument_functions_exclude_functions, arg);
+ break;
+
+ case OPT_finstrument_functions_exclude_file_list_:
+ add_comma_separated_to_vector
+ (&opts->x_flag_instrument_functions_exclude_files, arg);
+ break;
+
+ case OPT_fmessage_length_:
+ pp_set_line_maximum_length (dc->printer, value);
+ diagnostic_set_caret_max_width (dc, value);
+ break;
+
+ case OPT_fopt_info:
+ case OPT_fopt_info_:
+ /* Deferred. */
+ break;
+
+ case OPT_foffload_options_:
+ /* Deferred. */
+ break;
+
+ case OPT_foffload_abi_:
+#ifdef ACCEL_COMPILER
+ /* Handled in the 'mkoffload's. */
+#else
+ error_at (loc, "%<-foffload-abi%> option can be specified only for "
+ "offload compiler");
+#endif
+ break;
+
+ case OPT_fpack_struct_:
+ if (value <= 0 || (value & (value - 1)) || value > 16)
+ error_at (loc,
+ "structure alignment must be a small power of two, not %wu",
+ value);
+ else
+ opts->x_initial_max_fld_align = value;
+ break;
+
+ case OPT_fplugin_:
+ case OPT_fplugin_arg_:
+ /* Deferred. */
+ break;
+
+ case OPT_fprofile_use_:
+ opts->x_profile_data_prefix = xstrdup (arg);
+ opts->x_flag_profile_use = true;
+ value = true;
+ /* No break here - do -fprofile-use processing. */
+ /* FALLTHRU */
+ case OPT_fprofile_use:
+ enable_fdo_optimizations (opts, opts_set, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_reorder_functions,
+ value);
+ /* Indirect call profiling should do all useful transformations
+ speculative devirtualization does. */
+ if (opts->x_flag_value_profile_transformations)
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_devirtualize_speculatively,
+ false);
+ break;
+
+ case OPT_fauto_profile_:
+ opts->x_auto_profile_file = xstrdup (arg);
+ opts->x_flag_auto_profile = true;
+ value = true;
+ /* No break here - do -fauto-profile processing. */
+ /* FALLTHRU */
+ case OPT_fauto_profile:
+ enable_fdo_optimizations (opts, opts_set, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_correction, value);
+ break;
+
+ case OPT_fprofile_generate_:
+ opts->x_profile_data_prefix = xstrdup (arg);
+ value = true;
+ /* No break here - do -fprofile-generate processing. */
+ /* FALLTHRU */
+ case OPT_fprofile_generate:
+ SET_OPTION_IF_UNSET (opts, opts_set, profile_arc_flag, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_profile_values, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_inline_functions, value);
+ SET_OPTION_IF_UNSET (opts, opts_set, flag_ipa_bit_cp, value);
+ break;
+
+ case OPT_fprofile_info_section:
+ opts->x_profile_info_section = ".gcov_info";
+ break;
+
+ case OPT_fpatchable_function_entry_:
+ {
+ HOST_WIDE_INT patch_area_size, patch_area_start;
+ parse_and_check_patch_area (arg, true, &patch_area_size,
+ &patch_area_start);
+ }
+ break;
+
+ case OPT_ftree_vectorize:
+ /* Automatically sets -ftree-loop-vectorize and
+ -ftree-slp-vectorize. Nothing more to do here. */
+ break;
+ case OPT_fzero_call_used_regs_:
+ opts->x_flag_zero_call_used_regs
+ = parse_zero_call_used_regs_options (arg);
+ break;
+
+ case OPT_fshow_column:
+ dc->show_column = value;
+ break;
+
+ case OPT_frandom_seed:
+ /* The real switch is -fno-random-seed. */
+ if (value)
+ return false;
+ /* Deferred. */
+ break;
+
+ case OPT_frandom_seed_:
+ /* Deferred. */
+ break;
+
+ case OPT_fsched_verbose_:
+#ifdef INSN_SCHEDULING
+ /* Handled with Var in common.opt. */
+ break;
+#else
+ return false;
+#endif
+
+ case OPT_fsched_stalled_insns_:
+ opts->x_flag_sched_stalled_insns = value;
+ if (opts->x_flag_sched_stalled_insns == 0)
+ opts->x_flag_sched_stalled_insns = -1;
+ break;
+
+ case OPT_fsched_stalled_insns_dep_:
+ opts->x_flag_sched_stalled_insns_dep = value;
+ break;
+
+ case OPT_fstack_check_:
+ if (!strcmp (arg, "no"))
+ opts->x_flag_stack_check = NO_STACK_CHECK;
+ else if (!strcmp (arg, "generic"))
+ /* This is the old stack checking method. */
+ opts->x_flag_stack_check = STACK_CHECK_BUILTIN
+ ? FULL_BUILTIN_STACK_CHECK
+ : GENERIC_STACK_CHECK;
+ else if (!strcmp (arg, "specific"))
+ /* This is the new stack checking method. */
+ opts->x_flag_stack_check = STACK_CHECK_BUILTIN
+ ? FULL_BUILTIN_STACK_CHECK
+ : STACK_CHECK_STATIC_BUILTIN
+ ? STATIC_BUILTIN_STACK_CHECK
+ : GENERIC_STACK_CHECK;
+ else
+ warning_at (loc, 0, "unknown stack check parameter %qs", arg);
+ break;
+
+ case OPT_fstack_limit:
+ /* The real switch is -fno-stack-limit. */
+ if (value)
+ return false;
+ /* Deferred. */
+ break;
+
+ case OPT_fstack_limit_register_:
+ case OPT_fstack_limit_symbol_:
+ /* Deferred. */
+ break;
+
+ case OPT_fstack_usage:
+ opts->x_flag_stack_usage = value;
+ opts->x_flag_stack_usage_info = value != 0;
+ break;
+
+ case OPT_g:
+ set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
+ loc);
+ break;
+
+ case OPT_gbtf:
+ set_debug_level (BTF_DEBUG, false, arg, opts, opts_set, loc);
+ /* set the debug level to level 2, but if already at level 3,
+ don't lower it. */
+ if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
+ opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
+ break;
+
+ case OPT_gctf:
+ set_debug_level (CTF_DEBUG, false, arg, opts, opts_set, loc);
+ /* CTF generation feeds off DWARF dies. For optimal CTF, switch debug
+ info level to 2. If off or at level 1, set it to level 2, but if
+ already at level 3, don't lower it. */
+ if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL
+ && opts->x_ctf_debug_info_level > CTFINFO_LEVEL_NONE)
+ opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
+ break;
+
+ case OPT_gdwarf:
+ if (arg && strlen (arg) != 0)
+ {
+ error_at (loc, "%<-gdwarf%s%> is ambiguous; "
+ "use %<-gdwarf-%s%> for DWARF version "
+ "or %<-gdwarf%> %<-g%s%> for debug level", arg, arg, arg);
+ break;
+ }
+ else
+ value = opts->x_dwarf_version;
+
+ /* FALLTHRU */
+ case OPT_gdwarf_:
+ if (value < 2 || value > 5)
+ error_at (loc, "dwarf version %wu is not supported", value);
+ else
+ opts->x_dwarf_version = value;
+ set_debug_level (DWARF2_DEBUG, false, "", opts, opts_set, loc);
+ break;
+
+ case OPT_ggdb:
+ 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. */
+ break;
+
+ case OPT_pedantic_errors:
+ dc->pedantic_errors = 1;
+ control_warning_option (OPT_Wpedantic, DK_ERROR, NULL, value,
+ loc, lang_mask,
+ handlers, opts, opts_set,
+ dc);
+ break;
+
+ case OPT_flto:
+ opts->x_flag_lto = value ? "" : NULL;
+ break;
+
+ case OPT_flto_:
+ if (strcmp (arg, "none") != 0
+ && strcmp (arg, "jobserver") != 0
+ && strcmp (arg, "auto") != 0
+ && atoi (arg) == 0)
+ error_at (loc,
+ "unrecognized argument to %<-flto=%> option: %qs", arg);
+ break;
+
+ case OPT_w:
+ dc->dc_inhibit_warnings = true;
+ break;
+
+ case OPT_fmax_errors_:
+ dc->max_errors = value;
+ break;
+
+ case OPT_fuse_ld_bfd:
+ case OPT_fuse_ld_gold:
+ case OPT_fuse_ld_lld:
+ case OPT_fuse_ld_mold:
+ case OPT_fuse_linker_plugin:
+ /* No-op. Used by the driver and passed to us because it starts with f.*/
+ break;
+
+ case OPT_fwrapv:
+ if (value)
+ opts->x_flag_trapv = 0;
+ break;
+
+ case OPT_ftrapv:
+ if (value)
+ opts->x_flag_wrapv = 0;
+ break;
+
+ case OPT_fstrict_overflow:
+ opts->x_flag_wrapv = !value;
+ opts->x_flag_wrapv_pointer = !value;
+ if (!value)
+ opts->x_flag_trapv = 0;
+ break;
+
+ case OPT_fipa_icf:
+ opts->x_flag_ipa_icf_functions = value;
+ opts->x_flag_ipa_icf_variables = value;
+ break;
+
+ case OPT_falign_loops_:
+ check_alignment_argument (loc, arg, "loops",
+ &opts->x_flag_align_loops,
+ &opts->x_str_align_loops);
+ break;
+
+ case OPT_falign_jumps_:
+ check_alignment_argument (loc, arg, "jumps",
+ &opts->x_flag_align_jumps,
+ &opts->x_str_align_jumps);
+ break;
+
+ case OPT_falign_labels_:
+ check_alignment_argument (loc, arg, "labels",
+ &opts->x_flag_align_labels,
+ &opts->x_str_align_labels);
+ break;
+
+ case OPT_falign_functions_:
+ check_alignment_argument (loc, arg, "functions",
+ &opts->x_flag_align_functions,
+ &opts->x_str_align_functions);
+ break;
+
+ case OPT_ftabstop_:
+ /* It is documented that we silently ignore silly values. */
+ if (value >= 1 && value <= 100)
+ dc->tabstop = value;
+ break;
+
+ case OPT_freport_bug:
+ dc->report_bug = value;
+ break;
+
+ default:
+ /* If the flag was handled in a standard way, assume the lack of
+ processing here is intentional. */
+ gcc_assert (option_flag_var (scode, opts));
+ break;
+ }
+
+ common_handle_option_auto (opts, opts_set, decoded, lang_mask, kind,
+ loc, handlers, dc);
+ return true;
+}
+
+/* Used to set the level of strict aliasing warnings in OPTS,
+ when no level is specified (i.e., when -Wstrict-aliasing, and not
+ -Wstrict-aliasing=level was given).
+ ONOFF is assumed to take value 1 when -Wstrict-aliasing is specified,
+ and 0 otherwise. After calling this function, wstrict_aliasing will be
+ set to the default value of -Wstrict_aliasing=level, currently 3. */
+static void
+set_Wstrict_aliasing (struct gcc_options *opts, int onoff)
+{
+ gcc_assert (onoff == 0 || onoff == 1);
+ if (onoff != 0)
+ opts->x_warn_strict_aliasing = 3;
+ else
+ opts->x_warn_strict_aliasing = 0;
+}
+
+/* The following routines are useful in setting all the flags that
+ -ffast-math and -fno-fast-math imply. */
+static void
+set_fast_math_flags (struct gcc_options *opts, int set)
+{
+ if (!opts->frontend_set_flag_unsafe_math_optimizations)
+ {
+ opts->x_flag_unsafe_math_optimizations = set;
+ set_unsafe_math_optimizations_flags (opts, set);
+ }
+ if (!opts->frontend_set_flag_finite_math_only)
+ opts->x_flag_finite_math_only = set;
+ if (!opts->frontend_set_flag_errno_math)
+ opts->x_flag_errno_math = !set;
+ if (set)
+ {
+ if (opts->frontend_set_flag_excess_precision == EXCESS_PRECISION_DEFAULT)
+ opts->x_flag_excess_precision
+ = set ? EXCESS_PRECISION_FAST : EXCESS_PRECISION_DEFAULT;
+ if (!opts->frontend_set_flag_signaling_nans)
+ opts->x_flag_signaling_nans = 0;
+ if (!opts->frontend_set_flag_rounding_math)
+ opts->x_flag_rounding_math = 0;
+ if (!opts->frontend_set_flag_cx_limited_range)
+ opts->x_flag_cx_limited_range = 1;
+ }
+}
+
+/* When -funsafe-math-optimizations is set the following
+ flags are set as well. */
+static void
+set_unsafe_math_optimizations_flags (struct gcc_options *opts, int set)
+{
+ if (!opts->frontend_set_flag_trapping_math)
+ opts->x_flag_trapping_math = !set;
+ if (!opts->frontend_set_flag_signed_zeros)
+ opts->x_flag_signed_zeros = !set;
+ if (!opts->frontend_set_flag_associative_math)
+ opts->x_flag_associative_math = set;
+ if (!opts->frontend_set_flag_reciprocal_math)
+ opts->x_flag_reciprocal_math = set;
+}
+
+/* Return true iff flags in OPTS are set as if -ffast-math. */
+bool
+fast_math_flags_set_p (const struct gcc_options *opts)
+{
+ return (!opts->x_flag_trapping_math
+ && opts->x_flag_unsafe_math_optimizations
+ && opts->x_flag_finite_math_only
+ && !opts->x_flag_signed_zeros
+ && !opts->x_flag_errno_math
+ && opts->x_flag_excess_precision == EXCESS_PRECISION_FAST);
+}
+
+/* Return true iff flags are set as if -ffast-math but using the flags stored
+ in the struct cl_optimization structure. */
+bool
+fast_math_flags_struct_set_p (struct cl_optimization *opt)
+{
+ return (!opt->x_flag_trapping_math
+ && opt->x_flag_unsafe_math_optimizations
+ && opt->x_flag_finite_math_only
+ && !opt->x_flag_signed_zeros
+ && !opt->x_flag_errno_math);
+}
+
+/* Handle a debug output -g switch for options OPTS
+ (OPTS_SET->x_write_symbols storing whether a debug format was passed
+ explicitly), location LOC. EXTENDED is true or false to support
+ extended output (2 is special and means "-ggdb" was given). */
+static void
+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)
+ {
+ opts->x_write_symbols = PREFERRED_DEBUGGING_TYPE;
+
+ if (extended == 2)
+ {
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
+ if (opts->x_write_symbols & CTF_DEBUG)
+ 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
+ }
+
+ if (opts->x_write_symbols == NO_DEBUG)
+ warning_at (loc, 0, "target system does not support debug output");
+ }
+ else if ((opts->x_write_symbols & CTF_DEBUG)
+ || (opts->x_write_symbols & BTF_DEBUG))
+ {
+ opts->x_write_symbols |= DWARF2_DEBUG;
+ opts_set->x_write_symbols |= DWARF2_DEBUG;
+ }
+ }
+ else
+ {
+ /* Make and retain the choice if both CTF and DWARF debug info are to
+ be generated. */
+ if (((dinfo == DWARF2_DEBUG) || (dinfo == CTF_DEBUG))
+ && ((opts->x_write_symbols == (DWARF2_DEBUG|CTF_DEBUG))
+ || (opts->x_write_symbols == DWARF2_DEBUG)
+ || (opts->x_write_symbols == CTF_DEBUG)))
+ {
+ opts->x_write_symbols |= dinfo;
+ opts_set->x_write_symbols |= dinfo;
+ }
+ /* However, CTF and BTF are not allowed together at this time. */
+ else if (((dinfo == DWARF2_DEBUG) || (dinfo == BTF_DEBUG))
+ && ((opts->x_write_symbols == (DWARF2_DEBUG|BTF_DEBUG))
+ || (opts->x_write_symbols == DWARF2_DEBUG)
+ || (opts->x_write_symbols == BTF_DEBUG)))
+ {
+ opts->x_write_symbols |= dinfo;
+ opts_set->x_write_symbols |= dinfo;
+ }
+ else
+ {
+ /* Does it conflict with an already selected debug format? */
+ if (opts_set->x_write_symbols != NO_DEBUG
+ && opts->x_write_symbols != NO_DEBUG
+ && dinfo != opts->x_write_symbols)
+ {
+ gcc_assert (debug_set_count (dinfo) <= 1);
+ error_at (loc, "debug format %qs conflicts with prior selection",
+ debug_type_names[debug_set_to_format (dinfo)]);
+ }
+ opts->x_write_symbols = dinfo;
+ opts_set->x_write_symbols = dinfo;
+ }
+ }
+
+ if (dinfo != BTF_DEBUG)
+ {
+ /* A debug flag without a level defaults to level 2.
+ If off or at level 1, set it to level 2, but if already
+ at level 3, don't lower it. */
+ if (*arg == '\0')
+ {
+ if (dinfo == CTF_DEBUG)
+ opts->x_ctf_debug_info_level = CTFINFO_LEVEL_NORMAL;
+ else if (opts->x_debug_info_level < DINFO_LEVEL_NORMAL)
+ opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
+ }
+ else
+ {
+ int argval = integral_argument (arg);
+ if (argval == -1)
+ error_at (loc, "unrecognized debug output level %qs", arg);
+ else if (argval > 3)
+ error_at (loc, "debug output level %qs is too high", arg);
+ else
+ {
+ if (dinfo == CTF_DEBUG)
+ opts->x_ctf_debug_info_level
+ = (enum ctf_debug_info_levels) argval;
+ else
+ opts->x_debug_info_level = (enum debug_info_levels) argval;
+ }
+ }
+ }
+ else if (*arg != '\0')
+ error_at (loc, "unrecognized btf debug output level %qs", arg);
+}
+
+/* Arrange to dump core on error for diagnostic context DC. (The
+ regular error message is still printed first, except in the case of
+ abort ().) */
+
+static void
+setup_core_dumping (diagnostic_context *dc)
+{
+#ifdef SIGABRT
+ signal (SIGABRT, SIG_DFL);
+#endif
+#if defined(HAVE_SETRLIMIT)
+ {
+ struct rlimit rlim;
+ if (getrlimit (RLIMIT_CORE, &rlim) != 0)
+ fatal_error (input_location, "getting core file size maximum limit: %m");
+ rlim.rlim_cur = rlim.rlim_max;
+ if (setrlimit (RLIMIT_CORE, &rlim) != 0)
+ fatal_error (input_location,
+ "setting core file size limit to maximum: %m");
+ }
+#endif
+ diagnostic_abort_on_error (dc);
+}
+
+/* Parse a -d<ARG> command line switch for OPTS, location LOC,
+ diagnostic context DC. */
+
+static void
+decode_d_option (const char *arg, struct gcc_options *opts,
+ location_t loc, diagnostic_context *dc)
+{
+ int c;
+
+ while (*arg)
+ switch (c = *arg++)
+ {
+ case 'A':
+ opts->x_flag_debug_asm = 1;
+ break;
+ case 'p':
+ opts->x_flag_print_asm_name = 1;
+ break;
+ case 'P':
+ opts->x_flag_dump_rtl_in_asm = 1;
+ opts->x_flag_print_asm_name = 1;
+ break;
+ case 'x':
+ opts->x_rtl_dump_and_exit = 1;
+ break;
+ case 'D': /* These are handled by the preprocessor. */
+ case 'I':
+ case 'M':
+ case 'N':
+ case 'U':
+ break;
+ case 'H':
+ setup_core_dumping (dc);
+ break;
+ case 'a':
+ opts->x_flag_dump_all_passed = true;
+ break;
+
+ default:
+ warning_at (loc, 0, "unrecognized gcc debugging option: %c", c);
+ break;
+ }
+}
+
+/* Enable (or disable if VALUE is 0) a warning option ARG (language
+ mask LANG_MASK, option handlers HANDLERS) as an error for option
+ structures OPTS and OPTS_SET, diagnostic context DC (possibly
+ NULL), location LOC. This is used by -Werror=. */
+
+static void
+enable_warning_as_error (const char *arg, int value, unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ location_t loc, diagnostic_context *dc)
+{
+ char *new_option;
+ int option_index;
+
+ new_option = XNEWVEC (char, strlen (arg) + 2);
+ new_option[0] = 'W';
+ strcpy (new_option + 1, arg);
+ option_index = find_opt (new_option, lang_mask);
+ if (option_index == OPT_SPECIAL_unknown)
+ {
+ // sdcpp option_proposer op;
+ const char *hint = 0; // sdcpp op.suggest_option (new_option);
+ if (hint)
+ error_at (loc, "%<-W%serror=%s%>: no option %<-%s%>;"
+ " did you mean %<-%s%>?", value ? "" : "no-",
+ arg, new_option, hint);
+ else
+ error_at (loc, "%<-W%serror=%s%>: no option %<-%s%>",
+ value ? "" : "no-", arg, new_option);
+ }
+ else if (!(cl_options[option_index].flags & CL_WARNING))
+ error_at (loc, "%<-Werror=%s%>: %<-%s%> is not an option that "
+ "controls warnings", arg, new_option);
+ else
+ {
+ const diagnostic_t kind = value ? DK_ERROR : DK_WARNING;
+ const char *arg = NULL;
+
+ if (cl_options[option_index].flags & CL_JOINED)
+ arg = new_option + cl_options[option_index].opt_len;
+ control_warning_option (option_index, (int) kind, arg, value,
+ loc, lang_mask,
+ handlers, opts, opts_set, dc);
+ }
+ free (new_option);
+}
+
+/* Return malloced memory for the name of the option OPTION_INDEX
+ which enabled a diagnostic (context CONTEXT), originally of type
+ ORIG_DIAG_KIND but possibly converted to DIAG_KIND by options such
+ as -Werror. */
+
+char *
+option_name (diagnostic_context *context, int option_index,
+ diagnostic_t orig_diag_kind, diagnostic_t diag_kind)
+{
+ if (option_index)
+ {
+ /* A warning classified as an error. */
+ if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN)
+ && diag_kind == DK_ERROR)
+ return concat (cl_options[OPT_Werror_].opt_text,
+ /* Skip over "-W". */
+ cl_options[option_index].opt_text + 2,
+ NULL);
+ /* A warning with option. */
+ else
+ return xstrdup (cl_options[option_index].opt_text);
+ }
+ /* A warning without option classified as an error. */
+ else if ((orig_diag_kind == DK_WARNING || orig_diag_kind == DK_PEDWARN
+ || diag_kind == DK_WARNING)
+ && context->warning_as_error_requested)
+ return xstrdup (cl_options[OPT_Werror].opt_text);
+ else
+ return NULL;
+}
+
+/* Get the page within the documentation for this option. */
+
+static const char *
+get_option_html_page (int option_index)
+{
+ const cl_option *cl_opt = &cl_options[option_index];
+
+ /* Analyzer options are on their own page. */
+ if (strstr (cl_opt->opt_text, "analyzer-"))
+ return "gcc/Static-Analyzer-Options.html";
+
+ /* Handle -flto= option. */
+ if (strstr (cl_opt->opt_text, "flto"))
+ return "gcc/Optimize-Options.html";
+
+#ifdef CL_Fortran
+ if ((cl_opt->flags & CL_Fortran) != 0
+ /* If it is option common to both C/C++ and Fortran, it is documented
+ in gcc/ rather than gfortran/ docs. */
+ && (cl_opt->flags & CL_C) == 0
+#ifdef CL_CXX
+ && (cl_opt->flags & CL_CXX) == 0
+#endif
+ )
+ return "gfortran/Error-and-Warning-Options.html";
+#endif
+
+ return "gcc/Warning-Options.html";
+}
+
+/* Return malloced memory for a URL describing the option OPTION_INDEX
+ which enabled a diagnostic (context CONTEXT). */
+
+char *
+get_option_url (diagnostic_context *, int option_index)
+{
+ if (option_index)
+ return concat (/* DOCUMENTATION_ROOT_URL should be supplied via -D by
+ the Makefile (see --with-documentation-root-url), and
+ should have a trailing slash. */
+ DOCUMENTATION_ROOT_URL,
+
+ /* get_option_html_page will return something like
+ "gcc/Warning-Options.html". */
+ get_option_html_page (option_index),
+
+ /* Expect an anchor of the form "index-Wfoo" e.g.
+ <a name="index-Wformat"></a>, and thus an id within
+ the URL of "#index-Wformat". */
+ "#index", cl_options[option_index].opt_text,
+ NULL);
+ else
+ return NULL;
+}
+
+/* Return a heap allocated producer with command line options. */
+
+char *
+gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count)
+{
+ auto_vec<const char *> switches;
+ char *options_string, *tail;
+ const char *p;
+ size_t len = 0;
+
+ for (unsigned i = 0; i < options_count; i++)
+ switch (options[i].opt_index)
+ {
+ case OPT_o:
+ case OPT_d:
+ case OPT_dumpbase:
+ case OPT_dumpbase_ext:
+ case OPT_dumpdir:
+ case OPT_quiet:
+ case OPT_version:
+ case OPT_v:
+ case OPT_w:
+ case OPT_L:
+ case OPT_D:
+ case OPT_I:
+ case OPT_U:
+ case OPT_SPECIAL_unknown:
+ case OPT_SPECIAL_ignore:
+ case OPT_SPECIAL_warn_removed:
+ case OPT_SPECIAL_program_name:
+ case OPT_SPECIAL_input_file:
+ case OPT_grecord_gcc_switches:
+ case OPT_frecord_gcc_switches:
+ case OPT__output_pch_:
+ case OPT_fdiagnostics_show_location_:
+ case OPT_fdiagnostics_show_option:
+ case OPT_fdiagnostics_show_caret:
+ case OPT_fdiagnostics_show_labels:
+ case OPT_fdiagnostics_show_line_numbers:
+ case OPT_fdiagnostics_color_:
+ case OPT_fdiagnostics_format_:
+ case OPT_fverbose_asm:
+ case OPT____:
+ case OPT__sysroot_:
+ case OPT_nostdinc:
+ case OPT_nostdinc__:
+ case OPT_fpreprocessed:
+// case OPT_fltrans_output_list_:
+// case OPT_fresolution_:
+ case OPT_fdebug_prefix_map_:
+ case OPT_fmacro_prefix_map_:
+ case OPT_ffile_prefix_map_:
+ case OPT_fprofile_prefix_map_:
+ case OPT_fcompare_debug:
+ case OPT_fchecking:
+ case OPT_fchecking_:
+ /* Ignore these. */
+ continue;
+ case OPT_flto_:
+ {
+ const char *lto_canonical = "-flto";
+ switches.safe_push (lto_canonical);
+ len += strlen (lto_canonical) + 1;
+ break;
+ }
+ default:
+ if (cl_options[options[i].opt_index].flags
+ & CL_NO_DWARF_RECORD)
+ continue;
+ gcc_checking_assert (options[i].canonical_option[0][0] == '-');
+ switch (options[i].canonical_option[0][1])
+ {
+ case 'M':
+ case 'i':
+ case 'W':
+ continue;
+ case 'f':
+ if (strncmp (options[i].canonical_option[0] + 2,
+ "dump", 4) == 0)
+ continue;
+ break;
+ default:
+ break;
+ }
+ switches.safe_push (options[i].orig_option_with_args_text);
+ len += strlen (options[i].orig_option_with_args_text) + 1;
+ break;
+ }
+
+ options_string = XNEWVEC (char, len + 1);
+ tail = options_string;
+
+ unsigned i;
+ FOR_EACH_VEC_ELT (switches, i, p)
+ {
+ len = strlen (p);
+ memcpy (tail, p, len);
+ tail += len;
+ if (i != switches.length () - 1)
+ {
+ *tail = ' ';
+ ++tail;
+ }
+ }
+
+ *tail = '\0';
+ return options_string;
+}
+
+/* Return a heap allocated producer string including command line options. */
+
+char *
+gen_producer_string (const char *language_string, cl_decoded_option *options,
+ unsigned int options_count)
+{
+ char *cmdline = gen_command_line_string (options, options_count);
+ char *combined = concat (language_string, " ", version_string, " ",
+ cmdline, NULL);
+ free (cmdline);
+ return combined;
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that get_option_html_page works as expected. */
+
+static void
+test_get_option_html_page ()
+{
+ ASSERT_STREQ (get_option_html_page (OPT_Wcpp), "gcc/Warning-Options.html");
+ ASSERT_STREQ (get_option_html_page (OPT_Wanalyzer_double_free),
+ "gcc/Static-Analyzer-Options.html");
+#ifdef CL_Fortran
+ ASSERT_STREQ (get_option_html_page (OPT_Wline_truncation),
+ "gfortran/Error-and-Warning-Options.html");
+#endif
+}
+
+/* Verify EnumSet and EnumBitSet requirements. */
+
+static void
+test_enum_sets ()
+{
+ for (unsigned i = 0; i < cl_options_count; ++i)
+ if (cl_options[i].var_type == CLVC_ENUM
+ && cl_options[i].var_value != CLEV_NORMAL)
+ {
+ const struct cl_enum *e = &cl_enums[cl_options[i].var_enum];
+ unsigned HOST_WIDE_INT used_sets = 0;
+ unsigned HOST_WIDE_INT mask = 0;
+ unsigned highest_set = 0;
+ for (unsigned j = 0; e->values[j].arg; ++j)
+ {
+ unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT;
+ if (cl_options[i].var_value == CLEV_BITSET)
+ {
+ /* For EnumBitSet Set shouldn't be used and Value should
+ be a power of two. */
+ ASSERT_TRUE (set == 0);
+ ASSERT_TRUE (pow2p_hwi (e->values[j].value));
+ continue;
+ }
+ /* Test that enumerators referenced in EnumSet have all
+ Set(n) on them within the valid range. */
+ ASSERT_TRUE (set >= 1 && set <= HOST_BITS_PER_WIDE_INT);
+ highest_set = MAX (set, highest_set);
+ used_sets |= HOST_WIDE_INT_1U << (set - 1);
+ }
+ if (cl_options[i].var_value == CLEV_BITSET)
+ continue;
+ /* If there is just one set, no point to using EnumSet. */
+ ASSERT_TRUE (highest_set >= 2);
+ /* Test that there are no gaps in between the sets. */
+ if (highest_set == HOST_BITS_PER_WIDE_INT)
+ ASSERT_TRUE (used_sets == HOST_WIDE_INT_M1U);
+ else
+ ASSERT_TRUE (used_sets == (HOST_WIDE_INT_1U << highest_set) - 1);
+ for (unsigned int j = 1; j <= highest_set; ++j)
+ {
+ unsigned HOST_WIDE_INT this_mask = 0;
+ for (unsigned k = 0; e->values[k].arg; ++k)
+ {
+ unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT;
+ if (set == j)
+ this_mask |= e->values[j].value;
+ }
+ ASSERT_TRUE ((mask & this_mask) == 0);
+ mask |= this_mask;
+ }
+ }
+}
+
+/* Run all of the selftests within this file. */
+
+void
+opts_cc_tests ()
+{
+ test_get_option_html_page ();
+ test_enum_sets ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/support/cpp/gcc/opts.h b/support/cpp/gcc/opts.h
new file mode 100644
index 000000000..a43ce66cf
--- /dev/null
+++ b/support/cpp/gcc/opts.h
@@ -0,0 +1,529 @@
+/* Command line option handling.
+ Copyright (C) 2002-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_OPTS_H
+#define GCC_OPTS_H
+
+#include "obstack.h"
+
+/* Specifies how a switch's VAR_VALUE relates to its FLAG_VAR. */
+enum cl_var_type {
+ /* The switch is an integer value. */
+ CLVC_INTEGER,
+
+ /* The switch is enabled when FLAG_VAR == VAR_VALUE. */
+ CLVC_EQUAL,
+
+ /* The switch is enabled when VAR_VALUE is not set in FLAG_VAR. */
+ CLVC_BIT_CLEAR,
+
+ /* The switch is enabled when VAR_VALUE is set in FLAG_VAR. */
+ CLVC_BIT_SET,
+
+ /* The switch is enabled when FLAG_VAR is less than HOST_WIDE_INT_M1U. */
+ CLVC_SIZE,
+
+ /* The switch takes a string argument and FLAG_VAR points to that
+ argument. */
+ CLVC_STRING,
+
+ /* The switch takes an enumerated argument (VAR_ENUM says what
+ enumeration) and FLAG_VAR points to that argument. */
+ CLVC_ENUM,
+
+ /* The switch should be stored in the VEC pointed to by FLAG_VAR for
+ later processing. */
+ CLVC_DEFER
+};
+
+/* Values for var_value member of CLVC_ENUM. */
+enum cl_enum_var_value {
+ /* Enum without EnumSet or EnumBitSet. */
+ CLEV_NORMAL,
+
+ /* EnumSet. */
+ CLEV_SET,
+
+ /* EnumBitSet. */
+ CLEV_BITSET
+};
+
+struct cl_option
+{
+ /* Text of the option, including initial '-'. */
+ const char *opt_text;
+ /* Help text for --help, or NULL. */
+ const char *help;
+ /* Error message for missing argument, or NULL. */
+ const char *missing_argument_error;
+ /* Warning to give when this option is used, or NULL. */
+ const char *warn_message;
+ /* Argument of alias target when positive option given, or NULL. */
+ const char *alias_arg;
+ /* Argument of alias target when negative option given, or NULL. */
+ const char *neg_alias_arg;
+ /* Alias target, or N_OPTS if not an alias. */
+ unsigned short alias_target;
+ /* Previous option that is an initial substring of this one, or
+ N_OPTS if none. */
+ unsigned short back_chain;
+ /* Option length, not including initial '-'. */
+ unsigned char opt_len;
+ /* Next option in a sequence marked with Negative, or -1 if none.
+ For a single option with both a negative and a positve form
+ (such as -Wall and -Wno-all), NEG_IDX is equal to the option's
+ own index (i.e., cl_options[IDX].neg_idx == IDX holds). */
+ int neg_index;
+ /* CL_* flags for this option. */
+ unsigned int flags;
+ /* Disabled in this configuration. */
+ BOOL_BITFIELD cl_disabled : 1;
+ /* Options marked with CL_SEPARATE take a number of separate
+ arguments (1 to 4) that is one more than the number in this
+ bit-field. */
+ unsigned int cl_separate_nargs : 2;
+ /* Option is an alias when used with separate argument. */
+ BOOL_BITFIELD cl_separate_alias : 1;
+ /* Alias to negative form of option. */
+ BOOL_BITFIELD cl_negative_alias : 1;
+ /* Option takes no argument in the driver. */
+ BOOL_BITFIELD cl_no_driver_arg : 1;
+ /* Reject this option in the driver. */
+ BOOL_BITFIELD cl_reject_driver : 1;
+ /* Reject no- form. */
+ BOOL_BITFIELD cl_reject_negative : 1;
+ /* Missing argument OK (joined). */
+ BOOL_BITFIELD cl_missing_ok : 1;
+ /* Argument is an integer >=0. */
+ BOOL_BITFIELD cl_uinteger : 1;
+ /* Argument is a HOST_WIDE_INT. */
+ BOOL_BITFIELD cl_host_wide_int : 1;
+ /* Argument should be converted to lowercase. */
+ BOOL_BITFIELD cl_tolower : 1;
+ /* Argument is an unsigned integer with an optional byte suffix. */
+ BOOL_BITFIELD cl_byte_size: 1;
+ /* Offset of field for this option in struct gcc_options, or
+ (unsigned short) -1 if none. */
+ unsigned short flag_var_offset;
+ /* Index in cl_enums of enum used for this option's arguments, for
+ CLVC_ENUM options. */
+ unsigned short var_enum;
+ /* How this option's value is determined and sets a field. */
+ enum cl_var_type var_type;
+ /* Value or bit-mask with which to set a field. */
+ HOST_WIDE_INT var_value;
+ /* Range info minimum, or -1. */
+ int range_min;
+ /* Range info maximum, or -1. */
+ int range_max;
+};
+
+struct cl_var
+{
+ /* Name of the variable. */
+ const char *var_name;
+ /* Offset of field for this var in struct gcc_options. */
+ unsigned short var_offset;
+};
+
+/* Records that the state of an option consists of SIZE bytes starting
+ at DATA. DATA might point to CH in some cases. */
+struct cl_option_state {
+ const void *data;
+ size_t size;
+ char ch;
+};
+
+extern const struct cl_option cl_options[];
+extern const unsigned int cl_options_count;
+#ifdef ENABLE_PLUGIN
+extern const struct cl_var cl_vars[];
+#endif
+extern const char *const lang_names[];
+extern const unsigned int cl_lang_count;
+
+#define CL_PARAMS (1U << 16) /* Fake entry. Used to display --param info with --help. */
+#define CL_WARNING (1U << 17) /* Enables an (optional) warning message. */
+#define CL_OPTIMIZATION (1U << 18) /* Enables an (optional) optimization. */
+#define CL_DRIVER (1U << 19) /* Driver option. */
+#define CL_TARGET (1U << 20) /* Target-specific option. */
+#define CL_COMMON (1U << 21) /* Language-independent. */
+
+#define CL_MIN_OPTION_CLASS CL_PARAMS
+#define CL_MAX_OPTION_CLASS CL_COMMON
+
+/* From here on the bits describe attributes of the options.
+ Before this point the bits have described the class of the option.
+ This distinction is important because --help will not list options
+ which only have these higher bits set. */
+
+#define CL_JOINED (1U << 22) /* If takes joined argument. */
+#define CL_SEPARATE (1U << 23) /* If takes a separate argument. */
+#define CL_UNDOCUMENTED (1U << 24) /* Do not output with --help. */
+#define CL_NO_DWARF_RECORD (1U << 25) /* Do not add to producer string. */
+#define CL_PCH_IGNORE (1U << 26) /* Do compare state for pch. */
+
+/* Flags for an enumerated option argument. */
+#define CL_ENUM_CANONICAL (1 << 0) /* Canonical for this value. */
+#define CL_ENUM_DRIVER_ONLY (1 << 1) /* Only accepted in the driver. */
+#define CL_ENUM_SET_SHIFT 2 /* Shift for enum set. */
+
+/* Structure describing an enumerated option argument. */
+
+struct cl_enum_arg
+{
+ /* The argument text, or NULL at the end of the array. */
+ const char *arg;
+
+ /* The corresponding integer value. */
+ int value;
+
+ /* Flags associated with this argument. */
+ unsigned int flags;
+};
+
+/* Structure describing an enumerated set of option arguments. */
+
+struct cl_enum
+{
+ /* Help text, or NULL if the values should not be listed in --help
+ output. */
+ const char *help;
+
+ /* Error message for unknown arguments, or NULL to use a generic
+ error. */
+ const char *unknown_error;
+
+ /* Array of possible values. */
+ const struct cl_enum_arg *values;
+
+ /* The size of the type used to store a value. */
+ size_t var_size;
+
+ /* Function to set a variable of this type. */
+ void (*set) (void *var, int value);
+
+ /* Function to get the value of a variable of this type. */
+ int (*get) (const void *var);
+};
+
+extern const struct cl_enum cl_enums[];
+extern const unsigned int cl_enums_count;
+
+/* Possible ways in which a command-line option may be erroneous.
+ These do not include not being known at all; an option index of
+ OPT_SPECIAL_unknown is used for that. */
+
+#define CL_ERR_DISABLED (1 << 0) /* Disabled in this configuration. */
+#define CL_ERR_MISSING_ARG (1 << 1) /* Argument required but missing. */
+#define CL_ERR_WRONG_LANG (1 << 2) /* Option for wrong language. */
+#define CL_ERR_UINT_ARG (1 << 3) /* Bad unsigned integer argument. */
+#define CL_ERR_INT_RANGE_ARG (1 << 4) /* Bad unsigned integer argument. */
+#define CL_ERR_ENUM_ARG (1 << 5) /* Bad enumerated argument. */
+#define CL_ERR_NEGATIVE (1 << 6) /* Negative form of option
+ not permitted (together
+ with OPT_SPECIAL_unknown). */
+#define CL_ERR_ENUM_SET_ARG (1 << 7) /* Bad argument of enumerated set. */
+
+/* Structure describing the result of decoding an option. */
+
+struct cl_decoded_option
+{
+ /* The index of this option, or an OPT_SPECIAL_* value for
+ non-options and unknown options. */
+ size_t opt_index;
+
+ /* Any warning to give for use of this option, or NULL if none. */
+ const char *warn_message;
+
+ /* The string argument, or NULL if none. For OPT_SPECIAL_* cases,
+ the option or non-option command-line argument. */
+ const char *arg;
+
+ /* The original text of option plus arguments, with separate argv
+ elements concatenated into one string with spaces separating
+ them. This is for such uses as diagnostics and
+ -frecord-gcc-switches. */
+ const char *orig_option_with_args_text;
+
+ /* The canonical form of the option and its argument, for when it is
+ necessary to reconstruct argv elements (in particular, for
+ processing specs and passing options to subprocesses from the
+ driver). */
+ const char *canonical_option[4];
+
+ /* The number of elements in the canonical form of the option and
+ arguments; always at least 1. */
+ size_t canonical_option_num_elements;
+
+ /* For a boolean option, 1 for the true case and 0 for the "no-"
+ case. For an unsigned integer option, the value of the
+ argument. For enum the value of the enumerator corresponding
+ to argument string. 1 in all other cases. */
+ HOST_WIDE_INT value;
+
+ /* For EnumSet the value mask. Variable should be changed to
+ value | (prev_value & ~mask). */
+ HOST_WIDE_INT mask;
+
+ /* Any flags describing errors detected in this option. */
+ int errors;
+};
+
+/* Structure describing an option deferred for handling after the main
+ option handlers. */
+
+struct cl_deferred_option
+{
+ /* Elements from struct cl_decoded_option used for deferred
+ options. */
+ size_t opt_index;
+ const char *arg;
+ int value;
+};
+
+/* Structure describing a single option-handling callback. */
+
+struct cl_option_handler_func
+{
+ /* The function called to handle the option. */
+ bool (*handler) (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask, int kind, location_t loc,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc,
+ void (*target_option_override_hook) (void));
+
+ /* The mask that must have some bit in common with the flags for the
+ option for this particular handler to be used. */
+ unsigned int mask;
+};
+
+/* Structure describing the callbacks used in handling options. */
+
+struct cl_option_handlers
+{
+ /* Callback for an unknown option to determine whether to give an
+ error for it, and possibly store information to diagnose the
+ option at a later point. Return true if an error should be
+ given, false otherwise. */
+ bool (*unknown_option_callback) (const struct cl_decoded_option *decoded);
+
+ /* Callback to handle, and possibly diagnose, an option for another
+ language. */
+ void (*wrong_lang_callback) (const struct cl_decoded_option *decoded,
+ unsigned int lang_mask);
+
+ /* Target option override hook. */
+ void (*target_option_override_hook) (void);
+
+ /* The number of individual handlers. */
+ size_t num_handlers;
+
+ /* The handlers themselves. */
+ struct cl_option_handler_func handlers[3];
+};
+
+/* Hold command-line options associated with stack limitation. */
+extern const char *opt_fstack_limit_symbol_arg;
+extern int opt_fstack_limit_register_no;
+
+/* Input file names. */
+
+extern const char **in_fnames;
+
+/* The count of input filenames. */
+
+extern unsigned num_in_fnames;
+
+extern char *opts_concat (const char *first, ...);
+
+/* Obstack for option strings. */
+
+extern struct obstack opts_obstack;
+
+size_t find_opt (const char *input, unsigned int lang_mask);
+extern HOST_WIDE_INT integral_argument (const char *arg, int * = NULL, bool = false);
+extern bool enum_value_to_arg (const struct cl_enum_arg *enum_args,
+ const char **argp, int value,
+ unsigned int lang_mask);
+extern void decode_cmdline_options_to_array (unsigned int argc,
+ const char **argv,
+ unsigned int lang_mask,
+ struct cl_decoded_option **decoded_options,
+ unsigned int *decoded_options_count);
+extern void init_options_once (void);
+extern void init_options_struct (struct gcc_options *opts,
+ struct gcc_options *opts_set);
+extern void init_opts_obstack (void);
+extern void decode_cmdline_options_to_array_default_mask (unsigned int argc,
+ const char **argv,
+ struct cl_decoded_option **decoded_options,
+ unsigned int *decoded_options_count);
+extern void set_default_handlers (struct cl_option_handlers *handlers,
+ void (*target_option_override_hook) (void));
+extern void decode_options (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded_options,
+ unsigned int decoded_options_count,
+ location_t loc,
+ diagnostic_context *dc,
+ void (*target_option_override_hook) (void));
+extern int option_enabled (int opt_idx, unsigned lang_mask, void *opts);
+
+extern bool get_option_state (struct gcc_options *, int,
+ struct cl_option_state *);
+extern void set_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ int opt_index, HOST_WIDE_INT value, const char *arg,
+ int kind, location_t loc, diagnostic_context *dc,
+ HOST_WIDE_INT = 0);
+extern void *option_flag_var (int opt_index, struct gcc_options *opts);
+bool handle_generated_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ size_t opt_index, const char *arg,
+ HOST_WIDE_INT value,
+ unsigned int lang_mask, int kind, location_t loc,
+ const struct cl_option_handlers *handlers,
+ bool generated_p, diagnostic_context *dc);
+void generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
+ unsigned int lang_mask,
+ struct cl_decoded_option *decoded);
+void generate_option_input_file (const char *file,
+ struct cl_decoded_option *decoded);
+extern void read_cmdline_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded,
+ location_t loc,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc);
+extern void control_warning_option (unsigned int opt_index, int kind,
+ const char *arg, bool imply, location_t loc,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ diagnostic_context *dc);
+extern char *write_langs (unsigned int mask);
+extern void print_ignored_options (void);
+extern void handle_common_deferred_options (void);
+unsigned int parse_sanitizer_options (const char *, location_t, int,
+ unsigned int, int, bool);
+
+unsigned int parse_no_sanitize_attribute (char *value);
+extern bool common_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask, int kind,
+ location_t loc,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc,
+ void (*target_option_override_hook) (void));
+extern bool target_handle_option (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ const struct cl_decoded_option *decoded,
+ unsigned int lang_mask, int kind,
+ location_t loc,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc,
+ void (*target_option_override_hook) (void));
+extern void finish_options (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ location_t loc);
+extern void diagnose_options (gcc_options *opts, gcc_options *opts_set,
+ location_t loc);
+extern void print_help (struct gcc_options *opts, unsigned int lang_mask, const
+ char *help_option_argument);
+extern void default_options_optimization (struct gcc_options *opts,
+ struct gcc_options *opts_set,
+ struct cl_decoded_option *decoded_options,
+ unsigned int decoded_options_count,
+ location_t loc,
+ unsigned int lang_mask,
+ const struct cl_option_handlers *handlers,
+ diagnostic_context *dc);
+extern void set_struct_debug_option (struct gcc_options *opts,
+ location_t loc,
+ const char *value);
+extern bool opt_enum_arg_to_value (size_t opt_index, const char *arg,
+ int *value,
+ unsigned int lang_mask);
+
+extern const struct sanitizer_opts_s
+{
+ const char *const name;
+ unsigned int flag;
+ size_t len;
+ bool can_recover;
+} sanitizer_opts[];
+
+extern const struct zero_call_used_regs_opts_s
+{
+ const char *const name;
+ unsigned int flag;
+} zero_call_used_regs_opts[];
+
+extern vec<const char *> help_option_arguments;
+
+extern void add_misspelling_candidates (auto_vec<char *> *candidates,
+ const struct cl_option *option,
+ const char *base_option);
+extern const char *candidates_list_and_hint (const char *arg, char *&str,
+ const auto_vec <const char *> &
+ candidates);
+
+
+extern bool parse_and_check_align_values (const char *flag,
+ const char *name,
+ auto_vec<unsigned> &result_values,
+ bool report_error,
+ location_t loc);
+
+extern void parse_and_check_patch_area (const char *arg, bool report_error,
+ HOST_WIDE_INT *patch_area_size,
+ HOST_WIDE_INT *patch_area_start);
+
+extern void parse_options_from_collect_gcc_options (const char *, obstack *,
+ int *);
+
+extern void prepend_xassembler_to_collect_as_options (const char *, obstack *);
+
+extern char *gen_command_line_string (cl_decoded_option *options,
+ unsigned int options_count);
+extern char *gen_producer_string (const char *language_string,
+ cl_decoded_option *options,
+ unsigned int options_count);
+
+/* Set OPTION in OPTS to VALUE if the option is not set in OPTS_SET. */
+
+#define SET_OPTION_IF_UNSET(OPTS, OPTS_SET, OPTION, VALUE) \
+ do \
+ { \
+ if (!(OPTS_SET)->x_ ## OPTION) \
+ (OPTS)->x_ ## OPTION = VALUE; \
+ } \
+ while (false)
+
+/* Return true if OPTION is set by user in global options. */
+
+#define OPTION_SET_P(OPTION) global_options_set.x_ ## OPTION
+
+#endif
diff --git a/support/cpp/gcc/output.h b/support/cpp/gcc/output.h
new file mode 100644
index 000000000..6dea63091
--- /dev/null
+++ b/support/cpp/gcc/output.h
@@ -0,0 +1,635 @@
+/* Declarations for insn-output.cc and other code to write to asm_out_file.
+ These functions are defined in final.cc, and varasm.cc.
+ 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/>. */
+
+#ifndef GCC_OUTPUT_H
+#define GCC_OUTPUT_H
+
+/* Initialize data in final at the beginning of a compilation. */
+extern void init_final (const char *);
+
+/* Enable APP processing of subsequent output.
+ Used before the output from an `asm' statement. */
+extern void app_enable (void);
+
+/* Disable APP processing of subsequent output.
+ Called from varasm.cc before most kinds of output. */
+extern void app_disable (void);
+
+/* Return the number of slots filled in the current
+ delayed branch sequence (we don't count the insn needing the
+ delay slot). Zero if not in a delayed branch sequence. */
+extern int dbr_sequence_length (void);
+
+/* Indicate that branch shortening hasn't yet been done. */
+extern void init_insn_lengths (void);
+
+/* Obtain the current length of an insn. If branch shortening has been done,
+ get its actual length. Otherwise, get its maximum length. */
+extern int get_attr_length (rtx_insn *);
+
+/* Obtain the current length of an insn. If branch shortening has been done,
+ get its actual length. Otherwise, get its minimum length. */
+extern int get_attr_min_length (rtx_insn *);
+
+/* Make a pass over all insns and compute their actual lengths by shortening
+ any branches of variable length if possible. */
+extern void shorten_branches (rtx_insn *);
+
+const char *get_some_local_dynamic_name ();
+
+/* Output assembler code for the start of a function,
+ and initialize some of the variables in this file
+ for the new function. The label for the function and associated
+ assembler pseudo-ops have already been output in
+ `assemble_start_function'. */
+extern void final_start_function (rtx_insn *, FILE *, int);
+
+/* Output assembler code for the end of a function.
+ For clarity, args are same as those of `final_start_function'
+ even though not all of them are needed. */
+extern void final_end_function (void);
+
+/* Output assembler code for some insns: all or part of a function. */
+extern void final (rtx_insn *, FILE *, int);
+
+/* The final scan for one insn, INSN. Args are same as in `final', except
+ that INSN is the insn being scanned. Value returned is the next insn to
+ be scanned. */
+extern rtx_insn *final_scan_insn (rtx_insn *, FILE *, int, int, int *);
+
+/* Replace a SUBREG with a REG or a MEM, based on the thing it is a
+ subreg of. */
+extern rtx alter_subreg (rtx *, bool);
+
+/* Print an operand using machine-dependent assembler syntax. */
+extern void output_operand (rtx, int);
+
+/* Report inconsistency between the assembler template and the operands.
+ In an `asm', it's the user's fault; otherwise, the compiler's fault. */
+extern void output_operand_lossage (const char *, ...) ATTRIBUTE_PRINTF_1;
+
+/* Output a string of assembler code, substituting insn operands.
+ Defined in final.cc. */
+extern void output_asm_insn (const char *, rtx *);
+
+/* Compute a worst-case reference address of a branch so that it
+ can be safely used in the presence of aligned labels.
+ Defined in final.cc. */
+extern int insn_current_reference_address (rtx_insn *);
+
+/* Find the alignment associated with a CODE_LABEL.
+ Defined in final.cc. */
+extern align_flags label_to_alignment (rtx);
+
+/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
+extern void output_asm_label (rtx);
+
+/* Marks SYMBOL_REFs in x as referenced through use of assemble_external. */
+extern void mark_symbol_refs_as_used (rtx);
+
+/* Print a memory reference operand for address X with access mode MODE
+ using machine-dependent assembler syntax. */
+extern void output_address (machine_mode, rtx);
+
+/* Print an integer constant expression in assembler syntax.
+ Addition and subtraction are the only arithmetic
+ that may appear in these expressions. */
+extern void output_addr_const (FILE *, rtx);
+
+/* Output a string of assembler code, substituting numbers, strings
+ and fixed syntactic prefixes. */
+#if GCC_VERSION >= 3004
+#define ATTRIBUTE_ASM_FPRINTF(m, n) __attribute__ ((__format__ (__asm_fprintf__, m, n))) ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_ASM_FPRINTF(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+
+extern void fprint_whex (FILE *, unsigned HOST_WIDE_INT);
+extern void fprint_ul (FILE *, unsigned long);
+extern int sprint_ul (char *, unsigned long);
+
+extern void asm_fprintf (FILE *file, const char *p, ...)
+ ATTRIBUTE_ASM_FPRINTF(2, 3);
+
+/* Return nonzero if this function has no function calls. */
+extern int leaf_function_p (void);
+
+/* Return 1 if branch is a forward branch.
+ Uses insn_shuid array, so it works only in the final pass. May be used by
+ output templates to add branch prediction hints, for example. */
+extern int final_forward_branch_p (rtx_insn *);
+
+/* Return 1 if this function uses only the registers that can be
+ safely renumbered. */
+extern int only_leaf_regs_used (void);
+
+/* Scan IN_RTX and its subexpressions, and renumber all regs into those
+ available in leaf functions. */
+extern void leaf_renumber_regs_insn (rtx);
+
+/* Locate the proper template for the given insn-code. */
+extern const char *get_insn_template (int, rtx_insn *);
+
+/* Functions in varasm.cc. */
+
+/* Emit any pending weak declarations. */
+extern void weak_finish (void);
+
+/* Decode an `asm' spec for a declaration as a register name.
+ Return the register number, or -1 if nothing specified,
+ or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
+ or -3 if ASMSPEC is `cc' and is not recognized,
+ or -4 if ASMSPEC is `memory' and is not recognized.
+ Accept an exact spelling or a decimal number.
+ Prefixes such as % are optional. */
+extern int decode_reg_name (const char *);
+
+/* Similar to decode_reg_name, but takes an extra parameter that is a
+ pointer to the number of (internal) registers described by the
+ external name. */
+extern int decode_reg_name_and_count (const char *, int *);
+
+extern void do_assemble_alias (tree, tree);
+extern void do_assemble_symver (tree, tree);
+
+extern void default_assemble_visibility (tree, int);
+
+/* Output a string of literal assembler code
+ for an `asm' keyword used between functions. */
+extern void assemble_asm (tree);
+
+/* Get the function's name from a decl, as described by its RTL. */
+extern const char *get_fnname_from_decl (tree);
+
+/* Output assembler code for the constant pool of a function and associated
+ with defining the name of the function. DECL describes the function.
+ NAME is the function's name. For the constant pool, we use the current
+ constant pool data. */
+extern void assemble_start_function (tree, const char *);
+
+/* Output assembler code associated with defining the size of the
+ function. DECL describes the function. NAME is the function's name. */
+extern void assemble_end_function (tree, const char *);
+
+/* Assemble everything that is needed for a variable or function declaration.
+ Not used for automatic variables, and not used for function definitions.
+ Should not be called for variables of incomplete structure type.
+
+ TOP_LEVEL is nonzero if this variable has file scope.
+ AT_END is nonzero if this is the special handling, at end of compilation,
+ to define things that have had only tentative definitions.
+ DONT_OUTPUT_DATA if nonzero means don't actually output the
+ initial value (that will be done by the caller). */
+extern void assemble_variable (tree, int, int, int);
+
+/* Put the vtable verification constructor initialization function
+ into the preinit array. */
+extern void assemble_vtv_preinit_initializer (tree);
+
+/* Assemble everything that is needed for a variable declaration that has
+ no definition in the current translation unit. */
+extern void assemble_undefined_decl (tree);
+
+/* Compute the alignment of variable specified by DECL.
+ DONT_OUTPUT_DATA is from assemble_variable. */
+extern void align_variable (tree decl, bool dont_output_data);
+
+/* Queue for outputting something to declare an external symbol to the
+ assembler. (Most assemblers don't need this, so we normally output
+ nothing.) Do nothing if DECL is not external. */
+extern void assemble_external (tree);
+
+/* Assemble code to leave SIZE bytes of zeros. */
+extern void assemble_zeros (unsigned HOST_WIDE_INT);
+
+/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */
+extern void assemble_align (unsigned int);
+
+/* Assemble a string constant with the specified C string as contents. */
+extern void assemble_string (const char *, int);
+
+/* Similar, for calling a library function FUN. */
+extern void assemble_external_libcall (rtx);
+
+/* Assemble a label named NAME. */
+extern void assemble_label (FILE *, const char *);
+
+/* Output to FILE (an assembly file) a reference to NAME. If NAME
+ starts with a *, the rest of NAME is output verbatim. Otherwise
+ NAME is transformed in a target-specific way (usually by the
+ addition of an underscore). */
+extern void assemble_name_raw (FILE *, const char *);
+
+/* Return NAME that should actually be emitted, looking through
+ transparent aliases. If NAME refers to an entity that is also
+ represented as a tree (like a function or variable), mark the entity
+ as referenced. */
+extern const char *assemble_name_resolve (const char *);
+
+/* Like assemble_name_raw, but should be used when NAME might refer to
+ an entity that is also represented as a tree (like a function or
+ variable). If NAME does refer to such an entity, that entity will
+ be marked as referenced. */
+extern void assemble_name (FILE *, const char *);
+
+/* Return the assembler directive for creating a given kind of integer
+ object. SIZE is the number of bytes in the object and ALIGNED_P
+ indicates whether it is known to be aligned. Return NULL if the
+ assembly dialect has no such directive.
+
+ The returned string should be printed at the start of a new line and
+ be followed immediately by the object's initial value. */
+extern const char *integer_asm_op (int, int);
+
+/* Use directive OP to assemble an integer object X. Print OP at the
+ start of the line, followed immediately by the value of X. */
+extern void assemble_integer_with_op (const char *, rtx);
+
+/* The default implementation of the asm_out.integer target hook. */
+extern bool default_assemble_integer (rtx, unsigned int, int);
+
+/* Assemble the integer constant X into an object of SIZE bytes. ALIGN is
+ the alignment of the integer in bits. Return 1 if we were able to output
+ the constant, otherwise 0. If FORCE is nonzero the constant must
+ be outputable. */
+extern bool assemble_integer (rtx, unsigned, unsigned, int);
+
+/* Return section for TEXT_SECITON_NAME if DECL or DECL_SECTION_NAME (DECL)
+ is NULL. */
+extern section *get_named_text_section (tree, const char *, const char *);
+
+/* An interface to assemble_integer for the common case in which a value is
+ fully aligned and must be printed. VALUE is the value of the integer
+ object and SIZE is the number of bytes it contains. */
+#define assemble_aligned_integer(SIZE, VALUE) \
+ assemble_integer (VALUE, SIZE, (SIZE) * BITS_PER_UNIT, 1)
+
+/* Assemble the floating-point constant D into an object of size MODE. ALIGN
+ is the alignment of the constant in bits. If REVERSE is true, D is output
+ in reverse storage order. */
+extern void assemble_real (REAL_VALUE_TYPE, scalar_float_mode, unsigned,
+ bool = false);
+
+/* Write the address of the entity given by SYMBOL to SEC. */
+extern void assemble_addr_to_section (rtx, section *);
+
+/* Return TRUE if and only if the constant pool has no entries. Note
+ that even entries we might end up choosing not to emit are counted
+ here, so there is the potential for missed optimizations. */
+extern bool constant_pool_empty_p (void);
+
+extern rtx_insn *peephole (rtx_insn *);
+
+extern void output_shared_constant_pool (void);
+
+extern void output_object_blocks (void);
+
+extern void output_quoted_string (FILE *, const char *);
+
+/* When outputting delayed branch sequences, this rtx holds the
+ sequence being output. It is null when no delayed branch
+ sequence is being output, so it can be used as a test in the
+ insn output code.
+
+ This variable is defined in final.cc. */
+extern rtx_sequence *final_sequence;
+
+/* File in which assembler code is being written. */
+
+#ifdef BUFSIZ
+extern FILE *asm_out_file;
+#endif
+
+/* The first global object in the file. */
+extern const char *first_global_object_name;
+
+/* The first weak object in the file. */
+extern const char *weak_global_object_name;
+
+/* Nonnull if the insn currently being emitted was a COND_EXEC pattern. */
+extern rtx current_insn_predicate;
+
+/* Last insn processed by final_scan_insn. */
+extern rtx_insn *current_output_insn;
+
+/* Nonzero while outputting an `asm' with operands.
+ This means that inconsistencies are the user's fault, so don't die.
+ The precise value is the insn being output, to pass to error_for_asm. */
+extern const rtx_insn *this_is_asm_operands;
+
+/* Carry information from ASM_DECLARE_OBJECT_NAME
+ to ASM_FINISH_DECLARE_OBJECT. */
+extern int size_directive_output;
+extern tree last_assemble_variable_decl;
+
+extern bool first_function_block_is_cold;
+
+/* Decide whether DECL needs to be in a writable section.
+ RELOC is the same as for SELECT_SECTION. */
+extern bool decl_readonly_section (const_tree, int);
+
+/* This can be used to compute RELOC for the function above, when
+ given a constant expression. */
+extern int compute_reloc_for_constant (tree);
+
+/* This can be used to compute RELOC for get_variable_section. */
+extern int compute_reloc_for_var (tree);
+
+/* User label prefix in effect for this compilation. */
+extern const char *user_label_prefix;
+
+/* Default target function prologue and epilogue assembler output. */
+extern void default_function_pro_epilogue (FILE *);
+
+/* Default target function switched text sections. */
+extern void default_function_switched_text_sections (FILE *, tree, bool);
+
+/* Default target hook that outputs nothing to a stream. */
+extern void no_asm_to_stream (FILE *);
+
+/* Flags controlling properties of a section. */
+enum section_flag
+{
+ /* This SECTION_STYLE is used for unnamed sections that we can switch
+ to using a special assembler directive. */
+ SECTION_UNNAMED = 0,
+
+ SECTION_ENTSIZE = (1UL << 8) - 1, /* entity size in section */
+ SECTION_CODE = 1UL << 8, /* contains code */
+ SECTION_WRITE = 1UL << 9, /* data is writable */
+
+ SECTION_DEBUG = 1UL << 10, /* contains debug data */
+ SECTION_LINKONCE = 1UL << 11, /* is linkonce */
+ SECTION_SMALL = 1UL << 12, /* contains "small data" */
+ SECTION_BSS = 1UL << 13, /* contains zeros only */
+ SECTION_MERGE = 1UL << 14, /* contains mergeable data */
+ SECTION_STRINGS = 1UL << 15, /* contains zero terminated strings
+ without embedded zeros */
+ SECTION_OVERRIDE = 1UL << 16, /* allow override of default flags */
+ SECTION_TLS = 1UL << 17, /* contains thread-local storage */
+ SECTION_NOTYPE = 1UL << 18, /* don't output @progbits */
+ SECTION_DECLARED = 1UL << 19, /* section has been used */
+
+ /* This SECTION_STYLE is used for named sections that we can switch
+ to using a general section directive. */
+ SECTION_NAMED = 1UL << 20,
+
+ /* This SECTION_STYLE is used for sections that we cannot switch to at
+ all. The choice of section is implied by the directive that we use
+ to declare the object. */
+ SECTION_NOSWITCH = 1UL << 21,
+
+ /* bits used for SECTION_STYLE */
+ SECTION_STYLE_MASK = SECTION_NAMED | SECTION_NOSWITCH,
+
+ SECTION_COMMON = 1UL << 22, /* contains common data */
+ SECTION_RELRO = 1UL << 23, /* data is readonly after
+ relocation processing */
+ SECTION_EXCLUDE = 1UL << 24, /* discarded by the linker */
+ SECTION_RETAIN = 1UL << 25, /* retained by the linker. */
+ SECTION_LINK_ORDER = 1UL << 26, /* section needs link-order. */
+
+ /* NB: The maximum SECTION_MACH_DEP is (1UL << 28) since AVR needs 4 bits
+ in SECTION_MACH_DEP. */
+ SECTION_MACH_DEP = 1UL << 27,
+
+ /* subsequent bits reserved for target */
+};
+
+/* A helper function for default_elf_select_section and
+ default_elf_unique_section. Categorizes the DECL. */
+
+enum section_category
+{
+ SECCAT_TEXT,
+
+ SECCAT_RODATA,
+ SECCAT_RODATA_MERGE_STR,
+ SECCAT_RODATA_MERGE_STR_INIT,
+ SECCAT_RODATA_MERGE_CONST,
+ SECCAT_SRODATA,
+
+ SECCAT_DATA,
+
+ /* To optimize loading of shared programs, define following subsections
+ of data section:
+ _REL Contains data that has relocations, so they get grouped
+ together and dynamic linker will visit fewer pages in memory.
+ _RO Contains data that is otherwise read-only. This is useful
+ with prelinking as most relocations won't be dynamically
+ linked and thus stay read only.
+ _LOCAL Marks data containing relocations only to local objects.
+ These relocations will get fully resolved by prelinking. */
+ SECCAT_DATA_REL,
+ SECCAT_DATA_REL_LOCAL,
+ SECCAT_DATA_REL_RO,
+ SECCAT_DATA_REL_RO_LOCAL,
+
+ SECCAT_SDATA,
+ SECCAT_TDATA,
+
+ SECCAT_BSS,
+ SECCAT_SBSS,
+ SECCAT_TBSS
+};
+
+/* Information that is provided by all instances of the section type. */
+struct GTY(()) section_common {
+ /* The set of SECTION_* flags that apply to this section. */
+ unsigned int flags;
+};
+
+/* Information about a SECTION_NAMED section. */
+struct GTY(()) named_section {
+ struct section_common common;
+
+ /* The name of the section. */
+ const char *name;
+
+ /* If nonnull, the VAR_DECL or FUNCTION_DECL with which the
+ section is associated. */
+ tree decl;
+};
+
+/* A callback that writes the assembly code for switching to an unnamed
+ section. The argument provides callback-specific data. */
+typedef void (*unnamed_section_callback) (const char *);
+
+/* Information about a SECTION_UNNAMED section. */
+struct GTY(()) unnamed_section {
+ struct section_common common;
+
+ /* The callback used to switch to the section, and the data that
+ should be passed to the callback. */
+ unnamed_section_callback GTY ((callback)) callback;
+ const char *data;
+
+ /* The next entry in the chain of unnamed sections. */
+ section *next;
+};
+
+/* A callback that writes the assembly code for a decl in a
+ SECTION_NOSWITCH section. DECL is the decl that should be assembled
+ and NAME is the name of its SYMBOL_REF. SIZE is the size of the decl
+ in bytes and ROUNDED is that size rounded up to the next
+ BIGGEST_ALIGNMENT / BITS_PER_UNIT boundary.
+
+ Return true if the callback used DECL_ALIGN to set the object's
+ alignment. A false return value implies that we are relying
+ on the rounded size to align the decl. */
+typedef bool (*noswitch_section_callback) (tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT rounded);
+
+/* Information about a SECTION_NOSWITCH section. */
+struct GTY(()) noswitch_section {
+ struct section_common common;
+
+ /* The callback used to assemble decls in this section. */
+ noswitch_section_callback GTY ((callback)) callback;
+};
+
+/* Information about a section, which may be named or unnamed. */
+union GTY ((desc ("SECTION_STYLE (&(%h))"), for_user)) section {
+ struct section_common GTY ((skip)) common;
+ struct named_section GTY ((tag ("SECTION_NAMED"))) named;
+ struct unnamed_section GTY ((tag ("SECTION_UNNAMED"))) unnamed;
+ struct noswitch_section GTY ((tag ("SECTION_NOSWITCH"))) noswitch;
+};
+
+/* Return the style of section SECT. */
+#define SECTION_STYLE(SECT) ((SECT)->common.flags & SECTION_STYLE_MASK)
+
+struct object_block;
+
+/* Special well-known sections. */
+extern GTY(()) section *text_section;
+extern GTY(()) section *data_section;
+extern GTY(()) section *readonly_data_section;
+extern GTY(()) section *sdata_section;
+extern GTY(()) section *ctors_section;
+extern GTY(()) section *dtors_section;
+extern GTY(()) section *bss_section;
+extern GTY(()) section *sbss_section;
+extern GTY(()) section *exception_section;
+extern GTY(()) section *eh_frame_section;
+extern GTY(()) section *tls_comm_section;
+extern GTY(()) section *comm_section;
+extern GTY(()) section *lcomm_section;
+extern GTY(()) section *bss_noswitch_section;
+
+extern GTY(()) section *in_section;
+extern GTY(()) bool in_cold_section_p;
+
+extern section *get_unnamed_section (unsigned int, void (*) (const char *),
+ const char *);
+extern section *get_section (const char *, unsigned int, tree,
+ bool not_existing = false);
+extern section *get_named_section (tree, const char *, int);
+extern section *get_variable_section (tree, bool);
+extern void place_block_symbol (rtx);
+extern rtx get_section_anchor (struct object_block *, HOST_WIDE_INT,
+ enum tls_model);
+extern section *mergeable_constant_section (machine_mode,
+ unsigned HOST_WIDE_INT,
+ unsigned int);
+extern section *function_section (tree);
+extern section *unlikely_text_section (void);
+extern section *current_function_section (void);
+extern void switch_to_other_text_partition (void);
+
+/* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
+ not) section for PRIORITY. */
+extern section *get_cdtor_priority_section (int, bool);
+
+extern bool unlikely_text_section_p (section *);
+extern void switch_to_section (section *, tree = nullptr);
+extern void output_section_asm_op (const char *);
+
+extern void record_tm_clone_pair (tree, tree);
+extern void finish_tm_clone_pairs (void);
+extern tree get_tm_clone_pair (tree);
+
+extern void default_asm_output_source_filename (FILE *, const char *);
+extern void output_file_directive (FILE *, const char *);
+
+extern unsigned int default_section_type_flags (tree, const char *, int);
+
+extern bool have_global_bss_p (void);
+extern bool bss_initializer_p (const_tree, bool = false);
+
+extern void default_no_named_section (const char *, unsigned int, tree);
+extern void default_elf_asm_named_section (const char *, unsigned int, tree);
+extern enum section_category categorize_decl_for_section (const_tree, int);
+extern void default_coff_asm_named_section (const char *, unsigned int, tree);
+extern void default_pe_asm_named_section (const char *, unsigned int, tree);
+
+extern void default_named_section_asm_out_destructor (rtx, int);
+extern void default_dtor_section_asm_out_destructor (rtx, int);
+extern void default_named_section_asm_out_constructor (rtx, int);
+extern void default_ctor_section_asm_out_constructor (rtx, int);
+
+extern section *default_select_section (tree, int, unsigned HOST_WIDE_INT);
+extern section *default_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
+extern void default_unique_section (tree, int);
+extern section *default_function_rodata_section (tree, bool);
+extern section *default_no_function_rodata_section (tree, bool);
+extern section *default_clone_table_section (void);
+extern section *default_select_rtx_section (machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+extern section *default_elf_select_rtx_section (machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+extern void default_encode_section_info (tree, rtx, int);
+extern const char *default_strip_name_encoding (const char *);
+extern void default_asm_output_anchor (rtx);
+extern bool default_use_anchors_for_symbol_p (const_rtx);
+extern bool default_binds_local_p (const_tree);
+extern bool default_binds_local_p_1 (const_tree, int);
+extern bool default_binds_local_p_2 (const_tree);
+extern bool default_binds_local_p_3 (const_tree, bool, bool, bool, bool);
+extern void default_globalize_label (FILE *, const char *);
+extern void default_globalize_decl_name (FILE *, tree);
+extern void default_emit_unwind_label (FILE *, tree, int, int);
+extern void default_emit_except_table_label (FILE *);
+extern void default_generate_internal_label (char *, const char *,
+ unsigned long);
+extern void default_internal_label (FILE *, const char *, unsigned long);
+extern void default_asm_declare_constant_name (FILE *, const char *,
+ const_tree, HOST_WIDE_INT);
+extern void default_file_start (void);
+extern void file_end_indicate_exec_stack (void);
+extern void file_end_indicate_split_stack (void);
+
+extern void default_elf_asm_output_external (FILE *file, tree,
+ const char *);
+extern void default_elf_asm_output_limited_string (FILE *, const char *);
+extern void default_elf_asm_output_ascii (FILE *, const char *, unsigned int);
+extern void default_elf_internal_label (FILE *, const char *, unsigned long);
+
+extern void default_elf_init_array_asm_out_constructor (rtx, int);
+extern void default_elf_fini_array_asm_out_destructor (rtx, int);
+extern int maybe_assemble_visibility (tree);
+
+extern int default_address_cost (rtx, machine_mode, addr_space_t, bool);
+
+/* Stack usage. */
+extern void output_stack_usage (void);
+
+#endif /* ! GCC_OUTPUT_H */
diff --git a/support/cpp/gcc/params.opt b/support/cpp/gcc/params.opt
new file mode 100644
index 000000000..b88e13720
--- /dev/null
+++ b/support/cpp/gcc/params.opt
@@ -0,0 +1,1204 @@
+; Parameter options of the compiler.
+
+; Copyright (C) 2019-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/>.
+
+; See the GCC internals manual (options.texi) for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+-param=align-loop-iterations=
+Common Joined UInteger Var(param_align_loop_iterations) Init(4) Param Optimization
+Loops iterating at least selected number of iterations will get loop alignment.
+
+-param=align-threshold=
+Common Joined UInteger Var(param_align_threshold) Init(100) IntegerRange(1, 65536) Param Optimization
+Select fraction of the maximal frequency of executions of basic block in function given basic block get alignment.
+
+-param=asan-globals=
+Common Joined UInteger Var(param_asan_globals) Init(1) IntegerRange(0, 1) Param
+Enable asan globals protection.
+
+-param=asan-instrument-allocas=
+Common Joined UInteger Var(param_asan_protect_allocas) Init(1) IntegerRange(0, 1) Param Optimization
+Enable asan allocas/VLAs protection.
+
+-param=asan-instrument-reads=
+Common Joined UInteger Var(param_asan_instrument_reads) Init(1) IntegerRange(0, 1) Param Optimization
+Enable asan load operations protection.
+
+-param=asan-instrument-writes=
+Common Joined UInteger Var(param_asan_instrument_writes) Init(1) IntegerRange(0, 1) Param Optimization
+Enable asan store operations protection.
+
+-param=asan-instrumentation-with-call-threshold=
+Common Joined UInteger Var(param_asan_instrumentation_with_call_threshold) Init(7000) Param Optimization
+Use callbacks instead of inline code if number of accesses in function becomes greater or equal to this number.
+
+-param=asan-memintrin=
+Common Joined UInteger Var(param_asan_memintrin) Init(1) IntegerRange(0, 1) Param Optimization
+Enable asan builtin functions protection.
+
+-param=asan-stack=
+Common Joined UInteger Var(param_asan_stack) Init(1) IntegerRange(0, 1) Param Optimization
+Enable asan stack protection.
+
+-param=asan-use-after-return=
+Common Joined UInteger Var(param_asan_use_after_return) Init(1) IntegerRange(0, 1) Param Optimization
+Enable asan detection of use-after-return bugs.
+
+-param=hwasan-instrument-stack=
+Common Joined UInteger Var(param_hwasan_instrument_stack) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of statically sized stack-allocated variables.
+
+-param=hwasan-random-frame-tag=
+Common Joined UInteger Var(param_hwasan_random_frame_tag) Init(1) IntegerRange(0, 1) Param Optimization
+Use random base tag for each frame, as opposed to base always zero.
+
+-param=hwasan-instrument-allocas=
+Common Joined UInteger Var(param_hwasan_instrument_allocas) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of allocas/VLAs.
+
+-param=hwasan-instrument-reads=
+Common Joined UInteger Var(param_hwasan_instrument_reads) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of load operations.
+
+-param=hwasan-instrument-writes=
+Common Joined UInteger Var(param_hwasan_instrument_writes) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of store operations.
+
+-param=hwasan-instrument-mem-intrinsics=
+Common Joined UInteger Var(param_hwasan_instrument_mem_intrinsics) Init(1) IntegerRange(0, 1) Param Optimization
+Enable hwasan instrumentation of builtin functions.
+
+-param=avg-loop-niter=
+Common Joined UInteger Var(param_avg_loop_niter) Init(10) IntegerRange(1, 65536) Param Optimization
+Average number of iterations of a loop.
+
+-param=avoid-fma-max-bits=
+Common Joined UInteger Var(param_avoid_fma_max_bits) IntegerRange(0, 512) Param Optimization
+Maximum number of bits for which we avoid creating FMAs.
+
+-param=builtin-expect-probability=
+Common Joined UInteger Var(param_builtin_expect_probability) Init(90) IntegerRange(0, 100) Param Optimization
+Set the estimated probability in percentage for builtin expect. The default value is 90% probability.
+
+-param=builtin-string-cmp-inline-length=
+Common Joined UInteger Var(param_builtin_string_cmp_inline_length) Init(3) IntegerRange(0, 100) Param Optimization
+The maximum length of a constant string for a builtin string cmp call eligible for inlining. The default value is 3.
+
+-param=case-values-threshold=
+Common Joined UInteger Var(param_case_values_threshold) Param Optimization
+The smallest number of different values for which it is best to use a jump-table instead of a tree of conditional branches, if 0, use the default for the machine.
+
+-param=comdat-sharing-probability=
+Common Joined UInteger Var(param_comdat_sharing_probability) Init(20) Param Optimization
+Probability that COMDAT function will be shared with different compilation unit.
+
+-param=cxx-max-namespaces-for-diagnostic-help=
+Common Joined UInteger Var(param_cxx_max_namespaces_for_diagnostic_help) Init(1000) Param
+Maximum number of namespaces to search for alternatives when name lookup fails.
+
+-param=dse-max-alias-queries-per-store=
+Common Joined UInteger Var(param_dse_max_alias_queries_per_store) Init(256) Param Optimization
+Maximum number of queries into the alias oracle per store.
+
+-param=dse-max-object-size=
+Common Joined UInteger Var(param_dse_max_object_size) Init(256) Param Optimization
+Maximum size (in bytes) of objects tracked bytewise by dead store elimination.
+
+-param=early-inlining-insns=
+Common Joined UInteger Var(param_early_inlining_insns) Init(6) Optimization Param
+Maximal estimated growth of function body caused by early inlining of single call.
+
+-param=evrp-sparse-threshold=
+Common Joined UInteger Var(param_evrp_sparse_threshold) Init(800) Optimization Param
+Maximum number of basic blocks before EVRP uses a sparse cache.
+
+-param=evrp-switch-limit=
+Common Joined UInteger Var(param_evrp_switch_limit) Init(50) Optimization Param
+Maximum number of outgoing edges in a switch before EVRP will not process it.
+
+-param=evrp-mode=
+Common Joined Var(param_evrp_mode) Enum(evrp_mode) Init(EVRP_MODE_RVRP_ONLY) Param Optimization
+--param=evrp-mode=[legacy|ranger|legacy-first|ranger-first] Specifies the mode Early VRP should operate in.
+
+Enum
+Name(evrp_mode) Type(enum evrp_mode) UnknownError(unknown evrp mode %qs)
+
+EnumValue
+Enum(evrp_mode) String(legacy) Value(EVRP_MODE_EVRP_ONLY)
+
+EnumValue
+Enum(evrp_mode) String(ranger) Value(EVRP_MODE_RVRP_ONLY)
+
+EnumValue
+Enum(evrp_mode) String(legacy-first) Value(EVRP_MODE_EVRP_FIRST)
+
+EnumValue
+Enum(evrp_mode) String(ranger-first) Value(EVRP_MODE_RVRP_FIRST)
+
+-param=fsm-scale-path-blocks=
+Common Joined UInteger Var(param_fsm_scale_path_blocks) Init(3) IntegerRange(1, 10) Param Optimization
+Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements.
+
+-param=fsm-scale-path-stmts=
+Common Joined UInteger Var(param_fsm_scale_path_stmts) Init(2) IntegerRange(1, 10) Param Optimization
+Scale factor to apply to the number of statements in a threading path when comparing to the number of (scaled) blocks.
+
+-param=gcse-after-reload-critical-fraction=
+Common Joined UInteger Var(param_gcse_after_reload_critical_fraction) Init(10) Param Optimization
+The threshold ratio of critical edges execution count that permit performing redundancy elimination after reload.
+
+-param=gcse-after-reload-partial-fraction=
+Common Joined UInteger Var(param_gcse_after_reload_partial_fraction) Init(3) Param Optimization
+The threshold ratio for performing partial redundancy elimination after reload.
+
+-param=gcse-cost-distance-ratio=
+Common Joined UInteger Var(param_gcse_cost_distance_ratio) Init(10) Param Optimization
+Scaling factor in calculation of maximum distance an expression can be moved by GCSE optimizations.
+
+-param=gcse-unrestricted-cost=
+Common Joined UInteger Var(param_gcse_unrestricted_cost) Init(3) Param Optimization
+Cost at which GCSE optimizations will not constraint the distance an expression can travel.
+
+-param=ggc-min-expand=
+Common Joined UInteger Var(param_ggc_min_expand) Init(30) Param
+Minimum heap expansion to trigger garbage collection, as a percentage of the total size of the heap.
+
+-param=ggc-min-heapsize=
+Common Joined UInteger Var(param_ggc_min_heapsize) Init(4096) Param
+Minimum heap size before we start collecting garbage, in kilobytes.
+
+-param=gimple-fe-computed-hot-bb-threshold=
+Common Joined UInteger Var(param_gimple_fe_computed_hot_bb_threshold) Param
+The number of executions of a basic block which is considered hot. The parameter is used only in GIMPLE FE.
+
+-param=graphite-allow-codegen-errors=
+Common Joined UInteger Var(param_graphite_allow_codegen_errors) IntegerRange(0, 1) Param
+Whether codegen errors should be ICEs when -fchecking.
+
+-param=graphite-max-arrays-per-scop=
+Common Joined UInteger Var(param_graphite_max_arrays_per_scop) Init(100) Param Optimization
+Maximum number of arrays per SCoP.
+
+-param=graphite-max-nb-scop-params=
+Common Joined UInteger Var(param_graphite_max_nb_scop_params) Init(10) Param Optimization
+Maximum number of parameters in a SCoP.
+
+-param=hash-table-verification-limit=
+Common Joined UInteger Var(param_hash_table_verification_limit) Init(10) Param
+The number of elements for which hash table verification is done for each searched element.
+
+-param=hot-bb-count-fraction=
+Common Joined UInteger Var(param_hot_bb_count_fraction) Init(10000) Param
+The denominator n of fraction 1/n of the maximal execution count of a basic block in the entire program that a basic block needs to at least have in order to be considered hot (used in non-LTO mode).
+
+-param=hot-bb-count-ws-permille=
+Common Joined UInteger Var(param_hot_bb_count_ws_permille) Init(990) IntegerRange(0, 1000) Param
+The number of most executed permilles of the profiled execution of the entire program to which the execution count of a basic block must be part of in order to be considered hot (used in LTO mode).
+
+-param=hot-bb-frequency-fraction=
+Common Joined UInteger Var(param_hot_bb_frequency_fraction) Init(1000) Param
+The denominator n of fraction 1/n of the execution frequency of the entry block of a function that a basic block of this function needs to at least have in order to be considered hot.
+
+-param=inline-heuristics-hint-percent=
+Common Joined UInteger Var(param_inline_heuristics_hint_percent) Init(200) Optimization IntegerRange(100, 1000000) Param
+The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable.
+
+-param=inline-min-speedup=
+Common Joined UInteger Var(param_inline_min_speedup) Init(30) Optimization IntegerRange(0, 100) Param
+The minimal estimated speedup allowing inliner to ignore inline-insns-single and inline-insns-auto.
+
+-param=inline-unit-growth=
+Common Joined UInteger Var(param_inline_unit_growth) Init(40) Optimization Param
+How much can given compilation unit grow because of the inlining (in percent).
+
+-param=integer-share-limit=
+Common Joined UInteger Var(param_integer_share_limit) Init(251) IntegerRange(2, 65536) Param
+The upper bound for sharing integer constants.
+
+-param=ipa-cp-eval-threshold=
+Common Joined UInteger Var(param_ipa_cp_eval_threshold) Init(500) Param Optimization
+Threshold ipa-cp opportunity evaluation that is still considered beneficial to clone.
+
+-param=ipa-cp-loop-hint-bonus=
+Common Joined UInteger Var(param_ipa_cp_loop_hint_bonus) Init(64) Param Optimization
+Compile-time bonus IPA-CP assigns to candidates which make loop bounds or strides known.
+
+-param=ipa-cp-max-recursive-depth=
+Common Joined UInteger Var(param_ipa_cp_max_recursive_depth) Init(8) Param Optimization
+Maximum depth of recursive cloning for self-recursive function.
+
+-param=ipa-cp-min-recursive-probability=
+Common Joined UInteger Var(param_ipa_cp_min_recursive_probability) Init(2) Param Optimization
+Recursive cloning only when the probability of call being executed exceeds the parameter.
+
+-param=ipa-cp-recursive-freq-factor=
+Common Joined UInteger Var(param_ipa_cp_recursive_freq_factor) Init(6) Param Optimization
+When propagating IPA-CP effect estimates, multiply frequencies of recursive edges that bring back an unchanged value by this factor.
+
+-param=ipa-cp-recursion-penalty=
+Common Joined UInteger Var(param_ipa_cp_recursion_penalty) Init(40) IntegerRange(0, 100) Param Optimization
+Percentage penalty the recursive functions will receive when they are evaluated for cloning.
+
+-param=ipa-cp-single-call-penalty=
+Common Joined UInteger Var(param_ipa_cp_single_call_penalty) Init(15) IntegerRange(0, 100) Param Optimization
+Percentage penalty functions containing a single call to another function will receive when they are evaluated for cloning.
+
+-param=ipa-cp-unit-growth=
+Common Joined UInteger Var(param_ipa_cp_unit_growth) Init(10) Param Optimization
+How much can given compilation unit grow because of the interprocedural constant propagation (in percent).
+
+-param=ipa-cp-large-unit-insns=
+Common Joined UInteger Var(param_ipa_cp_large_unit_insns) Optimization Init(16000) Param
+The size of translation unit that IPA-CP pass considers large.
+
+-param=ipa-cp-value-list-size=
+Common Joined UInteger Var(param_ipa_cp_value_list_size) Init(8) Param Optimization
+Maximum size of a list of values associated with each parameter for interprocedural constant propagation.
+
+-param=ipa-cp-profile-count-base=
+Common Joined UInteger Var(param_ipa_cp_profile_count_base) Init(10) IntegerRange(0, 100) Param Optimization
+When using profile feedback, use the edge at this percentage position in frequncy histogram as the bases for IPA-CP heuristics.
+
+-param=ipa-jump-function-lookups=
+Common Joined UInteger Var(param_ipa_jump_function_lookups) Init(8) Param Optimization
+Maximum number of statements visited during jump function offset discovery.
+
+-param=ipa-max-aa-steps=
+Common Joined UInteger Var(param_ipa_max_aa_steps) Init(25000) Param Optimization
+Maximum number of statements that will be visited by IPA formal parameter analysis based on alias analysis in any given function.
+
+-param=ipa-max-agg-items=
+Common Joined UInteger Var(param_ipa_max_agg_items) Init(16) Param Optimization
+Maximum number of aggregate content items for a parameter in jump functions and lattices.
+
+-param=ipa-max-param-expr-ops=
+Common Joined UInteger Var(param_ipa_max_param_expr_ops) Init(10) Param Optimization
+Maximum number of operations in a parameter expression that can be handled by IPA analysis.
+
+-param=ipa-max-loop-predicates=
+Common Joined UInteger Var(param_ipa_max_loop_predicates) Init(16) Param Optimization
+Maximum number of different predicates used to track properties of loops in IPA analysis.
+
+-param=ipa-max-switch-predicate-bounds=
+Common Joined UInteger Var(param_ipa_max_switch_predicate_bounds) Init(5) Param Optimization
+Maximal number of boundary endpoints of case ranges of switch statement used during IPA function summary generation.
+
+-param=ipa-sra-max-replacements=
+Common Joined UInteger Var(param_ipa_sra_max_replacements) Optimization Init(8) IntegerRange(0, 16) Param
+Maximum pieces that IPA-SRA tracks per formal parameter, as a consequence, also the maximum number of replacements of a formal parameter.
+
+-param=ipa-sra-ptr-growth-factor=
+Common Joined UInteger Var(param_ipa_sra_ptr_growth_factor) Init(2) Param Optimization
+Maximum allowed growth of number and total size of new parameters that ipa-sra replaces a pointer to an aggregate with.
+
+-param=ira-loop-reserved-regs=
+Common Joined UInteger Var(param_ira_loop_reserved_regs) Init(2) Param Optimization
+The number of registers in each class kept unused by loop invariant motion.
+
+-param=ira-max-conflict-table-size=
+Common Joined UInteger Var(param_ira_max_conflict_table_size) Init(1000) Param Optimization
+Max size of conflict table in MB.
+
+-param=ira-max-loops-num=
+Common Joined UInteger Var(param_ira_max_loops_num) Init(100) Param Optimization
+Max loops number for regional RA.
+
+-param=ira-consider-dup-in-all-alts=
+Common Joined UInteger Var(param_ira_consider_dup_in_all_alts) Init(1) IntegerRange(0, 1) Param Optimization
+Control ira to consider matching constraint (duplicated operand number) heavily in all available alternatives for preferred register class. If it is set as zero, it means ira only respects the matching constraint when it's in the only available alternative with an appropriate register class. Otherwise, it means ira will check all available alternatives for preferred register class even if it has found some choice with an appropriate register class and respect the found qualified matching constraint.
+
+-param=iv-always-prune-cand-set-bound=
+Common Joined UInteger Var(param_iv_always_prune_cand_set_bound) Init(10) Param Optimization
+If number of candidates in the set is smaller, we always try to remove unused ivs during its optimization.
+
+-param=iv-consider-all-candidates-bound=
+Common Joined UInteger Var(param_iv_consider_all_candidates_bound) Init(40) Param Optimization
+Bound on number of candidates below that all candidates are considered in iv optimizations.
+
+-param=iv-max-considered-uses=
+Common Joined UInteger Var(param_iv_max_considered_uses) Init(250) Param Optimization
+Bound on number of iv uses in loop optimized in iv optimizations.
+
+-param=jump-table-max-growth-ratio-for-size=
+Common Joined UInteger Var(param_jump_table_max_growth_ratio_for_size) Init(300) Param Optimization
+The maximum code size growth ratio when expanding into a jump table (in percent). The parameter is used when optimizing for size.
+
+-param=jump-table-max-growth-ratio-for-speed=
+Common Joined UInteger Var(param_jump_table_max_growth_ratio_for_speed) Init(800) Param Optimization
+The maximum code size growth ratio when expanding into a jump table (in percent). The parameter is used when optimizing for speed.
+
+-param=l1-cache-line-size=
+Common Joined UInteger Var(param_l1_cache_line_size) Init(32) Param Optimization
+The size of L1 cache line.
+
+-param=destructive-interference-size=
+Common Joined UInteger Var(param_destruct_interfere_size) Init(0) Param Optimization
+The minimum recommended offset between two concurrently-accessed objects to
+avoid additional performance degradation due to contention introduced by the
+implementation. Typically the L1 cache line size, but can be larger to
+accommodate a variety of target processors with different cache line sizes.
+C++17 code might use this value in structure layout, but is strongly
+discouraged from doing so in public ABIs.
+
+-param=constructive-interference-size=
+Common Joined UInteger Var(param_construct_interfere_size) Init(0) Param Optimization
+The maximum recommended size of contiguous memory occupied by two objects
+accessed with temporal locality by concurrent threads. Typically the L1 cache
+line size, but can be smaller to accommodate a variety of target processors with
+different cache line sizes.
+
+-param=l1-cache-size=
+Common Joined UInteger Var(param_l1_cache_size) Init(64) Param Optimization
+The size of L1 cache.
+
+-param=l2-cache-size=
+Common Joined UInteger Var(param_l2_cache_size) Init(512) Param Optimization
+The size of L2 cache.
+
+-param=large-function-growth=
+Common Joined UInteger Var(param_large_function_growth) Optimization Init(100) Param
+Maximal growth due to inlining of large function (in percent).
+
+-param=large-function-insns=
+Common Joined UInteger Var(param_large_function_insns) Optimization Init(2700) Param
+The size of function body to be considered large.
+
+-param=large-stack-frame=
+Common Joined UInteger Var(param_large_stack_frame) Init(256) Optimization Param
+The size of stack frame to be considered large.
+
+-param=large-stack-frame-growth=
+Common Joined UInteger Var(param_stack_frame_growth) Optimization Init(1000) Param
+Maximal stack frame growth due to inlining (in percent).
+
+-param=large-unit-insns=
+Common Joined UInteger Var(param_large_unit_insns) Optimization Init(10000) Param
+The size of translation unit to be considered large.
+
+-param=lazy-modules=
+C++ Joined UInteger Var(param_lazy_modules) Init(32768) Param
+Maximum number of concurrently open C++ module files when lazy loading.
+
+-param=lim-expensive=
+Common Joined UInteger Var(param_lim_expensive) Init(20) Param Optimization
+The minimum cost of an expensive expression in the loop invariant motion.
+
+-param=logical-op-non-short-circuit=
+Common Joined UInteger Var(param_logical_op_non_short_circuit) Init(-1) IntegerRange(0, 1) Param
+True if a non-short-circuit operation is optimal.
+
+-param=loop-block-tile-size=
+Common Joined UInteger Var(param_loop_block_tile_size) Init(51) Param Optimization
+Size of tiles for loop blocking.
+
+-param=loop-interchange-max-num-stmts=
+Common Joined UInteger Var(param_loop_interchange_max_num_stmts) Init(64) Param Optimization
+The maximum number of stmts in loop nest for loop interchange.
+
+-param=loop-interchange-stride-ratio=
+Common Joined UInteger Var(param_loop_interchange_stride_ratio) Init(2) Param Optimization
+The minimum stride ratio for loop interchange to be profitable.
+
+-param=loop-invariant-max-bbs-in-loop=
+Common Joined UInteger Var(param_loop_invariant_max_bbs_in_loop) Init(10000) Param Optimization
+Max basic blocks number in loop for loop invariant motion.
+
+-param=loop-max-datarefs-for-datadeps=
+Common Joined UInteger Var(param_loop_max_datarefs_for_datadeps) Init(1000) Param Optimization
+Maximum number of datarefs in loop for building loop data dependencies.
+
+-param=loop-versioning-max-inner-insns=
+Common Joined UInteger Var(param_loop_versioning_max_inner_insns) Init(200) Param Optimization
+The maximum number of instructions in an inner loop that is being considered for versioning.
+
+-param=loop-versioning-max-outer-insns=
+Common Joined UInteger Var(param_loop_versioning_max_outer_insns) Init(100) Param Optimization
+The maximum number of instructions in an outer loop that is being considered for versioning, on top of the instructions in inner loops.
+
+-param=lra-inheritance-ebb-probability-cutoff=
+Common Joined UInteger Var(param_lra_inheritance_ebb_probability_cutoff) Init(40) IntegerRange(0, 100) Param Optimization
+Minimal fall-through edge probability in percentage used to add BB to inheritance EBB in LRA.
+
+-param=lra-max-considered-reload-pseudos=
+Common Joined UInteger Var(param_lra_max_considered_reload_pseudos) Init(500) Param Optimization
+The max number of reload pseudos which are considered during spilling a non-reload pseudo.
+
+-param=lto-max-partition=
+Common Joined UInteger Var(param_max_partition_size) Init(1000000) Param
+Maximal size of a partition for LTO (in estimated instructions).
+
+-param=lto-max-streaming-parallelism=
+Common Joined UInteger Var(param_max_lto_streaming_parallelism) Init(32) IntegerRange(1, 65536) Param
+maximal number of LTO partitions streamed in parallel.
+
+-param=lto-min-partition=
+Common Joined UInteger Var(param_min_partition_size) Init(10000) Param
+Minimal size of a partition for LTO (in estimated instructions).
+
+-param=lto-partitions=
+Common Joined UInteger Var(param_lto_partitions) Init(128) IntegerRange(1, 65536) Param
+Number of partitions the program should be split to.
+
+-param=max-average-unrolled-insns=
+Common Joined UInteger Var(param_max_average_unrolled_insns) Init(80) Param Optimization
+The maximum number of instructions to consider to unroll in a loop on average.
+
+-param=max-combine-insns=
+Common Joined UInteger Var(param_max_combine_insns) Init(4) IntegerRange(2, 4) Param Optimization
+The maximum number of insns combine tries to combine.
+
+-param=max-completely-peel-loop-nest-depth=
+Common Joined UInteger Var(param_max_unroll_iterations) Init(8) Param Optimization
+The maximum depth of a loop nest we completely peel.
+
+-param=max-completely-peel-times=
+Common Joined UInteger Var(param_max_completely_peel_times) Init(16) Param Optimization
+The maximum number of peelings of a single loop that is peeled completely.
+
+-param=max-completely-peeled-insns=
+Common Joined UInteger Var(param_max_completely_peeled_insns) Init(200) Param Optimization
+The maximum number of insns of a completely peeled loop.
+
+-param=max-crossjump-edges=
+Common Joined UInteger Var(param_max_crossjump_edges) Init(100) Param Optimization
+The maximum number of incoming edges to consider for crossjumping.
+
+-param=max-cse-insns=
+Common Joined UInteger Var(param_max_cse_insns) Init(1000) Param Optimization
+The maximum instructions CSE process before flushing.
+
+-param=max-cse-path-length=
+Common Joined UInteger Var(param_max_cse_path_length) Init(10) IntegerRange(1, 65536) Param Optimization
+The maximum length of path considered in cse.
+
+-param=max-cselib-memory-locations=
+Common Joined UInteger Var(param_max_cselib_memory_locations) Init(500) Param Optimization
+The maximum memory locations recorded by cselib.
+
+-param=max-debug-marker-count=
+Common Joined UInteger Var(param_max_debug_marker_count) Init(100000) Param Optimization
+Max. count of debug markers to expand or inline.
+
+-param=max-delay-slot-insn-search=
+Common Joined UInteger Var(param_max_delay_slot_insn_search) Init(100) Param Optimization
+The maximum number of instructions to consider to fill a delay slot.
+
+-param=max-delay-slot-live-search=
+Common Joined UInteger Var(param_max_delay_slot_live_search) Init(333) Param Optimization
+The maximum number of instructions to consider to find accurate live register information.
+
+-param=max-dse-active-local-stores=
+Common Joined UInteger Var(param_max_dse_active_local_stores) Init(5000) Param Optimization
+Maximum number of active local stores in RTL dead store elimination.
+
+-param=max-early-inliner-iterations=
+Common Joined UInteger Var(param_early_inliner_max_iterations) Init(1) Param Optimization
+The maximum number of nested indirect inlining performed by early inliner.
+
+-param=max-fields-for-field-sensitive=
+Common Joined UInteger Var(param_max_fields_for_field_sensitive) Param
+Maximum number of fields in a structure before pointer analysis treats the structure as a single variable.
+
+-param=max-fsm-thread-length=
+Common Joined UInteger Var(param_max_fsm_thread_length) Init(10) IntegerRange(1, 999999) Param Optimization
+Maximum number of basic blocks on a jump thread path.
+
+-param=max-fsm-thread-path-insns=
+Common Joined UInteger Var(param_max_fsm_thread_path_insns) Init(100) IntegerRange(1, 999999) Param Optimization
+Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path.
+
+-param=max-gcse-insertion-ratio=
+Common Joined UInteger Var(param_max_gcse_insertion_ratio) Init(20) Param Optimization
+The maximum ratio of insertions to deletions of expressions in GCSE.
+
+-param=max-gcse-memory=
+Common Joined UInteger Var(param_max_gcse_memory) Init(131072) Param Optimization
+The maximum amount of memory to be allocated by GCSE, in kilobytes.
+
+-param=max-goto-duplication-insns=
+Common Joined UInteger Var(param_max_goto_duplication_insns) Init(8) Param Optimization
+The maximum number of insns to duplicate when unfactoring computed gotos.
+
+-param=max-grow-copy-bb-insns=
+Common Joined UInteger Var(param_max_grow_copy_bb_insns) Init(8) Param Optimization
+The maximum expansion factor when copying basic blocks.
+
+-param=max-hoist-depth=
+Common Joined UInteger Var(param_max_hoist_depth) Init(30) Param Optimization
+Maximum depth of search in the dominator tree for expressions to hoist.
+
+-param=max-inline-functions-called-once-loop-depth=
+Common Joined UInteger Var(param_inline_functions_called_once_loop_depth) Init(6) Optimization Param
+Maximum loop depth of a call which is considered for inlining functions called once.
+
+-param=max-inline-functions-called-once-insns=
+Common Joined UInteger Var(param_inline_functions_called_once_insns) Init(4000) Optimization Param
+Maximum combined size of caller and callee which is inlined if callee is called once.
+
+-param=max-inline-insns-auto=
+Common Joined UInteger Var(param_max_inline_insns_auto) Init(15) Optimization Param
+The maximum number of instructions when automatically inlining.
+
+-param=max-inline-insns-recursive=
+Common Joined UInteger Var(param_max_inline_insns_recursive) Optimization Init(450) Param
+The maximum number of instructions inline function can grow to via recursive inlining.
+
+-param=max-inline-insns-recursive-auto=
+Common Joined UInteger Var(param_max_inline_insns_recursive_auto) Optimization Init(450) Param
+The maximum number of instructions non-inline function can grow to via recursive inlining.
+
+-param=max-inline-insns-single=
+Common Joined UInteger Var(param_max_inline_insns_single) Optimization Init(70) Param
+The maximum number of instructions in a single function eligible for inlining.
+
+-param=max-inline-insns-size=
+Common Joined UInteger Var(param_max_inline_insns_size) Optimization Param
+The maximum number of instructions when inlining for size.
+
+-param=max-inline-insns-small=
+Common Joined UInteger Var(param_max_inline_insns_small) Optimization Param
+The maximum number of instructions when automatically inlining small functions.
+
+-param=max-inline-recursive-depth=
+Common Joined UInteger Var(param_max_inline_recursive_depth) Optimization Init(8) Param
+The maximum depth of recursive inlining for inline functions.
+
+-param=max-inline-recursive-depth-auto=
+Common Joined UInteger Var(param_max_inline_recursive_depth_auto) Optimization Init(8) Param
+The maximum depth of recursive inlining for non-inline functions.
+
+-param=max-isl-operations=
+Common Joined UInteger Var(param_max_isl_operations) Init(350000) Param Optimization
+Maximum number of isl operations, 0 means unlimited.
+
+-param=max-iterations-computation-cost=
+Common Joined UInteger Var(param_max_iterations_computation_cost) Init(10) Param Optimization
+Bound on the cost of an expression to compute the number of iterations.
+
+-param=max-iterations-to-track=
+Common Joined UInteger Var(param_max_iterations_to_track) Init(1000) Param Optimization
+Bound on the number of iterations the brute force # of iterations analysis algorithm evaluates.
+
+-param=max-jump-thread-duplication-stmts=
+Common Joined UInteger Var(param_max_jump_thread_duplication_stmts) Init(15) Param Optimization
+Maximum number of statements allowed in a block that needs to be duplicated when threading jumps.
+
+-param=max-last-value-rtl=
+Common Joined UInteger Var(param_max_last_value_rtl) Init(10000) Param Optimization
+The maximum number of RTL nodes that can be recorded as combiner's last value.
+
+-param=max-loop-header-insns=
+Common Joined UInteger Var(param_max_loop_header_insns) Init(20) Param Optimization
+The maximum number of insns in loop header duplicated by the copy loop headers pass.
+
+-param=max-modulo-backtrack-attempts=
+Common Joined UInteger Var(param_max_modulo_backtrack_attempts) Init(40) Param Optimization
+The maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop.
+
+-param=min-pagesize=
+Common Joined UInteger Var(param_min_pagesize) Init(4096) Param Optimization
+Minimum page size for warning purposes.
+
+-param=max-partial-antic-length=
+Common Joined UInteger Var(param_max_partial_antic_length) Init(100) Param Optimization
+Maximum length of partial antic set when performing tree pre optimization.
+
+-param=max-peel-branches=
+Common Joined UInteger Var(param_max_peel_branches) Init(32) Param Optimization
+The maximum number of branches on the path through the peeled sequence.
+
+-param=max-peel-times=
+Common Joined UInteger Var(param_max_peel_times) Init(16) Param Optimization
+The maximum number of peelings of a single loop.
+
+-param=max-peeled-insns=
+Common Joined UInteger Var(param_max_peeled_insns) Init(100) Param Optimization
+The maximum number of insns of a peeled loop.
+
+-param=max-pending-list-length=
+Common Joined UInteger Var(param_max_pending_list_length) Init(32) Param Optimization
+The maximum length of scheduling's pending operations list.
+
+-param=max-pipeline-region-blocks=
+Common Joined UInteger Var(param_max_pipeline_region_blocks) Init(15) Param Optimization
+The maximum number of blocks in a region to be considered for interblock scheduling.
+
+-param=max-pipeline-region-insns=
+Common Joined UInteger Var(param_max_pipeline_region_insns) Init(200) Param Optimization
+The maximum number of insns in a region to be considered for interblock scheduling.
+
+-param=max-pow-sqrt-depth=
+Common Joined UInteger Var(param_max_pow_sqrt_depth) Init(5) IntegerRange(1, 32) Param Optimization
+Maximum depth of sqrt chains to use when synthesizing exponentiation by a real constant.
+
+-param=max-predicted-iterations=
+Common Joined UInteger Var(param_max_predicted_iterations) Init(100) IntegerRange(0, 65536) Param Optimization
+The maximum number of loop iterations we predict statically.
+
+-param=max-reload-search-insns=
+Common Joined UInteger Var(param_max_reload_search_insns) Init(100) Param Optimization
+The maximum number of instructions to search backward when looking for equivalent reload.
+
+-param=max-rtl-if-conversion-insns=
+Common Joined UInteger Var(param_max_rtl_if_conversion_insns) Init(10) IntegerRange(0, 99) Param Optimization
+Maximum number of insns in a basic block to consider for RTL if-conversion.
+
+-param=max-rtl-if-conversion-predictable-cost=
+Common Joined UInteger Var(param_max_rtl_if_conversion_predictable_cost) Init(20) IntegerRange(0, 200) Param Optimization
+Maximum permissible cost for the sequence that would be generated by the RTL if-conversion pass for a branch that is considered predictable.
+
+-param=max-rtl-if-conversion-unpredictable-cost=
+Common Joined UInteger Var(param_max_rtl_if_conversion_unpredictable_cost) Init(40) IntegerRange(0, 200) Param Optimization
+Maximum permissible cost for the sequence that would be generated by the RTL if-conversion pass for a branch that is considered unpredictable.
+
+-param=max-sched-extend-regions-iters=
+Common Joined UInteger Var(param_max_sched_extend_regions_iters) Param Optimization
+The maximum number of iterations through CFG to extend regions.
+
+-param=max-sched-insn-conflict-delay=
+Common Joined UInteger Var(param_max_sched_insn_conflict_delay) Init(3) IntegerRange(1, 10) Param Optimization
+The maximum conflict delay for an insn to be considered for speculative motion.
+
+-param=max-sched-ready-insns=
+Common Joined UInteger Var(param_max_sched_ready_insns) Init(100) IntegerRange(1, 65536) Param Optimization
+The maximum number of instructions ready to be issued to be considered by the scheduler during the first scheduling pass.
+
+-param=max-sched-region-blocks=
+Common Joined UInteger Var(param_max_sched_region_blocks) Init(10) Param Optimization
+The maximum number of blocks in a region to be considered for interblock scheduling.
+
+-param=max-sched-region-insns=
+Common Joined UInteger Var(param_max_sched_region_insns) Init(100) Param Optimization
+The maximum number of insns in a region to be considered for interblock scheduling.
+
+-param=max-slsr-cand-scan=
+Common Joined UInteger Var(param_max_slsr_candidate_scan) Init(50) IntegerRange(1, 999999) Param Optimization
+Maximum length of candidate scans for straight-line strength reduction.
+
+-param=max-speculative-devirt-maydefs=
+Common Joined UInteger Var(param_max_speculative_devirt_maydefs) Init(50) Param Optimization
+Maximum number of may-defs visited when devirtualizing speculatively.
+
+-param=max-ssa-name-query-depth=
+Common Joined UInteger Var(param_max_ssa_name_query_depth) Init(3) IntegerRange(1, 10) Param
+Maximum recursion depth allowed when querying a property of an SSA name.
+
+-param=max-stores-to-merge=
+Common Joined UInteger Var(param_max_stores_to_merge) Init(64) IntegerRange(2, 65536) Param Optimization
+Maximum number of constant stores to merge in the store merging pass.
+
+-param=max-stores-to-sink=
+Common Joined UInteger Var(param_max_stores_to_sink) Init(2) Param Optimization
+Maximum number of conditional store pairs that can be sunk.
+
+-param=max-store-chains-to-track=
+Common Joined UInteger Var(param_max_store_chains_to_track) Init(64) IntegerRange(1, 65536) Param
+Maximum number of store chains to track at the same time in the store merging pass.
+
+-param=max-stores-to-track=
+Common Joined UInteger Var(param_max_stores_to_track) Init(1024) IntegerRange(2, 1048576) Param
+Maximum number of store chains to track at the same time in the store merging pass.
+
+-param=max-tail-merge-comparisons=
+Common Joined UInteger Var(param_max_tail_merge_comparisons) Init(10) Param Optimization
+Maximum amount of similar bbs to compare a bb with.
+
+-param=max-tail-merge-iterations=
+Common Joined UInteger Var(param_max_tail_merge_iterations) Init(2) Param Optimization
+Maximum amount of iterations of the pass over a function.
+
+-param=max-tracked-strlens=
+Common Joined UInteger Var(param_max_tracked_strlens) Init(10000) Param Optimization
+Maximum number of strings for which strlen optimization pass will track string lengths.
+
+-param=max-tree-if-conversion-phi-args=
+Common Joined UInteger Var(param_max_tree_if_conversion_phi_args) Init(4) IntegerRange(2, 65536) Param Optimization
+Maximum number of arguments in a PHI supported by TREE if-conversion unless the loop is marked with simd pragma.
+
+-param=max-unroll-times=
+Common Joined UInteger Var(param_max_unroll_times) Init(8) Param Optimization
+The maximum number of unrollings of a single loop.
+
+-param=max-unrolled-insns=
+Common Joined UInteger Var(param_max_unrolled_insns) Init(200) Param Optimization
+The maximum number of instructions to consider to unroll in a loop.
+
+-param=max-unswitch-insns=
+Common Joined UInteger Var(param_max_unswitch_insns) Init(50) Param Optimization
+The maximum number of insns of an unswitched loop.
+
+-param=max-unswitch-level=
+Common Joined UInteger Var(param_max_unswitch_level) Init(3) Param Optimization
+The maximum number of unswitchings in a single loop.
+
+-param=max-variable-expansions-in-unroller=
+Common Joined UInteger Var(param_max_variable_expansions) Init(1) Param Optimization
+If -fvariable-expansion-in-unroller is used, the maximum number of times that an individual variable will be expanded during loop unrolling.
+
+-param=max-vartrack-expr-depth=
+Common Joined UInteger Var(param_max_vartrack_expr_depth) Init(12) Param Optimization
+Max. recursion depth for expanding var tracking expressions.
+
+-param=max-vartrack-reverse-op-size=
+Common Joined UInteger Var(param_max_vartrack_reverse_op_size) Init(50) Param Optimization
+Max. size of loc list for which reverse ops should be added.
+
+-param=max-vartrack-size=
+Common Joined UInteger Var(param_max_vartrack_size) Init(50000000) Param Optimization
+Max. size of var tracking hash tables.
+
+-param=max-find-base-term-values=
+Common Joined UInteger Var(param_max_find_base_term_values) Init(200) Param Optimization
+Maximum number of VALUEs handled during a single find_base_term call.
+
+-param=max-vrp-switch-assertions=
+Common Joined UInteger Var(param_max_vrp_switch_assertions) Init(10) Param Optimization
+Maximum number of assertions to add along the default edge of a switch statement during VRP.
+
+-param=min-crossjump-insns=
+Common Joined UInteger Var(param_min_crossjump_insns) Init(5) IntegerRange(1, 65536) Param Optimization
+The minimum number of matching instructions to consider for crossjumping.
+
+-param=min-inline-recursive-probability=
+Common Joined UInteger Var(param_min_inline_recursive_probability) Init(10) Optimization Param
+Inline recursively only when the probability of call being executed exceeds the parameter.
+
+-param=min-insn-to-prefetch-ratio=
+Common Joined UInteger Var(param_min_insn_to_prefetch_ratio) Init(9) Param Optimization
+Min. ratio of insns to prefetches to enable prefetching for a loop with an unknown trip count.
+
+-param=min-loop-cond-split-prob=
+Common Joined UInteger Var(param_min_loop_cond_split_prob) Init(30) IntegerRange(0, 100) Param Optimization
+The minimum threshold for probability of semi-invariant condition statement to trigger loop split.
+
+-param=min-nondebug-insn-uid=
+Common Joined UInteger Var(param_min_nondebug_insn_uid) Param
+The minimum UID to be used for a nondebug insn.
+
+-param=min-size-for-stack-sharing=
+Common Joined UInteger Var(param_min_size_for_stack_sharing) Init(32) Param Optimization
+The minimum size of variables taking part in stack slot sharing when not optimizing.
+
+-param=min-spec-prob=
+Common Joined UInteger Var(param_min_spec_prob) Init(40) Param Optimization
+The minimum probability of reaching a source block for interblock speculative scheduling.
+
+-param=min-vect-loop-bound=
+Common Joined UInteger Var(param_min_vect_loop_bound) Param Optimization
+If -ftree-vectorize is used, the minimal loop bound of a loop to be considered for vectorization.
+
+-param=openacc-kernels=
+Common Joined Enum(openacc_kernels) Var(param_openacc_kernels) Init(OPENACC_KERNELS_PARLOOPS) Param
+--param=openacc-kernels=[decompose|parloops] Specify mode of OpenACC 'kernels' constructs handling.
+
+Enum
+Name(openacc_kernels) Type(enum openacc_kernels)
+
+EnumValue
+Enum(openacc_kernels) String(decompose) Value(OPENACC_KERNELS_DECOMPOSE)
+
+EnumValue
+Enum(openacc_kernels) String(parloops) Value(OPENACC_KERNELS_PARLOOPS)
+
+-param=openacc-privatization=
+Common Joined Enum(openacc_privatization) Var(param_openacc_privatization) Init(OPENACC_PRIVATIZATION_QUIET) Param
+--param=openacc-privatization=[quiet|noisy] Specify mode of OpenACC privatization diagnostics.
+
+Enum
+Name(openacc_privatization) Type(enum openacc_privatization)
+
+EnumValue
+Enum(openacc_privatization) String(quiet) Value(OPENACC_PRIVATIZATION_QUIET)
+
+EnumValue
+Enum(openacc_privatization) String(noisy) Value(OPENACC_PRIVATIZATION_NOISY)
+
+-param=parloops-chunk-size=
+Common Joined UInteger Var(param_parloops_chunk_size) Param Optimization
+Chunk size of omp schedule for loops parallelized by parloops.
+
+-param=parloops-min-per-thread=
+Common Joined UInteger Var(param_parloops_min_per_thread) Init(100) IntegerRange(2, 65536) Param Optimization
+Minimum number of iterations per thread of an innermost parallelized loop.
+
+-param=parloops-schedule=
+Common Joined Var(param_parloops_schedule) Enum(parloops_schedule_type) Param Optimization
+--param=parloops-schedule=[static|dynamic|guided|auto|runtime] Schedule type of omp schedule for loops parallelized by parloops.
+
+Enum
+Name(parloops_schedule_type) Type(int)
+
+EnumValue
+Enum(parloops_schedule_type) String(static) Value(PARLOOPS_SCHEDULE_STATIC)
+
+EnumValue
+Enum(parloops_schedule_type) String(dynamic) Value(PARLOOPS_SCHEDULE_DYNAMIC)
+
+EnumValue
+Enum(parloops_schedule_type) String(guided) Value(PARLOOPS_SCHEDULE_GUIDED)
+
+EnumValue
+Enum(parloops_schedule_type) String(auto) Value(PARLOOPS_SCHEDULE_AUTO)
+
+EnumValue
+Enum(parloops_schedule_type) String(runtime) Value(PARLOOPS_SCHEDULE_RUNTIME)
+
+-param=partial-inlining-entry-probability=
+Common Joined UInteger Var(param_partial_inlining_entry_probability) Init(70) Optimization IntegerRange(0, 100) Param
+Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen.
+
+-param=predictable-branch-outcome=
+Common Joined UInteger Var(param_predictable_branch_outcome) Init(2) IntegerRange(0, 50) Param Optimization
+Maximal estimated outcome of branch considered predictable.
+
+-param=prefetch-dynamic-strides=
+Common Joined UInteger Var(param_prefetch_dynamic_strides) Init(1) IntegerRange(0, 1) Param Optimization
+Whether software prefetch hints should be issued for non-constant strides.
+
+-param=prefetch-latency=
+Common Joined UInteger Var(param_prefetch_latency) Init(200) Param Optimization
+The number of insns executed before prefetch is completed.
+
+-param=prefetch-min-insn-to-mem-ratio=
+Common Joined UInteger Var(param_prefetch_min_insn_to_mem_ratio) Init(3) Param Optimization
+Min. ratio of insns to mem ops to enable prefetching in a loop.
+
+-param=prefetch-minimum-stride=
+Common Joined UInteger Var(param_prefetch_minimum_stride) Init(-1) Param Optimization
+The minimum constant stride beyond which we should use prefetch hints for.
+
+-param=profile-func-internal-id=
+Common Joined UInteger Var(param_profile_func_internal_id) IntegerRange(0, 1) Param
+Use internal function id in profile lookup.
+
+-param=ranger-debug=
+Common Joined Var(param_ranger_debug) Enum(ranger_debug) Init(RANGER_DEBUG_NONE) Param Optimization
+--param=ranger-debug=[none|trace|gori|cache|tracegori|all] Specifies the output mode for debugging ranger.
+
+Enum
+Name(ranger_debug) Type(enum ranger_debug) UnknownError(unknown ranger debug mode %qs)
+
+EnumValue
+Enum(ranger_debug) String(none) Value(RANGER_DEBUG_NONE)
+
+EnumValue
+Enum(ranger_debug) String(trace) Value(RANGER_DEBUG_TRACE)
+
+EnumValue
+Enum(ranger_debug) String(cache) Value(RANGER_DEBUG_TRACE_CACHE)
+
+EnumValue
+Enum(ranger_debug) String(gori) Value(RANGER_DEBUG_GORI)
+
+EnumValue
+Enum(ranger_debug) String(tracegori) Value(RANGER_DEBUG_TRACE_GORI)
+
+EnumValue
+Enum(ranger_debug) String(all) Value(RANGER_DEBUG_ALL)
+
+-param=ranger-logical-depth=
+Common Joined UInteger Var(param_ranger_logical_depth) Init(6) IntegerRange(1, 999) Param Optimization
+Maximum depth of logical expression evaluation ranger will look through when
+evaluating outgoing edge ranges.
+
+-param=relation-block-limit=
+Common Joined UInteger Var(param_relation_block_limit) Init(200) IntegerRange(0, 9999) Param Optimization
+Maximum number of relations the oracle will register in a basic block.
+
+-param=rpo-vn-max-loop-depth=
+Common Joined UInteger Var(param_rpo_vn_max_loop_depth) Init(7) IntegerRange(2, 65536) Param Optimization
+Maximum depth of a loop nest to fully value-number optimistically.
+
+-param=sccvn-max-alias-queries-per-access=
+Common Joined UInteger Var(param_sccvn_max_alias_queries_per_access) Init(1000) Param Optimization
+Maximum number of disambiguations to perform per memory access.
+
+-param=scev-max-expr-complexity=
+Common Joined UInteger Var(param_scev_max_expr_complexity) Init(10) Param Optimization
+Bound on the complexity of the expressions in the scalar evolutions analyzer.
+
+-param=scev-max-expr-size=
+Common Joined UInteger Var(param_scev_max_expr_size) Init(100) Param Optimization
+Bound on size of expressions used in the scalar evolutions analyzer.
+
+-param=sched-autopref-queue-depth=
+Common Joined UInteger Var(param_sched_autopref_queue_depth) Init(-1) Param Optimization
+Hardware autoprefetcher scheduler model control flag. Number of lookahead cycles the model looks into, at '0' only enable instruction sorting heuristic. Disabled by default.
+
+-param=sched-mem-true-dep-cost=
+Common Joined UInteger Var(param_sched_mem_true_dep_cost) Init(1) Param Optimization
+Minimal distance between possibly conflicting store and load.
+
+-param=sched-pressure-algorithm=
+Common Joined UInteger Var(param_sched_pressure_algorithm) Init(1) IntegerRange(1, 2) Param Optimization
+Which -fsched-pressure algorithm to apply.
+
+-param=sched-spec-prob-cutoff=
+Common Joined UInteger Var(param_sched_spec_prob_cutoff) Init(40) IntegerRange(0, 100) Param Optimization
+The minimal probability of speculation success (in percents), so that speculative insn will be scheduled.
+
+-param=sched-state-edge-prob-cutoff=
+Common Joined UInteger Var(param_sched_state_edge_prob_cutoff) Init(10) IntegerRange(0, 100) Param Optimization
+The minimum probability an edge must have for the scheduler to save its state across it.
+
+-param=selsched-insns-to-rename=
+Common Joined UInteger Var(param_selsched_insns_to_rename) Init(2) Param Optimization
+Maximum number of instructions in the ready list that are considered eligible for renaming.
+
+-param=selsched-max-lookahead=
+Common Joined UInteger Var(param_selsched_max_lookahead) Init(50) Param Optimization
+The maximum size of the lookahead window of selective scheduling.
+
+-param=selsched-max-sched-times=
+Common Joined UInteger Var(param_selsched_max_sched_times) Init(2) IntegerRange(1, 65536) Param Optimization
+Maximum number of times that an insn could be scheduled.
+
+-param=simultaneous-prefetches=
+Common Joined UInteger Var(param_simultaneous_prefetches) Init(3) Param Optimization
+The number of prefetches that can run at the same time.
+
+-param=sink-frequency-threshold=
+Common Joined UInteger Var(param_sink_frequency_threshold) Init(75) IntegerRange(0, 100) Param Optimization
+Target block's relative execution frequency (as a percentage) required to sink a statement.
+
+-param=sms-dfa-history=
+Common Joined UInteger Var(param_sms_dfa_history) IntegerRange(0, 16) Param Optimization
+The number of cycles the swing modulo scheduler considers when checking conflicts using DFA.
+
+-param=sms-loop-average-count-threshold=
+Common Joined UInteger Var(param_sms_loop_average_count_threshold) Param Optimization
+A threshold on the average loop count considered by the swing modulo scheduler.
+
+-param=sms-max-ii-factor=
+Common Joined UInteger Var(param_sms_max_ii_factor) Init(2) IntegerRange(1, 16) Param Optimization
+A factor for tuning the upper bound that swing modulo scheduler uses for scheduling a loop.
+
+-param=sms-min-sc=
+Common Joined UInteger Var(param_sms_min_sc) Init(2) IntegerRange(1, 2) Param Optimization
+The minimum value of stage count that swing modulo scheduler will generate.
+
+-param=sra-max-scalarization-size-Osize=
+Common Joined UInteger Var(param_sra_max_scalarization_size_size) Param Optimization
+Maximum size, in storage units, of an aggregate which should be considered for scalarization when compiling for size.
+
+-param=sra-max-scalarization-size-Ospeed=
+Common Joined UInteger Var(param_sra_max_scalarization_size_speed) Param Optimization
+Maximum size, in storage units, of an aggregate which should be considered for scalarization when compiling for speed.
+
+-param=sra-max-propagations=
+Common Joined UInteger Var(param_sra_max_propagations) Param Optimization Init(32)
+Maximum number of artificial accesses to enable forward propagation that Scalar Replacement of Aggregates will keep for one local variable.
+
+-param=ssa-name-def-chain-limit=
+Common Joined UInteger Var(param_ssa_name_def_chain_limit) Init(512) Param Optimization
+The maximum number of SSA_NAME assignments to follow in determining a value.
+
+-param=ssp-buffer-size=
+Common Joined UInteger Var(param_ssp_buffer_size) Init(8) IntegerRange(1, 65536) Param Optimization
+The lower bound for a buffer to be considered for stack smashing protection.
+
+-param=stack-clash-protection-guard-size=
+Common Joined UInteger Var(param_stack_clash_protection_guard_size) Init(12) IntegerRange(12, 30) Param Optimization
+Size of the stack guard expressed as a power of two in bytes.
+
+-param=stack-clash-protection-probe-interval=
+Common Joined UInteger Var(param_stack_clash_protection_probe_interval) Init(12) IntegerRange(10, 16) Param Optimization
+Interval in which to probe the stack expressed as a power of two in bytes.
+
+-param=store-merging-allow-unaligned=
+Common Joined UInteger Var(param_store_merging_allow_unaligned) Init(1) IntegerRange(0, 1) Param Optimization
+Allow the store merging pass to introduce unaligned stores if it is legal to do so.
+
+-param=store-merging-max-size=
+Common Joined UInteger Var(param_store_merging_max_size) Init(65536) IntegerRange(1, 65536) Param Optimization
+Maximum size of a single store merging region in bytes.
+
+-param=switch-conversion-max-branch-ratio=
+Common Joined UInteger Var(param_switch_conversion_branch_ratio) Init(8) IntegerRange(1, 65536) Param Optimization
+The maximum ratio between array size and switch branches for a switch conversion to take place.
+
+-param=modref-max-bases=
+Common Joined UInteger Var(param_modref_max_bases) Init(32) Param Optimization
+Maximum number of bases stored in each modref tree.
+
+-param=modref-max-refs=
+Common Joined UInteger Var(param_modref_max_refs) Init(16) Param Optimization
+Maximum number of references stored in each modref base.
+
+-param=modref-max-accesses=
+Common Joined UInteger Var(param_modref_max_accesses) Init(16) Param Optimization
+Maximum number of accesses stored in each modref reference.
+
+-param=modref-max-tests=
+Common Joined UInteger Var(param_modref_max_tests) Init(64) Param Optimization
+Maximum number of tests performed by modref query.
+
+-param=modref-max-depth=
+Common Joined UInteger Var(param_modref_max_depth) Init(256) IntegerRange(1, 65536) Param Optimization
+Maximum depth of DFS walk used by modref escape analysis.
+
+-param=modref-max-escape-points=
+Common Joined UInteger Var(param_modref_max_escape_points) Init(256) Param Optimization
+Maximum number of escape points tracked by modref per SSA-name.
+
+-param=modref-max-adjustments=
+Common Joined UInteger Var(param_modref_max_adjustments) Init(8) IntegerRange(0, 254) Param Optimization
+Maximum number of times a given range is adjusted during the dataflow.
+
+-param=threader-debug=
+Common Joined Var(param_threader_debug) Enum(threader_debug) Init(THREADER_DEBUG_NONE) Param Optimization
+--param=threader-debug=[none|all] Enables verbose dumping of the threader solver.
+
+Enum
+Name(threader_debug) Type(enum threader_debug) UnknownError(unknown threader debug mode %qs)
+
+EnumValue
+Enum(threader_debug) String(none) Value(THREADER_DEBUG_NONE)
+
+EnumValue
+Enum(threader_debug) String(all) Value(THREADER_DEBUG_ALL)
+
+-param=tm-max-aggregate-size=
+Common Joined UInteger Var(param_tm_max_aggregate_size) Init(9) Param Optimization
+Size in bytes after which thread-local aggregates should be instrumented with the logging functions instead of save/restore pairs.
+
+-param=tracer-dynamic-coverage=
+Common Joined UInteger Var(param_tracer_dynamic_coverage) Init(75) IntegerRange(0, 100) Param Optimization
+The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is not available.
+
+-param=tracer-dynamic-coverage-feedback=
+Common Joined UInteger Var(param_tracer_dynamic_coverage_feedback) Init(95) IntegerRange(0, 100) Param Optimization
+The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is available.
+
+-param=tracer-max-code-growth=
+Common Joined UInteger Var(param_tracer_max_code_growth) Init(100) Param Optimization
+Maximal code growth caused by tail duplication (in percent).
+
+-param=tracer-min-branch-probability=
+Common Joined UInteger Var(param_tracer_min_branch_probability) Init(50) IntegerRange(0, 100) Param Optimization
+Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is not available.
+
+-param=tracer-min-branch-probability-feedback=
+Common Joined UInteger Var(param_tracer_min_branch_probability_feedback) Init(80) IntegerRange(0, 100) Param Optimization
+Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is available.
+
+-param=tracer-min-branch-ratio=
+Common Joined UInteger Var(param_tracer_min_branch_ratio) Init(10) IntegerRange(0, 100) Param Optimization
+Stop reverse growth if the reverse probability of best edge is less than this threshold (in percent).
+
+-param=tree-reassoc-width=
+Common Joined UInteger Var(param_tree_reassoc_width) Param Optimization
+Set the maximum number of instructions executed in parallel in reassociated tree. If 0, use the target dependent heuristic.
+
+-param=tsan-distinguish-volatile=
+Common Joined UInteger Var(param_tsan_distinguish_volatile) IntegerRange(0, 1) Param
+Emit special instrumentation for accesses to volatiles.
+
+-param=tsan-instrument-func-entry-exit=
+Common Joined UInteger Var(param_tsan_instrument_func_entry_exit) Init(1) IntegerRange(0, 1) Param
+Emit instrumentation calls to __tsan_func_entry() and __tsan_func_exit().
+
+-param=uninit-control-dep-attempts=
+Common Joined UInteger Var(param_uninit_control_dep_attempts) Init(1000) IntegerRange(1, 65536) Param Optimization
+Maximum number of nested calls to search for control dependencies during uninitialized variable analysis.
+
+-param=uninlined-function-insns=
+Common Joined UInteger Var(param_uninlined_function_insns) Init(2) Optimization IntegerRange(0, 1000000) Param
+Instruction accounted for function prologue, epilogue and other overhead.
+
+-param=uninlined-function-time=
+Common Joined UInteger Var(param_uninlined_function_time) Optimization IntegerRange(0, 1000000) Param
+Time accounted for function prologue, epilogue and other overhead.
+
+-param=uninlined-thunk-insns=
+Common Joined UInteger Var(param_uninlined_function_thunk_insns) Optimization Init(2) IntegerRange(0, 1000000) Param
+Instruction accounted for function thunk overhead.
+
+-param=uninlined-thunk-time=
+Common Joined UInteger Var(param_uninlined_function_thunk_time) Optimization Init(2) IntegerRange(0, 1000000) Param
+Time accounted for function thunk overhead.
+
+-param=unlikely-bb-count-fraction=
+Common Joined UInteger Var(param_unlikely_bb_count_fraction) Init(20) Param Optimization
+The denominator n of fraction 1/n of the number of profiled runs of the entire program below which the execution count of a basic block must be in order for the basic block to be considered unlikely.
+
+-param=unroll-jam-max-unroll=
+Common Joined UInteger Var(param_unroll_jam_max_unroll) Init(4) Param Optimization
+Maximum unroll factor for the unroll-and-jam transformation.
+
+-param=unroll-jam-min-percent=
+Common Joined UInteger Var(param_unroll_jam_min_percent) Init(1) IntegerRange(0, 100) Param Optimization
+Minimum percentage of memrefs that must go away for unroll-and-jam to be considered profitable.
+
+-param=use-after-scope-direct-emission-threshold=
+Common Joined UInteger Var(param_use_after_scope_direct_emission_threshold) Init(256) Param Optimization
+Use direct poisoning/unpoisoning instructions for variables smaller or equal to this number.
+
+-param=use-canonical-types=
+Common Joined UInteger Var(param_use_canonical_types) Init(1) IntegerRange(0, 1) Param
+Whether to use canonical types.
+
+-param=vect-epilogues-nomask=
+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-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.
+
+-param=vect-max-version-for-alias-checks=
+Common Joined UInteger Var(param_vect_max_version_for_alias_checks) Init(10) Param Optimization
+Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check.
+
+-param=vect-max-version-for-alignment-checks=
+Common Joined UInteger Var(param_vect_max_version_for_alignment_checks) Init(6) Param Optimization
+Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check.
+
+-param=vect-partial-vector-usage=
+Common Joined UInteger Var(param_vect_partial_vector_usage) Init(2) IntegerRange(0, 2) Param Optimization
+Controls how loop vectorizer uses partial vectors. 0 means never, 1 means only for loops whose need to iterate can be removed, 2 means for all loops. The default value is 2.
+
+-param=vect-inner-loop-cost-factor=
+Common Joined UInteger Var(param_vect_inner_loop_cost_factor) Init(50) IntegerRange(1, 10000) Param Optimization
+The maximum factor which the loop vectorizer applies to the cost of statements in an inner loop relative to the loop being vectorized.
+
+-param=vect-induction-float=
+Common Joined UInteger Var(param_vect_induction_float) Init(1) IntegerRage(0, 1) Param Optimization
+Enable loop vectorization of floating point inductions.
+
+-param=vrp1-mode=
+Common Joined Var(param_vrp1_mode) Enum(vrp_mode) Init(VRP_MODE_VRP) Param Optimization
+--param=vrp1-mode=[vrp|ranger] Specifies the mode VRP1 should operate in.
+
+-param=vrp2-mode=
+Common Joined Var(param_vrp2_mode) Enum(vrp_mode) Init(VRP_MODE_RANGER) Param Optimization
+--param=vrp2-mode=[vrp|ranger] Specifies the mode VRP2 should operate in.
+
+Enum
+Name(vrp_mode) Type(enum vrp_mode) UnknownError(unknown vrp mode %qs)
+
+EnumValue
+Enum(vrp_mode) String(vrp) Value(VRP_MODE_VRP)
+
+EnumValue
+Enum(vrp_mode) String(ranger) Value(VRP_MODE_RANGER)
+
+; This comment is to ensure we retain the blank line above.
diff --git a/support/cpp/gcc/pass_manager.h b/support/cpp/gcc/pass_manager.h
new file mode 100644
index 000000000..43484da27
--- /dev/null
+++ b/support/cpp/gcc/pass_manager.h
@@ -0,0 +1,148 @@
+/* pass_manager.h - The pipeline of optimization passes
+ Copyright (C) 2013-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_PASS_MANAGER_H
+#define GCC_PASS_MANAGER_H
+
+class opt_pass;
+struct register_pass_info;
+
+/* Define a list of pass lists so that both passes.cc and plugins can easily
+ find all the pass lists. */
+#define GCC_PASS_LISTS \
+ DEF_PASS_LIST (all_lowering_passes) \
+ DEF_PASS_LIST (all_small_ipa_passes) \
+ DEF_PASS_LIST (all_regular_ipa_passes) \
+ DEF_PASS_LIST (all_late_ipa_passes) \
+ DEF_PASS_LIST (all_passes)
+
+#define DEF_PASS_LIST(LIST) PASS_LIST_NO_##LIST,
+enum pass_list
+{
+ GCC_PASS_LISTS
+ PASS_LIST_NUM
+};
+#undef DEF_PASS_LIST
+
+namespace gcc {
+
+class context;
+
+class pass_manager
+{
+public:
+ pass_manager (context *ctxt);
+ ~pass_manager ();
+
+ void register_pass (struct register_pass_info *pass_info);
+ void register_one_dump_file (opt_pass *pass);
+
+ opt_pass *get_pass_for_id (int id) const;
+
+ void dump_passes () const;
+
+ void dump_profile_report () const;
+
+ void finish_optimization_passes ();
+
+ /* Access to specific passes, so that the majority can be private. */
+ void execute_early_local_passes ();
+ unsigned int execute_pass_mode_switching ();
+
+ /* Various passes are manually cloned by epiphany. */
+ opt_pass *get_pass_split_all_insns () const {
+ return pass_split_all_insns_1;
+ }
+ opt_pass *get_pass_mode_switching () const {
+ return pass_mode_switching_1;
+ }
+ opt_pass *get_pass_peephole2 () const { return pass_peephole2_1; }
+ opt_pass *get_pass_profile () const { return pass_profile_1; }
+
+ void register_pass_name (opt_pass *pass, const char *name);
+
+ opt_pass *get_pass_by_name (const char *name);
+
+ opt_pass *get_rest_of_compilation () const
+ {
+ return pass_rest_of_compilation_1;
+ }
+ opt_pass *get_clean_slate () const { return pass_clean_state_1; }
+
+public:
+ /* The root of the compilation pass tree, once constructed. */
+ opt_pass *all_passes;
+ opt_pass *all_small_ipa_passes;
+ opt_pass *all_lowering_passes;
+ opt_pass *all_regular_ipa_passes;
+ opt_pass *all_late_ipa_passes;
+
+ /* A map from static pass id to optimization pass. */
+ opt_pass **passes_by_id;
+ int passes_by_id_size;
+
+ opt_pass **pass_lists[PASS_LIST_NUM];
+
+private:
+ void set_pass_for_id (int id, opt_pass *pass);
+ void register_dump_files (opt_pass *pass);
+ void create_pass_tab () const;
+
+private:
+ context *m_ctxt;
+ hash_map<free_string_hash, opt_pass *> *m_name_to_pass_map;
+
+ /* References to all of the individual passes.
+ These fields are generated via macro expansion.
+
+ For example:
+ NEXT_PASS (pass_build_cfg, 1);
+ within pass-instances.def means that there is a field:
+ opt_pass *pass_build_cfg_1;
+
+ Similarly, the various:
+ NEXT_PASS (pass_copy_prop, 1);
+ ...
+ NEXT_PASS (pass_copy_prop, 8);
+ in pass-instances.def lead to fields:
+ opt_pass *pass_copy_prop_1;
+ ...
+ opt_pass *pass_copy_prop_8; */
+
+#define INSERT_PASSES_AFTER(PASS)
+#define PUSH_INSERT_PASSES_WITHIN(PASS)
+#define POP_INSERT_PASSES()
+#define NEXT_PASS(PASS, NUM) opt_pass *PASS ## _ ## NUM
+#define NEXT_PASS_WITH_ARG(PASS, NUM, ARG) NEXT_PASS (PASS, NUM)
+#define TERMINATE_PASS_LIST(PASS)
+
+#include "pass-instances.def"
+
+#undef INSERT_PASSES_AFTER
+#undef PUSH_INSERT_PASSES_WITHIN
+#undef POP_INSERT_PASSES
+#undef NEXT_PASS
+#undef NEXT_PASS_WITH_ARG
+#undef TERMINATE_PASS_LIST
+
+}; // class pass_manager
+
+} // namespace gcc
+
+#endif /* ! GCC_PASS_MANAGER_H */
diff --git a/support/cpp/gcc/passes.def b/support/cpp/gcc/passes.def
new file mode 100644
index 000000000..375d3d62d
--- /dev/null
+++ b/support/cpp/gcc/passes.def
@@ -0,0 +1,538 @@
+/* Description of pass structure
+ 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/>. */
+
+/*
+ Macros that should be defined when using this file:
+ INSERT_PASSES_AFTER (PASS)
+ PUSH_INSERT_PASSES_WITHIN (PASS)
+ POP_INSERT_PASSES ()
+ NEXT_PASS (PASS)
+ TERMINATE_PASS_LIST (PASS)
+ */
+
+ /* All passes needed to lower the function into shape optimizers can
+ operate on. These passes are always run first on the function, but
+ backend might produce already lowered functions that are not processed
+ by these passes. */
+ INSERT_PASSES_AFTER (all_lowering_passes)
+ NEXT_PASS (pass_warn_unused_result);
+ NEXT_PASS (pass_diagnose_omp_blocks);
+ NEXT_PASS (pass_diagnose_tm_blocks);
+ NEXT_PASS (pass_omp_oacc_kernels_decompose);
+ NEXT_PASS (pass_lower_omp);
+ NEXT_PASS (pass_lower_cf);
+ NEXT_PASS (pass_lower_tm);
+ NEXT_PASS (pass_refactor_eh);
+ NEXT_PASS (pass_lower_eh);
+ NEXT_PASS (pass_coroutine_lower_builtins);
+ NEXT_PASS (pass_build_cfg);
+ NEXT_PASS (pass_warn_function_return);
+ NEXT_PASS (pass_coroutine_early_expand_ifns);
+ NEXT_PASS (pass_expand_omp);
+ NEXT_PASS (pass_build_cgraph_edges);
+ TERMINATE_PASS_LIST (all_lowering_passes)
+
+ /* Interprocedural optimization passes. */
+ INSERT_PASSES_AFTER (all_small_ipa_passes)
+ NEXT_PASS (pass_ipa_free_lang_data);
+ NEXT_PASS (pass_ipa_function_and_variable_visibility);
+ NEXT_PASS (pass_build_ssa_passes);
+ PUSH_INSERT_PASSES_WITHIN (pass_build_ssa_passes)
+ NEXT_PASS (pass_fixup_cfg);
+ NEXT_PASS (pass_build_ssa);
+ NEXT_PASS (pass_walloca, /*strict_mode_p=*/true);
+ NEXT_PASS (pass_warn_printf);
+ NEXT_PASS (pass_warn_nonnull_compare);
+ NEXT_PASS (pass_early_warn_uninitialized);
+ NEXT_PASS (pass_warn_access, /*early=*/true);
+ NEXT_PASS (pass_ubsan);
+ NEXT_PASS (pass_nothrow);
+ NEXT_PASS (pass_rebuild_cgraph_edges);
+ POP_INSERT_PASSES ()
+
+ NEXT_PASS (pass_local_optimization_passes);
+ PUSH_INSERT_PASSES_WITHIN (pass_local_optimization_passes)
+ NEXT_PASS (pass_fixup_cfg);
+ NEXT_PASS (pass_rebuild_cgraph_edges);
+ NEXT_PASS (pass_local_fn_summary);
+ NEXT_PASS (pass_early_inline);
+ NEXT_PASS (pass_warn_recursion);
+ NEXT_PASS (pass_all_early_optimizations);
+ PUSH_INSERT_PASSES_WITHIN (pass_all_early_optimizations)
+ NEXT_PASS (pass_remove_cgraph_callee_edges);
+ NEXT_PASS (pass_early_object_sizes);
+ /* Don't record nonzero bits before IPA to avoid
+ using too much memory. */
+ NEXT_PASS (pass_ccp, false /* nonzero_p */);
+ /* After CCP we rewrite no longer addressed locals into SSA
+ form if possible. */
+ NEXT_PASS (pass_forwprop);
+ NEXT_PASS (pass_early_thread_jumps, /*first=*/true);
+ NEXT_PASS (pass_sra_early);
+ /* pass_build_ealias is a dummy pass that ensures that we
+ execute TODO_rebuild_alias at this point. */
+ NEXT_PASS (pass_build_ealias);
+ NEXT_PASS (pass_fre, true /* may_iterate */);
+ NEXT_PASS (pass_early_vrp);
+ NEXT_PASS (pass_merge_phi);
+ NEXT_PASS (pass_dse);
+ NEXT_PASS (pass_cd_dce, false /* update_address_taken_p */);
+ NEXT_PASS (pass_phiopt, true /* early_p */);
+ NEXT_PASS (pass_tail_recursion);
+ NEXT_PASS (pass_if_to_switch);
+ NEXT_PASS (pass_convert_switch);
+ NEXT_PASS (pass_cleanup_eh);
+ NEXT_PASS (pass_profile);
+ NEXT_PASS (pass_local_pure_const);
+ NEXT_PASS (pass_modref);
+ /* Split functions creates parts that are not run through
+ early optimizations again. It is thus good idea to do this
+ late. */
+ NEXT_PASS (pass_split_functions);
+ NEXT_PASS (pass_strip_predict_hints, true /* early_p */);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_release_ssa_names);
+ NEXT_PASS (pass_rebuild_cgraph_edges);
+ NEXT_PASS (pass_local_fn_summary);
+ POP_INSERT_PASSES ()
+
+ NEXT_PASS (pass_ipa_remove_symbols);
+ NEXT_PASS (pass_ipa_oacc);
+ PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc)
+ NEXT_PASS (pass_ipa_pta);
+ /* Pass group that runs when the function is an offloaded function
+ containing oacc kernels loops. */
+ NEXT_PASS (pass_ipa_oacc_kernels);
+ PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc_kernels)
+ NEXT_PASS (pass_oacc_kernels);
+ PUSH_INSERT_PASSES_WITHIN (pass_oacc_kernels)
+ NEXT_PASS (pass_ch);
+ NEXT_PASS (pass_fre, true /* may_iterate */);
+ /* We use pass_lim to rewrite in-memory iteration and reduction
+ variable accesses in loops into local variables accesses. */
+ NEXT_PASS (pass_lim);
+ NEXT_PASS (pass_dominator, false /* may_peel_loop_headers_p */);
+ NEXT_PASS (pass_dce);
+ NEXT_PASS (pass_parallelize_loops, true /* oacc_kernels_p */);
+ NEXT_PASS (pass_expand_omp_ssa);
+ NEXT_PASS (pass_rebuild_cgraph_edges);
+ POP_INSERT_PASSES ()
+ POP_INSERT_PASSES ()
+ POP_INSERT_PASSES ()
+
+ NEXT_PASS (pass_target_clone);
+ NEXT_PASS (pass_ipa_auto_profile);
+ NEXT_PASS (pass_ipa_tree_profile);
+ PUSH_INSERT_PASSES_WITHIN (pass_ipa_tree_profile)
+ NEXT_PASS (pass_feedback_split_functions);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_ipa_free_fn_summary, true /* small_p */);
+ NEXT_PASS (pass_ipa_increase_alignment);
+ NEXT_PASS (pass_ipa_tm);
+ NEXT_PASS (pass_ipa_lower_emutls);
+ TERMINATE_PASS_LIST (all_small_ipa_passes)
+
+ INSERT_PASSES_AFTER (all_regular_ipa_passes)
+ NEXT_PASS (pass_analyzer);
+ NEXT_PASS (pass_ipa_odr);
+ NEXT_PASS (pass_ipa_whole_program_visibility);
+ NEXT_PASS (pass_ipa_profile);
+ NEXT_PASS (pass_ipa_icf);
+ NEXT_PASS (pass_ipa_devirt);
+ NEXT_PASS (pass_ipa_cp);
+ NEXT_PASS (pass_ipa_sra);
+ NEXT_PASS (pass_ipa_cdtor_merge);
+ NEXT_PASS (pass_ipa_fn_summary);
+ NEXT_PASS (pass_ipa_inline);
+ NEXT_PASS (pass_ipa_pure_const);
+ NEXT_PASS (pass_ipa_modref);
+ NEXT_PASS (pass_ipa_free_fn_summary, false /* small_p */);
+ NEXT_PASS (pass_ipa_reference);
+ /* This pass needs to be scheduled after any IP code duplication. */
+ NEXT_PASS (pass_ipa_single_use);
+ /* Comdat privatization come last, as direct references to comdat local
+ symbols are not allowed outside of the comdat group. Privatizing early
+ would result in missed optimizations due to this restriction. */
+ NEXT_PASS (pass_ipa_comdats);
+ TERMINATE_PASS_LIST (all_regular_ipa_passes)
+
+ /* Simple IPA passes executed after the regular passes. In WHOPR mode the
+ passes are executed after partitioning and thus see just parts of the
+ compiled unit. */
+ INSERT_PASSES_AFTER (all_late_ipa_passes)
+ NEXT_PASS (pass_ipa_pta);
+ NEXT_PASS (pass_omp_simd_clone);
+ TERMINATE_PASS_LIST (all_late_ipa_passes)
+
+ /* These passes are run after IPA passes on every function that is being
+ output to the assembler file. */
+ INSERT_PASSES_AFTER (all_passes)
+ NEXT_PASS (pass_fixup_cfg);
+ NEXT_PASS (pass_lower_eh_dispatch);
+ NEXT_PASS (pass_oacc_loop_designation);
+ NEXT_PASS (pass_omp_oacc_neuter_broadcast);
+ NEXT_PASS (pass_oacc_device_lower);
+ NEXT_PASS (pass_omp_device_lower);
+ NEXT_PASS (pass_omp_target_link);
+ NEXT_PASS (pass_adjust_alignment);
+ NEXT_PASS (pass_all_optimizations);
+ PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations)
+ NEXT_PASS (pass_remove_cgraph_callee_edges);
+ /* Initial scalar cleanups before alias computation.
+ They ensure memory accesses are not indirect wherever possible. */
+ NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
+ NEXT_PASS (pass_ccp, true /* nonzero_p */);
+ /* After CCP we rewrite no longer addressed locals into SSA
+ form if possible. */
+ NEXT_PASS (pass_object_sizes);
+ NEXT_PASS (pass_post_ipa_warn);
+ /* Must run before loop unrolling. */
+ NEXT_PASS (pass_warn_access, /*early=*/true);
+ NEXT_PASS (pass_complete_unrolli);
+ NEXT_PASS (pass_backprop);
+ NEXT_PASS (pass_phiprop);
+ NEXT_PASS (pass_forwprop);
+ /* pass_build_alias is a dummy pass that ensures that we
+ execute TODO_rebuild_alias at this point. */
+ NEXT_PASS (pass_build_alias);
+ NEXT_PASS (pass_return_slot);
+ NEXT_PASS (pass_fre, true /* may_iterate */);
+ NEXT_PASS (pass_merge_phi);
+ NEXT_PASS (pass_thread_jumps_full, /*first=*/true);
+ NEXT_PASS (pass_vrp, true /* warn_array_bounds_p */);
+ NEXT_PASS (pass_dse);
+ NEXT_PASS (pass_dce);
+ /* pass_stdarg is always run and at this point we execute
+ TODO_remove_unused_locals to prune CLOBBERs of dead
+ variables which are otherwise a churn on alias walkings. */
+ NEXT_PASS (pass_stdarg);
+ NEXT_PASS (pass_call_cdce);
+ NEXT_PASS (pass_cselim);
+ NEXT_PASS (pass_copy_prop);
+ NEXT_PASS (pass_tree_ifcombine);
+ NEXT_PASS (pass_merge_phi);
+ NEXT_PASS (pass_phiopt, false /* early_p */);
+ NEXT_PASS (pass_tail_recursion);
+ NEXT_PASS (pass_ch);
+ NEXT_PASS (pass_lower_complex);
+ NEXT_PASS (pass_sra);
+ /* The dom pass will also resolve all __builtin_constant_p calls
+ that are still there to 0. This has to be done after some
+ propagations have already run, but before some more dead code
+ is removed, and this place fits nicely. Remember this when
+ trying to move or duplicate pass_dominator somewhere earlier. */
+ NEXT_PASS (pass_thread_jumps, /*first=*/true);
+ NEXT_PASS (pass_dominator, true /* may_peel_loop_headers_p */);
+ /* Threading can leave many const/copy propagations in the IL.
+ Clean them up. Failure to do so well can lead to false
+ positives from warnings for erroneous code. */
+ NEXT_PASS (pass_copy_prop);
+ /* Identify paths that should never be executed in a conforming
+ program and isolate those paths. */
+ NEXT_PASS (pass_isolate_erroneous_paths);
+ NEXT_PASS (pass_reassoc, true /* early_p */);
+ NEXT_PASS (pass_dce);
+ NEXT_PASS (pass_forwprop);
+ NEXT_PASS (pass_phiopt, false /* early_p */);
+ NEXT_PASS (pass_ccp, true /* nonzero_p */);
+ /* After CCP we rewrite no longer addressed locals into SSA
+ form if possible. */
+ NEXT_PASS (pass_cse_sincos);
+ NEXT_PASS (pass_optimize_bswap);
+ NEXT_PASS (pass_laddress);
+ NEXT_PASS (pass_lim);
+ NEXT_PASS (pass_walloca, false);
+ NEXT_PASS (pass_pre);
+ NEXT_PASS (pass_sink_code, false /* unsplit edges */);
+ NEXT_PASS (pass_sancov);
+ NEXT_PASS (pass_asan);
+ NEXT_PASS (pass_tsan);
+ NEXT_PASS (pass_dse);
+ NEXT_PASS (pass_dce);
+ /* Pass group that runs when 1) enabled, 2) there are loops
+ in the function. Make sure to run pass_fix_loops before
+ to discover/remove loops before running the gate function
+ of pass_tree_loop. */
+ NEXT_PASS (pass_fix_loops);
+ NEXT_PASS (pass_tree_loop);
+ PUSH_INSERT_PASSES_WITHIN (pass_tree_loop)
+ /* Before loop_init we rewrite no longer addressed locals into SSA
+ form if possible. */
+ NEXT_PASS (pass_tree_loop_init);
+ NEXT_PASS (pass_tree_unswitch);
+ NEXT_PASS (pass_scev_cprop);
+ NEXT_PASS (pass_loop_split);
+ NEXT_PASS (pass_loop_versioning);
+ NEXT_PASS (pass_loop_jam);
+ /* All unswitching, final value replacement and splitting can expose
+ empty loops. Remove them now. */
+ NEXT_PASS (pass_cd_dce, false /* update_address_taken_p */);
+ NEXT_PASS (pass_iv_canon);
+ NEXT_PASS (pass_loop_distribution);
+ NEXT_PASS (pass_linterchange);
+ NEXT_PASS (pass_copy_prop);
+ NEXT_PASS (pass_graphite);
+ PUSH_INSERT_PASSES_WITHIN (pass_graphite)
+ NEXT_PASS (pass_graphite_transforms);
+ NEXT_PASS (pass_lim);
+ NEXT_PASS (pass_copy_prop);
+ NEXT_PASS (pass_dce);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_parallelize_loops, false /* oacc_kernels_p */);
+ NEXT_PASS (pass_expand_omp_ssa);
+ NEXT_PASS (pass_ch_vect);
+ NEXT_PASS (pass_if_conversion);
+ /* pass_vectorize must immediately follow pass_if_conversion.
+ Please do not add any other passes in between. */
+ NEXT_PASS (pass_vectorize);
+ PUSH_INSERT_PASSES_WITHIN (pass_vectorize)
+ NEXT_PASS (pass_dce);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_predcom);
+ NEXT_PASS (pass_complete_unroll);
+ NEXT_PASS (pass_pre_slp_scalar_cleanup);
+ PUSH_INSERT_PASSES_WITHIN (pass_pre_slp_scalar_cleanup)
+ NEXT_PASS (pass_fre, false /* may_iterate */);
+ NEXT_PASS (pass_dse);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_slp_vectorize);
+ NEXT_PASS (pass_loop_prefetch);
+ /* Run IVOPTs after the last pass that uses data-reference analysis
+ as that doesn't handle TARGET_MEM_REFs. */
+ NEXT_PASS (pass_iv_optimize);
+ NEXT_PASS (pass_lim);
+ NEXT_PASS (pass_tree_loop_done);
+ POP_INSERT_PASSES ()
+ /* Pass group that runs when pass_tree_loop is disabled or there
+ are no loops in the function. */
+ NEXT_PASS (pass_tree_no_loop);
+ PUSH_INSERT_PASSES_WITHIN (pass_tree_no_loop)
+ NEXT_PASS (pass_slp_vectorize);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_simduid_cleanup);
+ NEXT_PASS (pass_lower_vector_ssa);
+ NEXT_PASS (pass_lower_switch);
+ NEXT_PASS (pass_cse_reciprocals);
+ NEXT_PASS (pass_reassoc, false /* early_p */);
+ NEXT_PASS (pass_strength_reduction);
+ NEXT_PASS (pass_split_paths);
+ NEXT_PASS (pass_tracer);
+ NEXT_PASS (pass_fre, false /* may_iterate */);
+ /* After late FRE we rewrite no longer addressed locals into SSA
+ form if possible. */
+ NEXT_PASS (pass_thread_jumps, /*first=*/false);
+ NEXT_PASS (pass_dominator, false /* may_peel_loop_headers_p */);
+ NEXT_PASS (pass_strlen);
+ NEXT_PASS (pass_thread_jumps_full, /*first=*/false);
+ NEXT_PASS (pass_vrp, false /* warn_array_bounds_p */);
+ /* Run CCP to compute alignment and nonzero bits. */
+ NEXT_PASS (pass_ccp, true /* nonzero_p */);
+ NEXT_PASS (pass_warn_restrict);
+ NEXT_PASS (pass_dse);
+ NEXT_PASS (pass_cd_dce, true /* update_address_taken_p */);
+ /* After late CD DCE we rewrite no longer addressed locals into SSA
+ form if possible. */
+ NEXT_PASS (pass_forwprop);
+ NEXT_PASS (pass_sink_code, true /* unsplit edges */);
+ NEXT_PASS (pass_phiopt, false /* early_p */);
+ NEXT_PASS (pass_fold_builtins);
+ NEXT_PASS (pass_optimize_widening_mul);
+ NEXT_PASS (pass_store_merging);
+ NEXT_PASS (pass_tail_calls);
+ /* If DCE is not run before checking for uninitialized uses,
+ we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c).
+ However, this also causes us to misdiagnose cases that should be
+ real warnings (e.g., testsuite/gcc.dg/pr18501.c). */
+ NEXT_PASS (pass_dce);
+ /* Split critical edges before late uninit warning to reduce the
+ number of false positives from it. */
+ NEXT_PASS (pass_split_crit_edges);
+ NEXT_PASS (pass_late_warn_uninitialized);
+ NEXT_PASS (pass_local_pure_const);
+ NEXT_PASS (pass_modref);
+ /* uncprop replaces constants by SSA names. This makes analysis harder
+ and thus it should be run last. */
+ NEXT_PASS (pass_uncprop);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_all_optimizations_g);
+ PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations_g)
+ /* The idea is that with -Og we do not perform any IPA optimization
+ so post-IPA work should be restricted to semantically required
+ passes and all optimization work is done early. */
+ NEXT_PASS (pass_remove_cgraph_callee_edges);
+ NEXT_PASS (pass_strip_predict_hints, false /* early_p */);
+ /* Lower remaining pieces of GIMPLE. */
+ NEXT_PASS (pass_lower_complex);
+ NEXT_PASS (pass_lower_vector_ssa);
+ NEXT_PASS (pass_lower_switch);
+ /* Perform simple scalar cleanup which is constant/copy propagation. */
+ NEXT_PASS (pass_ccp, true /* nonzero_p */);
+ NEXT_PASS (pass_post_ipa_warn);
+ NEXT_PASS (pass_object_sizes);
+ /* Fold remaining builtins. */
+ NEXT_PASS (pass_fold_builtins);
+ NEXT_PASS (pass_strlen);
+ /* Copy propagation also copy-propagates constants, this is necessary
+ to forward object-size and builtin folding results properly. */
+ NEXT_PASS (pass_copy_prop);
+ NEXT_PASS (pass_dce);
+ NEXT_PASS (pass_sancov);
+ NEXT_PASS (pass_asan);
+ NEXT_PASS (pass_tsan);
+ /* ??? We do want some kind of loop invariant motion, but we possibly
+ need to adjust LIM to be more friendly towards preserving accurate
+ debug information here. */
+ /* Split critical edges before late uninit warning to reduce the
+ number of false positives from it. */
+ NEXT_PASS (pass_split_crit_edges);
+ NEXT_PASS (pass_late_warn_uninitialized);
+ /* uncprop replaces constants by SSA names. This makes analysis harder
+ and thus it should be run last. */
+ NEXT_PASS (pass_uncprop);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_tm_init);
+ PUSH_INSERT_PASSES_WITHIN (pass_tm_init)
+ NEXT_PASS (pass_tm_mark);
+ NEXT_PASS (pass_tm_memopt);
+ NEXT_PASS (pass_tm_edges);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_simduid_cleanup);
+ NEXT_PASS (pass_vtable_verify);
+ NEXT_PASS (pass_lower_vaarg);
+ NEXT_PASS (pass_lower_vector);
+ NEXT_PASS (pass_lower_complex_O0);
+ NEXT_PASS (pass_sancov_O0);
+ NEXT_PASS (pass_lower_switch_O0);
+ NEXT_PASS (pass_asan_O0);
+ NEXT_PASS (pass_tsan_O0);
+ NEXT_PASS (pass_sanopt);
+ NEXT_PASS (pass_cleanup_eh);
+ NEXT_PASS (pass_lower_resx);
+ NEXT_PASS (pass_nrv);
+ NEXT_PASS (pass_gimple_isel);
+ NEXT_PASS (pass_harden_conditional_branches);
+ NEXT_PASS (pass_harden_compares);
+ NEXT_PASS (pass_warn_access, /*early=*/false);
+ NEXT_PASS (pass_cleanup_cfg_post_optimizing);
+ NEXT_PASS (pass_warn_function_noreturn);
+
+ NEXT_PASS (pass_expand);
+
+ NEXT_PASS (pass_rest_of_compilation);
+ PUSH_INSERT_PASSES_WITHIN (pass_rest_of_compilation)
+ NEXT_PASS (pass_instantiate_virtual_regs);
+ NEXT_PASS (pass_into_cfg_layout_mode);
+ NEXT_PASS (pass_jump);
+ NEXT_PASS (pass_lower_subreg);
+ NEXT_PASS (pass_df_initialize_opt);
+ NEXT_PASS (pass_cse);
+ NEXT_PASS (pass_rtl_fwprop);
+ NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_rtl_pre);
+ NEXT_PASS (pass_rtl_hoist);
+ NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_rtl_store_motion);
+ NEXT_PASS (pass_cse_after_global_opts);
+ NEXT_PASS (pass_rtl_ifcvt);
+ NEXT_PASS (pass_reginfo_init);
+ /* Perform loop optimizations. It might be better to do them a bit
+ sooner, but we want the profile feedback to work more
+ efficiently. */
+ NEXT_PASS (pass_loop2);
+ PUSH_INSERT_PASSES_WITHIN (pass_loop2)
+ NEXT_PASS (pass_rtl_loop_init);
+ NEXT_PASS (pass_rtl_move_loop_invariants);
+ NEXT_PASS (pass_rtl_unroll_loops);
+ NEXT_PASS (pass_rtl_doloop);
+ NEXT_PASS (pass_rtl_loop_done);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_lower_subreg2);
+ NEXT_PASS (pass_web);
+ NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_cse2);
+ NEXT_PASS (pass_rtl_dse1);
+ NEXT_PASS (pass_rtl_fwprop_addr);
+ NEXT_PASS (pass_inc_dec);
+ NEXT_PASS (pass_initialize_regs);
+ NEXT_PASS (pass_ud_rtl_dce);
+ NEXT_PASS (pass_combine);
+ NEXT_PASS (pass_if_after_combine);
+ NEXT_PASS (pass_jump_after_combine);
+ NEXT_PASS (pass_partition_blocks);
+ NEXT_PASS (pass_outof_cfg_layout_mode);
+ NEXT_PASS (pass_split_all_insns);
+ NEXT_PASS (pass_lower_subreg3);
+ NEXT_PASS (pass_df_initialize_no_opt);
+ NEXT_PASS (pass_stack_ptr_mod);
+ NEXT_PASS (pass_mode_switching);
+ NEXT_PASS (pass_match_asm_constraints);
+ NEXT_PASS (pass_sms);
+ NEXT_PASS (pass_live_range_shrinkage);
+ NEXT_PASS (pass_sched);
+ NEXT_PASS (pass_early_remat);
+ NEXT_PASS (pass_ira);
+ NEXT_PASS (pass_reload);
+ NEXT_PASS (pass_postreload);
+ PUSH_INSERT_PASSES_WITHIN (pass_postreload)
+ NEXT_PASS (pass_postreload_cse);
+ NEXT_PASS (pass_gcse2);
+ NEXT_PASS (pass_split_after_reload);
+ NEXT_PASS (pass_ree);
+ NEXT_PASS (pass_compare_elim_after_reload);
+ NEXT_PASS (pass_thread_prologue_and_epilogue);
+ NEXT_PASS (pass_rtl_dse2);
+ NEXT_PASS (pass_stack_adjustments);
+ NEXT_PASS (pass_jump2);
+ NEXT_PASS (pass_duplicate_computed_gotos);
+ NEXT_PASS (pass_sched_fusion);
+ NEXT_PASS (pass_peephole2);
+ NEXT_PASS (pass_if_after_reload);
+ NEXT_PASS (pass_regrename);
+ NEXT_PASS (pass_cprop_hardreg);
+ NEXT_PASS (pass_fast_rtl_dce);
+ NEXT_PASS (pass_reorder_blocks);
+ NEXT_PASS (pass_leaf_regs);
+ NEXT_PASS (pass_split_before_sched2);
+ NEXT_PASS (pass_sched2);
+ NEXT_PASS (pass_stack_regs);
+ PUSH_INSERT_PASSES_WITHIN (pass_stack_regs)
+ NEXT_PASS (pass_split_before_regstack);
+ NEXT_PASS (pass_stack_regs_run);
+ POP_INSERT_PASSES ()
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_late_compilation);
+ PUSH_INSERT_PASSES_WITHIN (pass_late_compilation)
+ NEXT_PASS (pass_zero_call_used_regs);
+ NEXT_PASS (pass_compute_alignments);
+ NEXT_PASS (pass_variable_tracking);
+ NEXT_PASS (pass_free_cfg);
+ NEXT_PASS (pass_machine_reorg);
+ NEXT_PASS (pass_cleanup_barriers);
+ NEXT_PASS (pass_delay_slots);
+ NEXT_PASS (pass_split_for_shorten_branches);
+ NEXT_PASS (pass_convert_to_eh_region_ranges);
+ NEXT_PASS (pass_shorten_branches);
+ NEXT_PASS (pass_set_nothrow_function_flags);
+ NEXT_PASS (pass_dwarf2_frame);
+ NEXT_PASS (pass_final);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_df_finish);
+ POP_INSERT_PASSES ()
+ NEXT_PASS (pass_clean_state);
+ TERMINATE_PASS_LIST (all_passes)
diff --git a/support/cpp/gcc/plugin.def b/support/cpp/gcc/plugin.def
new file mode 100644
index 000000000..a8808288b
--- /dev/null
+++ b/support/cpp/gcc/plugin.def
@@ -0,0 +1,112 @@
+/* This file contains the definitions for plugin events in GCC.
+ Copyright (C) 2009-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/>. */
+
+/* Called before parsing the body of a function. */
+DEFEVENT (PLUGIN_START_PARSE_FUNCTION)
+
+/* After finishing parsing a function. */
+DEFEVENT (PLUGIN_FINISH_PARSE_FUNCTION)
+
+/* To hook into pass manager. */
+DEFEVENT (PLUGIN_PASS_MANAGER_SETUP)
+
+/* After finishing parsing a type. */
+DEFEVENT (PLUGIN_FINISH_TYPE)
+
+/* After finishing parsing a declaration. */
+DEFEVENT (PLUGIN_FINISH_DECL)
+
+/* Useful for summary processing. */
+DEFEVENT (PLUGIN_FINISH_UNIT)
+
+/* Allows to see low level AST in C and C++ frontends. */
+DEFEVENT (PLUGIN_PRE_GENERICIZE)
+
+/* Called before GCC exits. */
+DEFEVENT (PLUGIN_FINISH)
+
+/* Information about the plugin. */
+DEFEVENT (PLUGIN_INFO)
+
+/* Called at start of GCC Garbage Collection. */
+DEFEVENT (PLUGIN_GGC_START)
+
+/* Extend the GGC marking. */
+DEFEVENT (PLUGIN_GGC_MARKING)
+
+/* Called at end of GGC. */
+DEFEVENT (PLUGIN_GGC_END)
+
+/* Register an extra GGC root table. */
+DEFEVENT (PLUGIN_REGISTER_GGC_ROOTS)
+
+/* Called during attribute registration. */
+DEFEVENT (PLUGIN_ATTRIBUTES)
+
+/* Called before processing a translation unit. */
+DEFEVENT (PLUGIN_START_UNIT)
+
+/* Called during pragma registration. */
+DEFEVENT (PLUGIN_PRAGMAS)
+
+/* Called before first pass from all_passes. */
+DEFEVENT (PLUGIN_ALL_PASSES_START)
+
+/* Called after last pass from all_passes. */
+DEFEVENT (PLUGIN_ALL_PASSES_END)
+
+/* Called before first ipa pass. */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_START)
+
+/* Called after last ipa pass. */
+DEFEVENT (PLUGIN_ALL_IPA_PASSES_END)
+
+/* Allows to override pass gate decision for current_pass. */
+DEFEVENT (PLUGIN_OVERRIDE_GATE)
+
+/* Called before executing a pass. */
+DEFEVENT (PLUGIN_PASS_EXECUTION)
+
+/* Called before executing subpasses of a GIMPLE_PASS in
+ execute_ipa_pass_list. */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_START)
+
+/* Called after executing subpasses of a GIMPLE_PASS in
+ execute_ipa_pass_list. */
+DEFEVENT (PLUGIN_EARLY_GIMPLE_PASSES_END)
+
+/* Called when a pass is first instantiated. */
+DEFEVENT (PLUGIN_NEW_PASS)
+
+/* Called when a file is #include-d or given via the #line directive.
+ this could happen many times. The event data is the included file path,
+ as a const char* pointer. */
+DEFEVENT (PLUGIN_INCLUDE_FILE)
+
+/* Called when -fanalyzer starts. The event data is an
+ ana::plugin_analyzer_init_iface *. */
+DEFEVENT (PLUGIN_ANALYZER_INIT)
+
+/* When adding a new hard-coded plugin event, don't forget to edit in
+ file plugin.cc the functions register_callback and
+ invoke_plugin_callbacks_full accordingly! */
+
+/* After the hard-coded events above, plugins can dynamically allocate events
+ at run time.
+ PLUGIN_EVENT_FIRST_DYNAMIC only appears as last enum element. */
diff --git a/support/cpp/gcc/plugin.h b/support/cpp/gcc/plugin.h
new file mode 100644
index 000000000..ff999c405
--- /dev/null
+++ b/support/cpp/gcc/plugin.h
@@ -0,0 +1,205 @@
+/* Header file for internal GCC plugin mechanism.
+ Copyright (C) 2009-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 PLUGIN_H
+#define PLUGIN_H
+
+#include "highlev-plugin-common.h"
+
+/* Event names. */
+enum plugin_event
+{
+# define DEFEVENT(NAME) NAME,
+# include "plugin.def"
+# undef DEFEVENT
+ PLUGIN_EVENT_FIRST_DYNAMIC
+};
+
+/* All globals declared here have C linkage to reduce link compatibility
+ issues with implementation language choice and mangling. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const char **plugin_event_name;
+
+struct plugin_argument
+{
+ char *key; /* key of the argument. */
+ char *value; /* value is optional and can be NULL. */
+};
+
+/* Additional information about the plugin. Used by --help and --version. */
+
+struct plugin_info
+{
+ const char *version;
+ const char *help;
+};
+
+/* Represents the gcc version. Used to avoid using an incompatible plugin. */
+
+struct plugin_gcc_version
+{
+ const char *basever;
+ const char *datestamp;
+ const char *devphase;
+ const char *revision;
+ const char *configuration_arguments;
+};
+
+/* Object that keeps track of the plugin name and its arguments. */
+struct plugin_name_args
+{
+ char *base_name; /* Short name of the plugin (filename without
+ .so suffix). */
+ const char *full_name; /* Path to the plugin as specified with
+ -fplugin=. */
+ int argc; /* Number of arguments specified with
+ -fplugin-arg-... */
+ struct plugin_argument *argv; /* Array of ARGC key-value pairs. */
+ const char *version; /* Version string provided by plugin. */
+ const char *help; /* Help string provided by plugin. */
+};
+
+/* The default version check. Compares every field in VERSION. */
+
+extern bool plugin_default_version_check (struct plugin_gcc_version *,
+ struct plugin_gcc_version *);
+
+/* Function type for the plugin initialization routine. Each plugin module
+ should define this as an externally-visible function with name
+ "plugin_init."
+
+ PLUGIN_INFO - plugin invocation information.
+ VERSION - the plugin_gcc_version symbol of GCC.
+
+ Returns 0 if initialization finishes successfully. */
+
+typedef int (*plugin_init_func) (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version);
+
+/* Declaration for "plugin_init" function so that it doesn't need to be
+ duplicated in every plugin. */
+extern int plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version);
+
+/* Function type for a plugin callback routine.
+
+ GCC_DATA - event-specific data provided by GCC
+ USER_DATA - plugin-specific data provided by the plugin */
+
+typedef void (*plugin_callback_func) (void *gcc_data, void *user_data);
+
+/* Called from the plugin's initialization code. Register a single callback.
+ This function can be called multiple times.
+
+ PLUGIN_NAME - display name for this plugin
+ EVENT - which event the callback is for
+ CALLBACK - the callback to be called at the event
+ USER_DATA - plugin-provided data.
+*/
+
+/* Number of event ids / names registered so far. */
+
+extern int get_event_last (void);
+
+int get_named_event_id (const char *name, enum insert_option insert);
+
+/* This is also called without a callback routine for the
+ PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO and PLUGIN_REGISTER_GGC_ROOTS
+ pseudo-events, with a specific user_data.
+ */
+
+extern void register_callback (const char *plugin_name,
+ int event,
+ plugin_callback_func callback,
+ void *user_data);
+
+extern int unregister_callback (const char *plugin_name, int event);
+
+
+/* Retrieve the plugin directory name, as returned by the
+ -fprint-file-name=plugin argument to the gcc program, which is the
+ -iplugindir program argument to cc1. */
+extern const char* default_plugin_dir_name (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/* In case the C++ compiler does name mangling for globals, declare
+ plugin_is_GPL_compatible extern "C" so that a later definition
+ in a plugin file will have this linkage. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int plugin_is_GPL_compatible;
+#ifdef __cplusplus
+}
+#endif
+
+
+struct attribute_spec;
+struct scoped_attributes;
+
+extern void add_new_plugin (const char *);
+extern void parse_plugin_arg_opt (const char *);
+extern int invoke_plugin_callbacks_full (int, void *);
+extern void initialize_plugins (void);
+extern bool plugins_active_p (void);
+extern void dump_active_plugins (FILE *);
+extern void debug_active_plugins (void);
+extern void warn_if_plugins (void);
+extern void print_plugins_versions (FILE *file, const char *indent);
+extern void print_plugins_help (FILE *file, const char *indent);
+extern void finalize_plugins (void);
+
+extern bool flag_plugin_added;
+
+/* Called from inside GCC. Invoke all plugin callbacks registered with
+ the specified event.
+ Return PLUGEVT_SUCCESS if at least one callback was called,
+ PLUGEVT_NO_CALLBACK if there was no callback.
+
+ EVENT - the event identifier
+ GCC_DATA - event-specific data provided by the compiler */
+
+static inline int
+invoke_plugin_callbacks (int event ATTRIBUTE_UNUSED,
+ void *gcc_data ATTRIBUTE_UNUSED)
+{
+#ifdef ENABLE_PLUGIN
+ /* True iff at least one plugin has been added. */
+ if (flag_plugin_added)
+ return invoke_plugin_callbacks_full (event, gcc_data);
+#endif
+
+ return PLUGEVT_NO_CALLBACK;
+}
+
+/* In attribs.cc. */
+
+extern void register_attribute (const struct attribute_spec *attr);
+/* The default argument for the third parameter is given in attribs.h. */
+extern struct scoped_attributes* register_scoped_attributes (const struct attribute_spec *,
+ const char *,
+ bool);
+
+#endif /* PLUGIN_H */
diff --git a/support/cpp/gcc/poly-int-types.h b/support/cpp/gcc/poly-int-types.h
new file mode 100644
index 000000000..e14143ceb
--- /dev/null
+++ b/support/cpp/gcc/poly-int-types.h
@@ -0,0 +1,103 @@
+/* Typedefs for polynomial integers used in GCC.
+ Copyright (C) 2016-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 HAVE_POLY_INT_TYPES_H
+#define HAVE_POLY_INT_TYPES_H
+
+typedef poly_int_pod<NUM_POLY_INT_COEFFS, unsigned short> poly_uint16_pod;
+typedef poly_int_pod<NUM_POLY_INT_COEFFS, HOST_WIDE_INT> poly_int64_pod;
+typedef poly_int_pod<NUM_POLY_INT_COEFFS,
+ unsigned HOST_WIDE_INT> poly_uint64_pod;
+typedef poly_int_pod<NUM_POLY_INT_COEFFS, offset_int> poly_offset_int_pod;
+typedef poly_int_pod<NUM_POLY_INT_COEFFS, wide_int> poly_wide_int_pod;
+typedef poly_int_pod<NUM_POLY_INT_COEFFS, widest_int> poly_widest_int_pod;
+
+typedef poly_int<NUM_POLY_INT_COEFFS, unsigned short> poly_uint16;
+typedef poly_int<NUM_POLY_INT_COEFFS, HOST_WIDE_INT> poly_int64;
+typedef poly_int<NUM_POLY_INT_COEFFS, unsigned HOST_WIDE_INT> poly_uint64;
+typedef poly_int<NUM_POLY_INT_COEFFS, offset_int> poly_offset_int;
+typedef poly_int<NUM_POLY_INT_COEFFS, wide_int> poly_wide_int;
+typedef poly_int<NUM_POLY_INT_COEFFS, wide_int_ref> poly_wide_int_ref;
+typedef poly_int<NUM_POLY_INT_COEFFS, widest_int> poly_widest_int;
+
+/* Divide bit quantity X by BITS_PER_UNIT and round down (towards -Inf).
+ If X is a bit size, this gives the number of whole bytes spanned by X.
+
+ This is safe because non-constant mode sizes must be a whole number
+ of bytes in size. */
+#define bits_to_bytes_round_down(X) force_align_down_and_div (X, BITS_PER_UNIT)
+
+/* Divide bit quantity X by BITS_PER_UNIT and round up (towards +Inf).
+ If X is a bit size, this gives the number of whole or partial bytes
+ spanned by X.
+
+ This is safe because non-constant mode sizes must be a whole number
+ of bytes in size. */
+#define bits_to_bytes_round_up(X) force_align_up_and_div (X, BITS_PER_UNIT)
+
+/* Return the number of bits in bit quantity X that do not belong to
+ whole bytes. This is equivalent to:
+
+ X - bits_to_bytes_round_down (X) * BITS_PER_UNIT
+
+ This is safe because non-constant mode sizes must be a whole number
+ of bytes in size. */
+#define num_trailing_bits(X) force_get_misalignment (X, BITS_PER_UNIT)
+
+/* Round bit quantity X down to the nearest byte boundary.
+
+ This is safe because non-constant mode sizes must be a whole number
+ of bytes in size. */
+#define round_down_to_byte_boundary(X) force_align_down (X, BITS_PER_UNIT)
+
+/* Round bit quantity X up the nearest byte boundary.
+
+ This is safe because non-constant mode sizes must be a whole number
+ of bytes in size. */
+#define round_up_to_byte_boundary(X) force_align_up (X, BITS_PER_UNIT)
+
+/* Return the size of an element in a vector of size SIZE, given that
+ the vector has NELTS elements. The return value is in the same units
+ as SIZE (either bits or bytes).
+
+ to_constant () is safe in this situation because vector elements are
+ always constant-sized scalars. */
+#define vector_element_size(SIZE, NELTS) \
+ (exact_div (SIZE, NELTS).to_constant ())
+
+/* Return the number of unroll times when a vector that has NELTS1 elements
+ is unrolled to vectors that have NELTS2 elements.
+
+ to_constant () is safe in this situation because the multiples of the
+ NELTS of two vectors are always constant-size scalars. */
+#define vector_unroll_factor(NELTS1, NELTS2) \
+ (exact_div (NELTS1, NELTS2).to_constant ())
+
+/* Wrapper for poly_int arguments to target macros, so that if a target
+ doesn't need polynomial-sized modes, its header file can continue to
+ treat the argument as a normal constant. This should go away once
+ macros are moved to target hooks. It shouldn't be used in other
+ contexts. */
+#if NUM_POLY_INT_COEFFS == 1
+#define MACRO_INT(X) ((X).to_constant ())
+#else
+#define MACRO_INT(X) (X)
+#endif
+
+#endif
diff --git a/support/cpp/gcc/poly-int.h b/support/cpp/gcc/poly-int.h
new file mode 100644
index 000000000..2bf9d9859
--- /dev/null
+++ b/support/cpp/gcc/poly-int.h
@@ -0,0 +1,2735 @@
+/* Polynomial integer classes.
+ Copyright (C) 2014-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 provides a representation of sizes and offsets whose exact
+ values depend on certain runtime properties. The motivating example
+ is the Arm SVE ISA, in which the number of vector elements is only
+ known at runtime. See doc/poly-int.texi for more details.
+
+ Tests for poly-int.h are located in testsuite/gcc.dg/plugin,
+ since they are too expensive (in terms of binary size) to be
+ included as selftests. */
+
+#ifndef HAVE_POLY_INT_H
+#define HAVE_POLY_INT_H
+
+template<unsigned int N, typename T> struct poly_int_pod;
+template<unsigned int N, typename T> class poly_int;
+
+/* poly_coeff_traiits<T> describes the properties of a poly_int
+ coefficient type T:
+
+ - poly_coeff_traits<T1>::rank is less than poly_coeff_traits<T2>::rank
+ if T1 can promote to T2. For C-like types the rank is:
+
+ (2 * number of bytes) + (unsigned ? 1 : 0)
+
+ wide_ints don't have a normal rank and so use a value of INT_MAX.
+ Any fixed-width integer should be promoted to wide_int if possible
+ and lead to an error otherwise.
+
+ - poly_coeff_traits<T>::int_type is the type to which an integer
+ literal should be cast before comparing it with T.
+
+ - poly_coeff_traits<T>::precision is the number of bits that T can hold.
+
+ - poly_coeff_traits<T>::signedness is:
+ 0 if T is unsigned
+ 1 if T is signed
+ -1 if T has no inherent sign (as for wide_int).
+
+ - poly_coeff_traits<T>::max_value, if defined, is the maximum value of T.
+
+ - poly_coeff_traits<T>::result is a type that can hold results of
+ operations on T. This is different from T itself in cases where T
+ is the result of an accessor like wi::to_offset. */
+template<typename T, wi::precision_type = wi::int_traits<T>::precision_type>
+struct poly_coeff_traits;
+
+template<typename T>
+struct poly_coeff_traits<T, wi::FLEXIBLE_PRECISION>
+{
+ typedef T result;
+ typedef T int_type;
+ static const int signedness = (T (0) >= T (-1));
+ static const int precision = sizeof (T) * CHAR_BIT;
+ static const T max_value = (signedness
+ ? ((T (1) << (precision - 2))
+ + ((T (1) << (precision - 2)) - 1))
+ : T (-1));
+ static const int rank = sizeof (T) * 2 + !signedness;
+};
+
+template<typename T>
+struct poly_coeff_traits<T, wi::VAR_PRECISION>
+{
+ typedef T result;
+ typedef int int_type;
+ static const int signedness = -1;
+ static const int precision = WIDE_INT_MAX_PRECISION;
+ static const int rank = INT_MAX;
+};
+
+template<typename T>
+struct poly_coeff_traits<T, wi::CONST_PRECISION>
+{
+ typedef WI_UNARY_RESULT (T) result;
+ typedef int int_type;
+ /* These types are always signed. */
+ static const int signedness = 1;
+ static const int precision = wi::int_traits<T>::precision;
+ static const int rank = precision * 2 / CHAR_BIT;
+};
+
+/* Information about a pair of coefficient types. */
+template<typename T1, typename T2>
+struct poly_coeff_pair_traits
+{
+ /* True if T1 can represent all the values of T2.
+
+ Either:
+
+ - T1 should be a type with the same signedness as T2 and no less
+ precision. This allows things like int16_t -> int16_t and
+ uint32_t -> uint64_t.
+
+ - T1 should be signed, T2 should be unsigned, and T1 should be
+ wider than T2. This allows things like uint16_t -> int32_t.
+
+ This rules out cases in which T1 has less precision than T2 or where
+ the conversion would reinterpret the top bit. E.g. int16_t -> uint32_t
+ can be dangerous and should have an explicit cast if deliberate. */
+ static const bool lossless_p = (poly_coeff_traits<T1>::signedness
+ == poly_coeff_traits<T2>::signedness
+ ? (poly_coeff_traits<T1>::precision
+ >= poly_coeff_traits<T2>::precision)
+ : (poly_coeff_traits<T1>::signedness == 1
+ && poly_coeff_traits<T2>::signedness == 0
+ && (poly_coeff_traits<T1>::precision
+ > poly_coeff_traits<T2>::precision)));
+
+ /* 0 if T1 op T2 should promote to HOST_WIDE_INT,
+ 1 if T1 op T2 should promote to unsigned HOST_WIDE_INT,
+ 2 if T1 op T2 should use wide-int rules. */
+#define RANK(X) poly_coeff_traits<X>::rank
+ static const int result_kind
+ = ((RANK (T1) <= RANK (HOST_WIDE_INT)
+ && RANK (T2) <= RANK (HOST_WIDE_INT))
+ ? 0
+ : (RANK (T1) <= RANK (unsigned HOST_WIDE_INT)
+ && RANK (T2) <= RANK (unsigned HOST_WIDE_INT))
+ ? 1 : 2);
+#undef RANK
+};
+
+/* SFINAE class that makes T3 available as "type" if T2 can represent all the
+ values in T1. */
+template<typename T1, typename T2, typename T3,
+ bool lossless_p = poly_coeff_pair_traits<T1, T2>::lossless_p>
+struct if_lossless;
+template<typename T1, typename T2, typename T3>
+struct if_lossless<T1, T2, T3, true>
+{
+ typedef T3 type;
+};
+
+/* poly_int_traits<T> describes an integer type T that might be polynomial
+ or non-polynomial:
+
+ - poly_int_traits<T>::is_poly is true if T is a poly_int-based type
+ and false otherwise.
+
+ - poly_int_traits<T>::num_coeffs gives the number of coefficients in T
+ if T is a poly_int and 1 otherwise.
+
+ - poly_int_traits<T>::coeff_type gives the coefficent type of T if T
+ is a poly_int and T itself otherwise
+
+ - poly_int_traits<T>::int_type is a shorthand for
+ typename poly_coeff_traits<coeff_type>::int_type. */
+template<typename T>
+struct poly_int_traits
+{
+ static const bool is_poly = false;
+ static const unsigned int num_coeffs = 1;
+ typedef T coeff_type;
+ typedef typename poly_coeff_traits<T>::int_type int_type;
+};
+template<unsigned int N, typename C>
+struct poly_int_traits<poly_int_pod<N, C> >
+{
+ static const bool is_poly = true;
+ static const unsigned int num_coeffs = N;
+ typedef C coeff_type;
+ typedef typename poly_coeff_traits<C>::int_type int_type;
+};
+template<unsigned int N, typename C>
+struct poly_int_traits<poly_int<N, C> > : poly_int_traits<poly_int_pod<N, C> >
+{
+};
+
+/* SFINAE class that makes T2 available as "type" if T1 is a non-polynomial
+ type. */
+template<typename T1, typename T2 = T1,
+ bool is_poly = poly_int_traits<T1>::is_poly>
+struct if_nonpoly {};
+template<typename T1, typename T2>
+struct if_nonpoly<T1, T2, false>
+{
+ typedef T2 type;
+};
+
+/* SFINAE class that makes T3 available as "type" if both T1 and T2 are
+ non-polynomial types. */
+template<typename T1, typename T2, typename T3,
+ bool is_poly1 = poly_int_traits<T1>::is_poly,
+ bool is_poly2 = poly_int_traits<T2>::is_poly>
+struct if_nonpoly2 {};
+template<typename T1, typename T2, typename T3>
+struct if_nonpoly2<T1, T2, T3, false, false>
+{
+ typedef T3 type;
+};
+
+/* SFINAE class that makes T2 available as "type" if T1 is a polynomial
+ type. */
+template<typename T1, typename T2 = T1,
+ bool is_poly = poly_int_traits<T1>::is_poly>
+struct if_poly {};
+template<typename T1, typename T2>
+struct if_poly<T1, T2, true>
+{
+ typedef T2 type;
+};
+
+/* poly_result<T1, T2> describes the result of an operation on two
+ types T1 and T2, where at least one of the types is polynomial:
+
+ - poly_result<T1, T2>::type gives the result type for the operation.
+ The intention is to provide normal C-like rules for integer ranks,
+ except that everything smaller than HOST_WIDE_INT promotes to
+ HOST_WIDE_INT.
+
+ - poly_result<T1, T2>::cast is the type to which an operand of type
+ T1 should be cast before doing the operation, to ensure that
+ the operation is done at the right precision. Casting to
+ poly_result<T1, T2>::type would also work, but casting to this
+ type is more efficient. */
+template<typename T1, typename T2 = T1,
+ int result_kind = poly_coeff_pair_traits<T1, T2>::result_kind>
+struct poly_result;
+
+/* Promote pair to HOST_WIDE_INT. */
+template<typename T1, typename T2>
+struct poly_result<T1, T2, 0>
+{
+ typedef HOST_WIDE_INT type;
+ /* T1 and T2 are primitive types, so cast values to T before operating
+ on them. */
+ typedef type cast;
+};
+
+/* Promote pair to unsigned HOST_WIDE_INT. */
+template<typename T1, typename T2>
+struct poly_result<T1, T2, 1>
+{
+ typedef unsigned HOST_WIDE_INT type;
+ /* T1 and T2 are primitive types, so cast values to T before operating
+ on them. */
+ typedef type cast;
+};
+
+/* Use normal wide-int rules. */
+template<typename T1, typename T2>
+struct poly_result<T1, T2, 2>
+{
+ typedef WI_BINARY_RESULT (T1, T2) type;
+ /* Don't cast values before operating on them; leave the wi:: routines
+ to handle promotion as necessary. */
+ typedef const T1 &cast;
+};
+
+/* The coefficient type for the result of a binary operation on two
+ poly_ints, the first of which has coefficients of type C1 and the
+ second of which has coefficients of type C2. */
+#define POLY_POLY_COEFF(C1, C2) typename poly_result<C1, C2>::type
+
+/* Enforce that T2 is non-polynomial and provide the cofficient type of
+ the result of a binary operation in which the first operand is a
+ poly_int with coefficients of type C1 and the second operand is
+ a constant of type T2. */
+#define POLY_CONST_COEFF(C1, T2) \
+ POLY_POLY_COEFF (C1, typename if_nonpoly<T2>::type)
+
+/* Likewise in reverse. */
+#define CONST_POLY_COEFF(T1, C2) \
+ POLY_POLY_COEFF (typename if_nonpoly<T1>::type, C2)
+
+/* The result type for a binary operation on poly_int<N, C1> and
+ poly_int<N, C2>. */
+#define POLY_POLY_RESULT(N, C1, C2) poly_int<N, POLY_POLY_COEFF (C1, C2)>
+
+/* Enforce that T2 is non-polynomial and provide the result type
+ for a binary operation on poly_int<N, C1> and T2. */
+#define POLY_CONST_RESULT(N, C1, T2) poly_int<N, POLY_CONST_COEFF (C1, T2)>
+
+/* Enforce that T1 is non-polynomial and provide the result type
+ for a binary operation on T1 and poly_int<N, C2>. */
+#define CONST_POLY_RESULT(N, T1, C2) poly_int<N, CONST_POLY_COEFF (T1, C2)>
+
+/* Enforce that T1 and T2 are non-polynomial and provide the result type
+ for a binary operation on T1 and T2. */
+#define CONST_CONST_RESULT(N, T1, T2) \
+ POLY_POLY_COEFF (typename if_nonpoly<T1>::type, \
+ typename if_nonpoly<T2>::type)
+
+/* The type to which a coefficient of type C1 should be cast before
+ using it in a binary operation with a coefficient of type C2. */
+#define POLY_CAST(C1, C2) typename poly_result<C1, C2>::cast
+
+/* Provide the coefficient type for the result of T1 op T2, where T1
+ and T2 can be polynomial or non-polynomial. */
+#define POLY_BINARY_COEFF(T1, T2) \
+ typename poly_result<typename poly_int_traits<T1>::coeff_type, \
+ typename poly_int_traits<T2>::coeff_type>::type
+
+/* The type to which an integer constant should be cast before
+ comparing it with T. */
+#define POLY_INT_TYPE(T) typename poly_int_traits<T>::int_type
+
+/* RES is a poly_int result that has coefficients of type C and that
+ is being built up a coefficient at a time. Set coefficient number I
+ to VALUE in the most efficient way possible.
+
+ For primitive C it is better to assign directly, since it avoids
+ any further calls and so is more efficient when the compiler is
+ built at -O0. But for wide-int based C it is better to construct
+ the value in-place. This means that calls out to a wide-int.cc
+ routine can take the address of RES rather than the address of
+ a temporary.
+
+ The dummy self-comparison against C * is just a way of checking
+ that C gives the right type. */
+#define POLY_SET_COEFF(C, RES, I, VALUE) \
+ ((void) (&(RES).coeffs[0] == (C *) (void *) &(RES).coeffs[0]), \
+ wi::int_traits<C>::precision_type == wi::FLEXIBLE_PRECISION \
+ ? (void) ((RES).coeffs[I] = VALUE) \
+ : (void) ((RES).coeffs[I].~C (), new (&(RES).coeffs[I]) C (VALUE)))
+
+/* A base POD class for polynomial integers. The polynomial has N
+ coefficients of type C. */
+template<unsigned int N, typename C>
+struct poly_int_pod
+{
+public:
+ template<typename Ca>
+ poly_int_pod &operator = (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator = (const Ca &);
+
+ template<typename Ca>
+ poly_int_pod &operator += (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator += (const Ca &);
+
+ template<typename Ca>
+ poly_int_pod &operator -= (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator -= (const Ca &);
+
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator *= (const Ca &);
+
+ poly_int_pod &operator <<= (unsigned int);
+
+ bool is_constant () const;
+
+ template<typename T>
+ typename if_lossless<T, C, bool>::type is_constant (T *) const;
+
+ C to_constant () const;
+
+ template<typename Ca>
+ static poly_int<N, C> from (const poly_int_pod<N, Ca> &, unsigned int,
+ signop);
+ template<typename Ca>
+ static poly_int<N, C> from (const poly_int_pod<N, Ca> &, signop);
+
+ bool to_shwi (poly_int_pod<N, HOST_WIDE_INT> *) const;
+ bool to_uhwi (poly_int_pod<N, unsigned HOST_WIDE_INT> *) const;
+ poly_int<N, HOST_WIDE_INT> force_shwi () const;
+ poly_int<N, unsigned HOST_WIDE_INT> force_uhwi () const;
+
+#if POLY_INT_CONVERSION
+ operator C () const;
+#endif
+
+ C coeffs[N];
+};
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator = (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator = (const Ca &a)
+{
+ POLY_SET_COEFF (C, *this, 0, a);
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator += (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] += a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator += (const Ca &a)
+{
+ this->coeffs[0] += a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator -= (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] -= a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator -= (const Ca &a)
+{
+ this->coeffs[0] -= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator *= (const Ca &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] *= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator <<= (unsigned int a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] <<= a;
+ return *this;
+}
+
+/* Return true if the polynomial value is a compile-time constant. */
+
+template<unsigned int N, typename C>
+inline bool
+poly_int_pod<N, C>::is_constant () const
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (this->coeffs[i] != 0)
+ return false;
+ return true;
+}
+
+/* Return true if the polynomial value is a compile-time constant,
+ storing its value in CONST_VALUE if so. */
+
+template<unsigned int N, typename C>
+template<typename T>
+inline typename if_lossless<T, C, bool>::type
+poly_int_pod<N, C>::is_constant (T *const_value) const
+{
+ if (is_constant ())
+ {
+ *const_value = this->coeffs[0];
+ return true;
+ }
+ return false;
+}
+
+/* Return the value of a polynomial that is already known to be a
+ compile-time constant.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the value is constant in that context. */
+
+template<unsigned int N, typename C>
+inline C
+poly_int_pod<N, C>::to_constant () const
+{
+ gcc_checking_assert (is_constant ());
+ return this->coeffs[0];
+}
+
+/* Convert X to a wide_int-based polynomial in which each coefficient
+ has BITSIZE bits. If X's coefficients are smaller than BITSIZE,
+ extend them according to SGN. */
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>
+poly_int_pod<N, C>::from (const poly_int_pod<N, Ca> &a,
+ unsigned int bitsize, signop sgn)
+{
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, C::from (a.coeffs[i], bitsize, sgn));
+ return r;
+}
+
+/* Convert X to a fixed_wide_int-based polynomial, extending according
+ to SGN. */
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>
+poly_int_pod<N, C>::from (const poly_int_pod<N, Ca> &a, signop sgn)
+{
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, C::from (a.coeffs[i], sgn));
+ return r;
+}
+
+/* Return true if the coefficients of this generic_wide_int-based
+ polynomial can be represented as signed HOST_WIDE_INTs without loss
+ of precision. Store the HOST_WIDE_INT representation in *R if so. */
+
+template<unsigned int N, typename C>
+inline bool
+poly_int_pod<N, C>::to_shwi (poly_int_pod<N, HOST_WIDE_INT> *r) const
+{
+ for (unsigned int i = 0; i < N; i++)
+ if (!wi::fits_shwi_p (this->coeffs[i]))
+ return false;
+ for (unsigned int i = 0; i < N; i++)
+ r->coeffs[i] = this->coeffs[i].to_shwi ();
+ return true;
+}
+
+/* Return true if the coefficients of this generic_wide_int-based
+ polynomial can be represented as unsigned HOST_WIDE_INTs without
+ loss of precision. Store the unsigned HOST_WIDE_INT representation
+ in *R if so. */
+
+template<unsigned int N, typename C>
+inline bool
+poly_int_pod<N, C>::to_uhwi (poly_int_pod<N, unsigned HOST_WIDE_INT> *r) const
+{
+ for (unsigned int i = 0; i < N; i++)
+ if (!wi::fits_uhwi_p (this->coeffs[i]))
+ return false;
+ for (unsigned int i = 0; i < N; i++)
+ r->coeffs[i] = this->coeffs[i].to_uhwi ();
+ return true;
+}
+
+/* Force a generic_wide_int-based constant to HOST_WIDE_INT precision,
+ truncating if necessary. */
+
+template<unsigned int N, typename C>
+inline poly_int<N, HOST_WIDE_INT>
+poly_int_pod<N, C>::force_shwi () const
+{
+ poly_int_pod<N, HOST_WIDE_INT> r;
+ for (unsigned int i = 0; i < N; i++)
+ r.coeffs[i] = this->coeffs[i].to_shwi ();
+ return r;
+}
+
+/* Force a generic_wide_int-based constant to unsigned HOST_WIDE_INT precision,
+ truncating if necessary. */
+
+template<unsigned int N, typename C>
+inline poly_int<N, unsigned HOST_WIDE_INT>
+poly_int_pod<N, C>::force_uhwi () const
+{
+ poly_int_pod<N, unsigned HOST_WIDE_INT> r;
+ for (unsigned int i = 0; i < N; i++)
+ r.coeffs[i] = this->coeffs[i].to_uhwi ();
+ return r;
+}
+
+#if POLY_INT_CONVERSION
+/* Provide a conversion operator to constants. */
+
+template<unsigned int N, typename C>
+inline
+poly_int_pod<N, C>::operator C () const
+{
+ gcc_checking_assert (this->is_constant ());
+ return this->coeffs[0];
+}
+#endif
+
+/* The main class for polynomial integers. The class provides
+ constructors that are necessarily missing from the POD base. */
+template<unsigned int N, typename C>
+class poly_int : public poly_int_pod<N, C>
+{
+public:
+ poly_int () {}
+
+ template<typename Ca>
+ poly_int (const poly_int<N, Ca> &);
+ template<typename Ca>
+ poly_int (const poly_int_pod<N, Ca> &);
+ template<typename C0>
+ poly_int (const C0 &);
+ template<typename C0, typename C1>
+ poly_int (const C0 &, const C1 &);
+
+ template<typename Ca>
+ poly_int &operator = (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator = (const Ca &);
+
+ template<typename Ca>
+ poly_int &operator += (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator += (const Ca &);
+
+ template<typename Ca>
+ poly_int &operator -= (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator -= (const Ca &);
+
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator *= (const Ca &);
+
+ poly_int &operator <<= (unsigned int);
+};
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline
+poly_int<N, C>::poly_int (const poly_int<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline
+poly_int<N, C>::poly_int (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
+}
+
+template<unsigned int N, typename C>
+template<typename C0>
+inline
+poly_int<N, C>::poly_int (const C0 &c0)
+{
+ POLY_SET_COEFF (C, *this, 0, c0);
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
+}
+
+template<unsigned int N, typename C>
+template<typename C0, typename C1>
+inline
+poly_int<N, C>::poly_int (const C0 &c0, const C1 &c1)
+{
+ STATIC_ASSERT (N >= 2);
+ POLY_SET_COEFF (C, *this, 0, c0);
+ POLY_SET_COEFF (C, *this, 1, c1);
+ for (unsigned int i = 2; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>&
+poly_int<N, C>::operator = (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] = a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator = (const Ca &a)
+{
+ this->coeffs[0] = a;
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ this->coeffs[i] = wi::ints_for<C>::zero (this->coeffs[0]);
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>&
+poly_int<N, C>::operator += (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] += a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator += (const Ca &a)
+{
+ this->coeffs[0] += a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>&
+poly_int<N, C>::operator -= (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] -= a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator -= (const Ca &a)
+{
+ this->coeffs[0] -= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator *= (const Ca &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] *= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+inline poly_int<N, C>&
+poly_int<N, C>::operator <<= (unsigned int a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] <<= a;
+ return *this;
+}
+
+/* Return true if every coefficient of A is in the inclusive range [B, C]. */
+
+template<typename Ca, typename Cb, typename Cc>
+inline typename if_nonpoly<Ca, bool>::type
+coeffs_in_range_p (const Ca &a, const Cb &b, const Cc &c)
+{
+ return a >= b && a <= c;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cc>
+inline typename if_nonpoly<Ca, bool>::type
+coeffs_in_range_p (const poly_int_pod<N, Ca> &a, const Cb &b, const Cc &c)
+{
+ for (unsigned int i = 0; i < N; i++)
+ if (a.coeffs[i] < b || a.coeffs[i] > c)
+ return false;
+ return true;
+}
+
+namespace wi {
+/* Poly version of wi::shwi, with the same interface. */
+
+template<unsigned int N>
+inline poly_int<N, hwi_with_prec>
+shwi (const poly_int_pod<N, HOST_WIDE_INT> &a, unsigned int precision)
+{
+ poly_int<N, hwi_with_prec> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (hwi_with_prec, r, i, wi::shwi (a.coeffs[i], precision));
+ return r;
+}
+
+/* Poly version of wi::uhwi, with the same interface. */
+
+template<unsigned int N>
+inline poly_int<N, hwi_with_prec>
+uhwi (const poly_int_pod<N, unsigned HOST_WIDE_INT> &a, unsigned int precision)
+{
+ poly_int<N, hwi_with_prec> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (hwi_with_prec, r, i, wi::uhwi (a.coeffs[i], precision));
+ return r;
+}
+
+/* Poly version of wi::sext, with the same interface. */
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+sext (const poly_int_pod<N, Ca> &a, unsigned int precision)
+{
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sext (a.coeffs[i], precision));
+ return r;
+}
+
+/* Poly version of wi::zext, with the same interface. */
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+zext (const poly_int_pod<N, Ca> &a, unsigned int precision)
+{
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::zext (a.coeffs[i], precision));
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+operator + (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) + b.coeffs[i]);
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+operator + (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, NCa (a.coeffs[0]) + b);
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+operator + (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef CONST_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, a + NCb (b.coeffs[0]));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCb (b.coeffs[i]));
+ return r;
+}
+
+namespace wi {
+/* Poly versions of wi::add, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i], b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::add (a.coeffs[0], b));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i],
+ wi::ints_for<Cb>::zero (b)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::add (a, b.coeffs[0]));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::add (wi::ints_for<Ca>::zero (a),
+ b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
+ signop sgn, wi::overflow_type *overflow)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::add (a.coeffs[0], b.coeffs[0], sgn, overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ wi::overflow_type suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i], b.coeffs[i], sgn,
+ &suboverflow));
+ wi::accumulate_overflow (*overflow, suboverflow);
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+operator - (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) - b.coeffs[i]);
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+operator - (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, NCa (a.coeffs[0]) - b);
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+operator - (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef CONST_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, a - NCb (b.coeffs[0]));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, -NCb (b.coeffs[i]));
+ return r;
+}
+
+namespace wi {
+/* Poly versions of wi::sub, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i], b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::sub (a.coeffs[0], b));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i],
+ wi::ints_for<Cb>::zero (b)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::sub (a, b.coeffs[0]));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sub (wi::ints_for<Ca>::zero (a),
+ b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
+ signop sgn, wi::overflow_type *overflow)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::sub (a.coeffs[0], b.coeffs[0], sgn, overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ wi::overflow_type suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i], b.coeffs[i], sgn,
+ &suboverflow));
+ wi::accumulate_overflow (*overflow, suboverflow);
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+operator - (const poly_int_pod<N, Ca> &a)
+{
+ typedef POLY_CAST (Ca, Ca) NCa;
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, -NCa (a.coeffs[i]));
+ return r;
+}
+
+namespace wi {
+/* Poly version of wi::neg, with the same interface. */
+
+template<unsigned int N, typename Ca>
+inline poly_int<N, WI_UNARY_RESULT (Ca)>
+neg (const poly_int_pod<N, Ca> &a)
+{
+ typedef WI_UNARY_RESULT (Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::neg (a.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca>
+inline poly_int<N, WI_UNARY_RESULT (Ca)>
+neg (const poly_int_pod<N, Ca> &a, wi::overflow_type *overflow)
+{
+ typedef WI_UNARY_RESULT (Ca) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::neg (a.coeffs[0], overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ wi::overflow_type suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::neg (a.coeffs[i], &suboverflow));
+ wi::accumulate_overflow (*overflow, suboverflow);
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+operator ~ (const poly_int_pod<N, Ca> &a)
+{
+ if (N >= 2)
+ return -1 - a;
+ return ~a.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+operator * (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) * b);
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+operator * (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef CONST_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a) * b.coeffs[i]);
+ return r;
+}
+
+namespace wi {
+/* Poly versions of wi::mul, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+mul (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::mul (a.coeffs[i], b));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+mul (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::mul (a, b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+mul (const poly_int_pod<N, Ca> &a, const Cb &b,
+ signop sgn, wi::overflow_type *overflow)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::mul (a.coeffs[0], b, sgn, overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ wi::overflow_type suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::mul (a.coeffs[i], b, sgn, &suboverflow));
+ wi::accumulate_overflow (*overflow, suboverflow);
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+operator << (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Ca) NCa;
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) << b);
+ return r;
+}
+
+namespace wi {
+/* Poly version of wi::lshift, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Ca)>
+lshift (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::lshift (a.coeffs[i], b));
+ return r;
+}
+}
+
+/* Return true if a0 + a1 * x might equal b0 + b1 * x for some nonnegative
+ integer x. */
+
+template<typename Ca, typename Cb>
+inline bool
+maybe_eq_2 (const Ca &a0, const Ca &a1, const Cb &b0, const Cb &b1)
+{
+ if (a1 != b1)
+ /* a0 + a1 * x == b0 + b1 * x
+ ==> (a1 - b1) * x == b0 - a0
+ ==> x == (b0 - a0) / (a1 - b1)
+
+ We need to test whether that's a valid value of x.
+ (b0 - a0) and (a1 - b1) must not have opposite signs
+ and the result must be integral. */
+ return (a1 < b1
+ ? b0 <= a0 && (a0 - b0) % (b1 - a1) == 0
+ : b0 >= a0 && (b0 - a0) % (a1 - b1) == 0);
+ return a0 == b0;
+}
+
+/* Return true if a0 + a1 * x might equal b for some nonnegative
+ integer x. */
+
+template<typename Ca, typename Cb>
+inline bool
+maybe_eq_2 (const Ca &a0, const Ca &a1, const Cb &b)
+{
+ if (a1 != 0)
+ /* a0 + a1 * x == b
+ ==> x == (b - a0) / a1
+
+ We need to test whether that's a valid value of x.
+ (b - a0) and a1 must not have opposite signs and the
+ result must be integral. */
+ return (a1 < 0
+ ? b <= a0 && (a0 - b) % a1 == 0
+ : b >= a0 && (b - a0) % a1 == 0);
+ return a0 == b;
+}
+
+/* Return true if A might equal B for some indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_eq (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ STATIC_ASSERT (N <= 2);
+ if (N == 2)
+ return maybe_eq_2 (a.coeffs[0], a.coeffs[1], b.coeffs[0], b.coeffs[1]);
+ return a.coeffs[0] == b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_eq (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ STATIC_ASSERT (N <= 2);
+ if (N == 2)
+ return maybe_eq_2 (a.coeffs[0], a.coeffs[1], b);
+ return a.coeffs[0] == b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_eq (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ STATIC_ASSERT (N <= 2);
+ if (N == 2)
+ return maybe_eq_2 (b.coeffs[0], b.coeffs[1], a);
+ return a == b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_eq (const Ca &a, const Cb &b)
+{
+ return a == b;
+}
+
+/* Return true if A might not equal B for some indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_ne (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] != b.coeffs[i])
+ return true;
+ return a.coeffs[0] != b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_ne (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] != 0)
+ return true;
+ return a.coeffs[0] != b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_ne (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (b.coeffs[i] != 0)
+ return true;
+ return a != b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_ne (const Ca &a, const Cb &b)
+{
+ return a != b;
+}
+
+/* Return true if A is known to be equal to B. */
+#define known_eq(A, B) (!maybe_ne (A, B))
+
+/* Return true if A is known to be unequal to B. */
+#define known_ne(A, B) (!maybe_eq (A, B))
+
+/* Return true if A might be less than or equal to B for some
+ indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_le (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < b.coeffs[i])
+ return true;
+ return a.coeffs[0] <= b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_le (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < 0)
+ return true;
+ return a.coeffs[0] <= b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_le (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (b.coeffs[i] > 0)
+ return true;
+ return a <= b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_le (const Ca &a, const Cb &b)
+{
+ return a <= b;
+}
+
+/* Return true if A might be less than B for some indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_lt (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < b.coeffs[i])
+ return true;
+ return a.coeffs[0] < b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_lt (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < 0)
+ return true;
+ return a.coeffs[0] < b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_lt (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (b.coeffs[i] > 0)
+ return true;
+ return a < b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_lt (const Ca &a, const Cb &b)
+{
+ return a < b;
+}
+
+/* Return true if A may be greater than or equal to B. */
+#define maybe_ge(A, B) maybe_le (B, A)
+
+/* Return true if A may be greater than B. */
+#define maybe_gt(A, B) maybe_lt (B, A)
+
+/* Return true if A is known to be less than or equal to B. */
+#define known_le(A, B) (!maybe_gt (A, B))
+
+/* Return true if A is known to be less than B. */
+#define known_lt(A, B) (!maybe_ge (A, B))
+
+/* Return true if A is known to be greater than B. */
+#define known_gt(A, B) (!maybe_le (A, B))
+
+/* Return true if A is known to be greater than or equal to B. */
+#define known_ge(A, B) (!maybe_lt (A, B))
+
+/* Return true if A and B are ordered by the partial ordering known_le. */
+
+template<typename T1, typename T2>
+inline bool
+ordered_p (const T1 &a, const T2 &b)
+{
+ return ((poly_int_traits<T1>::num_coeffs == 1
+ && poly_int_traits<T2>::num_coeffs == 1)
+ || known_le (a, b)
+ || known_le (b, a));
+}
+
+/* Assert that A and B are known to be ordered and return the minimum
+ of the two.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the values are ordered in that context. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+ordered_min (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return a;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return b;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+ordered_min (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return a;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return b;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+ordered_min (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (known_le (a, b))
+ return a;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return b;
+ }
+}
+
+/* Assert that A and B are known to be ordered and return the maximum
+ of the two.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the values are ordered in that context. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+ordered_max (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return b;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return a;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+ordered_max (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return b;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return a;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+ordered_max (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (known_le (a, b))
+ return b;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return a;
+ }
+}
+
+/* Return a constant lower bound on the value of A, which is known
+ to be nonnegative. */
+
+template<unsigned int N, typename Ca>
+inline Ca
+constant_lower_bound (const poly_int_pod<N, Ca> &a)
+{
+ gcc_checking_assert (known_ge (a, POLY_INT_TYPE (Ca) (0)));
+ return a.coeffs[0];
+}
+
+/* Return the constant lower bound of A, given that it is no less than B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_COEFF (Ca, Cb)
+constant_lower_bound_with_limit (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (known_ge (a, b))
+ return a.coeffs[0];
+ return b;
+}
+
+/* Return the constant upper bound of A, given that it is no greater
+ than B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_COEFF (Ca, Cb)
+constant_upper_bound_with_limit (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (known_le (a, b))
+ return a.coeffs[0];
+ return b;
+}
+
+/* Return a value that is known to be no greater than A and B. This
+ will be the greatest lower bound for some indeterminate values but
+ not necessarily for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+lower_bound (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, MIN (NCa (a.coeffs[0]), NCb (b)));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MIN (NCa (a.coeffs[i]), ICb (0)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+lower_bound (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ return lower_bound (b, a);
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+lower_bound (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MIN (NCa (a.coeffs[i]), NCb (b.coeffs[i])));
+ return r;
+}
+
+template<typename Ca, typename Cb>
+inline CONST_CONST_RESULT (N, Ca, Cb)
+lower_bound (const Ca &a, const Cb &b)
+{
+ return a < b ? a : b;
+}
+
+/* Return a value that is known to be no less than A and B. This will
+ be the least upper bound for some indeterminate values but not
+ necessarily for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+upper_bound (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, MAX (NCa (a.coeffs[0]), NCb (b)));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MAX (NCa (a.coeffs[i]), ICb (0)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+upper_bound (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ return upper_bound (b, a);
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+upper_bound (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MAX (NCa (a.coeffs[i]), NCb (b.coeffs[i])));
+ return r;
+}
+
+/* Return the greatest common divisor of all nonzero coefficients, or zero
+ if all coefficients are zero. */
+
+template<unsigned int N, typename Ca>
+inline POLY_BINARY_COEFF (Ca, Ca)
+coeff_gcd (const poly_int_pod<N, Ca> &a)
+{
+ /* Find the first nonzero coefficient, stopping at 0 whatever happens. */
+ unsigned int i;
+ for (i = N - 1; i > 0; --i)
+ if (a.coeffs[i] != 0)
+ break;
+ typedef POLY_BINARY_COEFF (Ca, Ca) C;
+ C r = a.coeffs[i];
+ for (unsigned int j = 0; j < i; ++j)
+ if (a.coeffs[j] != 0)
+ r = gcd (r, C (a.coeffs[j]));
+ return r;
+}
+
+/* Return a value that is a multiple of both A and B. This will be the
+ least common multiple for some indeterminate values but necessarily
+ for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+POLY_CONST_RESULT (N, Ca, Cb)
+common_multiple (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ POLY_BINARY_COEFF (Ca, Ca) xgcd = coeff_gcd (a);
+ return a * (least_common_multiple (xgcd, b) / xgcd);
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+common_multiple (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ return common_multiple (b, a);
+}
+
+/* Return a value that is a multiple of both A and B, asserting that
+ such a value exists. The result will be the least common multiple
+ for some indeterminate values but necessarily for all.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the values have a common multiple (which might
+ for example be because we know A / B is rational). */
+
+template<unsigned int N, typename Ca, typename Cb>
+POLY_POLY_RESULT (N, Ca, Cb)
+force_common_multiple (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b)
+{
+ if (b.is_constant ())
+ return common_multiple (a, b.coeffs[0]);
+ if (a.is_constant ())
+ return common_multiple (a.coeffs[0], b);
+
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+ typedef POLY_INT_TYPE (Ca) ICa;
+
+ for (unsigned int i = 1; i < N; ++i)
+ if (a.coeffs[i] != ICa (0))
+ {
+ C lcm = least_common_multiple (NCa (a.coeffs[i]), NCb (b.coeffs[i]));
+ C amul = lcm / a.coeffs[i];
+ C bmul = lcm / b.coeffs[i];
+ for (unsigned int j = 0; j < N; ++j)
+ gcc_checking_assert (a.coeffs[j] * amul == b.coeffs[j] * bmul);
+ return a * amul;
+ }
+ gcc_unreachable ();
+}
+
+/* Compare A and B for sorting purposes, returning -1 if A should come
+ before B, 0 if A and B are identical, and 1 if A should come after B.
+ This is a lexicographical compare of the coefficients in reverse order.
+
+ A consequence of this is that all constant sizes come before all
+ non-constant ones, regardless of magnitude (since a size is never
+ negative). This is what most callers want. For example, when laying
+ data out on the stack, it's better to keep all the constant-sized
+ data together so that it can be accessed as a constant offset from a
+ single base. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline int
+compare_sizes_for_sort (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b)
+{
+ for (unsigned int i = N; i-- > 0; )
+ if (a.coeffs[i] != b.coeffs[i])
+ return a.coeffs[i] < b.coeffs[i] ? -1 : 1;
+ return 0;
+}
+
+/* Return true if we can calculate VALUE & (ALIGN - 1) at compile time. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+can_align_p (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ for (unsigned int i = 1; i < N; i++)
+ if ((value.coeffs[i] & (align - 1)) != 0)
+ return false;
+ return true;
+}
+
+/* Return true if we can align VALUE up to the smallest multiple of
+ ALIGN that is >= VALUE. Store the aligned value in *ALIGNED if so. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+can_align_up (const poly_int_pod<N, Ca> &value, Cb align,
+ poly_int_pod<N, Ca> *aligned)
+{
+ if (!can_align_p (value, align))
+ return false;
+ *aligned = value + (-value.coeffs[0] & (align - 1));
+ return true;
+}
+
+/* Return true if we can align VALUE down to the largest multiple of
+ ALIGN that is <= VALUE. Store the aligned value in *ALIGNED if so. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+can_align_down (const poly_int_pod<N, Ca> &value, Cb align,
+ poly_int_pod<N, Ca> *aligned)
+{
+ if (!can_align_p (value, align))
+ return false;
+ *aligned = value - (value.coeffs[0] & (align - 1));
+ return true;
+}
+
+/* Return true if we can align A and B up to the smallest multiples of
+ ALIGN that are >= A and B respectively, and if doing so gives the
+ same value. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cc>
+inline bool
+known_equal_after_align_up (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cc align)
+{
+ poly_int<N, Ca> aligned_a;
+ poly_int<N, Cb> aligned_b;
+ return (can_align_up (a, align, &aligned_a)
+ && can_align_up (b, align, &aligned_b)
+ && known_eq (aligned_a, aligned_b));
+}
+
+/* Return true if we can align A and B down to the largest multiples of
+ ALIGN that are <= A and B respectively, and if doing so gives the
+ same value. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cc>
+inline bool
+known_equal_after_align_down (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cc align)
+{
+ poly_int<N, Ca> aligned_a;
+ poly_int<N, Cb> aligned_b;
+ return (can_align_down (a, align, &aligned_a)
+ && can_align_down (b, align, &aligned_b)
+ && known_eq (aligned_a, aligned_b));
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time and return
+ the smallest multiple of ALIGN that is >= VALUE.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_up (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+ return value + (-value.coeffs[0] & (align - 1));
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time and return
+ the largest multiple of ALIGN that is <= VALUE.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_down (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+ return value - (value.coeffs[0] & (align - 1));
+}
+
+/* Return a value <= VALUE that is a multiple of ALIGN. It will be the
+ greatest such value for some indeterminate values but not necessarily
+ for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+aligned_lower_bound (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ poly_int<N, Ca> r;
+ for (unsigned int i = 0; i < N; i++)
+ /* This form copes correctly with more type combinations than
+ value.coeffs[i] & -align would. */
+ POLY_SET_COEFF (Ca, r, i, (value.coeffs[i]
+ - (value.coeffs[i] & (align - 1))));
+ return r;
+}
+
+/* Return a value >= VALUE that is a multiple of ALIGN. It will be the
+ least such value for some indeterminate values but not necessarily
+ for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+aligned_upper_bound (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ poly_int<N, Ca> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (Ca, r, i, (value.coeffs[i]
+ + (-value.coeffs[i] & (align - 1))));
+ return r;
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time. Align VALUE
+ down to the largest multiple of ALIGN that is <= VALUE, then divide by
+ ALIGN.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_down_and_div (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+
+ poly_int<N, Ca> r;
+ POLY_SET_COEFF (Ca, r, 0, ((value.coeffs[0]
+ - (value.coeffs[0] & (align - 1)))
+ / align));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (Ca, r, i, value.coeffs[i] / align);
+ return r;
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time. Align VALUE
+ up to the smallest multiple of ALIGN that is >= VALUE, then divide by
+ ALIGN.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_up_and_div (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+
+ poly_int<N, Ca> r;
+ POLY_SET_COEFF (Ca, r, 0, ((value.coeffs[0]
+ + (-value.coeffs[0] & (align - 1)))
+ / align));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (Ca, r, i, value.coeffs[i] / align);
+ return r;
+}
+
+/* Return true if we know at compile time the difference between VALUE
+ and the equal or preceding multiple of ALIGN. Store the value in
+ *MISALIGN if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline bool
+known_misalignment (const poly_int_pod<N, Ca> &value, Cb align, Cm *misalign)
+{
+ gcc_checking_assert (align != 0);
+ if (!can_align_p (value, align))
+ return false;
+ *misalign = value.coeffs[0] & (align - 1);
+ return true;
+}
+
+/* Return X & (Y - 1), asserting that this value is known. Please add
+ an a comment above callers to this function to explain why the condition
+ is known to hold. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_BINARY_COEFF (Ca, Ca)
+force_get_misalignment (const poly_int_pod<N, Ca> &a, Cb align)
+{
+ gcc_checking_assert (can_align_p (a, align));
+ return a.coeffs[0] & (align - 1);
+}
+
+/* Return the maximum alignment that A is known to have. Return 0
+ if A is known to be zero. */
+
+template<unsigned int N, typename Ca>
+inline POLY_BINARY_COEFF (Ca, Ca)
+known_alignment (const poly_int_pod<N, Ca> &a)
+{
+ typedef POLY_BINARY_COEFF (Ca, Ca) C;
+ C r = a.coeffs[0];
+ for (unsigned int i = 1; i < N; ++i)
+ r |= a.coeffs[i];
+ return r & -r;
+}
+
+/* Return true if we can compute A | B at compile time, storing the
+ result in RES if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cr>
+inline typename if_nonpoly<Cb, bool>::type
+can_ior_p (const poly_int_pod<N, Ca> &a, Cb b, Cr *result)
+{
+ /* Coefficients 1 and above must be a multiple of something greater
+ than B. */
+ typedef POLY_INT_TYPE (Ca) int_type;
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if ((-(a.coeffs[i] & -a.coeffs[i]) & b) != int_type (0))
+ return false;
+ *result = a;
+ result->coeffs[0] |= b;
+ return true;
+}
+
+/* Return true if A is a constant multiple of B, storing the
+ multiple in *MULTIPLE if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Cb, bool>::type
+constant_multiple_p (const poly_int_pod<N, Ca> &a, Cb b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a.coeffs[0]) % NCb (b) != 0 || !a.is_constant ())
+ return false;
+ *multiple = NCa (a.coeffs[0]) / NCb (b);
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Ca, bool>::type
+constant_multiple_p (Ca a, const poly_int_pod<N, Cb> &b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) int_type;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a) % NCb (b.coeffs[0]) != 0
+ || (a != int_type (0) && !b.is_constant ()))
+ return false;
+ *multiple = NCa (a) / NCb (b.coeffs[0]);
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline bool
+constant_multiple_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) ICa;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+
+ if (NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0)
+ return false;
+
+ C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+ for (unsigned int i = 1; i < N; ++i)
+ if (b.coeffs[i] == ICb (0)
+ ? a.coeffs[i] != ICa (0)
+ : (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0
+ || NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != r))
+ return false;
+
+ *multiple = r;
+ return true;
+}
+
+/* Return true if A is a constant multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+constant_multiple_p (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a.coeffs[0]) % NCb (b) != 0 || !a.is_constant ())
+ return false;
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+constant_multiple_p (Ca a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) int_type;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a) % NCb (b.coeffs[0]) != 0
+ || (a != int_type (0) && !b.is_constant ()))
+ return false;
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+constant_multiple_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) ICa;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+
+ if (NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0)
+ return false;
+
+ C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+ for (unsigned int i = 1; i < N; ++i)
+ if (b.coeffs[i] == ICb (0)
+ ? a.coeffs[i] != ICa (0)
+ : (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0
+ || NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != r))
+ return false;
+ return true;
+}
+
+
+/* Return true if A is a multiple of B. */
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+multiple_p (Ca a, Cb b)
+{
+ return a % b == 0;
+}
+
+/* Return true if A is a (polynomial) multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+multiple_p (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ for (unsigned int i = 0; i < N; ++i)
+ if (a.coeffs[i] % b != 0)
+ return false;
+ return true;
+}
+
+/* Return true if A is a (constant) multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+multiple_p (Ca a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_INT_TYPE (Ca) int_type;
+
+ /* Do the modulus before the constant check, to catch divide by
+ potential zeros. */
+ return a % b.coeffs[0] == 0 && (a == int_type (0) || b.is_constant ());
+}
+
+/* Return true if A is a (polynomial) multiple of B. This handles cases
+ where either B is constant or the multiple is constant. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+multiple_p (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (b.is_constant ())
+ return multiple_p (a, b.coeffs[0]);
+ POLY_BINARY_COEFF (Ca, Ca) tmp;
+ return constant_multiple_p (a, b, &tmp);
+}
+
+/* Return true if A is a (constant) multiple of B, storing the
+ multiple in *MULTIPLE if so. */
+
+template<typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+multiple_p (Ca a, Cb b, Cm *multiple)
+{
+ if (a % b != 0)
+ return false;
+ *multiple = a / b;
+ return true;
+}
+
+/* Return true if A is a (polynomial) multiple of B, storing the
+ multiple in *MULTIPLE if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Cb, bool>::type
+multiple_p (const poly_int_pod<N, Ca> &a, Cb b, poly_int_pod<N, Cm> *multiple)
+{
+ if (!multiple_p (a, b))
+ return false;
+ for (unsigned int i = 0; i < N; ++i)
+ multiple->coeffs[i] = a.coeffs[i] / b;
+ return true;
+}
+
+/* Return true if B is a constant and A is a (constant) multiple of B,
+ storing the multiple in *MULTIPLE if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Ca, bool>::type
+multiple_p (Ca a, const poly_int_pod<N, Cb> &b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+
+ /* Do the modulus before the constant check, to catch divide by
+ potential zeros. */
+ if (a % b.coeffs[0] != 0 || (NCa (a) != 0 && !b.is_constant ()))
+ return false;
+ *multiple = a / b.coeffs[0];
+ return true;
+}
+
+/* Return true if A is a (polynomial) multiple of B, storing the
+ multiple in *MULTIPLE if so. This handles cases where either
+ B is constant or the multiple is constant. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline bool
+multiple_p (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
+ poly_int_pod<N, Cm> *multiple)
+{
+ if (b.is_constant ())
+ return multiple_p (a, b.coeffs[0], multiple);
+ return constant_multiple_p (a, b, multiple);
+}
+
+/* Return A / B, given that A is known to be a multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+exact_div (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ {
+ gcc_checking_assert (a.coeffs[i] % b == 0);
+ POLY_SET_COEFF (C, r, i, a.coeffs[i] / b);
+ }
+ return r;
+}
+
+/* Return A / B, given that A is known to be a multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+exact_div (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (b.is_constant ())
+ return exact_div (a, b.coeffs[0]);
+
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+ typedef POLY_INT_TYPE (Cb) int_type;
+
+ gcc_checking_assert (a.coeffs[0] % b.coeffs[0] == 0);
+ C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+ for (unsigned int i = 1; i < N; ++i)
+ gcc_checking_assert (b.coeffs[i] == int_type (0)
+ ? a.coeffs[i] == int_type (0)
+ : (a.coeffs[i] % b.coeffs[i] == 0
+ && NCa (a.coeffs[i]) / NCb (b.coeffs[i]) == r));
+
+ return r;
+}
+
+/* Return true if there is some constant Q and polynomial r such that:
+
+ (1) a = b * Q + r
+ (2) |b * Q| <= |a|
+ (3) |r| < |b|
+
+ Store the value Q in *QUOTIENT if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly2<Cb, Cq, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b, Cq *quotient)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+
+ /* Do the division before the constant check, to catch divide by
+ zero errors. */
+ Cq q = NCa (a.coeffs[0]) / NCb (b);
+ if (!a.is_constant ())
+ return false;
+ *quotient = q;
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly<Cq, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cq *quotient)
+{
+ /* We can calculate Q from the case in which the indeterminates
+ are zero. */
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) ICa;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+ C q = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+
+ /* Check the other coefficients and record whether the division is exact.
+ The only difficult case is when it isn't. If we require a and b to
+ ordered wrt zero, there can be no two coefficients of the same value
+ that have opposite signs. This means that:
+
+ |a| = |a0| + |a1 * x1| + |a2 * x2| + ...
+ |b| = |b0| + |b1 * x1| + |b2 * x2| + ...
+
+ The Q we've just calculated guarantees:
+
+ |b0 * Q| <= |a0|
+ |a0 - b0 * Q| < |b0|
+
+ and so:
+
+ (2) |b * Q| <= |a|
+
+ is satisfied if:
+
+ |bi * xi * Q| <= |ai * xi|
+
+ for each i in [1, N]. This is trivially true when xi is zero.
+ When it isn't we need:
+
+ (2') |bi * Q| <= |ai|
+
+ r is calculated as:
+
+ r = r0 + r1 * x1 + r2 * x2 + ...
+ where ri = ai - bi * Q
+
+ Restricting to ordered a and b also guarantees that no two ris
+ have opposite signs, so we have:
+
+ |r| = |r0| + |r1 * x1| + |r2 * x2| + ...
+
+ We know from the calculation of Q that |r0| < |b0|, so:
+
+ (3) |r| < |b|
+
+ is satisfied if:
+
+ (3') |ai - bi * Q| <= |bi|
+
+ for each i in [1, N]. */
+ bool rem_p = NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0;
+ for (unsigned int i = 1; i < N; ++i)
+ {
+ if (b.coeffs[i] == ICb (0))
+ {
+ /* For bi == 0 we simply need: (3') |ai| == 0. */
+ if (a.coeffs[i] != ICa (0))
+ return false;
+ }
+ else
+ {
+ if (q == 0)
+ {
+ /* For Q == 0 we simply need: (3') |ai| <= |bi|. */
+ if (a.coeffs[i] != ICa (0))
+ {
+ /* Use negative absolute to avoid overflow, i.e.
+ -|ai| >= -|bi|. */
+ C neg_abs_a = (a.coeffs[i] < 0 ? a.coeffs[i] : -a.coeffs[i]);
+ C neg_abs_b = (b.coeffs[i] < 0 ? b.coeffs[i] : -b.coeffs[i]);
+ if (neg_abs_a < neg_abs_b)
+ return false;
+ rem_p = true;
+ }
+ }
+ else
+ {
+ /* Otherwise just check for the case in which ai / bi == Q. */
+ if (NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != q)
+ return false;
+ if (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0)
+ rem_p = true;
+ }
+ }
+ }
+
+ /* If the division isn't exact, require both values to be ordered wrt 0,
+ so that we can guarantee conditions (2) and (3) for all indeterminate
+ values. */
+ if (rem_p && (!ordered_p (a, ICa (0)) || !ordered_p (b, ICb (0))))
+ return false;
+
+ *quotient = q;
+ return true;
+}
+
+/* Likewise, but also store r in *REMAINDER. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq, typename Cr>
+inline typename if_nonpoly<Cq, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cq *quotient, Cr *remainder)
+{
+ if (!can_div_trunc_p (a, b, quotient))
+ return false;
+ *remainder = a - *quotient * b;
+ return true;
+}
+
+/* Return true if there is some polynomial q and constant R such that:
+
+ (1) a = B * q + R
+ (2) |B * q| <= |a|
+ (3) |R| < |B|
+
+ Store the value q in *QUOTIENT if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly<Cb, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b,
+ poly_int_pod<N, Cq> *quotient)
+{
+ /* The remainder must be constant. */
+ for (unsigned int i = 1; i < N; ++i)
+ if (a.coeffs[i] % b != 0)
+ return false;
+ for (unsigned int i = 0; i < N; ++i)
+ quotient->coeffs[i] = a.coeffs[i] / b;
+ return true;
+}
+
+/* Likewise, but also store R in *REMAINDER. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq, typename Cr>
+inline typename if_nonpoly<Cb, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b,
+ poly_int_pod<N, Cq> *quotient, Cr *remainder)
+{
+ if (!can_div_trunc_p (a, b, quotient))
+ return false;
+ *remainder = a.coeffs[0] % b;
+ return true;
+}
+
+/* Return true if we can compute A / B at compile time, rounding towards zero.
+ Store the result in QUOTIENT if so.
+
+ This handles cases in which either B is constant or the result is
+ constant. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline bool
+can_div_trunc_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ poly_int_pod<N, Cq> *quotient)
+{
+ if (b.is_constant ())
+ return can_div_trunc_p (a, b.coeffs[0], quotient);
+ if (!can_div_trunc_p (a, b, &quotient->coeffs[0]))
+ return false;
+ for (unsigned int i = 1; i < N; ++i)
+ quotient->coeffs[i] = 0;
+ return true;
+}
+
+/* Return true if there is some constant Q and polynomial r such that:
+
+ (1) a = b * Q + r
+ (2) |a| <= |b * Q|
+ (3) |r| < |b|
+
+ Store the value Q in *QUOTIENT if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly<Cq, bool>::type
+can_div_away_from_zero_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cq *quotient)
+{
+ if (!can_div_trunc_p (a, b, quotient))
+ return false;
+ if (maybe_ne (*quotient * b, a))
+ *quotient += (*quotient < 0 ? -1 : 1);
+ return true;
+}
+
+/* Use print_dec to print VALUE to FILE, where SGN is the sign
+ of the values. */
+
+template<unsigned int N, typename C>
+void
+print_dec (const poly_int_pod<N, C> &value, FILE *file, signop sgn)
+{
+ if (value.is_constant ())
+ print_dec (value.coeffs[0], file, sgn);
+ else
+ {
+ fprintf (file, "[");
+ for (unsigned int i = 0; i < N; ++i)
+ {
+ print_dec (value.coeffs[i], file, sgn);
+ fputc (i == N - 1 ? ']' : ',', file);
+ }
+ }
+}
+
+/* Likewise without the signop argument, for coefficients that have an
+ inherent signedness. */
+
+template<unsigned int N, typename C>
+void
+print_dec (const poly_int_pod<N, C> &value, FILE *file)
+{
+ STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
+ print_dec (value, file,
+ poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED);
+}
+
+/* Use print_hex to print VALUE to FILE. */
+
+template<unsigned int N, typename C>
+void
+print_hex (const poly_int_pod<N, C> &value, FILE *file)
+{
+ if (value.is_constant ())
+ print_hex (value.coeffs[0], file);
+ else
+ {
+ fprintf (file, "[");
+ for (unsigned int i = 0; i < N; ++i)
+ {
+ print_hex (value.coeffs[i], file);
+ fputc (i == N - 1 ? ']' : ',', file);
+ }
+ }
+}
+
+/* Helper for calculating the distance between two points P1 and P2,
+ in cases where known_le (P1, P2). T1 and T2 are the types of the
+ two positions, in either order. The coefficients of P2 - P1 have
+ type unsigned HOST_WIDE_INT if the coefficients of both T1 and T2
+ have C++ primitive type, otherwise P2 - P1 has its usual
+ wide-int-based type.
+
+ The actual subtraction should look something like this:
+
+ typedef poly_span_traits<T1, T2> span_traits;
+ span_traits::cast (P2) - span_traits::cast (P1)
+
+ Applying the cast before the subtraction avoids undefined overflow
+ for signed T1 and T2.
+
+ The implementation of the cast tries to avoid unnecessary arithmetic
+ or copying. */
+template<typename T1, typename T2,
+ typename Res = POLY_BINARY_COEFF (POLY_BINARY_COEFF (T1, T2),
+ unsigned HOST_WIDE_INT)>
+struct poly_span_traits
+{
+ template<typename T>
+ static const T &cast (const T &x) { return x; }
+};
+
+template<typename T1, typename T2>
+struct poly_span_traits<T1, T2, unsigned HOST_WIDE_INT>
+{
+ template<typename T>
+ static typename if_nonpoly<T, unsigned HOST_WIDE_INT>::type
+ cast (const T &x) { return x; }
+
+ template<unsigned int N, typename T>
+ static poly_int<N, unsigned HOST_WIDE_INT>
+ cast (const poly_int_pod<N, T> &x) { return x; }
+};
+
+/* Return true if SIZE represents a known size, assuming that all-ones
+ indicates an unknown size. */
+
+template<typename T>
+inline bool
+known_size_p (const T &a)
+{
+ return maybe_ne (a, POLY_INT_TYPE (T) (-1));
+}
+
+/* Return true if range [POS, POS + SIZE) might include VAL.
+ SIZE can be the special value -1, in which case the range is
+ open-ended. */
+
+template<typename T1, typename T2, typename T3>
+inline bool
+maybe_in_range_p (const T1 &val, const T2 &pos, const T3 &size)
+{
+ typedef poly_span_traits<T1, T2> start_span;
+ typedef poly_span_traits<T3, T3> size_span;
+ if (known_lt (val, pos))
+ return false;
+ if (!known_size_p (size))
+ return true;
+ if ((poly_int_traits<T1>::num_coeffs > 1
+ || poly_int_traits<T2>::num_coeffs > 1)
+ && maybe_lt (val, pos))
+ /* In this case we don't know whether VAL >= POS is true at compile
+ time, so we can't prove that VAL >= POS + SIZE. */
+ return true;
+ return maybe_lt (start_span::cast (val) - start_span::cast (pos),
+ size_span::cast (size));
+}
+
+/* Return true if range [POS, POS + SIZE) is known to include VAL.
+ SIZE can be the special value -1, in which case the range is
+ open-ended. */
+
+template<typename T1, typename T2, typename T3>
+inline bool
+known_in_range_p (const T1 &val, const T2 &pos, const T3 &size)
+{
+ typedef poly_span_traits<T1, T2> start_span;
+ typedef poly_span_traits<T3, T3> size_span;
+ return (known_size_p (size)
+ && known_ge (val, pos)
+ && known_lt (start_span::cast (val) - start_span::cast (pos),
+ size_span::cast (size)));
+}
+
+/* Return true if the two ranges [POS1, POS1 + SIZE1) and [POS2, POS2 + SIZE2)
+ might overlap. SIZE1 and/or SIZE2 can be the special value -1, in which
+ case the range is open-ended. */
+
+template<typename T1, typename T2, typename T3, typename T4>
+inline bool
+ranges_maybe_overlap_p (const T1 &pos1, const T2 &size1,
+ const T3 &pos2, const T4 &size2)
+{
+ if (maybe_in_range_p (pos2, pos1, size1))
+ return maybe_ne (size2, POLY_INT_TYPE (T4) (0));
+ if (maybe_in_range_p (pos1, pos2, size2))
+ return maybe_ne (size1, POLY_INT_TYPE (T2) (0));
+ return false;
+}
+
+/* Return true if the two ranges [POS1, POS1 + SIZE1) and [POS2, POS2 + SIZE2)
+ are known to overlap. SIZE1 and/or SIZE2 can be the special value -1,
+ in which case the range is open-ended. */
+
+template<typename T1, typename T2, typename T3, typename T4>
+inline bool
+ranges_known_overlap_p (const T1 &pos1, const T2 &size1,
+ const T3 &pos2, const T4 &size2)
+{
+ typedef poly_span_traits<T1, T3> start_span;
+ typedef poly_span_traits<T2, T2> size1_span;
+ typedef poly_span_traits<T4, T4> size2_span;
+ /* known_gt (POS1 + SIZE1, POS2) [infinite precision]
+ --> known_gt (SIZE1, POS2 - POS1) [infinite precision]
+ --> known_gt (SIZE1, POS2 - lower_bound (POS1, POS2)) [infinite precision]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ always nonnegative
+ --> known_gt (SIZE1, span1::cast (POS2 - lower_bound (POS1, POS2))).
+
+ Using the saturating subtraction enforces that SIZE1 must be
+ nonzero, since known_gt (0, x) is false for all nonnegative x.
+ If POS2.coeff[I] < POS1.coeff[I] for some I > 0, increasing
+ indeterminate number I makes the unsaturated condition easier to
+ satisfy, so using a saturated coefficient of zero tests the case in
+ which the indeterminate is zero (the minimum value). */
+ return (known_size_p (size1)
+ && known_size_p (size2)
+ && known_lt (start_span::cast (pos2)
+ - start_span::cast (lower_bound (pos1, pos2)),
+ size1_span::cast (size1))
+ && known_lt (start_span::cast (pos1)
+ - start_span::cast (lower_bound (pos1, pos2)),
+ size2_span::cast (size2)));
+}
+
+/* Return true if range [POS1, POS1 + SIZE1) is known to be a subrange of
+ [POS2, POS2 + SIZE2). SIZE1 and/or SIZE2 can be the special value -1,
+ in which case the range is open-ended. */
+
+template<typename T1, typename T2, typename T3, typename T4>
+inline bool
+known_subrange_p (const T1 &pos1, const T2 &size1,
+ const T3 &pos2, const T4 &size2)
+{
+ typedef typename poly_int_traits<T2>::coeff_type C2;
+ typedef poly_span_traits<T1, T3> start_span;
+ typedef poly_span_traits<T2, T4> size_span;
+ return (known_gt (size1, POLY_INT_TYPE (T2) (0))
+ && (poly_coeff_traits<C2>::signedness > 0
+ || known_size_p (size1))
+ && known_size_p (size2)
+ && known_ge (pos1, pos2)
+ && known_le (size1, size2)
+ && known_le (start_span::cast (pos1) - start_span::cast (pos2),
+ size_span::cast (size2) - size_span::cast (size1)));
+}
+
+/* Return true if the endpoint of the range [POS, POS + SIZE) can be
+ stored in a T, or if SIZE is the special value -1, which makes the
+ range open-ended. */
+
+template<typename T>
+inline typename if_nonpoly<T, bool>::type
+endpoint_representable_p (const T &pos, const T &size)
+{
+ return (!known_size_p (size)
+ || pos <= poly_coeff_traits<T>::max_value - size);
+}
+
+template<unsigned int N, typename C>
+inline bool
+endpoint_representable_p (const poly_int_pod<N, C> &pos,
+ const poly_int_pod<N, C> &size)
+{
+ if (known_size_p (size))
+ for (unsigned int i = 0; i < N; ++i)
+ if (pos.coeffs[i] > poly_coeff_traits<C>::max_value - size.coeffs[i])
+ return false;
+ return true;
+}
+
+template<unsigned int N, typename C>
+void
+gt_ggc_mx (poly_int_pod<N, C> *)
+{
+}
+
+template<unsigned int N, typename C>
+void
+gt_pch_nx (poly_int_pod<N, C> *)
+{
+}
+
+template<unsigned int N, typename C>
+void
+gt_pch_nx (poly_int_pod<N, C> *, gt_pointer_operator, void *)
+{
+}
+
+#undef POLY_SET_COEFF
+#undef POLY_INT_TYPE
+#undef POLY_BINARY_COEFF
+#undef CONST_CONST_RESULT
+#undef POLY_CONST_RESULT
+#undef CONST_POLY_RESULT
+#undef POLY_POLY_RESULT
+#undef POLY_CONST_COEFF
+#undef CONST_POLY_COEFF
+#undef POLY_POLY_COEFF
+
+#endif
diff --git a/support/cpp/gcc/predict.def b/support/cpp/gcc/predict.def
new file mode 100644
index 000000000..c3f76f566
--- /dev/null
+++ b/support/cpp/gcc/predict.def
@@ -0,0 +1,238 @@
+/* Definitions for the branch prediction routines in the GNU compiler.
+ Copyright (C) 2001-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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_PREDICTOR (ENUM, NAME, HITRATE)
+
+ This macro will be called once for each predictor. The ENUM will
+ be of type `enum br_predictor', and will enumerate all supported
+ predictors. The order of DEF_PREDICTOR calls is important, as
+ in the first match combining heuristics, the predictor appearing
+ first in this file will win.
+
+ NAME is used in the debugging output to determine predictor type.
+
+ HITRATE is the probability that edge predicted by predictor as taken
+ will be really taken (so it should be always above
+ REG_BR_PROB_BASE / 2). */
+
+
+/* A value used as final outcome of all heuristics. */
+DEF_PREDICTOR (PRED_COMBINED, "combined", PROB_ALWAYS, 0)
+
+/* An outcome estimated by Dempster-Shaffer theory. */
+DEF_PREDICTOR (PRED_DS_THEORY, "DS theory", PROB_ALWAYS, 0)
+
+/* A combined heuristics using probability determined by first
+ matching heuristics from this list. */
+DEF_PREDICTOR (PRED_FIRST_MATCH, "first match", PROB_ALWAYS, 0)
+
+/* Heuristic applying when no heuristic below applies. */
+DEF_PREDICTOR (PRED_NO_PREDICTION, "no prediction", PROB_ALWAYS, 0)
+
+/* Mark unconditional jump as taken. */
+DEF_PREDICTOR (PRED_UNCONDITIONAL, "unconditional jump", PROB_ALWAYS,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Return value of malloc function is almost always non-null. */
+DEF_PREDICTOR (PRED_MALLOC_NONNULL, "malloc returned non-NULL", \
+ PROB_VERY_LIKELY, PRED_FLAG_FIRST_MATCH)
+
+/* Use number of loop iterations determined by # of iterations
+ analysis to set probability. We don't want to use Dempster-Shaffer
+ theory here, as the predictions is exact. */
+DEF_PREDICTOR (PRED_LOOP_ITERATIONS, "loop iterations", PROB_UNINITIALIZED,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Assume that any given atomic operation has low contention,
+ and thus the compare-and-swap operation succeeds. */
+DEF_PREDICTOR (PRED_COMPARE_AND_SWAP, "compare and swap", PROB_VERY_LIKELY,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Hints dropped by user via __builtin_expect feature. Note: the
+ probability of PROB_VERY_LIKELY is now overwritten by param
+ builtin_expect_probability with a default value of HITRATE(90).
+ Refer to param.def for details. */
+DEF_PREDICTOR (PRED_BUILTIN_EXPECT, "__builtin_expect", PROB_VERY_LIKELY,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Hints provided by user via __builtin_expect_with_probability. */
+DEF_PREDICTOR (PRED_BUILTIN_EXPECT_WITH_PROBABILITY,
+ "__builtin_expect_with_probability", PROB_UNINITIALIZED,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Branches to hot labels are likely. */
+DEF_PREDICTOR (PRED_HOT_LABEL, "hot label", HITRATE (90),
+ PRED_FLAG_FIRST_MATCH)
+
+/* Branches to cold labels are extremely unlikely. */
+DEF_PREDICTOR (PRED_COLD_LABEL, "cold label", HITRATE (90),
+ PRED_FLAG_FIRST_MATCH)
+
+/* Use number of loop iterations guessed by the contents of the loop. */
+DEF_PREDICTOR (PRED_LOOP_ITERATIONS_GUESSED, "guessed loop iterations",
+ PROB_UNINITIALIZED, PRED_FLAG_FIRST_MATCH)
+
+/* Use number of loop iterations guessed by the contents of the loop. */
+DEF_PREDICTOR (PRED_LOOP_ITERATIONS_MAX, "guessed loop iterations",
+ PROB_UNINITIALIZED, PRED_FLAG_FIRST_MATCH)
+
+/* Branch containing goto is probably not taken. */
+DEF_PREDICTOR (PRED_CONTINUE, "continue", HITRATE (67), 0)
+
+/* Branch to basic block containing call marked by noreturn attribute. */
+DEF_PREDICTOR (PRED_NORETURN, "noreturn call", PROB_VERY_LIKELY,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Branch to basic block containing call marked by cold function attribute. */
+DEF_PREDICTOR (PRED_COLD_FUNCTION, "cold function call", PROB_VERY_LIKELY,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Edge causing loop to terminate is probably not taken. */
+DEF_PREDICTOR (PRED_LOOP_EXIT, "loop exit", HITRATE (89),
+ PRED_FLAG_FIRST_MATCH)
+
+/* Same as LOOP_EXIT but for loops containing recursive call. */
+DEF_PREDICTOR (PRED_LOOP_EXIT_WITH_RECURSION, "loop exit with recursion",
+ HITRATE (78), PRED_FLAG_FIRST_MATCH)
+
+/* Edge causing loop to terminate by computing value used by later
+ conditional. */
+DEF_PREDICTOR (PRED_LOOP_EXTRA_EXIT, "extra loop exit", HITRATE (67),
+ PRED_FLAG_FIRST_MATCH)
+
+/* Pointers are usually not NULL. */
+DEF_PREDICTOR (PRED_POINTER, "pointer", HITRATE (70), 0)
+DEF_PREDICTOR (PRED_TREE_POINTER, "pointer (on trees)", HITRATE (70), 0)
+
+/* NE is probable, EQ not etc... */
+DEF_PREDICTOR (PRED_OPCODE_POSITIVE, "opcode values positive", HITRATE (59), 0)
+DEF_PREDICTOR (PRED_OPCODE_NONEQUAL, "opcode values nonequal", HITRATE (66), 0)
+DEF_PREDICTOR (PRED_FPOPCODE, "fp_opcode", HITRATE (90), 0)
+DEF_PREDICTOR (PRED_TREE_OPCODE_POSITIVE, "opcode values positive (on trees)",
+ HITRATE (59), 0)
+DEF_PREDICTOR (PRED_TREE_OPCODE_NONEQUAL, "opcode values nonequal (on trees)",
+ HITRATE (66), 0)
+DEF_PREDICTOR (PRED_TREE_FPOPCODE, "fp_opcode (on trees)", HITRATE (90), 0)
+
+/* Branch guarding call is probably taken. */
+DEF_PREDICTOR (PRED_CALL, "call", HITRATE (67), 0)
+
+/* Call predictors are for now ignored, lets leave the predictor
+ to measure its benefit. */
+DEF_PREDICTOR (PRED_INDIR_CALL, "indirect call", PROB_EVEN, 0)
+DEF_PREDICTOR (PRED_POLYMORPHIC_CALL, "polymorphic call", PROB_EVEN, 0)
+DEF_PREDICTOR (PRED_RECURSIVE_CALL, "recursive call", PROB_EVEN, 0)
+
+/* Branch causing function to terminate is probably not taken. */
+DEF_PREDICTOR (PRED_TREE_EARLY_RETURN, "early return (on trees)", HITRATE (66),
+ 0)
+
+/* Branch containing goto is probably not taken. */
+DEF_PREDICTOR (PRED_GOTO, "goto", HITRATE (66), 0)
+
+/* Branch ending with return constant is probably not taken. */
+DEF_PREDICTOR (PRED_CONST_RETURN, "const return", HITRATE (65), 0)
+
+/* Branch ending with return negative constant is probably not taken. */
+DEF_PREDICTOR (PRED_NEGATIVE_RETURN, "negative return", HITRATE (98), 0)
+
+/* Branch ending with return; is probably not taken */
+DEF_PREDICTOR (PRED_NULL_RETURN, "null return", HITRATE (71), 0)
+
+/* Branches to compare induction variable to a loop bound is
+ extremely likely. */
+DEF_PREDICTOR (PRED_LOOP_IV_COMPARE_GUESS, "guess loop iv compare",
+ HITRATE (64), 0)
+
+/* Use number of loop iterations determined by # of iterations analysis
+ to set probability of branches that compares IV to loop bound variable. */
+DEF_PREDICTOR (PRED_LOOP_IV_COMPARE, "loop iv compare", PROB_UNINITIALIZED,
+ PRED_FLAG_FIRST_MATCH)
+
+/* In the following code
+ for (loop1)
+ if (cond)
+ for (loop2)
+ body;
+ guess that cond is unlikely. */
+DEF_PREDICTOR (PRED_LOOP_GUARD, "loop guard", HITRATE (73), 0)
+
+/* Same but for loops containing recursion. */
+DEF_PREDICTOR (PRED_LOOP_GUARD_WITH_RECURSION, "loop guard with recursion",
+ HITRATE (85), 0)
+
+/* The following predictors are used in Fortran. */
+
+/* Branch leading to an integer overflow are extremely unlikely. */
+DEF_PREDICTOR (PRED_FORTRAN_OVERFLOW, "Fortran overflow", PROB_ALWAYS,
+ PRED_FLAG_FIRST_MATCH)
+
+/* Branch leading to a failure status are unlikely. This can occur for out
+ of memory. This predictor only occurs when the user explicitly asked
+ for a return status. By default, the code aborts,
+ which is handled via PRED_NORETURN. */
+DEF_PREDICTOR (PRED_FORTRAN_FAIL_ALLOC, "Fortran fail alloc",
+ PROB_VERY_LIKELY, 0)
+
+/* Predictor is used for an allocation of an already allocated memory or
+ deallocating an already deallocated allocatable. */
+DEF_PREDICTOR (PRED_FORTRAN_REALLOC, "Fortran repeated allocation/deallocation",
+ PROB_LIKELY, 0)
+
+/* Branch leading to an I/O failure status are unlikely. This predictor is
+ used for I/O failures such as for invalid unit numbers. This predictor
+ only occurs when the user explicitly asked for a return status. By default,
+ the code aborts, which is handled via PRED_NORETURN. */
+DEF_PREDICTOR (PRED_FORTRAN_FAIL_IO, "Fortran fail IO", HITRATE (85), 0)
+
+/* Branch leading to a run-time warning message which is printed only once
+ are unlikely. The print-warning branch itself can be likely or unlikely. */
+DEF_PREDICTOR (PRED_FORTRAN_WARN_ONCE, "Fortran warn once", HITRATE (75), 0)
+
+/* Branch belonging to a zero-sized array. */
+DEF_PREDICTOR (PRED_FORTRAN_SIZE_ZERO, "Fortran zero-sized array", \
+ HITRATE (99), 0)
+
+/* Branch belonging to an invalid bound index, in a context where it is
+ standard conform and well defined but rather pointless and, hence, rather
+ unlikely to occur. */
+DEF_PREDICTOR (PRED_FORTRAN_INVALID_BOUND, "Fortran invalid bound", \
+ HITRATE (90), 0)
+
+/* Branch belonging to the handling of absent optional arguments. This
+ predictor is used when an optional dummy argument, associated with an
+ absent argument, is passed on as actual argument to another procedure,
+ which in turn has an optional argument. */
+DEF_PREDICTOR (PRED_FORTRAN_ABSENT_DUMMY, "Fortran absent dummy", \
+ HITRATE (60), 0)
+
+/* Fortran DO statement generates a pre-header guard:
+ empty = (step > 0 ? to < from : to > from), which can be predicted
+ to be very likely. */
+DEF_PREDICTOR (PRED_FORTRAN_LOOP_PREHEADER, "Fortran loop preheader", \
+ HITRATE (99), 0)
+
+/* Fortran assumed size arrays can be non-contiguous, so they need
+ to be repacked. */
+
+DEF_PREDICTOR (PRED_FORTRAN_CONTIGUOUS, "Fortran contiguous", \
+ HITRATE (75), 0)
+
diff --git a/support/cpp/gcc/predict.h b/support/cpp/gcc/predict.h
new file mode 100644
index 000000000..864997498
--- /dev/null
+++ b/support/cpp/gcc/predict.h
@@ -0,0 +1,110 @@
+/* Definitions for branch prediction routines in the GNU compiler.
+ Copyright (C) 2001-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_PREDICT_H
+#define GCC_PREDICT_H
+
+#include "profile-count.h"
+
+/* Random guesstimation given names.
+ PROB_VERY_UNLIKELY should be small enough so basic block predicted
+ by it gets below HOT_BB_FREQUENCY_FRACTION. */
+#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1)
+#define PROB_EVEN (REG_BR_PROB_BASE / 2)
+#define PROB_VERY_LIKELY (REG_BR_PROB_BASE - PROB_VERY_UNLIKELY)
+#define PROB_ALWAYS (REG_BR_PROB_BASE)
+#define PROB_UNLIKELY (REG_BR_PROB_BASE / 5 - 1)
+#define PROB_LIKELY (REG_BR_PROB_BASE - PROB_UNLIKELY)
+#define PROB_UNINITIALIZED (-1)
+
+#define DEF_PREDICTOR(ENUM, NAME, HITRATE, FLAGS) ENUM,
+enum br_predictor
+{
+#include "predict.def"
+
+ /* Upper bound on non-language-specific builtins. */
+ END_PREDICTORS
+};
+#undef DEF_PREDICTOR
+enum prediction
+{
+ NOT_TAKEN,
+ TAKEN
+};
+
+/* In emit-rtl.cc. */
+extern profile_probability split_branch_probability;
+
+extern gcov_type get_hot_bb_threshold (void);
+extern void set_hot_bb_threshold (gcov_type);
+extern bool maybe_hot_count_p (struct function *, profile_count);
+extern bool maybe_hot_bb_p (struct function *, const_basic_block);
+extern bool maybe_hot_edge_p (edge);
+extern bool probably_never_executed_bb_p (struct function *, const_basic_block);
+extern bool probably_never_executed_edge_p (struct function *, edge);
+extern enum optimize_size_level optimize_function_for_size_p (struct function *);
+extern bool optimize_function_for_speed_p (struct function *);
+extern optimization_type function_optimization_type (struct function *);
+extern enum optimize_size_level optimize_bb_for_size_p (const_basic_block);
+extern bool optimize_bb_for_speed_p (const_basic_block);
+extern optimization_type bb_optimization_type (const_basic_block);
+extern enum optimize_size_level optimize_edge_for_size_p (edge);
+extern bool optimize_edge_for_speed_p (edge);
+extern enum optimize_size_level optimize_insn_for_size_p (void);
+extern bool optimize_insn_for_speed_p (void);
+extern enum optimize_size_level optimize_loop_for_size_p (class loop *);
+extern bool optimize_loop_for_speed_p (class loop *);
+extern bool optimize_loop_nest_for_speed_p (class loop *);
+extern enum optimize_size_level optimize_loop_nest_for_size_p (class loop *);
+extern bool predictable_edge_p (edge);
+extern void rtl_profile_for_bb (basic_block);
+extern void rtl_profile_for_edge (edge);
+extern void default_rtl_profile (void);
+extern bool rtl_predicted_by_p (const_basic_block, enum br_predictor);
+extern bool gimple_predicted_by_p (const_basic_block, enum br_predictor);
+extern bool edge_probability_reliable_p (const_edge);
+extern bool br_prob_note_reliable_p (const_rtx);
+extern void predict_insn_def (rtx_insn *, enum br_predictor, enum prediction);
+extern void rtl_predict_edge (edge, enum br_predictor, int);
+extern void gimple_predict_edge (edge, enum br_predictor, int);
+extern void remove_predictions_associated_with_edge (edge);
+extern void predict_edge_def (edge, enum br_predictor, enum prediction);
+extern void invert_br_probabilities (rtx);
+extern void guess_outgoing_edge_probabilities (basic_block);
+extern void tree_guess_outgoing_edge_probabilities (basic_block);
+extern void tree_estimate_probability (bool);
+extern void handle_missing_profiles (void);
+extern bool update_max_bb_count (void);
+extern bool expensive_function_p (int);
+extern void estimate_bb_frequencies (bool);
+extern void compute_function_frequency (void);
+extern tree build_predict_expr (enum br_predictor, enum prediction);
+extern const char *predictor_name (enum br_predictor);
+extern void rebuild_frequencies (void);
+extern void report_predictor_hitrates (void);
+extern void force_edge_cold (edge, bool);
+extern void propagate_unlikely_bbs_forward (void);
+extern void change_edge_frequency (edge, profile_probability);
+
+extern void add_reg_br_prob_note (rtx_insn *, profile_probability);
+
+/* In ipa-pure-const.cc */
+extern void warn_function_cold (tree);
+
+#endif /* GCC_PREDICT_H */
diff --git a/support/cpp/gcc/prefix.cc b/support/cpp/gcc/prefix.cc
new file mode 100644
index 000000000..c6b4124d1
--- /dev/null
+++ b/support/cpp/gcc/prefix.cc
@@ -0,0 +1,355 @@
+/* Utility to update paths from internal to external forms.
+ 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 Library General Public License as published by
+the Free Software Foundation; either version 3 of the License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This file contains routines to update a path, both to canonicalize
+ the directory format and to handle any prefix translation.
+
+ This file must be compiled with -DPREFIX= to specify the "prefix"
+ value used by configure. If a filename does not begin with this
+ prefix, it will not be affected other than by directory canonicalization.
+
+ Each caller of 'update_path' may specify both a filename and
+ a translation prefix and consist of the name of the package that contains
+ the file ("@GCC", "@BINUTIL", "@GNU", etc).
+
+ If the prefix is not specified, the filename will only undergo
+ directory canonicalization.
+
+ If it is specified, the string given by PREFIX will be replaced
+ by the specified prefix (with a '@' in front unless the prefix begins
+ with a '$') and further translation will be done as follows
+ until none of the two conditions below are met:
+
+ 1) If the filename begins with '@', the string between the '@' and
+ the end of the name or the first '/' or directory separator will
+ be considered a "key" and looked up as follows:
+
+ -- If this is a Win32 OS, then the Registry will be examined for
+ an entry of "key" in
+
+ HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\<KEY>
+
+ if found, that value will be used. <KEY> defaults to GCC version
+ string, but can be overridden at configuration time.
+
+ -- If not found (or not a Win32 OS), the environment variable
+ key_ROOT (the value of "key" concatenated with the constant "_ROOT")
+ is tried. If that fails, then PREFIX (see above) is used.
+
+ 2) If the filename begins with a '$', the rest of the string up
+ to the end or the first '/' or directory separator will be used
+ as an environment variable, whose value will be returned.
+
+ Once all this is done, any '/' will be converted to DIR_SEPARATOR,
+ if they are different.
+
+ NOTE: using resolve_keyed_path under Win32 requires linking with
+ advapi32.dll. */
+
+
+#include <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ \
+ <<":" << __func__ << "\n" )
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
+#include <windows.h>
+#endif
+#include "prefix.h"
+#include "common/common-target.h"
+
+static const char *std_prefix = PREFIX;
+
+static const char *get_key_value (char *);
+static char *translate_name (char *);
+static char *save_string (const char *, int);
+static void tr (char *, int, int);
+
+#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
+static char *lookup_key (char *);
+static HKEY reg_key = (HKEY) INVALID_HANDLE_VALUE;
+#endif
+
+/* Given KEY, as above, return its value. */
+
+static const char *
+get_key_value (char *key)
+{
+ const char *prefix = 0;
+ char *temp = 0;
+
+#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
+ prefix = lookup_key (key);
+#endif
+
+ if (prefix == 0)
+ prefix = getenv (temp = concat (key, "_ROOT", NULL));
+
+ if (prefix == 0)
+ prefix = std_prefix;
+
+ free (temp);
+
+ return prefix;
+}
+
+/* Return a copy of a string that has been placed in the heap. */
+
+static char *
+save_string (const char *s, int len)
+{
+ char *result = XNEWVEC (char, len + 1);
+
+ memcpy (result, s, len);
+ result[len] = 0;
+ return result;
+}
+
+#if defined(_WIN32) && defined(ENABLE_WIN32_REGISTRY)
+
+#ifndef WIN32_REGISTRY_KEY
+# define WIN32_REGISTRY_KEY BASEVER
+#endif
+
+/* Look up "key" in the registry, as above. */
+
+static char *
+lookup_key (char *key)
+{
+ char *dst;
+ DWORD size;
+ DWORD type;
+ LONG res;
+
+ if (reg_key == (HKEY) INVALID_HANDLE_VALUE)
+ {
+ res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0,
+ KEY_READ, &reg_key);
+
+ if (res == ERROR_SUCCESS)
+ res = RegOpenKeyExA (reg_key, "Free Software Foundation", 0,
+ KEY_READ, &reg_key);
+
+ if (res == ERROR_SUCCESS)
+ res = RegOpenKeyExA (reg_key, WIN32_REGISTRY_KEY, 0,
+ KEY_READ, &reg_key);
+
+ if (res != ERROR_SUCCESS)
+ {
+ reg_key = (HKEY) INVALID_HANDLE_VALUE;
+ return 0;
+ }
+ }
+
+ size = 32;
+ dst = XNEWVEC (char, size);
+
+ res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size);
+ if (res == ERROR_MORE_DATA && type == REG_SZ)
+ {
+ dst = XRESIZEVEC (char, dst, size);
+ res = RegQueryValueExA (reg_key, key, 0, &type, (LPBYTE) dst, &size);
+ }
+
+ if (type != REG_SZ || res != ERROR_SUCCESS)
+ {
+ free (dst);
+ dst = 0;
+ }
+
+ return dst;
+}
+#endif
+
+/* If NAME, a malloc-ed string, starts with a '@' or '$', apply the
+ translation rules above and return a newly malloc-ed name.
+ Otherwise, return the given name. */
+
+static char *
+translate_name (char *name)
+{
+ char code;
+ char *key, *old_name;
+ const char *prefix;
+ int keylen;
+
+ for (;;)
+ {
+ code = name[0];
+ if (code != '@' && code != '$')
+ break;
+
+ for (keylen = 0;
+ (name[keylen + 1] != 0 && !IS_DIR_SEPARATOR (name[keylen + 1]));
+ keylen++)
+ ;
+
+ key = (char *) alloca (keylen + 1);
+ memcpy (key, &name[1], keylen);
+ key[keylen] = 0;
+
+ if (code == '@')
+ {
+ prefix = get_key_value (key);
+ if (prefix == 0)
+ prefix = std_prefix;
+ }
+ else
+ prefix = getenv (key);
+
+ if (prefix == 0)
+ prefix = PREFIX;
+
+ /* We used to strip trailing DIR_SEPARATORs here, but that can
+ sometimes yield a result with no separator when one was coded
+ and intended by the user, causing two path components to run
+ together. */
+
+ old_name = name;
+ name = concat (prefix, &name[keylen + 1], NULL);
+ free (old_name);
+ }
+
+ return name;
+}
+
+/* In a NUL-terminated STRING, replace character C1 with C2 in-place. */
+static void
+tr (char *string, int c1, int c2)
+{
+ do
+ {
+ if (*string == c1)
+ *string = c2;
+ }
+ while (*string++);
+}
+
+/* Update PATH using KEY if PATH starts with PREFIX as a directory.
+ The returned string is always malloc-ed, and the caller is
+ responsible for freeing it. */
+
+char *
+update_path (const char *path, const char *key)
+{
+ char *result, *p;
+ const int len = strlen (std_prefix);
+
+ if (! filename_ncmp (path, std_prefix, len)
+ && (IS_DIR_SEPARATOR (path[len])
+ || path[len] == '\0')
+ && key != 0)
+ {
+ bool free_key = false;
+
+ if (key[0] != '$')
+ {
+ key = concat ("@", key, NULL);
+ free_key = true;
+ }
+
+ result = concat (key, &path[len], NULL);
+ if (free_key)
+ free (CONST_CAST (char *, key));
+ result = translate_name (result);
+ }
+ else
+ result = xstrdup (path);
+
+ p = result;
+ while (1)
+ {
+ char *src, *dest;
+
+ p = strchr (p, '.');
+ if (p == NULL)
+ break;
+ /* Look for `/../' */
+ if (p[1] == '.'
+ && IS_DIR_SEPARATOR (p[2])
+ && (p != result && IS_DIR_SEPARATOR (p[-1])))
+ {
+ *p = 0;
+ if (1 // sdcpp !targetm_common.always_strip_dotdot
+ && access (result, X_OK) == 0)
+ {
+ *p = '.';
+ break;
+ }
+ else
+ {
+ /* We can't access the dir, so we won't be able to
+ access dir/.. either. Strip out `dir/../'. If `dir'
+ turns out to be `.', strip one more path component. */
+ dest = p;
+ do
+ {
+ --dest;
+ while (dest != result && IS_DIR_SEPARATOR (*dest))
+ --dest;
+ while (dest != result && !IS_DIR_SEPARATOR (dest[-1]))
+ --dest;
+ }
+ while (dest != result && *dest == '.');
+ /* If we have something like `./..' or `/..', don't
+ strip anything more. */
+ if (*dest == '.' || IS_DIR_SEPARATOR (*dest))
+ {
+ *p = '.';
+ break;
+ }
+ src = p + 3;
+ while (IS_DIR_SEPARATOR (*src))
+ ++src;
+ p = dest;
+ while ((*dest++ = *src++) != 0)
+ ;
+ }
+ }
+ else
+ ++p;
+ }
+
+#ifdef UPDATE_PATH_HOST_CANONICALIZE
+ /* Perform host dependent canonicalization when needed. */
+ UPDATE_PATH_HOST_CANONICALIZE (result);
+#endif
+
+#ifdef DIR_SEPARATOR_2
+ /* Convert DIR_SEPARATOR_2 to DIR_SEPARATOR. */
+ if (DIR_SEPARATOR_2 != DIR_SEPARATOR)
+ tr (result, DIR_SEPARATOR_2, DIR_SEPARATOR);
+#endif
+
+#if defined (DIR_SEPARATOR) && !defined (DIR_SEPARATOR_2)
+ if (DIR_SEPARATOR != '/')
+ tr (result, '/', DIR_SEPARATOR);
+#endif
+
+ return result;
+}
+
+/* Reset the standard prefix. */
+void
+set_std_prefix (const char *prefix, int len)
+{
+ std_prefix = save_string (prefix, len);
+}
diff --git a/support/cpp/gcc/prefix.h b/support/cpp/gcc/prefix.h
new file mode 100644
index 000000000..8276eb86a
--- /dev/null
+++ b/support/cpp/gcc/prefix.h
@@ -0,0 +1,40 @@
+/* Provide prototypes for functions exported from prefix.cc.
+ 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 Library General Public License as published by
+the Free Software Foundation; either version 3 of the License, 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+
+#ifndef GCC_PREFIX_H
+#define GCC_PREFIX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These functions are called by the Ada frontend with C convention. */
+
+/* Update PATH using KEY if PATH starts with PREFIX. The returned
+ string is always malloc-ed, and the caller is responsible for
+ freeing it. */
+extern char *update_path (const char *path, const char *key);
+extern void set_std_prefix (const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! GCC_PREFIX_H */
diff --git a/support/cpp/gcc/pretty-print.cc b/support/cpp/gcc/pretty-print.cc
new file mode 100644
index 000000000..53733a604
--- /dev/null
+++ b/support/cpp/gcc/pretty-print.cc
@@ -0,0 +1,2629 @@
+/* Various declarations for language-independent pretty-print subroutines.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+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 "intl.h"
+#include "pretty-print.h"
+#include "diagnostic-color.h"
+#include "diagnostic-event-id.h"
+#include "selftest.h"
+
+#if HAVE_ICONV
+#include <iconv.h>
+#endif
+
+#ifdef __MINGW32__
+
+/* Replacement for fputs() that handles ANSI escape codes on Windows NT.
+ Contributed by: Liu Hao (lh_mouse at 126 dot com)
+
+ XXX: This file is compiled into libcommon.a that will be self-contained.
+ It looks like that these functions can be put nowhere else. */
+
+#include <io.h>
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+
+/* Write all bytes in [s,s+n) into the specified stream.
+ Errors are ignored. */
+static void
+write_all (HANDLE h, const char *s, size_t n)
+{
+ size_t rem = n;
+ DWORD step;
+
+ while (rem != 0)
+ {
+ if (rem <= UINT_MAX)
+ step = rem;
+ else
+ step = UINT_MAX;
+ if (!WriteFile (h, s + n - rem, step, &step, NULL))
+ break;
+ rem -= step;
+ }
+}
+
+/* Find the beginning of an escape sequence.
+ There are two cases:
+ 1. If the sequence begins with an ESC character (0x1B) and a second
+ character X in [0x40,0x5F], returns X and stores a pointer to
+ the third character into *head.
+ 2. If the sequence begins with a character X in [0x80,0x9F], returns
+ (X-0x40) and stores a pointer to the second character into *head.
+ Stores the number of ESC character(s) in *prefix_len.
+ Returns 0 if no such sequence can be found. */
+static int
+find_esc_head (int *prefix_len, const char **head, const char *str)
+{
+ int c;
+ const char *r = str;
+ int escaped = 0;
+
+ for (;;)
+ {
+ c = (unsigned char) *r;
+ if (c == 0)
+ {
+ /* Not found. */
+ return 0;
+ }
+ if (escaped && 0x40 <= c && c <= 0x5F)
+ {
+ /* Found (case 1). */
+ *prefix_len = 2;
+ *head = r + 1;
+ return c;
+ }
+ if (0x80 <= c && c <= 0x9F)
+ {
+ /* Found (case 2). */
+ *prefix_len = 1;
+ *head = r + 1;
+ return c - 0x40;
+ }
+ ++r;
+ escaped = c == 0x1B;
+ }
+}
+
+/* Find the terminator of an escape sequence.
+ str should be the value stored in *head by a previous successful
+ call to find_esc_head().
+ Returns 0 if no such sequence can be found. */
+static int
+find_esc_terminator (const char **term, const char *str)
+{
+ int c;
+ const char *r = str;
+
+ for (;;)
+ {
+ c = (unsigned char) *r;
+ if (c == 0)
+ {
+ /* Not found. */
+ return 0;
+ }
+ if (0x40 <= c && c <= 0x7E)
+ {
+ /* Found. */
+ *term = r;
+ return c;
+ }
+ ++r;
+ }
+}
+
+/* Handle a sequence of codes. Sequences that are invalid, reserved,
+ unrecognized or unimplemented are ignored silently.
+ There isn't much we can do because of lameness of Windows consoles. */
+static void
+eat_esc_sequence (HANDLE h, int esc_code,
+ const char *esc_head, const char *esc_term)
+{
+ /* Numbers in an escape sequence cannot be negative, because
+ a minus sign in the middle of it would have terminated it. */
+ long n1, n2;
+ char *eptr, *delim;
+ CONSOLE_SCREEN_BUFFER_INFO sb;
+ COORD cr;
+ /* ED and EL parameters. */
+ DWORD cnt, step;
+ long rows;
+ /* SGR parameters. */
+ WORD attrib_add, attrib_rm;
+ const char *param;
+
+ switch (MAKEWORD (esc_code, *esc_term))
+ {
+ /* ESC [ n1 'A'
+ Move the cursor up by n1 characters. */
+ case MAKEWORD ('[', 'A'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ /* Stop at the topmost boundary. */
+ if (cr.Y > n1)
+ cr.Y -= n1;
+ else
+ cr.Y = 0;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'B'
+ Move the cursor down by n1 characters. */
+ case MAKEWORD ('[', 'B'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ /* Stop at the bottommost boundary. */
+ if (sb.dwSize.Y - cr.Y > n1)
+ cr.Y += n1;
+ else
+ cr.Y = sb.dwSize.Y;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'C'
+ Move the cursor right by n1 characters. */
+ case MAKEWORD ('[', 'C'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ /* Stop at the rightmost boundary. */
+ if (sb.dwSize.X - cr.X > n1)
+ cr.X += n1;
+ else
+ cr.X = sb.dwSize.X;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'D'
+ Move the cursor left by n1 characters. */
+ case MAKEWORD ('[', 'D'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ /* Stop at the leftmost boundary. */
+ if (cr.X > n1)
+ cr.X -= n1;
+ else
+ cr.X = 0;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'E'
+ Move the cursor to the beginning of the n1-th line downwards. */
+ case MAKEWORD ('[', 'E'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ cr.X = 0;
+ /* Stop at the bottommost boundary. */
+ if (sb.dwSize.Y - cr.Y > n1)
+ cr.Y += n1;
+ else
+ cr.Y = sb.dwSize.Y;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'F'
+ Move the cursor to the beginning of the n1-th line upwards. */
+ case MAKEWORD ('[', 'F'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ cr.X = 0;
+ /* Stop at the topmost boundary. */
+ if (cr.Y > n1)
+ cr.Y -= n1;
+ else
+ cr.Y = 0;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'G'
+ Move the cursor to the (1-based) n1-th column. */
+ case MAKEWORD ('[', 'G'):
+ if (esc_head == esc_term)
+ n1 = 1;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ n1 -= 1;
+ /* Stop at the leftmost or rightmost boundary. */
+ if (n1 < 0)
+ cr.X = 0;
+ else if (n1 > sb.dwSize.X)
+ cr.X = sb.dwSize.X;
+ else
+ cr.X = n1;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 ';' n2 'H'
+ ESC [ n1 ';' n2 'f'
+ Move the cursor to the (1-based) n1-th row and
+ (also 1-based) n2-th column. */
+ case MAKEWORD ('[', 'H'):
+ case MAKEWORD ('[', 'f'):
+ if (esc_head == esc_term)
+ {
+ /* Both parameters are omitted and set to 1 by default. */
+ n1 = 1;
+ n2 = 1;
+ }
+ else if (!(delim = (char *) memchr (esc_head, ';',
+ esc_term - esc_head)))
+ {
+ /* Only the first parameter is given. The second one is
+ set to 1 by default. */
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ n2 = 1;
+ }
+ else
+ {
+ /* Both parameters are given. The first one shall be
+ terminated by the semicolon. */
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != delim)
+ break;
+ n2 = strtol (delim + 1, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ cr = sb.dwCursorPosition;
+ n1 -= 1;
+ n2 -= 1;
+ /* The cursor position shall be relative to the view coord of
+ the console window, which is usually smaller than the actual
+ buffer. FWIW, the 'appropriate' solution will be shrinking
+ the buffer to match the size of the console window,
+ destroying scrollback in the process. */
+ n1 += sb.srWindow.Top;
+ n2 += sb.srWindow.Left;
+ /* Stop at the topmost or bottommost boundary. */
+ if (n1 < 0)
+ cr.Y = 0;
+ else if (n1 > sb.dwSize.Y)
+ cr.Y = sb.dwSize.Y;
+ else
+ cr.Y = n1;
+ /* Stop at the leftmost or rightmost boundary. */
+ if (n2 < 0)
+ cr.X = 0;
+ else if (n2 > sb.dwSize.X)
+ cr.X = sb.dwSize.X;
+ else
+ cr.X = n2;
+ SetConsoleCursorPosition (h, cr);
+ }
+ break;
+
+ /* ESC [ n1 'J'
+ Erase display. */
+ case MAKEWORD ('[', 'J'):
+ if (esc_head == esc_term)
+ /* This is one of the very few codes whose parameters have
+ a default value of zero. */
+ n1 = 0;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ /* The cursor is not necessarily in the console window, which
+ makes the behavior of this code harder to define. */
+ switch (n1)
+ {
+ case 0:
+ /* If the cursor is in or above the window, erase from
+ it to the bottom of the window; otherwise, do nothing. */
+ cr = sb.dwCursorPosition;
+ cnt = sb.dwSize.X - sb.dwCursorPosition.X;
+ rows = sb.srWindow.Bottom - sb.dwCursorPosition.Y;
+ break;
+ case 1:
+ /* If the cursor is in or under the window, erase from
+ it to the top of the window; otherwise, do nothing. */
+ cr.X = 0;
+ cr.Y = sb.srWindow.Top;
+ cnt = sb.dwCursorPosition.X + 1;
+ rows = sb.dwCursorPosition.Y - sb.srWindow.Top;
+ break;
+ case 2:
+ /* Erase the entire window. */
+ cr.X = sb.srWindow.Left;
+ cr.Y = sb.srWindow.Top;
+ cnt = 0;
+ rows = sb.srWindow.Bottom - sb.srWindow.Top + 1;
+ break;
+ default:
+ /* Erase the entire buffer. */
+ cr.X = 0;
+ cr.Y = 0;
+ cnt = 0;
+ rows = sb.dwSize.Y;
+ break;
+ }
+ if (rows < 0)
+ break;
+ cnt += rows * sb.dwSize.X;
+ FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
+ FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
+ }
+ break;
+
+ /* ESC [ n1 'K'
+ Erase line. */
+ case MAKEWORD ('[', 'K'):
+ if (esc_head == esc_term)
+ /* This is one of the very few codes whose parameters have
+ a default value of zero. */
+ n1 = 0;
+ else
+ {
+ n1 = strtol (esc_head, &eptr, 10);
+ if (eptr != esc_term)
+ break;
+ }
+
+ if (GetConsoleScreenBufferInfo (h, &sb))
+ {
+ switch (n1)
+ {
+ case 0:
+ /* Erase from the cursor to the end. */
+ cr = sb.dwCursorPosition;
+ cnt = sb.dwSize.X - sb.dwCursorPosition.X;
+ break;
+ case 1:
+ /* Erase from the cursor to the beginning. */
+ cr = sb.dwCursorPosition;
+ cr.X = 0;
+ cnt = sb.dwCursorPosition.X + 1;
+ break;
+ default:
+ /* Erase the entire line. */
+ cr = sb.dwCursorPosition;
+ cr.X = 0;
+ cnt = sb.dwSize.X;
+ break;
+ }
+ FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
+ FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
+ }
+ break;
+
+ /* ESC [ n1 ';' n2 'm'
+ Set SGR parameters. Zero or more parameters will follow. */
+ case MAKEWORD ('[', 'm'):
+ attrib_add = 0;
+ attrib_rm = 0;
+ if (esc_head == esc_term)
+ {
+ /* When no parameter is given, reset the console. */
+ attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
+ | FOREGROUND_BLUE);
+ attrib_rm = -1; /* Removes everything. */
+ goto sgr_set_it;
+ }
+ param = esc_head;
+ do
+ {
+ /* Parse a parameter. */
+ n1 = strtol (param, &eptr, 10);
+ if (*eptr != ';' && eptr != esc_term)
+ goto sgr_set_it;
+
+ switch (n1)
+ {
+ case 0:
+ /* Reset. */
+ attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
+ | FOREGROUND_BLUE);
+ attrib_rm = -1; /* Removes everything. */
+ break;
+ case 1:
+ /* Bold. */
+ attrib_add |= FOREGROUND_INTENSITY;
+ break;
+ case 4:
+ /* Underline. */
+ attrib_add |= COMMON_LVB_UNDERSCORE;
+ break;
+ case 5:
+ /* Blink. */
+ /* XXX: It is not BLINKING at all! */
+ attrib_add |= BACKGROUND_INTENSITY;
+ break;
+ case 7:
+ /* Reverse. */
+ attrib_add |= COMMON_LVB_REVERSE_VIDEO;
+ break;
+ case 22:
+ /* No bold. */
+ attrib_add &= ~FOREGROUND_INTENSITY;
+ attrib_rm |= FOREGROUND_INTENSITY;
+ break;
+ case 24:
+ /* No underline. */
+ attrib_add &= ~COMMON_LVB_UNDERSCORE;
+ attrib_rm |= COMMON_LVB_UNDERSCORE;
+ break;
+ case 25:
+ /* No blink. */
+ /* XXX: It is not BLINKING at all! */
+ attrib_add &= ~BACKGROUND_INTENSITY;
+ attrib_rm |= BACKGROUND_INTENSITY;
+ break;
+ case 27:
+ /* No reverse. */
+ attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
+ attrib_rm |= COMMON_LVB_REVERSE_VIDEO;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ /* Foreground color. */
+ attrib_add &= ~(FOREGROUND_RED | FOREGROUND_GREEN
+ | FOREGROUND_BLUE);
+ n1 -= 30;
+ if (n1 & 1)
+ attrib_add |= FOREGROUND_RED;
+ if (n1 & 2)
+ attrib_add |= FOREGROUND_GREEN;
+ if (n1 & 4)
+ attrib_add |= FOREGROUND_BLUE;
+ attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN
+ | FOREGROUND_BLUE);
+ break;
+ case 38:
+ /* Reserved for extended foreground color.
+ Don't know how to handle parameters remaining.
+ Bail out. */
+ goto sgr_set_it;
+ case 39:
+ /* Reset foreground color. */
+ /* Set to grey. */
+ attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
+ | FOREGROUND_BLUE);
+ attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN
+ | FOREGROUND_BLUE);
+ break;
+ case 40:
+ case 41:
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ case 46:
+ case 47:
+ /* Background color. */
+ attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN
+ | BACKGROUND_BLUE);
+ n1 -= 40;
+ if (n1 & 1)
+ attrib_add |= BACKGROUND_RED;
+ if (n1 & 2)
+ attrib_add |= BACKGROUND_GREEN;
+ if (n1 & 4)
+ attrib_add |= BACKGROUND_BLUE;
+ attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN
+ | BACKGROUND_BLUE);
+ break;
+ case 48:
+ /* Reserved for extended background color.
+ Don't know how to handle parameters remaining.
+ Bail out. */
+ goto sgr_set_it;
+ case 49:
+ /* Reset background color. */
+ /* Set to black. */
+ attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN
+ | BACKGROUND_BLUE);
+ attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN
+ | BACKGROUND_BLUE);
+ break;
+ }
+
+ /* Prepare the next parameter. */
+ param = eptr + 1;
+ }
+ while (param != esc_term);
+
+sgr_set_it:
+ /* 0xFFFF removes everything. If it is not the case,
+ care must be taken to preserve old attributes. */
+ if (attrib_rm != 0xFFFF && GetConsoleScreenBufferInfo (h, &sb))
+ {
+ attrib_add |= sb.wAttributes & ~attrib_rm;
+ }
+ if (attrib_add & COMMON_LVB_REVERSE_VIDEO)
+ {
+ /* COMMON_LVB_REVERSE_VIDEO is only effective for DBCS.
+ * Swap foreground and background colors by hand.
+ */
+ attrib_add = (attrib_add & 0xFF00)
+ | ((attrib_add & 0x00F0) >> 4)
+ | ((attrib_add & 0x000F) << 4);
+ attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
+ }
+ SetConsoleTextAttribute (h, attrib_add);
+ break;
+ }
+}
+
+int
+mingw_ansi_fputs (const char *str, FILE *fp)
+{
+ const char *read = str;
+ HANDLE h;
+ DWORD mode;
+ int esc_code, prefix_len;
+ const char *esc_head, *esc_term;
+
+ h = (HANDLE) _get_osfhandle (_fileno (fp));
+ if (h == INVALID_HANDLE_VALUE)
+ return EOF;
+
+ /* Don't mess up stdio functions with Windows APIs. */
+ fflush (fp);
+
+ if (GetConsoleMode (h, &mode))
+ /* If it is a console, translate ANSI escape codes as needed. */
+ for (;;)
+ {
+ if ((esc_code = find_esc_head (&prefix_len, &esc_head, read)) == 0)
+ {
+ /* Write all remaining characters, then exit. */
+ write_all (h, read, strlen (read));
+ break;
+ }
+ if (find_esc_terminator (&esc_term, esc_head) == 0)
+ /* Ignore incomplete escape sequences at the moment.
+ FIXME: The escape state shall be cached for further calls
+ to this function. */
+ break;
+ write_all (h, read, esc_head - prefix_len - read);
+ eat_esc_sequence (h, esc_code, esc_head, esc_term);
+ read = esc_term + 1;
+ }
+ else
+ /* If it is not a console, write everything as-is. */
+ write_all (h, read, strlen (read));
+
+ return 1;
+}
+
+#endif /* __MINGW32__ */
+
+static int
+decode_utf8_char (const unsigned char *, size_t len, unsigned int *);
+static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
+
+/* Overwrite the given location/range within this text_info's rich_location.
+ For use e.g. when implementing "+" in client format decoders. */
+
+void
+text_info::set_location (unsigned int idx, location_t loc,
+ enum range_display_kind range_display_kind)
+{
+ gcc_checking_assert (m_richloc);
+ m_richloc->set_range (idx, loc, range_display_kind);
+}
+
+location_t
+text_info::get_location (unsigned int index_of_location) const
+{
+ gcc_checking_assert (m_richloc);
+
+ if (index_of_location == 0)
+ return m_richloc->get_loc ();
+ else
+ return UNKNOWN_LOCATION;
+}
+
+// Default construct an output buffer.
+
+output_buffer::output_buffer ()
+ : formatted_obstack (),
+ chunk_obstack (),
+ obstack (&formatted_obstack),
+ cur_chunk_array (),
+ stream (stderr),
+ line_length (),
+ digit_buffer (),
+ flush_p (true)
+{
+ obstack_init (&formatted_obstack);
+ obstack_init (&chunk_obstack);
+}
+
+// Release resources owned by an output buffer at the end of lifetime.
+
+output_buffer::~output_buffer ()
+{
+ obstack_free (&chunk_obstack, NULL);
+ obstack_free (&formatted_obstack, NULL);
+}
+
+
+/* Format an integer given by va_arg (ARG, type-specifier T) where
+ type-specifier is a precision modifier as indicated by PREC. F is
+ a string used to construct the appropriate format-specifier. */
+#define pp_integer_with_precision(PP, ARG, PREC, T, F) \
+ do \
+ switch (PREC) \
+ { \
+ case 0: \
+ pp_scalar (PP, "%" F, va_arg (ARG, T)); \
+ break; \
+ \
+ case 1: \
+ pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \
+ break; \
+ \
+ case 2: \
+ pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \
+ break; \
+ \
+ default: \
+ break; \
+ } \
+ while (0)
+
+
+/* Subroutine of pp_set_maximum_length. Set up PRETTY-PRINTER's
+ internal maximum characters per line. */
+static void
+pp_set_real_maximum_length (pretty_printer *pp)
+{
+ /* If we're told not to wrap lines then do the obvious thing. In case
+ we'll emit prefix only once per message, it is appropriate
+ not to increase unnecessarily the line-length cut-off. */
+ if (!pp_is_wrapping_line (pp)
+ || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_ONCE
+ || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
+ pp->maximum_length = pp_line_cutoff (pp);
+ else
+ {
+ int prefix_length = pp->prefix ? strlen (pp->prefix) : 0;
+ /* If the prefix is ridiculously too long, output at least
+ 32 characters. */
+ if (pp_line_cutoff (pp) - prefix_length < 32)
+ pp->maximum_length = pp_line_cutoff (pp) + 32;
+ else
+ pp->maximum_length = pp_line_cutoff (pp);
+ }
+}
+
+/* Clear PRETTY-PRINTER's output state. */
+static inline void
+pp_clear_state (pretty_printer *pp)
+{
+ pp->emitted_prefix = false;
+ pp_indentation (pp) = 0;
+}
+
+/* Print X to PP in decimal. */
+#if 0 // sdcpp
+template<unsigned int N, typename T>
+void
+pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &x)
+{
+ if (x.is_constant ())
+ pp_wide_integer (pp, x.coeffs[0]);
+ else
+ {
+ pp_left_bracket (pp);
+ for (unsigned int i = 0; i < N; ++i)
+ {
+ if (i != 0)
+ pp_comma (pp);
+ pp_wide_integer (pp, x.coeffs[i]);
+ }
+ pp_right_bracket (pp);
+ }
+}
+
+template void pp_wide_integer (pretty_printer *, const poly_uint16_pod &);
+template void pp_wide_integer (pretty_printer *, const poly_int64_pod &);
+template void pp_wide_integer (pretty_printer *, const poly_uint64_pod &);
+#endif // sdcpp
+
+/* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */
+void
+pp_write_text_to_stream (pretty_printer *pp)
+{
+ const char *text = pp_formatted_text (pp);
+#ifdef __MINGW32__
+ mingw_ansi_fputs (text, pp_buffer (pp)->stream);
+#else
+ fputs (text, pp_buffer (pp)->stream);
+#endif
+ pp_clear_output_area (pp);
+}
+
+/* As pp_write_text_to_stream, but for GraphViz label output.
+
+ Flush the formatted text of pretty-printer PP onto the attached stream.
+ Replace characters in PPF that have special meaning in a GraphViz .dot
+ file.
+
+ This routine is not very fast, but it doesn't have to be as this is only
+ be used by routines dumping intermediate representations in graph form. */
+
+void
+pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record)
+{
+ const char *text = pp_formatted_text (pp);
+ const char *p = text;
+ FILE *fp = pp_buffer (pp)->stream;
+
+ for (;*p; p++)
+ {
+ bool escape_char;
+ switch (*p)
+ {
+ /* Print newlines as a left-aligned newline. */
+ case '\n':
+ fputs ("\\l", fp);
+ escape_char = true;
+ break;
+
+ /* The following characters are only special for record-shape nodes. */
+ case '|':
+ case '{':
+ case '}':
+ case '<':
+ case '>':
+ case ' ':
+ escape_char = for_record;
+ break;
+
+ /* The following characters always have to be escaped
+ for use in labels. */
+ case '\\':
+ /* There is a bug in some (f.i. 2.36.0) versions of graphiz
+ ( http://www.graphviz.org/mantisbt/view.php?id=2524 ) related to
+ backslash as last char in label. Let's avoid triggering it. */
+ gcc_assert (*(p + 1) != '\0');
+ /* Fall through. */
+ case '"':
+ escape_char = true;
+ break;
+
+ default:
+ escape_char = false;
+ break;
+ }
+
+ if (escape_char)
+ fputc ('\\', fp);
+
+ fputc (*p, fp);
+ }
+
+ pp_clear_output_area (pp);
+}
+
+/* As pp_write_text_to_stream, but for GraphViz HTML-like strings.
+
+ Flush the formatted text of pretty-printer PP onto the attached stream,
+ escaping these characters
+ " & < >
+ using XML escape sequences.
+
+ http://www.graphviz.org/doc/info/lang.html#html states:
+ special XML escape sequences for ", &, <, and > may be necessary in
+ order to embed these characters in attribute values or raw text
+ This doesn't list "'" (which would normally be escaped in XML
+ as "&apos;" or in HTML as "&#39;");.
+
+ Experiments show that escaping "'" doesn't seem to be necessary. */
+
+void
+pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp)
+{
+ const char *text = pp_formatted_text (pp);
+ const char *p = text;
+ FILE *fp = pp_buffer (pp)->stream;
+
+ for (;*p; p++)
+ {
+ switch (*p)
+ {
+ case '"':
+ fputs ("&quot;", fp);
+ break;
+ case '&':
+ fputs ("&amp;", fp);
+ break;
+ case '<':
+ fputs ("&lt;", fp);
+ break;
+ case '>':
+ fputs ("&gt;",fp);
+ break;
+
+ default:
+ fputc (*p, fp);
+ break;
+ }
+ }
+
+ pp_clear_output_area (pp);
+}
+
+/* Wrap a text delimited by START and END into PRETTY-PRINTER. */
+static void
+pp_wrap_text (pretty_printer *pp, const char *start, const char *end)
+{
+ bool wrapping_line = pp_is_wrapping_line (pp);
+
+ while (start != end)
+ {
+ /* Dump anything bordered by whitespaces. */
+ {
+ const char *p = start;
+ while (p != end && !ISBLANK (*p) && *p != '\n')
+ ++p;
+ if (wrapping_line
+ && p - start >= pp_remaining_character_count_for_line (pp))
+ pp_newline (pp);
+ pp_append_text (pp, start, p);
+ start = p;
+ }
+
+ if (start != end && ISBLANK (*start))
+ {
+ pp_space (pp);
+ ++start;
+ }
+ if (start != end && *start == '\n')
+ {
+ pp_newline (pp);
+ ++start;
+ }
+ }
+}
+
+/* Same as pp_wrap_text but wrap text only when in line-wrapping mode. */
+static inline void
+pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end)
+{
+ if (pp_is_wrapping_line (pp))
+ pp_wrap_text (pp, start, end);
+ else
+ pp_append_text (pp, start, end);
+}
+
+/* Append to the output area of PRETTY-PRINTER a string specified by its
+ STARTing character and LENGTH. */
+static inline void
+pp_append_r (pretty_printer *pp, const char *start, int length)
+{
+ output_buffer_append_r (pp_buffer (pp), start, length);
+}
+
+/* Insert enough spaces into the output area of PRETTY-PRINTER to bring
+ the column position to the current indentation level, assuming that a
+ newline has just been written to the buffer. */
+void
+pp_indent (pretty_printer *pp)
+{
+ int n = pp_indentation (pp);
+ int i;
+
+ for (i = 0; i < n; ++i)
+ pp_space (pp);
+}
+
+static const char *get_end_url_string (pretty_printer *);
+
+/* The following format specifiers are recognized as being client independent:
+ %d, %i: (signed) integer in base ten.
+ %u: unsigned integer in base ten.
+ %o: unsigned integer in base eight.
+ %x: unsigned integer in base sixteen.
+ %ld, %li, %lo, %lu, %lx: long versions of the above.
+ %lld, %lli, %llo, %llu, %llx: long long versions.
+ %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
+ %f: double
+ %c: character.
+ %s: string.
+ %p: pointer (printed in a host-dependent manner).
+ %r: if pp_show_color(pp), switch to color identified by const char *.
+ %R: if pp_show_color(pp), reset color.
+ %m: strerror(text->err_no) - does not consume a value from args_ptr.
+ %%: '%'.
+ %<: opening quote.
+ %>: closing quote.
+ %{: URL start. Consumes a const char * argument for the URL.
+ %}: URL end. Does not consume any arguments.
+ %': apostrophe (should only be used in untranslated messages;
+ translations should use appropriate punctuation directly).
+ %@: diagnostic_event_id_ptr, for which event_id->known_p () must be true.
+ %.*s: a substring the length of which is specified by an argument
+ integer.
+ %Ns: likewise, but length specified as constant in the format string.
+ Flag 'q': quote formatted text (must come immediately after '%').
+ %Z: Requires two arguments - array of int, and len. Prints elements
+ of the array.
+
+ Arguments can be used sequentially, or through %N$ resp. *N$
+ notation Nth argument after the format string. If %N$ / *N$
+ notation is used, it must be used for all arguments, except %m, %%,
+ %<, %>, %} and %', which may not have a number, as they do not consume
+ an argument. When %M$.*N$s is used, M must be N + 1. (This may
+ also be written %M$.*s, provided N is not otherwise used.) The
+ format string must have conversion specifiers with argument numbers
+ 1 up to highest argument; each argument may only be used once.
+ A format string can have at most 30 arguments. */
+
+/* Formatting phases 1 and 2: render TEXT->format_spec plus
+ TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[].
+ Phase 3 is in pp_output_formatted_text. */
+
+void
+pp_format (pretty_printer *pp, text_info *text)
+{
+ output_buffer *buffer = pp_buffer (pp);
+ const char *p;
+ const char **args;
+ struct chunk_info *new_chunk_array;
+
+ unsigned int curarg = 0, chunk = 0, argno;
+ pp_wrapping_mode_t old_wrapping_mode;
+ bool any_unnumbered = false, any_numbered = false;
+ const char **formatters[PP_NL_ARGMAX];
+
+ /* Allocate a new chunk structure. */
+ new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
+ new_chunk_array->prev = buffer->cur_chunk_array;
+ buffer->cur_chunk_array = new_chunk_array;
+ args = new_chunk_array->args;
+
+ /* Formatting phase 1: split up TEXT->format_spec into chunks in
+ pp_buffer (PP)->args[]. Even-numbered chunks are to be output
+ verbatim, odd-numbered chunks are format specifiers.
+ %m, %%, %<, %>, %} and %' are replaced with the appropriate text at
+ this point. */
+
+ memset (formatters, 0, sizeof formatters);
+
+ for (p = text->format_spec; *p; )
+ {
+ while (*p != '\0' && *p != '%')
+ {
+ obstack_1grow (&buffer->chunk_obstack, *p);
+ p++;
+ }
+
+ if (*p == '\0')
+ break;
+
+ switch (*++p)
+ {
+ case '\0':
+ gcc_unreachable ();
+
+ case '%':
+ obstack_1grow (&buffer->chunk_obstack, '%');
+ p++;
+ continue;
+
+ case '<':
+ {
+ obstack_grow (&buffer->chunk_obstack,
+ open_quote, strlen (open_quote));
+ const char *colorstr
+ = colorize_start (pp_show_color (pp), "quote");
+ obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
+ p++;
+ continue;
+ }
+
+ case '>':
+ {
+ const char *colorstr = colorize_stop (pp_show_color (pp));
+ obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
+ }
+ /* FALLTHRU */
+ case '\'':
+ obstack_grow (&buffer->chunk_obstack,
+ close_quote, strlen (close_quote));
+ p++;
+ continue;
+
+ case '}':
+ {
+ const char *endurlstr = get_end_url_string (pp);
+ obstack_grow (&buffer->chunk_obstack, endurlstr,
+ strlen (endurlstr));
+ }
+ p++;
+ continue;
+
+ case 'R':
+ {
+ const char *colorstr = colorize_stop (pp_show_color (pp));
+ obstack_grow (&buffer->chunk_obstack, colorstr,
+ strlen (colorstr));
+ p++;
+ continue;
+ }
+
+ case 'm':
+ {
+ const char *errstr = xstrerror (text->err_no);
+ obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
+ }
+ p++;
+ continue;
+
+ default:
+ /* Handled in phase 2. Terminate the plain chunk here. */
+ obstack_1grow (&buffer->chunk_obstack, '\0');
+ gcc_assert (chunk < PP_NL_ARGMAX * 2);
+ args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ break;
+ }
+
+ if (ISDIGIT (*p))
+ {
+ char *end;
+ argno = strtoul (p, &end, 10) - 1;
+ p = end;
+ gcc_assert (*p == '$');
+ p++;
+
+ any_numbered = true;
+ gcc_assert (!any_unnumbered);
+ }
+ else
+ {
+ argno = curarg++;
+ any_unnumbered = true;
+ gcc_assert (!any_numbered);
+ }
+ gcc_assert (argno < PP_NL_ARGMAX);
+ gcc_assert (!formatters[argno]);
+ formatters[argno] = &args[chunk];
+ do
+ {
+ obstack_1grow (&buffer->chunk_obstack, *p);
+ p++;
+ }
+ while (strchr ("qwl+#", p[-1]));
+
+ if (p[-1] == '.')
+ {
+ /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
+ (where M == N + 1). */
+ if (ISDIGIT (*p))
+ {
+ do
+ {
+ obstack_1grow (&buffer->chunk_obstack, *p);
+ p++;
+ }
+ while (ISDIGIT (p[-1]));
+ gcc_assert (p[-1] == 's');
+ }
+ else
+ {
+ gcc_assert (*p == '*');
+ obstack_1grow (&buffer->chunk_obstack, '*');
+ p++;
+
+ if (ISDIGIT (*p))
+ {
+ char *end;
+ unsigned int argno2 = strtoul (p, &end, 10) - 1;
+ p = end;
+ gcc_assert (argno2 == argno - 1);
+ gcc_assert (!any_unnumbered);
+ gcc_assert (*p == '$');
+
+ p++;
+ formatters[argno2] = formatters[argno];
+ }
+ else
+ {
+ gcc_assert (!any_numbered);
+ formatters[argno+1] = formatters[argno];
+ curarg++;
+ }
+ gcc_assert (*p == 's');
+ obstack_1grow (&buffer->chunk_obstack, 's');
+ p++;
+ }
+ }
+ if (*p == '\0')
+ break;
+
+ obstack_1grow (&buffer->chunk_obstack, '\0');
+ gcc_assert (chunk < PP_NL_ARGMAX * 2);
+ args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ }
+
+ obstack_1grow (&buffer->chunk_obstack, '\0');
+ gcc_assert (chunk < PP_NL_ARGMAX * 2);
+ args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ args[chunk] = 0;
+
+ /* Set output to the argument obstack, and switch line-wrapping and
+ prefixing off. */
+ buffer->obstack = &buffer->chunk_obstack;
+ const int old_line_length = buffer->line_length;
+ old_wrapping_mode = pp_set_verbatim_wrapping (pp);
+
+ /* Second phase. Replace each formatter with the formatted text it
+ corresponds to. */
+
+ for (argno = 0; formatters[argno]; argno++)
+ {
+ int precision = 0;
+ bool wide = false;
+ bool plus = false;
+ bool hash = false;
+ bool quote = false;
+
+ /* We do not attempt to enforce any ordering on the modifier
+ characters. */
+
+ for (p = *formatters[argno];; p++)
+ {
+ switch (*p)
+ {
+ case 'q':
+ gcc_assert (!quote);
+ quote = true;
+ continue;
+
+ case '+':
+ gcc_assert (!plus);
+ plus = true;
+ continue;
+
+ case '#':
+ gcc_assert (!hash);
+ hash = true;
+ continue;
+
+ case 'w':
+ gcc_assert (!wide);
+ wide = true;
+ continue;
+
+ case 'l':
+ /* We don't support precision beyond that of "long long". */
+ gcc_assert (precision < 2);
+ precision++;
+ continue;
+ }
+ break;
+ }
+
+ gcc_assert (!wide || precision == 0);
+
+ if (quote)
+ pp_begin_quote (pp, pp_show_color (pp));
+
+ switch (*p)
+ {
+ case 'r':
+ pp_string (pp, colorize_start (pp_show_color (pp),
+ va_arg (*text->args_ptr,
+ const char *)));
+ break;
+
+ case 'c':
+ {
+ /* When quoting, print alphanumeric, punctuation, and the space
+ character unchanged, and all others in hexadecimal with the
+ "\x" prefix. Otherwise print them all unchanged. */
+ int chr = va_arg (*text->args_ptr, int);
+ if (ISPRINT (chr) || !quote)
+ pp_character (pp, chr);
+ else
+ {
+ const char str [2] = { chr, '\0' };
+ pp_quoted_string (pp, str, 1);
+ }
+ break;
+ }
+
+ case 'd':
+ case 'i':
+ if (wide)
+ pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
+ else
+ pp_integer_with_precision
+ (pp, *text->args_ptr, precision, int, "d");
+ break;
+
+ case 'o':
+ if (wide)
+ pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
+ va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
+ else
+ pp_integer_with_precision
+ (pp, *text->args_ptr, precision, unsigned, "o");
+ break;
+
+ case 's':
+ if (quote)
+ pp_quoted_string (pp, va_arg (*text->args_ptr, const char *));
+ else
+ pp_string (pp, va_arg (*text->args_ptr, const char *));
+ break;
+
+ case 'p':
+ pp_pointer (pp, va_arg (*text->args_ptr, void *));
+ break;
+
+ case 'u':
+ if (wide)
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
+ va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
+ else
+ pp_integer_with_precision
+ (pp, *text->args_ptr, precision, unsigned, "u");
+ break;
+
+ case 'f':
+ pp_double (pp, va_arg (*text->args_ptr, double));
+ break;
+
+ case 'Z':
+ {
+ int *v = va_arg (*text->args_ptr, int *);
+ unsigned len = va_arg (*text->args_ptr, unsigned);
+
+ for (unsigned i = 0; i < len; ++i)
+ {
+ pp_scalar (pp, "%i", v[i]);
+ if (i < len - 1)
+ {
+ pp_comma (pp);
+ pp_space (pp);
+ }
+ }
+ break;
+ }
+
+ case 'x':
+ if (wide)
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
+ va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
+ else
+ pp_integer_with_precision
+ (pp, *text->args_ptr, precision, unsigned, "x");
+ break;
+
+ case '.':
+ {
+ int n;
+ const char *s;
+
+ /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
+ (where M == N + 1). The format string should be verified
+ already from the first phase. */
+ p++;
+ if (ISDIGIT (*p))
+ {
+ char *end;
+ n = strtoul (p, &end, 10);
+ p = end;
+ gcc_assert (*p == 's');
+ }
+ else
+ {
+ gcc_assert (*p == '*');
+ p++;
+ gcc_assert (*p == 's');
+ n = va_arg (*text->args_ptr, int);
+
+ /* This consumes a second entry in the formatters array. */
+ gcc_assert (formatters[argno] == formatters[argno+1]);
+ argno++;
+ }
+
+ s = va_arg (*text->args_ptr, const char *);
+
+ /* Append the lesser of precision and strlen (s) characters
+ from the array (which need not be a nul-terminated string).
+ Negative precision is treated as if it were omitted. */
+ size_t len = n < 0 ? strlen (s) : strnlen (s, n);
+
+ pp_append_text (pp, s, s + len);
+ }
+ break;
+
+ case '@':
+ {
+ /* diagnostic_event_id_t *. */
+ diagnostic_event_id_ptr event_id
+ = va_arg (*text->args_ptr, diagnostic_event_id_ptr);
+ gcc_assert (event_id->known_p ());
+
+ pp_string (pp, colorize_start (pp_show_color (pp), "path"));
+ pp_character (pp, '(');
+ pp_decimal_int (pp, event_id->one_based ());
+ pp_character (pp, ')');
+ pp_string (pp, colorize_stop (pp_show_color (pp)));
+ }
+ break;
+
+ case '{':
+ pp_begin_url (pp, va_arg (*text->args_ptr, const char *));
+ break;
+
+ default:
+ {
+ bool ok;
+
+ /* Call the format decoder.
+ Pass the address of "quote" so that format decoders can
+ potentially disable printing of the closing quote
+ (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
+ of frontends). */
+ gcc_assert (pp_format_decoder (pp));
+ ok = pp_format_decoder (pp) (pp, text, p,
+ precision, wide, plus, hash, &quote,
+ formatters[argno]);
+ gcc_assert (ok);
+ }
+ }
+
+ if (quote)
+ pp_end_quote (pp, pp_show_color (pp));
+
+ obstack_1grow (&buffer->chunk_obstack, '\0');
+ *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
+ }
+
+ if (CHECKING_P)
+ for (; argno < PP_NL_ARGMAX; argno++)
+ gcc_assert (!formatters[argno]);
+
+ /* If the client supplied a postprocessing object, call its "handle"
+ hook here. */
+ if (pp->m_format_postprocessor)
+ pp->m_format_postprocessor->handle (pp);
+
+ /* Revert to normal obstack and wrapping mode. */
+ buffer->obstack = &buffer->formatted_obstack;
+ buffer->line_length = old_line_length;
+ pp_wrapping_mode (pp) = old_wrapping_mode;
+ pp_clear_state (pp);
+}
+
+/* Format of a message pointed to by TEXT. */
+void
+pp_output_formatted_text (pretty_printer *pp)
+{
+ unsigned int chunk;
+ output_buffer *buffer = pp_buffer (pp);
+ struct chunk_info *chunk_array = buffer->cur_chunk_array;
+ const char **args = chunk_array->args;
+
+ gcc_assert (buffer->obstack == &buffer->formatted_obstack);
+
+ /* This is a third phase, first 2 phases done in pp_format_args.
+ Now we actually print it. */
+ for (chunk = 0; args[chunk]; chunk++)
+ pp_string (pp, args[chunk]);
+
+ /* Deallocate the chunk structure and everything after it (i.e. the
+ associated series of formatted strings). */
+ buffer->cur_chunk_array = chunk_array->prev;
+ obstack_free (&buffer->chunk_obstack, chunk_array);
+}
+
+/* Helper subroutine of output_verbatim and verbatim. Do the appropriate
+ settings needed by BUFFER for a verbatim formatting. */
+void
+pp_format_verbatim (pretty_printer *pp, text_info *text)
+{
+ /* Set verbatim mode. */
+ pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
+
+ /* Do the actual formatting. */
+ pp_format (pp, text);
+ pp_output_formatted_text (pp);
+
+ /* Restore previous settings. */
+ pp_wrapping_mode (pp) = oldmode;
+}
+
+/* Flush the content of BUFFER onto the attached stream. This
+ function does nothing unless pp->output_buffer->flush_p. */
+void
+pp_flush (pretty_printer *pp)
+{
+ pp_clear_state (pp);
+ if (!pp->buffer->flush_p)
+ return;
+ pp_write_text_to_stream (pp);
+ fflush (pp_buffer (pp)->stream);
+}
+
+/* Flush the content of BUFFER onto the attached stream independently
+ of the value of pp->output_buffer->flush_p. */
+void
+pp_really_flush (pretty_printer *pp)
+{
+ pp_clear_state (pp);
+ pp_write_text_to_stream (pp);
+ fflush (pp_buffer (pp)->stream);
+}
+
+/* Sets the number of maximum characters per line PRETTY-PRINTER can
+ output in line-wrapping mode. A LENGTH value 0 suppresses
+ line-wrapping. */
+void
+pp_set_line_maximum_length (pretty_printer *pp, int length)
+{
+ pp_line_cutoff (pp) = length;
+ pp_set_real_maximum_length (pp);
+}
+
+/* Clear PRETTY-PRINTER output area text info. */
+void
+pp_clear_output_area (pretty_printer *pp)
+{
+ obstack_free (pp_buffer (pp)->obstack,
+ obstack_base (pp_buffer (pp)->obstack));
+ pp_buffer (pp)->line_length = 0;
+}
+
+/* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
+ will eventually be free-ed. */
+
+void
+pp_set_prefix (pretty_printer *pp, char *prefix)
+{
+ free (pp->prefix);
+ pp->prefix = prefix;
+ pp_set_real_maximum_length (pp);
+ pp->emitted_prefix = false;
+ pp_indentation (pp) = 0;
+}
+
+/* Take ownership of PP's prefix, setting it to NULL.
+ This allows clients to save, override, and then restore an existing
+ prefix, without it being free-ed. */
+
+char *
+pp_take_prefix (pretty_printer *pp)
+{
+ char *result = pp->prefix;
+ pp->prefix = NULL;
+ return result;
+}
+
+/* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
+void
+pp_destroy_prefix (pretty_printer *pp)
+{
+ if (pp->prefix != NULL)
+ {
+ free (pp->prefix);
+ pp->prefix = NULL;
+ }
+}
+
+/* Write out PRETTY-PRINTER's prefix. */
+void
+pp_emit_prefix (pretty_printer *pp)
+{
+ if (pp->prefix != NULL)
+ {
+ switch (pp_prefixing_rule (pp))
+ {
+ default:
+ case DIAGNOSTICS_SHOW_PREFIX_NEVER:
+ break;
+
+ case DIAGNOSTICS_SHOW_PREFIX_ONCE:
+ if (pp->emitted_prefix)
+ {
+ pp_indent (pp);
+ break;
+ }
+ pp_indentation (pp) += 3;
+ /* Fall through. */
+
+ case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
+ {
+ int prefix_length = strlen (pp->prefix);
+ pp_append_r (pp, pp->prefix, prefix_length);
+ pp->emitted_prefix = true;
+ }
+ break;
+ }
+ }
+}
+
+/* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */
+
+pretty_printer::pretty_printer (int maximum_length)
+ : buffer (new (XCNEW (output_buffer)) output_buffer ()),
+ prefix (),
+ padding (pp_none),
+ maximum_length (),
+ indent_skip (),
+ wrapping (),
+ format_decoder (),
+ m_format_postprocessor (NULL),
+ emitted_prefix (),
+ need_newline (),
+ translate_identifiers (true),
+ show_color (),
+ url_format (URL_FORMAT_NONE)
+{
+ pp_line_cutoff (this) = maximum_length;
+ /* By default, we emit prefixes once per message. */
+ pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
+ pp_set_prefix (this, NULL);
+}
+
+/* Copy constructor for pretty_printer. */
+
+pretty_printer::pretty_printer (const pretty_printer &other)
+: buffer (new (XCNEW (output_buffer)) output_buffer ()),
+ prefix (),
+ padding (other.padding),
+ maximum_length (other.maximum_length),
+ indent_skip (other.indent_skip),
+ wrapping (other.wrapping),
+ format_decoder (other.format_decoder),
+ m_format_postprocessor (NULL),
+ emitted_prefix (other.emitted_prefix),
+ need_newline (other.need_newline),
+ translate_identifiers (other.translate_identifiers),
+ show_color (other.show_color),
+ url_format (other.url_format)
+{
+ pp_line_cutoff (this) = maximum_length;
+ /* By default, we emit prefixes once per message. */
+ pp_prefixing_rule (this) = pp_prefixing_rule (&other);
+ pp_set_prefix (this, NULL);
+
+ if (other.m_format_postprocessor)
+ m_format_postprocessor = other.m_format_postprocessor->clone ();
+}
+
+pretty_printer::~pretty_printer ()
+{
+ if (m_format_postprocessor)
+ delete m_format_postprocessor;
+ buffer->~output_buffer ();
+ XDELETE (buffer);
+ free (prefix);
+}
+
+/* Base class implementation of pretty_printer::clone vfunc. */
+
+pretty_printer *
+pretty_printer::clone () const
+{
+ return new pretty_printer (*this);
+}
+
+/* Append a string delimited by START and END to the output area of
+ PRETTY-PRINTER. No line wrapping is done. However, if beginning a
+ new line then emit PRETTY-PRINTER's prefix and skip any leading
+ whitespace if appropriate. The caller must ensure that it is
+ safe to do so. */
+void
+pp_append_text (pretty_printer *pp, const char *start, const char *end)
+{
+ /* Emit prefix and skip whitespace if we're starting a new line. */
+ if (pp_buffer (pp)->line_length == 0)
+ {
+ pp_emit_prefix (pp);
+ if (pp_is_wrapping_line (pp))
+ while (start != end && *start == ' ')
+ ++start;
+ }
+ pp_append_r (pp, start, end - start);
+}
+
+/* Finishes constructing a NULL-terminated character string representing
+ the PRETTY-PRINTED text. */
+const char *
+pp_formatted_text (pretty_printer *pp)
+{
+ return output_buffer_formatted_text (pp_buffer (pp));
+}
+
+/* Return a pointer to the last character emitted in PRETTY-PRINTER's
+ output area. A NULL pointer means no character available. */
+const char *
+pp_last_position_in_text (const pretty_printer *pp)
+{
+ return output_buffer_last_position_in_text (pp_buffer (pp));
+}
+
+/* Return the amount of characters PRETTY-PRINTER can accept to
+ make a full line. Meaningful only in line-wrapping mode. */
+int
+pp_remaining_character_count_for_line (pretty_printer *pp)
+{
+ return pp->maximum_length - pp_buffer (pp)->line_length;
+}
+
+
+/* Format a message into BUFFER a la printf. */
+void
+pp_printf (pretty_printer *pp, const char *msg, ...)
+{
+ text_info text;
+ va_list ap;
+
+ va_start (ap, msg);
+ text.err_no = errno;
+ text.args_ptr = &ap;
+ text.format_spec = msg;
+ pp_format (pp, &text);
+ pp_output_formatted_text (pp);
+ va_end (ap);
+}
+
+
+/* Output MESSAGE verbatim into BUFFER. */
+void
+pp_verbatim (pretty_printer *pp, const char *msg, ...)
+{
+ text_info text;
+ va_list ap;
+
+ va_start (ap, msg);
+ text.err_no = errno;
+ text.args_ptr = &ap;
+ text.format_spec = msg;
+ pp_format_verbatim (pp, &text);
+ va_end (ap);
+}
+
+
+
+/* Have PRETTY-PRINTER start a new line. */
+void
+pp_newline (pretty_printer *pp)
+{
+ obstack_1grow (pp_buffer (pp)->obstack, '\n');
+ pp_needs_newline (pp) = false;
+ pp_buffer (pp)->line_length = 0;
+}
+
+/* Have PRETTY-PRINTER add a CHARACTER. */
+void
+pp_character (pretty_printer *pp, int c)
+{
+ if (pp_is_wrapping_line (pp)
+ /* If printing UTF-8, don't wrap in the middle of a sequence. */
+ && (((unsigned int) c) & 0xC0) != 0x80
+ && pp_remaining_character_count_for_line (pp) <= 0)
+ {
+ pp_newline (pp);
+ if (ISSPACE (c))
+ return;
+ }
+ obstack_1grow (pp_buffer (pp)->obstack, c);
+ ++pp_buffer (pp)->line_length;
+}
+
+/* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
+ be line-wrapped if in appropriate mode. */
+void
+pp_string (pretty_printer *pp, const char *str)
+{
+ gcc_checking_assert (str);
+ pp_maybe_wrap_text (pp, str, str + strlen (str));
+}
+
+/* Append the leading N characters of STRING to the output area of
+ PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
+ Setting N = -1 is as if N were set to strlen (STRING). The STRING
+ may be line-wrapped if in appropriate mode. */
+static void
+pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
+{
+ gcc_checking_assert (str);
+
+ const char *last = str;
+ const char *ps;
+
+ /* Compute the length if not specified. */
+ if (n == (size_t) -1)
+ n = strlen (str);
+
+ for (ps = str; n; ++ps, --n)
+ {
+ if (ISPRINT (*ps))
+ continue;
+
+ /* Don't escape a valid UTF-8 extended char. */
+ const unsigned char *ups = (const unsigned char *) ps;
+ if (*ups & 0x80)
+ {
+ unsigned int extended_char;
+ const int valid_utf8_len = decode_utf8_char (ups, n, &extended_char);
+ if (valid_utf8_len > 0)
+ {
+ ps += valid_utf8_len - 1;
+ n -= valid_utf8_len - 1;
+ continue;
+ }
+ }
+
+ if (last < ps)
+ pp_maybe_wrap_text (pp, last, ps);
+
+ /* Append the hexadecimal value of the character. Allocate a buffer
+ that's large enough for a 32-bit char plus the hex prefix. */
+ char buf [11];
+ int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
+ pp_maybe_wrap_text (pp, buf, buf + n);
+ last = ps + 1;
+ }
+
+ pp_maybe_wrap_text (pp, last, ps);
+}
+
+/* Maybe print out a whitespace if needed. */
+
+void
+pp_maybe_space (pretty_printer *pp)
+{
+ if (pp->padding != pp_none)
+ {
+ pp_space (pp);
+ pp->padding = pp_none;
+ }
+}
+
+// Add a newline to the pretty printer PP and flush formatted text.
+
+void
+pp_newline_and_flush (pretty_printer *pp)
+{
+ pp_newline (pp);
+ pp_flush (pp);
+ pp_needs_newline (pp) = false;
+}
+
+// Add a newline to the pretty printer PP, followed by indentation.
+
+void
+pp_newline_and_indent (pretty_printer *pp, int n)
+{
+ pp_indentation (pp) += n;
+ pp_newline (pp);
+ pp_indent (pp);
+ pp_needs_newline (pp) = false;
+}
+
+// Add separator C, followed by a single whitespace.
+
+void
+pp_separate_with (pretty_printer *pp, char c)
+{
+ pp_character (pp, c);
+ pp_space (pp);
+}
+
+/* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
+ using the "quote" color. */
+
+void
+pp_begin_quote (pretty_printer *pp, bool show_color)
+{
+ pp_string (pp, open_quote);
+ pp_string (pp, colorize_start (show_color, "quote"));
+}
+
+/* If SHOW_COLOR is true, stop colorizing.
+ Add a localized close quote. */
+
+void
+pp_end_quote (pretty_printer *pp, bool show_color)
+{
+ pp_string (pp, colorize_stop (show_color));
+ pp_string (pp, close_quote);
+}
+
+
+/* The string starting at P has LEN (at least 1) bytes left; if they
+ start with a valid UTF-8 sequence, return the length of that
+ sequence and set *VALUE to the value of that sequence, and
+ otherwise return 0 and set *VALUE to (unsigned int) -1. */
+
+static int
+decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
+{
+ unsigned int t = *p;
+
+ if (len == 0)
+ abort ();
+ if (t & 0x80)
+ {
+ size_t utf8_len = 0;
+ unsigned int ch;
+ size_t i;
+ for (t = *p; t & 0x80; t <<= 1)
+ utf8_len++;
+
+ if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
+ {
+ *value = (unsigned int) -1;
+ return 0;
+ }
+ ch = *p & ((1 << (7 - utf8_len)) - 1);
+ for (i = 1; i < utf8_len; i++)
+ {
+ unsigned int u = p[i];
+ if ((u & 0xC0) != 0x80)
+ {
+ *value = (unsigned int) -1;
+ return 0;
+ }
+ ch = (ch << 6) | (u & 0x3F);
+ }
+ if ( (ch <= 0x7F && utf8_len > 1)
+ || (ch <= 0x7FF && utf8_len > 2)
+ || (ch <= 0xFFFF && utf8_len > 3)
+ || (ch <= 0x1FFFFF && utf8_len > 4)
+ || (ch <= 0x3FFFFFF && utf8_len > 5)
+ || (ch >= 0xD800 && ch <= 0xDFFF))
+ {
+ *value = (unsigned int) -1;
+ return 0;
+ }
+ *value = ch;
+ return utf8_len;
+ }
+ else
+ {
+ *value = t;
+ return 1;
+ }
+}
+
+/* Allocator for identifier_to_locale and corresponding function to
+ free memory. */
+
+void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
+void (*identifier_to_locale_free) (void *) = free;
+
+/* Given IDENT, an identifier in the internal encoding, return a
+ version of IDENT suitable for diagnostics in the locale character
+ set: either IDENT itself, or a string, allocated using
+ identifier_to_locale_alloc, converted to the locale character set
+ and using escape sequences if not representable in the locale
+ character set or containing control characters or invalid byte
+ sequences. Existing backslashes in IDENT are not doubled, so the
+ result may not uniquely specify the contents of an arbitrary byte
+ sequence identifier. */
+
+const char *
+identifier_to_locale (const char *ident)
+{
+ const unsigned char *uid = (const unsigned char *) ident;
+ size_t idlen = strlen (ident);
+ bool valid_printable_utf8 = true;
+ bool all_ascii = true;
+ size_t i;
+
+ for (i = 0; i < idlen;)
+ {
+ unsigned int c;
+ size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
+ if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
+ {
+ valid_printable_utf8 = false;
+ break;
+ }
+ if (utf8_len > 1)
+ all_ascii = false;
+ i += utf8_len;
+ }
+
+ /* If IDENT contains invalid UTF-8 sequences (which may occur with
+ attributes putting arbitrary byte sequences in identifiers), or
+ control characters, we use octal escape sequences for all bytes
+ outside printable ASCII. */
+ if (!valid_printable_utf8)
+ {
+ char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
+ char *p = ret;
+ for (i = 0; i < idlen; i++)
+ {
+ if (uid[i] > 0x1F && uid[i] < 0x7F)
+ *p++ = uid[i];
+ else
+ {
+ sprintf (p, "\\%03o", uid[i]);
+ p += 4;
+ }
+ }
+ *p = 0;
+ return ret;
+ }
+
+ /* Otherwise, if it is valid printable ASCII, or printable UTF-8
+ with the locale character set being UTF-8, IDENT is used. */
+ if (all_ascii || locale_utf8)
+ return ident;
+
+ /* Otherwise IDENT is converted to the locale character set if
+ possible. */
+#if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
+ if (locale_encoding != NULL)
+ {
+ iconv_t cd = iconv_open (locale_encoding, "UTF-8");
+ bool conversion_ok = true;
+ char *ret = NULL;
+ if (cd != (iconv_t) -1)
+ {
+ size_t ret_alloc = 4 * idlen + 1;
+ for (;;)
+ {
+ /* Repeat the whole conversion process as needed with
+ larger buffers so non-reversible transformations can
+ always be detected. */
+ ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
+ char *outbuf;
+ size_t inbytesleft = idlen;
+ size_t outbytesleft = ret_alloc - 1;
+ size_t iconv_ret;
+
+ ret = (char *) identifier_to_locale_alloc (ret_alloc);
+ outbuf = ret;
+
+ if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
+ {
+ conversion_ok = false;
+ break;
+ }
+
+ iconv_ret = iconv (cd, &inbuf, &inbytesleft,
+ &outbuf, &outbytesleft);
+ if (iconv_ret == (size_t) -1 || inbytesleft != 0)
+ {
+ if (errno == E2BIG)
+ {
+ ret_alloc *= 2;
+ identifier_to_locale_free (ret);
+ ret = NULL;
+ continue;
+ }
+ else
+ {
+ conversion_ok = false;
+ break;
+ }
+ }
+ else if (iconv_ret != 0)
+ {
+ conversion_ok = false;
+ break;
+ }
+ /* Return to initial shift state. */
+ if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
+ {
+ if (errno == E2BIG)
+ {
+ ret_alloc *= 2;
+ identifier_to_locale_free (ret);
+ ret = NULL;
+ continue;
+ }
+ else
+ {
+ conversion_ok = false;
+ break;
+ }
+ }
+ *outbuf = 0;
+ break;
+ }
+ iconv_close (cd);
+ if (conversion_ok)
+ return ret;
+ }
+ }
+#endif
+
+ /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
+ {
+ char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
+ char *p = ret;
+ for (i = 0; i < idlen;)
+ {
+ unsigned int c;
+ size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
+ if (utf8_len == 1)
+ *p++ = uid[i];
+ else
+ {
+ sprintf (p, "\\U%08x", c);
+ p += 10;
+ }
+ i += utf8_len;
+ }
+ *p = 0;
+ return ret;
+ }
+}
+
+/* Support for encoding URLs.
+ See egmontkob/Hyperlinks_in_Terminal_Emulators.md
+ ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
+
+ > A hyperlink is opened upon encountering an OSC 8 escape sequence with
+ > the target URI. The syntax is
+ >
+ > OSC 8 ; params ; URI ST
+ >
+ > A hyperlink is closed with the same escape sequence, omitting the
+ > parameters and the URI but keeping the separators:
+ >
+ > OSC 8 ; ; ST
+ >
+ > OSC (operating system command) is typically ESC ].
+
+ Use BEL instead of ST, as that is currently rendered better in some
+ terminal emulators that don't support OSC 8, like konsole. */
+
+/* If URL-printing is enabled, write an "open URL" escape sequence to PP
+ for the given URL. */
+
+void
+pp_begin_url (pretty_printer *pp, const char *url)
+{
+ switch (pp->url_format)
+ {
+ case URL_FORMAT_NONE:
+ break;
+ case URL_FORMAT_ST:
+ pp_string (pp, "\33]8;;");
+ pp_string (pp, url);
+ pp_string (pp, "\33\\");
+ break;
+ case URL_FORMAT_BEL:
+ pp_string (pp, "\33]8;;");
+ pp_string (pp, url);
+ pp_string (pp, "\a");
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Helper function for pp_end_url and pp_format, return the "close URL" escape
+ sequence string. */
+
+static const char *
+get_end_url_string (pretty_printer *pp)
+{
+ switch (pp->url_format)
+ {
+ case URL_FORMAT_NONE:
+ return "";
+ case URL_FORMAT_ST:
+ return "\33]8;;\33\\";
+ case URL_FORMAT_BEL:
+ return "\33]8;;\a";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* If URL-printing is enabled, write a "close URL" escape sequence to PP. */
+
+void
+pp_end_url (pretty_printer *pp)
+{
+ if (pp->url_format != URL_FORMAT_NONE)
+ pp_string (pp, get_end_url_string (pp));
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Smoketest for pretty_printer. */
+
+static void
+test_basic_printing ()
+{
+ pretty_printer pp;
+ pp_string (&pp, "hello");
+ pp_space (&pp);
+ pp_string (&pp, "world");
+
+ ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
+}
+
+/* Helper function for testing pp_format.
+ Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
+ prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */
+
+static void
+assert_pp_format_va (const location &loc, const char *expected,
+ bool show_color, const char *fmt, va_list *ap)
+{
+ pretty_printer pp;
+ text_info ti;
+ rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+ ti.format_spec = fmt;
+ ti.args_ptr = ap;
+ ti.err_no = 0;
+ ti.x_data = NULL;
+ ti.m_richloc = &rich_loc;
+
+ pp_show_color (&pp) = show_color;
+ pp_format (&pp, &ti);
+ pp_output_formatted_text (&pp);
+ ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
+}
+
+/* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
+ prints EXPECTED, with show_color disabled. */
+
+static void
+assert_pp_format (const location &loc, const char *expected,
+ const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ assert_pp_format_va (loc, expected, false, fmt, &ap);
+ va_end (ap);
+}
+
+/* As above, but with colorization enabled. */
+
+static void
+assert_pp_format_colored (const location &loc, const char *expected,
+ const char *fmt, ...)
+{
+ /* The tests of colorization assume the default color scheme.
+ If GCC_COLORS is set, then the colors have potentially been
+ overridden; skip the test. */
+ if (getenv ("GCC_COLORS"))
+ return;
+
+ va_list ap;
+
+ va_start (ap, fmt);
+ assert_pp_format_va (loc, expected, true, fmt, &ap);
+ va_end (ap);
+}
+
+/* Helper function for calling testing pp_format,
+ by calling assert_pp_format with various numbers of arguments.
+ These exist mostly to avoid having to write SELFTEST_LOCATION
+ throughout test_pp_format. */
+
+#define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \
+ SELFTEST_BEGIN_STMT \
+ assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
+ (ARG1)); \
+ SELFTEST_END_STMT
+
+#define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \
+ SELFTEST_BEGIN_STMT \
+ assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
+ (ARG1), (ARG2)); \
+ SELFTEST_END_STMT
+
+#define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \
+ SELFTEST_BEGIN_STMT \
+ assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
+ (ARG1), (ARG2), (ARG3)); \
+ SELFTEST_END_STMT
+
+/* Verify that pp_format works, for various format codes. */
+
+static void
+test_pp_format ()
+{
+ /* Avoid introducing locale-specific differences in the results
+ by hardcoding open_quote and close_quote. */
+ auto_fix_quotes fix_quotes;
+
+ /* Verify that plain text is passed through unchanged. */
+ assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
+
+ /* Verify various individual format codes, in the order listed in the
+ comment for pp_format above. For each code, we append a second
+ argument with a known bit pattern (0x12345678), to ensure that we
+ are consuming arguments correctly. */
+ ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
+ 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
+ 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
+ 0x12345678);
+ ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
+ 0x12345678);
+ ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
+ ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
+ ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
+ 0x12345678);
+
+ /* Not nul-terminated. */
+ char arr[5] = { '1', '2', '3', '4', '5' };
+ ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
+ ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
+ ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
+
+ /* We can't test for %p; the pointer is printed in an implementation-defined
+ manner. */
+ ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
+ "normal %rcolored%R normal %x",
+ "error", 0x12345678);
+ assert_pp_format_colored
+ (SELFTEST_LOCATION,
+ "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
+ "normal %rcolored%R normal %x", "error", 0x12345678);
+ /* TODO:
+ %m: strerror(text->err_no) - does not consume a value from args_ptr. */
+ ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
+ ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
+ ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
+ ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
+ ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
+ ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
+
+ /* Verify flag 'q'. */
+ ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
+ assert_pp_format_colored (SELFTEST_LOCATION,
+ "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
+ "foo", 0x12345678);
+ /* Verify "%@". */
+ {
+ diagnostic_event_id_t first (2);
+ diagnostic_event_id_t second (7);
+
+ ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
+ "first %<free%> at %@; second %<free%> at %@",
+ &first, &second);
+ assert_pp_format_colored
+ (SELFTEST_LOCATION,
+ "first `free' at (3);"
+ " second `free' at (8)",
+ "first %<free%> at %@; second %<free%> at %@",
+ &first, &second);
+ }
+
+ /* Verify %Z. */
+ int v[] = { 1, 2, 3 };
+ ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
+
+ int v2[] = { 0 };
+ ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
+
+ /* Verify that combinations work, along with unformatted text. */
+ assert_pp_format (SELFTEST_LOCATION,
+ "the quick brown fox jumps over the lazy dog",
+ "the %s %s %s jumps over the %s %s",
+ "quick", "brown", "fox", "lazy", "dog");
+ assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
+ assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
+ "problem with %qs at line %i", "bar", 10);
+}
+
+/* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
+
+class test_pretty_printer : public pretty_printer
+{
+ public:
+ test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
+ int max_line_length)
+ {
+ pp_set_prefix (this, xstrdup ("PREFIX: "));
+ wrapping.rule = rule;
+ pp_set_line_maximum_length (this, max_line_length);
+ }
+};
+
+/* Verify that the various values of enum diagnostic_prefixing_rule_t work
+ as expected, with and without line wrapping. */
+
+static void
+test_prefixes_and_wrapping ()
+{
+ /* Tests of the various prefixing rules, without wrapping.
+ Newlines embedded in pp_string don't affect it; we have to
+ explicitly call pp_newline. */
+ {
+ test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
+ pp_string (&pp, "the quick brown fox");
+ pp_newline (&pp);
+ pp_string (&pp, "jumps over the lazy dog");
+ pp_newline (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "PREFIX: the quick brown fox\n"
+ " jumps over the lazy dog\n");
+ }
+ {
+ test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
+ pp_string (&pp, "the quick brown fox");
+ pp_newline (&pp);
+ pp_string (&pp, "jumps over the lazy dog");
+ pp_newline (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "the quick brown fox\n"
+ "jumps over the lazy dog\n");
+ }
+ {
+ test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
+ pp_string (&pp, "the quick brown fox");
+ pp_newline (&pp);
+ pp_string (&pp, "jumps over the lazy dog");
+ pp_newline (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "PREFIX: the quick brown fox\n"
+ "PREFIX: jumps over the lazy dog\n");
+ }
+
+ /* Tests of the various prefixing rules, with wrapping. */
+ {
+ test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
+ pp_string (&pp, "the quick brown fox jumps over the lazy dog");
+ pp_newline (&pp);
+ pp_string (&pp, "able was I ere I saw elba");
+ pp_newline (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "PREFIX: the quick \n"
+ " brown fox jumps \n"
+ " over the lazy \n"
+ " dog\n"
+ " able was I ere I \n"
+ " saw elba\n");
+ }
+ {
+ test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
+ pp_string (&pp, "the quick brown fox jumps over the lazy dog");
+ pp_newline (&pp);
+ pp_string (&pp, "able was I ere I saw elba");
+ pp_newline (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "the quick brown fox \n"
+ "jumps over the lazy \n"
+ "dog\n"
+ "able was I ere I \n"
+ "saw elba\n");
+ }
+ {
+ test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
+ pp_string (&pp, "the quick brown fox jumps over the lazy dog");
+ pp_newline (&pp);
+ pp_string (&pp, "able was I ere I saw elba");
+ pp_newline (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "PREFIX: the quick brown fox jumps over the lazy dog\n"
+ "PREFIX: able was I ere I saw elba\n");
+ }
+
+}
+
+/* Verify that URL-printing works as expected. */
+
+void
+test_urls ()
+{
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_NONE;
+ pp_begin_url (&pp, "http://example.com");
+ pp_string (&pp, "This is a link");
+ pp_end_url (&pp);
+ ASSERT_STREQ ("This is a link",
+ pp_formatted_text (&pp));
+ }
+
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_ST;
+ pp_begin_url (&pp, "http://example.com");
+ pp_string (&pp, "This is a link");
+ pp_end_url (&pp);
+ ASSERT_STREQ ("\33]8;;http://example.com\33\\This is a link\33]8;;\33\\",
+ pp_formatted_text (&pp));
+ }
+
+ {
+ pretty_printer pp;
+ pp.url_format = URL_FORMAT_BEL;
+ pp_begin_url (&pp, "http://example.com");
+ pp_string (&pp, "This is a link");
+ pp_end_url (&pp);
+ ASSERT_STREQ ("\33]8;;http://example.com\aThis is a link\33]8;;\a",
+ pp_formatted_text (&pp));
+ }
+}
+
+/* Test multibyte awareness. */
+static void test_utf8 ()
+{
+
+ /* Check that pp_quoted_string leaves valid UTF-8 alone. */
+ {
+ pretty_printer pp;
+ const char *s = "\xf0\x9f\x98\x82";
+ pp_quoted_string (&pp, s);
+ ASSERT_STREQ (pp_formatted_text (&pp), s);
+ }
+
+ /* Check that pp_quoted_string escapes non-UTF-8 nonprintable bytes. */
+ {
+ pretty_printer pp;
+ pp_quoted_string (&pp, "\xf0!\x9f\x98\x82");
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "\\xf0!\\x9f\\x98\\x82");
+ }
+
+ /* Check that pp_character will line-wrap at the beginning of a UTF-8
+ sequence, but not in the middle. */
+ {
+ pretty_printer pp (3);
+ const char s[] = "---\xf0\x9f\x98\x82";
+ for (int i = 0; i != sizeof (s) - 1; ++i)
+ pp_character (&pp, s[i]);
+ pp_newline (&pp);
+ for (int i = 1; i != sizeof (s) - 1; ++i)
+ pp_character (&pp, s[i]);
+ pp_character (&pp, '-');
+ ASSERT_STREQ (pp_formatted_text (&pp),
+ "---\n"
+ "\xf0\x9f\x98\x82\n"
+ "--\xf0\x9f\x98\x82\n"
+ "-");
+ }
+
+}
+
+/* Run all of the selftests within this file. */
+
+void
+pretty_print_cc_tests ()
+{
+ test_basic_printing ();
+ test_pp_format ();
+ test_prefixes_and_wrapping ();
+ test_urls ();
+ test_utf8 ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
diff --git a/support/cpp/gcc/pretty-print.h b/support/cpp/gcc/pretty-print.h
new file mode 100644
index 000000000..3eed9aad3
--- /dev/null
+++ b/support/cpp/gcc/pretty-print.h
@@ -0,0 +1,436 @@
+/* Various declarations for language-independent pretty-print subroutines.
+ Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
+
+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_PRETTY_PRINT_H
+#define GCC_PRETTY_PRINT_H
+
+#include "obstack.h"
+#include "diagnostic-url.h"
+
+/* Maximum number of format string arguments. */
+#define PP_NL_ARGMAX 30
+
+/* The type of a text to be formatted according a format specification
+ along with a list of things. */
+struct text_info
+{
+ const char *format_spec;
+ va_list *args_ptr;
+ int err_no; /* for %m */
+ void **x_data;
+ rich_location *m_richloc;
+
+ void set_location (unsigned int idx, location_t loc,
+ enum range_display_kind range_display_kind);
+ location_t get_location (unsigned int index_of_location) const;
+};
+
+/* How often diagnostics are prefixed by their locations:
+ o DIAGNOSTICS_SHOW_PREFIX_NEVER: never - not yet supported;
+ o DIAGNOSTICS_SHOW_PREFIX_ONCE: emit only once;
+ o DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE: emit each time a physical
+ line is started. */
+enum diagnostic_prefixing_rule_t
+{
+ DIAGNOSTICS_SHOW_PREFIX_ONCE = 0x0,
+ DIAGNOSTICS_SHOW_PREFIX_NEVER = 0x1,
+ DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE = 0x2
+};
+
+/* The chunk_info data structure forms a stack of the results from the
+ first phase of formatting (pp_format) which have not yet been
+ output (pp_output_formatted_text). A stack is necessary because
+ the diagnostic starter may decide to generate its own output by way
+ of the formatter. */
+struct chunk_info
+{
+ /* Pointer to previous chunk on the stack. */
+ struct chunk_info *prev;
+
+ /* Array of chunks to output. Each chunk is a NUL-terminated string.
+ In the first phase of formatting, even-numbered chunks are
+ to be output verbatim, odd-numbered chunks are format specifiers.
+ The second phase replaces all odd-numbered chunks with formatted
+ text, and the third phase simply emits all the chunks in sequence
+ with appropriate line-wrapping. */
+ const char *args[PP_NL_ARGMAX * 2];
+};
+
+/* The output buffer datatype. This is best seen as an abstract datatype
+ whose fields should not be accessed directly by clients. */
+class output_buffer
+{
+public:
+ output_buffer ();
+ ~output_buffer ();
+
+ /* Obstack where the text is built up. */
+ struct obstack formatted_obstack;
+
+ /* Obstack containing a chunked representation of the format
+ specification plus arguments. */
+ struct obstack chunk_obstack;
+
+ /* Currently active obstack: one of the above two. This is used so
+ that the text formatters don't need to know which phase we're in. */
+ struct obstack *obstack;
+
+ /* Stack of chunk arrays. These come from the chunk_obstack. */
+ struct chunk_info *cur_chunk_array;
+
+ /* Where to output formatted text. */
+ FILE *stream;
+
+ /* The amount of characters output so far. */
+ int line_length;
+
+ /* This must be large enough to hold any printed integer or
+ floating-point value. */
+ char digit_buffer[128];
+
+ /* Nonzero means that text should be flushed when
+ appropriate. Otherwise, text is buffered until either
+ pp_really_flush or pp_clear_output_area are called. */
+ bool flush_p;
+};
+
+/* Finishes constructing a NULL-terminated character string representing
+ the buffered text. */
+static inline const char *
+output_buffer_formatted_text (output_buffer *buff)
+{
+ obstack_1grow (buff->obstack, '\0');
+ return (const char *) obstack_base (buff->obstack);
+}
+
+/* Append to the output buffer a string specified by its
+ STARTing character and LENGTH. */
+static inline void
+output_buffer_append_r (output_buffer *buff, const char *start, int length)
+{
+ gcc_checking_assert (start);
+ obstack_grow (buff->obstack, start, length);
+ for (int i = 0; i < length; i++)
+ if (start[i] == '\n')
+ buff->line_length = 0;
+ else
+ buff->line_length++;
+}
+
+/* Return a pointer to the last character emitted in the
+ output_buffer. A NULL pointer means no character available. */
+static inline const char *
+output_buffer_last_position_in_text (const output_buffer *buff)
+{
+ const char *p = NULL;
+ struct obstack *text = buff->obstack;
+
+ if (obstack_base (text) != obstack_next_free (text))
+ p = ((const char *) obstack_next_free (text)) - 1;
+ return p;
+}
+
+
+/* The type of pretty-printer flags passed to clients. */
+typedef unsigned int pp_flags;
+
+enum pp_padding
+{
+ pp_none, pp_before, pp_after
+};
+
+/* Structure for switching in and out of verbatim mode in a convenient
+ manner. */
+struct pp_wrapping_mode_t
+{
+ /* Current prefixing rule. */
+ diagnostic_prefixing_rule_t rule;
+
+ /* The ideal upper bound of number of characters per line, as suggested
+ by front-end. */
+ int line_cutoff;
+};
+
+/* Maximum characters per line in automatic line wrapping mode.
+ Zero means don't wrap lines. */
+#define pp_line_cutoff(PP) (PP)->wrapping.line_cutoff
+
+/* Prefixing rule used in formatting a diagnostic message. */
+#define pp_prefixing_rule(PP) (PP)->wrapping.rule
+
+/* Get or set the wrapping mode as a single entity. */
+#define pp_wrapping_mode(PP) (PP)->wrapping
+
+/* The type of a hook that formats client-specific data onto a pretty_printer.
+ A client-supplied formatter returns true if everything goes well,
+ otherwise it returns false. */
+typedef bool (*printer_fn) (pretty_printer *, text_info *, const char *,
+ int, bool, bool, bool, bool *, const char **);
+
+/* Client supplied function used to decode formats. */
+#define pp_format_decoder(PP) (PP)->format_decoder
+
+/* Base class for an optional client-supplied object for doing additional
+ processing between stages 2 and 3 of formatted printing. */
+class format_postprocessor
+{
+ public:
+ virtual ~format_postprocessor () {}
+ virtual format_postprocessor *clone() const = 0;
+ virtual void handle (pretty_printer *) = 0;
+};
+
+/* TRUE if a newline character needs to be added before further
+ formatting. */
+#define pp_needs_newline(PP) (PP)->need_newline
+
+/* True if PRETTY-PRINTER is in line-wrapping mode. */
+#define pp_is_wrapping_line(PP) (pp_line_cutoff (PP) > 0)
+
+/* The amount of whitespace to be emitted when starting a new line. */
+#define pp_indentation(PP) (PP)->indent_skip
+
+/* True if identifiers are translated to the locale character set on
+ output. */
+#define pp_translate_identifiers(PP) (PP)->translate_identifiers
+
+/* True if colors should be shown. */
+#define pp_show_color(PP) (PP)->show_color
+
+/* The data structure that contains the bare minimum required to do
+ proper pretty-printing. Clients may derived from this structure
+ and add additional fields they need. */
+class pretty_printer
+{
+public:
+ /* Default construct a pretty printer with specified
+ maximum line length cut off limit. */
+ explicit pretty_printer (int = 0);
+ explicit pretty_printer (const pretty_printer &other);
+
+ virtual ~pretty_printer ();
+
+ virtual pretty_printer *clone () const;
+
+ /* Where we print external representation of ENTITY. */
+ output_buffer *buffer;
+
+ /* The prefix for each new line. If non-NULL, this is "owned" by the
+ pretty_printer, and will eventually be free-ed. */
+ char *prefix;
+
+ /* Where to put whitespace around the entity being formatted. */
+ pp_padding padding;
+
+ /* The real upper bound of number of characters per line, taking into
+ account the case of a very very looong prefix. */
+ int maximum_length;
+
+ /* Indentation count. */
+ int indent_skip;
+
+ /* Current wrapping mode. */
+ pp_wrapping_mode_t wrapping;
+
+ /* If non-NULL, this function formats a TEXT into the BUFFER. When called,
+ TEXT->format_spec points to a format code. FORMAT_DECODER should call
+ pp_string (and related functions) to add data to the BUFFER.
+ FORMAT_DECODER can read arguments from *TEXT->args_pts using VA_ARG.
+ If the BUFFER needs additional characters from the format string, it
+ should advance the TEXT->format_spec as it goes. When FORMAT_DECODER
+ returns, TEXT->format_spec should point to the last character processed.
+ The QUOTE and BUFFER_PTR are passed in, to allow for deferring-handling
+ of format codes (e.g. %H and %I in the C++ frontend). */
+ printer_fn format_decoder;
+
+ /* If non-NULL, this is called by pp_format once after all format codes
+ have been processed, to allow for client-specific postprocessing.
+ This is used by the C++ frontend for handling the %H and %I
+ format codes (which interract with each other). */
+ format_postprocessor *m_format_postprocessor;
+
+ /* Nonzero if current PREFIX was emitted at least once. */
+ bool emitted_prefix;
+
+ /* Nonzero means one should emit a newline before outputting anything. */
+ bool need_newline;
+
+ /* Nonzero means identifiers are translated to the locale character
+ set on output. */
+ bool translate_identifiers;
+
+ /* Nonzero means that text should be colorized. */
+ bool show_color;
+
+ /* Whether URLs should be emitted, and which terminator to use. */
+ diagnostic_url_format url_format;
+};
+
+static inline const char *
+pp_get_prefix (const pretty_printer *pp) { return pp->prefix; }
+
+#define pp_space(PP) pp_character (PP, ' ')
+#define pp_left_paren(PP) pp_character (PP, '(')
+#define pp_right_paren(PP) pp_character (PP, ')')
+#define pp_left_bracket(PP) pp_character (PP, '[')
+#define pp_right_bracket(PP) pp_character (PP, ']')
+#define pp_left_brace(PP) pp_character (PP, '{')
+#define pp_right_brace(PP) pp_character (PP, '}')
+#define pp_semicolon(PP) pp_character (PP, ';')
+#define pp_comma(PP) pp_character (PP, ',')
+#define pp_dot(PP) pp_character (PP, '.')
+#define pp_colon(PP) pp_character (PP, ':')
+#define pp_colon_colon(PP) pp_string (PP, "::")
+#define pp_arrow(PP) pp_string (PP, "->")
+#define pp_equal(PP) pp_character (PP, '=')
+#define pp_question(PP) pp_character (PP, '?')
+#define pp_bar(PP) pp_character (PP, '|')
+#define pp_bar_bar(PP) pp_string (PP, "||")
+#define pp_carret(PP) pp_character (PP, '^')
+#define pp_ampersand(PP) pp_character (PP, '&')
+#define pp_ampersand_ampersand(PP) pp_string (PP, "&&")
+#define pp_less(PP) pp_character (PP, '<')
+#define pp_less_equal(PP) pp_string (PP, "<=")
+#define pp_greater(PP) pp_character (PP, '>')
+#define pp_greater_equal(PP) pp_string (PP, ">=")
+#define pp_plus(PP) pp_character (PP, '+')
+#define pp_minus(PP) pp_character (PP, '-')
+#define pp_star(PP) pp_character (PP, '*')
+#define pp_slash(PP) pp_character (PP, '/')
+#define pp_modulo(PP) pp_character (PP, '%')
+#define pp_exclamation(PP) pp_character (PP, '!')
+#define pp_complement(PP) pp_character (PP, '~')
+#define pp_quote(PP) pp_character (PP, '\'')
+#define pp_backquote(PP) pp_character (PP, '`')
+#define pp_doublequote(PP) pp_character (PP, '"')
+#define pp_underscore(PP) pp_character (PP, '_')
+#define pp_maybe_newline_and_indent(PP, N) \
+ if (pp_needs_newline (PP)) pp_newline_and_indent (PP, N)
+#define pp_scalar(PP, FORMAT, SCALAR) \
+ do \
+ { \
+ sprintf (pp_buffer (PP)->digit_buffer, FORMAT, SCALAR); \
+ pp_string (PP, pp_buffer (PP)->digit_buffer); \
+ } \
+ while (0)
+#define pp_decimal_int(PP, I) pp_scalar (PP, "%d", I)
+#define pp_unsigned_wide_integer(PP, I) \
+ pp_scalar (PP, HOST_WIDE_INT_PRINT_UNSIGNED, (unsigned HOST_WIDE_INT) I)
+#define pp_wide_int(PP, W, SGN) \
+ do \
+ { \
+ print_dec (W, pp_buffer (PP)->digit_buffer, SGN); \
+ pp_string (PP, pp_buffer (PP)->digit_buffer); \
+ } \
+ while (0)
+#define pp_double(PP, F) pp_scalar (PP, "%f", F)
+#define pp_pointer(PP, P) pp_scalar (PP, "%p", P)
+
+#define pp_identifier(PP, ID) pp_string (PP, (pp_translate_identifiers (PP) \
+ ? identifier_to_locale (ID) \
+ : (ID)))
+
+
+#define pp_buffer(PP) (PP)->buffer
+
+extern void pp_set_line_maximum_length (pretty_printer *, int);
+extern void pp_set_prefix (pretty_printer *, char *);
+extern char *pp_take_prefix (pretty_printer *);
+extern void pp_destroy_prefix (pretty_printer *);
+extern int pp_remaining_character_count_for_line (pretty_printer *);
+extern void pp_clear_output_area (pretty_printer *);
+extern const char *pp_formatted_text (pretty_printer *);
+extern const char *pp_last_position_in_text (const pretty_printer *);
+extern void pp_emit_prefix (pretty_printer *);
+extern void pp_append_text (pretty_printer *, const char *, const char *);
+extern void pp_newline_and_flush (pretty_printer *);
+extern void pp_newline_and_indent (pretty_printer *, int);
+extern void pp_separate_with (pretty_printer *, char);
+
+/* If we haven't already defined a front-end-specific diagnostics
+ style, use the generic one. */
+#ifdef GCC_DIAG_STYLE
+#define GCC_PPDIAG_STYLE GCC_DIAG_STYLE
+#else
+#define GCC_PPDIAG_STYLE __gcc_diag__
+#endif
+
+/* This header may be included before diagnostics-core.h, hence the duplicate
+ definitions to allow for GCC-specific formats. */
+#if GCC_VERSION >= 3005
+#define ATTRIBUTE_GCC_PPDIAG(m, n) __attribute__ ((__format__ (GCC_PPDIAG_STYLE, m ,n))) ATTRIBUTE_NONNULL(m)
+#else
+#define ATTRIBUTE_GCC_PPDIAG(m, n) ATTRIBUTE_NONNULL(m)
+#endif
+extern void pp_printf (pretty_printer *, const char *, ...)
+ ATTRIBUTE_GCC_PPDIAG(2,3);
+
+extern void pp_verbatim (pretty_printer *, const char *, ...)
+ ATTRIBUTE_GCC_PPDIAG(2,3);
+extern void pp_flush (pretty_printer *);
+extern void pp_really_flush (pretty_printer *);
+extern void pp_format (pretty_printer *, text_info *);
+extern void pp_output_formatted_text (pretty_printer *);
+extern void pp_format_verbatim (pretty_printer *, text_info *);
+
+extern void pp_indent (pretty_printer *);
+extern void pp_newline (pretty_printer *);
+extern void pp_character (pretty_printer *, int);
+extern void pp_string (pretty_printer *, const char *);
+
+extern void pp_write_text_to_stream (pretty_printer *);
+extern void pp_write_text_as_dot_label_to_stream (pretty_printer *, bool);
+extern void pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp);
+
+extern void pp_maybe_space (pretty_printer *);
+
+extern void pp_begin_quote (pretty_printer *, bool);
+extern void pp_end_quote (pretty_printer *, bool);
+
+extern void pp_begin_url (pretty_printer *pp, const char *url);
+extern void pp_end_url (pretty_printer *pp);
+
+/* Switch into verbatim mode and return the old mode. */
+static inline pp_wrapping_mode_t
+pp_set_verbatim_wrapping_ (pretty_printer *pp)
+{
+ pp_wrapping_mode_t oldmode = pp_wrapping_mode (pp);
+ pp_line_cutoff (pp) = 0;
+ pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_NEVER;
+ return oldmode;
+}
+#define pp_set_verbatim_wrapping(PP) pp_set_verbatim_wrapping_ (PP)
+
+extern const char *identifier_to_locale (const char *);
+extern void *(*identifier_to_locale_alloc) (size_t);
+extern void (*identifier_to_locale_free) (void *);
+
+/* Print I to PP in decimal. */
+
+inline void
+pp_wide_integer (pretty_printer *pp, HOST_WIDE_INT i)
+{
+ pp_scalar (pp, HOST_WIDE_INT_PRINT_DEC, i);
+}
+
+// sdcpp template<unsigned int N, typename T>
+// sdcpp void pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &);
+
+#endif /* GCC_PRETTY_PRINT_H */
diff --git a/support/cpp/gcc/print-rtl.h b/support/cpp/gcc/print-rtl.h
new file mode 100644
index 000000000..7703f3f90
--- /dev/null
+++ b/support/cpp/gcc/print-rtl.h
@@ -0,0 +1,165 @@
+/* Print RTL for GCC.
+ 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/>. */
+
+#ifndef GCC_PRINT_RTL_H
+#define GCC_PRINT_RTL_H
+
+#ifndef GENERATOR_FILE
+#include "bitmap.h"
+#endif /* #ifndef GENERATOR_FILE */
+
+class rtx_reuse_manager;
+
+/* A class for writing rtx to a FILE *. */
+
+class rtx_writer
+{
+ public:
+ rtx_writer (FILE *outfile, int ind, bool simple, bool compact,
+ rtx_reuse_manager *reuse_manager);
+
+ void print_rtx (const_rtx in_rtx);
+ void print_rtl (const_rtx rtx_first);
+ int print_rtl_single_with_indent (const_rtx x, int ind);
+
+ void finish_directive ();
+
+ private:
+ void print_rtx_operand_code_0 (const_rtx in_rtx, int idx);
+ void print_rtx_operand_code_e (const_rtx in_rtx, int idx);
+ void print_rtx_operand_codes_E_and_V (const_rtx in_rtx, int idx);
+ void print_rtx_operand_code_i (const_rtx in_rtx, int idx);
+ void print_rtx_operand_code_r (const_rtx in_rtx);
+ void print_rtx_operand_code_u (const_rtx in_rtx, int idx);
+ void print_rtx_operand (const_rtx in_rtx, int idx);
+ bool operand_has_default_value_p (const_rtx in_rtx, int idx);
+
+ private:
+ FILE *m_outfile;
+ int m_sawclose;
+ int m_indent;
+ bool m_in_call_function_usage;
+
+ /* True means use simplified format without flags, modes, etc. */
+ bool m_simple;
+
+ /* If true, use compact dump format:
+ - PREV/NEXT_INSN UIDs are omitted
+ - INSN_CODEs are omitted,
+ - register numbers are omitted for hard and virtual regs, and
+ non-virtual pseudos are offset relative to the first such reg, and
+ printed with a '%' sigil e.g. "%0" for (LAST_VIRTUAL_REGISTER + 1),
+ - insn names are prefixed with "c" (e.g. "cinsn", "cnote", etc). */
+ bool m_compact;
+
+#ifndef GENERATOR_FILE
+ /* An optional instance of rtx_reuse_manager. */
+ rtx_reuse_manager *m_rtx_reuse_manager;
+#endif
+};
+
+#ifdef BUFSIZ
+extern void print_rtl (FILE *, const_rtx);
+#endif
+extern void print_rtx_insn_vec (FILE *file, const vec<rtx_insn *> &vec);
+
+extern void dump_value_slim (FILE *, const_rtx, int);
+extern void dump_insn_slim (FILE *, const rtx_insn *);
+extern void dump_rtl_slim (FILE *, const rtx_insn *, const rtx_insn *,
+ int, int);
+extern void print_value (pretty_printer *, const_rtx, int);
+extern void print_pattern (pretty_printer *, const_rtx, int);
+extern void print_insn (pretty_printer *pp, const rtx_insn *x, int verbose);
+extern void print_insn_with_notes (pretty_printer *, const rtx_insn *);
+
+extern void rtl_dump_bb_for_graph (pretty_printer *, basic_block);
+extern const char *str_pattern_slim (const_rtx);
+
+extern void print_rtx_function (FILE *file, function *fn, bool compact);
+
+#ifndef GENERATOR_FILE
+
+/* For some rtx codes (such as SCRATCH), instances are defined to only be
+ equal for pointer equality: two distinct SCRATCH instances are non-equal.
+ copy_rtx preserves this equality by reusing the SCRATCH instance.
+
+ For example, in this x86 instruction:
+
+ (cinsn (set (mem/v:BLK (scratch:DI) [0 A8])
+ (unspec:BLK [
+ (mem/v:BLK (scratch:DI) [0 A8])
+ ] UNSPEC_MEMORY_BLOCKAGE)) "test.c":2
+ (nil))
+
+ the two instances of "(scratch:DI)" are actually the same underlying
+ rtx pointer (and thus "equal"), and the insn will only be recognized
+ (as "*memory_blockage") if this pointer-equality is preserved.
+
+ To be able to preserve this pointer-equality when round-tripping
+ through dumping/loading the rtl, we need some syntax. The first
+ time a reused rtx is encountered in the dump, we prefix it with
+ a reuse ID:
+
+ (0|scratch:DI)
+
+ Subsequent references to the rtx in the dump can be expressed using
+ "reuse_rtx" e.g.:
+
+ (reuse_rtx 0)
+
+ This class is responsible for tracking a set of reuse IDs during a dump.
+
+ Dumping with reuse-support is done in two passes:
+
+ (a) a first pass in which "preprocess" is called on each top-level rtx
+ to be seen in the dump. This traverses the rtx and its descendents,
+ identifying rtx that will be seen more than once in the actual dump,
+ and assigning them reuse IDs.
+
+ (b) the actual dump, via print_rtx etc. print_rtx detect the presence
+ of a live rtx_reuse_manager and uses it if there is one. Any rtx
+ that were assigned reuse IDs will be printed with it the first time
+ that they are seen, and then printed as "(reuse_rtx ID)" subsequently.
+
+ The first phase is needed since otherwise there would be no way to tell
+ if an rtx will be reused when first encountering it. */
+
+class rtx_reuse_manager
+{
+ public:
+ rtx_reuse_manager ();
+
+ /* The first pass. */
+ void preprocess (const_rtx x);
+
+ /* The second pass (within print_rtx). */
+ bool has_reuse_id (const_rtx x, int *out);
+ bool seen_def_p (int reuse_id);
+ void set_seen_def (int reuse_id);
+
+ private:
+ hash_map<const_rtx, int> m_rtx_occurrence_count;
+ hash_map<const_rtx, int> m_rtx_reuse_ids;
+ auto_bitmap m_defs_seen;
+ int m_next_id;
+};
+
+#endif /* #ifndef GENERATOR_FILE */
+
+#endif // GCC_PRINT_RTL_H
diff --git a/support/cpp/gcc/print-tree.h b/support/cpp/gcc/print-tree.h
new file mode 100644
index 000000000..035e22912
--- /dev/null
+++ b/support/cpp/gcc/print-tree.h
@@ -0,0 +1,50 @@
+/* Declarations for printing trees in human readable form
+ Copyright (C) 2013-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_PRINT_TREE_H
+#define GCC_PRINT_TREE_H
+
+extern void debug_tree (tree);
+extern void debug_raw (const tree_node &ref);
+extern void debug_raw (const tree_node *ptr);
+extern void debug (const tree_node &ref);
+extern void debug (const tree_node *ptr);
+extern void debug_verbose (const tree_node &ref);
+extern void debug_verbose (const tree_node *ptr);
+extern void debug_head (const tree_node &ref);
+extern void debug_head (const tree_node *ptr);
+extern void debug_body (const tree_node &ref);
+extern void debug_body (const tree_node *ptr);
+extern void debug (vec<tree, va_gc> &ref);
+extern void debug (vec<tree, va_gc> *ptr);
+extern void debug_raw (vec<tree, va_gc> &ref);
+extern void debug_raw (vec<tree, va_gc> *ptr);
+#ifdef BUFSIZ
+extern void dump_addr (FILE*, const char *, const void *);
+extern void print_node (FILE *, const char *, tree, int,
+ bool brief_for_visited = true);
+extern void print_node_brief (FILE *, const char *, const_tree, int);
+extern void indent_to (FILE *, int);
+#endif
+#define PRINT_DECL_ORIGIN 0x1
+#define PRINT_DECL_NAME 0x2
+#define PRINT_DECL_UNIQUE_NAME 0x4
+extern void print_decl_identifier (FILE *, tree, int flags);
+
+#endif // GCC_PRINT_TREE_H
diff --git a/support/cpp/gcc/profile-count.h b/support/cpp/gcc/profile-count.h
new file mode 100644
index 000000000..7c66f8dd8
--- /dev/null
+++ b/support/cpp/gcc/profile-count.h
@@ -0,0 +1,1250 @@
+/* Profile counter container type.
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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_PROFILE_COUNT_H
+#define GCC_PROFILE_COUNT_H
+
+struct function;
+struct profile_count;
+class sreal;
+
+/* Quality of the profile count. Because gengtype does not support enums
+ inside of classes, this is in global namespace. */
+enum profile_quality {
+ /* Uninitialized value. */
+ UNINITIALIZED_PROFILE,
+
+ /* Profile is based on static branch prediction heuristics and may
+ or may not match reality. It is local to function and cannot be compared
+ inter-procedurally. Never used by probabilities (they are always local).
+ */
+ GUESSED_LOCAL,
+
+ /* Profile was read by feedback and was 0, we used local heuristics to guess
+ better. This is the case of functions not run in profile feedback.
+ Never used by probabilities. */
+ GUESSED_GLOBAL0,
+
+ /* Same as GUESSED_GLOBAL0 but global count is adjusted 0. */
+ GUESSED_GLOBAL0_ADJUSTED,
+
+ /* Profile is based on static branch prediction heuristics. It may or may
+ not reflect the reality but it can be compared interprocedurally
+ (for example, we inlined function w/o profile feedback into function
+ with feedback and propagated from that).
+ Never used by probabilities. */
+ GUESSED,
+
+ /* Profile was determined by autofdo. */
+ AFDO,
+
+ /* Profile was originally based on feedback but it was adjusted
+ by code duplicating optimization. It may not precisely reflect the
+ particular code path. */
+ ADJUSTED,
+
+ /* Profile was read from profile feedback or determined by accurate static
+ method. */
+ PRECISE
+};
+
+extern const char *profile_quality_as_string (enum profile_quality);
+extern bool parse_profile_quality (const char *value,
+ profile_quality *quality);
+
+/* The base value for branch probability notes and edge probabilities. */
+#define REG_BR_PROB_BASE 10000
+
+#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
+
+bool slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res);
+
+/* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */
+
+inline bool
+safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
+{
+#if (GCC_VERSION >= 5000)
+ uint64_t tmp;
+ if (!__builtin_mul_overflow (a, b, &tmp)
+ && !__builtin_add_overflow (tmp, c/2, &tmp))
+ {
+ *res = tmp / c;
+ return true;
+ }
+ if (c == 1)
+ {
+ *res = (uint64_t) -1;
+ return false;
+ }
+#else
+ if (a < ((uint64_t)1 << 31)
+ && b < ((uint64_t)1 << 31)
+ && c < ((uint64_t)1 << 31))
+ {
+ *res = (a * b + (c / 2)) / c;
+ return true;
+ }
+#endif
+ return slow_safe_scale_64bit (a, b, c, res);
+}
+
+/* Data type to hold probabilities. It implements fixed point arithmetics
+ with capping so probability is always in range [0,1] and scaling requiring
+ values greater than 1 needs to be represented otherwise.
+
+ In addition to actual value the quality of profile is tracked and propagated
+ through all operations. Special value UNINITIALIZED_PROFILE is used for probabilities
+ that has not been determined yet (for example because of
+ -fno-guess-branch-probability)
+
+ Typically probabilities are derived from profile feedback (via
+ probability_in_gcov_type), autoFDO or guessed statically and then propagated
+ thorough the compilation.
+
+ Named probabilities are available:
+ - never (0 probability)
+ - guessed_never
+ - very_unlikely (1/2000 probability)
+ - unlikely (1/5 probability)
+ - even (1/2 probability)
+ - likely (4/5 probability)
+ - very_likely (1999/2000 probability)
+ - guessed_always
+ - always
+
+ Named probabilities except for never/always are assumed to be statically
+ guessed and thus not necessarily accurate. The difference between never
+ and guessed_never is that the first one should be used only in case that
+ well behaving program will very likely not execute the "never" path.
+ For example if the path is going to abort () call or it exception handling.
+
+ Always and guessed_always probabilities are symmetric.
+
+ For legacy code we support conversion to/from REG_BR_PROB_BASE based fixpoint
+ integer arithmetics. Once the code is converted to branch probabilities,
+ these conversions will probably go away because they are lossy.
+*/
+
+class GTY((user)) profile_probability
+{
+ static const int n_bits = 29;
+ /* We can technically use ((uint32_t) 1 << (n_bits - 1)) - 2 but that
+ will lead to harder multiplication sequences. */
+ static const uint32_t max_probability = (uint32_t) 1 << (n_bits - 2);
+ static const uint32_t uninitialized_probability
+ = ((uint32_t) 1 << (n_bits - 1)) - 1;
+
+ uint32_t m_val : 29;
+ enum profile_quality m_quality : 3;
+
+ friend struct profile_count;
+public:
+ profile_probability (): m_val (uninitialized_probability),
+ m_quality (GUESSED)
+ {}
+
+ profile_probability (uint32_t val, profile_quality quality):
+ m_val (val), m_quality (quality)
+ {}
+
+ /* Named probabilities. */
+ static profile_probability never ()
+ {
+ profile_probability ret;
+ ret.m_val = 0;
+ ret.m_quality = PRECISE;
+ return ret;
+ }
+
+ static profile_probability guessed_never ()
+ {
+ profile_probability ret;
+ ret.m_val = 0;
+ ret.m_quality = GUESSED;
+ return ret;
+ }
+
+ static profile_probability very_unlikely ()
+ {
+ /* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
+ profile_probability r = guessed_always ().apply_scale (1, 2000);
+ r.m_val--;
+ return r;
+ }
+
+ static profile_probability unlikely ()
+ {
+ /* Be consistent with PROB_VERY_LIKELY in predict.h. */
+ profile_probability r = guessed_always ().apply_scale (1, 5);
+ r.m_val--;
+ return r;
+ }
+
+ static profile_probability even ()
+ {
+ return guessed_always ().apply_scale (1, 2);
+ }
+
+ static profile_probability very_likely ()
+ {
+ return always () - very_unlikely ();
+ }
+
+ static profile_probability likely ()
+ {
+ return always () - unlikely ();
+ }
+
+ static profile_probability guessed_always ()
+ {
+ profile_probability ret;
+ ret.m_val = max_probability;
+ ret.m_quality = GUESSED;
+ return ret;
+ }
+
+ static profile_probability always ()
+ {
+ profile_probability ret;
+ ret.m_val = max_probability;
+ ret.m_quality = PRECISE;
+ return ret;
+ }
+
+ /* Probabilities which has not been initialized. Either because
+ initialization did not happen yet or because profile is unknown. */
+ static profile_probability uninitialized ()
+ {
+ profile_probability c;
+ c.m_val = uninitialized_probability;
+ c.m_quality = GUESSED;
+ return c;
+ }
+
+ /* Return true if value has been initialized. */
+ bool initialized_p () const
+ {
+ return m_val != uninitialized_probability;
+ }
+
+ /* Return true if value can be trusted. */
+ bool reliable_p () const
+ {
+ return m_quality >= ADJUSTED;
+ }
+
+ /* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
+ this is mostly to support legacy code and should go away. */
+ static profile_probability from_reg_br_prob_base (int v)
+ {
+ profile_probability ret;
+ gcc_checking_assert (v >= 0 && v <= REG_BR_PROB_BASE);
+ ret.m_val = RDIV (v * (uint64_t) max_probability, REG_BR_PROB_BASE);
+ ret.m_quality = GUESSED;
+ return ret;
+ }
+
+ /* Return THIS with quality set to ADJUSTED. */
+ profile_probability adjusted () const
+ {
+ profile_probability ret = *this;
+ if (!initialized_p ())
+ return *this;
+ ret.m_quality = ADJUSTED;
+ return ret;
+ }
+
+ int to_reg_br_prob_base () const
+ {
+ gcc_checking_assert (initialized_p ());
+ return RDIV (m_val * (uint64_t) REG_BR_PROB_BASE, max_probability);
+ }
+
+ /* Conversion to and from RTL representation of profile probabilities. */
+ static profile_probability from_reg_br_prob_note (int v)
+ {
+ profile_probability ret;
+ ret.m_val = ((unsigned int)v) / 8;
+ ret.m_quality = (enum profile_quality)(v & 7);
+ return ret;
+ }
+
+ int to_reg_br_prob_note () const
+ {
+ gcc_checking_assert (initialized_p ());
+ int ret = m_val * 8 + m_quality;
+ gcc_checking_assert (from_reg_br_prob_note (ret) == *this);
+ return ret;
+ }
+
+ /* Return VAL1/VAL2. */
+ static profile_probability probability_in_gcov_type
+ (gcov_type val1, gcov_type val2)
+ {
+ profile_probability ret;
+ gcc_checking_assert (val1 >= 0 && val2 > 0);
+ if (val1 > val2)
+ ret.m_val = max_probability;
+ else
+ {
+ uint64_t tmp;
+ safe_scale_64bit (val1, max_probability, val2, &tmp);
+ gcc_checking_assert (tmp <= max_probability);
+ ret.m_val = tmp;
+ }
+ ret.m_quality = PRECISE;
+ return ret;
+ }
+
+ /* Basic operations. */
+ bool operator== (const profile_probability &other) const
+ {
+ return m_val == other.m_val && m_quality == other.m_quality;
+ }
+
+ profile_probability operator+ (const profile_probability &other) const
+ {
+ if (other == never ())
+ return *this;
+ if (*this == never ())
+ return other;
+ if (!initialized_p () || !other.initialized_p ())
+ return uninitialized ();
+
+ profile_probability ret;
+ ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+
+ profile_probability &operator+= (const profile_probability &other)
+ {
+ if (other == never ())
+ return *this;
+ if (*this == never ())
+ {
+ *this = other;
+ return *this;
+ }
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = uninitialized ();
+ else
+ {
+ m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+
+ profile_probability operator- (const profile_probability &other) const
+ {
+ if (*this == never ()
+ || other == never ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return uninitialized ();
+ profile_probability ret;
+ ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+
+ profile_probability &operator-= (const profile_probability &other)
+ {
+ if (*this == never ()
+ || other == never ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = uninitialized ();
+ else
+ {
+ m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+
+ profile_probability operator* (const profile_probability &other) const
+ {
+ if (*this == never ()
+ || other == never ())
+ return never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return uninitialized ();
+ profile_probability ret;
+ ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ ret.m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
+ return ret;
+ }
+
+ profile_probability &operator*= (const profile_probability &other)
+ {
+ if (*this == never ()
+ || other == never ())
+ return *this = never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = uninitialized ();
+ else
+ {
+ m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
+ m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
+ }
+ return *this;
+ }
+
+ profile_probability operator/ (const profile_probability &other) const
+ {
+ if (*this == never ())
+ return never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return uninitialized ();
+ profile_probability ret;
+ /* If we get probability above 1, mark it as unreliable and return 1. */
+ if (m_val >= other.m_val)
+ {
+ ret.m_val = max_probability;
+ ret.m_quality = MIN (MIN (m_quality, other.m_quality),
+ GUESSED);
+ return ret;
+ }
+ else if (!m_val)
+ ret.m_val = 0;
+ else
+ {
+ gcc_checking_assert (other.m_val);
+ ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ other.m_val),
+ max_probability);
+ }
+ ret.m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
+ return ret;
+ }
+
+ profile_probability &operator/= (const profile_probability &other)
+ {
+ if (*this == never ())
+ return *this = never ();
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = uninitialized ();
+ else
+ {
+ /* If we get probability above 1, mark it as unreliable
+ and return 1. */
+ if (m_val > other.m_val)
+ {
+ m_val = max_probability;
+ m_quality = MIN (MIN (m_quality, other.m_quality),
+ GUESSED);
+ return *this;
+ }
+ else if (!m_val)
+ ;
+ else
+ {
+ gcc_checking_assert (other.m_val);
+ m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
+ other.m_val),
+ max_probability);
+ }
+ m_quality = MIN (MIN (m_quality, other.m_quality), ADJUSTED);
+ }
+ return *this;
+ }
+
+ /* Split *THIS (ORIG) probability into 2 probabilities, such that
+ the returned one (FIRST) is *THIS * CPROB and *THIS is
+ adjusted (SECOND) so that FIRST + FIRST.invert () * SECOND
+ == ORIG. This is useful e.g. when splitting a conditional
+ branch like:
+ if (cond)
+ goto lab; // ORIG probability
+ into
+ if (cond1)
+ goto lab; // FIRST = ORIG * CPROB probability
+ if (cond2)
+ goto lab; // SECOND probability
+ such that the overall probability of jumping to lab remains
+ the same. CPROB gives the relative probability between the
+ branches. */
+ profile_probability split (const profile_probability &cprob)
+ {
+ profile_probability ret = *this * cprob;
+ /* The following is equivalent to:
+ *this = cprob.invert () * *this / ret.invert ();
+ Avoid scaling when overall outcome is supposed to be always.
+ Without knowing that one is inverse of other, the result would be
+ conservative. */
+ if (!(*this == always ()))
+ *this = (*this - ret) / ret.invert ();
+ return ret;
+ }
+
+ gcov_type apply (gcov_type val) const
+ {
+ if (*this == uninitialized ())
+ return val / 2;
+ return RDIV (val * m_val, max_probability);
+ }
+
+ /* Return 1-*THIS. */
+ profile_probability invert () const
+ {
+ return always() - *this;
+ }
+
+ /* Return THIS with quality dropped to GUESSED. */
+ profile_probability guessed () const
+ {
+ profile_probability ret = *this;
+ ret.m_quality = GUESSED;
+ return ret;
+ }
+
+ /* Return THIS with quality dropped to AFDO. */
+ profile_probability afdo () const
+ {
+ profile_probability ret = *this;
+ ret.m_quality = AFDO;
+ return ret;
+ }
+
+ /* Return *THIS * NUM / DEN. */
+ profile_probability apply_scale (int64_t num, int64_t den) const
+ {
+ if (*this == never ())
+ return *this;
+ if (!initialized_p ())
+ return uninitialized ();
+ profile_probability ret;
+ uint64_t tmp;
+ safe_scale_64bit (m_val, num, den, &tmp);
+ ret.m_val = MIN (tmp, max_probability);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
+ return ret;
+ }
+
+ /* Return true when the probability of edge is reliable.
+
+ The profile guessing code is good at predicting branch outcome (i.e.
+ taken/not taken), that is predicted right slightly over 75% of time.
+ It is however notoriously poor on predicting the probability itself.
+ In general the profile appear a lot flatter (with probabilities closer
+ to 50%) than the reality so it is bad idea to use it to drive optimization
+ such as those disabling dynamic branch prediction for well predictable
+ branches.
+
+ There are two exceptions - edges leading to noreturn edges and edges
+ predicted by number of iterations heuristics are predicted well. This macro
+ should be able to distinguish those, but at the moment it simply check for
+ noreturn heuristic that is only one giving probability over 99% or bellow
+ 1%. In future we might want to propagate reliability information across the
+ CFG if we find this information useful on multiple places. */
+ bool probably_reliable_p () const
+ {
+ if (m_quality >= ADJUSTED)
+ return true;
+ if (!initialized_p ())
+ return false;
+ return m_val < max_probability / 100
+ || m_val > max_probability - max_probability / 100;
+ }
+
+ /* Return false if profile_probability is bogus. */
+ bool verify () const
+ {
+ gcc_checking_assert (m_quality != UNINITIALIZED_PROFILE);
+ if (m_val == uninitialized_probability)
+ return m_quality == GUESSED;
+ else if (m_quality < GUESSED)
+ return false;
+ return m_val <= max_probability;
+ }
+
+ /* Comparisons are three-state and conservative. False is returned if
+ the inequality cannot be decided. */
+ bool operator< (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val < other.m_val;
+ }
+
+ bool operator> (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val > other.m_val;
+ }
+
+ bool operator<= (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val <= other.m_val;
+ }
+
+ bool operator>= (const profile_probability &other) const
+ {
+ return initialized_p () && other.initialized_p () && m_val >= other.m_val;
+ }
+
+ /* Get the value of the count. */
+ uint32_t value () const { return m_val; }
+
+ /* Get the quality of the count. */
+ enum profile_quality quality () const { return m_quality; }
+
+ /* Output THIS to F. */
+ void dump (FILE *f) const;
+
+ /* Output THIS to BUFFER. */
+ void dump (char *buffer) const;
+
+ /* Print THIS to stderr. */
+ void debug () const;
+
+ /* Return true if THIS is known to differ significantly from OTHER. */
+ bool differs_from_p (profile_probability other) const;
+
+ /* Return if difference is greater than 50%. */
+ bool differs_lot_from_p (profile_probability other) const;
+
+ /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
+ happens with COUNT2 probability. Return probability that either *THIS or
+ OTHER happens. */
+ profile_probability combine_with_count (profile_count count1,
+ profile_probability other,
+ profile_count count2) const;
+
+ /* Return probability as sreal. */
+ sreal to_sreal () const;
+ /* LTO streaming support. */
+ static profile_probability stream_in (class lto_input_block *);
+ void stream_out (struct output_block *);
+ void stream_out (struct lto_output_stream *);
+};
+
+/* Main data type to hold profile counters in GCC. Profile counts originate
+ either from profile feedback, static profile estimation or both. We do not
+ perform whole program profile propagation and thus profile estimation
+ counters are often local to function, while counters from profile feedback
+ (or special cases of profile estimation) can be used inter-procedurally.
+
+ There are 3 basic types
+ 1) local counters which are result of intra-procedural static profile
+ estimation.
+ 2) ipa counters which are result of profile feedback or special case
+ of static profile estimation (such as in function main).
+ 3) counters which counts as 0 inter-procedurally (because given function
+ was never run in train feedback) but they hold local static profile
+ estimate.
+
+ Counters of type 1 and 3 cannot be mixed with counters of different type
+ within operation (because whole function should use one type of counter)
+ with exception that global zero mix in most operations where outcome is
+ well defined.
+
+ To take local counter and use it inter-procedurally use ipa member function
+ which strips information irrelevant at the inter-procedural level.
+
+ Counters are 61bit integers representing number of executions during the
+ train run or normalized frequency within the function.
+
+ As the profile is maintained during the compilation, many adjustments are
+ made. Not all transformations can be made precisely, most importantly
+ when code is being duplicated. It also may happen that part of CFG has
+ profile counts known while other do not - for example when LTO optimizing
+ partly profiled program or when profile was lost due to COMDAT merging.
+
+ For this reason profile_count tracks more information than
+ just unsigned integer and it is also ready for profile mismatches.
+ The API of this data type represent operations that are natural
+ on profile counts - sum, difference and operation with scales and
+ probabilities. All operations are safe by never getting negative counts
+ and they do end up in uninitialized scale if any of the parameters is
+ uninitialized.
+
+ All comparisons that are three state and handling of probabilities. Thus
+ a < b is not equal to !(a >= b).
+
+ The following pre-defined counts are available:
+
+ profile_count::zero () for code that is known to execute zero times at
+ runtime (this can be detected statically i.e. for paths leading to
+ abort ();
+ profile_count::one () for code that is known to execute once (such as
+ main () function
+ profile_count::uninitialized () for unknown execution count.
+
+ */
+
+struct GTY(()) profile_count
+{
+public:
+ /* Use 62bit to hold basic block counters. Should be at least
+ 64bit. Although a counter cannot be negative, we use a signed
+ type to hold various extra stages. */
+
+ static const int n_bits = 61;
+ static const uint64_t max_count = ((uint64_t) 1 << n_bits) - 2;
+private:
+ static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
+
+#if defined (__arm__) && (__GNUC__ >= 6 && __GNUC__ <= 8)
+ /* Work-around for PR88469. A bug in the gcc-6/7/8 PCS layout code
+ incorrectly detects the alignment of a structure where the only
+ 64-bit aligned object is a bit-field. We force the alignment of
+ the entire field to mitigate this. */
+#define UINT64_BIT_FIELD_ALIGN __attribute__ ((aligned(8)))
+#else
+#define UINT64_BIT_FIELD_ALIGN
+#endif
+ uint64_t UINT64_BIT_FIELD_ALIGN m_val : n_bits;
+#undef UINT64_BIT_FIELD_ALIGN
+ enum profile_quality m_quality : 3;
+public:
+
+ /* Return true if both values can meaningfully appear in single function
+ body. We have either all counters in function local or global, otherwise
+ operations between them are not really defined well. */
+ bool compatible_p (const profile_count other) const
+ {
+ if (!initialized_p () || !other.initialized_p ())
+ return true;
+ if (*this == zero ()
+ || other == zero ())
+ return true;
+ /* Do not allow nonzero global profile together with local guesses
+ that are globally0. */
+ if (ipa ().nonzero_p ()
+ && !(other.ipa () == other))
+ return false;
+ if (other.ipa ().nonzero_p ()
+ && !(ipa () == *this))
+ return false;
+
+ return ipa_p () == other.ipa_p ();
+ }
+
+ /* Used for counters which are expected to be never executed. */
+ static profile_count zero ()
+ {
+ return from_gcov_type (0);
+ }
+
+ static profile_count adjusted_zero ()
+ {
+ profile_count c;
+ c.m_val = 0;
+ c.m_quality = ADJUSTED;
+ return c;
+ }
+
+ static profile_count guessed_zero ()
+ {
+ profile_count c;
+ c.m_val = 0;
+ c.m_quality = GUESSED;
+ return c;
+ }
+
+ static profile_count one ()
+ {
+ return from_gcov_type (1);
+ }
+
+ /* Value of counters which has not been initialized. Either because
+ initialization did not happen yet or because profile is unknown. */
+ static profile_count uninitialized ()
+ {
+ profile_count c;
+ c.m_val = uninitialized_count;
+ c.m_quality = GUESSED_LOCAL;
+ return c;
+ }
+
+ /* Conversion to gcov_type is lossy. */
+ gcov_type to_gcov_type () const
+ {
+ gcc_checking_assert (initialized_p ());
+ return m_val;
+ }
+
+ /* Return true if value has been initialized. */
+ bool initialized_p () const
+ {
+ return m_val != uninitialized_count;
+ }
+
+ /* Return true if value can be trusted. */
+ bool reliable_p () const
+ {
+ return m_quality >= ADJUSTED;
+ }
+
+ /* Return true if value can be operated inter-procedurally. */
+ bool ipa_p () const
+ {
+ return !initialized_p () || m_quality >= GUESSED_GLOBAL0;
+ }
+
+ /* Return true if quality of profile is precise. */
+ bool precise_p () const
+ {
+ return m_quality == PRECISE;
+ }
+
+ /* Get the value of the count. */
+ uint64_t value () const { return m_val; }
+
+ /* Get the quality of the count. */
+ enum profile_quality quality () const { return m_quality; }
+
+ /* When merging basic blocks, the two different profile counts are unified.
+ Return true if this can be done without losing info about profile.
+ The only case we care about here is when first BB contains something
+ that makes it terminate in a way not visible in CFG. */
+ bool ok_for_merging (profile_count other) const
+ {
+ if (m_quality < ADJUSTED
+ || other.m_quality < ADJUSTED)
+ return true;
+ return !(other < *this);
+ }
+
+ /* When merging two BBs with different counts, pick common count that looks
+ most representative. */
+ profile_count merge (profile_count other) const
+ {
+ if (*this == other || !other.initialized_p ()
+ || m_quality > other.m_quality)
+ return *this;
+ if (other.m_quality > m_quality
+ || other > *this)
+ return other;
+ return *this;
+ }
+
+ /* Basic operations. */
+ bool operator== (const profile_count &other) const
+ {
+ return m_val == other.m_val && m_quality == other.m_quality;
+ }
+
+ profile_count operator+ (const profile_count &other) const
+ {
+ if (other == zero ())
+ return *this;
+ if (*this == zero ())
+ return other;
+ if (!initialized_p () || !other.initialized_p ())
+ return uninitialized ();
+
+ profile_count ret;
+ gcc_checking_assert (compatible_p (other));
+ ret.m_val = m_val + other.m_val;
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+
+ profile_count &operator+= (const profile_count &other)
+ {
+ if (other == zero ())
+ return *this;
+ if (*this == zero ())
+ {
+ *this = other;
+ return *this;
+ }
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = uninitialized ();
+ else
+ {
+ gcc_checking_assert (compatible_p (other));
+ m_val += other.m_val;
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+
+ profile_count operator- (const profile_count &other) const
+ {
+ if (*this == zero () || other == zero ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return uninitialized ();
+ gcc_checking_assert (compatible_p (other));
+ profile_count ret;
+ ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
+ ret.m_quality = MIN (m_quality, other.m_quality);
+ return ret;
+ }
+
+ profile_count &operator-= (const profile_count &other)
+ {
+ if (*this == zero () || other == zero ())
+ return *this;
+ if (!initialized_p () || !other.initialized_p ())
+ return *this = uninitialized ();
+ else
+ {
+ gcc_checking_assert (compatible_p (other));
+ m_val = m_val >= other.m_val ? m_val - other.m_val: 0;
+ m_quality = MIN (m_quality, other.m_quality);
+ }
+ return *this;
+ }
+
+ /* Return false if profile_count is bogus. */
+ bool verify () const
+ {
+ gcc_checking_assert (m_quality != UNINITIALIZED_PROFILE);
+ return m_val != uninitialized_count || m_quality == GUESSED_LOCAL;
+ }
+
+ /* Comparisons are three-state and conservative. False is returned if
+ the inequality cannot be decided. */
+ bool operator< (const profile_count &other) const
+ {
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ if (*this == zero ())
+ return !(other == zero ());
+ if (other == zero ())
+ return false;
+ gcc_checking_assert (compatible_p (other));
+ return m_val < other.m_val;
+ }
+
+ bool operator> (const profile_count &other) const
+ {
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ if (*this == zero ())
+ return false;
+ if (other == zero ())
+ return !(*this == zero ());
+ gcc_checking_assert (compatible_p (other));
+ return initialized_p () && other.initialized_p () && m_val > other.m_val;
+ }
+
+ bool operator< (const gcov_type other) const
+ {
+ gcc_checking_assert (ipa_p ());
+ gcc_checking_assert (other >= 0);
+ return ipa ().initialized_p () && ipa ().m_val < (uint64_t) other;
+ }
+
+ bool operator> (const gcov_type other) const
+ {
+ gcc_checking_assert (ipa_p ());
+ gcc_checking_assert (other >= 0);
+ return ipa ().initialized_p () && ipa ().m_val > (uint64_t) other;
+ }
+
+ bool operator<= (const profile_count &other) const
+ {
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ if (*this == zero ())
+ return true;
+ if (other == zero ())
+ return (*this == zero ());
+ gcc_checking_assert (compatible_p (other));
+ return m_val <= other.m_val;
+ }
+
+ bool operator>= (const profile_count &other) const
+ {
+ if (!initialized_p () || !other.initialized_p ())
+ return false;
+ if (other == zero ())
+ return true;
+ if (*this == zero ())
+ return (other == zero ());
+ gcc_checking_assert (compatible_p (other));
+ return m_val >= other.m_val;
+ }
+
+ bool operator<= (const gcov_type other) const
+ {
+ gcc_checking_assert (ipa_p ());
+ gcc_checking_assert (other >= 0);
+ return ipa ().initialized_p () && ipa ().m_val <= (uint64_t) other;
+ }
+
+ bool operator>= (const gcov_type other) const
+ {
+ gcc_checking_assert (ipa_p ());
+ gcc_checking_assert (other >= 0);
+ return ipa ().initialized_p () && ipa ().m_val >= (uint64_t) other;
+ }
+
+ /* Return true when value is not zero and can be used for scaling.
+ This is different from *this > 0 because that requires counter to
+ be IPA. */
+ bool nonzero_p () const
+ {
+ return initialized_p () && m_val != 0;
+ }
+
+ /* Make counter forcibly nonzero. */
+ profile_count force_nonzero () const
+ {
+ if (!initialized_p ())
+ return *this;
+ profile_count ret = *this;
+ if (ret.m_val == 0)
+ {
+ ret.m_val = 1;
+ ret.m_quality = MIN (m_quality, ADJUSTED);
+ }
+ return ret;
+ }
+
+ profile_count max (profile_count other) const
+ {
+ profile_count val = *this;
+
+ /* Always prefer nonzero IPA counts over local counts. */
+ if (ipa ().nonzero_p () || other.ipa ().nonzero_p ())
+ {
+ val = ipa ();
+ other = other.ipa ();
+ }
+ if (!initialized_p ())
+ return other;
+ if (!other.initialized_p ())
+ return *this;
+ if (*this == zero ())
+ return other;
+ if (other == zero ())
+ return *this;
+ gcc_checking_assert (compatible_p (other));
+ if (val.m_val < other.m_val || (m_val == other.m_val
+ && val.m_quality < other.m_quality))
+ return other;
+ return *this;
+ }
+
+ /* PROB is a probability in scale 0...REG_BR_PROB_BASE. Scale counter
+ accordingly. */
+ profile_count apply_probability (int prob) const
+ {
+ gcc_checking_assert (prob >= 0 && prob <= REG_BR_PROB_BASE);
+ if (m_val == 0)
+ return *this;
+ if (!initialized_p ())
+ return uninitialized ();
+ profile_count ret;
+ ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
+ return ret;
+ }
+
+ /* Scale counter according to PROB. */
+ profile_count apply_probability (profile_probability prob) const
+ {
+ if (*this == zero ())
+ return *this;
+ if (prob == profile_probability::never ())
+ return zero ();
+ if (!initialized_p ())
+ return uninitialized ();
+ profile_count ret;
+ uint64_t tmp;
+ safe_scale_64bit (m_val, prob.m_val, profile_probability::max_probability,
+ &tmp);
+ ret.m_val = tmp;
+ ret.m_quality = MIN (m_quality, prob.m_quality);
+ return ret;
+ }
+
+ /* Return *THIS * NUM / DEN. */
+ profile_count apply_scale (int64_t num, int64_t den) const
+ {
+ if (m_val == 0)
+ return *this;
+ if (!initialized_p ())
+ return uninitialized ();
+ profile_count ret;
+ uint64_t tmp;
+
+ gcc_checking_assert (num >= 0 && den > 0);
+ safe_scale_64bit (m_val, num, den, &tmp);
+ ret.m_val = MIN (tmp, max_count);
+ ret.m_quality = MIN (m_quality, ADJUSTED);
+ return ret;
+ }
+
+ profile_count apply_scale (profile_count num, profile_count den) const
+ {
+ if (*this == zero ())
+ return *this;
+ if (num == zero ())
+ return num;
+ if (!initialized_p () || !num.initialized_p () || !den.initialized_p ())
+ return uninitialized ();
+ if (num == den)
+ return *this;
+ gcc_checking_assert (den.m_val);
+
+ profile_count ret;
+ uint64_t val;
+ safe_scale_64bit (m_val, num.m_val, den.m_val, &val);
+ ret.m_val = MIN (val, max_count);
+ ret.m_quality = MIN (MIN (MIN (m_quality, ADJUSTED),
+ num.m_quality), den.m_quality);
+ /* Be sure that ret is not local if num is global.
+ Also ensure that ret is not global0 when num is global. */
+ if (num.ipa_p ())
+ ret.m_quality = MAX (ret.m_quality,
+ num == num.ipa () ? GUESSED : num.m_quality);
+ return ret;
+ }
+
+ /* Return THIS with quality dropped to GUESSED_LOCAL. */
+ profile_count guessed_local () const
+ {
+ profile_count ret = *this;
+ if (!initialized_p ())
+ return *this;
+ ret.m_quality = GUESSED_LOCAL;
+ return ret;
+ }
+
+ /* We know that profile is globally 0 but keep local profile if present. */
+ profile_count global0 () const
+ {
+ profile_count ret = *this;
+ if (!initialized_p ())
+ return *this;
+ ret.m_quality = GUESSED_GLOBAL0;
+ return ret;
+ }
+
+ /* We know that profile is globally adjusted 0 but keep local profile
+ if present. */
+ profile_count global0adjusted () const
+ {
+ profile_count ret = *this;
+ if (!initialized_p ())
+ return *this;
+ ret.m_quality = GUESSED_GLOBAL0_ADJUSTED;
+ return ret;
+ }
+
+ /* Return THIS with quality dropped to GUESSED. */
+ profile_count guessed () const
+ {
+ profile_count ret = *this;
+ ret.m_quality = MIN (ret.m_quality, GUESSED);
+ return ret;
+ }
+
+ /* Return variant of profile count which is always safe to compare
+ across functions. */
+ profile_count ipa () const
+ {
+ if (m_quality > GUESSED_GLOBAL0_ADJUSTED)
+ return *this;
+ if (m_quality == GUESSED_GLOBAL0)
+ return zero ();
+ if (m_quality == GUESSED_GLOBAL0_ADJUSTED)
+ return adjusted_zero ();
+ return uninitialized ();
+ }
+
+ /* Return THIS with quality dropped to AFDO. */
+ profile_count afdo () const
+ {
+ profile_count ret = *this;
+ ret.m_quality = AFDO;
+ return ret;
+ }
+
+ /* Return probability of event with counter THIS within event with counter
+ OVERALL. */
+ profile_probability probability_in (const profile_count overall) const
+ {
+ if (*this == zero ()
+ && !(overall == zero ()))
+ return profile_probability::never ();
+ if (!initialized_p () || !overall.initialized_p ()
+ || !overall.m_val)
+ return profile_probability::uninitialized ();
+ if (*this == overall && m_quality == PRECISE)
+ return profile_probability::always ();
+ profile_probability ret;
+ gcc_checking_assert (compatible_p (overall));
+
+ if (overall.m_val < m_val)
+ {
+ ret.m_val = profile_probability::max_probability;
+ ret.m_quality = GUESSED;
+ return ret;
+ }
+ else
+ ret.m_val = RDIV (m_val * profile_probability::max_probability,
+ overall.m_val);
+ ret.m_quality = MIN (MAX (MIN (m_quality, overall.m_quality),
+ GUESSED), ADJUSTED);
+ return ret;
+ }
+
+ int to_frequency (struct function *fun) const;
+ int to_cgraph_frequency (profile_count entry_bb_count) const;
+ sreal to_sreal_scale (profile_count in, bool *known = NULL) const;
+
+ /* Output THIS to F. */
+ void dump (FILE *f) const;
+
+ /* Output THIS to BUFFER. */
+ void dump (char *buffer) const;
+
+ /* Print THIS to stderr. */
+ void debug () const;
+
+ /* Return true if THIS is known to differ significantly from OTHER. */
+ bool differs_from_p (profile_count other) const;
+
+ /* We want to scale profile across function boundary from NUM to DEN.
+ Take care of the side case when NUM and DEN are zeros of incompatible
+ kinds. */
+ static void adjust_for_ipa_scaling (profile_count *num, profile_count *den);
+
+ /* THIS is a count of bb which is known to be executed IPA times.
+ Combine this information into bb counter. This means returning IPA
+ if it is nonzero, not changing anything if IPA is uninitialized
+ and if IPA is zero, turning THIS into corresponding local profile with
+ global0. */
+ profile_count combine_with_ipa_count (profile_count ipa);
+
+ /* Same as combine_with_ipa_count but inside function with count IPA2. */
+ profile_count combine_with_ipa_count_within
+ (profile_count ipa, profile_count ipa2);
+
+ /* The profiling runtime uses gcov_type, which is usually 64bit integer.
+ Conversions back and forth are used to read the coverage and get it
+ into internal representation. */
+ static profile_count from_gcov_type (gcov_type v,
+ profile_quality quality = PRECISE);
+
+ /* LTO streaming support. */
+ static profile_count stream_in (class lto_input_block *);
+ void stream_out (struct output_block *);
+ void stream_out (struct lto_output_stream *);
+};
+#endif
diff --git a/support/cpp/gcc/range-op.h b/support/cpp/gcc/range-op.h
new file mode 100644
index 000000000..a51969c22
--- /dev/null
+++ b/support/cpp/gcc/range-op.h
@@ -0,0 +1,115 @@
+/* Header file for range operator class.
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.com>
+ and Aldy Hernandez <aldyh@redhat.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.
+
+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_RANGE_OP_H
+#define GCC_RANGE_OP_H
+
+// This class is implemented for each kind of operator supported by
+// the range generator. It serves various purposes.
+//
+// 1 - Generates range information for the specific operation between
+// two ranges. This provides the ability to fold ranges for an
+// expression.
+//
+// 2 - Performs range algebra on the expression such that a range can be
+// adjusted in terms of one of the operands:
+//
+// def = op1 + op2
+//
+// Given a range for def, we can adjust the range so that it is in
+// terms of either operand.
+//
+// op1_range (def_range, op2) will adjust the range in place so it
+// is in terms of op1. Since op1 = def - op2, it will subtract
+// op2 from each element of the range.
+//
+// 3 - Creates a range for an operand based on whether the result is 0 or
+// non-zero. This is mostly for logical true false, but can serve other
+// purposes.
+// ie 0 = op1 - op2 implies op2 has the same range as op1.
+
+class range_operator
+{
+public:
+ // Perform an operation between 2 ranges and return it.
+ virtual bool fold_range (irange &r, tree type,
+ const irange &lh,
+ const irange &rh,
+ relation_kind rel = VREL_NONE) const;
+
+ // Return the range for op[12] in the general case. LHS is the range for
+ // the LHS of the expression, OP[12]is the range for the other
+ //
+ // The operand and the result is returned in R.
+ //
+ // TYPE is the expected type of the range.
+ //
+ // Return TRUE if the operation is performed and a valid range is available.
+ //
+ // i.e. [LHS] = ??? + OP2
+ // is re-formed as R = [LHS] - OP2.
+ virtual bool op1_range (irange &r, tree type,
+ const irange &lhs,
+ const irange &op2,
+ relation_kind rel = VREL_NONE) const;
+ virtual bool op2_range (irange &r, tree type,
+ const irange &lhs,
+ const irange &op1,
+ relation_kind rel = VREL_NONE) const;
+
+ // The following routines are used to represent relations between the
+ // various operations. If the caller knows where the symbolics are,
+ // it can query for relationships between them given known ranges.
+ virtual enum tree_code lhs_op1_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2) const;
+ virtual enum tree_code lhs_op2_relation (const irange &lhs,
+ const irange &op1,
+ const irange &op2) const;
+ virtual enum tree_code op1_op2_relation (const irange &lhs) const;
+protected:
+ // Perform an integral operation between 2 sub-ranges and return it.
+ virtual void wi_fold (irange &r, tree type,
+ const wide_int &lh_lb,
+ const wide_int &lh_ub,
+ const wide_int &rh_lb,
+ const wide_int &rh_ub) const;
+ // Side effect of relation for generic fold_range clients.
+ virtual bool op1_op2_relation_effect (irange &lhs_range, tree type,
+ const irange &op1_range,
+ const irange &op2_range,
+ relation_kind rel) const;
+ // Called by fold range to split small subranges into parts.
+ void wi_fold_in_parts (irange &r, tree type,
+ const wide_int &lh_lb,
+ const wide_int &lh_ub,
+ const wide_int &rh_lb,
+ const wide_int &rh_ub) const;
+};
+
+extern range_operator *range_op_handler (enum tree_code code, tree type);
+extern void range_cast (irange &, tree type);
+extern void wi_set_zero_nonzero_bits (tree type,
+ const wide_int &, const wide_int &,
+ wide_int &maybe_nonzero,
+ wide_int &mustbe_nonzero);
+
+#endif // GCC_RANGE_OP_H
diff --git a/support/cpp/gcc/range.h b/support/cpp/gcc/range.h
new file mode 100644
index 000000000..5eb784b2d
--- /dev/null
+++ b/support/cpp/gcc/range.h
@@ -0,0 +1,28 @@
+/* Header file for misc range functions. -*- C++ -*-
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldyh@redhat.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.
+
+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_RANGE_H
+#define GCC_RANGE_H
+
+value_range range_zero (tree type);
+value_range range_nonzero (tree type);
+value_range range_positives (tree type);
+value_range range_negatives (tree type);
+#endif // GCC_RANGE_H
diff --git a/support/cpp/gcc/read-md.h b/support/cpp/gcc/read-md.h
new file mode 100644
index 000000000..6c6d90ec7
--- /dev/null
+++ b/support/cpp/gcc/read-md.h
@@ -0,0 +1,408 @@
+/* MD reader definitions.
+ 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/>. */
+
+#if 0 // ndef GCC_READ_MD_H
+#define GCC_READ_MD_H
+
+#include "obstack.h"
+
+/* Records a position in the file. */
+class file_location {
+public:
+ file_location () {}
+ file_location (const char *, int, int);
+
+ const char *filename;
+ int lineno;
+ int colno;
+};
+
+inline file_location::file_location (const char *filename_in, int lineno_in, int colno_in)
+: filename (filename_in), lineno (lineno_in), colno (colno_in) {}
+
+/* Holds one symbol or number in the .md file. */
+struct md_name {
+ /* The name as it appeared in the .md file. Names are syntactically
+ limited to the length of this buffer. */
+ char buffer[256];
+
+ /* The name that should actually be used by the generator programs.
+ This is an expansion of NAME, after things like constant substitution. */
+ char *string;
+};
+
+/* This structure represents a constant defined by define_constant,
+ define_enum, or such-like. */
+struct md_constant {
+ /* The name of the constant. */
+ char *name;
+
+ /* The string to which the constants expands. */
+ char *value;
+
+ /* If the constant is associated with a enumeration, this field
+ points to that enumeration, otherwise it is null. */
+ struct enum_type *parent_enum;
+};
+
+/* This structure represents one value in an enum_type. */
+struct enum_value {
+ /* The next value in the enum, or null if this is the last. */
+ struct enum_value *next;
+
+ /* The name of the value as it appears in the .md file. */
+ char *name;
+
+ /* The definition of the related C value. */
+ struct md_constant *def;
+};
+
+/* This structure represents an enum defined by define_enum or the like. */
+struct enum_type {
+ /* The C name of the enumeration. */
+ char *name;
+
+ /* True if this is an md-style enum (DEFINE_ENUM) rather than
+ a C-style enum (DEFINE_C_ENUM). */
+ bool md_p;
+
+ /* The values of the enumeration. There is always at least one. */
+ struct enum_value *values;
+
+ /* A pointer to the null terminator in VALUES. */
+ struct enum_value **tail_ptr;
+
+ /* The number of enumeration values. */
+ unsigned int num_values;
+};
+
+/* Describes one instance of an overloaded_name. */
+struct overloaded_instance {
+ /* The next instance in the chain, or null if none. */
+ overloaded_instance *next;
+
+ /* The values that the overloaded_name arguments should have for this
+ instance to be chosen. Each value is a C token. */
+ vec<const char *> arg_values;
+
+ /* The full (non-overloaded) name of the pattern. */
+ const char *name;
+
+ /* The corresponding define_expand or define_insn. */
+ rtx insn;
+};
+
+/* Describes a define_expand or define_insn whose name was preceded by '@'.
+ Overloads are uniquely determined by their name and the types of their
+ arguments; it's possible to have overloads with the same name but
+ different argument types. */
+struct overloaded_name {
+ /* The next overloaded name in the chain. */
+ overloaded_name *next;
+
+ /* The overloaded name (i.e. the name with "@" character and
+ "<...>" placeholders removed). */
+ const char *name;
+
+ /* The C types of the iterators that determine the underlying pattern,
+ in the same order as in the pattern name. E.g. "<mode>" in the
+ pattern name would give a "machine_mode" argument here. */
+ vec<const char *> arg_types;
+
+ /* The first instance associated with this overloaded_name. */
+ overloaded_instance *first_instance;
+
+ /* Where to chain new overloaded_instances. */
+ overloaded_instance **next_instance_ptr;
+};
+
+struct mapping;
+
+/* A class for reading .md files and RTL dump files.
+
+ Implemented in read-md.cc.
+
+ This class has responsibility for reading chars from input files, and
+ for certain common top-level directives including the "include"
+ directive.
+
+ It does not handle parsing the hierarchically-nested expressions of
+ rtl.def; for that see the rtx_reader subclass below (implemented in
+ read-rtl.cc). */
+
+class md_reader
+{
+ public:
+ /* Associates PTR (which can be a string, etc.) with the file location
+ specified by LOC. */
+ struct ptr_loc {
+ const void *ptr;
+ file_location loc;
+ };
+
+ md_reader (bool compact);
+ virtual ~md_reader ();
+
+ bool read_md_files (int, const char **, bool (*) (const char *));
+ bool read_file (const char *filename);
+ bool read_file_fragment (const char *filename,
+ int first_line,
+ int last_line);
+
+ /* A hook that handles a single .md-file directive, up to but not
+ including the closing ')'. It takes two arguments: the file position
+ at which the directive started, and the name of the directive. The next
+ unread character is the optional space after the directive name. */
+ virtual void handle_unknown_directive (file_location, const char *) = 0;
+
+ file_location get_current_location () const;
+
+ bool is_compact () const { return m_compact; }
+
+ /* Defined in read-md.cc. */
+ int read_char (void);
+ void unread_char (int ch);
+ file_location read_name (struct md_name *name);
+ file_location read_name_or_nil (struct md_name *);
+ void read_escape ();
+ char *read_quoted_string ();
+ char *read_braced_string ();
+ char *read_string (int star_if_braced);
+ void read_skip_construct (int depth, file_location loc);
+ void require_char (char expected);
+ void require_char_ws (char expected);
+ void require_word_ws (const char *expected);
+ int peek_char (void);
+
+ void set_md_ptr_loc (const void *ptr, file_location);
+ const struct ptr_loc *get_md_ptr_loc (const void *ptr);
+ void copy_md_ptr_loc (const void *new_ptr, const void *old_ptr);
+ void fprint_md_ptr_loc (FILE *outf, const void *ptr);
+ void print_md_ptr_loc (const void *ptr);
+
+ struct enum_type *lookup_enum_type (const char *name);
+ void traverse_enum_types (htab_trav callback, void *info);
+
+ void handle_constants ();
+ void traverse_md_constants (htab_trav callback, void *info);
+ void handle_enum (file_location loc, bool md_p);
+
+ const char *join_c_conditions (const char *cond1, const char *cond2);
+ void fprint_c_condition (FILE *outf, const char *cond);
+ void print_c_condition (const char *cond);
+
+ /* Defined in read-rtl.cc. */
+ const char *apply_iterator_to_string (const char *string);
+ rtx copy_rtx_for_iterators (rtx original);
+ void read_conditions ();
+ void record_potential_iterator_use (struct iterator_group *group,
+ file_location loc, rtx x,
+ unsigned int index, const char *name);
+ struct mapping *read_mapping (struct iterator_group *group, htab_t table);
+ overloaded_name *handle_overloaded_name (rtx, vec<mapping *> *);
+
+ const char *get_top_level_filename () const { return m_toplevel_fname; }
+ const char *get_filename () const { return m_read_md_filename; }
+ int get_lineno () const { return m_read_md_lineno; }
+ int get_colno () const { return m_read_md_colno; }
+
+ struct obstack *get_string_obstack () { return &m_string_obstack; }
+ htab_t get_md_constants () { return m_md_constants; }
+
+ overloaded_name *get_overloads () const { return m_first_overload; }
+
+ private:
+ /* A singly-linked list of filenames. */
+ struct file_name_list {
+ struct file_name_list *next;
+ const char *fname;
+ };
+
+ private:
+ void handle_file ();
+ void handle_toplevel_file ();
+ void handle_include (file_location loc);
+ void add_include_path (const char *arg);
+
+ bool read_name_1 (struct md_name *name, file_location *out_loc);
+
+ private:
+ /* Are we reading a compact dump? */
+ bool m_compact;
+
+ /* The name of the toplevel file that indirectly included
+ m_read_md_file. */
+ const char *m_toplevel_fname;
+
+ /* The directory part of m_toplevel_fname
+ NULL if m_toplevel_fname is a bare filename. */
+ char *m_base_dir;
+
+ /* The file we are reading. */
+ FILE *m_read_md_file;
+
+ /* The filename of m_read_md_file. */
+ const char *m_read_md_filename;
+
+ /* The current line number in m_read_md_file. */
+ int m_read_md_lineno;
+
+ /* The current column number in m_read_md_file. */
+ int m_read_md_colno;
+
+ /* The column number before the last newline, so that
+ we can handle unread_char ('\n') at least once whilst
+ retaining column information. */
+ int m_last_line_colno;
+
+ /* The first directory to search. */
+ file_name_list *m_first_dir_md_include;
+
+ /* A pointer to the null terminator of the md include chain. */
+ file_name_list **m_last_dir_md_include_ptr;
+
+ /* Obstack used for allocating MD strings. */
+ struct obstack m_string_obstack;
+
+ /* A table of ptr_locs, hashed on the PTR field. */
+ htab_t m_ptr_locs;
+
+ /* An obstack for the above. Plain xmalloc is a bit heavyweight for a
+ small structure like ptr_loc. */
+ struct obstack m_ptr_loc_obstack;
+
+ /* A hash table of triples (A, B, C), where each of A, B and C is a condition
+ and A is equivalent to "B && C". This is used to keep track of the source
+ of conditions that are made up of separate MD strings (such as the split
+ condition of a define_insn_and_split). */
+ htab_t m_joined_conditions;
+
+ /* An obstack for allocating joined_conditions entries. */
+ struct obstack m_joined_conditions_obstack;
+
+ /* A table of md_constant structures, hashed by name. Null if no
+ constant expansion should occur. */
+ htab_t m_md_constants;
+
+ /* A table of enum_type structures, hashed by name. */
+ htab_t m_enum_types;
+
+ /* If non-zero, filter the input to just this subset of lines. */
+ int m_first_line;
+ int m_last_line;
+
+ /* The first overloaded_name. */
+ overloaded_name *m_first_overload;
+
+ /* Where to chain further overloaded_names, */
+ overloaded_name **m_next_overload_ptr;
+
+ /* A hash table of overloaded_names, keyed off their name and the types of
+ their arguments. */
+ htab_t m_overloads_htab;
+};
+
+/* Global singleton; constrast with rtx_reader_ptr below. */
+extern md_reader *md_reader_ptr;
+
+/* An md_reader subclass which skips unknown directives, for
+ the gen* tools that purely use read-md.o. */
+
+class noop_reader : public md_reader
+{
+ public:
+ noop_reader () : md_reader (false) {}
+
+ /* A dummy implementation which skips unknown directives. */
+ void handle_unknown_directive (file_location, const char *);
+};
+
+/* An md_reader subclass that actually handles full hierarchical
+ rtx expressions.
+
+ Implemented in read-rtl.cc. */
+
+class rtx_reader : public md_reader
+{
+ public:
+ rtx_reader (bool compact);
+ ~rtx_reader ();
+
+ bool read_rtx (const char *rtx_name, vec<rtx> *rtxen);
+ rtx rtx_alloc_for_name (const char *);
+ rtx read_rtx_code (const char *code_name);
+ virtual rtx read_rtx_operand (rtx return_rtx, int idx);
+ rtx read_nested_rtx ();
+ rtx read_rtx_variadic (rtx form);
+ char *read_until (const char *terminator_chars, bool consume_terminator);
+
+ virtual void handle_any_trailing_information (rtx) {}
+ virtual rtx postprocess (rtx x) { return x; }
+
+ /* Hook to allow function_reader subclass to put STRINGBUF into gc-managed
+ memory, rather than within an obstack.
+ This base class implementation is a no-op. */
+ virtual const char *finalize_string (char *stringbuf) { return stringbuf; }
+
+ protected:
+ /* Analogous to rtx_writer's m_in_call_function_usage. */
+ bool m_in_call_function_usage;
+
+ /* Support for "reuse_rtx" directives. */
+ auto_vec<rtx> m_reuse_rtx_by_id;
+};
+
+/* Global singleton; constrast with md_reader_ptr above. */
+extern rtx_reader *rtx_reader_ptr;
+
+extern void (*include_callback) (const char *);
+
+/* Read the next character from the MD file. */
+
+static inline int
+read_char (void)
+{
+ return md_reader_ptr->read_char ();
+}
+
+/* Put back CH, which was the last character read from the MD file. */
+
+static inline void
+unread_char (int ch)
+{
+ md_reader_ptr->unread_char (ch);
+}
+
+extern hashval_t leading_string_hash (const void *);
+extern int leading_string_eq_p (const void *, const void *);
+extern const char *join_c_conditions (const char *, const char *);
+extern void message_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2;
+extern void error_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2;
+extern void fatal_at (file_location, const char *, ...) ATTRIBUTE_PRINTF_2;
+extern void fatal_with_file_and_line (const char *, ...)
+ ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
+extern void fatal_expected_char (int, int) ATTRIBUTE_NORETURN;
+extern int read_skip_spaces (void);
+extern int n_comma_elts (const char *);
+extern const char *scan_comma_elt (const char **);
+extern void upcase_string (char *);
+extern void traverse_enum_types (htab_trav, void *);
+extern struct enum_type *lookup_enum_type (const char *);
+
+#endif /* GCC_READ_MD_H */
diff --git a/support/cpp/gcc/real.h b/support/cpp/gcc/real.h
new file mode 100644
index 000000000..6a5571fb3
--- /dev/null
+++ b/support/cpp/gcc/real.h
@@ -0,0 +1,545 @@
+/* Definitions of floating-point access for GNU compiler.
+ Copyright (C) 1989-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_REAL_H
+#define GCC_REAL_H
+
+/* An expanded form of the represented number. */
+
+/* Enumerate the special cases of numbers that we encounter. */
+enum real_value_class {
+ rvc_zero,
+ rvc_normal,
+ rvc_inf,
+ rvc_nan
+};
+
+#define SIGNIFICAND_BITS (128 + HOST_BITS_PER_LONG)
+#define EXP_BITS (32 - 6)
+#define MAX_EXP ((1 << (EXP_BITS - 1)) - 1)
+#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
+#define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
+
+struct GTY(()) real_value {
+ /* Use the same underlying type for all bit-fields, so as to make
+ sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
+ be miscomputed. */
+ unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
+ /* 1 if number is decimal floating point. */
+ unsigned int decimal : 1;
+ /* 1 if number is negative. */
+ unsigned int sign : 1;
+ /* 1 if number is signalling. */
+ unsigned int signalling : 1;
+ /* 1 if number is canonical
+ All are generally used for handling cases in real.cc. */
+ unsigned int canonical : 1;
+ /* unbiased exponent of the number. */
+ unsigned int uexp : EXP_BITS;
+ /* significand of the number. */
+ unsigned long sig[SIGSZ];
+};
+
+#define REAL_EXP(REAL) \
+ ((int)((REAL)->uexp ^ (unsigned int)(1 << (EXP_BITS - 1))) \
+ - (1 << (EXP_BITS - 1)))
+#define SET_REAL_EXP(REAL, EXP) \
+ ((REAL)->uexp = ((unsigned int)(EXP) & (unsigned int)((1 << EXP_BITS) - 1)))
+
+/* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it
+ needs to be a macro. We do need to continue to have a structure tag
+ so that other headers can forward declare it. */
+#define REAL_VALUE_TYPE struct real_value
+
+/* We store a REAL_VALUE_TYPE into an rtx, and we do this by putting it in
+ consecutive "w" slots. Moreover, we've got to compute the number of "w"
+ slots at preprocessor time, which means we can't use sizeof. Guess. */
+
+#define REAL_VALUE_TYPE_SIZE (SIGNIFICAND_BITS + 32)
+#define REAL_WIDTH \
+ (REAL_VALUE_TYPE_SIZE/HOST_BITS_PER_WIDE_INT \
+ + (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */
+
+
+// SDCC hack
+// #undef REAL_WIDTH
+// #define REAL_WIDTH 2
+
+/* Verify the guess. */
+extern char test_real_width
+ [sizeof (REAL_VALUE_TYPE) <= REAL_WIDTH * sizeof (HOST_WIDE_INT) ? 1 : -1];
+
+/* Calculate the format for CONST_DOUBLE. We need as many slots as
+ are necessary to overlay a REAL_VALUE_TYPE on them. This could be
+ as many as four (32-bit HOST_WIDE_INT, 128-bit REAL_VALUE_TYPE).
+
+ A number of places assume that there are always at least two 'w'
+ slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
+
+#if REAL_WIDTH == 1
+# define CONST_DOUBLE_FORMAT "ww"
+#else
+# if REAL_WIDTH == 2
+# define CONST_DOUBLE_FORMAT "ww"
+# else
+# if REAL_WIDTH == 3
+# define CONST_DOUBLE_FORMAT "www"
+# else
+# if REAL_WIDTH == 4
+# define CONST_DOUBLE_FORMAT "wwww"
+# else
+# if REAL_WIDTH == 5
+# define CONST_DOUBLE_FORMAT "wwwww"
+# else
+# if REAL_WIDTH == 6
+# define CONST_DOUBLE_FORMAT "wwwwww"
+# else
+ #error "REAL_WIDTH > 6 not supported"
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+
+/* Describes the properties of the specific target format in use. */
+struct real_format
+{
+ /* Move to and from the target bytes. */
+ void (*encode) (const struct real_format *, long *,
+ const REAL_VALUE_TYPE *);
+ void (*decode) (const struct real_format *, REAL_VALUE_TYPE *,
+ const long *);
+
+ /* The radix of the exponent and digits of the significand. */
+ int b;
+
+ /* Size of the significand in digits of radix B. */
+ int p;
+
+ /* Size of the significant of a NaN, in digits of radix B. */
+ int pnan;
+
+ /* The minimum negative integer, x, such that b**(x-1) is normalized. */
+ int emin;
+
+ /* The maximum integer, x, such that b**(x-1) is representable. */
+ int emax;
+
+ /* The bit position of the sign bit, for determining whether a value
+ is positive/negative, or -1 for a complex encoding. */
+ int signbit_ro;
+
+ /* The bit position of the sign bit, for changing the sign of a number,
+ or -1 for a complex encoding. */
+ int signbit_rw;
+
+ /* If this is an IEEE interchange format, the number of bits in the
+ format; otherwise, if it is an IEEE extended format, one more
+ than the greatest number of bits in an interchange format it
+ extends; otherwise 0. Formats need not follow the IEEE 754-2008
+ recommended practice regarding how signaling NaNs are identified,
+ and may vary in the choice of default NaN, but must follow other
+ IEEE practice regarding having NaNs, infinities and subnormal
+ values, and the relation of minimum and maximum exponents, and,
+ for interchange formats, the details of the encoding. */
+ int ieee_bits;
+
+ /* Default rounding mode for operations on this format. */
+ bool round_towards_zero;
+ bool has_sign_dependent_rounding;
+
+ /* Properties of the format. */
+ bool has_nans;
+ bool has_inf;
+ bool has_denorm;
+ bool has_signed_zero;
+ bool qnan_msb_set;
+ bool canonical_nan_lsbs_set;
+ const char *name;
+};
+
+
+/* The target format used for each floating point mode.
+ Float modes are followed by decimal float modes, with entries for
+ float modes indexed by (MODE - first float mode), and entries for
+ decimal float modes indexed by (MODE - first decimal float mode) +
+ the number of float modes. */
+extern const struct real_format *
+ real_format_for_mode[NUM_MODE_FLOAT + NUM_MODE_DECIMAL_FLOAT];
+
+#define REAL_MODE_FORMAT(MODE) \
+ (real_format_for_mode[DECIMAL_FLOAT_MODE_P (MODE) \
+ ? (((MODE) - MIN_MODE_DECIMAL_FLOAT) \
+ + NUM_MODE_FLOAT) \
+ : GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ ? ((MODE) - MIN_MODE_FLOAT) \
+ : (gcc_unreachable (), 0)])
+
+#define FLOAT_MODE_FORMAT(MODE) \
+ (REAL_MODE_FORMAT (as_a <scalar_float_mode> (GET_MODE_INNER (MODE))))
+
+/* The following macro determines whether the floating point format is
+ composite, i.e. may contain non-consecutive mantissa bits, in which
+ case compile-time FP overflow may not model run-time overflow. */
+#define MODE_COMPOSITE_P(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && FLOAT_MODE_FORMAT (MODE)->pnan < FLOAT_MODE_FORMAT (MODE)->p)
+
+/* Accessor macros for format properties. */
+#define MODE_HAS_NANS(MODE) \
+ (FLOAT_MODE_P (MODE) && FLOAT_MODE_FORMAT (MODE)->has_nans)
+#define MODE_HAS_INFINITIES(MODE) \
+ (FLOAT_MODE_P (MODE) && FLOAT_MODE_FORMAT (MODE)->has_inf)
+#define MODE_HAS_SIGNED_ZEROS(MODE) \
+ (FLOAT_MODE_P (MODE) && FLOAT_MODE_FORMAT (MODE)->has_signed_zero)
+#define MODE_HAS_SIGN_DEPENDENT_ROUNDING(MODE) \
+ (FLOAT_MODE_P (MODE) \
+ && FLOAT_MODE_FORMAT (MODE)->has_sign_dependent_rounding)
+
+/* This class allows functions in this file to accept a floating-point
+ format as either a mode or an explicit real_format pointer. In the
+ former case the mode must be VOIDmode (which means "no particular
+ format") or must satisfy SCALAR_FLOAT_MODE_P. */
+class format_helper
+{
+public:
+ format_helper (const real_format *format) : m_format (format) {}
+ template<typename T> format_helper (const T &);
+ const real_format *operator-> () const { return m_format; }
+ operator const real_format *() const { return m_format; }
+
+ bool decimal_p () const { return m_format && m_format->b == 10; }
+ bool can_represent_integral_type_p (tree type) const;
+
+private:
+ const real_format *m_format;
+};
+
+template<typename T>
+inline format_helper::format_helper (const T &m)
+ : m_format (m == VOIDmode ? 0 : REAL_MODE_FORMAT (m))
+{}
+
+/* Declare functions in real.cc. */
+
+/* True if the given mode has a NaN representation and the treatment of
+ NaN operands is important. Certain optimizations, such as folding
+ x * 0 into 0, are not correct for NaN operands, and are normally
+ disabled for modes with NaNs. The user can ask for them to be
+ done anyway using the -funsafe-math-optimizations switch. */
+extern bool HONOR_NANS (machine_mode);
+extern bool HONOR_NANS (const_tree);
+extern bool HONOR_NANS (const_rtx);
+
+/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs). */
+extern bool HONOR_SNANS (machine_mode);
+extern bool HONOR_SNANS (const_tree);
+extern bool HONOR_SNANS (const_rtx);
+
+/* As for HONOR_NANS, but true if the mode can represent infinity and
+ the treatment of infinite values is important. */
+extern bool HONOR_INFINITIES (machine_mode);
+extern bool HONOR_INFINITIES (const_tree);
+extern bool HONOR_INFINITIES (const_rtx);
+
+/* Like HONOR_NANS, but true if the given mode distinguishes between
+ positive and negative zero, and the sign of zero is important. */
+extern bool HONOR_SIGNED_ZEROS (machine_mode);
+extern bool HONOR_SIGNED_ZEROS (const_tree);
+extern bool HONOR_SIGNED_ZEROS (const_rtx);
+
+/* Like HONOR_NANS, but true if given mode supports sign-dependent rounding,
+ and the rounding mode is important. */
+extern bool HONOR_SIGN_DEPENDENT_ROUNDING (machine_mode);
+extern bool HONOR_SIGN_DEPENDENT_ROUNDING (const_tree);
+extern bool HONOR_SIGN_DEPENDENT_ROUNDING (const_rtx);
+
+/* Binary or unary arithmetic on tree_code. */
+extern bool real_arithmetic (REAL_VALUE_TYPE *, int, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *);
+
+/* Compare reals by tree_code. */
+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 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 finite. */
+extern bool real_isfinite (const REAL_VALUE_TYPE *);
+
+/* Determine whether a floating-point value X is negative. */
+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 *);
+
+/* 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 *);
+extern bool real_less (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+
+/* Extend or truncate to a new format. */
+extern void real_convert (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *);
+
+/* Return true if truncating to NEW is exact. */
+extern bool exact_real_truncate (format_helper, const REAL_VALUE_TYPE *);
+
+/* Render R as a decimal floating point constant. */
+extern void real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t,
+ size_t, int);
+
+/* Render R as a decimal floating point constant, rounded so as to be
+ parsed back to the same value when interpreted in mode MODE. */
+extern void real_to_decimal_for_mode (char *, const REAL_VALUE_TYPE *, size_t,
+ size_t, int, machine_mode);
+
+/* Render R as a hexadecimal floating point constant. */
+extern void real_to_hexadecimal (char *, const REAL_VALUE_TYPE *,
+ size_t, size_t, int);
+
+/* Render R as an integer. */
+extern HOST_WIDE_INT real_to_integer (const REAL_VALUE_TYPE *);
+
+/* Initialize R from a decimal or hexadecimal string. Return -1 if
+ the value underflows, +1 if overflows, and 0 otherwise. */
+extern int real_from_string (REAL_VALUE_TYPE *, const char *);
+/* Wrapper to allow different internal representation for decimal floats. */
+extern void real_from_string3 (REAL_VALUE_TYPE *, const char *, format_helper);
+
+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 bool real_nan (REAL_VALUE_TYPE *, const char *, int, format_helper);
+
+extern void real_maxval (REAL_VALUE_TYPE *, int, machine_mode);
+
+extern void real_2expN (REAL_VALUE_TYPE *, int, format_helper);
+
+extern unsigned int real_hash (const REAL_VALUE_TYPE *);
+
+
+/* Target formats defined in real.cc. */
+extern const struct real_format ieee_single_format;
+extern const struct real_format mips_single_format;
+extern const struct real_format motorola_single_format;
+extern const struct real_format spu_single_format;
+extern const struct real_format ieee_double_format;
+extern const struct real_format mips_double_format;
+extern const struct real_format motorola_double_format;
+extern const struct real_format ieee_extended_motorola_format;
+extern const struct real_format ieee_extended_intel_96_format;
+extern const struct real_format ieee_extended_intel_96_round_53_format;
+extern const struct real_format ieee_extended_intel_128_format;
+extern const struct real_format ibm_extended_format;
+extern const struct real_format mips_extended_format;
+extern const struct real_format ieee_quad_format;
+extern const struct real_format mips_quad_format;
+extern const struct real_format vax_f_format;
+extern const struct real_format vax_d_format;
+extern const struct real_format vax_g_format;
+extern const struct real_format real_internal_format;
+extern const struct real_format decimal_single_format;
+extern const struct real_format decimal_double_format;
+extern const struct real_format decimal_quad_format;
+extern const struct real_format ieee_half_format;
+extern const struct real_format arm_half_format;
+extern const struct real_format arm_bfloat_half_format;
+
+
+/* ====================================================================== */
+/* Crap. */
+
+/* Determine whether a floating-point value X is infinite. */
+#define REAL_VALUE_ISINF(x) real_isinf (&(x))
+
+/* Determine whether a floating-point value X is a NaN. */
+#define REAL_VALUE_ISNAN(x) real_isnan (&(x))
+
+/* Determine whether a floating-point value X is a signaling NaN. */
+#define REAL_VALUE_ISSIGNALING_NAN(x) real_issignaling_nan (&(x))
+
+/* Determine whether a floating-point value X is negative. */
+#define REAL_VALUE_NEGATIVE(x) real_isneg (&(x))
+
+/* Determine whether a floating-point value X is minus zero. */
+#define REAL_VALUE_MINUS_ZERO(x) real_isnegzero (&(x))
+
+/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
+ real_to_target (OUT, &(IN), \
+ float_mode_for_size (LONG_DOUBLE_TYPE_SIZE).require ())
+
+#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
+ real_to_target (OUT, &(IN), float_mode_for_size (64).require ())
+
+/* IN is a REAL_VALUE_TYPE. OUT is a long. */
+#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
+ ((OUT) = real_to_target (NULL, &(IN), float_mode_for_size (32).require ()))
+
+/* Real values to IEEE 754 decimal floats. */
+
+/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
+#define REAL_VALUE_TO_TARGET_DECIMAL128(IN, OUT) \
+ real_to_target (OUT, &(IN), decimal_float_mode_for_size (128).require ())
+
+#define REAL_VALUE_TO_TARGET_DECIMAL64(IN, OUT) \
+ real_to_target (OUT, &(IN), decimal_float_mode_for_size (64).require ())
+
+/* IN is a REAL_VALUE_TYPE. OUT is a long. */
+#define REAL_VALUE_TO_TARGET_DECIMAL32(IN, OUT) \
+ ((OUT) = real_to_target (NULL, &(IN), \
+ decimal_float_mode_for_size (32).require ()))
+
+extern REAL_VALUE_TYPE real_value_truncate (format_helper, REAL_VALUE_TYPE);
+
+extern REAL_VALUE_TYPE real_value_negate (const REAL_VALUE_TYPE *);
+extern REAL_VALUE_TYPE real_value_abs (const REAL_VALUE_TYPE *);
+
+extern int significand_size (format_helper);
+
+extern REAL_VALUE_TYPE real_from_string2 (const char *, format_helper);
+
+#define REAL_VALUE_ATOF(s, m) \
+ real_from_string2 (s, m)
+
+#define CONST_DOUBLE_ATOF(s, m) \
+ const_double_from_real_value (real_from_string2 (s, m), m)
+
+#define REAL_VALUE_FIX(r) \
+ real_to_integer (&(r))
+
+/* ??? Not quite right. */
+#define REAL_VALUE_UNSIGNED_FIX(r) \
+ real_to_integer (&(r))
+
+/* ??? These were added for Paranoia support. */
+
+/* Return floor log2(R). */
+extern int real_exponent (const REAL_VALUE_TYPE *);
+
+/* R = A * 2**EXP. */
+extern void real_ldexp (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
+
+/* **** End of software floating point emulator interface macros **** */
+
+/* Constant real values 0, 1, 2, -1 and 0.5. */
+
+extern REAL_VALUE_TYPE dconst0;
+extern REAL_VALUE_TYPE dconst1;
+extern REAL_VALUE_TYPE dconst2;
+extern REAL_VALUE_TYPE dconstm1;
+extern REAL_VALUE_TYPE dconsthalf;
+
+#define dconst_e() (*dconst_e_ptr ())
+#define dconst_third() (*dconst_third_ptr ())
+#define dconst_quarter() (*dconst_quarter_ptr ())
+#define dconst_sixth() (*dconst_sixth_ptr ())
+#define dconst_ninth() (*dconst_ninth_ptr ())
+#define dconst_sqrt2() (*dconst_sqrt2_ptr ())
+
+/* Function to return the real value special constant 'e'. */
+extern const REAL_VALUE_TYPE * dconst_e_ptr (void);
+
+/* Returns a cached REAL_VALUE_TYPE corresponding to 1/n, for various n. */
+extern const REAL_VALUE_TYPE *dconst_third_ptr (void);
+extern const REAL_VALUE_TYPE *dconst_quarter_ptr (void);
+extern const REAL_VALUE_TYPE *dconst_sixth_ptr (void);
+extern const REAL_VALUE_TYPE *dconst_ninth_ptr (void);
+
+/* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2). */
+extern const REAL_VALUE_TYPE * dconst_sqrt2_ptr (void);
+
+/* Function to return a real value (not a tree node)
+ from a given integer constant. */
+REAL_VALUE_TYPE real_value_from_int_cst (const_tree, const_tree);
+
+/* Return a CONST_DOUBLE with value R and mode M. */
+extern rtx const_double_from_real_value (REAL_VALUE_TYPE, machine_mode);
+
+/* Replace R by 1/R in the given format, if the result is exact. */
+extern bool exact_real_inverse (format_helper, REAL_VALUE_TYPE *);
+
+/* Return true if arithmetic on values in IMODE that were promoted
+ from values in TMODE is equivalent to direct arithmetic on values
+ in TMODE. */
+bool real_can_shorten_arithmetic (machine_mode, machine_mode);
+
+/* In tree.cc: wrap up a REAL_VALUE_TYPE in a tree node. */
+extern tree build_real (tree, REAL_VALUE_TYPE);
+
+/* Likewise, but first truncate the value to the type. */
+extern tree build_real_truncate (tree, REAL_VALUE_TYPE);
+
+/* Calculate R as X raised to the integer exponent N in format FMT. */
+extern bool real_powi (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *, HOST_WIDE_INT);
+
+/* Standard round to integer value functions. */
+extern void real_trunc (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *);
+extern void real_floor (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *);
+extern void real_ceil (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *);
+extern void real_round (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *);
+extern void real_roundeven (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *);
+
+/* Set the sign of R to the sign of X. */
+extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+
+/* Check whether the real constant value given is an integer. */
+extern bool real_isinteger (const REAL_VALUE_TYPE *, format_helper);
+extern bool real_isinteger (const REAL_VALUE_TYPE *, HOST_WIDE_INT *);
+
+/* Calculate nextafter (X, Y) in format FMT. */
+extern bool real_nextafter (REAL_VALUE_TYPE *, format_helper,
+ const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
+
+/* Write into BUF the maximum representable finite floating-point
+ number, (1 - b**-p) * b**emax for a given FP format FMT as a hex
+ float string. BUF must be large enough to contain the result. */
+extern void get_max_float (const struct real_format *, char *, size_t, bool);
+
+#if 0 // sdcpp ndef GENERATOR_FILE
+/* real related routines. */
+extern wide_int real_to_integer (const REAL_VALUE_TYPE *, bool *, int);
+extern void real_from_integer (REAL_VALUE_TYPE *, format_helper,
+ const wide_int_ref &, signop);
+#endif
+
+/* Fills r with the largest value such that 1 + r*r won't overflow.
+ This is used in both sin (atan (x)) and cos (atan(x)) optimizations. */
+extern void build_sinatan_real (REAL_VALUE_TYPE *, tree);
+
+#endif /* ! GCC_REAL_H */
diff --git a/support/cpp/gcc/recog.h b/support/cpp/gcc/recog.h
new file mode 100644
index 000000000..c30f60ef6
--- /dev/null
+++ b/support/cpp/gcc/recog.h
@@ -0,0 +1,565 @@
+/* Declarations for interface to insn recognizer and insn-output.cc.
+ 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/>. */
+
+#if 0 // sdcpp ndef GCC_RECOG_H
+#define GCC_RECOG_H
+
+/* Random number that should be large enough for all purposes. Also define
+ a type that has at least MAX_RECOG_ALTERNATIVES + 1 bits, with the extra
+ bit giving an invalid value that can be used to mean "uninitialized". */
+#define MAX_RECOG_ALTERNATIVES 35
+typedef uint64_t alternative_mask; /* Keep in sync with genattrtab.cc. */
+
+/* A mask of all alternatives. */
+#define ALL_ALTERNATIVES ((alternative_mask) -1)
+
+/* A mask containing just alternative X. */
+#define ALTERNATIVE_BIT(X) ((alternative_mask) 1 << (X))
+
+/* Types of operands. */
+enum op_type {
+ OP_IN,
+ OP_OUT,
+ OP_INOUT
+};
+
+struct operand_alternative
+{
+ /* Pointer to the beginning of the constraint string for this alternative,
+ for easier access by alternative number. */
+ const char *constraint;
+
+ /* The register class valid for this alternative (possibly NO_REGS). */
+ ENUM_BITFIELD (reg_class) cl : 16;
+
+ /* "Badness" of this alternative, computed from number of '?' and '!'
+ characters in the constraint string. */
+ unsigned int reject : 16;
+
+ /* -1 if no matching constraint was found, or an operand number. */
+ int matches : 8;
+ /* The same information, but reversed: -1 if this operand is not
+ matched by any other, or the operand number of the operand that
+ matches this one. */
+ int matched : 8;
+
+ /* Nonzero if '&' was found in the constraint string. */
+ unsigned int earlyclobber : 1;
+ /* Nonzero if TARGET_MEM_CONSTRAINT was found in the constraint
+ string. */
+ unsigned int memory_ok : 1;
+ /* Nonzero if 'p' was found in the constraint string. */
+ unsigned int is_address : 1;
+ /* Nonzero if 'X' was found in the constraint string, or if the constraint
+ string for this alternative was empty. */
+ unsigned int anything_ok : 1;
+
+ unsigned int unused : 12;
+};
+
+/* Return the class for operand I of alternative ALT, taking matching
+ constraints into account. */
+
+static inline enum reg_class
+alternative_class (const operand_alternative *alt, int i)
+{
+ return alt[i].matches >= 0 ? alt[alt[i].matches].cl : alt[i].cl;
+}
+
+/* A class for substituting one rtx for another within an instruction,
+ or for recursively simplifying the instruction as-is. Derived classes
+ can record or filter certain decisions. */
+
+class insn_propagation : public simplify_context
+{
+public:
+ /* Assignments for RESULT_FLAGS.
+
+ UNSIMPLIFIED is true if a substitution has been made inside an rtx
+ X and if neither X nor its parent expressions could be simplified.
+
+ FIRST_SPARE_RESULT is the first flag available for derived classes. */
+ static const uint16_t UNSIMPLIFIED = 1U << 0;
+ static const uint16_t FIRST_SPARE_RESULT = 1U << 1;
+
+ insn_propagation (rtx_insn *);
+ insn_propagation (rtx_insn *, rtx, rtx, bool = true);
+ bool apply_to_pattern (rtx *);
+ bool apply_to_rvalue (rtx *);
+
+ /* Return true if we should accept a substitution into the address of
+ memory expression MEM. Undoing changes OLD_NUM_CHANGES and up restores
+ MEM's original address. */
+ virtual bool check_mem (int /*old_num_changes*/,
+ rtx /*mem*/) { return true; }
+
+ /* Note that we've simplified OLD_RTX into NEW_RTX. When substituting,
+ this only happens if a substitution occured within OLD_RTX.
+ Undoing OLD_NUM_CHANGES and up will restore the old form of OLD_RTX.
+ OLD_RESULT_FLAGS is the value that RESULT_FLAGS had before processing
+ OLD_RTX. */
+ virtual void note_simplification (int /*old_num_changes*/,
+ uint16_t /*old_result_flags*/,
+ rtx /*old_rtx*/, rtx /*new_rtx*/) {}
+
+private:
+ bool apply_to_mem_1 (rtx);
+ bool apply_to_lvalue_1 (rtx);
+ bool apply_to_rvalue_1 (rtx *);
+ bool apply_to_pattern_1 (rtx *);
+
+public:
+ /* The instruction that we are simplifying or propagating into. */
+ rtx_insn *insn;
+
+ /* If FROM is nonnull, we're replacing FROM with TO, otherwise we're
+ just doing a recursive simplification. */
+ rtx from;
+ rtx to;
+
+ /* The number of times that we have replaced FROM with TO. */
+ unsigned int num_replacements;
+
+ /* A bitmask of flags that describe the result of the simplificiation;
+ see above for details. */
+ uint16_t result_flags : 16;
+
+ /* True if we should unshare TO when making the next substitution,
+ false if we can use TO itself. */
+ uint16_t should_unshare : 1;
+
+ /* True if we should call check_mem after substituting into a memory. */
+ uint16_t should_check_mems : 1;
+
+ /* True if we should call note_simplification after each simplification. */
+ uint16_t should_note_simplifications : 1;
+
+ /* For future expansion. */
+ uint16_t spare : 13;
+
+ /* Gives the reason that a substitution failed, for debug purposes. */
+ const char *failure_reason;
+};
+
+/* Try to replace FROM with TO in INSN. SHARED_P is true if TO is shared
+ with other instructions, false if INSN can use TO directly. */
+
+inline insn_propagation::insn_propagation (rtx_insn *insn, rtx from, rtx to,
+ bool shared_p)
+ : insn (insn),
+ from (from),
+ to (to),
+ num_replacements (0),
+ result_flags (0),
+ should_unshare (shared_p),
+ should_check_mems (false),
+ should_note_simplifications (false),
+ spare (0),
+ failure_reason (nullptr)
+{
+}
+
+/* Try to simplify INSN without performing a substitution. */
+
+inline insn_propagation::insn_propagation (rtx_insn *insn)
+ : insn_propagation (insn, NULL_RTX, NULL_RTX)
+{
+}
+
+extern void init_recog (void);
+extern void init_recog_no_volatile (void);
+extern int check_asm_operands (rtx);
+extern int asm_operand_ok (rtx, const char *, const char **);
+extern bool validate_change (rtx, rtx *, rtx, bool);
+extern bool validate_unshare_change (rtx, rtx *, rtx, bool);
+extern bool validate_change_xveclen (rtx, rtx *, int, bool);
+extern bool canonicalize_change_group (rtx_insn *insn, rtx x);
+extern int insn_invalid_p (rtx_insn *, bool);
+extern int verify_changes (int);
+extern void confirm_change_group (void);
+extern int apply_change_group (void);
+extern int num_validated_changes (void);
+extern void cancel_changes (int);
+extern void temporarily_undo_changes (int);
+extern void redo_changes (int);
+extern int constrain_operands (int, alternative_mask);
+extern int constrain_operands_cached (rtx_insn *, int);
+extern bool memory_address_addr_space_p (machine_mode, rtx, addr_space_t);
+#define memory_address_p(mode,addr) \
+ memory_address_addr_space_p ((mode), (addr), ADDR_SPACE_GENERIC)
+extern bool strict_memory_address_addr_space_p (machine_mode, rtx,
+ addr_space_t);
+#define strict_memory_address_p(mode,addr) \
+ strict_memory_address_addr_space_p ((mode), (addr), ADDR_SPACE_GENERIC)
+extern int validate_replace_rtx_subexp (rtx, rtx, rtx_insn *, rtx *);
+extern int validate_replace_rtx (rtx, rtx, rtx_insn *);
+extern int validate_replace_rtx_part (rtx, rtx, rtx *, rtx_insn *);
+extern int validate_replace_rtx_part_nosimplify (rtx, rtx, rtx *, rtx_insn *);
+extern void validate_replace_rtx_group (rtx, rtx, rtx_insn *);
+extern void validate_replace_src_group (rtx, rtx, rtx_insn *);
+extern bool validate_simplify_insn (rtx_insn *insn);
+extern int num_changes_pending (void);
+extern bool reg_fits_class_p (const_rtx, reg_class_t, int, machine_mode);
+extern bool valid_insn_p (rtx_insn *);
+
+extern bool offsettable_memref_p (rtx);
+extern bool offsettable_nonstrict_memref_p (rtx);
+extern bool offsettable_address_addr_space_p (int, machine_mode, rtx,
+ addr_space_t);
+#define offsettable_address_p(strict,mode,addr) \
+ offsettable_address_addr_space_p ((strict), (mode), (addr), \
+ ADDR_SPACE_GENERIC)
+extern bool mode_dependent_address_p (rtx, addr_space_t);
+
+extern int recog (rtx, rtx_insn *, int *);
+#ifndef GENERATOR_FILE
+static inline int recog_memoized (rtx_insn *insn);
+#endif
+extern void add_clobbers (rtx, int);
+extern int added_clobbers_hard_reg_p (int);
+extern void insn_extract (rtx_insn *);
+extern void extract_insn (rtx_insn *);
+extern void extract_constrain_insn (rtx_insn *insn);
+extern void extract_constrain_insn_cached (rtx_insn *);
+extern void extract_insn_cached (rtx_insn *);
+extern void preprocess_constraints (int, int, const char **,
+ operand_alternative *, rtx **);
+extern const operand_alternative *preprocess_insn_constraints (unsigned int);
+extern void preprocess_constraints (rtx_insn *);
+extern rtx_insn *peep2_next_insn (int);
+extern int peep2_regno_dead_p (int, int);
+extern int peep2_reg_dead_p (int, rtx);
+#ifdef HARD_CONST
+extern rtx peep2_find_free_register (int, int, const char *,
+ machine_mode, HARD_REG_SET *);
+#endif
+extern rtx_insn *peephole2_insns (rtx, rtx_insn *, int *);
+
+extern int store_data_bypass_p (rtx_insn *, rtx_insn *);
+extern int if_test_bypass_p (rtx_insn *, rtx_insn *);
+
+extern void copy_frame_info_to_split_insn (rtx_insn *, rtx_insn *);
+
+#ifndef GENERATOR_FILE
+/* Try recognizing the instruction INSN,
+ and return the code number that results.
+ Remember the code so that repeated calls do not
+ need to spend the time for actual rerecognition.
+
+ This function is the normal interface to instruction recognition.
+ The automatically-generated function `recog' is normally called
+ through this one. */
+
+static inline int
+recog_memoized (rtx_insn *insn)
+{
+ if (INSN_CODE (insn) < 0)
+ INSN_CODE (insn) = recog (PATTERN (insn), insn, 0);
+ return INSN_CODE (insn);
+}
+#endif
+
+/* Skip chars until the next ',' or the end of the string. This is
+ useful to skip alternatives in a constraint string. */
+static inline const char *
+skip_alternative (const char *p)
+{
+ const char *r = p;
+ while (*r != '\0' && *r != ',')
+ r++;
+ if (*r == ',')
+ r++;
+ return r;
+}
+
+/* Nonzero means volatile operands are recognized. */
+extern int volatile_ok;
+
+/* RAII class for temporarily setting volatile_ok. */
+
+class temporary_volatile_ok
+{
+public:
+ temporary_volatile_ok (int value) : save_volatile_ok (volatile_ok)
+ {
+ volatile_ok = value;
+ }
+
+ ~temporary_volatile_ok () { volatile_ok = save_volatile_ok; }
+
+private:
+ temporary_volatile_ok (const temporary_volatile_ok &);
+ int save_volatile_ok;
+};
+
+/* Set by constrain_operands to the number of the alternative that
+ matched. */
+extern int which_alternative;
+
+/* The following vectors hold the results from insn_extract. */
+
+struct recog_data_d
+{
+ /* It is very tempting to make the 5 operand related arrays into a
+ structure and index on that. However, to be source compatible
+ with all of the existing md file insn constraints and output
+ templates, we need `operand' as a flat array. Without that
+ member, making an array for the rest seems pointless. */
+
+ /* Gives value of operand N. */
+ rtx operand[MAX_RECOG_OPERANDS];
+
+ /* Gives location where operand N was found. */
+ rtx *operand_loc[MAX_RECOG_OPERANDS];
+
+ /* Gives the constraint string for operand N. */
+ const char *constraints[MAX_RECOG_OPERANDS];
+
+ /* Nonzero if operand N is a match_operator or a match_parallel. */
+ char is_operator[MAX_RECOG_OPERANDS];
+
+ /* Gives the mode of operand N. */
+ machine_mode operand_mode[MAX_RECOG_OPERANDS];
+
+ /* Gives the type (in, out, inout) for operand N. */
+ enum op_type operand_type[MAX_RECOG_OPERANDS];
+
+ /* Gives location where the Nth duplicate-appearance of an operand
+ was found. This is something that matched MATCH_DUP. */
+ rtx *dup_loc[MAX_DUP_OPERANDS];
+
+ /* Gives the operand number that was duplicated in the Nth
+ duplicate-appearance of an operand. */
+ char dup_num[MAX_DUP_OPERANDS];
+
+ /* ??? Note that these are `char' instead of `unsigned char' to (try to)
+ avoid certain lossage from K&R C, wherein `unsigned char' default
+ promotes to `unsigned int' instead of `int' as in ISO C. As of 1999,
+ the most common places to bootstrap from K&R C are SunOS and HPUX,
+ both of which have signed characters by default. The only other
+ supported natives that have both K&R C and unsigned characters are
+ ROMP and Irix 3, and neither have been seen for a while, but do
+ continue to consider unsignedness when performing arithmetic inside
+ a comparison. */
+
+ /* The number of operands of the insn. */
+ char n_operands;
+
+ /* The number of MATCH_DUPs in the insn. */
+ char n_dups;
+
+ /* The number of alternatives in the constraints for the insn. */
+ char n_alternatives;
+
+ /* True if insn is ASM_OPERANDS. */
+ bool is_asm;
+
+ /* In case we are caching, hold insn data was generated for. */
+ rtx_insn *insn;
+};
+
+extern struct recog_data_d recog_data;
+
+extern const operand_alternative *recog_op_alt;
+
+/* Return a pointer to an array in which index OP describes the constraints
+ on operand OP of the current instruction alternative (which_alternative).
+ Only valid after calling preprocess_constraints and constrain_operands. */
+
+inline static const operand_alternative *
+which_op_alt ()
+{
+ gcc_checking_assert (IN_RANGE (which_alternative, 0,
+ recog_data.n_alternatives - 1));
+ return &recog_op_alt[which_alternative * recog_data.n_operands];
+}
+
+/* A table defined in insn-output.cc that give information about
+ each insn-code value. */
+
+typedef bool (*insn_operand_predicate_fn) (rtx, machine_mode);
+typedef const char * (*insn_output_fn) (rtx *, rtx_insn *);
+
+struct insn_gen_fn
+{
+ typedef void (*stored_funcptr) (void);
+
+ template<typename ...Ts>
+ rtx_insn *operator() (Ts... args) const
+ {
+ typedef rtx_insn *(*funcptr) (decltype ((void) args, NULL_RTX)...);
+ return ((funcptr) func) (args...);
+ }
+
+ // This is for compatibility of code that invokes functions like
+ // (*funcptr) (arg)
+ insn_gen_fn operator * (void) const { return *this; }
+
+ // The wrapped function pointer must be public and there must not be any
+ // constructors. Otherwise the insn_data_d struct initializers generated
+ // by genoutput.cc will result in static initializer functions, which defeats
+ // the purpose of the generated insn_data_d array.
+ stored_funcptr func;
+};
+
+struct insn_operand_data
+{
+ const insn_operand_predicate_fn predicate;
+
+ const char *const constraint;
+
+ ENUM_BITFIELD(machine_mode) const mode : 16;
+
+ const char strict_low;
+
+ const char is_operator;
+
+ const char eliminable;
+
+ const char allows_mem;
+};
+
+/* Legal values for insn_data.output_format. Indicate what type of data
+ is stored in insn_data.output. */
+#define INSN_OUTPUT_FORMAT_NONE 0 /* abort */
+#define INSN_OUTPUT_FORMAT_SINGLE 1 /* const char * */
+#define INSN_OUTPUT_FORMAT_MULTI 2 /* const char * const * */
+#define INSN_OUTPUT_FORMAT_FUNCTION 3 /* const char * (*)(...) */
+
+struct insn_data_d
+{
+ const char *const name;
+#if HAVE_DESIGNATED_UNION_INITIALIZERS
+ union {
+ const char *single;
+ const char *const *multi;
+ insn_output_fn function;
+ } output;
+#else
+ struct {
+ const char *single;
+ const char *const *multi;
+ insn_output_fn function;
+ } output;
+#endif
+ const insn_gen_fn genfun;
+ const struct insn_operand_data *const operand;
+
+ const char n_generator_args;
+ const char n_operands;
+ const char n_dups;
+ const char n_alternatives;
+ const char output_format;
+};
+
+extern const struct insn_data_d insn_data[];
+extern int peep2_current_count;
+
+#ifndef GENERATOR_FILE
+#include "insn-codes.h"
+
+/* An enum of boolean attributes that may only depend on the current
+ subtarget, not on things like operands or compiler phase. */
+enum bool_attr {
+ BA_ENABLED,
+ BA_PREFERRED_FOR_SPEED,
+ BA_PREFERRED_FOR_SIZE,
+ BA_LAST = BA_PREFERRED_FOR_SIZE
+};
+
+/* Target-dependent globals. */
+struct target_recog {
+ bool x_initialized;
+ alternative_mask x_bool_attr_masks[NUM_INSN_CODES][BA_LAST + 1];
+ operand_alternative *x_op_alt[NUM_INSN_CODES];
+};
+
+extern struct target_recog default_target_recog;
+#if SWITCHABLE_TARGET
+extern struct target_recog *this_target_recog;
+#else
+#define this_target_recog (&default_target_recog)
+#endif
+
+alternative_mask get_enabled_alternatives (rtx_insn *);
+alternative_mask get_preferred_alternatives (rtx_insn *);
+alternative_mask get_preferred_alternatives (rtx_insn *, basic_block);
+bool check_bool_attrs (rtx_insn *);
+
+void recog_init ();
+
+/* This RAII class can help to undo tentative insn changes on failure.
+ When an object of the class goes out of scope, it undoes all group
+ changes that have been made via the validate_change machinery and
+ not yet confirmed via confirm_change_group.
+
+ For example:
+
+ insn_change_watermark watermark;
+ validate_change (..., true); // A
+ ...
+ if (test)
+ // Undoes change A.
+ return false;
+ ...
+ validate_change (..., true); // B
+ ...
+ if (test)
+ // Undoes changes A and B.
+ return false;
+ ...
+ confirm_change_group ();
+
+ Code that wants to avoid this behavior can use keep ():
+
+ insn_change_watermark watermark;
+ validate_change (..., true); // A
+ ...
+ if (test)
+ // Undoes change A.
+ return false;
+ ...
+ watermark.keep ();
+ validate_change (..., true); // B
+ ...
+ if (test)
+ // Undoes change B, but not A.
+ return false;
+ ...
+ confirm_change_group (); */
+class insn_change_watermark
+{
+public:
+ insn_change_watermark () : m_old_num_changes (num_validated_changes ()) {}
+ ~insn_change_watermark ();
+ void keep () { m_old_num_changes = num_validated_changes (); }
+
+private:
+ int m_old_num_changes;
+};
+
+inline insn_change_watermark::~insn_change_watermark ()
+{
+ if (m_old_num_changes < num_validated_changes ())
+ cancel_changes (m_old_num_changes);
+}
+
+#endif
+
+#endif /* GCC_RECOG_H */
diff --git a/support/cpp/gcc/reg-notes.def b/support/cpp/gcc/reg-notes.def
new file mode 100644
index 000000000..704bc75b0
--- /dev/null
+++ b/support/cpp/gcc/reg-notes.def
@@ -0,0 +1,249 @@
+/* Register note definitions.
+ Copyright (C) 2004-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 defines all the codes that may appear on individual
+ EXPR_LIST, INSN_LIST and INT_LIST rtxes in the REG_NOTES chain of an insn.
+ The codes are stored in the mode field of the rtx. Source files
+ define DEF_REG_NOTE appropriately before including this file.
+
+ CFA related notes meant for RTX_FRAME_RELATED_P instructions
+ should be declared with REG_CFA_NOTE macro instead of REG_NOTE. */
+
+/* Shorthand. */
+#define REG_NOTE(NAME) DEF_REG_NOTE (REG_##NAME)
+#ifndef REG_CFA_NOTE
+# define REG_CFA_NOTE(NAME) REG_NOTE (NAME)
+#endif
+
+/* REG_DEP_TRUE is used in scheduler dependencies lists to represent a
+ read-after-write dependency (i.e. a true data dependency). This is
+ here, not grouped with REG_DEP_ANTI and REG_DEP_OUTPUT, because some
+ passes use a literal 0 for it. */
+REG_NOTE (DEP_TRUE)
+
+/* The value in REG dies in this insn (i.e., it is not needed past
+ this insn). If REG is set in this insn, the REG_DEAD note may,
+ but need not, be omitted. */
+REG_NOTE (DEAD)
+
+/* The REG is autoincremented or autodecremented in this insn. */
+REG_NOTE (INC)
+
+/* Describes the insn as a whole; it says that the insn sets a
+ register to a constant value or to be equivalent to a memory
+ address. If the register is spilled to the stack then the constant
+ value should be substituted for it. The contents of the REG_EQUIV
+ is the constant value or memory address, which may be different
+ from the source of the SET although it has the same value. A
+ REG_EQUIV note may also appear on an insn which copies a register
+ parameter to a pseudo-register, if there is a memory address which
+ could be used to hold that pseudo-register throughout the function. */
+REG_NOTE (EQUIV)
+
+/* Like REG_EQUIV except that the destination is only momentarily
+ equal to the specified rtx. Therefore, it cannot be used for
+ substitution; but it can be used for cse. */
+REG_NOTE (EQUAL)
+
+/* The register is always nonnegative during the containing loop.
+ This is used in branches so that decrement and branch instructions
+ terminating on zero can be matched. There must be an insn pattern
+ in the md file named `decrement_and_branch_until_zero' or else this
+ will never be added to any instructions. */
+REG_NOTE (NONNEG)
+
+/* Identifies a register set in this insn and never used. */
+REG_NOTE (UNUSED)
+
+/* Points to a CODE_LABEL. Used by JUMP_INSNs to say that the CODE_LABEL
+ contained in the REG_LABEL_TARGET note is a possible jump target of
+ this insn. This note is an INSN_LIST. */
+REG_NOTE (LABEL_TARGET)
+
+/* Points to a CODE_LABEL. Used by any insn to say that the CODE_LABEL
+ contained in the REG_LABEL_OPERAND note is used by the insn, but as an
+ operand, not as a jump target (though it may indirectly be a jump
+ target for a later jump insn). This note is an INSN_LIST. */
+REG_NOTE (LABEL_OPERAND)
+
+/* REG_DEP_OUTPUT and REG_DEP_ANTI are used in scheduler dependencies lists
+ to represent write-after-write and write-after-read dependencies
+ respectively. */
+REG_NOTE (DEP_OUTPUT)
+REG_NOTE (DEP_ANTI)
+REG_NOTE (DEP_CONTROL)
+
+/* REG_BR_PROB is attached to JUMP_INSNs. It has an
+ integer value (in an INT_LIST). For jumps, it is the probability
+ that this is a taken branch. The integer represents a value of
+ profile_probability type. Use to_reg_br_prob_note and from_reg_br_prob_note
+ to extract the actual value. */
+REG_NOTE (BR_PROB)
+
+/* Attached to a call insn; indicates that the call is malloc-like and
+ that the pointer returned cannot alias anything else. */
+REG_NOTE (NOALIAS)
+
+/* REG_BR_PRED is attached to JUMP_INSNs. It contains
+ CONCAT of two integer value. First specifies the branch predictor
+ that added the note, second specifies the predicted hitrate of
+ branch in a fixed point arithmetic based on REG_BR_PROB_BASE. */
+REG_NOTE (BR_PRED)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for DWARF to interpret what they imply. The attached rtx is used
+ instead of intuition. */
+REG_CFA_NOTE (FRAME_RELATED_EXPR)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. The insn's first pattern must be
+ a SET, and the destination must be the CFA register. The attached
+ rtx is an expression that defines the CFA. In the simplest case, the
+ rtx could be just the stack_pointer_rtx; more common would be a PLUS
+ with a base register and a constant offset. In the most complicated
+ cases, this will result in a DW_CFA_def_cfa_expression with the rtx
+ expression rendered in a dwarf location expression. */
+REG_CFA_NOTE (CFA_DEF_CFA)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. This note adjusts the expression
+ from which the CFA is computed. The attached rtx defines a new CFA
+ expression, relative to the old CFA expression. This rtx must be of
+ the form (SET new-cfa-reg (PLUS old-cfa-reg const_int)). If the note
+ rtx is NULL, we use the first SET of the insn. */
+REG_CFA_NOTE (CFA_ADJUST_CFA)
+
+/* Similar to FRAME_RELATED_EXPR, with the additional information that
+ this is a save to memory, i.e. will result in DW_CFA_offset or the
+ like. The pattern or the insn should be a simple store relative to
+ the CFA. */
+REG_CFA_NOTE (CFA_OFFSET)
+
+/* Similar to FRAME_RELATED_EXPR, with the additional information that this
+ is a save to a register, i.e. will result in DW_CFA_register. The insn
+ or the pattern should be simple reg-reg move. */
+REG_CFA_NOTE (CFA_REGISTER)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. This is a save to memory, i.e. will
+ result in a DW_CFA_expression. The pattern or the insn should be a
+ store of a register to an arbitrary (non-validated) memory address. */
+REG_CFA_NOTE (CFA_EXPRESSION)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. The DWARF expression computes the value of
+ the given register. */
+REG_CFA_NOTE (CFA_VAL_EXPRESSION)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, with the information
+ that this is a restore operation, i.e. will result in DW_CFA_restore
+ or the like. Either the attached rtx, or the destination of the insn's
+ first pattern is the register to be restored. */
+REG_CFA_NOTE (CFA_RESTORE)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, marks insn that sets
+ vDRAP from DRAP. If vDRAP is a register, vdrap_reg is initalized
+ to the argument, if it is a MEM, it is ignored. */
+REG_CFA_NOTE (CFA_SET_VDRAP)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, indicating a window
+ save operation, i.e. will result in a DW_CFA_GNU_window_save.
+ The argument is ignored. */
+REG_CFA_NOTE (CFA_WINDOW_SAVE)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, marks the insn as
+ requiring that all queued information should be flushed *before* insn,
+ regardless of what is visible in the rtl. The argument is ignored.
+ This is normally used for a call instruction which is not exposed to
+ the rest of the compiler as a CALL_INSN. */
+REG_CFA_NOTE (CFA_FLUSH_QUEUE)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, toggling the mangling status
+ of return address. Currently it's only used by AArch64. The argument is
+ ignored. */
+REG_CFA_NOTE (CFA_TOGGLE_RA_MANGLE)
+
+/* Indicates what exception region an INSN belongs in. This is used
+ to indicate what region to which a call may throw. REGION 0
+ indicates that a call cannot throw at all. REGION -1 indicates
+ that it cannot throw, nor will it execute a non-local goto. */
+REG_NOTE (EH_REGION)
+
+/* Used by haifa-sched to save NOTE_INSN notes across scheduling. */
+REG_NOTE (SAVE_NOTE)
+
+/* Indicates that a call does not return. */
+REG_NOTE (NORETURN)
+
+/* Indicates that an indirect jump is a non-local goto instead of a
+ computed goto. */
+REG_NOTE (NON_LOCAL_GOTO)
+
+/* This kind of note is generated at each to `setjmp', and similar
+ functions that can return twice. */
+REG_NOTE (SETJMP)
+
+/* This kind of note is generated at each transactional memory
+ builtin, to indicate we need to generate transaction restart
+ edges for this insn. */
+REG_NOTE (TM)
+
+/* Indicates the cumulative offset of the stack pointer accounting
+ for pushed arguments. This will only be generated when
+ ACCUMULATE_OUTGOING_ARGS is false. */
+REG_NOTE (ARGS_SIZE)
+
+/* Used for communication between IRA and caller-save.cc, indicates
+ that the return value of a call can be used to reinitialize a
+ pseudo reg. */
+REG_NOTE (RETURNED)
+
+/* Indicates the instruction is a stack check probe that should not
+ be combined with other stack adjustments. */
+REG_NOTE (STACK_CHECK)
+
+/* Used to mark a call with the function decl called by the call.
+ The decl might not be available in the call due to splitting of the call
+ insn. This note is a SYMBOL_REF. */
+REG_NOTE (CALL_DECL)
+
+/* Indicates that the call is an untyped_call. These calls are special
+ in that they set all of the target ABI's return value registers to a
+ defined value without explicitly saying so. For example, a typical
+ untyped_call sequence has the form:
+
+ (call (mem (symbol_ref "foo")))
+ (set (reg pseudo1) (reg result1))
+ ...
+ (set (reg pseudon) (reg resultn))
+
+ The ABI specifies that result1..resultn are clobbered by the call,
+ but the RTL does not indicate that result1..resultn are the results
+ of the call. */
+REG_NOTE (UNTYPED_CALL)
+
+/* Indicate that a call should not be verified for control-flow consistency.
+ The target address of the call is assumed as a valid address and no check
+ to validate a branch to the target address is needed. The call is marked
+ when a called function has a 'notrack' attribute. This note is used by the
+ compiler when the option -fcf-protection=branch is specified. */
+REG_NOTE (CALL_NOCF_CHECK)
+
+/* The values passed to callee, for debuginfo purposes. */
+REG_NOTE (CALL_ARG_LOCATION)
diff --git a/support/cpp/gcc/regs.h b/support/cpp/gcc/regs.h
new file mode 100644
index 000000000..80060a1fc
--- /dev/null
+++ b/support/cpp/gcc/regs.h
@@ -0,0 +1,392 @@
+/* Define per-register tables for data flow info and register allocation.
+ 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/>. */
+
+#if 0 // sdcpp ndef GCC_REGS_H
+#define GCC_REGS_H
+
+#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
+
+/* When you only have the mode of a pseudo register before it has a hard
+ register chosen for it, this reports the size of each hard register
+ a pseudo in such a mode would get allocated to. A target may
+ override this. */
+
+#ifndef REGMODE_NATURAL_SIZE
+#define REGMODE_NATURAL_SIZE(MODE) UNITS_PER_WORD
+#endif
+
+/* Maximum register number used in this function, plus one. */
+
+extern int max_regno;
+
+/* REG_N_REFS and REG_N_SETS are initialized by a call to
+ regstat_init_n_sets_and_refs from the current values of
+ DF_REG_DEF_COUNT and DF_REG_USE_COUNT. REG_N_REFS and REG_N_SETS
+ should only be used if a pass need to change these values in some
+ magical way or the pass needs to have accurate values for these
+ and is not using incremental df scanning.
+
+ At the end of a pass that uses REG_N_REFS and REG_N_SETS, a call
+ should be made to regstat_free_n_sets_and_refs.
+
+ Local alloc seems to play pretty loose with these values.
+ REG_N_REFS is set to 0 if the register is used in an asm.
+ Furthermore, local_alloc calls regclass to hack both REG_N_REFS and
+ REG_N_SETS for three address insns. Other passes seem to have
+ other special values. */
+
+
+
+/* Structure to hold values for REG_N_SETS (i) and REG_N_REFS (i). */
+
+struct regstat_n_sets_and_refs_t
+{
+ int sets; /* # of times (REG n) is set */
+ int refs; /* # of times (REG n) is used or set */
+};
+
+extern struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
+
+/* Indexed by n, gives number of times (REG n) is used or set. */
+static inline int
+REG_N_REFS (int regno)
+{
+ return regstat_n_sets_and_refs[regno].refs;
+}
+
+/* Indexed by n, gives number of times (REG n) is used or set. */
+#define SET_REG_N_REFS(N,V) (regstat_n_sets_and_refs[N].refs = V)
+#define INC_REG_N_REFS(N,V) (regstat_n_sets_and_refs[N].refs += V)
+
+/* Indexed by n, gives number of times (REG n) is set. */
+static inline int
+REG_N_SETS (int regno)
+{
+ return regstat_n_sets_and_refs[regno].sets;
+}
+
+/* Indexed by n, gives number of times (REG n) is set. */
+#define SET_REG_N_SETS(N,V) (regstat_n_sets_and_refs[N].sets = V)
+#define INC_REG_N_SETS(N,V) (regstat_n_sets_and_refs[N].sets += V)
+
+/* Given a REG, return TRUE if the reg is a PARM_DECL, FALSE otherwise. */
+extern bool reg_is_parm_p (rtx);
+
+/* Functions defined in regstat.cc. */
+extern void regstat_init_n_sets_and_refs (void);
+extern void regstat_free_n_sets_and_refs (void);
+extern void regstat_compute_ri (void);
+extern void regstat_free_ri (void);
+extern bitmap regstat_get_setjmp_crosses (void);
+extern void regstat_compute_calls_crossed (void);
+extern void regstat_free_calls_crossed (void);
+extern void dump_reg_info (FILE *);
+
+/* Register information indexed by register number. This structure is
+ initialized by calling regstat_compute_ri and is destroyed by
+ calling regstat_free_ri. */
+struct reg_info_t
+{
+ int freq; /* # estimated frequency (REG n) is used or set */
+ int deaths; /* # of times (REG n) dies */
+ int calls_crossed; /* # of calls (REG n) is live across */
+ int basic_block; /* # of basic blocks (REG n) is used in */
+};
+
+extern struct reg_info_t *reg_info_p;
+
+/* The number allocated elements of reg_info_p. */
+extern size_t reg_info_p_size;
+
+/* Estimate frequency of references to register N. */
+
+#define REG_FREQ(N) (reg_info_p[N].freq)
+
+/* The weights for each insn varies from 0 to REG_FREQ_BASE.
+ This constant does not need to be high, as in infrequently executed
+ regions we want to count instructions equivalently to optimize for
+ size instead of speed. */
+#define REG_FREQ_MAX 1000
+
+/* Compute register frequency from the BB frequency. When optimizing for size,
+ or profile driven feedback is available and the function is never executed,
+ frequency is always equivalent. Otherwise rescale the basic block
+ frequency. */
+#define REG_FREQ_FROM_BB(bb) ((optimize_function_for_size_p (cfun) \
+ || !cfun->cfg->count_max.initialized_p ()) \
+ ? REG_FREQ_MAX \
+ : ((bb)->count.to_frequency (cfun) \
+ * REG_FREQ_MAX / BB_FREQ_MAX) \
+ ? ((bb)->count.to_frequency (cfun) \
+ * REG_FREQ_MAX / BB_FREQ_MAX) \
+ : 1)
+
+/* Indexed by N, gives number of insns in which register N dies.
+ Note that if register N is live around loops, it can die
+ in transitions between basic blocks, and that is not counted here.
+ So this is only a reliable indicator of how many regions of life there are
+ for registers that are contained in one basic block. */
+
+#define REG_N_DEATHS(N) (reg_info_p[N].deaths)
+
+/* Get the number of consecutive words required to hold pseudo-reg N. */
+
+#define PSEUDO_REGNO_SIZE(N) \
+ ((GET_MODE_SIZE (PSEUDO_REGNO_MODE (N)) + UNITS_PER_WORD - 1) \
+ / UNITS_PER_WORD)
+
+/* Get the number of bytes required to hold pseudo-reg N. */
+
+#define PSEUDO_REGNO_BYTES(N) \
+ GET_MODE_SIZE (PSEUDO_REGNO_MODE (N))
+
+/* Get the machine mode of pseudo-reg N. */
+
+#define PSEUDO_REGNO_MODE(N) GET_MODE (regno_reg_rtx[N])
+
+/* Indexed by N, gives number of CALL_INSNS across which (REG n) is live. */
+
+#define REG_N_CALLS_CROSSED(N) (reg_info_p[N].calls_crossed)
+
+/* Indexed by n, gives number of basic block that (REG n) is used in.
+ If the value is REG_BLOCK_GLOBAL (-1),
+ it means (REG n) is used in more than one basic block.
+ REG_BLOCK_UNKNOWN (0) means it hasn't been seen yet so we don't know.
+ This information remains valid for the rest of the compilation
+ of the current function; it is used to control register allocation. */
+
+#define REG_BLOCK_UNKNOWN 0
+#define REG_BLOCK_GLOBAL -1
+
+#define REG_BASIC_BLOCK(N) (reg_info_p[N].basic_block)
+
+/* Vector of substitutions of register numbers,
+ used to map pseudo regs into hardware regs.
+
+ This can't be folded into reg_n_info without changing all of the
+ machine dependent directories, since the reload functions
+ in the machine dependent files access it. */
+
+extern short *reg_renumber;
+
+/* Flag set by local-alloc or global-alloc if they decide to allocate
+ something in a call-clobbered register. */
+
+extern int caller_save_needed;
+
+/* Select a register mode required for caller save of hard regno REGNO. */
+#ifndef HARD_REGNO_CALLER_SAVE_MODE
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+ choose_hard_reg_mode (REGNO, NREGS, NULL)
+#endif
+
+/* Target-dependent globals. */
+struct target_regs {
+ /* For each starting hard register, the number of consecutive hard
+ registers that a given machine mode occupies. */
+ unsigned char x_hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
+
+ /* The max value found in x_hard_regno_nregs. */
+ unsigned char x_hard_regno_max_nregs;
+
+ /* For each hard register, the widest mode object that it can contain.
+ This will be a MODE_INT mode if the register can hold integers. Otherwise
+ it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
+ register. */
+ machine_mode x_reg_raw_mode[FIRST_PSEUDO_REGISTER];
+
+ /* Vector indexed by machine mode saying whether there are regs of
+ that mode. */
+ bool x_have_regs_of_mode[MAX_MACHINE_MODE];
+
+ /* 1 if the corresponding class contains a register of the given mode. */
+ char x_contains_reg_of_mode[N_REG_CLASSES][MAX_MACHINE_MODE];
+
+ /* 1 if the corresponding class contains a register of the given mode
+ which is not global and can therefore be allocated. */
+ char x_contains_allocatable_reg_of_mode[N_REG_CLASSES][MAX_MACHINE_MODE];
+
+ /* Record for each mode whether we can move a register directly to or
+ from an object of that mode in memory. If we can't, we won't try
+ to use that mode directly when accessing a field of that mode. */
+ char x_direct_load[NUM_MACHINE_MODES];
+ char x_direct_store[NUM_MACHINE_MODES];
+
+ /* Record for each mode whether we can float-extend from memory. */
+ bool x_float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+};
+
+extern struct target_regs default_target_regs;
+#if SWITCHABLE_TARGET
+extern struct target_regs *this_target_regs;
+#else
+#define this_target_regs (&default_target_regs)
+#endif
+#define hard_regno_max_nregs \
+ (this_target_regs->x_hard_regno_max_nregs)
+#define reg_raw_mode \
+ (this_target_regs->x_reg_raw_mode)
+#define have_regs_of_mode \
+ (this_target_regs->x_have_regs_of_mode)
+#define contains_reg_of_mode \
+ (this_target_regs->x_contains_reg_of_mode)
+#define contains_allocatable_reg_of_mode \
+ (this_target_regs->x_contains_allocatable_reg_of_mode)
+#define direct_load \
+ (this_target_regs->x_direct_load)
+#define direct_store \
+ (this_target_regs->x_direct_store)
+#define float_extend_from_mem \
+ (this_target_regs->x_float_extend_from_mem)
+
+/* Return the number of hard registers in (reg:MODE REGNO). */
+
+ALWAYS_INLINE unsigned char
+hard_regno_nregs (unsigned int regno, machine_mode mode)
+{
+ return this_target_regs->x_hard_regno_nregs[regno][mode];
+}
+
+/* Return an exclusive upper bound on the registers occupied by hard
+ register (reg:MODE REGNO). */
+
+static inline unsigned int
+end_hard_regno (machine_mode mode, unsigned int regno)
+{
+ return regno + hard_regno_nregs (regno, mode);
+}
+
+/* Add to REGS all the registers required to store a value of mode MODE
+ in register REGNO. */
+
+static inline void
+add_to_hard_reg_set (HARD_REG_SET *regs, machine_mode mode,
+ unsigned int regno)
+{
+ unsigned int end_regno;
+
+ end_regno = end_hard_regno (mode, regno);
+ do
+ SET_HARD_REG_BIT (*regs, regno);
+ while (++regno < end_regno);
+}
+
+/* Likewise, but remove the registers. */
+
+static inline void
+remove_from_hard_reg_set (HARD_REG_SET *regs, machine_mode mode,
+ unsigned int regno)
+{
+ unsigned int end_regno;
+
+ end_regno = end_hard_regno (mode, regno);
+ do
+ CLEAR_HARD_REG_BIT (*regs, regno);
+ while (++regno < end_regno);
+}
+
+/* Return true if REGS contains the whole of (reg:MODE REGNO). */
+
+static inline bool
+in_hard_reg_set_p (const_hard_reg_set regs, machine_mode mode,
+ unsigned int regno)
+{
+ unsigned int end_regno;
+
+ gcc_assert (HARD_REGISTER_NUM_P (regno));
+
+ if (!TEST_HARD_REG_BIT (regs, regno))
+ return false;
+
+ end_regno = end_hard_regno (mode, regno);
+
+ if (!HARD_REGISTER_NUM_P (end_regno - 1))
+ return false;
+
+ while (++regno < end_regno)
+ if (!TEST_HARD_REG_BIT (regs, regno))
+ return false;
+
+ return true;
+}
+
+/* Return true if (reg:MODE REGNO) includes an element of REGS. */
+
+static inline bool
+overlaps_hard_reg_set_p (const_hard_reg_set regs, machine_mode mode,
+ unsigned int regno)
+{
+ unsigned int end_regno;
+
+ if (TEST_HARD_REG_BIT (regs, regno))
+ return true;
+
+ end_regno = end_hard_regno (mode, regno);
+ while (++regno < end_regno)
+ if (TEST_HARD_REG_BIT (regs, regno))
+ return true;
+
+ return false;
+}
+
+/* Like add_to_hard_reg_set, but use a REGNO/NREGS range instead of
+ REGNO and MODE. */
+
+static inline void
+add_range_to_hard_reg_set (HARD_REG_SET *regs, unsigned int regno,
+ int nregs)
+{
+ while (nregs-- > 0)
+ SET_HARD_REG_BIT (*regs, regno + nregs);
+}
+
+/* Likewise, but remove the registers. */
+
+static inline void
+remove_range_from_hard_reg_set (HARD_REG_SET *regs, unsigned int regno,
+ int nregs)
+{
+ while (nregs-- > 0)
+ CLEAR_HARD_REG_BIT (*regs, regno + nregs);
+}
+
+/* Like overlaps_hard_reg_set_p, but use a REGNO/NREGS range instead of
+ REGNO and MODE. */
+static inline bool
+range_overlaps_hard_reg_set_p (const_hard_reg_set set, unsigned regno,
+ int nregs)
+{
+ while (nregs-- > 0)
+ if (TEST_HARD_REG_BIT (set, regno + nregs))
+ return true;
+ return false;
+}
+
+/* Like in_hard_reg_set_p, but use a REGNO/NREGS range instead of
+ REGNO and MODE. */
+static inline bool
+range_in_hard_reg_set_p (const_hard_reg_set set, unsigned regno, int nregs)
+{
+ while (nregs-- > 0)
+ if (!TEST_HARD_REG_BIT (set, regno + nregs))
+ return false;
+ return true;
+}
+
+#endif /* GCC_REGS_H */
diff --git a/support/cpp/gcc/regset.h b/support/cpp/gcc/regset.h
new file mode 100644
index 000000000..005353806
--- /dev/null
+++ b/support/cpp/gcc/regset.h
@@ -0,0 +1,123 @@
+/* Define regsets.
+ 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/>. */
+
+#ifndef GCC_REGSET_H
+#define GCC_REGSET_H
+
+/* TODO: regset is just a bitmap in its implementation. The compiler does
+ not consistently use one or the other, i.e. sometimes variables are
+ declared as bitmap but they are actually regsets and regset accessors
+ are used, and vice versa, or mixed (see e.g. spilled_regs in IRA).
+
+ This should be cleaned up, either by just dropping the regset type, or
+ by changing all bitmaps that are really regsets to the regset type. For
+ the latter option, a good start would be to change everything allocated
+ on the reg_obstack to regset. */
+
+
+/* Head of register set linked list. */
+typedef bitmap_head regset_head;
+
+/* A pointer to a regset_head. */
+typedef bitmap regset;
+
+/* Allocate a register set with oballoc. */
+#define ALLOC_REG_SET(OBSTACK) BITMAP_ALLOC (OBSTACK)
+
+/* Do any cleanup needed on a regset when it is no longer used. */
+#define FREE_REG_SET(REGSET) BITMAP_FREE (REGSET)
+
+/* Initialize a new regset. */
+#define INIT_REG_SET(HEAD) bitmap_initialize (HEAD, &reg_obstack)
+
+/* Clear a register set by freeing up the linked list. */
+#define CLEAR_REG_SET(HEAD) bitmap_clear (HEAD)
+
+/* True if the register set is empty. */
+#define REG_SET_EMPTY_P(HEAD) bitmap_empty_p (HEAD)
+
+/* Copy a register set to another register set. */
+#define COPY_REG_SET(TO, FROM) bitmap_copy (TO, FROM)
+
+/* Compare two register sets. */
+#define REG_SET_EQUAL_P(A, B) bitmap_equal_p (A, B)
+
+/* `and' a register set with a second register set. */
+#define AND_REG_SET(TO, FROM) bitmap_and_into (TO, FROM)
+
+/* `and' the complement of a register set with a register set. */
+#define AND_COMPL_REG_SET(TO, FROM) bitmap_and_compl_into (TO, FROM)
+
+/* Inclusive or a register set with a second register set. */
+#define IOR_REG_SET(TO, FROM) bitmap_ior_into (TO, FROM)
+
+/* Same, but with FROM being a HARD_REG_SET. */
+#define IOR_REG_SET_HRS(TO, FROM) \
+ bitmap_ior_into (TO, bitmap_view<HARD_REG_SET> (FROM))
+
+/* Exclusive or a register set with a second register set. */
+#define XOR_REG_SET(TO, FROM) bitmap_xor_into (TO, FROM)
+
+/* Or into TO the register set FROM1 `and'ed with the complement of FROM2. */
+#define IOR_AND_COMPL_REG_SET(TO, FROM1, FROM2) \
+ bitmap_ior_and_compl_into (TO, FROM1, FROM2)
+
+/* Clear a single register in a register set. */
+#define CLEAR_REGNO_REG_SET(HEAD, REG) bitmap_clear_bit (HEAD, REG)
+
+/* Set a single register in a register set. */
+#define SET_REGNO_REG_SET(HEAD, REG) bitmap_set_bit (HEAD, REG)
+
+/* Return true if a register is set in a register set. */
+#define REGNO_REG_SET_P(TO, REG) bitmap_bit_p (TO, REG)
+
+/* Copy the hard registers in a register set to the hard register set. */
+extern void reg_set_to_hard_reg_set (HARD_REG_SET *, const_bitmap);
+#define REG_SET_TO_HARD_REG_SET(TO, FROM) \
+do { \
+ CLEAR_HARD_REG_SET (TO); \
+ reg_set_to_hard_reg_set (&TO, FROM); \
+} while (0)
+
+typedef bitmap_iterator reg_set_iterator;
+
+/* Loop over all registers in REGSET, starting with MIN, setting REGNUM to the
+ register number and executing CODE for all registers that are set. */
+#define EXECUTE_IF_SET_IN_REG_SET(REGSET, MIN, REGNUM, RSI) \
+ EXECUTE_IF_SET_IN_BITMAP (REGSET, MIN, REGNUM, RSI)
+
+/* Loop over all registers in REGSET1 and REGSET2, starting with MIN, setting
+ REGNUM to the register number and executing CODE for all registers that are
+ set in the first regset and not set in the second. */
+#define EXECUTE_IF_AND_COMPL_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, RSI) \
+ EXECUTE_IF_AND_COMPL_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, RSI)
+
+/* Loop over all registers in REGSET1 and REGSET2, starting with MIN, setting
+ REGNUM to the register number and executing CODE for all registers that are
+ set in both regsets. */
+#define EXECUTE_IF_AND_IN_REG_SET(REGSET1, REGSET2, MIN, REGNUM, RSI) \
+ EXECUTE_IF_AND_IN_BITMAP (REGSET1, REGSET2, MIN, REGNUM, RSI) \
+
+/* An obstack for regsets. */
+extern bitmap_obstack reg_obstack;
+
+/* In df-core.cc (which should use regset consistently instead of bitmap...) */
+extern void dump_regset (regset, FILE *);
+
+#endif /* GCC_REGSET_H */
diff --git a/support/cpp/gcc/reload.h b/support/cpp/gcc/reload.h
new file mode 100644
index 000000000..2e4bc74fa
--- /dev/null
+++ b/support/cpp/gcc/reload.h
@@ -0,0 +1,466 @@
+/* Communication between reload.cc, reload1.cc and the rest of 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/>. */
+
+#if 0 // sdcpp ndef GCC_RELOAD_H
+#define GCC_RELOAD_H
+
+/* If secondary reloads are the same for inputs and outputs, define those
+ macros here. */
+
+#ifdef SECONDARY_RELOAD_CLASS
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ SECONDARY_RELOAD_CLASS (CLASS, MODE, X)
+#endif
+
+extern int register_move_cost (machine_mode, reg_class_t, reg_class_t);
+extern int memory_move_cost (machine_mode, reg_class_t, bool);
+extern int memory_move_secondary_cost (machine_mode, reg_class_t, bool);
+
+/* Maximum number of reloads we can need. */
+#define MAX_RELOADS (2 * MAX_RECOG_OPERANDS * (MAX_REGS_PER_ADDRESS + 1))
+
+/* Encode the usage of a reload. The following codes are supported:
+
+ RELOAD_FOR_INPUT reload of an input operand
+ RELOAD_FOR_OUTPUT likewise, for output
+ RELOAD_FOR_INSN a reload that must not conflict with anything
+ used in the insn, but may conflict with
+ something used before or after the insn
+ RELOAD_FOR_INPUT_ADDRESS reload for parts of the address of an object
+ that is an input reload
+ RELOAD_FOR_INPADDR_ADDRESS reload needed for RELOAD_FOR_INPUT_ADDRESS
+ RELOAD_FOR_OUTPUT_ADDRESS like RELOAD_FOR INPUT_ADDRESS, for output
+ RELOAD_FOR_OUTADDR_ADDRESS reload needed for RELOAD_FOR_OUTPUT_ADDRESS
+ RELOAD_FOR_OPERAND_ADDRESS reload for the address of a non-reloaded
+ operand; these don't conflict with
+ any other addresses.
+ RELOAD_FOR_OPADDR_ADDR reload needed for RELOAD_FOR_OPERAND_ADDRESS
+ reloads; usually secondary reloads
+ RELOAD_OTHER none of the above, usually multiple uses
+ RELOAD_FOR_OTHER_ADDRESS reload for part of the address of an input
+ that is marked RELOAD_OTHER.
+
+ This used to be "enum reload_when_needed" but some debuggers have trouble
+ with an enum tag and variable of the same name. */
+
+enum reload_type
+{
+ RELOAD_FOR_INPUT, RELOAD_FOR_OUTPUT, RELOAD_FOR_INSN,
+ RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_INPADDR_ADDRESS,
+ RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS,
+ RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OPADDR_ADDR,
+ RELOAD_OTHER, RELOAD_FOR_OTHER_ADDRESS
+};
+
+#ifdef GCC_INSN_CODES_H
+/* Each reload is recorded with a structure like this. */
+struct reload
+{
+ /* The value to reload from */
+ rtx in;
+ /* Where to store reload-reg afterward if nec (often the same as
+ reload_in) */
+ rtx out;
+
+ /* The class of registers to reload into. */
+ enum reg_class rclass;
+
+ /* The mode this operand should have when reloaded, on input. */
+ machine_mode inmode;
+ /* The mode this operand should have when reloaded, on output. */
+ machine_mode outmode;
+
+ /* The mode of the reload register. */
+ machine_mode mode;
+
+ /* the largest number of registers this reload will require. */
+ unsigned int nregs;
+
+ /* Positive amount to increment or decrement by if
+ reload_in is a PRE_DEC, PRE_INC, POST_DEC, POST_INC.
+ Ignored otherwise (don't assume it is zero). */
+ poly_int64_pod inc;
+ /* A reg for which reload_in is the equivalent.
+ If reload_in is a symbol_ref which came from
+ reg_equiv_constant, then this is the pseudo
+ which has that symbol_ref as equivalent. */
+ rtx in_reg;
+ rtx out_reg;
+
+ /* Used in find_reload_regs to record the allocated register. */
+ int regno;
+ /* This is the register to reload into. If it is zero when `find_reloads'
+ returns, you must find a suitable register in the class specified by
+ reload_reg_class, and store here an rtx for that register with mode from
+ reload_inmode or reload_outmode. */
+ rtx reg_rtx;
+ /* The operand number being reloaded. This is used to group related reloads
+ and need not always be equal to the actual operand number in the insn,
+ though it current will be; for in-out operands, it is one of the two
+ operand numbers. */
+ int opnum;
+
+ /* Gives the reload number of a secondary input reload, when needed;
+ otherwise -1. */
+ int secondary_in_reload;
+ /* Gives the reload number of a secondary output reload, when needed;
+ otherwise -1. */
+ int secondary_out_reload;
+ /* If a secondary input reload is required, gives the INSN_CODE that uses the
+ secondary reload as a scratch register, or CODE_FOR_nothing if the
+ secondary reload register is to be an intermediate register. */
+ enum insn_code secondary_in_icode;
+ /* Likewise, for a secondary output reload. */
+ enum insn_code secondary_out_icode;
+
+ /* Classifies reload as needed either for addressing an input reload,
+ addressing an output, for addressing a non-reloaded mem ref, or for
+ unspecified purposes (i.e., more than one of the above). */
+ enum reload_type when_needed;
+
+ /* Nonzero for an optional reload. Optional reloads are ignored unless the
+ value is already sitting in a register. */
+ unsigned int optional:1;
+ /* nonzero if this reload shouldn't be combined with another reload. */
+ unsigned int nocombine:1;
+ /* Nonzero if this is a secondary register for one or more reloads. */
+ unsigned int secondary_p:1;
+ /* Nonzero if this reload must use a register not already allocated to a
+ group. */
+ unsigned int nongroup:1;
+};
+
+extern struct reload rld[MAX_RELOADS];
+extern int n_reloads;
+#endif
+
+/* Target-dependent globals. */
+struct target_reload {
+ /* Nonzero if indirect addressing is supported when the innermost MEM is
+ of the form (MEM (SYMBOL_REF sym)). It is assumed that the level to
+ which these are valid is the same as spill_indirect_levels, above. */
+ bool x_indirect_symref_ok;
+
+ /* Nonzero if indirect addressing is supported on the machine; this means
+ that spilling (REG n) does not require reloading it into a register in
+ order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))). The
+ value indicates the level of indirect addressing supported, e.g., two
+ means that (MEM (MEM (REG n))) is also valid if (REG n) does not get
+ a hard register. */
+ unsigned char x_spill_indirect_levels;
+
+ /* True if caller-save has been reinitialized. */
+ bool x_caller_save_initialized_p;
+
+ /* Modes for each hard register that we can save. The smallest mode is wide
+ enough to save the entire contents of the register. When saving the
+ register because it is live we first try to save in multi-register modes.
+ If that is not possible the save is done one register at a time. */
+ machine_mode (x_regno_save_mode
+ [FIRST_PSEUDO_REGISTER]
+ [MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1]);
+
+ /* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid
+ in the given mode. */
+ bool x_double_reg_address_ok[MAX_MACHINE_MODE];
+
+ /* We will only make a register eligible for caller-save if it can be
+ saved in its widest mode with a simple SET insn as long as the memory
+ address is valid. We record the INSN_CODE is those insns here since
+ when we emit them, the addresses might not be valid, so they might not
+ be recognized. */
+ int x_cached_reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
+ int x_cached_reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
+};
+
+extern struct target_reload default_target_reload;
+#if SWITCHABLE_TARGET
+extern struct target_reload *this_target_reload;
+#else
+#define this_target_reload (&default_target_reload)
+#endif
+
+#define indirect_symref_ok \
+ (this_target_reload->x_indirect_symref_ok)
+#define double_reg_address_ok \
+ (this_target_reload->x_double_reg_address_ok)
+#define caller_save_initialized_p \
+ (this_target_reload->x_caller_save_initialized_p)
+
+/* Register equivalences. Indexed by register number. */
+struct reg_equivs_t
+{
+ /* The constant value to which pseudo reg N is equivalent,
+ or zero if pseudo reg N is not equivalent to a constant.
+ find_reloads looks at this in order to replace pseudo reg N
+ with the constant it stands for. */
+ rtx constant;
+
+ /* An invariant value to which pseudo reg N is equivalent.
+ eliminate_regs_in_insn uses this to replace pseudos in particular
+ contexts. */
+ rtx invariant;
+
+ /* A memory location to which pseudo reg N is equivalent,
+ prior to any register elimination (such as frame pointer to stack
+ pointer). Depending on whether or not it is a valid address, this value
+ is transferred to either equiv_address or equiv_mem. */
+ rtx memory_loc;
+
+ /* The address of stack slot to which pseudo reg N is equivalent.
+ This is used when the address is not valid as a memory address
+ (because its displacement is too big for the machine.) */
+ rtx address;
+
+ /* The memory slot to which pseudo reg N is equivalent,
+ or zero if pseudo reg N is not equivalent to a memory slot. */
+ rtx mem;
+
+ /* An EXPR_LIST of REG_EQUIVs containing MEMs with
+ alternate representations of the location of pseudo reg N. */
+ rtx_expr_list *alt_mem_list;
+
+ /* The list of insns that initialized reg N from its equivalent
+ constant or memory slot. */
+ rtx_insn_list *init;
+};
+
+#define reg_equiv_constant(ELT) \
+ (*reg_equivs)[(ELT)].constant
+#define reg_equiv_invariant(ELT) \
+ (*reg_equivs)[(ELT)].invariant
+#define reg_equiv_memory_loc(ELT) \
+ (*reg_equivs)[(ELT)].memory_loc
+#define reg_equiv_address(ELT) \
+ (*reg_equivs)[(ELT)].address
+#define reg_equiv_mem(ELT) \
+ (*reg_equivs)[(ELT)].mem
+#define reg_equiv_alt_mem_list(ELT) \
+ (*reg_equivs)[(ELT)].alt_mem_list
+#define reg_equiv_init(ELT) \
+ (*reg_equivs)[(ELT)].init
+
+extern vec<reg_equivs_t, va_gc> *reg_equivs;
+
+/* All the "earlyclobber" operands of the current insn
+ are recorded here. */
+extern int n_earlyclobbers;
+extern rtx reload_earlyclobbers[MAX_RECOG_OPERANDS];
+
+/* Save the number of operands. */
+extern int reload_n_operands;
+
+/* First uid used by insns created by reload in this function.
+ Used in find_equiv_reg. */
+extern int reload_first_uid;
+
+extern int num_not_at_initial_offset;
+
+#if defined HARD_CONST && defined CLEAR_REG_SET
+/* This structure describes instructions which are relevant for reload.
+ Apart from all regular insns, this also includes CODE_LABELs, since they
+ must be examined for register elimination. */
+class insn_chain
+{
+public:
+ /* Links to the neighbor instructions. */
+ class insn_chain *next, *prev;
+
+ /* Link through a chains set up by calculate_needs_all_insns, containing
+ all insns that need reloading. */
+ class insn_chain *next_need_reload;
+
+ /* The rtx of the insn. */
+ rtx_insn *insn;
+
+ /* The basic block this insn is in. */
+ int block;
+
+ /* Nonzero if find_reloads said the insn requires reloading. */
+ unsigned int need_reload:1;
+ /* Nonzero if find_reloads needs to be run during reload_as_needed to
+ perform modifications on any operands. */
+ unsigned int need_operand_change:1;
+ /* Nonzero if eliminate_regs_in_insn said it requires eliminations. */
+ unsigned int need_elim:1;
+ /* Nonzero if this insn was inserted by perform_caller_saves. */
+ unsigned int is_caller_save_insn:1;
+
+ /* Register life information: record all live hard registers, and
+ all live pseudos that have a hard register. This set also
+ contains pseudos spilled by IRA. */
+ bitmap_head live_throughout;
+ bitmap_head dead_or_set;
+
+ /* Copies of the global variables computed by find_reloads. */
+ struct reload *rld;
+ int n_reloads;
+
+ /* Indicates which registers have already been used for spills. */
+ HARD_REG_SET used_spill_regs;
+};
+
+/* A chain of insn_chain structures to describe all non-note insns in
+ a function. */
+extern class insn_chain *reload_insn_chain;
+
+/* Allocate a new insn_chain structure. */
+extern class insn_chain *new_insn_chain (void);
+#endif
+
+#if defined HARD_CONST
+extern void compute_use_by_pseudos (HARD_REG_SET *, bitmap);
+#endif
+
+/* Functions from reload.cc: */
+
+extern reg_class_t secondary_reload_class (bool, reg_class_t,
+ machine_mode, rtx);
+
+#ifdef GCC_INSN_CODES_H
+extern enum reg_class scratch_reload_class (enum insn_code);
+#endif
+
+/* Return a memory location that will be used to copy X in mode MODE.
+ If we haven't already made a location for this mode in this insn,
+ call find_reloads_address on the location being returned. */
+extern rtx get_secondary_mem (rtx, machine_mode, int, enum reload_type);
+
+/* Clear any secondary memory locations we've made. */
+extern void clear_secondary_mem (void);
+
+/* Transfer all replacements that used to be in reload FROM to be in
+ reload TO. */
+extern void transfer_replacements (int, int);
+
+/* IN_RTX is the value loaded by a reload that we now decided to inherit,
+ or a subpart of it. If we have any replacements registered for IN_RTX,
+ cancel the reloads that were supposed to load them.
+ Return nonzero if we canceled any reloads. */
+extern int remove_address_replacements (rtx in_rtx);
+
+/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
+ if they are the same hard reg, and has special hacks for
+ autoincrement and autodecrement. */
+extern int operands_match_p (rtx, rtx);
+
+/* Return 1 if altering OP will not modify the value of CLOBBER. */
+extern int safe_from_earlyclobber (rtx, rtx);
+
+/* Search the body of INSN for values that need reloading and record them
+ with push_reload. REPLACE nonzero means record also where the values occur
+ so that subst_reloads can be used. */
+extern int find_reloads (rtx_insn *, int, int, int, short *);
+
+/* Compute the sum of X and Y, making canonicalizations assumed in an
+ address, namely: sum constant integers, surround the sum of two
+ constants with a CONST, put the constant as the second operand, and
+ group the constant on the outermost sum. */
+extern rtx form_sum (machine_mode, rtx, rtx);
+
+/* Substitute into the current INSN the registers into which we have reloaded
+ the things that need reloading. */
+extern void subst_reloads (rtx_insn *);
+
+/* Make a copy of any replacements being done into X and move those copies
+ to locations in Y, a copy of X. We only look at the highest level of
+ the RTL. */
+extern void copy_replacements (rtx, rtx);
+
+/* Change any replacements being done to *X to be done to *Y */
+extern void move_replacements (rtx *x, rtx *y);
+
+/* If LOC was scheduled to be replaced by something, return the replacement.
+ Otherwise, return *LOC. */
+extern rtx find_replacement (rtx *);
+
+/* Nonzero if modifying X will affect IN. */
+extern int reg_overlap_mentioned_for_reload_p (rtx, rtx);
+
+/* Check the insns before INSN to see if there is a suitable register
+ containing the same value as GOAL. */
+extern rtx find_equiv_reg (rtx, rtx_insn *, enum reg_class, int, short *,
+ int, machine_mode);
+
+/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */
+extern int regno_clobbered_p (unsigned int, rtx_insn *, machine_mode, int);
+
+/* Return 1 if X is an operand of an insn that is being earlyclobbered. */
+extern int earlyclobber_operand_p (rtx);
+
+/* Record one reload that needs to be performed. */
+extern int push_reload (rtx, rtx, rtx *, rtx *, enum reg_class,
+ machine_mode, machine_mode,
+ int, int, int, enum reload_type);
+
+/* Functions in reload1.cc: */
+
+/* Initialize the reload pass once per compilation. */
+extern void init_reload (void);
+
+/* The reload pass itself. */
+extern bool reload (rtx_insn *, int);
+
+/* Mark the slots in regs_ever_live for the hard regs
+ used by pseudo-reg number REGNO. */
+extern void mark_home_live (int);
+
+/* Scan X and replace any eliminable registers (such as fp) with a
+ replacement (such as sp), plus an offset. */
+extern rtx eliminate_regs (rtx, machine_mode, rtx);
+extern bool elimination_target_reg_p (rtx);
+
+/* Called from the register allocator to estimate costs of eliminating
+ invariant registers. */
+extern void calculate_elim_costs_all_insns (void);
+
+/* Deallocate the reload register used by reload number R. */
+extern void deallocate_reload_reg (int r);
+
+/* Functions in caller-save.cc: */
+
+/* Initialize for caller-save. */
+extern void init_caller_save (void);
+
+/* Initialize save areas by showing that we haven't allocated any yet. */
+extern void init_save_areas (void);
+
+/* Allocate save areas for any hard registers that might need saving. */
+extern void setup_save_areas (void);
+
+/* Find the places where hard regs are live across calls and save them. */
+extern void save_call_clobbered_regs (void);
+
+/* Replace (subreg (reg)) with the appropriate (reg) for any operands. */
+extern void cleanup_subreg_operands (rtx_insn *);
+
+/* Debugging support. */
+extern void debug_reload_to_stream (FILE *);
+extern void debug_reload (void);
+
+/* Compute the actual register we should reload to, in case we're
+ reloading to/from a register that is wider than a word. */
+extern rtx reload_adjust_reg_for_mode (rtx, machine_mode);
+
+/* Allocate or grow the reg_equiv tables, initializing new entries to 0. */
+extern void grow_reg_equivs (void);
+
+#endif /* GCC_RELOAD_H */
diff --git a/support/cpp/gcc/resource.h b/support/cpp/gcc/resource.h
new file mode 100644
index 000000000..43ac571cb
--- /dev/null
+++ b/support/cpp/gcc/resource.h
@@ -0,0 +1,55 @@
+/* Definitions for computing resource usage of specific insns.
+ 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.
+
+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_RESOURCE_H
+#define GCC_RESOURCE_H
+
+/* Macro to clear all resources. */
+#define CLEAR_RESOURCE(RES) \
+ do { (RES)->memory = (RES)->volatil = (RES)->cc = 0; \
+ CLEAR_HARD_REG_SET ((RES)->regs); } while (0)
+
+/* The resources used by a given insn. */
+struct resources
+{
+ char memory; /* Insn sets or needs a memory location. */
+ char volatil; /* Insn sets or needs a volatile memory loc. */
+ char cc; /* Insn sets or needs the condition codes. */
+ HARD_REG_SET regs; /* Which registers are set or needed. */
+};
+
+/* The kinds of rtl mark_*_resources will consider */
+enum mark_resource_type
+{
+ MARK_SRC_DEST = 0,
+ MARK_SRC_DEST_CALL = 1
+};
+
+extern void mark_target_live_regs (rtx_insn *, rtx, struct resources *);
+extern void mark_set_resources (rtx, struct resources *, int,
+ enum mark_resource_type);
+extern void mark_referenced_resources (rtx, struct resources *, bool);
+extern void clear_hashed_info_for_insn (rtx_insn *);
+extern void clear_hashed_info_until_next_barrier (rtx_insn *);
+extern void incr_ticks_for_insn (rtx_insn *);
+extern void mark_end_of_function_resources (rtx, bool);
+extern void init_resource_info (rtx_insn *);
+extern void free_resource_info (void);
+
+#endif /* GCC_RESOURCE_H */
diff --git a/support/cpp/gcc/rtl-iter.h b/support/cpp/gcc/rtl-iter.h
new file mode 100644
index 000000000..320657c16
--- /dev/null
+++ b/support/cpp/gcc/rtl-iter.h
@@ -0,0 +1,292 @@
+/* RTL iterators
+ Copyright (C) 2014-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 structure describes the subrtxes of an rtx as follows:
+
+ - if the rtx has no subrtxes, START and COUNT are both 0.
+
+ - if all the subrtxes of an rtx are stored in a contiguous block
+ of XEXPs ("e"s), START is the index of the first XEXP and COUNT
+ is the number of them.
+
+ - otherwise START is arbitrary and COUNT is UCHAR_MAX.
+
+ rtx_all_subrtx_bounds applies to all codes. rtx_nonconst_subrtx_bounds
+ is like rtx_all_subrtx_bounds except that all constant rtxes are treated
+ as having no subrtxes. */
+struct rtx_subrtx_bound_info {
+ unsigned char start;
+ unsigned char count;
+};
+extern rtx_subrtx_bound_info rtx_all_subrtx_bounds[];
+extern rtx_subrtx_bound_info rtx_nonconst_subrtx_bounds[];
+
+/* Return true if CODE has no subrtxes. */
+
+static inline bool
+leaf_code_p (enum rtx_code code)
+{
+ return rtx_all_subrtx_bounds[code].count == 0;
+}
+
+/* Used to iterate over subrtxes of an rtx. T abstracts the type of
+ access. */
+template <typename T>
+class generic_subrtx_iterator
+{
+ static const size_t LOCAL_ELEMS = 16;
+ typedef typename T::value_type value_type;
+ typedef typename T::rtx_type rtx_type;
+ typedef typename T::rtunion_type rtunion_type;
+
+public:
+ class array_type
+ {
+ public:
+ array_type ();
+ ~array_type ();
+ value_type stack[LOCAL_ELEMS];
+ vec <value_type, va_heap, vl_embed> *heap;
+ };
+ generic_subrtx_iterator (array_type &, value_type,
+ const rtx_subrtx_bound_info *);
+
+ value_type operator * () const;
+ bool at_end () const;
+ void next ();
+ void skip_subrtxes ();
+ void substitute (value_type);
+
+private:
+ /* The bounds to use for iterating over subrtxes. */
+ const rtx_subrtx_bound_info *m_bounds;
+
+ /* The storage used for the worklist. */
+ array_type &m_array;
+
+ /* The current rtx. */
+ value_type m_current;
+
+ /* The base of the current worklist. */
+ value_type *m_base;
+
+ /* The number of subrtxes in M_BASE. */
+ size_t m_end;
+
+ /* The following booleans shouldn't end up in registers or memory
+ but just direct control flow. */
+
+ /* True if the iteration is over. */
+ bool m_done;
+
+ /* True if we should skip the subrtxes of M_CURRENT. */
+ bool m_skip;
+
+ /* True if M_CURRENT has been replaced with a different rtx. */
+ bool m_substitute;
+
+ static void free_array (array_type &);
+ static size_t add_subrtxes_to_queue (array_type &, value_type *, size_t,
+ rtx_type);
+ static value_type *add_single_to_queue (array_type &, value_type *, size_t,
+ value_type);
+};
+
+template <typename T>
+inline generic_subrtx_iterator <T>::array_type::array_type () : heap (0) {}
+
+template <typename T>
+inline generic_subrtx_iterator <T>::array_type::~array_type ()
+{
+ if (__builtin_expect (heap != 0, false))
+ free_array (*this);
+}
+
+/* Iterate over X and its subrtxes, in arbitrary order. Use ARRAY to
+ store the worklist. We use an external array in order to avoid
+ capturing the fields of this structure when taking the address of
+ the array. Use BOUNDS to find the bounds of simple "e"-string codes. */
+
+template <typename T>
+inline generic_subrtx_iterator <T>::
+generic_subrtx_iterator (array_type &array, value_type x,
+ const rtx_subrtx_bound_info *bounds)
+ : m_bounds (bounds),
+ m_array (array),
+ m_current (x),
+ m_base (m_array.stack),
+ m_end (0),
+ m_done (false),
+ m_skip (false),
+ m_substitute (false)
+{
+}
+
+/* Return the current subrtx. */
+
+template <typename T>
+inline typename T::value_type
+generic_subrtx_iterator <T>::operator * () const
+{
+ return m_current;
+}
+
+/* Return true if the iteration has finished. */
+
+template <typename T>
+inline bool
+generic_subrtx_iterator <T>::at_end () const
+{
+ return m_done;
+}
+
+/* Move on to the next subrtx. */
+
+template <typename T>
+inline void
+generic_subrtx_iterator <T>::next ()
+{
+ if (m_substitute)
+ {
+ m_substitute = false;
+ m_skip = false;
+ return;
+ }
+ if (!m_skip)
+ {
+ /* Add the subrtxes of M_CURRENT. */
+ rtx_type x = T::get_rtx (m_current);
+ if (__builtin_expect (x != 0, true))
+ {
+ enum rtx_code code = GET_CODE (x);
+ ssize_t count = m_bounds[code].count;
+ if (count > 0)
+ {
+ /* Handle the simple case of a single "e" block that is known
+ to fit into the current array. */
+ if (__builtin_expect (m_end + count <= LOCAL_ELEMS + 1, true))
+ {
+ /* Set M_CURRENT to the first subrtx and queue the rest. */
+ ssize_t start = m_bounds[code].start;
+ rtunion_type *src = &x->u.fld[start];
+ if (__builtin_expect (count > 2, false))
+ m_base[m_end++] = T::get_value (src[2].rt_rtx);
+ if (count > 1)
+ m_base[m_end++] = T::get_value (src[1].rt_rtx);
+ m_current = T::get_value (src[0].rt_rtx);
+ return;
+ }
+ /* Handle cases which aren't simple "e" sequences or where
+ the sequence might overrun M_BASE. */
+ count = add_subrtxes_to_queue (m_array, m_base, m_end, x);
+ if (count > 0)
+ {
+ m_end += count;
+ if (m_end > LOCAL_ELEMS)
+ m_base = m_array.heap->address ();
+ m_current = m_base[--m_end];
+ return;
+ }
+ }
+ }
+ }
+ else
+ m_skip = false;
+ if (m_end == 0)
+ m_done = true;
+ else
+ m_current = m_base[--m_end];
+}
+
+/* Skip the subrtxes of the current rtx. */
+
+template <typename T>
+inline void
+generic_subrtx_iterator <T>::skip_subrtxes ()
+{
+ m_skip = true;
+}
+
+/* Ignore the subrtxes of the current rtx and look at X instead. */
+
+template <typename T>
+inline void
+generic_subrtx_iterator <T>::substitute (value_type x)
+{
+ m_substitute = true;
+ m_current = x;
+}
+
+/* Iterators for const_rtx. */
+struct const_rtx_accessor
+{
+ typedef const_rtx value_type;
+ typedef const_rtx rtx_type;
+ typedef const rtunion rtunion_type;
+ static rtx_type get_rtx (value_type x) { return x; }
+ static value_type get_value (rtx_type x) { return x; }
+};
+typedef generic_subrtx_iterator <const_rtx_accessor> subrtx_iterator;
+
+/* Iterators for non-constant rtx. */
+struct rtx_var_accessor
+{
+ typedef rtx value_type;
+ typedef rtx rtx_type;
+ typedef rtunion rtunion_type;
+ static rtx_type get_rtx (value_type x) { return x; }
+ static value_type get_value (rtx_type x) { return x; }
+};
+typedef generic_subrtx_iterator <rtx_var_accessor> subrtx_var_iterator;
+
+/* Iterators for rtx *. */
+struct rtx_ptr_accessor
+{
+ typedef rtx *value_type;
+ typedef rtx rtx_type;
+ typedef rtunion rtunion_type;
+ static rtx_type get_rtx (value_type ptr) { return *ptr; }
+ static value_type get_value (rtx_type &x) { return &x; }
+};
+typedef generic_subrtx_iterator <rtx_ptr_accessor> subrtx_ptr_iterator;
+
+#define ALL_BOUNDS rtx_all_subrtx_bounds
+#define NONCONST_BOUNDS rtx_nonconst_subrtx_bounds
+
+/* Use ITER to iterate over const_rtx X and its recursive subrtxes,
+ using subrtx_iterator::array ARRAY as the storage for the worklist.
+ ARRAY can be reused for multiple consecutive iterations but shouldn't
+ be shared by two concurrent iterations. TYPE is ALL if all subrtxes
+ are of interest or NONCONST if it is safe to ignore subrtxes of
+ constants. */
+#define FOR_EACH_SUBRTX(ITER, ARRAY, X, TYPE) \
+ for (subrtx_iterator ITER (ARRAY, X, TYPE##_BOUNDS); !ITER.at_end (); \
+ ITER.next ())
+
+/* Like FOR_EACH_SUBRTX, but iterate over subrtxes of an rtx X. */
+#define FOR_EACH_SUBRTX_VAR(ITER, ARRAY, X, TYPE) \
+ for (subrtx_var_iterator ITER (ARRAY, X, TYPE##_BOUNDS); !ITER.at_end (); \
+ ITER.next ())
+
+/* Like FOR_EACH_SUBRTX, but iterate over subrtx pointers of rtx pointer X.
+ For example, if X is &PATTERN (insn) and the pattern is a SET, iterate
+ over &PATTERN (insn), &SET_DEST (PATTERN (insn)), etc. */
+#define FOR_EACH_SUBRTX_PTR(ITER, ARRAY, X, TYPE) \
+ for (subrtx_ptr_iterator ITER (ARRAY, X, TYPE##_BOUNDS); !ITER.at_end (); \
+ ITER.next ())
diff --git a/support/cpp/gcc/rtl.def b/support/cpp/gcc/rtl.def
new file mode 100644
index 000000000..08e31fa35
--- /dev/null
+++ b/support/cpp/gcc/rtl.def
@@ -0,0 +1,1368 @@
+/* This file contains the definitions and documentation for the
+ Register Transfer Expressions (rtx's) that make up the
+ Register Transfer Language (rtl) used in the Back End of the 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/>. */
+
+
+/* Expression definitions and descriptions for all targets are in this file.
+ Some will not be used for some targets.
+
+ The fields in the cpp macro call "DEF_RTL_EXPR()"
+ are used to create declarations in the C source of the compiler.
+
+ The fields are:
+
+ 1. The internal name of the rtx used in the C source.
+ It is a tag in the enumeration "enum rtx_code" defined in "rtl.h".
+ By convention these are in UPPER_CASE.
+
+ 2. The name of the rtx in the external ASCII format read by
+ read_rtx(), and printed by print_rtx().
+ These names are stored in rtx_name[].
+ By convention these are the internal (field 1) names in lower_case.
+
+ 3. The print format, and type of each rtx->u.fld[] (field) in this rtx.
+ These formats are stored in rtx_format[].
+ The meaning of the formats is documented in front of this array in rtl.cc
+
+ 4. The class of the rtx. These are stored in rtx_class and are accessed
+ via the GET_RTX_CLASS macro. They are defined as follows:
+
+ RTX_CONST_OBJ
+ an rtx code that can be used to represent a constant object
+ (e.g, CONST_INT)
+ RTX_OBJ
+ an rtx code that can be used to represent an object (e.g, REG, MEM)
+ RTX_COMPARE
+ an rtx code for a comparison (e.g, LT, GT)
+ RTX_COMM_COMPARE
+ an rtx code for a commutative comparison (e.g, EQ, NE, ORDERED)
+ RTX_UNARY
+ an rtx code for a unary arithmetic expression (e.g, NEG, NOT)
+ RTX_COMM_ARITH
+ an rtx code for a commutative binary operation (e.g,, PLUS, MULT)
+ RTX_TERNARY
+ an rtx code for a non-bitfield three input operation (IF_THEN_ELSE)
+ RTX_BIN_ARITH
+ an rtx code for a non-commutative binary operation (e.g., MINUS, DIV)
+ RTX_BITFIELD_OPS
+ an rtx code for a bit-field operation (ZERO_EXTRACT, SIGN_EXTRACT)
+ RTX_INSN
+ an rtx code for a machine insn (INSN, JUMP_INSN, CALL_INSN) or
+ data that will be output as assembly pseudo-ops (DEBUG_INSN)
+ RTX_MATCH
+ an rtx code for something that matches in insns (e.g, MATCH_DUP)
+ RTX_AUTOINC
+ an rtx code for autoincrement addressing modes (e.g. POST_DEC)
+ RTX_EXTRA
+ everything else
+
+ All of the expressions that appear only in machine descriptions,
+ not in RTL used by the compiler itself, are at the end of the file. */
+
+/* Unknown, or no such operation; the enumeration constant should have
+ value zero. */
+DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RTX_EXTRA)
+
+/* Used in the cselib routines to describe a value. Objects of this
+ kind are only allocated in cselib.cc, in an alloc pool instead of in
+ GC memory. The only operand of a VALUE is a cselib_val.
+ var-tracking requires this to have a distinct integral value from
+ DECL codes in trees. */
+DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
+
+/* The RTL generated for a DEBUG_EXPR_DECL. It links back to the
+ DEBUG_EXPR_DECL in the first operand. */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
+/* ---------------------------------------------------------------------
+ Expressions used in constructing lists.
+ --------------------------------------------------------------------- */
+
+/* A linked list of expressions. */
+DEF_RTL_EXPR(EXPR_LIST, "expr_list", "ee", RTX_EXTRA)
+
+/* A linked list of instructions.
+ The insns are represented in print by their uids. */
+DEF_RTL_EXPR(INSN_LIST, "insn_list", "ue", RTX_EXTRA)
+
+/* A linked list of integers. */
+DEF_RTL_EXPR(INT_LIST, "int_list", "ie", RTX_EXTRA)
+
+/* SEQUENCE is used in late passes of the compiler to group insns for
+ one reason or another.
+
+ For example, after delay slot filling, branch instructions with filled
+ delay slots are represented as a SEQUENCE of length 1 + n_delay_slots,
+ with the branch instruction in XEXPVEC(seq, 0, 0) and the instructions
+ occupying the delay slots in the remaining XEXPVEC slots.
+
+ Another place where a SEQUENCE may appear, is in REG_FRAME_RELATED_EXPR
+ notes, to express complex operations that are not obvious from the insn
+ to which the REG_FRAME_RELATED_EXPR note is attached. In this usage of
+ SEQUENCE, the sequence vector slots do not hold real instructions but
+ only pseudo-instructions that can be translated to DWARF CFA expressions.
+
+ Some back ends also use SEQUENCE to group insns in bundles.
+
+ Much of the compiler infrastructure is not prepared to handle SEQUENCE
+ objects. Only passes after pass_free_cfg are expected to handle them. */
+DEF_RTL_EXPR(SEQUENCE, "sequence", "E", RTX_EXTRA)
+
+/* Represents a non-global base address. This is only used in alias.cc. */
+DEF_RTL_EXPR(ADDRESS, "address", "i", RTX_EXTRA)
+
+/* ----------------------------------------------------------------------
+ Expression types used for things in the instruction chain.
+
+ All formats must start with "uu" to handle the chain.
+ Each insn expression holds an rtl instruction and its semantics
+ during back-end processing.
+ See macros in "rtl.h" for the meaning of each rtx->u.fld[].
+
+ ---------------------------------------------------------------------- */
+
+/* An annotation for variable assignment tracking. */
+DEF_RTL_EXPR(DEBUG_INSN, "debug_insn", "uuBeiie", RTX_INSN)
+
+/* An instruction that cannot jump. */
+DEF_RTL_EXPR(INSN, "insn", "uuBeiie", RTX_INSN)
+
+/* An instruction that can possibly jump.
+ Fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */
+DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "uuBeiie0", RTX_INSN)
+
+/* An instruction that can possibly call a subroutine
+ but which will not change which instruction comes next
+ in the current function.
+ Field ( rtx->u.fld[8] ) is CALL_INSN_FUNCTION_USAGE.
+ All other fields ( rtx->u.fld[] ) have exact same meaning as INSN's. */
+DEF_RTL_EXPR(CALL_INSN, "call_insn", "uuBeiiee", RTX_INSN)
+
+/* Placeholder for tablejump JUMP_INSNs. The pattern of this kind
+ of rtx is always either an ADDR_VEC or an ADDR_DIFF_VEC. These
+ placeholders do not appear as real instructions inside a basic
+ block, but are considered active_insn_p instructions for historical
+ reasons, when jump table data was represented with JUMP_INSNs. */
+DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN)
+
+/* A marker that indicates that control will not flow through. */
+DEF_RTL_EXPR(BARRIER, "barrier", "uu00000", RTX_EXTRA)
+
+/* Holds a label that is followed by instructions.
+ Operand:
+ 3: is used in jump.cc for the use-count of the label.
+ 4: is used in the sh backend.
+ 5: is a number that is unique in the entire compilation.
+ 6: is the user-given name of the label, if any. */
+DEF_RTL_EXPR(CODE_LABEL, "code_label", "uuB00is", RTX_EXTRA)
+
+/* Say where in the code a source line starts, for symbol table's sake.
+ Operand:
+ 3: note-specific data
+ 4: enum insn_note
+ 5: unique number if insn_note == note_insn_deleted_label. */
+DEF_RTL_EXPR(NOTE, "note", "uuB0ni", RTX_EXTRA)
+
+/* ----------------------------------------------------------------------
+ Top level constituents of INSN, JUMP_INSN and CALL_INSN.
+ ---------------------------------------------------------------------- */
+
+/* Conditionally execute code.
+ Operand 0 is the condition that if true, the code is executed.
+ Operand 1 is the code to be executed (typically a SET).
+
+ Semantics are that there are no side effects if the condition
+ is false. This pattern is created automatically by the if_convert
+ pass run after reload or by target-specific splitters. */
+DEF_RTL_EXPR(COND_EXEC, "cond_exec", "ee", RTX_EXTRA)
+
+/* Several operations to be done in parallel (perhaps under COND_EXEC). */
+DEF_RTL_EXPR(PARALLEL, "parallel", "E", RTX_EXTRA)
+
+/* A string that is passed through to the assembler as input.
+ One can obviously pass comments through by using the
+ assembler comment syntax.
+ These occur in an insn all by themselves as the PATTERN.
+ They also appear inside an ASM_OPERANDS
+ as a convenient way to hold a string. */
+DEF_RTL_EXPR(ASM_INPUT, "asm_input", "si", RTX_EXTRA)
+
+/* An assembler instruction with operands.
+ 1st operand is the instruction template.
+ 2nd operand is the constraint for the output.
+ 3rd operand is the number of the output this expression refers to.
+ When an insn stores more than one value, a separate ASM_OPERANDS
+ is made for each output; this integer distinguishes them.
+ 4th is a vector of values of input operands.
+ 5th is a vector of modes and constraints for the input operands.
+ Each element is an ASM_INPUT containing a constraint string
+ and whose mode indicates the mode of the input operand.
+ 6th is a vector of labels that may be branched to by the asm.
+ 7th is the source line number. */
+DEF_RTL_EXPR(ASM_OPERANDS, "asm_operands", "ssiEEEi", RTX_EXTRA)
+
+/* A machine-specific operation.
+ 1st operand is a vector of operands being used by the operation so that
+ any needed reloads can be done.
+ 2nd operand is a unique value saying which of a number of machine-specific
+ operations is to be performed.
+ (Note that the vector must be the first operand because of the way that
+ genrecog.cc record positions within an insn.)
+
+ UNSPEC can occur all by itself in a PATTERN, as a component of a PARALLEL,
+ or inside an expression.
+ UNSPEC by itself or as a component of a PARALLEL
+ is currently considered not deletable.
+
+ FIXME: Replace all uses of UNSPEC that appears by itself or as a component
+ of a PARALLEL with USE.
+ */
+DEF_RTL_EXPR(UNSPEC, "unspec", "Ei", RTX_EXTRA)
+
+/* Similar, but a volatile operation and one which may trap. */
+DEF_RTL_EXPR(UNSPEC_VOLATILE, "unspec_volatile", "Ei", RTX_EXTRA)
+
+/* ----------------------------------------------------------------------
+ Table jump addresses.
+ ---------------------------------------------------------------------- */
+
+/* Vector of addresses, stored as full words.
+ Each element is a LABEL_REF to a CODE_LABEL whose address we want. */
+DEF_RTL_EXPR(ADDR_VEC, "addr_vec", "E", RTX_EXTRA)
+
+/* Vector of address differences X0 - BASE, X1 - BASE, ...
+ First operand is BASE; the vector contains the X's.
+ The machine mode of this rtx says how much space to leave
+ for each difference and is adjusted by branch shortening if
+ CASE_VECTOR_SHORTEN_MODE is defined.
+ The third and fourth operands store the target labels with the
+ minimum and maximum addresses respectively.
+ The fifth operand stores flags for use by branch shortening.
+ Set at the start of shorten_branches:
+ min_align: the minimum alignment for any of the target labels.
+ base_after_vec: true iff BASE is after the ADDR_DIFF_VEC.
+ min_after_vec: true iff minimum addr target label is after the ADDR_DIFF_VEC.
+ max_after_vec: true iff maximum addr target label is after the ADDR_DIFF_VEC.
+ min_after_base: true iff minimum address target label is after BASE.
+ max_after_base: true iff maximum address target label is after BASE.
+ Set by the actual branch shortening process:
+ offset_unsigned: true iff offsets have to be treated as unsigned.
+ scale: scaling that is necessary to make offsets fit into the mode.
+
+ The third, fourth and fifth operands are only valid when
+ CASE_VECTOR_SHORTEN_MODE is defined, and only in an optimizing
+ compilation. */
+DEF_RTL_EXPR(ADDR_DIFF_VEC, "addr_diff_vec", "eEee0", RTX_EXTRA)
+
+/* Memory prefetch, with attributes supported on some targets.
+ Operand 1 is the address of the memory to fetch.
+ Operand 2 is 1 for a write access, 0 otherwise.
+ Operand 3 is the level of temporal locality; 0 means there is no
+ temporal locality and 1, 2, and 3 are for increasing levels of temporal
+ locality.
+
+ The attributes specified by operands 2 and 3 are ignored for targets
+ whose prefetch instructions do not support them. */
+DEF_RTL_EXPR(PREFETCH, "prefetch", "eee", RTX_EXTRA)
+
+/* ----------------------------------------------------------------------
+ At the top level of an instruction (perhaps under PARALLEL).
+ ---------------------------------------------------------------------- */
+
+/* Assignment.
+ Operand 1 is the location (REG, MEM, PC or whatever) assigned to.
+ Operand 2 is the value stored there.
+ ALL assignment must use SET.
+ Instructions that do multiple assignments must use multiple SET,
+ under PARALLEL. */
+DEF_RTL_EXPR(SET, "set", "ee", RTX_EXTRA)
+
+/* Indicate something is used in a way that we don't want to explain.
+ For example, subroutine calls will use the register
+ in which the static chain is passed.
+
+ USE cannot appear as an operand of other rtx except for PARALLEL.
+ USE is not deletable, as it indicates that the operand
+ is used in some unknown way. */
+DEF_RTL_EXPR(USE, "use", "e", RTX_EXTRA)
+
+/* Indicate something is clobbered in a way that we don't want to explain.
+ For example, subroutine calls will clobber some physical registers
+ (the ones that are by convention not saved).
+
+ CLOBBER cannot appear as an operand of other rtx except for PARALLEL.
+ CLOBBER of a hard register appearing by itself (not within PARALLEL)
+ is considered undeletable before reload. */
+DEF_RTL_EXPR(CLOBBER, "clobber", "e", RTX_EXTRA)
+
+/* Call a subroutine.
+ Operand 1 is the address to call.
+ Operand 2 is the number of arguments. */
+
+DEF_RTL_EXPR(CALL, "call", "ee", RTX_EXTRA)
+
+/* Return from a subroutine. */
+
+DEF_RTL_EXPR(RETURN, "return", "", RTX_EXTRA)
+
+/* Like RETURN, but truly represents only a function return, while
+ RETURN may represent an insn that also performs other functions
+ of the function epilogue. Like RETURN, this may also occur in
+ conditional jumps. */
+DEF_RTL_EXPR(SIMPLE_RETURN, "simple_return", "", RTX_EXTRA)
+
+/* Special for EH return from subroutine. */
+
+DEF_RTL_EXPR(EH_RETURN, "eh_return", "", RTX_EXTRA)
+
+/* Conditional trap.
+ Operand 1 is the condition.
+ Operand 2 is the trap code.
+ For an unconditional trap, make the condition (const_int 1). */
+DEF_RTL_EXPR(TRAP_IF, "trap_if", "ee", RTX_EXTRA)
+
+/* ----------------------------------------------------------------------
+ Primitive values for use in expressions.
+ ---------------------------------------------------------------------- */
+
+/* numeric integer constant */
+DEF_RTL_EXPR(CONST_INT, "const_int", "w", RTX_CONST_OBJ)
+
+/* numeric integer constant */
+DEF_RTL_EXPR(CONST_WIDE_INT, "const_wide_int", "", RTX_CONST_OBJ)
+
+/* An rtx representation of a poly_wide_int. */
+DEF_RTL_EXPR(CONST_POLY_INT, "const_poly_int", "", RTX_CONST_OBJ)
+
+/* fixed-point constant */
+DEF_RTL_EXPR(CONST_FIXED, "const_fixed", "www", RTX_CONST_OBJ)
+
+/* numeric floating point or integer constant. If the mode is
+ VOIDmode it is an int otherwise it has a floating point mode and a
+ floating point value. Operands hold the value. They are all 'w'
+ and there may be from 2 to 6; see real.h. */
+DEF_RTL_EXPR(CONST_DOUBLE, "const_double", CONST_DOUBLE_FORMAT, RTX_CONST_OBJ)
+
+/* Describes a vector constant. */
+DEF_RTL_EXPR(CONST_VECTOR, "const_vector", "E", RTX_CONST_OBJ)
+
+/* String constant. Used for attributes in machine descriptions and
+ for special cases in DWARF2 debug output. NOT used for source-
+ language string constants. */
+DEF_RTL_EXPR(CONST_STRING, "const_string", "s", RTX_OBJ)
+
+/* This is used to encapsulate an expression whose value is constant
+ (such as the sum of a SYMBOL_REF and a CONST_INT) so that it will be
+ recognized as a constant operand rather than by arithmetic instructions. */
+
+DEF_RTL_EXPR(CONST, "const", "e", RTX_CONST_OBJ)
+
+/* program counter. Ordinary jumps are represented
+ by a SET whose first operand is (PC). */
+DEF_RTL_EXPR(PC, "pc", "", RTX_OBJ)
+
+/* A register. The "operand" is the register number, accessed with
+ the REGNO macro. If this number is less than FIRST_PSEUDO_REGISTER
+ then a hardware register is being referred to. The second operand
+ points to a reg_attrs structure.
+ This rtx needs to have as many (or more) fields as a MEM, since we
+ can change REG rtx's into MEMs during reload. */
+DEF_RTL_EXPR(REG, "reg", "r", RTX_OBJ)
+
+/* A scratch register. This represents a register used only within a
+ single insn. It will be replaced by a REG during register allocation
+ or reload unless the constraint indicates that the register won't be
+ needed, in which case it can remain a SCRATCH. */
+DEF_RTL_EXPR(SCRATCH, "scratch", "", RTX_OBJ)
+
+/* A reference to a part of another value. The first operand is the
+ complete value and the second is the byte offset of the selected part. */
+DEF_RTL_EXPR(SUBREG, "subreg", "ep", RTX_EXTRA)
+
+/* This one-argument rtx is used for move instructions
+ that are guaranteed to alter only the low part of a destination.
+ Thus, (SET (SUBREG:HI (REG...)) (MEM:HI ...))
+ has an unspecified effect on the high part of REG,
+ but (SET (STRICT_LOW_PART (SUBREG:HI (REG...))) (MEM:HI ...))
+ is guaranteed to alter only the bits of REG that are in HImode.
+
+ The actual instruction used is probably the same in both cases,
+ but the register constraints may be tighter when STRICT_LOW_PART
+ is in use. */
+
+DEF_RTL_EXPR(STRICT_LOW_PART, "strict_low_part", "e", RTX_EXTRA)
+
+/* (CONCAT a b) represents the virtual concatenation of a and b
+ to make a value that has as many bits as a and b put together.
+ This is used for complex values. Normally it appears only
+ in DECL_RTLs and during RTL generation, but not in the insn chain. */
+DEF_RTL_EXPR(CONCAT, "concat", "ee", RTX_OBJ)
+
+/* (CONCATN [a1 a2 ... an]) represents the virtual concatenation of
+ all An to make a value. This is an extension of CONCAT to larger
+ number of components. Like CONCAT, it should not appear in the
+ insn chain. Every element of the CONCATN is the same size. */
+DEF_RTL_EXPR(CONCATN, "concatn", "E", RTX_OBJ)
+
+/* A memory location; operand is the address. The second operand is the
+ alias set to which this MEM belongs. We use `0' instead of `w' for this
+ field so that the field need not be specified in machine descriptions. */
+DEF_RTL_EXPR(MEM, "mem", "e0", RTX_OBJ)
+
+/* Reference to an assembler label in the code for this function.
+ The operand is a CODE_LABEL found in the insn chain. */
+DEF_RTL_EXPR(LABEL_REF, "label_ref", "u", RTX_CONST_OBJ)
+
+/* Reference to a named label:
+ Operand 0: label name
+ Operand 1: tree from which this symbol is derived, or null.
+ This is either a DECL node, or some kind of constant. */
+DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s0", RTX_CONST_OBJ)
+
+/* ----------------------------------------------------------------------
+ Expressions for operators in an rtl pattern
+ ---------------------------------------------------------------------- */
+
+/* if_then_else. This is used in representing ordinary
+ conditional jump instructions.
+ Operand:
+ 0: condition
+ 1: then expr
+ 2: else expr */
+DEF_RTL_EXPR(IF_THEN_ELSE, "if_then_else", "eee", RTX_TERNARY)
+
+/* Comparison, produces a condition code result. */
+DEF_RTL_EXPR(COMPARE, "compare", "ee", RTX_BIN_ARITH)
+
+/* plus */
+DEF_RTL_EXPR(PLUS, "plus", "ee", RTX_COMM_ARITH)
+
+/* Operand 0 minus operand 1. */
+DEF_RTL_EXPR(MINUS, "minus", "ee", RTX_BIN_ARITH)
+
+/* Minus operand 0. */
+DEF_RTL_EXPR(NEG, "neg", "e", RTX_UNARY)
+
+DEF_RTL_EXPR(MULT, "mult", "ee", RTX_COMM_ARITH)
+
+/* Multiplication with signed saturation */
+DEF_RTL_EXPR(SS_MULT, "ss_mult", "ee", RTX_COMM_ARITH)
+/* Multiplication with unsigned saturation */
+DEF_RTL_EXPR(US_MULT, "us_mult", "ee", RTX_COMM_ARITH)
+
+/* Signed high-part multiplication. */
+DEF_RTL_EXPR(SMUL_HIGHPART, "smul_highpart", "ee", RTX_COMM_ARITH)
+/* Unsigned high-part multiplication. */
+DEF_RTL_EXPR(UMUL_HIGHPART, "umul_highpart", "ee", RTX_COMM_ARITH)
+
+/* Operand 0 divided by operand 1. */
+DEF_RTL_EXPR(DIV, "div", "ee", RTX_BIN_ARITH)
+/* Division with signed saturation */
+DEF_RTL_EXPR(SS_DIV, "ss_div", "ee", RTX_BIN_ARITH)
+/* Division with unsigned saturation */
+DEF_RTL_EXPR(US_DIV, "us_div", "ee", RTX_BIN_ARITH)
+
+/* Remainder of operand 0 divided by operand 1. */
+DEF_RTL_EXPR(MOD, "mod", "ee", RTX_BIN_ARITH)
+
+/* Unsigned divide and remainder. */
+DEF_RTL_EXPR(UDIV, "udiv", "ee", RTX_BIN_ARITH)
+DEF_RTL_EXPR(UMOD, "umod", "ee", RTX_BIN_ARITH)
+
+/* Bitwise operations. */
+DEF_RTL_EXPR(AND, "and", "ee", RTX_COMM_ARITH)
+DEF_RTL_EXPR(IOR, "ior", "ee", RTX_COMM_ARITH)
+DEF_RTL_EXPR(XOR, "xor", "ee", RTX_COMM_ARITH)
+DEF_RTL_EXPR(NOT, "not", "e", RTX_UNARY)
+
+/* Operand:
+ 0: value to be shifted.
+ 1: number of bits. */
+DEF_RTL_EXPR(ASHIFT, "ashift", "ee", RTX_BIN_ARITH) /* shift left */
+DEF_RTL_EXPR(ROTATE, "rotate", "ee", RTX_BIN_ARITH) /* rotate left */
+DEF_RTL_EXPR(ASHIFTRT, "ashiftrt", "ee", RTX_BIN_ARITH) /* arithmetic shift right */
+DEF_RTL_EXPR(LSHIFTRT, "lshiftrt", "ee", RTX_BIN_ARITH) /* logical shift right */
+DEF_RTL_EXPR(ROTATERT, "rotatert", "ee", RTX_BIN_ARITH) /* rotate right */
+
+/* Minimum and maximum values of two operands. We need both signed and
+ unsigned forms. (We cannot use MIN for SMIN because it conflicts
+ with a macro of the same name.) The signed variants should be used
+ with floating point. Further, if both operands are zeros, or if either
+ operand is NaN, then it is unspecified which of the two operands is
+ returned as the result. */
+
+DEF_RTL_EXPR(SMIN, "smin", "ee", RTX_COMM_ARITH)
+DEF_RTL_EXPR(SMAX, "smax", "ee", RTX_COMM_ARITH)
+DEF_RTL_EXPR(UMIN, "umin", "ee", RTX_COMM_ARITH)
+DEF_RTL_EXPR(UMAX, "umax", "ee", RTX_COMM_ARITH)
+
+/* These unary operations are used to represent incrementation
+ and decrementation as they occur in memory addresses.
+ The amount of increment or decrement are not represented
+ because they can be understood from the machine-mode of the
+ containing MEM. These operations exist in only two cases:
+ 1. pushes onto the stack.
+ 2. created automatically by the auto-inc-dec pass. */
+DEF_RTL_EXPR(PRE_DEC, "pre_dec", "e", RTX_AUTOINC)
+DEF_RTL_EXPR(PRE_INC, "pre_inc", "e", RTX_AUTOINC)
+DEF_RTL_EXPR(POST_DEC, "post_dec", "e", RTX_AUTOINC)
+DEF_RTL_EXPR(POST_INC, "post_inc", "e", RTX_AUTOINC)
+
+/* These binary operations are used to represent generic address
+ side-effects in memory addresses, except for simple incrementation
+ or decrementation which use the above operations. They are
+ created automatically by the life_analysis pass in flow.c.
+ The first operand is a REG which is used as the address.
+ The second operand is an expression that is assigned to the
+ register, either before (PRE_MODIFY) or after (POST_MODIFY)
+ evaluating the address.
+ Currently, the compiler can only handle second operands of the
+ form (plus (reg) (reg)) and (plus (reg) (const_int)), where
+ the first operand of the PLUS has to be the same register as
+ the first operand of the *_MODIFY. */
+DEF_RTL_EXPR(PRE_MODIFY, "pre_modify", "ee", RTX_AUTOINC)
+DEF_RTL_EXPR(POST_MODIFY, "post_modify", "ee", RTX_AUTOINC)
+
+/* Comparison operations. The first 6 are allowed only for integral,
+floating-point and vector modes. LTGT is only allowed for floating-point
+modes. The last 4 are allowed only for integral and vector modes.
+For floating-point operations, if either operand is a NaN, then NE returns
+true and the remaining operations return false. The operations other than
+EQ and NE may generate an exception on quiet NaNs. */
+DEF_RTL_EXPR(NE, "ne", "ee", RTX_COMM_COMPARE)
+DEF_RTL_EXPR(EQ, "eq", "ee", RTX_COMM_COMPARE)
+DEF_RTL_EXPR(GE, "ge", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(GT, "gt", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(LE, "le", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(LT, "lt", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(LTGT, "ltgt", "ee", RTX_COMM_COMPARE)
+DEF_RTL_EXPR(GEU, "geu", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(GTU, "gtu", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(LEU, "leu", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(LTU, "ltu", "ee", RTX_COMPARE)
+
+/* Additional floating-point unordered comparison flavors. */
+DEF_RTL_EXPR(UNORDERED, "unordered", "ee", RTX_COMM_COMPARE)
+DEF_RTL_EXPR(ORDERED, "ordered", "ee", RTX_COMM_COMPARE)
+
+/* These are equivalent to unordered or ... */
+DEF_RTL_EXPR(UNEQ, "uneq", "ee", RTX_COMM_COMPARE)
+DEF_RTL_EXPR(UNGE, "unge", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(UNGT, "ungt", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(UNLE, "unle", "ee", RTX_COMPARE)
+DEF_RTL_EXPR(UNLT, "unlt", "ee", RTX_COMPARE)
+
+/* Represents the result of sign-extending the sole operand.
+ The machine modes of the operand and of the SIGN_EXTEND expression
+ determine how much sign-extension is going on. */
+DEF_RTL_EXPR(SIGN_EXTEND, "sign_extend", "e", RTX_UNARY)
+
+/* Similar for zero-extension (such as unsigned short to int). */
+DEF_RTL_EXPR(ZERO_EXTEND, "zero_extend", "e", RTX_UNARY)
+
+/* Similar but here the operand has a wider mode. */
+DEF_RTL_EXPR(TRUNCATE, "truncate", "e", RTX_UNARY)
+
+/* Similar for extending floating-point values (such as SFmode to DFmode). */
+DEF_RTL_EXPR(FLOAT_EXTEND, "float_extend", "e", RTX_UNARY)
+DEF_RTL_EXPR(FLOAT_TRUNCATE, "float_truncate", "e", RTX_UNARY)
+
+/* Conversion of fixed point operand to floating point value. */
+DEF_RTL_EXPR(FLOAT, "float", "e", RTX_UNARY)
+
+/* With fixed-point machine mode:
+ Conversion of floating point operand to fixed point value.
+ Value is defined only when the operand's value is an integer.
+ With floating-point machine mode (and operand with same mode):
+ Operand is rounded toward zero to produce an integer value
+ represented in floating point. */
+DEF_RTL_EXPR(FIX, "fix", "e", RTX_UNARY)
+
+/* Conversion of unsigned fixed point operand to floating point value. */
+DEF_RTL_EXPR(UNSIGNED_FLOAT, "unsigned_float", "e", RTX_UNARY)
+
+/* With fixed-point machine mode:
+ Conversion of floating point operand to *unsigned* fixed point value.
+ Value is defined only when the operand's value is an integer. */
+DEF_RTL_EXPR(UNSIGNED_FIX, "unsigned_fix", "e", RTX_UNARY)
+
+/* Conversions involving fractional fixed-point types without saturation,
+ including:
+ fractional to fractional (of different precision),
+ signed integer to fractional,
+ fractional to signed integer,
+ floating point to fractional,
+ fractional to floating point.
+ NOTE: fractional can be either signed or unsigned for conversions. */
+DEF_RTL_EXPR(FRACT_CONVERT, "fract_convert", "e", RTX_UNARY)
+
+/* Conversions involving fractional fixed-point types and unsigned integer
+ without saturation, including:
+ unsigned integer to fractional,
+ fractional to unsigned integer.
+ NOTE: fractional can be either signed or unsigned for conversions. */
+DEF_RTL_EXPR(UNSIGNED_FRACT_CONVERT, "unsigned_fract_convert", "e", RTX_UNARY)
+
+/* Conversions involving fractional fixed-point types with saturation,
+ including:
+ fractional to fractional (of different precision),
+ signed integer to fractional,
+ floating point to fractional.
+ NOTE: fractional can be either signed or unsigned for conversions. */
+DEF_RTL_EXPR(SAT_FRACT, "sat_fract", "e", RTX_UNARY)
+
+/* Conversions involving fractional fixed-point types and unsigned integer
+ with saturation, including:
+ unsigned integer to fractional.
+ NOTE: fractional can be either signed or unsigned for conversions. */
+DEF_RTL_EXPR(UNSIGNED_SAT_FRACT, "unsigned_sat_fract", "e", RTX_UNARY)
+
+/* Absolute value */
+DEF_RTL_EXPR(ABS, "abs", "e", RTX_UNARY)
+
+/* Square root */
+DEF_RTL_EXPR(SQRT, "sqrt", "e", RTX_UNARY)
+
+/* Swap bytes. */
+DEF_RTL_EXPR(BSWAP, "bswap", "e", RTX_UNARY)
+
+/* Find first bit that is set.
+ Value is 1 + number of trailing zeros in the arg.,
+ or 0 if arg is 0. */
+DEF_RTL_EXPR(FFS, "ffs", "e", RTX_UNARY)
+
+/* Count number of leading redundant sign bits (number of leading
+ sign bits minus one). */
+DEF_RTL_EXPR(CLRSB, "clrsb", "e", RTX_UNARY)
+
+/* Count leading zeros. */
+DEF_RTL_EXPR(CLZ, "clz", "e", RTX_UNARY)
+
+/* Count trailing zeros. */
+DEF_RTL_EXPR(CTZ, "ctz", "e", RTX_UNARY)
+
+/* Population count (number of 1 bits). */
+DEF_RTL_EXPR(POPCOUNT, "popcount", "e", RTX_UNARY)
+
+/* Population parity (number of 1 bits modulo 2). */
+DEF_RTL_EXPR(PARITY, "parity", "e", RTX_UNARY)
+
+/* Reference to a signed bit-field of specified size and position.
+ Operand 0 is the memory unit (usually SImode or QImode) which
+ contains the field's first bit. Operand 1 is the width, in bits.
+ Operand 2 is the number of bits in the memory unit before the
+ first bit of this field.
+ If BITS_BIG_ENDIAN is defined, the first bit is the msb and
+ operand 2 counts from the msb of the memory unit.
+ Otherwise, the first bit is the lsb and operand 2 counts from
+ the lsb of the memory unit.
+ This kind of expression cannot appear as an lvalue in RTL. */
+DEF_RTL_EXPR(SIGN_EXTRACT, "sign_extract", "eee", RTX_BITFIELD_OPS)
+
+/* Similar for unsigned bit-field.
+ But note! This kind of expression _can_ appear as an lvalue. */
+DEF_RTL_EXPR(ZERO_EXTRACT, "zero_extract", "eee", RTX_BITFIELD_OPS)
+
+/* For RISC machines. These save memory when splitting insns. */
+
+/* HIGH are the high-order bits of a constant expression. */
+DEF_RTL_EXPR(HIGH, "high", "e", RTX_CONST_OBJ)
+
+/* LO_SUM is the sum of a register and the low-order bits
+ of a constant expression. */
+DEF_RTL_EXPR(LO_SUM, "lo_sum", "ee", RTX_OBJ)
+
+/* Describes a merge operation between two vector values.
+ Operands 0 and 1 are the vectors to be merged, operand 2 is a bitmask
+ that specifies where the parts of the result are taken from. Set bits
+ indicate operand 0, clear bits indicate operand 1. The parts are defined
+ by the mode of the vectors. */
+DEF_RTL_EXPR(VEC_MERGE, "vec_merge", "eee", RTX_TERNARY)
+
+/* Describes an operation that selects parts of a vector.
+ Operands 0 is the source vector, operand 1 is a PARALLEL that contains
+ a CONST_INT for each of the subparts of the result vector, giving the
+ number of the source subpart that should be stored into it. */
+DEF_RTL_EXPR(VEC_SELECT, "vec_select", "ee", RTX_BIN_ARITH)
+
+/* Describes a vector concat operation. Operands 0 and 1 are the source
+ vectors, the result is a vector that is as long as operands 0 and 1
+ combined and is the concatenation of the two source vectors. */
+DEF_RTL_EXPR(VEC_CONCAT, "vec_concat", "ee", RTX_BIN_ARITH)
+
+/* Describes an operation that converts a small vector into a larger one by
+ duplicating the input values. The output vector mode must have the same
+ submodes as the input vector mode, and the number of output parts must be
+ an integer multiple of the number of input parts. */
+DEF_RTL_EXPR(VEC_DUPLICATE, "vec_duplicate", "e", RTX_UNARY)
+
+/* Creation of a vector in which element I has the value BASE + I * STEP,
+ where BASE is the first operand and STEP is the second. The result
+ must have a vector integer mode. */
+DEF_RTL_EXPR(VEC_SERIES, "vec_series", "ee", RTX_BIN_ARITH)
+
+/* Addition with signed saturation */
+DEF_RTL_EXPR(SS_PLUS, "ss_plus", "ee", RTX_COMM_ARITH)
+
+/* Addition with unsigned saturation */
+DEF_RTL_EXPR(US_PLUS, "us_plus", "ee", RTX_COMM_ARITH)
+
+/* Operand 0 minus operand 1, with signed saturation. */
+DEF_RTL_EXPR(SS_MINUS, "ss_minus", "ee", RTX_BIN_ARITH)
+
+/* Negation with signed saturation. */
+DEF_RTL_EXPR(SS_NEG, "ss_neg", "e", RTX_UNARY)
+/* Negation with unsigned saturation. */
+DEF_RTL_EXPR(US_NEG, "us_neg", "e", RTX_UNARY)
+
+/* Absolute value with signed saturation. */
+DEF_RTL_EXPR(SS_ABS, "ss_abs", "e", RTX_UNARY)
+
+/* Shift left with signed saturation. */
+DEF_RTL_EXPR(SS_ASHIFT, "ss_ashift", "ee", RTX_BIN_ARITH)
+
+/* Shift left with unsigned saturation. */
+DEF_RTL_EXPR(US_ASHIFT, "us_ashift", "ee", RTX_BIN_ARITH)
+
+/* Operand 0 minus operand 1, with unsigned saturation. */
+DEF_RTL_EXPR(US_MINUS, "us_minus", "ee", RTX_BIN_ARITH)
+
+/* Signed saturating truncate. */
+DEF_RTL_EXPR(SS_TRUNCATE, "ss_truncate", "e", RTX_UNARY)
+
+/* Unsigned saturating truncate. */
+DEF_RTL_EXPR(US_TRUNCATE, "us_truncate", "e", RTX_UNARY)
+
+/* Floating point multiply/add combined instruction. */
+DEF_RTL_EXPR(FMA, "fma", "eee", RTX_TERNARY)
+
+/* Information about the variable and its location. */
+DEF_RTL_EXPR(VAR_LOCATION, "var_location", "te", RTX_EXTRA)
+
+/* Used in VAR_LOCATION for a pointer to a decl that is no longer
+ addressable. */
+DEF_RTL_EXPR(DEBUG_IMPLICIT_PTR, "debug_implicit_ptr", "t", RTX_OBJ)
+
+/* Represents value that argument had on function entry. The
+ single argument is the DECL_INCOMING_RTL of the corresponding
+ parameter. */
+DEF_RTL_EXPR(ENTRY_VALUE, "entry_value", "0", RTX_OBJ)
+
+/* Used in VAR_LOCATION for a reference to a parameter that has
+ been optimized away completely. */
+DEF_RTL_EXPR(DEBUG_PARAMETER_REF, "debug_parameter_ref", "t", RTX_OBJ)
+
+/* Used in marker DEBUG_INSNs to avoid being recognized as an insn. */
+DEF_RTL_EXPR(DEBUG_MARKER, "debug_marker", "", RTX_EXTRA)
+
+/* All expressions from this point forward appear only in machine
+ descriptions. */
+#ifdef GENERATOR_FILE
+
+/* Pattern-matching operators: */
+
+/* Use the function named by the second arg (the string)
+ as a predicate; if matched, store the structure that was matched
+ in the operand table at index specified by the first arg (the integer).
+ If the second arg is the null string, the structure is just stored.
+
+ A third string argument indicates to the register allocator restrictions
+ on where the operand can be allocated.
+
+ If the target needs no restriction on any instruction this field should
+ be the null string.
+
+ The string is prepended by:
+ '=' to indicate the operand is only written to.
+ '+' to indicate the operand is both read and written to.
+
+ Each character in the string represents an allocable class for an operand.
+ 'g' indicates the operand can be any valid class.
+ 'i' indicates the operand can be immediate (in the instruction) data.
+ 'r' indicates the operand can be in a register.
+ 'm' indicates the operand can be in memory.
+ 'o' a subset of the 'm' class. Those memory addressing modes that
+ can be offset at compile time (have a constant added to them).
+
+ Other characters indicate target dependent operand classes and
+ are described in each target's machine description.
+
+ For instructions with more than one operand, sets of classes can be
+ separated by a comma to indicate the appropriate multi-operand constraints.
+ There must be a 1 to 1 correspondence between these sets of classes in
+ all operands for an instruction.
+ */
+DEF_RTL_EXPR(MATCH_OPERAND, "match_operand", "iss", RTX_MATCH)
+
+/* Match a SCRATCH or a register. When used to generate rtl, a
+ SCRATCH is generated. As for MATCH_OPERAND, the mode specifies
+ the desired mode and the first argument is the operand number.
+ The second argument is the constraint. */
+DEF_RTL_EXPR(MATCH_SCRATCH, "match_scratch", "is", RTX_MATCH)
+
+/* Apply a predicate, AND match recursively the operands of the rtx.
+ Operand 0 is the operand-number, as in match_operand.
+ Operand 1 is a predicate to apply (as a string, a function name).
+ Operand 2 is a vector of expressions, each of which must match
+ one subexpression of the rtx this construct is matching. */
+DEF_RTL_EXPR(MATCH_OPERATOR, "match_operator", "isE", RTX_MATCH)
+
+/* Match a PARALLEL of arbitrary length. The predicate is applied
+ to the PARALLEL and the initial expressions in the PARALLEL are matched.
+ Operand 0 is the operand-number, as in match_operand.
+ Operand 1 is a predicate to apply to the PARALLEL.
+ Operand 2 is a vector of expressions, each of which must match the
+ corresponding element in the PARALLEL. */
+DEF_RTL_EXPR(MATCH_PARALLEL, "match_parallel", "isE", RTX_MATCH)
+
+/* Match only something equal to what is stored in the operand table
+ at the index specified by the argument. Use with MATCH_OPERAND. */
+DEF_RTL_EXPR(MATCH_DUP, "match_dup", "i", RTX_MATCH)
+
+/* Match only something equal to what is stored in the operand table
+ at the index specified by the argument. Use with MATCH_OPERATOR. */
+DEF_RTL_EXPR(MATCH_OP_DUP, "match_op_dup", "iE", RTX_MATCH)
+
+/* Match only something equal to what is stored in the operand table
+ at the index specified by the argument. Use with MATCH_PARALLEL. */
+DEF_RTL_EXPR(MATCH_PAR_DUP, "match_par_dup", "iE", RTX_MATCH)
+
+/* Appears only in define_predicate/define_special_predicate
+ expressions. Evaluates true only if the operand has an RTX code
+ from the set given by the argument (a comma-separated list). If the
+ second argument is present and nonempty, it is a sequence of digits
+ and/or letters which indicates the subexpression to test, using the
+ same syntax as genextract/genrecog's location strings: 0-9 for
+ XEXP (op, n), a-z for XVECEXP (op, 0, n); each character applies to
+ the result of the one before it. */
+DEF_RTL_EXPR(MATCH_CODE, "match_code", "ss", RTX_MATCH)
+
+/* Used to inject a C conditional expression into an .md file. It can
+ appear in a predicate definition or an attribute expression. */
+DEF_RTL_EXPR(MATCH_TEST, "match_test", "s", RTX_MATCH)
+
+/* Insn (and related) definitions. */
+
+/* Definition of the pattern for one kind of instruction.
+ Operand:
+ 0: names this instruction.
+ If the name is the null string, the instruction is in the
+ machine description just to be recognized, and will never be emitted by
+ the tree to rtl expander.
+ 1: is the pattern.
+ 2: is a string which is a C expression
+ giving an additional condition for recognizing this pattern.
+ A null string means no extra condition.
+ 3: is the action to execute if this pattern is matched.
+ If this assembler code template starts with a * then it is a fragment of
+ C code to run to decide on a template to use. Otherwise, it is the
+ template to use.
+ 4: optionally, a vector of attributes for this insn.
+ */
+DEF_RTL_EXPR(DEFINE_INSN, "define_insn", "sEsTV", RTX_EXTRA)
+
+/* Definition of a peephole optimization.
+ 1st operand: vector of insn patterns to match
+ 2nd operand: C expression that must be true
+ 3rd operand: template or C code to produce assembler output.
+ 4: optionally, a vector of attributes for this insn.
+
+ This form is deprecated; use define_peephole2 instead. */
+DEF_RTL_EXPR(DEFINE_PEEPHOLE, "define_peephole", "EsTV", RTX_EXTRA)
+
+/* Definition of a split operation.
+ 1st operand: insn pattern to match
+ 2nd operand: C expression that must be true
+ 3rd operand: vector of insn patterns to place into a SEQUENCE
+ 4th operand: optionally, some C code to execute before generating the
+ insns. This might, for example, create some RTX's and store them in
+ elements of `recog_data.operand' for use by the vector of
+ insn-patterns.
+ (`operands' is an alias here for `recog_data.operand'). */
+DEF_RTL_EXPR(DEFINE_SPLIT, "define_split", "EsES", RTX_EXTRA)
+
+/* Definition of an insn and associated split.
+ This is the concatenation, with a few modifications, of a define_insn
+ and a define_split which share the same pattern.
+ Operand:
+ 0: names this instruction.
+ If the name is the null string, the instruction is in the
+ machine description just to be recognized, and will never be emitted by
+ the tree to rtl expander.
+ 1: is the pattern.
+ 2: is a string which is a C expression
+ giving an additional condition for recognizing this pattern.
+ A null string means no extra condition.
+ 3: is the action to execute if this pattern is matched.
+ If this assembler code template starts with a * then it is a fragment of
+ C code to run to decide on a template to use. Otherwise, it is the
+ template to use.
+ 4: C expression that must be true for split. This may start with "&&"
+ in which case the split condition is the logical and of the insn
+ condition and what follows the "&&" of this operand.
+ 5: vector of insn patterns to place into a SEQUENCE
+ 6: optionally, some C code to execute before generating the
+ insns. This might, for example, create some RTX's and store them in
+ elements of `recog_data.operand' for use by the vector of
+ insn-patterns.
+ (`operands' is an alias here for `recog_data.operand').
+ 7: optionally, a vector of attributes for this insn. */
+DEF_RTL_EXPR(DEFINE_INSN_AND_SPLIT, "define_insn_and_split", "sEsTsESV", RTX_EXTRA)
+
+/* A form of define_insn_and_split in which the split insn pattern (operand 5)
+ is determined automatically by replacing match_operands with match_dups
+ and match_operators with match_op_dups. The operands are the same as
+ define_insn_and_split but with operand 5 removed. */
+DEF_RTL_EXPR(DEFINE_INSN_AND_REWRITE, "define_insn_and_rewrite", "sEsTsSV", RTX_EXTRA)
+
+/* Definition of an RTL peephole operation.
+ Follows the same arguments as define_split. */
+DEF_RTL_EXPR(DEFINE_PEEPHOLE2, "define_peephole2", "EsES", RTX_EXTRA)
+
+/* Define how to generate multiple insns for a standard insn name.
+ 1st operand: the insn name.
+ 2nd operand: vector of insn-patterns.
+ Use match_operand to substitute an element of `recog_data.operand'.
+ 3rd operand: C expression that must be true for this to be available.
+ This may not test any operands.
+ 4th operand: Extra C code to execute before generating the insns.
+ This might, for example, create some RTX's and store them in
+ elements of `recog_data.operand' for use by the vector of
+ insn-patterns.
+ (`operands' is an alias here for `recog_data.operand').
+ 5th: optionally, a vector of attributes for this expand. */
+DEF_RTL_EXPR(DEFINE_EXPAND, "define_expand", "sEssV", RTX_EXTRA)
+
+/* Define a requirement for delay slots.
+ 1st operand: Condition involving insn attributes that, if true,
+ indicates that the insn requires the number of delay slots
+ shown.
+ 2nd operand: Vector whose length is the three times the number of delay
+ slots required.
+ Each entry gives three conditions, each involving attributes.
+ The first must be true for an insn to occupy that delay slot
+ location. The second is true for all insns that can be
+ annulled if the branch is true and the third is true for all
+ insns that can be annulled if the branch is false.
+
+ Multiple DEFINE_DELAYs may be present. They indicate differing
+ requirements for delay slots. */
+DEF_RTL_EXPR(DEFINE_DELAY, "define_delay", "eE", RTX_EXTRA)
+
+/* Define attribute computation for `asm' instructions. */
+DEF_RTL_EXPR(DEFINE_ASM_ATTRIBUTES, "define_asm_attributes", "V", RTX_EXTRA)
+
+/* Definition of a conditional execution meta operation. Automatically
+ generates new instances of DEFINE_INSN, selected by having attribute
+ "predicable" true. The new pattern will contain a COND_EXEC and the
+ predicate at top-level.
+
+ Operand:
+ 0: The predicate pattern. The top-level form should match a
+ relational operator. Operands should have only one alternative.
+ 1: A C expression giving an additional condition for recognizing
+ the generated pattern.
+ 2: A template or C code to produce assembler output.
+ 3: A vector of attributes to append to the resulting cond_exec insn. */
+DEF_RTL_EXPR(DEFINE_COND_EXEC, "define_cond_exec", "EssV", RTX_EXTRA)
+
+/* Definition of an operand predicate. The difference between
+ DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE is that genrecog will
+ not warn about a match_operand with no mode if it has a predicate
+ defined with DEFINE_SPECIAL_PREDICATE.
+
+ Operand:
+ 0: The name of the predicate.
+ 1: A boolean expression which computes whether or not the predicate
+ matches. This expression can use IOR, AND, NOT, MATCH_OPERAND,
+ MATCH_CODE, and MATCH_TEST. It must be specific enough that genrecog
+ can calculate the set of RTX codes that can possibly match.
+ 2: A C function body which must return true for the predicate to match.
+ Optional. Use this when the test is too complicated to fit into a
+ match_test expression. */
+DEF_RTL_EXPR(DEFINE_PREDICATE, "define_predicate", "ses", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_SPECIAL_PREDICATE, "define_special_predicate", "ses", RTX_EXTRA)
+
+/* Definition of a register operand constraint. This simply maps the
+ constraint string to a register class.
+
+ Operand:
+ 0: The name of the constraint (often, but not always, a single letter).
+ 1: A C expression which evaluates to the appropriate register class for
+ this constraint. If this is not just a constant, it should look only
+ at -m switches and the like.
+ 2: A docstring for this constraint, in Texinfo syntax; not currently
+ used, in future will be incorporated into the manual's list of
+ machine-specific operand constraints. */
+DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RTX_EXTRA)
+
+/* Definition of a non-register operand constraint. These look at the
+ operand and decide whether it fits the constraint.
+
+ DEFINE_CONSTRAINT gets no special treatment if it fails to match.
+ It is appropriate for constant-only constraints, and most others.
+
+ DEFINE_MEMORY_CONSTRAINT tells reload that this constraint can be made
+ to match, if it doesn't already, by converting the operand to the form
+ (mem (reg X)) where X is a base register. It is suitable for constraints
+ that describe a subset of all memory references.
+
+ DEFINE_ADDRESS_CONSTRAINT tells reload that this constraint can be made
+ to match, if it doesn't already, by converting the operand to the form
+ (reg X) where X is a base register. It is suitable for constraints that
+ describe a subset of all address references.
+
+ When in doubt, use plain DEFINE_CONSTRAINT.
+
+ Operand:
+ 0: The name of the constraint (often, but not always, a single letter).
+ 1: A docstring for this constraint, in Texinfo syntax; not currently
+ used, in future will be incorporated into the manual's list of
+ machine-specific operand constraints.
+ 2: A boolean expression which computes whether or not the constraint
+ matches. It should follow the same rules as a define_predicate
+ expression, including the bit about specifying the set of RTX codes
+ that could possibly match. MATCH_TEST subexpressions may make use of
+ these variables:
+ `op' - the RTL object defining the operand.
+ `mode' - the mode of `op'.
+ `ival' - INTVAL(op), if op is a CONST_INT.
+ `hval' - CONST_DOUBLE_HIGH(op), if op is an integer CONST_DOUBLE.
+ `lval' - CONST_DOUBLE_LOW(op), if op is an integer CONST_DOUBLE.
+ `rval' - CONST_DOUBLE_REAL_VALUE(op), if op is a floating-point
+ CONST_DOUBLE.
+ Do not use ival/hval/lval/rval if op is not the appropriate kind of
+ RTL object. */
+DEF_RTL_EXPR(DEFINE_CONSTRAINT, "define_constraint", "sse", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_MEMORY_CONSTRAINT, "define_memory_constraint", "sse", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_SPECIAL_MEMORY_CONSTRAINT, "define_special_memory_constraint", "sse", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_RELAXED_MEMORY_CONSTRAINT, "define_relaxed_memory_constraint", "sse", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_ADDRESS_CONSTRAINT, "define_address_constraint", "sse", RTX_EXTRA)
+
+
+/* Constructions for CPU pipeline description described by NDFAs. */
+
+/* (define_cpu_unit string [string]) describes cpu functional
+ units (separated by comma).
+
+ 1st operand: Names of cpu functional units.
+ 2nd operand: Name of automaton (see comments for DEFINE_AUTOMATON).
+
+ All define_reservations, define_cpu_units, and
+ define_query_cpu_units should have unique names which may not be
+ "nothing". */
+DEF_RTL_EXPR(DEFINE_CPU_UNIT, "define_cpu_unit", "sS", RTX_EXTRA)
+
+/* (define_query_cpu_unit string [string]) describes cpu functional
+ units analogously to define_cpu_unit. The reservation of such
+ units can be queried for automaton state. */
+DEF_RTL_EXPR(DEFINE_QUERY_CPU_UNIT, "define_query_cpu_unit", "sS", RTX_EXTRA)
+
+/* (exclusion_set string string) means that each CPU functional unit
+ in the first string cannot be reserved simultaneously with any
+ unit whose name is in the second string and vise versa. CPU units
+ in the string are separated by commas. For example, it is useful
+ for description CPU with fully pipelined floating point functional
+ unit which can execute simultaneously only single floating point
+ insns or only double floating point insns. All CPU functional
+ units in a set should belong to the same automaton. */
+DEF_RTL_EXPR(EXCLUSION_SET, "exclusion_set", "ss", RTX_EXTRA)
+
+/* (presence_set string string) means that each CPU functional unit in
+ the first string cannot be reserved unless at least one of pattern
+ of units whose names are in the second string is reserved. This is
+ an asymmetric relation. CPU units or unit patterns in the strings
+ are separated by commas. Pattern is one unit name or unit names
+ separated by white-spaces.
+
+ For example, it is useful for description that slot1 is reserved
+ after slot0 reservation for a VLIW processor. We could describe it
+ by the following construction
+
+ (presence_set "slot1" "slot0")
+
+ Or slot1 is reserved only after slot0 and unit b0 reservation. In
+ this case we could write
+
+ (presence_set "slot1" "slot0 b0")
+
+ All CPU functional units in a set should belong to the same
+ automaton. */
+DEF_RTL_EXPR(PRESENCE_SET, "presence_set", "ss", RTX_EXTRA)
+
+/* (final_presence_set string string) is analogous to `presence_set'.
+ The difference between them is when checking is done. When an
+ instruction is issued in given automaton state reflecting all
+ current and planned unit reservations, the automaton state is
+ changed. The first state is a source state, the second one is a
+ result state. Checking for `presence_set' is done on the source
+ state reservation, checking for `final_presence_set' is done on the
+ result reservation. This construction is useful to describe a
+ reservation which is actually two subsequent reservations. For
+ example, if we use
+
+ (presence_set "slot1" "slot0")
+
+ the following insn will be never issued (because slot1 requires
+ slot0 which is absent in the source state).
+
+ (define_reservation "insn_and_nop" "slot0 + slot1")
+
+ but it can be issued if we use analogous `final_presence_set'. */
+DEF_RTL_EXPR(FINAL_PRESENCE_SET, "final_presence_set", "ss", RTX_EXTRA)
+
+/* (absence_set string string) means that each CPU functional unit in
+ the first string can be reserved only if each pattern of units
+ whose names are in the second string is not reserved. This is an
+ asymmetric relation (actually exclusion set is analogous to this
+ one but it is symmetric). CPU units or unit patterns in the string
+ are separated by commas. Pattern is one unit name or unit names
+ separated by white-spaces.
+
+ For example, it is useful for description that slot0 cannot be
+ reserved after slot1 or slot2 reservation for a VLIW processor. We
+ could describe it by the following construction
+
+ (absence_set "slot2" "slot0, slot1")
+
+ Or slot2 cannot be reserved if slot0 and unit b0 are reserved or
+ slot1 and unit b1 are reserved . In this case we could write
+
+ (absence_set "slot2" "slot0 b0, slot1 b1")
+
+ All CPU functional units in a set should to belong the same
+ automaton. */
+DEF_RTL_EXPR(ABSENCE_SET, "absence_set", "ss", RTX_EXTRA)
+
+/* (final_absence_set string string) is analogous to `absence_set' but
+ checking is done on the result (state) reservation. See comments
+ for `final_presence_set'. */
+DEF_RTL_EXPR(FINAL_ABSENCE_SET, "final_absence_set", "ss", RTX_EXTRA)
+
+/* (define_bypass number out_insn_names in_insn_names) names bypass
+ with given latency (the first number) from insns given by the first
+ string (see define_insn_reservation) into insns given by the second
+ string. Insn names in the strings are separated by commas. The
+ third operand is optional name of function which is additional
+ guard for the bypass. The function will get the two insns as
+ parameters. If the function returns zero the bypass will be
+ ignored for this case. Additional guard is necessary to recognize
+ complicated bypasses, e.g. when consumer is load address. If there
+ are more one bypass with the same output and input insns, the
+ chosen bypass is the first bypass with a guard in description whose
+ guard function returns nonzero. If there is no such bypass, then
+ bypass without the guard function is chosen. */
+DEF_RTL_EXPR(DEFINE_BYPASS, "define_bypass", "issS", RTX_EXTRA)
+
+/* (define_automaton string) describes names of automata generated and
+ used for pipeline hazards recognition. The names are separated by
+ comma. Actually it is possibly to generate the single automaton
+ but unfortunately it can be very large. If we use more one
+ automata, the summary size of the automata usually is less than the
+ single one. The automaton name is used in define_cpu_unit and
+ define_query_cpu_unit. All automata should have unique names. */
+DEF_RTL_EXPR(DEFINE_AUTOMATON, "define_automaton", "s", RTX_EXTRA)
+
+/* (automata_option string) describes option for generation of
+ automata. Currently there are the following options:
+
+ o "no-minimization" which makes no minimization of automata. This
+ is only worth to do when we are debugging the description and
+ need to look more accurately at reservations of states.
+
+ o "time" which means printing additional time statistics about
+ generation of automata.
+
+ o "v" which means generation of file describing the result
+ automata. The file has suffix `.dfa' and can be used for the
+ description verification and debugging.
+
+ o "w" which means generation of warning instead of error for
+ non-critical errors.
+
+ o "ndfa" which makes nondeterministic finite state automata.
+
+ o "progress" which means output of a progress bar showing how many
+ states were generated so far for automaton being processed. */
+DEF_RTL_EXPR(AUTOMATA_OPTION, "automata_option", "s", RTX_EXTRA)
+
+/* (define_reservation string string) names reservation (the first
+ string) of cpu functional units (the 2nd string). Sometimes unit
+ reservations for different insns contain common parts. In such
+ case, you can describe common part and use its name (the 1st
+ parameter) in regular expression in define_insn_reservation. All
+ define_reservations, define_cpu_units, and define_query_cpu_units
+ should have unique names which may not be "nothing". */
+DEF_RTL_EXPR(DEFINE_RESERVATION, "define_reservation", "ss", RTX_EXTRA)
+
+/* (define_insn_reservation name default_latency condition regexpr)
+ describes reservation of cpu functional units (the 3nd operand) for
+ instruction which is selected by the condition (the 2nd parameter).
+ The first parameter is used for output of debugging information.
+ The reservations are described by a regular expression according
+ the following syntax:
+
+ regexp = regexp "," oneof
+ | oneof
+
+ oneof = oneof "|" allof
+ | allof
+
+ allof = allof "+" repeat
+ | repeat
+
+ repeat = element "*" number
+ | element
+
+ element = cpu_function_unit_name
+ | reservation_name
+ | result_name
+ | "nothing"
+ | "(" regexp ")"
+
+ 1. "," is used for describing start of the next cycle in
+ reservation.
+
+ 2. "|" is used for describing the reservation described by the
+ first regular expression *or* the reservation described by the
+ second regular expression *or* etc.
+
+ 3. "+" is used for describing the reservation described by the
+ first regular expression *and* the reservation described by the
+ second regular expression *and* etc.
+
+ 4. "*" is used for convenience and simply means sequence in
+ which the regular expression are repeated NUMBER times with
+ cycle advancing (see ",").
+
+ 5. cpu functional unit name which means its reservation.
+
+ 6. reservation name -- see define_reservation.
+
+ 7. string "nothing" means no units reservation. */
+
+DEF_RTL_EXPR(DEFINE_INSN_RESERVATION, "define_insn_reservation", "sies", RTX_EXTRA)
+
+/* Expressions used for insn attributes. */
+
+/* Definition of an insn attribute.
+ 1st operand: name of the attribute
+ 2nd operand: comma-separated list of possible attribute values
+ 3rd operand: expression for the default value of the attribute. */
+DEF_RTL_EXPR(DEFINE_ATTR, "define_attr", "sse", RTX_EXTRA)
+
+/* Definition of an insn attribute that uses an existing enumerated type.
+ 1st operand: name of the attribute
+ 2nd operand: the name of the enumerated type
+ 3rd operand: expression for the default value of the attribute. */
+DEF_RTL_EXPR(DEFINE_ENUM_ATTR, "define_enum_attr", "sse", RTX_EXTRA)
+
+/* Marker for the name of an attribute. */
+DEF_RTL_EXPR(ATTR, "attr", "s", RTX_EXTRA)
+
+/* For use in the last (optional) operand of DEFINE_INSN or DEFINE_PEEPHOLE and
+ in DEFINE_ASM_INSN to specify an attribute to assign to insns matching that
+ pattern.
+
+ (set_attr "name" "value") is equivalent to
+ (set (attr "name") (const_string "value")) */
+DEF_RTL_EXPR(SET_ATTR, "set_attr", "ss", RTX_EXTRA)
+
+/* In the last operand of DEFINE_INSN and DEFINE_PEEPHOLE, this can be used to
+ specify that attribute values are to be assigned according to the
+ alternative matched.
+
+ The following three expressions are equivalent:
+
+ (set (attr "att") (cond [(eq_attrq "alternative" "1") (const_string "a1")
+ (eq_attrq "alternative" "2") (const_string "a2")]
+ (const_string "a3")))
+ (set_attr_alternative "att" [(const_string "a1") (const_string "a2")
+ (const_string "a3")])
+ (set_attr "att" "a1,a2,a3")
+ */
+DEF_RTL_EXPR(SET_ATTR_ALTERNATIVE, "set_attr_alternative", "sE", RTX_EXTRA)
+
+/* A conditional expression true if the value of the specified attribute of
+ the current insn equals the specified value. The first operand is the
+ attribute name and the second is the comparison value. */
+DEF_RTL_EXPR(EQ_ATTR, "eq_attr", "ss", RTX_EXTRA)
+
+/* A special case of the above representing a set of alternatives. The first
+ operand is bitmap of the set, the second one is the default value. */
+DEF_RTL_EXPR(EQ_ATTR_ALT, "eq_attr_alt", "ww", RTX_EXTRA)
+
+/* A conditional expression which is true if the specified flag is
+ true for the insn being scheduled in reorg.
+
+ genattr.cc defines the following flags which can be tested by
+ (attr_flag "foo") expressions in eligible_for_delay: forward, backward. */
+
+DEF_RTL_EXPR (ATTR_FLAG, "attr_flag", "s", RTX_EXTRA)
+
+/* General conditional. The first operand is a vector composed of pairs of
+ expressions. The first element of each pair is evaluated, in turn.
+ The value of the conditional is the second expression of the first pair
+ whose first expression evaluates nonzero. If none of the expressions is
+ true, the second operand will be used as the value of the conditional. */
+DEF_RTL_EXPR(COND, "cond", "Ee", RTX_EXTRA)
+
+/* Definition of a pattern substitution meta operation on a DEFINE_EXPAND
+ or a DEFINE_INSN. Automatically generates new instances of DEFINE_INSNs
+ that match the substitution pattern.
+
+ Operand:
+ 0: The name of the substitition template.
+ 1: Input template to match to see if a substitution is applicable.
+ 2: A C expression giving an additional condition for the generated
+ new define_expand or define_insn.
+ 3: Output tempalate to generate via substitution.
+
+ Within a DEFINE_SUBST template, the meaning of some RTL expressions is
+ different from their usual interpretation: a MATCH_OPERAND matches any
+ expression tree with matching machine mode or with VOIDmode. Likewise,
+ MATCH_OP_DUP and MATCH_DUP match more liberally in a DEFINE_SUBST than
+ in other RTL expressions. MATCH_OPERATOR matches all common operators
+ but also UNSPEC, UNSPEC_VOLATILE, and MATCH_OPERATORS from the input
+ DEFINE_EXPAND or DEFINE_INSN. */
+DEF_RTL_EXPR(DEFINE_SUBST, "define_subst", "sEsE", RTX_EXTRA)
+
+/* Substitution attribute to apply a DEFINE_SUBST to a pattern.
+
+ Operand:
+ 0: The name of the subst-attribute.
+ 1: The name of the DEFINE_SUBST to be applied for this attribute.
+ 2: String to substitute for the subst-attribute name in the pattern
+ name, for the case that the DEFINE_SUBST is not applied (i.e. the
+ unmodified version of the pattern).
+ 3: String to substitute for the subst-attribute name in the pattern
+ name, for the case that the DEFINE_SUBST is applied to the patten.
+
+ The use of DEFINE_SUBST and DEFINE_SUBST_ATTR is explained in the
+ GCC internals manual, under "RTL Templates Transformations". */
+DEF_RTL_EXPR(DEFINE_SUBST_ATTR, "define_subst_attr", "ssss", RTX_EXTRA)
+
+#endif /* GENERATOR_FILE */
+
+/*
+Local variables:
+mode:c
+End:
+*/
diff --git a/support/cpp/gcc/rtl.h b/support/cpp/gcc/rtl.h
new file mode 100644
index 000000000..764795e7c
--- /dev/null
+++ b/support/cpp/gcc/rtl.h
@@ -0,0 +1,4623 @@
+/* Register Transfer Language (RTL) definitions for GCC
+ 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/>. */
+
+#if 0 // ndef GCC_RTL_H
+#define GCC_RTL_H
+
+/* This file is occasionally included by generator files which expect
+ machmode.h and other files to exist and would not normally have been
+ included by coretypes.h. */
+#ifdef GENERATOR_FILE
+#include "real.h"
+#include "fixed-value.h"
+#include "statistics.h"
+#include "vec.h"
+#include "hash-table.h"
+#include "hash-set.h"
+#include "input.h"
+#include "is-a.h"
+#endif /* GENERATOR_FILE */
+
+#include "hard-reg-set.h"
+
+class predefined_function_abi;
+
+/* Value used by some passes to "recognize" noop moves as valid
+ instructions. */
+#define NOOP_MOVE_INSN_CODE INT_MAX
+
+/* Register Transfer Language EXPRESSIONS CODES */
+
+#define RTX_CODE enum rtx_code
+enum rtx_code {
+
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) ENUM ,
+#include "rtl.def" /* rtl expressions are documented here */
+#undef DEF_RTL_EXPR
+
+ LAST_AND_UNUSED_RTX_CODE}; /* A convenient way to get a value for
+ NUM_RTX_CODE.
+ Assumes default enum value assignment. */
+
+/* The cast here, saves many elsewhere. */
+#define NUM_RTX_CODE ((int) LAST_AND_UNUSED_RTX_CODE)
+
+/* Similar, but since generator files get more entries... */
+#ifdef GENERATOR_FILE
+# define NON_GENERATOR_NUM_RTX_CODE ((int) MATCH_OPERAND)
+#endif
+
+/* Register Transfer Language EXPRESSIONS CODE CLASSES */
+
+enum rtx_class {
+ /* We check bit 0-1 of some rtx class codes in the predicates below. */
+
+ /* Bit 0 = comparison if 0, arithmetic is 1
+ Bit 1 = 1 if commutative. */
+ RTX_COMPARE, /* 0 */
+ RTX_COMM_COMPARE,
+ RTX_BIN_ARITH,
+ RTX_COMM_ARITH,
+
+ /* Must follow the four preceding values. */
+ RTX_UNARY, /* 4 */
+
+ RTX_EXTRA,
+ RTX_MATCH,
+ RTX_INSN,
+
+ /* Bit 0 = 1 if constant. */
+ RTX_OBJ, /* 8 */
+ RTX_CONST_OBJ,
+
+ RTX_TERNARY,
+ RTX_BITFIELD_OPS,
+ RTX_AUTOINC
+};
+
+#define RTX_OBJ_MASK (~1)
+#define RTX_OBJ_RESULT (RTX_OBJ & RTX_OBJ_MASK)
+#define RTX_COMPARE_MASK (~1)
+#define RTX_COMPARE_RESULT (RTX_COMPARE & RTX_COMPARE_MASK)
+#define RTX_ARITHMETIC_MASK (~1)
+#define RTX_ARITHMETIC_RESULT (RTX_COMM_ARITH & RTX_ARITHMETIC_MASK)
+#define RTX_BINARY_MASK (~3)
+#define RTX_BINARY_RESULT (RTX_COMPARE & RTX_BINARY_MASK)
+#define RTX_COMMUTATIVE_MASK (~2)
+#define RTX_COMMUTATIVE_RESULT (RTX_COMM_COMPARE & RTX_COMMUTATIVE_MASK)
+#define RTX_NON_COMMUTATIVE_RESULT (RTX_COMPARE & RTX_COMMUTATIVE_MASK)
+
+extern const unsigned char rtx_length[NUM_RTX_CODE];
+#define GET_RTX_LENGTH(CODE) (rtx_length[(int) (CODE)])
+
+extern const char * const rtx_name[NUM_RTX_CODE];
+#define GET_RTX_NAME(CODE) (rtx_name[(int) (CODE)])
+
+extern const char * const rtx_format[NUM_RTX_CODE];
+#define GET_RTX_FORMAT(CODE) (rtx_format[(int) (CODE)])
+
+extern const enum rtx_class rtx_class[NUM_RTX_CODE];
+#define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)])
+
+/* True if CODE is part of the insn chain (i.e. has INSN_UID, PREV_INSN
+ and NEXT_INSN fields). */
+#define INSN_CHAIN_CODE_P(CODE) IN_RANGE (CODE, DEBUG_INSN, NOTE)
+
+extern const unsigned char rtx_code_size[NUM_RTX_CODE];
+extern const unsigned char rtx_next[NUM_RTX_CODE];
+
+/* The flags and bitfields of an ADDR_DIFF_VEC. BASE is the base label
+ relative to which the offsets are calculated, as explained in rtl.def. */
+struct addr_diff_vec_flags
+{
+ /* Set at the start of shorten_branches - ONLY WHEN OPTIMIZING - : */
+ unsigned min_align: 8;
+ /* Flags: */
+ unsigned base_after_vec: 1; /* BASE is after the ADDR_DIFF_VEC. */
+ unsigned min_after_vec: 1; /* minimum address target label is
+ after the ADDR_DIFF_VEC. */
+ unsigned max_after_vec: 1; /* maximum address target label is
+ after the ADDR_DIFF_VEC. */
+ unsigned min_after_base: 1; /* minimum address target label is
+ after BASE. */
+ unsigned max_after_base: 1; /* maximum address target label is
+ after BASE. */
+ /* Set by the actual branch shortening process - ONLY WHEN OPTIMIZING - : */
+ unsigned offset_unsigned: 1; /* offsets have to be treated as unsigned. */
+ unsigned : 2;
+ unsigned scale : 8;
+};
+
+/* Structure used to describe the attributes of a MEM. These are hashed
+ so MEMs that the same attributes share a data structure. This means
+ they cannot be modified in place. */
+class GTY(()) mem_attrs
+{
+public:
+ mem_attrs ();
+
+ /* The expression that the MEM accesses, or null if not known.
+ This expression might be larger than the memory reference itself.
+ (In other words, the MEM might access only part of the object.) */
+ tree expr;
+
+ /* The offset of the memory reference from the start of EXPR.
+ Only valid if OFFSET_KNOWN_P. */
+ poly_int64 offset;
+
+ /* The size of the memory reference in bytes. Only valid if
+ SIZE_KNOWN_P. */
+ poly_int64 size;
+
+ /* The alias set of the memory reference. */
+ alias_set_type alias;
+
+ /* The alignment of the reference in bits. Always a multiple of
+ BITS_PER_UNIT. Note that EXPR may have a stricter alignment
+ than the memory reference itself. */
+ unsigned int align;
+
+ /* The address space that the memory reference uses. */
+ unsigned char addrspace;
+
+ /* True if OFFSET is known. */
+ bool offset_known_p;
+
+ /* True if SIZE is known. */
+ bool size_known_p;
+};
+
+/* Structure used to describe the attributes of a REG in similar way as
+ mem_attrs does for MEM above. Note that the OFFSET field is calculated
+ in the same way as for mem_attrs, rather than in the same way as a
+ SUBREG_BYTE. For example, if a big-endian target stores a byte
+ object in the low part of a 4-byte register, the OFFSET field
+ will be -3 rather than 0. */
+
+class GTY((for_user)) reg_attrs {
+public:
+ tree decl; /* decl corresponding to REG. */
+ poly_int64 offset; /* Offset from start of DECL. */
+};
+
+/* Common union for an element of an rtx. */
+
+union rtunion
+{
+ int rt_int;
+ unsigned int rt_uint;
+ poly_uint16_pod rt_subreg;
+ const char *rt_str;
+ rtx rt_rtx;
+ rtvec rt_rtvec;
+ machine_mode rt_type;
+ addr_diff_vec_flags rt_addr_diff_vec_flags;
+ struct cselib_val *rt_cselib;
+ tree rt_tree;
+ basic_block rt_bb;
+ mem_attrs *rt_mem;
+ class constant_descriptor_rtx *rt_constant;
+ struct dw_cfi_node *rt_cfi;
+};
+
+/* Describes the properties of a REG. */
+struct GTY(()) reg_info {
+ /* The value of REGNO. */
+ unsigned int regno;
+
+ /* The value of REG_NREGS. */
+ unsigned int nregs : 8;
+ unsigned int unused : 24;
+
+ /* The value of REG_ATTRS. */
+ reg_attrs *attrs;
+};
+
+/* This structure remembers the position of a SYMBOL_REF within an
+ object_block structure. A SYMBOL_REF only provides this information
+ if SYMBOL_REF_HAS_BLOCK_INFO_P is true. */
+struct GTY(()) block_symbol {
+ /* The usual SYMBOL_REF fields. */
+ rtunion GTY ((skip)) fld[2];
+
+ /* The block that contains this object. */
+ struct object_block *block;
+
+ /* The offset of this object from the start of its block. It is negative
+ if the symbol has not yet been assigned an offset. */
+ HOST_WIDE_INT offset;
+};
+
+/* Describes a group of objects that are to be placed together in such
+ a way that their relative positions are known. */
+struct GTY((for_user)) object_block {
+ /* The section in which these objects should be placed. */
+ section *sect;
+
+ /* The alignment of the first object, measured in bits. */
+ unsigned int alignment;
+
+ /* The total size of the objects, measured in bytes. */
+ HOST_WIDE_INT size;
+
+ /* The SYMBOL_REFs for each object. The vector is sorted in
+ order of increasing offset and the following conditions will
+ hold for each element X:
+
+ SYMBOL_REF_HAS_BLOCK_INFO_P (X)
+ !SYMBOL_REF_ANCHOR_P (X)
+ SYMBOL_REF_BLOCK (X) == [address of this structure]
+ SYMBOL_REF_BLOCK_OFFSET (X) >= 0. */
+ vec<rtx, va_gc> *objects;
+
+ /* All the anchor SYMBOL_REFs used to address these objects, sorted
+ in order of increasing offset, and then increasing TLS model.
+ The following conditions will hold for each element X in this vector:
+
+ SYMBOL_REF_HAS_BLOCK_INFO_P (X)
+ SYMBOL_REF_ANCHOR_P (X)
+ SYMBOL_REF_BLOCK (X) == [address of this structure]
+ SYMBOL_REF_BLOCK_OFFSET (X) >= 0. */
+ vec<rtx, va_gc> *anchors;
+};
+
+struct GTY((variable_size)) hwivec_def {
+ HOST_WIDE_INT elem[1];
+};
+
+/* Number of elements of the HWIVEC if RTX is a CONST_WIDE_INT. */
+#define CWI_GET_NUM_ELEM(RTX) \
+ ((int)RTL_FLAG_CHECK1("CWI_GET_NUM_ELEM", (RTX), CONST_WIDE_INT)->u2.num_elem)
+#define CWI_PUT_NUM_ELEM(RTX, NUM) \
+ (RTL_FLAG_CHECK1("CWI_PUT_NUM_ELEM", (RTX), CONST_WIDE_INT)->u2.num_elem = (NUM))
+
+struct GTY((variable_size)) const_poly_int_def {
+ trailing_wide_ints<NUM_POLY_INT_COEFFS> coeffs;
+};
+
+/* RTL expression ("rtx"). */
+
+/* The GTY "desc" and "tag" options below are a kludge: we need a desc
+ field for gengtype to recognize that inheritance is occurring,
+ so that all subclasses are redirected to the traversal hook for the
+ base class.
+ However, all of the fields are in the base class, and special-casing
+ is at work. Hence we use desc and tag of 0, generating a switch
+ statement of the form:
+ switch (0)
+ {
+ case 0: // all the work happens here
+ }
+ in order to work with the existing special-casing in gengtype. */
+
+struct GTY((desc("0"), tag("0"),
+ chain_next ("RTX_NEXT (&%h)"),
+ chain_prev ("RTX_PREV (&%h)"))) rtx_def {
+ /* The kind of expression this is. */
+ ENUM_BITFIELD(rtx_code) code: 16;
+
+ /* The kind of value the expression has. */
+ ENUM_BITFIELD(machine_mode) mode : 8;
+
+ /* 1 in a MEM if we should keep the alias set for this mem unchanged
+ when we access a component.
+ 1 in a JUMP_INSN if it is a crossing jump.
+ 1 in a CALL_INSN if it is a sibling call.
+ 1 in a SET that is for a return.
+ In a CODE_LABEL, part of the two-bit alternate entry field.
+ 1 in a CONCAT is VAL_EXPR_IS_COPIED in var-tracking.cc.
+ 1 in a VALUE is SP_BASED_VALUE_P in cselib.cc.
+ 1 in a SUBREG generated by LRA for reload insns.
+ 1 in a REG if this is a static chain register.
+ Dumped as "/j" in RTL dumps. */
+ unsigned int jump : 1;
+ /* In a CODE_LABEL, part of the two-bit alternate entry field.
+ 1 in a MEM if it cannot trap.
+ 1 in a CALL_INSN logically equivalent to
+ ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P.
+ 1 in a VALUE is SP_DERIVED_VALUE_P in cselib.cc.
+ Dumped as "/c" in RTL dumps. */
+ unsigned int call : 1;
+ /* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
+ 1 in a SUBREG used for SUBREG_PROMOTED_UNSIGNED_P.
+ 1 in a SYMBOL_REF if it addresses something in the per-function
+ constants pool.
+ 1 in a CALL_INSN logically equivalent to ECF_CONST and TREE_READONLY.
+ 1 in a NOTE, or EXPR_LIST for a const call.
+ 1 in a JUMP_INSN of an annulling branch.
+ 1 in a CONCAT is VAL_EXPR_IS_CLOBBERED in var-tracking.cc.
+ 1 in a preserved VALUE is PRESERVED_VALUE_P in cselib.cc.
+ 1 in a clobber temporarily created for LRA.
+ Dumped as "/u" in RTL dumps. */
+ unsigned int unchanging : 1;
+ /* 1 in a MEM or ASM_OPERANDS expression if the memory reference is volatile.
+ 1 in an INSN, CALL_INSN, JUMP_INSN, CODE_LABEL, BARRIER, or NOTE
+ if it has been deleted.
+ 1 in a REG expression if corresponds to a variable declared by the user,
+ 0 for an internally generated temporary.
+ 1 in a SUBREG used for SUBREG_PROMOTED_UNSIGNED_P.
+ 1 in a LABEL_REF, REG_LABEL_TARGET or REG_LABEL_OPERAND note for a
+ non-local label.
+ In a SYMBOL_REF, this flag is used for machine-specific purposes.
+ In a PREFETCH, this flag indicates that it should be considered a
+ scheduling barrier.
+ 1 in a CONCAT is VAL_NEEDS_RESOLUTION in var-tracking.cc.
+ Dumped as "/v" in RTL dumps. */
+ unsigned int volatil : 1;
+ /* 1 in a REG if the register is used only in exit code a loop.
+ 1 in a SUBREG expression if was generated from a variable with a
+ promoted mode.
+ 1 in a CODE_LABEL if the label is used for nonlocal gotos
+ and must not be deleted even if its count is zero.
+ 1 in an INSN, JUMP_INSN or CALL_INSN if this insn must be scheduled
+ together with the preceding insn. Valid only within sched.
+ 1 in an INSN, JUMP_INSN, or CALL_INSN if insn is in a delay slot and
+ from the target of a branch. Valid from reorg until end of compilation;
+ cleared before used.
+
+ The name of the field is historical. It used to be used in MEMs
+ to record whether the MEM accessed part of a structure.
+ Dumped as "/s" in RTL dumps. */
+ unsigned int in_struct : 1;
+ /* At the end of RTL generation, 1 if this rtx is used. This is used for
+ copying shared structure. See `unshare_all_rtl'.
+ In a REG, this is not needed for that purpose, and used instead
+ in `leaf_renumber_regs_insn'.
+ 1 in a SYMBOL_REF, means that emit_library_call
+ has used it as the function.
+ 1 in a CONCAT is VAL_HOLDS_TRACK_EXPR in var-tracking.cc.
+ 1 in a VALUE or DEBUG_EXPR is VALUE_RECURSED_INTO in var-tracking.cc. */
+ unsigned int used : 1;
+ /* 1 in an INSN or a SET if this rtx is related to the call frame,
+ either changing how we compute the frame address or saving and
+ restoring registers in the prologue and epilogue.
+ 1 in a REG or MEM if it is a pointer.
+ 1 in a SYMBOL_REF if it addresses something in the per-function
+ constant string pool.
+ 1 in a VALUE is VALUE_CHANGED in var-tracking.cc.
+ Dumped as "/f" in RTL dumps. */
+ unsigned frame_related : 1;
+ /* 1 in a REG or PARALLEL that is the current function's return value.
+ 1 in a SYMBOL_REF for a weak symbol.
+ 1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P.
+ 1 in a CONCAT is VAL_EXPR_HAS_REVERSE in var-tracking.cc.
+ 1 in a VALUE or DEBUG_EXPR is NO_LOC_P in var-tracking.cc.
+ Dumped as "/i" in RTL dumps. */
+ unsigned return_val : 1;
+
+ union {
+ /* The final union field is aligned to 64 bits on LP64 hosts,
+ giving a 32-bit gap after the fields above. We optimize the
+ layout for that case and use the gap for extra code-specific
+ information. */
+
+ /* The ORIGINAL_REGNO of a REG. */
+ unsigned int original_regno;
+
+ /* The INSN_UID of an RTX_INSN-class code. */
+ int insn_uid;
+
+ /* The SYMBOL_REF_FLAGS of a SYMBOL_REF. */
+ unsigned int symbol_ref_flags;
+
+ /* The PAT_VAR_LOCATION_STATUS of a VAR_LOCATION. */
+ enum var_init_status var_location_status;
+
+ /* In a CONST_WIDE_INT (aka hwivec_def), this is the number of
+ HOST_WIDE_INTs in the hwivec_def. */
+ unsigned int num_elem;
+
+ /* Information about a CONST_VECTOR. */
+ struct
+ {
+ /* The value of CONST_VECTOR_NPATTERNS. */
+ unsigned int npatterns : 16;
+
+ /* The value of CONST_VECTOR_NELTS_PER_PATTERN. */
+ unsigned int nelts_per_pattern : 8;
+
+ /* For future expansion. */
+ unsigned int unused : 8;
+ } const_vector;
+ } GTY ((skip)) u2;
+
+ /* The first element of the operands of this rtx.
+ The number of operands and their types are controlled
+ by the `code' field, according to rtl.def. */
+ union u {
+ rtunion fld[1];
+ HOST_WIDE_INT hwint[1];
+ struct reg_info reg;
+ struct block_symbol block_sym;
+ struct real_value rv;
+ struct fixed_value fv;
+ struct hwivec_def hwiv;
+ struct const_poly_int_def cpi;
+ } GTY ((special ("rtx_def"), desc ("GET_CODE (&%0)"))) u;
+};
+
+/* A node for constructing singly-linked lists of rtx. */
+
+struct GTY(()) rtx_expr_list : public rtx_def
+{
+private:
+ /* No extra fields, but adds invariant: (GET_CODE (X) == EXPR_LIST). */
+
+public:
+ /* Get next in list. */
+ rtx_expr_list *next () const;
+
+ /* Get at the underlying rtx. */
+ rtx element () const;
+};
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_expr_list *>::test (rtx rt)
+{
+ return rt->code == EXPR_LIST;
+}
+
+struct GTY(()) rtx_insn_list : public rtx_def
+{
+private:
+ /* No extra fields, but adds invariant: (GET_CODE (X) == INSN_LIST).
+
+ This is an instance of:
+
+ DEF_RTL_EXPR(INSN_LIST, "insn_list", "ue", RTX_EXTRA)
+
+ i.e. a node for constructing singly-linked lists of rtx_insn *, where
+ the list is "external" to the insn (as opposed to the doubly-linked
+ list embedded within rtx_insn itself). */
+
+public:
+ /* Get next in list. */
+ rtx_insn_list *next () const;
+
+ /* Get at the underlying instruction. */
+ rtx_insn *insn () const;
+
+};
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_insn_list *>::test (rtx rt)
+{
+ return rt->code == INSN_LIST;
+}
+
+/* A node with invariant GET_CODE (X) == SEQUENCE i.e. a vector of rtx,
+ typically (but not always) of rtx_insn *, used in the late passes. */
+
+struct GTY(()) rtx_sequence : public rtx_def
+{
+private:
+ /* No extra fields, but adds invariant: (GET_CODE (X) == SEQUENCE). */
+
+public:
+ /* Get number of elements in sequence. */
+ int len () const;
+
+ /* Get i-th element of the sequence. */
+ rtx element (int index) const;
+
+ /* Get i-th element of the sequence, with a checked cast to
+ rtx_insn *. */
+ rtx_insn *insn (int index) const;
+};
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_sequence *>::test (rtx rt)
+{
+ return rt->code == SEQUENCE;
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const rtx_sequence *>::test (const_rtx rt)
+{
+ return rt->code == SEQUENCE;
+}
+
+struct GTY(()) rtx_insn : public rtx_def
+{
+public:
+ /* No extra fields, but adds the invariant:
+
+ (INSN_P (X)
+ || NOTE_P (X)
+ || JUMP_TABLE_DATA_P (X)
+ || BARRIER_P (X)
+ || LABEL_P (X))
+
+ i.e. that we must be able to use the following:
+ INSN_UID ()
+ NEXT_INSN ()
+ PREV_INSN ()
+ i.e. we have an rtx that has an INSN_UID field and can be part of
+ a linked list of insns.
+ */
+
+ /* Returns true if this insn has been deleted. */
+
+ bool deleted () const { return volatil; }
+
+ /* Mark this insn as deleted. */
+
+ void set_deleted () { volatil = true; }
+
+ /* Mark this insn as not deleted. */
+
+ void set_undeleted () { volatil = false; }
+};
+
+/* Subclasses of rtx_insn. */
+
+struct GTY(()) rtx_debug_insn : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ DEBUG_INSN_P (X) aka (GET_CODE (X) == DEBUG_INSN)
+ i.e. an annotation for tracking variable assignments.
+
+ This is an instance of:
+ DEF_RTL_EXPR(DEBUG_INSN, "debug_insn", "uuBeiie", RTX_INSN)
+ from rtl.def. */
+};
+
+struct GTY(()) rtx_nonjump_insn : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ NONJUMP_INSN_P (X) aka (GET_CODE (X) == INSN)
+ i.e an instruction that cannot jump.
+
+ This is an instance of:
+ DEF_RTL_EXPR(INSN, "insn", "uuBeiie", RTX_INSN)
+ from rtl.def. */
+};
+
+struct GTY(()) rtx_jump_insn : public rtx_insn
+{
+public:
+ /* No extra fields, but adds the invariant:
+ JUMP_P (X) aka (GET_CODE (X) == JUMP_INSN)
+ i.e. an instruction that can possibly jump.
+
+ This is an instance of:
+ DEF_RTL_EXPR(JUMP_INSN, "jump_insn", "uuBeiie0", RTX_INSN)
+ from rtl.def. */
+
+ /* Returns jump target of this instruction. The returned value is not
+ necessarily a code label: it may also be a RETURN or SIMPLE_RETURN
+ expression. Also, when the code label is marked "deleted", it is
+ replaced by a NOTE. In some cases the value is NULL_RTX. */
+
+ inline rtx jump_label () const;
+
+ /* Returns jump target cast to rtx_code_label *. */
+
+ inline rtx_code_label *jump_target () const;
+
+ /* Set jump target. */
+
+ inline void set_jump_target (rtx_code_label *);
+};
+
+struct GTY(()) rtx_call_insn : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ CALL_P (X) aka (GET_CODE (X) == CALL_INSN)
+ i.e. an instruction that can possibly call a subroutine
+ but which will not change which instruction comes next
+ in the current function.
+
+ This is an instance of:
+ DEF_RTL_EXPR(CALL_INSN, "call_insn", "uuBeiiee", RTX_INSN)
+ from rtl.def. */
+};
+
+struct GTY(()) rtx_jump_table_data : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ JUMP_TABLE_DATA_P (X) aka (GET_CODE (INSN) == JUMP_TABLE_DATA)
+ i.e. a data for a jump table, considered an instruction for
+ historical reasons.
+
+ This is an instance of:
+ DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN)
+ from rtl.def. */
+
+ /* This can be either:
+
+ (a) a table of absolute jumps, in which case PATTERN (this) is an
+ ADDR_VEC with arg 0 a vector of labels, or
+
+ (b) a table of relative jumps (e.g. for -fPIC), in which case
+ PATTERN (this) is an ADDR_DIFF_VEC, with arg 0 a LABEL_REF and
+ arg 1 the vector of labels.
+
+ This method gets the underlying vec. */
+
+ inline rtvec get_labels () const;
+ inline scalar_int_mode get_data_mode () const;
+};
+
+struct GTY(()) rtx_barrier : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ BARRIER_P (X) aka (GET_CODE (X) == BARRIER)
+ i.e. a marker that indicates that control will not flow through.
+
+ This is an instance of:
+ DEF_RTL_EXPR(BARRIER, "barrier", "uu00000", RTX_EXTRA)
+ from rtl.def. */
+};
+
+struct GTY(()) rtx_code_label : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ LABEL_P (X) aka (GET_CODE (X) == CODE_LABEL)
+ i.e. a label in the assembler.
+
+ This is an instance of:
+ DEF_RTL_EXPR(CODE_LABEL, "code_label", "uuB00is", RTX_EXTRA)
+ from rtl.def. */
+};
+
+struct GTY(()) rtx_note : public rtx_insn
+{
+ /* No extra fields, but adds the invariant:
+ NOTE_P(X) aka (GET_CODE (X) == NOTE)
+ i.e. a note about the corresponding source code.
+
+ This is an instance of:
+ DEF_RTL_EXPR(NOTE, "note", "uuB0ni", RTX_EXTRA)
+ from rtl.def. */
+};
+
+/* The size in bytes of an rtx header (code, mode and flags). */
+#define RTX_HDR_SIZE offsetof (struct rtx_def, u)
+
+/* The size in bytes of an rtx with code CODE. */
+#define RTX_CODE_SIZE(CODE) rtx_code_size[CODE]
+
+#define NULL_RTX (rtx) 0
+
+/* The "next" and "previous" RTX, relative to this one. */
+
+#define RTX_NEXT(X) (rtx_next[GET_CODE (X)] == 0 ? NULL \
+ : *(rtx *)(((char *)X) + rtx_next[GET_CODE (X)]))
+
+/* FIXME: the "NEXT_INSN (PREV_INSN (X)) == X" condition shouldn't be needed.
+ */
+#define RTX_PREV(X) ((INSN_P (X) \
+ || NOTE_P (X) \
+ || JUMP_TABLE_DATA_P (X) \
+ || BARRIER_P (X) \
+ || LABEL_P (X)) \
+ && PREV_INSN (as_a <rtx_insn *> (X)) != NULL \
+ && NEXT_INSN (PREV_INSN (as_a <rtx_insn *> (X))) == X \
+ ? PREV_INSN (as_a <rtx_insn *> (X)) : NULL)
+
+/* Define macros to access the `code' field of the rtx. */
+
+#define GET_CODE(RTX) ((enum rtx_code) (RTX)->code)
+#define PUT_CODE(RTX, CODE) ((RTX)->code = (CODE))
+
+#define GET_MODE(RTX) ((machine_mode) (RTX)->mode)
+#define PUT_MODE_RAW(RTX, MODE) ((RTX)->mode = (MODE))
+
+/* RTL vector. These appear inside RTX's when there is a need
+ for a variable number of things. The principle use is inside
+ PARALLEL expressions. */
+
+struct GTY(()) rtvec_def {
+ int num_elem; /* number of elements */
+ rtx GTY ((length ("%h.num_elem"))) elem[1];
+};
+
+#define NULL_RTVEC (rtvec) 0
+
+#define GET_NUM_ELEM(RTVEC) ((RTVEC)->num_elem)
+#define PUT_NUM_ELEM(RTVEC, NUM) ((RTVEC)->num_elem = (NUM))
+
+/* Predicate yielding nonzero iff X is an rtx for a register. */
+#define REG_P(X) (GET_CODE (X) == REG)
+
+/* Predicate yielding nonzero iff X is an rtx for a memory location. */
+#define MEM_P(X) (GET_CODE (X) == MEM)
+
+#if TARGET_SUPPORTS_WIDE_INT
+
+/* Match CONST_*s that can represent compile-time constant integers. */
+#define CASE_CONST_SCALAR_INT \
+ case CONST_INT: \
+ case CONST_WIDE_INT
+
+/* Match CONST_*s for which pointer equality corresponds to value
+ equality. */
+#define CASE_CONST_UNIQUE \
+ case CONST_INT: \
+ case CONST_WIDE_INT: \
+ case CONST_POLY_INT: \
+ case CONST_DOUBLE: \
+ case CONST_FIXED
+
+/* Match all CONST_* rtxes. */
+#define CASE_CONST_ANY \
+ case CONST_INT: \
+ case CONST_WIDE_INT: \
+ case CONST_POLY_INT: \
+ case CONST_DOUBLE: \
+ case CONST_FIXED: \
+ case CONST_VECTOR
+
+#else
+
+/* Match CONST_*s that can represent compile-time constant integers. */
+#define CASE_CONST_SCALAR_INT \
+ case CONST_INT: \
+ case CONST_DOUBLE
+
+/* Match CONST_*s for which pointer equality corresponds to value
+ equality. */
+#define CASE_CONST_UNIQUE \
+ case CONST_INT: \
+ case CONST_DOUBLE: \
+ case CONST_FIXED
+
+/* Match all CONST_* rtxes. */
+#define CASE_CONST_ANY \
+ case CONST_INT: \
+ case CONST_DOUBLE: \
+ case CONST_FIXED: \
+ case CONST_VECTOR
+#endif
+
+/* Predicate yielding nonzero iff X is an rtx for a constant integer. */
+#define CONST_INT_P(X) (GET_CODE (X) == CONST_INT)
+
+/* Predicate yielding nonzero iff X is an rtx for a constant integer. */
+#define CONST_WIDE_INT_P(X) (GET_CODE (X) == CONST_WIDE_INT)
+
+/* Predicate yielding nonzero iff X is an rtx for a polynomial constant
+ integer. */
+#define CONST_POLY_INT_P(X) \
+ (NUM_POLY_INT_COEFFS > 1 && GET_CODE (X) == CONST_POLY_INT)
+
+/* Predicate yielding nonzero iff X is an rtx for a constant fixed-point. */
+#define CONST_FIXED_P(X) (GET_CODE (X) == CONST_FIXED)
+
+/* Predicate yielding true iff X is an rtx for a double-int
+ or floating point constant. */
+#define CONST_DOUBLE_P(X) (GET_CODE (X) == CONST_DOUBLE)
+
+/* Predicate yielding true iff X is an rtx for a double-int. */
+#define CONST_DOUBLE_AS_INT_P(X) \
+ (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == VOIDmode)
+
+/* Predicate yielding true iff X is an rtx for a integer const. */
+#if TARGET_SUPPORTS_WIDE_INT
+#define CONST_SCALAR_INT_P(X) \
+ (CONST_INT_P (X) || CONST_WIDE_INT_P (X))
+#else
+#define CONST_SCALAR_INT_P(X) \
+ (CONST_INT_P (X) || CONST_DOUBLE_AS_INT_P (X))
+#endif
+
+/* Predicate yielding true iff X is an rtx for a double-int. */
+#define CONST_DOUBLE_AS_FLOAT_P(X) \
+ (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode)
+
+/* Predicate yielding nonzero iff X is an rtx for a constant vector. */
+#define CONST_VECTOR_P(X) (GET_CODE (X) == CONST_VECTOR)
+
+/* Predicate yielding nonzero iff X is a label insn. */
+#define LABEL_P(X) (GET_CODE (X) == CODE_LABEL)
+
+/* Predicate yielding nonzero iff X is a jump insn. */
+#define JUMP_P(X) (GET_CODE (X) == JUMP_INSN)
+
+/* Predicate yielding nonzero iff X is a call insn. */
+#define CALL_P(X) (GET_CODE (X) == CALL_INSN)
+
+/* 1 if RTX is a call_insn for a fake call.
+ CALL_INSN use "used" flag to indicate it's a fake call. */
+#define FAKE_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("FAKE_CALL_P", (RTX), CALL_INSN)->used)
+
+/* Predicate yielding nonzero iff X is an insn that cannot jump. */
+#define NONJUMP_INSN_P(X) (GET_CODE (X) == INSN)
+
+/* Predicate yielding nonzero iff X is a debug note/insn. */
+#define DEBUG_INSN_P(X) (GET_CODE (X) == DEBUG_INSN)
+
+/* Predicate yielding nonzero iff X is an insn that is not a debug insn. */
+#define NONDEBUG_INSN_P(X) (NONJUMP_INSN_P (X) || JUMP_P (X) || CALL_P (X))
+
+/* Nonzero if DEBUG_MARKER_INSN_P may possibly hold. */
+#define MAY_HAVE_DEBUG_MARKER_INSNS debug_nonbind_markers_p
+/* Nonzero if DEBUG_BIND_INSN_P may possibly hold. */
+#define MAY_HAVE_DEBUG_BIND_INSNS flag_var_tracking_assignments
+/* Nonzero if DEBUG_INSN_P may possibly hold. */
+#define MAY_HAVE_DEBUG_INSNS \
+ (MAY_HAVE_DEBUG_MARKER_INSNS || MAY_HAVE_DEBUG_BIND_INSNS)
+
+/* Predicate yielding nonzero iff X is a real insn. */
+#define INSN_P(X) (NONDEBUG_INSN_P (X) || DEBUG_INSN_P (X))
+
+/* Predicate yielding nonzero iff X is a note insn. */
+#define NOTE_P(X) (GET_CODE (X) == NOTE)
+
+/* Predicate yielding nonzero iff X is a barrier insn. */
+#define BARRIER_P(X) (GET_CODE (X) == BARRIER)
+
+/* Predicate yielding nonzero iff X is a data for a jump table. */
+#define JUMP_TABLE_DATA_P(INSN) (GET_CODE (INSN) == JUMP_TABLE_DATA)
+
+/* Predicate yielding nonzero iff RTX is a subreg. */
+#define SUBREG_P(RTX) (GET_CODE (RTX) == SUBREG)
+
+/* Predicate yielding true iff RTX is a symbol ref. */
+#define SYMBOL_REF_P(RTX) (GET_CODE (RTX) == SYMBOL_REF)
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_insn *>::test (rtx rt)
+{
+ return (INSN_P (rt)
+ || NOTE_P (rt)
+ || JUMP_TABLE_DATA_P (rt)
+ || BARRIER_P (rt)
+ || LABEL_P (rt));
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <const rtx_insn *>::test (const_rtx rt)
+{
+ return (INSN_P (rt)
+ || NOTE_P (rt)
+ || JUMP_TABLE_DATA_P (rt)
+ || BARRIER_P (rt)
+ || LABEL_P (rt));
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_debug_insn *>::test (rtx rt)
+{
+ return DEBUG_INSN_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_nonjump_insn *>::test (rtx rt)
+{
+ return NONJUMP_INSN_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_jump_insn *>::test (rtx rt)
+{
+ return JUMP_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_jump_insn *>::test (rtx_insn *insn)
+{
+ return JUMP_P (insn);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_call_insn *>::test (rtx rt)
+{
+ return CALL_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_call_insn *>::test (rtx_insn *insn)
+{
+ return CALL_P (insn);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_jump_table_data *>::test (rtx rt)
+{
+ return JUMP_TABLE_DATA_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_jump_table_data *>::test (rtx_insn *insn)
+{
+ return JUMP_TABLE_DATA_P (insn);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_barrier *>::test (rtx rt)
+{
+ return BARRIER_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_code_label *>::test (rtx rt)
+{
+ return LABEL_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_code_label *>::test (rtx_insn *insn)
+{
+ return LABEL_P (insn);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_note *>::test (rtx rt)
+{
+ return NOTE_P (rt);
+}
+
+template <>
+template <>
+inline bool
+is_a_helper <rtx_note *>::test (rtx_insn *insn)
+{
+ return NOTE_P (insn);
+}
+
+/* Predicate yielding nonzero iff X is a return or simple_return. */
+#define ANY_RETURN_P(X) \
+ (GET_CODE (X) == RETURN || GET_CODE (X) == SIMPLE_RETURN)
+
+/* 1 if X is a unary operator. */
+
+#define UNARY_P(X) \
+ (GET_RTX_CLASS (GET_CODE (X)) == RTX_UNARY)
+
+/* 1 if X is a binary operator. */
+
+#define BINARY_P(X) \
+ ((GET_RTX_CLASS (GET_CODE (X)) & RTX_BINARY_MASK) == RTX_BINARY_RESULT)
+
+/* 1 if X is an arithmetic operator. */
+
+#define ARITHMETIC_P(X) \
+ ((GET_RTX_CLASS (GET_CODE (X)) & RTX_ARITHMETIC_MASK) \
+ == RTX_ARITHMETIC_RESULT)
+
+/* 1 if X is an arithmetic operator. */
+
+#define COMMUTATIVE_ARITH_P(X) \
+ (GET_RTX_CLASS (GET_CODE (X)) == RTX_COMM_ARITH)
+
+/* 1 if X is a commutative arithmetic operator or a comparison operator.
+ These two are sometimes selected together because it is possible to
+ swap the two operands. */
+
+#define SWAPPABLE_OPERANDS_P(X) \
+ ((1 << GET_RTX_CLASS (GET_CODE (X))) \
+ & ((1 << RTX_COMM_ARITH) | (1 << RTX_COMM_COMPARE) \
+ | (1 << RTX_COMPARE)))
+
+/* 1 if X is a non-commutative operator. */
+
+#define NON_COMMUTATIVE_P(X) \
+ ((GET_RTX_CLASS (GET_CODE (X)) & RTX_COMMUTATIVE_MASK) \
+ == RTX_NON_COMMUTATIVE_RESULT)
+
+/* 1 if X is a commutative operator on integers. */
+
+#define COMMUTATIVE_P(X) \
+ ((GET_RTX_CLASS (GET_CODE (X)) & RTX_COMMUTATIVE_MASK) \
+ == RTX_COMMUTATIVE_RESULT)
+
+/* 1 if X is a relational operator. */
+
+#define COMPARISON_P(X) \
+ ((GET_RTX_CLASS (GET_CODE (X)) & RTX_COMPARE_MASK) == RTX_COMPARE_RESULT)
+
+/* 1 if X is a constant value that is an integer. */
+
+#define CONSTANT_P(X) \
+ (GET_RTX_CLASS (GET_CODE (X)) == RTX_CONST_OBJ)
+
+/* 1 if X is a LABEL_REF. */
+#define LABEL_REF_P(X) \
+ (GET_CODE (X) == LABEL_REF)
+
+/* 1 if X can be used to represent an object. */
+#define OBJECT_P(X) \
+ ((GET_RTX_CLASS (GET_CODE (X)) & RTX_OBJ_MASK) == RTX_OBJ_RESULT)
+
+/* General accessor macros for accessing the fields of an rtx. */
+
+#if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
+/* The bit with a star outside the statement expr and an & inside is
+ so that N can be evaluated only once. */
+#define RTL_CHECK1(RTX, N, C1) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
+ rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ if (GET_RTX_FORMAT (_code)[_n] != C1) \
+ rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
+#define RTL_CHECK2(RTX, N, C1, C2) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
+ rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ if (GET_RTX_FORMAT (_code)[_n] != C1 \
+ && GET_RTX_FORMAT (_code)[_n] != C2) \
+ rtl_check_failed_type2 (_rtx, _n, C1, C2, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
+#define RTL_CHECKC1(RTX, N, C) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ if (GET_CODE (_rtx) != (C)) \
+ rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
+#define RTL_CHECKC2(RTX, N, C1, C2) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_code != (C1) && _code != (C2)) \
+ rtl_check_failed_code2 (_rtx, (C1), (C2), __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
+#define RTL_CHECKC3(RTX, N, C1, C2, C3) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_code != (C1) && _code != (C2) && _code != (C3)) \
+ rtl_check_failed_code3 (_rtx, (C1), (C2), (C3), __FILE__, \
+ __LINE__, __FUNCTION__); \
+ &_rtx->u.fld[_n]; }))
+
+#define RTVEC_ELT(RTVEC, I) __extension__ \
+(*({ __typeof (RTVEC) const _rtvec = (RTVEC); const int _i = (I); \
+ if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec)) \
+ rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtvec->elem[_i]; }))
+
+#define XWINT(RTX, N) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); const int _n = (N); \
+ const enum rtx_code _code = GET_CODE (_rtx); \
+ if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
+ rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ if (GET_RTX_FORMAT (_code)[_n] != 'w') \
+ rtl_check_failed_type1 (_rtx, _n, 'w', __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.hwint[_n]; }))
+
+#define CWI_ELT(RTX, I) __extension__ \
+(*({ __typeof (RTX) const _cwi = (RTX); \
+ int _max = CWI_GET_NUM_ELEM (_cwi); \
+ const int _i = (I); \
+ if (_i < 0 || _i >= _max) \
+ cwi_check_failed_bounds (_cwi, _i, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_cwi->u.hwiv.elem[_i]; }))
+
+#define XCWINT(RTX, N, C) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != (C)) \
+ rtl_check_failed_code1 (_rtx, (C), __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.hwint[N]; }))
+
+#define XCMWINT(RTX, N, C, M) __extension__ \
+(*({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != (C) || GET_MODE (_rtx) != (M)) \
+ rtl_check_failed_code_mode (_rtx, (C), (M), false, __FILE__, \
+ __LINE__, __FUNCTION__); \
+ &_rtx->u.hwint[N]; }))
+
+#define XCNMPRV(RTX, C, M) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != (C) || GET_MODE (_rtx) == (M)) \
+ rtl_check_failed_code_mode (_rtx, (C), (M), true, __FILE__, \
+ __LINE__, __FUNCTION__); \
+ &_rtx->u.rv; })
+
+#define XCNMPFV(RTX, C, M) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != (C) || GET_MODE (_rtx) == (M)) \
+ rtl_check_failed_code_mode (_rtx, (C), (M), true, __FILE__, \
+ __LINE__, __FUNCTION__); \
+ &_rtx->u.fv; })
+
+#define REG_CHECK(RTX) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != REG) \
+ rtl_check_failed_code1 (_rtx, REG, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_rtx->u.reg; })
+
+#define BLOCK_SYMBOL_CHECK(RTX) __extension__ \
+({ __typeof (RTX) const _symbol = (RTX); \
+ const unsigned int flags = SYMBOL_REF_FLAGS (_symbol); \
+ if ((flags & SYMBOL_FLAG_HAS_BLOCK_INFO) == 0) \
+ rtl_check_failed_block_symbol (__FILE__, __LINE__, \
+ __FUNCTION__); \
+ &_symbol->u.block_sym; })
+
+#define HWIVEC_CHECK(RTX,C) __extension__ \
+({ __typeof (RTX) const _symbol = (RTX); \
+ RTL_CHECKC1 (_symbol, 0, C); \
+ &_symbol->u.hwiv; })
+
+extern void rtl_check_failed_bounds (const_rtx, int, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_type1 (const_rtx, int, int, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_type2 (const_rtx, int, int, int, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_code1 (const_rtx, enum rtx_code, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_code2 (const_rtx, enum rtx_code, enum rtx_code,
+ const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_code3 (const_rtx, enum rtx_code, enum rtx_code,
+ enum rtx_code, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_code_mode (const_rtx, enum rtx_code, machine_mode,
+ bool, const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtl_check_failed_block_symbol (const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void cwi_check_failed_bounds (const_rtx, int, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void rtvec_check_failed_bounds (const_rtvec, int, const char *, int,
+ const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+
+#else /* not ENABLE_RTL_CHECKING */
+
+#define RTL_CHECK1(RTX, N, C1) ((RTX)->u.fld[N])
+#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->u.fld[N])
+#define RTL_CHECKC1(RTX, N, C) ((RTX)->u.fld[N])
+#define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->u.fld[N])
+#define RTL_CHECKC3(RTX, N, C1, C2, C3) ((RTX)->u.fld[N])
+#define RTVEC_ELT(RTVEC, I) ((RTVEC)->elem[I])
+#define XWINT(RTX, N) ((RTX)->u.hwint[N])
+#define CWI_ELT(RTX, I) ((RTX)->u.hwiv.elem[I])
+#define XCWINT(RTX, N, C) ((RTX)->u.hwint[N])
+#define XCMWINT(RTX, N, C, M) ((RTX)->u.hwint[N])
+#define XCNMWINT(RTX, N, C, M) ((RTX)->u.hwint[N])
+#define XCNMPRV(RTX, C, M) (&(RTX)->u.rv)
+#define XCNMPFV(RTX, C, M) (&(RTX)->u.fv)
+#define REG_CHECK(RTX) (&(RTX)->u.reg)
+#define BLOCK_SYMBOL_CHECK(RTX) (&(RTX)->u.block_sym)
+#define HWIVEC_CHECK(RTX,C) (&(RTX)->u.hwiv)
+
+#endif
+
+/* General accessor macros for accessing the flags of an rtx. */
+
+/* Access an individual rtx flag, with no checking of any kind. */
+#define RTX_FLAG(RTX, FLAG) ((RTX)->FLAG)
+
+#if defined ENABLE_RTL_FLAG_CHECKING && (GCC_VERSION >= 2007)
+#define RTL_FLAG_CHECK1(NAME, RTX, C1) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2) \
+ rtl_check_failed_flag (NAME,_rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE (_rtx) != C3) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1 && GET_CODE(_rtx) != C2 \
+ && GET_CODE (_rtx) != C3 && GET_CODE(_rtx) != C4) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2 \
+ && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4 \
+ && GET_CODE (_rtx) != C5) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6) \
+ __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2 \
+ && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4 \
+ && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6) \
+ rtl_check_failed_flag (NAME,_rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7) \
+ __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (GET_CODE (_rtx) != C1 && GET_CODE (_rtx) != C2 \
+ && GET_CODE (_rtx) != C3 && GET_CODE (_rtx) != C4 \
+ && GET_CODE (_rtx) != C5 && GET_CODE (_rtx) != C6 \
+ && GET_CODE (_rtx) != C7) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+#define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) \
+ __extension__ \
+({ __typeof (RTX) const _rtx = (RTX); \
+ if (!INSN_CHAIN_CODE_P (GET_CODE (_rtx))) \
+ rtl_check_failed_flag (NAME, _rtx, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _rtx; })
+
+extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+ ;
+
+#else /* not ENABLE_RTL_FLAG_CHECKING */
+
+#define RTL_FLAG_CHECK1(NAME, RTX, C1) (RTX)
+#define RTL_FLAG_CHECK2(NAME, RTX, C1, C2) (RTX)
+#define RTL_FLAG_CHECK3(NAME, RTX, C1, C2, C3) (RTX)
+#define RTL_FLAG_CHECK4(NAME, RTX, C1, C2, C3, C4) (RTX)
+#define RTL_FLAG_CHECK5(NAME, RTX, C1, C2, C3, C4, C5) (RTX)
+#define RTL_FLAG_CHECK6(NAME, RTX, C1, C2, C3, C4, C5, C6) (RTX)
+#define RTL_FLAG_CHECK7(NAME, RTX, C1, C2, C3, C4, C5, C6, C7) (RTX)
+#define RTL_INSN_CHAIN_FLAG_CHECK(NAME, RTX) (RTX)
+#endif
+
+#define XINT(RTX, N) (RTL_CHECK2 (RTX, N, 'i', 'n').rt_int)
+#define XUINT(RTX, N) (RTL_CHECK2 (RTX, N, 'i', 'n').rt_uint)
+#define XSTR(RTX, N) (RTL_CHECK2 (RTX, N, 's', 'S').rt_str)
+#define XEXP(RTX, N) (RTL_CHECK2 (RTX, N, 'e', 'u').rt_rtx)
+#define XVEC(RTX, N) (RTL_CHECK2 (RTX, N, 'E', 'V').rt_rtvec)
+#define XMODE(RTX, N) (RTL_CHECK1 (RTX, N, 'M').rt_type)
+#define XTREE(RTX, N) (RTL_CHECK1 (RTX, N, 't').rt_tree)
+#define XBBDEF(RTX, N) (RTL_CHECK1 (RTX, N, 'B').rt_bb)
+#define XTMPL(RTX, N) (RTL_CHECK1 (RTX, N, 'T').rt_str)
+#define XCFI(RTX, N) (RTL_CHECK1 (RTX, N, 'C').rt_cfi)
+
+#define XVECEXP(RTX, N, M) RTVEC_ELT (XVEC (RTX, N), M)
+#define XVECLEN(RTX, N) GET_NUM_ELEM (XVEC (RTX, N))
+
+/* These are like XINT, etc. except that they expect a '0' field instead
+ of the normal type code. */
+
+#define X0INT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_int)
+#define X0UINT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_uint)
+#define X0STR(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_str)
+#define X0EXP(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_rtx)
+#define X0VEC(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_rtvec)
+#define X0MODE(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_type)
+#define X0TREE(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_tree)
+#define X0BBDEF(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_bb)
+#define X0ADVFLAGS(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_addr_diff_vec_flags)
+#define X0CSELIB(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_cselib)
+#define X0MEMATTR(RTX, N) (RTL_CHECKC1 (RTX, N, MEM).rt_mem)
+#define X0CONSTANT(RTX, N) (RTL_CHECK1 (RTX, N, '0').rt_constant)
+
+/* Access a '0' field with any type. */
+#define X0ANY(RTX, N) RTL_CHECK1 (RTX, N, '0')
+
+#define XCINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_int)
+#define XCUINT(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_uint)
+#define XCSUBREG(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_subreg)
+#define XCSTR(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_str)
+#define XCEXP(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_rtx)
+#define XCVEC(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_rtvec)
+#define XCMODE(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_type)
+#define XCTREE(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_tree)
+#define XCBBDEF(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_bb)
+#define XCCFI(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_cfi)
+#define XCCSELIB(RTX, N, C) (RTL_CHECKC1 (RTX, N, C).rt_cselib)
+
+#define XCVECEXP(RTX, N, M, C) RTVEC_ELT (XCVEC (RTX, N, C), M)
+#define XCVECLEN(RTX, N, C) GET_NUM_ELEM (XCVEC (RTX, N, C))
+
+#define XC2EXP(RTX, N, C1, C2) (RTL_CHECKC2 (RTX, N, C1, C2).rt_rtx)
+#define XC3EXP(RTX, N, C1, C2, C3) (RTL_CHECKC3 (RTX, N, C1, C2, C3).rt_rtx)
+
+
+/* Methods of rtx_expr_list. */
+
+inline rtx_expr_list *rtx_expr_list::next () const
+{
+ rtx tmp = XEXP (this, 1);
+ return safe_as_a <rtx_expr_list *> (tmp);
+}
+
+inline rtx rtx_expr_list::element () const
+{
+ return XEXP (this, 0);
+}
+
+/* Methods of rtx_insn_list. */
+
+inline rtx_insn_list *rtx_insn_list::next () const
+{
+ rtx tmp = XEXP (this, 1);
+ return safe_as_a <rtx_insn_list *> (tmp);
+}
+
+inline rtx_insn *rtx_insn_list::insn () const
+{
+ rtx tmp = XEXP (this, 0);
+ return safe_as_a <rtx_insn *> (tmp);
+}
+
+/* Methods of rtx_sequence. */
+
+inline int rtx_sequence::len () const
+{
+ return XVECLEN (this, 0);
+}
+
+inline rtx rtx_sequence::element (int index) const
+{
+ return XVECEXP (this, 0, index);
+}
+
+inline rtx_insn *rtx_sequence::insn (int index) const
+{
+ return as_a <rtx_insn *> (XVECEXP (this, 0, index));
+}
+
+/* ACCESS MACROS for particular fields of insns. */
+
+/* Holds a unique number for each insn.
+ These are not necessarily sequentially increasing. */
+inline int INSN_UID (const_rtx insn)
+{
+ return RTL_INSN_CHAIN_FLAG_CHECK ("INSN_UID",
+ (insn))->u2.insn_uid;
+}
+inline int& INSN_UID (rtx insn)
+{
+ return RTL_INSN_CHAIN_FLAG_CHECK ("INSN_UID",
+ (insn))->u2.insn_uid;
+}
+
+/* Chain insns together in sequence. */
+
+/* For now these are split in two: an rvalue form:
+ PREV_INSN/NEXT_INSN
+ and an lvalue form:
+ SET_NEXT_INSN/SET_PREV_INSN. */
+
+inline rtx_insn *PREV_INSN (const rtx_insn *insn)
+{
+ rtx prev = XEXP (insn, 0);
+ return safe_as_a <rtx_insn *> (prev);
+}
+
+inline rtx& SET_PREV_INSN (rtx_insn *insn)
+{
+ return XEXP (insn, 0);
+}
+
+inline rtx_insn *NEXT_INSN (const rtx_insn *insn)
+{
+ rtx next = XEXP (insn, 1);
+ return safe_as_a <rtx_insn *> (next);
+}
+
+inline rtx& SET_NEXT_INSN (rtx_insn *insn)
+{
+ return XEXP (insn, 1);
+}
+
+inline basic_block BLOCK_FOR_INSN (const_rtx insn)
+{
+ return XBBDEF (insn, 2);
+}
+
+inline basic_block& BLOCK_FOR_INSN (rtx insn)
+{
+ return XBBDEF (insn, 2);
+}
+
+inline void set_block_for_insn (rtx_insn *insn, basic_block bb)
+{
+ BLOCK_FOR_INSN (insn) = bb;
+}
+
+/* The body of an insn. */
+inline rtx PATTERN (const_rtx insn)
+{
+ return XEXP (insn, 3);
+}
+
+inline rtx& PATTERN (rtx insn)
+{
+ return XEXP (insn, 3);
+}
+
+inline unsigned int INSN_LOCATION (const rtx_insn *insn)
+{
+ return XUINT (insn, 4);
+}
+
+inline unsigned int& INSN_LOCATION (rtx_insn *insn)
+{
+ return XUINT (insn, 4);
+}
+
+inline bool INSN_HAS_LOCATION (const rtx_insn *insn)
+{
+ return LOCATION_LOCUS (INSN_LOCATION (insn)) != UNKNOWN_LOCATION;
+}
+
+/* LOCATION of an RTX if relevant. */
+#define RTL_LOCATION(X) (INSN_P (X) ? \
+ INSN_LOCATION (as_a <rtx_insn *> (X)) \
+ : UNKNOWN_LOCATION)
+
+/* Code number of instruction, from when it was recognized.
+ -1 means this instruction has not been recognized yet. */
+#define INSN_CODE(INSN) XINT (INSN, 5)
+
+inline rtvec rtx_jump_table_data::get_labels () const
+{
+ rtx pat = PATTERN (this);
+ if (GET_CODE (pat) == ADDR_VEC)
+ return XVEC (pat, 0);
+ else
+ return XVEC (pat, 1); /* presumably an ADDR_DIFF_VEC */
+}
+
+/* Return the mode of the data in the table, which is always a scalar
+ integer. */
+
+inline scalar_int_mode
+rtx_jump_table_data::get_data_mode () const
+{
+ return as_a <scalar_int_mode> (GET_MODE (PATTERN (this)));
+}
+
+/* If LABEL is followed by a jump table, return the table, otherwise
+ return null. */
+
+inline rtx_jump_table_data *
+jump_table_for_label (const rtx_code_label *label)
+{
+ return safe_dyn_cast <rtx_jump_table_data *> (NEXT_INSN (label));
+}
+
+#define RTX_FRAME_RELATED_P(RTX) \
+ (RTL_FLAG_CHECK6 ("RTX_FRAME_RELATED_P", (RTX), DEBUG_INSN, INSN, \
+ CALL_INSN, JUMP_INSN, BARRIER, SET)->frame_related)
+
+/* 1 if JUMP RTX is a crossing jump. */
+#define CROSSING_JUMP_P(RTX) \
+ (RTL_FLAG_CHECK1 ("CROSSING_JUMP_P", (RTX), JUMP_INSN)->jump)
+
+/* 1 if RTX is a call to a const function. Built from ECF_CONST and
+ TREE_READONLY. */
+#define RTL_CONST_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("RTL_CONST_CALL_P", (RTX), CALL_INSN)->unchanging)
+
+/* 1 if RTX is a call to a pure function. Built from ECF_PURE and
+ DECL_PURE_P. */
+#define RTL_PURE_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("RTL_PURE_CALL_P", (RTX), CALL_INSN)->return_val)
+
+/* 1 if RTX is a call to a const or pure function. */
+#define RTL_CONST_OR_PURE_CALL_P(RTX) \
+ (RTL_CONST_CALL_P (RTX) || RTL_PURE_CALL_P (RTX))
+
+/* 1 if RTX is a call to a looping const or pure function. Built from
+ ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P. */
+#define RTL_LOOPING_CONST_OR_PURE_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("CONST_OR_PURE_CALL_P", (RTX), CALL_INSN)->call)
+
+/* 1 if RTX is a call_insn for a sibling call. */
+#define SIBLING_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("SIBLING_CALL_P", (RTX), CALL_INSN)->jump)
+
+/* 1 if RTX is a jump_insn, call_insn, or insn that is an annulling branch. */
+#define INSN_ANNULLED_BRANCH_P(RTX) \
+ (RTL_FLAG_CHECK1 ("INSN_ANNULLED_BRANCH_P", (RTX), JUMP_INSN)->unchanging)
+
+/* 1 if RTX is an insn in a delay slot and is from the target of the branch.
+ If the branch insn has INSN_ANNULLED_BRANCH_P set, this insn should only be
+ executed if the branch is taken. For annulled branches with this bit
+ clear, the insn should be executed only if the branch is not taken. */
+#define INSN_FROM_TARGET_P(RTX) \
+ (RTL_FLAG_CHECK3 ("INSN_FROM_TARGET_P", (RTX), INSN, JUMP_INSN, \
+ CALL_INSN)->in_struct)
+
+/* In an ADDR_DIFF_VEC, the flags for RTX for use by branch shortening.
+ See the comments for ADDR_DIFF_VEC in rtl.def. */
+#define ADDR_DIFF_VEC_FLAGS(RTX) X0ADVFLAGS (RTX, 4)
+
+/* In a VALUE, the value cselib has assigned to RTX.
+ This is a "struct cselib_val", see cselib.h. */
+#define CSELIB_VAL_PTR(RTX) X0CSELIB (RTX, 0)
+
+/* Holds a list of notes on what this insn does to various REGs.
+ It is a chain of EXPR_LIST rtx's, where the second operand is the
+ chain pointer and the first operand is the REG being described.
+ The mode field of the EXPR_LIST contains not a real machine mode
+ but a value from enum reg_note. */
+#define REG_NOTES(INSN) XEXP(INSN, 6)
+
+/* In an ENTRY_VALUE this is the DECL_INCOMING_RTL of the argument in
+ question. */
+#define ENTRY_VALUE_EXP(RTX) (RTL_CHECKC1 (RTX, 0, ENTRY_VALUE).rt_rtx)
+
+enum reg_note
+{
+#define DEF_REG_NOTE(NAME) NAME,
+#include "reg-notes.def"
+#undef DEF_REG_NOTE
+ REG_NOTE_MAX
+};
+
+/* Define macros to extract and insert the reg-note kind in an EXPR_LIST. */
+#define REG_NOTE_KIND(LINK) ((enum reg_note) GET_MODE (LINK))
+#define PUT_REG_NOTE_KIND(LINK, KIND) \
+ PUT_MODE_RAW (LINK, (machine_mode) (KIND))
+
+/* Names for REG_NOTE's in EXPR_LIST insn's. */
+
+extern const char * const reg_note_name[];
+#define GET_REG_NOTE_NAME(MODE) (reg_note_name[(int) (MODE)])
+
+/* This field is only present on CALL_INSNs. It holds a chain of EXPR_LIST of
+ USE, CLOBBER and SET expressions.
+ USE expressions list the registers filled with arguments that
+ are passed to the function.
+ CLOBBER expressions document the registers explicitly clobbered
+ by this CALL_INSN.
+ SET expressions say that the return value of the call (the SET_DEST)
+ is equivalent to a value available before the call (the SET_SRC).
+ This kind of SET is used when the return value is predictable in
+ advance. It is purely an optimisation hint; unlike USEs and CLOBBERs,
+ it does not affect register liveness.
+
+ Pseudo registers cannot be mentioned in this list. */
+#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7)
+
+/* The label-number of a code-label. The assembler label
+ is made from `L' and the label-number printed in decimal.
+ Label numbers are unique in a compilation. */
+#define CODE_LABEL_NUMBER(INSN) XINT (INSN, 5)
+
+/* In a NOTE that is a line number, this is a string for the file name that the
+ line is in. We use the same field to record block numbers temporarily in
+ NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes. (We avoid lots of casts
+ between ints and pointers if we use a different macro for the block number.)
+ */
+
+/* Opaque data. */
+#define NOTE_DATA(INSN) RTL_CHECKC1 (INSN, 3, NOTE)
+#define NOTE_DELETED_LABEL_NAME(INSN) XCSTR (INSN, 3, NOTE)
+#define SET_INSN_DELETED(INSN) set_insn_deleted (INSN);
+#define NOTE_BLOCK(INSN) XCTREE (INSN, 3, NOTE)
+#define NOTE_EH_HANDLER(INSN) XCINT (INSN, 3, NOTE)
+#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE)
+#define NOTE_VAR_LOCATION(INSN) XCEXP (INSN, 3, NOTE)
+#define NOTE_MARKER_LOCATION(INSN) XCUINT (INSN, 3, NOTE)
+#define NOTE_CFI(INSN) XCCFI (INSN, 3, NOTE)
+#define NOTE_LABEL_NUMBER(INSN) XCINT (INSN, 3, NOTE)
+
+/* In a NOTE that is a line number, this is the line number.
+ Other kinds of NOTEs are identified by negative numbers here. */
+#define NOTE_KIND(INSN) XCINT (INSN, 4, NOTE)
+
+/* Nonzero if INSN is a note marking the beginning of a basic block. */
+#define NOTE_INSN_BASIC_BLOCK_P(INSN) \
+ (NOTE_P (INSN) && NOTE_KIND (INSN) == NOTE_INSN_BASIC_BLOCK)
+
+/* Nonzero if INSN is a debug nonbind marker note,
+ for which NOTE_MARKER_LOCATION can be used. */
+#define NOTE_MARKER_P(INSN) \
+ (NOTE_P (INSN) && \
+ (NOTE_KIND (INSN) == NOTE_INSN_BEGIN_STMT \
+ || NOTE_KIND (INSN) == NOTE_INSN_INLINE_ENTRY))
+
+/* Variable declaration and the location of a variable. */
+#define PAT_VAR_LOCATION_DECL(PAT) (XCTREE ((PAT), 0, VAR_LOCATION))
+#define PAT_VAR_LOCATION_LOC(PAT) (XCEXP ((PAT), 1, VAR_LOCATION))
+
+/* Initialization status of the variable in the location. Status
+ can be unknown, uninitialized or initialized. See enumeration
+ type below. */
+#define PAT_VAR_LOCATION_STATUS(PAT) \
+ (RTL_FLAG_CHECK1 ("PAT_VAR_LOCATION_STATUS", PAT, VAR_LOCATION) \
+ ->u2.var_location_status)
+
+/* Accessors for a NOTE_INSN_VAR_LOCATION. */
+#define NOTE_VAR_LOCATION_DECL(NOTE) \
+ PAT_VAR_LOCATION_DECL (NOTE_VAR_LOCATION (NOTE))
+#define NOTE_VAR_LOCATION_LOC(NOTE) \
+ PAT_VAR_LOCATION_LOC (NOTE_VAR_LOCATION (NOTE))
+#define NOTE_VAR_LOCATION_STATUS(NOTE) \
+ PAT_VAR_LOCATION_STATUS (NOTE_VAR_LOCATION (NOTE))
+
+/* Evaluate to TRUE if INSN is a debug insn that denotes a variable
+ location/value tracking annotation. */
+#define DEBUG_BIND_INSN_P(INSN) \
+ (DEBUG_INSN_P (INSN) \
+ && (GET_CODE (PATTERN (INSN)) \
+ == VAR_LOCATION))
+/* Evaluate to TRUE if INSN is a debug insn that denotes a program
+ source location marker. */
+#define DEBUG_MARKER_INSN_P(INSN) \
+ (DEBUG_INSN_P (INSN) \
+ && (GET_CODE (PATTERN (INSN)) \
+ != VAR_LOCATION))
+/* Evaluate to the marker kind. */
+#define INSN_DEBUG_MARKER_KIND(INSN) \
+ (GET_CODE (PATTERN (INSN)) == DEBUG_MARKER \
+ ? (GET_MODE (PATTERN (INSN)) == VOIDmode \
+ ? NOTE_INSN_BEGIN_STMT \
+ : GET_MODE (PATTERN (INSN)) == BLKmode \
+ ? NOTE_INSN_INLINE_ENTRY \
+ : (enum insn_note)-1) \
+ : (enum insn_note)-1)
+/* Create patterns for debug markers. These and the above abstract
+ the representation, so that it's easier to get rid of the abuse of
+ the mode to hold the marker kind. Other marker types are
+ envisioned, so a single bit flag won't do; maybe separate RTL codes
+ wouldn't be a problem. */
+#define GEN_RTX_DEBUG_MARKER_BEGIN_STMT_PAT() \
+ gen_rtx_DEBUG_MARKER (VOIDmode)
+#define GEN_RTX_DEBUG_MARKER_INLINE_ENTRY_PAT() \
+ gen_rtx_DEBUG_MARKER (BLKmode)
+
+/* The VAR_LOCATION rtx in a DEBUG_INSN. */
+#define INSN_VAR_LOCATION(INSN) \
+ (RTL_FLAG_CHECK1 ("INSN_VAR_LOCATION", PATTERN (INSN), VAR_LOCATION))
+/* A pointer to the VAR_LOCATION rtx in a DEBUG_INSN. */
+#define INSN_VAR_LOCATION_PTR(INSN) \
+ (&PATTERN (INSN))
+
+/* Accessors for a tree-expanded var location debug insn. */
+#define INSN_VAR_LOCATION_DECL(INSN) \
+ PAT_VAR_LOCATION_DECL (INSN_VAR_LOCATION (INSN))
+#define INSN_VAR_LOCATION_LOC(INSN) \
+ PAT_VAR_LOCATION_LOC (INSN_VAR_LOCATION (INSN))
+#define INSN_VAR_LOCATION_STATUS(INSN) \
+ PAT_VAR_LOCATION_STATUS (INSN_VAR_LOCATION (INSN))
+
+/* Expand to the RTL that denotes an unknown variable location in a
+ DEBUG_INSN. */
+#define gen_rtx_UNKNOWN_VAR_LOC() (gen_rtx_CLOBBER (VOIDmode, const0_rtx))
+
+/* Determine whether X is such an unknown location. */
+#define VAR_LOC_UNKNOWN_P(X) \
+ (GET_CODE (X) == CLOBBER && XEXP ((X), 0) == const0_rtx)
+
+/* 1 if RTX is emitted after a call, but it should take effect before
+ the call returns. */
+#define NOTE_DURING_CALL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("NOTE_VAR_LOCATION_DURING_CALL_P", (RTX), NOTE)->call)
+
+/* DEBUG_EXPR_DECL corresponding to a DEBUG_EXPR RTX. */
+#define DEBUG_EXPR_TREE_DECL(RTX) XCTREE (RTX, 0, DEBUG_EXPR)
+
+/* VAR_DECL/PARM_DECL DEBUG_IMPLICIT_PTR takes address of. */
+#define DEBUG_IMPLICIT_PTR_DECL(RTX) XCTREE (RTX, 0, DEBUG_IMPLICIT_PTR)
+
+/* PARM_DECL DEBUG_PARAMETER_REF references. */
+#define DEBUG_PARAMETER_REF_DECL(RTX) XCTREE (RTX, 0, DEBUG_PARAMETER_REF)
+
+/* Codes that appear in the NOTE_KIND field for kinds of notes
+ that are not line numbers. These codes are all negative.
+
+ Notice that we do not try to use zero here for any of
+ the special note codes because sometimes the source line
+ actually can be zero! This happens (for example) when we
+ are generating code for the per-translation-unit constructor
+ and destructor routines for some C++ translation unit. */
+
+enum insn_note
+{
+#define DEF_INSN_NOTE(NAME) NAME,
+#include "insn-notes.def"
+#undef DEF_INSN_NOTE
+
+ NOTE_INSN_MAX
+};
+
+/* Names for NOTE insn's other than line numbers. */
+
+extern const char * const note_insn_name[NOTE_INSN_MAX];
+#define GET_NOTE_INSN_NAME(NOTE_CODE) \
+ (note_insn_name[(NOTE_CODE)])
+
+/* The name of a label, in case it corresponds to an explicit label
+ in the input source code. */
+#define LABEL_NAME(RTX) XCSTR (RTX, 6, CODE_LABEL)
+
+/* In jump.cc, each label contains a count of the number
+ of LABEL_REFs that point at it, so unused labels can be deleted. */
+#define LABEL_NUSES(RTX) XCINT (RTX, 4, CODE_LABEL)
+
+/* Labels carry a two-bit field composed of the ->jump and ->call
+ bits. This field indicates whether the label is an alternate
+ entry point, and if so, what kind. */
+enum label_kind
+{
+ LABEL_NORMAL = 0, /* ordinary label */
+ LABEL_STATIC_ENTRY, /* alternate entry point, not exported */
+ LABEL_GLOBAL_ENTRY, /* alternate entry point, exported */
+ LABEL_WEAK_ENTRY /* alternate entry point, exported as weak symbol */
+};
+
+#if defined ENABLE_RTL_FLAG_CHECKING && (GCC_VERSION > 2007)
+
+/* Retrieve the kind of LABEL. */
+#define LABEL_KIND(LABEL) __extension__ \
+({ __typeof (LABEL) const _label = (LABEL); \
+ if (! LABEL_P (_label)) \
+ rtl_check_failed_flag ("LABEL_KIND", _label, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ (enum label_kind) ((_label->jump << 1) | _label->call); })
+
+/* Set the kind of LABEL. */
+#define SET_LABEL_KIND(LABEL, KIND) do { \
+ __typeof (LABEL) const _label = (LABEL); \
+ const unsigned int _kind = (KIND); \
+ if (! LABEL_P (_label)) \
+ rtl_check_failed_flag ("SET_LABEL_KIND", _label, __FILE__, __LINE__, \
+ __FUNCTION__); \
+ _label->jump = ((_kind >> 1) & 1); \
+ _label->call = (_kind & 1); \
+} while (0)
+
+#else
+
+/* Retrieve the kind of LABEL. */
+#define LABEL_KIND(LABEL) \
+ ((enum label_kind) (((LABEL)->jump << 1) | (LABEL)->call))
+
+/* Set the kind of LABEL. */
+#define SET_LABEL_KIND(LABEL, KIND) do { \
+ rtx const _label = (LABEL); \
+ const unsigned int _kind = (KIND); \
+ _label->jump = ((_kind >> 1) & 1); \
+ _label->call = (_kind & 1); \
+} while (0)
+
+#endif /* rtl flag checking */
+
+#define LABEL_ALT_ENTRY_P(LABEL) (LABEL_KIND (LABEL) != LABEL_NORMAL)
+
+/* In jump.cc, each JUMP_INSN can point to a label that it can jump to,
+ so that if the JUMP_INSN is deleted, the label's LABEL_NUSES can
+ be decremented and possibly the label can be deleted. */
+#define JUMP_LABEL(INSN) XCEXP (INSN, 7, JUMP_INSN)
+
+inline rtx_insn *JUMP_LABEL_AS_INSN (const rtx_insn *insn)
+{
+ return safe_as_a <rtx_insn *> (JUMP_LABEL (insn));
+}
+
+/* Methods of rtx_jump_insn. */
+
+inline rtx rtx_jump_insn::jump_label () const
+{
+ return JUMP_LABEL (this);
+}
+
+inline rtx_code_label *rtx_jump_insn::jump_target () const
+{
+ return safe_as_a <rtx_code_label *> (JUMP_LABEL (this));
+}
+
+inline void rtx_jump_insn::set_jump_target (rtx_code_label *target)
+{
+ JUMP_LABEL (this) = target;
+}
+
+/* Once basic blocks are found, each CODE_LABEL starts a chain that
+ goes through all the LABEL_REFs that jump to that label. The chain
+ eventually winds up at the CODE_LABEL: it is circular. */
+#define LABEL_REFS(LABEL) XCEXP (LABEL, 3, CODE_LABEL)
+
+/* Get the label that a LABEL_REF references. */
+static inline rtx_insn *
+label_ref_label (const_rtx ref)
+{
+ return as_a<rtx_insn *> (XCEXP (ref, 0, LABEL_REF));
+}
+
+/* Set the label that LABEL_REF ref refers to. */
+
+static inline void
+set_label_ref_label (rtx ref, rtx_insn *label)
+{
+ XCEXP (ref, 0, LABEL_REF) = label;
+}
+
+/* For a REG rtx, REGNO extracts the register number. REGNO can only
+ be used on RHS. Use SET_REGNO to change the value. */
+#define REGNO(RTX) (rhs_regno(RTX))
+#define SET_REGNO(RTX, N) (df_ref_change_reg_with_loc (RTX, N))
+
+/* Return the number of consecutive registers in a REG. This is always
+ 1 for pseudo registers and is determined by TARGET_HARD_REGNO_NREGS for
+ hard registers. */
+#define REG_NREGS(RTX) (REG_CHECK (RTX)->nregs)
+
+/* ORIGINAL_REGNO holds the number the register originally had; for a
+ pseudo register turned into a hard reg this will hold the old pseudo
+ register number. */
+#define ORIGINAL_REGNO(RTX) \
+ (RTL_FLAG_CHECK1 ("ORIGINAL_REGNO", (RTX), REG)->u2.original_regno)
+
+/* Force the REGNO macro to only be used on the lhs. */
+static inline unsigned int
+rhs_regno (const_rtx x)
+{
+ return REG_CHECK (x)->regno;
+}
+
+/* Return the final register in REG X plus one. */
+static inline unsigned int
+END_REGNO (const_rtx x)
+{
+ return REGNO (x) + REG_NREGS (x);
+}
+
+/* Change the REGNO and REG_NREGS of REG X to the specified values,
+ bypassing the df machinery. */
+static inline void
+set_regno_raw (rtx x, unsigned int regno, unsigned int nregs)
+{
+ reg_info *reg = REG_CHECK (x);
+ reg->regno = regno;
+ reg->nregs = nregs;
+}
+
+/* 1 if RTX is a reg or parallel that is the current function's return
+ value. */
+#define REG_FUNCTION_VALUE_P(RTX) \
+ (RTL_FLAG_CHECK2 ("REG_FUNCTION_VALUE_P", (RTX), REG, PARALLEL)->return_val)
+
+/* 1 if RTX is a reg that corresponds to a variable declared by the user. */
+#define REG_USERVAR_P(RTX) \
+ (RTL_FLAG_CHECK1 ("REG_USERVAR_P", (RTX), REG)->volatil)
+
+/* 1 if RTX is a reg that holds a pointer value. */
+#define REG_POINTER(RTX) \
+ (RTL_FLAG_CHECK1 ("REG_POINTER", (RTX), REG)->frame_related)
+
+/* 1 if RTX is a mem that holds a pointer value. */
+#define MEM_POINTER(RTX) \
+ (RTL_FLAG_CHECK1 ("MEM_POINTER", (RTX), MEM)->frame_related)
+
+/* 1 if the given register REG corresponds to a hard register. */
+#define HARD_REGISTER_P(REG) (HARD_REGISTER_NUM_P (REGNO (REG)))
+
+/* 1 if the given register number REG_NO corresponds to a hard register. */
+#define HARD_REGISTER_NUM_P(REG_NO) ((REG_NO) < FIRST_PSEUDO_REGISTER)
+
+/* For a CONST_INT rtx, INTVAL extracts the integer. */
+#define INTVAL(RTX) XCWINT (RTX, 0, CONST_INT)
+#define UINTVAL(RTX) ((unsigned HOST_WIDE_INT) INTVAL (RTX))
+
+/* For a CONST_WIDE_INT, CONST_WIDE_INT_NUNITS is the number of
+ elements actually needed to represent the constant.
+ CONST_WIDE_INT_ELT gets one of the elements. 0 is the least
+ significant HOST_WIDE_INT. */
+#define CONST_WIDE_INT_VEC(RTX) HWIVEC_CHECK (RTX, CONST_WIDE_INT)
+#define CONST_WIDE_INT_NUNITS(RTX) CWI_GET_NUM_ELEM (RTX)
+#define CONST_WIDE_INT_ELT(RTX, N) CWI_ELT (RTX, N)
+
+/* For a CONST_POLY_INT, CONST_POLY_INT_COEFFS gives access to the
+ individual coefficients, in the form of a trailing_wide_ints structure. */
+#define CONST_POLY_INT_COEFFS(RTX) \
+ (RTL_FLAG_CHECK1("CONST_POLY_INT_COEFFS", (RTX), \
+ CONST_POLY_INT)->u.cpi.coeffs)
+
+/* For a CONST_DOUBLE:
+#if TARGET_SUPPORTS_WIDE_INT == 0
+ For a VOIDmode, there are two integers CONST_DOUBLE_LOW is the
+ low-order word and ..._HIGH the high-order.
+#endif
+ For a float, there is a REAL_VALUE_TYPE structure, and
+ CONST_DOUBLE_REAL_VALUE(r) is a pointer to it. */
+#define CONST_DOUBLE_LOW(r) XCMWINT (r, 0, CONST_DOUBLE, VOIDmode)
+#define CONST_DOUBLE_HIGH(r) XCMWINT (r, 1, CONST_DOUBLE, VOIDmode)
+#define CONST_DOUBLE_REAL_VALUE(r) \
+ ((const struct real_value *) XCNMPRV (r, CONST_DOUBLE, VOIDmode))
+
+#define CONST_FIXED_VALUE(r) \
+ ((const struct fixed_value *) XCNMPFV (r, CONST_FIXED, VOIDmode))
+#define CONST_FIXED_VALUE_HIGH(r) \
+ ((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.high))
+#define CONST_FIXED_VALUE_LOW(r) \
+ ((HOST_WIDE_INT) (CONST_FIXED_VALUE (r)->data.low))
+
+/* For a CONST_VECTOR, return element #n. */
+#define CONST_VECTOR_ELT(RTX, N) const_vector_elt (RTX, N)
+
+/* See rtl.texi for a description of these macros. */
+#define CONST_VECTOR_NPATTERNS(RTX) \
+ (RTL_FLAG_CHECK1 ("CONST_VECTOR_NPATTERNS", (RTX), CONST_VECTOR) \
+ ->u2.const_vector.npatterns)
+
+#define CONST_VECTOR_NELTS_PER_PATTERN(RTX) \
+ (RTL_FLAG_CHECK1 ("CONST_VECTOR_NELTS_PER_PATTERN", (RTX), CONST_VECTOR) \
+ ->u2.const_vector.nelts_per_pattern)
+
+#define CONST_VECTOR_DUPLICATE_P(RTX) \
+ (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 1)
+
+#define CONST_VECTOR_STEPPED_P(RTX) \
+ (CONST_VECTOR_NELTS_PER_PATTERN (RTX) == 3)
+
+#define CONST_VECTOR_ENCODED_ELT(RTX, N) XCVECEXP (RTX, 0, N, CONST_VECTOR)
+
+/* Return the number of elements encoded directly in a CONST_VECTOR. */
+
+inline unsigned int
+const_vector_encoded_nelts (const_rtx x)
+{
+ return CONST_VECTOR_NPATTERNS (x) * CONST_VECTOR_NELTS_PER_PATTERN (x);
+}
+
+/* For a CONST_VECTOR, return the number of elements in a vector. */
+#define CONST_VECTOR_NUNITS(RTX) GET_MODE_NUNITS (GET_MODE (RTX))
+
+/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
+ SUBREG_BYTE extracts the byte-number. */
+
+#define SUBREG_REG(RTX) XCEXP (RTX, 0, SUBREG)
+#define SUBREG_BYTE(RTX) XCSUBREG (RTX, 1, SUBREG)
+
+/* in rtlanal.cc */
+/* Return the right cost to give to an operation
+ to make the cost of the corresponding register-to-register instruction
+ N times that of a fast register-to-register instruction. */
+#define COSTS_N_INSNS(N) ((N) * 4)
+
+/* Maximum cost of an rtl expression. This value has the special meaning
+ not to use an rtx with this cost under any circumstances. */
+#define MAX_COST INT_MAX
+
+/* Return true if CODE always has VOIDmode. */
+
+static inline bool
+always_void_p (enum rtx_code code)
+{
+ return code == SET;
+}
+
+/* A structure to hold all available cost information about an rtl
+ expression. */
+struct full_rtx_costs
+{
+ int speed;
+ int size;
+};
+
+/* Initialize a full_rtx_costs structure C to the maximum cost. */
+static inline void
+init_costs_to_max (struct full_rtx_costs *c)
+{
+ c->speed = MAX_COST;
+ c->size = MAX_COST;
+}
+
+/* Initialize a full_rtx_costs structure C to zero cost. */
+static inline void
+init_costs_to_zero (struct full_rtx_costs *c)
+{
+ c->speed = 0;
+ c->size = 0;
+}
+
+/* Compare two full_rtx_costs structures A and B, returning true
+ if A < B when optimizing for speed. */
+static inline bool
+costs_lt_p (struct full_rtx_costs *a, struct full_rtx_costs *b,
+ bool speed)
+{
+ if (speed)
+ return (a->speed < b->speed
+ || (a->speed == b->speed && a->size < b->size));
+ else
+ return (a->size < b->size
+ || (a->size == b->size && a->speed < b->speed));
+}
+
+/* Increase both members of the full_rtx_costs structure C by the
+ cost of N insns. */
+static inline void
+costs_add_n_insns (struct full_rtx_costs *c, int n)
+{
+ c->speed += COSTS_N_INSNS (n);
+ c->size += COSTS_N_INSNS (n);
+}
+
+/* Describes the shape of a subreg:
+
+ inner_mode == the mode of the SUBREG_REG
+ offset == the SUBREG_BYTE
+ outer_mode == the mode of the SUBREG itself. */
+class subreg_shape {
+public:
+ subreg_shape (machine_mode, poly_uint16, machine_mode);
+ bool operator == (const subreg_shape &) const;
+ bool operator != (const subreg_shape &) const;
+ unsigned HOST_WIDE_INT unique_id () const;
+
+ machine_mode inner_mode;
+ poly_uint16 offset;
+ machine_mode outer_mode;
+};
+
+inline
+subreg_shape::subreg_shape (machine_mode inner_mode_in,
+ poly_uint16 offset_in,
+ machine_mode outer_mode_in)
+ : inner_mode (inner_mode_in), offset (offset_in), outer_mode (outer_mode_in)
+{}
+
+inline bool
+subreg_shape::operator == (const subreg_shape &other) const
+{
+ return (inner_mode == other.inner_mode
+ && known_eq (offset, other.offset)
+ && outer_mode == other.outer_mode);
+}
+
+inline bool
+subreg_shape::operator != (const subreg_shape &other) const
+{
+ return !operator == (other);
+}
+
+/* Return an integer that uniquely identifies this shape. Structures
+ like rtx_def assume that a mode can fit in an 8-bit bitfield and no
+ current mode is anywhere near being 65536 bytes in size, so the
+ id comfortably fits in an int. */
+
+inline unsigned HOST_WIDE_INT
+subreg_shape::unique_id () const
+{
+ { STATIC_ASSERT (MAX_MACHINE_MODE <= 256); }
+ { STATIC_ASSERT (NUM_POLY_INT_COEFFS <= 3); }
+ { STATIC_ASSERT (sizeof (offset.coeffs[0]) <= 2); }
+ int res = (int) inner_mode + ((int) outer_mode << 8);
+ for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res += (HOST_WIDE_INT) offset.coeffs[i] << ((1 + i) * 16);
+ return res;
+}
+
+/* Return the shape of a SUBREG rtx. */
+
+static inline subreg_shape
+shape_of_subreg (const_rtx x)
+{
+ return subreg_shape (GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x), GET_MODE (x));
+}
+
+/* Information about an address. This structure is supposed to be able
+ to represent all supported target addresses. Please extend it if it
+ is not yet general enough. */
+struct address_info {
+ /* The mode of the value being addressed, or VOIDmode if this is
+ a load-address operation with no known address mode. */
+ machine_mode mode;
+
+ /* The address space. */
+ addr_space_t as;
+
+ /* True if this is an RTX_AUTOINC address. */
+ bool autoinc_p;
+
+ /* A pointer to the top-level address. */
+ rtx *outer;
+
+ /* A pointer to the inner address, after all address mutations
+ have been stripped from the top-level address. It can be one
+ of the following:
+
+ - A {PRE,POST}_{INC,DEC} of *BASE. SEGMENT, INDEX and DISP are null.
+
+ - A {PRE,POST}_MODIFY of *BASE. In this case either INDEX or DISP
+ points to the step value, depending on whether the step is variable
+ or constant respectively. SEGMENT is null.
+
+ - A plain sum of the form SEGMENT + BASE + INDEX + DISP,
+ with null fields evaluating to 0. */
+ rtx *inner;
+
+ /* Components that make up *INNER. Each one may be null or nonnull.
+ When nonnull, their meanings are as follows:
+
+ - *SEGMENT is the "segment" of memory to which the address refers.
+ This value is entirely target-specific and is only called a "segment"
+ because that's its most typical use. It contains exactly one UNSPEC,
+ pointed to by SEGMENT_TERM. The contents of *SEGMENT do not need
+ reloading.
+
+ - *BASE is a variable expression representing a base address.
+ It contains exactly one REG, SUBREG or MEM, pointed to by BASE_TERM.
+
+ - *INDEX is a variable expression representing an index value.
+ It may be a scaled expression, such as a MULT. It has exactly
+ one REG, SUBREG or MEM, pointed to by INDEX_TERM.
+
+ - *DISP is a constant, possibly mutated. DISP_TERM points to the
+ unmutated RTX_CONST_OBJ. */
+ rtx *segment;
+ rtx *base;
+ rtx *index;
+ rtx *disp;
+
+ rtx *segment_term;
+ rtx *base_term;
+ rtx *index_term;
+ rtx *disp_term;
+
+ /* In a {PRE,POST}_MODIFY address, this points to a second copy
+ of BASE_TERM, otherwise it is null. */
+ rtx *base_term2;
+
+ /* ADDRESS if this structure describes an address operand, MEM if
+ it describes a MEM address. */
+ enum rtx_code addr_outer_code;
+
+ /* If BASE is nonnull, this is the code of the rtx that contains it. */
+ enum rtx_code base_outer_code;
+};
+
+/* This is used to bundle an rtx and a mode together so that the pair
+ can be used with the wi:: routines. If we ever put modes into rtx
+ integer constants, this should go away and then just pass an rtx in. */
+typedef std::pair <rtx, machine_mode> rtx_mode_t;
+
+namespace wi
+{
+ template <>
+ struct int_traits <rtx_mode_t>
+ {
+ static const enum precision_type precision_type = VAR_PRECISION;
+ static const bool host_dependent_precision = false;
+ /* This ought to be true, except for the special case that BImode
+ is canonicalized to STORE_FLAG_VALUE, which might be 1. */
+ static const bool is_sign_extended = false;
+ static unsigned int get_precision (const rtx_mode_t &);
+ static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
+ const rtx_mode_t &);
+ };
+}
+
+inline unsigned int
+wi::int_traits <rtx_mode_t>::get_precision (const rtx_mode_t &x)
+{
+ return GET_MODE_PRECISION (as_a <scalar_mode> (x.second));
+}
+
+inline wi::storage_ref
+wi::int_traits <rtx_mode_t>::decompose (HOST_WIDE_INT *,
+ unsigned int precision,
+ const rtx_mode_t &x)
+{
+ gcc_checking_assert (precision == get_precision (x));
+ switch (GET_CODE (x.first))
+ {
+ case CONST_INT:
+ if (precision < HOST_BITS_PER_WIDE_INT)
+ /* Nonzero BImodes are stored as STORE_FLAG_VALUE, which on many
+ targets is 1 rather than -1. */
+ gcc_checking_assert (INTVAL (x.first)
+ == sext_hwi (INTVAL (x.first), precision)
+ || (x.second == BImode && INTVAL (x.first) == 1));
+
+ return wi::storage_ref (&INTVAL (x.first), 1, precision);
+
+ case CONST_WIDE_INT:
+ return wi::storage_ref (&CONST_WIDE_INT_ELT (x.first, 0),
+ CONST_WIDE_INT_NUNITS (x.first), precision);
+
+#if TARGET_SUPPORTS_WIDE_INT == 0
+ case CONST_DOUBLE:
+ return wi::storage_ref (&CONST_DOUBLE_LOW (x.first), 2, precision);
+#endif
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+namespace wi
+{
+ hwi_with_prec shwi (HOST_WIDE_INT, machine_mode mode);
+ wide_int min_value (machine_mode, signop);
+ wide_int max_value (machine_mode, signop);
+}
+
+inline wi::hwi_with_prec
+wi::shwi (HOST_WIDE_INT val, machine_mode mode)
+{
+ return shwi (val, GET_MODE_PRECISION (as_a <scalar_mode> (mode)));
+}
+
+/* Produce the smallest number that is represented in MODE. The precision
+ is taken from MODE and the sign from SGN. */
+inline wide_int
+wi::min_value (machine_mode mode, signop sgn)
+{
+ return min_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
+}
+
+/* Produce the largest number that is represented in MODE. The precision
+ is taken from MODE and the sign from SGN. */
+inline wide_int
+wi::max_value (machine_mode mode, signop sgn)
+{
+ return max_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
+}
+
+namespace wi
+{
+ typedef poly_int<NUM_POLY_INT_COEFFS,
+ generic_wide_int <wide_int_ref_storage <false, false> > >
+ rtx_to_poly_wide_ref;
+ rtx_to_poly_wide_ref to_poly_wide (const_rtx, machine_mode);
+}
+
+/* Return the value of a CONST_POLY_INT in its native precision. */
+
+inline wi::rtx_to_poly_wide_ref
+const_poly_int_value (const_rtx x)
+{
+ poly_int<NUM_POLY_INT_COEFFS, WIDE_INT_REF_FOR (wide_int)> res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = CONST_POLY_INT_COEFFS (x)[i];
+ return res;
+}
+
+/* Return true if X is a scalar integer or a CONST_POLY_INT. The value
+ can then be extracted using wi::to_poly_wide. */
+
+inline bool
+poly_int_rtx_p (const_rtx x)
+{
+ return CONST_SCALAR_INT_P (x) || CONST_POLY_INT_P (x);
+}
+
+/* Access X (which satisfies poly_int_rtx_p) as a poly_wide_int.
+ MODE is the mode of X. */
+
+inline wi::rtx_to_poly_wide_ref
+wi::to_poly_wide (const_rtx x, machine_mode mode)
+{
+ if (CONST_POLY_INT_P (x))
+ return const_poly_int_value (x);
+ return rtx_mode_t (const_cast<rtx> (x), mode);
+}
+
+/* Return the value of X as a poly_int64. */
+
+inline poly_int64
+rtx_to_poly_int64 (const_rtx x)
+{
+ if (CONST_POLY_INT_P (x))
+ {
+ poly_int64 res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = CONST_POLY_INT_COEFFS (x)[i].to_shwi ();
+ return res;
+ }
+ return INTVAL (x);
+}
+
+/* Return true if arbitrary value X is an integer constant that can
+ be represented as a poly_int64. Store the value in *RES if so,
+ otherwise leave it unmodified. */
+
+inline bool
+poly_int_rtx_p (const_rtx x, poly_int64_pod *res)
+{
+ if (CONST_INT_P (x))
+ {
+ *res = INTVAL (x);
+ return true;
+ }
+ if (CONST_POLY_INT_P (x))
+ {
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ if (!wi::fits_shwi_p (CONST_POLY_INT_COEFFS (x)[i]))
+ return false;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res->coeffs[i] = CONST_POLY_INT_COEFFS (x)[i].to_shwi ();
+ return true;
+ }
+ return false;
+}
+
+extern void init_rtlanal (void);
+extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool);
+extern int address_cost (rtx, machine_mode, addr_space_t, bool);
+extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
+ struct full_rtx_costs *);
+extern bool native_encode_rtx (machine_mode, rtx, vec<target_unit> &,
+ unsigned int, unsigned int);
+extern rtx native_decode_rtx (machine_mode, const vec<target_unit> &,
+ unsigned int);
+extern rtx native_decode_vector_rtx (machine_mode, const vec<target_unit> &,
+ unsigned int, unsigned int, unsigned int);
+extern poly_uint64 subreg_lsb (const_rtx);
+extern poly_uint64 subreg_size_lsb (poly_uint64, poly_uint64, poly_uint64);
+extern poly_uint64 subreg_size_offset_from_lsb (poly_uint64, poly_uint64,
+ poly_uint64);
+extern bool read_modify_subreg_p (const_rtx);
+
+/* Given a subreg's OUTER_MODE, INNER_MODE, and SUBREG_BYTE, return the
+ bit offset at which the subreg begins (counting from the least significant
+ bit of the operand). */
+
+inline poly_uint64
+subreg_lsb_1 (machine_mode outer_mode, machine_mode inner_mode,
+ poly_uint64 subreg_byte)
+{
+ return subreg_size_lsb (GET_MODE_SIZE (outer_mode),
+ GET_MODE_SIZE (inner_mode), subreg_byte);
+}
+
+/* Return the subreg byte offset for a subreg whose outer mode is
+ OUTER_MODE, whose inner mode is INNER_MODE, and where there are
+ LSB_SHIFT *bits* between the lsb of the outer value and the lsb of
+ the inner value. This is the inverse of subreg_lsb_1 (which converts
+ byte offsets to bit shifts). */
+
+inline poly_uint64
+subreg_offset_from_lsb (machine_mode outer_mode,
+ machine_mode inner_mode,
+ poly_uint64 lsb_shift)
+{
+ return subreg_size_offset_from_lsb (GET_MODE_SIZE (outer_mode),
+ GET_MODE_SIZE (inner_mode), lsb_shift);
+}
+
+extern unsigned int subreg_regno_offset (unsigned int, machine_mode,
+ poly_uint64, machine_mode);
+extern bool subreg_offset_representable_p (unsigned int, machine_mode,
+ poly_uint64, machine_mode);
+extern unsigned int subreg_regno (const_rtx);
+extern int simplify_subreg_regno (unsigned int, machine_mode,
+ poly_uint64, machine_mode);
+extern int lowpart_subreg_regno (unsigned int, machine_mode,
+ machine_mode);
+extern unsigned int subreg_nregs (const_rtx);
+extern unsigned int subreg_nregs_with_regno (unsigned int, const_rtx);
+extern unsigned HOST_WIDE_INT nonzero_bits (const_rtx, machine_mode);
+extern unsigned int num_sign_bit_copies (const_rtx, machine_mode);
+extern bool constant_pool_constant_p (rtx);
+extern bool truncated_to_mode (machine_mode, const_rtx);
+extern int low_bitmask_len (machine_mode, unsigned HOST_WIDE_INT);
+extern void split_double (rtx, rtx *, rtx *);
+extern rtx *strip_address_mutations (rtx *, enum rtx_code * = 0);
+extern void decompose_address (struct address_info *, rtx *,
+ machine_mode, addr_space_t, enum rtx_code);
+extern void decompose_lea_address (struct address_info *, rtx *);
+extern void decompose_mem_address (struct address_info *, rtx);
+extern void update_address (struct address_info *);
+extern HOST_WIDE_INT get_index_scale (const struct address_info *);
+extern enum rtx_code get_index_code (const struct address_info *);
+
+/* 1 if RTX is a subreg containing a reg that is already known to be
+ sign- or zero-extended from the mode of the subreg to the mode of
+ the reg. SUBREG_PROMOTED_UNSIGNED_P gives the signedness of the
+ extension.
+
+ When used as a LHS, is means that this extension must be done
+ when assigning to SUBREG_REG. */
+
+#define SUBREG_PROMOTED_VAR_P(RTX) \
+ (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED", (RTX), SUBREG)->in_struct)
+
+/* Valid for subregs which are SUBREG_PROMOTED_VAR_P(). In that case
+ this gives the necessary extensions:
+ 0 - signed (SPR_SIGNED)
+ 1 - normal unsigned (SPR_UNSIGNED)
+ 2 - value is both sign and unsign extended for mode
+ (SPR_SIGNED_AND_UNSIGNED).
+ -1 - pointer unsigned, which most often can be handled like unsigned
+ extension, except for generating instructions where we need to
+ emit special code (ptr_extend insns) on some architectures
+ (SPR_POINTER). */
+
+const int SRP_POINTER = -1;
+const int SRP_SIGNED = 0;
+const int SRP_UNSIGNED = 1;
+const int SRP_SIGNED_AND_UNSIGNED = 2;
+
+/* Sets promoted mode for SUBREG_PROMOTED_VAR_P(). */
+#define SUBREG_PROMOTED_SET(RTX, VAL) \
+do { \
+ rtx const _rtx = RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_SET", \
+ (RTX), SUBREG); \
+ switch (VAL) \
+ { \
+ case SRP_POINTER: \
+ _rtx->volatil = 0; \
+ _rtx->unchanging = 0; \
+ break; \
+ case SRP_SIGNED: \
+ _rtx->volatil = 0; \
+ _rtx->unchanging = 1; \
+ break; \
+ case SRP_UNSIGNED: \
+ _rtx->volatil = 1; \
+ _rtx->unchanging = 0; \
+ break; \
+ case SRP_SIGNED_AND_UNSIGNED: \
+ _rtx->volatil = 1; \
+ _rtx->unchanging = 1; \
+ break; \
+ } \
+} while (0)
+
+/* Gets the value stored in promoted mode for SUBREG_PROMOTED_VAR_P(),
+ including SRP_SIGNED_AND_UNSIGNED if promoted for
+ both signed and unsigned. */
+#define SUBREG_PROMOTED_GET(RTX) \
+ (2 * (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_GET", (RTX), SUBREG)->volatil)\
+ + (RTX)->unchanging - 1)
+
+/* Returns sign of promoted mode for SUBREG_PROMOTED_VAR_P(). */
+#define SUBREG_PROMOTED_SIGN(RTX) \
+ ((RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_SIGN", (RTX), SUBREG)->volatil) ? 1\
+ : (RTX)->unchanging - 1)
+
+/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted
+ for SIGNED type. */
+#define SUBREG_PROMOTED_SIGNED_P(RTX) \
+ (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_SIGNED_P", (RTX), SUBREG)->unchanging)
+
+/* Predicate to check if RTX of SUBREG_PROMOTED_VAR_P() is promoted
+ for UNSIGNED type. */
+#define SUBREG_PROMOTED_UNSIGNED_P(RTX) \
+ (RTL_FLAG_CHECK1 ("SUBREG_PROMOTED_UNSIGNED_P", (RTX), SUBREG)->volatil)
+
+/* Checks if RTX of SUBREG_PROMOTED_VAR_P() is promoted for given SIGN. */
+#define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \
+((SIGN) == SRP_POINTER ? SUBREG_PROMOTED_GET (RTX) == SRP_POINTER \
+ : (SIGN) == SRP_SIGNED ? SUBREG_PROMOTED_SIGNED_P (RTX) \
+ : SUBREG_PROMOTED_UNSIGNED_P (RTX))
+
+/* True if the REG is the static chain register for some CALL_INSN. */
+#define STATIC_CHAIN_REG_P(RTX) \
+ (RTL_FLAG_CHECK1 ("STATIC_CHAIN_REG_P", (RTX), REG)->jump)
+
+/* True if the subreg was generated by LRA for reload insns. Such
+ subregs are valid only during LRA. */
+#define LRA_SUBREG_P(RTX) \
+ (RTL_FLAG_CHECK1 ("LRA_SUBREG_P", (RTX), SUBREG)->jump)
+
+/* Access various components of an ASM_OPERANDS rtx. */
+
+#define ASM_OPERANDS_TEMPLATE(RTX) XCSTR (RTX, 0, ASM_OPERANDS)
+#define ASM_OPERANDS_OUTPUT_CONSTRAINT(RTX) XCSTR (RTX, 1, ASM_OPERANDS)
+#define ASM_OPERANDS_OUTPUT_IDX(RTX) XCINT (RTX, 2, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_VEC(RTX) XCVEC (RTX, 3, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XCVEC (RTX, 4, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT(RTX, N) XCVECEXP (RTX, 3, N, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_LENGTH(RTX) XCVECLEN (RTX, 3, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_CONSTRAINT_EXP(RTX, N) \
+ XCVECEXP (RTX, 4, N, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) \
+ XSTR (XCVECEXP (RTX, 4, N, ASM_OPERANDS), 0)
+#define ASM_OPERANDS_INPUT_MODE(RTX, N) \
+ GET_MODE (XCVECEXP (RTX, 4, N, ASM_OPERANDS))
+#define ASM_OPERANDS_LABEL_VEC(RTX) XCVEC (RTX, 5, ASM_OPERANDS)
+#define ASM_OPERANDS_LABEL_LENGTH(RTX) XCVECLEN (RTX, 5, ASM_OPERANDS)
+#define ASM_OPERANDS_LABEL(RTX, N) XCVECEXP (RTX, 5, N, ASM_OPERANDS)
+#define ASM_OPERANDS_SOURCE_LOCATION(RTX) XCUINT (RTX, 6, ASM_OPERANDS)
+#define ASM_INPUT_SOURCE_LOCATION(RTX) XCUINT (RTX, 1, ASM_INPUT)
+
+/* 1 if RTX is a mem that is statically allocated in read-only memory. */
+#define MEM_READONLY_P(RTX) \
+ (RTL_FLAG_CHECK1 ("MEM_READONLY_P", (RTX), MEM)->unchanging)
+
+/* 1 if RTX is a mem and we should keep the alias set for this mem
+ unchanged when we access a component. Set to 1, or example, when we
+ are already in a non-addressable component of an aggregate. */
+#define MEM_KEEP_ALIAS_SET_P(RTX) \
+ (RTL_FLAG_CHECK1 ("MEM_KEEP_ALIAS_SET_P", (RTX), MEM)->jump)
+
+/* 1 if RTX is a mem or asm_operand for a volatile reference. */
+#define MEM_VOLATILE_P(RTX) \
+ (RTL_FLAG_CHECK3 ("MEM_VOLATILE_P", (RTX), MEM, ASM_OPERANDS, \
+ ASM_INPUT)->volatil)
+
+/* 1 if RTX is a mem that cannot trap. */
+#define MEM_NOTRAP_P(RTX) \
+ (RTL_FLAG_CHECK1 ("MEM_NOTRAP_P", (RTX), MEM)->call)
+
+/* The memory attribute block. We provide access macros for each value
+ in the block and provide defaults if none specified. */
+#define MEM_ATTRS(RTX) X0MEMATTR (RTX, 1)
+
+/* The register attribute block. We provide access macros for each value
+ in the block and provide defaults if none specified. */
+#define REG_ATTRS(RTX) (REG_CHECK (RTX)->attrs)
+
+#ifndef GENERATOR_FILE
+/* For a MEM rtx, the alias set. If 0, this MEM is not in any alias
+ set, and may alias anything. Otherwise, the MEM can only alias
+ MEMs in a conflicting alias set. This value is set in a
+ language-dependent manner in the front-end, and should not be
+ altered in the back-end. These set numbers are tested with
+ alias_sets_conflict_p. */
+#define MEM_ALIAS_SET(RTX) (get_mem_attrs (RTX)->alias)
+
+/* For a MEM rtx, the decl it is known to refer to, if it is known to
+ refer to part of a DECL. It may also be a COMPONENT_REF. */
+#define MEM_EXPR(RTX) (get_mem_attrs (RTX)->expr)
+
+/* For a MEM rtx, true if its MEM_OFFSET is known. */
+#define MEM_OFFSET_KNOWN_P(RTX) (get_mem_attrs (RTX)->offset_known_p)
+
+/* For a MEM rtx, the offset from the start of MEM_EXPR. */
+#define MEM_OFFSET(RTX) (get_mem_attrs (RTX)->offset)
+
+/* For a MEM rtx, the address space. */
+#define MEM_ADDR_SPACE(RTX) (get_mem_attrs (RTX)->addrspace)
+
+/* For a MEM rtx, true if its MEM_SIZE is known. */
+#define MEM_SIZE_KNOWN_P(RTX) (get_mem_attrs (RTX)->size_known_p)
+
+/* For a MEM rtx, the size in bytes of the MEM. */
+#define MEM_SIZE(RTX) (get_mem_attrs (RTX)->size)
+
+/* For a MEM rtx, the alignment in bits. We can use the alignment of the
+ mode as a default when STRICT_ALIGNMENT, but not if not. */
+#define MEM_ALIGN(RTX) (get_mem_attrs (RTX)->align)
+#else
+#define MEM_ADDR_SPACE(RTX) ADDR_SPACE_GENERIC
+#endif
+
+/* For a REG rtx, the decl it is known to refer to, if it is known to
+ refer to part of a DECL. */
+#define REG_EXPR(RTX) (REG_ATTRS (RTX) == 0 ? 0 : REG_ATTRS (RTX)->decl)
+
+/* For a REG rtx, the offset from the start of REG_EXPR, if known, as an
+ HOST_WIDE_INT. */
+#define REG_OFFSET(RTX) (REG_ATTRS (RTX) == 0 ? 0 : REG_ATTRS (RTX)->offset)
+
+/* Copy the attributes that apply to memory locations from RHS to LHS. */
+#define MEM_COPY_ATTRIBUTES(LHS, RHS) \
+ (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
+ MEM_NOTRAP_P (LHS) = MEM_NOTRAP_P (RHS), \
+ MEM_READONLY_P (LHS) = MEM_READONLY_P (RHS), \
+ MEM_KEEP_ALIAS_SET_P (LHS) = MEM_KEEP_ALIAS_SET_P (RHS), \
+ MEM_POINTER (LHS) = MEM_POINTER (RHS), \
+ MEM_ATTRS (LHS) = MEM_ATTRS (RHS))
+
+/* 1 if RTX is a label_ref for a nonlocal label. */
+/* Likewise in an expr_list for a REG_LABEL_OPERAND or
+ REG_LABEL_TARGET note. */
+#define LABEL_REF_NONLOCAL_P(RTX) \
+ (RTL_FLAG_CHECK1 ("LABEL_REF_NONLOCAL_P", (RTX), LABEL_REF)->volatil)
+
+/* 1 if RTX is a code_label that should always be considered to be needed. */
+#define LABEL_PRESERVE_P(RTX) \
+ (RTL_FLAG_CHECK2 ("LABEL_PRESERVE_P", (RTX), CODE_LABEL, NOTE)->in_struct)
+
+/* During sched, 1 if RTX is an insn that must be scheduled together
+ with the preceding insn. */
+#define SCHED_GROUP_P(RTX) \
+ (RTL_FLAG_CHECK4 ("SCHED_GROUP_P", (RTX), DEBUG_INSN, INSN, \
+ JUMP_INSN, CALL_INSN)->in_struct)
+
+/* For a SET rtx, SET_DEST is the place that is set
+ and SET_SRC is the value it is set to. */
+#define SET_DEST(RTX) XC2EXP (RTX, 0, SET, CLOBBER)
+#define SET_SRC(RTX) XCEXP (RTX, 1, SET)
+#define SET_IS_RETURN_P(RTX) \
+ (RTL_FLAG_CHECK1 ("SET_IS_RETURN_P", (RTX), SET)->jump)
+
+/* For a TRAP_IF rtx, TRAP_CONDITION is an expression. */
+#define TRAP_CONDITION(RTX) XCEXP (RTX, 0, TRAP_IF)
+#define TRAP_CODE(RTX) XCEXP (RTX, 1, TRAP_IF)
+
+/* For a COND_EXEC rtx, COND_EXEC_TEST is the condition to base
+ conditionally executing the code on, COND_EXEC_CODE is the code
+ to execute if the condition is true. */
+#define COND_EXEC_TEST(RTX) XCEXP (RTX, 0, COND_EXEC)
+#define COND_EXEC_CODE(RTX) XCEXP (RTX, 1, COND_EXEC)
+
+/* 1 if RTX is a symbol_ref that addresses this function's rtl
+ constants pool. */
+#define CONSTANT_POOL_ADDRESS_P(RTX) \
+ (RTL_FLAG_CHECK1 ("CONSTANT_POOL_ADDRESS_P", (RTX), SYMBOL_REF)->unchanging)
+
+/* 1 if RTX is a symbol_ref that addresses a value in the file's
+ tree constant pool. This information is private to varasm.cc. */
+#define TREE_CONSTANT_POOL_ADDRESS_P(RTX) \
+ (RTL_FLAG_CHECK1 ("TREE_CONSTANT_POOL_ADDRESS_P", \
+ (RTX), SYMBOL_REF)->frame_related)
+
+/* Used if RTX is a symbol_ref, for machine-specific purposes. */
+#define SYMBOL_REF_FLAG(RTX) \
+ (RTL_FLAG_CHECK1 ("SYMBOL_REF_FLAG", (RTX), SYMBOL_REF)->volatil)
+
+/* 1 if RTX is a symbol_ref that has been the library function in
+ emit_library_call. */
+#define SYMBOL_REF_USED(RTX) \
+ (RTL_FLAG_CHECK1 ("SYMBOL_REF_USED", (RTX), SYMBOL_REF)->used)
+
+/* 1 if RTX is a symbol_ref for a weak symbol. */
+#define SYMBOL_REF_WEAK(RTX) \
+ (RTL_FLAG_CHECK1 ("SYMBOL_REF_WEAK", (RTX), SYMBOL_REF)->return_val)
+
+/* A pointer attached to the SYMBOL_REF; either SYMBOL_REF_DECL or
+ SYMBOL_REF_CONSTANT. */
+#define SYMBOL_REF_DATA(RTX) X0ANY ((RTX), 1)
+
+/* Set RTX's SYMBOL_REF_DECL to DECL. RTX must not be a constant
+ pool symbol. */
+#define SET_SYMBOL_REF_DECL(RTX, DECL) \
+ (gcc_assert (!CONSTANT_POOL_ADDRESS_P (RTX)), X0TREE ((RTX), 1) = (DECL))
+
+/* The tree (decl or constant) associated with the symbol, or null. */
+#define SYMBOL_REF_DECL(RTX) \
+ (CONSTANT_POOL_ADDRESS_P (RTX) ? NULL : X0TREE ((RTX), 1))
+
+/* Set RTX's SYMBOL_REF_CONSTANT to C. RTX must be a constant pool symbol. */
+#define SET_SYMBOL_REF_CONSTANT(RTX, C) \
+ (gcc_assert (CONSTANT_POOL_ADDRESS_P (RTX)), X0CONSTANT ((RTX), 1) = (C))
+
+/* The rtx constant pool entry for a symbol, or null. */
+#define SYMBOL_REF_CONSTANT(RTX) \
+ (CONSTANT_POOL_ADDRESS_P (RTX) ? X0CONSTANT ((RTX), 1) : NULL)
+
+/* A set of flags on a symbol_ref that are, in some respects, redundant with
+ information derivable from the tree decl associated with this symbol.
+ Except that we build a *lot* of SYMBOL_REFs that aren't associated with a
+ decl. In some cases this is a bug. But beyond that, it's nice to cache
+ this information to avoid recomputing it. Finally, this allows space for
+ the target to store more than one bit of information, as with
+ SYMBOL_REF_FLAG. */
+#define SYMBOL_REF_FLAGS(RTX) \
+ (RTL_FLAG_CHECK1 ("SYMBOL_REF_FLAGS", (RTX), SYMBOL_REF) \
+ ->u2.symbol_ref_flags)
+
+/* These flags are common enough to be defined for all targets. They
+ are computed by the default version of targetm.encode_section_info. */
+
+/* Set if this symbol is a function. */
+#define SYMBOL_FLAG_FUNCTION (1 << 0)
+#define SYMBOL_REF_FUNCTION_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_FUNCTION) != 0)
+/* Set if targetm.binds_local_p is true. */
+#define SYMBOL_FLAG_LOCAL (1 << 1)
+#define SYMBOL_REF_LOCAL_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_LOCAL) != 0)
+/* Set if targetm.in_small_data_p is true. */
+#define SYMBOL_FLAG_SMALL (1 << 2)
+#define SYMBOL_REF_SMALL_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_SMALL) != 0)
+/* The three-bit field at [5:3] is true for TLS variables; use
+ SYMBOL_REF_TLS_MODEL to extract the field as an enum tls_model. */
+#define SYMBOL_FLAG_TLS_SHIFT 3
+#define SYMBOL_REF_TLS_MODEL(RTX) \
+ ((enum tls_model) ((SYMBOL_REF_FLAGS (RTX) >> SYMBOL_FLAG_TLS_SHIFT) & 7))
+/* Set if this symbol is not defined in this translation unit. */
+#define SYMBOL_FLAG_EXTERNAL (1 << 6)
+#define SYMBOL_REF_EXTERNAL_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_EXTERNAL) != 0)
+/* Set if this symbol has a block_symbol structure associated with it. */
+#define SYMBOL_FLAG_HAS_BLOCK_INFO (1 << 7)
+#define SYMBOL_REF_HAS_BLOCK_INFO_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_HAS_BLOCK_INFO) != 0)
+/* Set if this symbol is a section anchor. SYMBOL_REF_ANCHOR_P implies
+ SYMBOL_REF_HAS_BLOCK_INFO_P. */
+#define SYMBOL_FLAG_ANCHOR (1 << 8)
+#define SYMBOL_REF_ANCHOR_P(RTX) \
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_ANCHOR) != 0)
+
+/* Subsequent bits are available for the target to use. */
+#define SYMBOL_FLAG_MACH_DEP_SHIFT 9
+#define SYMBOL_FLAG_MACH_DEP (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
+
+/* If SYMBOL_REF_HAS_BLOCK_INFO_P (RTX), this is the object_block
+ structure to which the symbol belongs, or NULL if it has not been
+ assigned a block. */
+#define SYMBOL_REF_BLOCK(RTX) (BLOCK_SYMBOL_CHECK (RTX)->block)
+
+/* If SYMBOL_REF_HAS_BLOCK_INFO_P (RTX), this is the offset of RTX from
+ the first object in SYMBOL_REF_BLOCK (RTX). The value is negative if
+ RTX has not yet been assigned to a block, or it has not been given an
+ offset within that block. */
+#define SYMBOL_REF_BLOCK_OFFSET(RTX) (BLOCK_SYMBOL_CHECK (RTX)->offset)
+
+/* True if RTX is flagged to be a scheduling barrier. */
+#define PREFETCH_SCHEDULE_BARRIER_P(RTX) \
+ (RTL_FLAG_CHECK1 ("PREFETCH_SCHEDULE_BARRIER_P", (RTX), PREFETCH)->volatil)
+
+/* Indicate whether the machine has any sort of auto increment addressing.
+ If not, we can avoid checking for REG_INC notes. */
+
+#if (defined (HAVE_PRE_INCREMENT) || defined (HAVE_PRE_DECREMENT) \
+ || defined (HAVE_POST_INCREMENT) || defined (HAVE_POST_DECREMENT) \
+ || defined (HAVE_PRE_MODIFY_DISP) || defined (HAVE_POST_MODIFY_DISP) \
+ || defined (HAVE_PRE_MODIFY_REG) || defined (HAVE_POST_MODIFY_REG))
+#define AUTO_INC_DEC 1
+#else
+#define AUTO_INC_DEC 0
+#endif
+
+/* Define a macro to look for REG_INC notes,
+ but save time on machines where they never exist. */
+
+#if AUTO_INC_DEC
+#define FIND_REG_INC_NOTE(INSN, REG) \
+ ((REG) != NULL_RTX && REG_P ((REG)) \
+ ? find_regno_note ((INSN), REG_INC, REGNO (REG)) \
+ : find_reg_note ((INSN), REG_INC, (REG)))
+#else
+#define FIND_REG_INC_NOTE(INSN, REG) 0
+#endif
+
+#ifndef HAVE_PRE_INCREMENT
+#define HAVE_PRE_INCREMENT 0
+#endif
+
+#ifndef HAVE_PRE_DECREMENT
+#define HAVE_PRE_DECREMENT 0
+#endif
+
+#ifndef HAVE_POST_INCREMENT
+#define HAVE_POST_INCREMENT 0
+#endif
+
+#ifndef HAVE_POST_DECREMENT
+#define HAVE_POST_DECREMENT 0
+#endif
+
+#ifndef HAVE_POST_MODIFY_DISP
+#define HAVE_POST_MODIFY_DISP 0
+#endif
+
+#ifndef HAVE_POST_MODIFY_REG
+#define HAVE_POST_MODIFY_REG 0
+#endif
+
+#ifndef HAVE_PRE_MODIFY_DISP
+#define HAVE_PRE_MODIFY_DISP 0
+#endif
+
+#ifndef HAVE_PRE_MODIFY_REG
+#define HAVE_PRE_MODIFY_REG 0
+#endif
+
+
+/* Some architectures do not have complete pre/post increment/decrement
+ instruction sets, or only move some modes efficiently. These macros
+ allow us to tune autoincrement generation. */
+
+#ifndef USE_LOAD_POST_INCREMENT
+#define USE_LOAD_POST_INCREMENT(MODE) HAVE_POST_INCREMENT
+#endif
+
+#ifndef USE_LOAD_POST_DECREMENT
+#define USE_LOAD_POST_DECREMENT(MODE) HAVE_POST_DECREMENT
+#endif
+
+#ifndef USE_LOAD_PRE_INCREMENT
+#define USE_LOAD_PRE_INCREMENT(MODE) HAVE_PRE_INCREMENT
+#endif
+
+#ifndef USE_LOAD_PRE_DECREMENT
+#define USE_LOAD_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
+#endif
+
+#ifndef USE_STORE_POST_INCREMENT
+#define USE_STORE_POST_INCREMENT(MODE) HAVE_POST_INCREMENT
+#endif
+
+#ifndef USE_STORE_POST_DECREMENT
+#define USE_STORE_POST_DECREMENT(MODE) HAVE_POST_DECREMENT
+#endif
+
+#ifndef USE_STORE_PRE_INCREMENT
+#define USE_STORE_PRE_INCREMENT(MODE) HAVE_PRE_INCREMENT
+#endif
+
+#ifndef USE_STORE_PRE_DECREMENT
+#define USE_STORE_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
+#endif
+
+/* Nonzero when we are generating CONCATs. */
+extern int generating_concat_p;
+
+/* Nonzero when we are expanding trees to RTL. */
+extern int currently_expanding_to_rtl;
+
+/* Generally useful functions. */
+
+#ifndef GENERATOR_FILE
+/* Return the cost of SET X. SPEED_P is true if optimizing for speed
+ rather than size. */
+
+static inline int
+set_rtx_cost (rtx x, bool speed_p)
+{
+ return rtx_cost (x, VOIDmode, INSN, 4, speed_p);
+}
+
+/* Like set_rtx_cost, but return both the speed and size costs in C. */
+
+static inline void
+get_full_set_rtx_cost (rtx x, struct full_rtx_costs *c)
+{
+ get_full_rtx_cost (x, VOIDmode, INSN, 4, c);
+}
+
+/* Return the cost of moving X into a register, relative to the cost
+ of a register move. SPEED_P is true if optimizing for speed rather
+ than size. */
+
+static inline int
+set_src_cost (rtx x, machine_mode mode, bool speed_p)
+{
+ return rtx_cost (x, mode, SET, 1, speed_p);
+}
+
+/* Like set_src_cost, but return both the speed and size costs in C. */
+
+static inline void
+get_full_set_src_cost (rtx x, machine_mode mode, struct full_rtx_costs *c)
+{
+ get_full_rtx_cost (x, mode, SET, 1, c);
+}
+#endif
+
+/* A convenience macro to validate the arguments of a zero_extract
+ expression. It determines whether SIZE lies inclusively within
+ [1, RANGE], POS lies inclusively within between [0, RANGE - 1]
+ and the sum lies inclusively within [1, RANGE]. RANGE must be
+ >= 1, but SIZE and POS may be negative. */
+#define EXTRACT_ARGS_IN_RANGE(SIZE, POS, RANGE) \
+ (IN_RANGE ((POS), 0, (unsigned HOST_WIDE_INT) (RANGE) - 1) \
+ && IN_RANGE ((SIZE), 1, (unsigned HOST_WIDE_INT) (RANGE) \
+ - (unsigned HOST_WIDE_INT)(POS)))
+
+/* In explow.cc */
+extern HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT, machine_mode);
+extern poly_int64 trunc_int_for_mode (poly_int64, machine_mode);
+extern rtx plus_constant (machine_mode, rtx, poly_int64, bool = false);
+extern HOST_WIDE_INT get_stack_check_protect (void);
+
+/* In rtl.cc */
+extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
+inline rtx
+rtx_init (rtx rt, RTX_CODE code)
+{
+ memset (rt, 0, RTX_HDR_SIZE);
+ PUT_CODE (rt, code);
+ return rt;
+}
+#define rtx_alloca(code) \
+ rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
+extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
+#define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
+#define const_wide_int_alloc(NWORDS) \
+ rtx_alloc_v (CONST_WIDE_INT, \
+ (sizeof (struct hwivec_def) \
+ + ((NWORDS)-1) * sizeof (HOST_WIDE_INT))) \
+
+extern rtvec rtvec_alloc (size_t);
+extern rtvec shallow_copy_rtvec (rtvec);
+extern bool shared_const_p (const_rtx);
+extern rtx copy_rtx (rtx);
+extern enum rtx_code classify_insn (rtx);
+extern void dump_rtx_statistics (void);
+
+/* In emit-rtl.cc */
+extern rtx copy_rtx_if_shared (rtx);
+
+/* In rtl.cc */
+extern unsigned int rtx_size (const_rtx);
+extern rtx shallow_copy_rtx (const_rtx CXX_MEM_STAT_INFO);
+extern int rtx_equal_p (const_rtx, const_rtx);
+extern bool rtvec_all_equal_p (const_rtvec);
+extern bool rtvec_series_p (rtvec, int);
+
+/* Return true if X is a vector constant with a duplicated element value. */
+
+inline bool
+const_vec_duplicate_p (const_rtx x)
+{
+ return (GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && CONST_VECTOR_DUPLICATE_P (x));
+}
+
+/* Return true if X is a vector constant with a duplicated element value.
+ Store the duplicated element in *ELT if so. */
+
+template <typename T>
+inline bool
+const_vec_duplicate_p (T x, T *elt)
+{
+ if (const_vec_duplicate_p (x))
+ {
+ *elt = CONST_VECTOR_ENCODED_ELT (x, 0);
+ return true;
+ }
+ return false;
+}
+
+/* Return true if X is a vector with a duplicated element value, either
+ constant or nonconstant. Store the duplicated element in *ELT if so. */
+
+template <typename T>
+inline bool
+vec_duplicate_p (T x, T *elt)
+{
+ if (GET_CODE (x) == VEC_DUPLICATE
+ && !VECTOR_MODE_P (GET_MODE (XEXP (x, 0))))
+ {
+ *elt = XEXP (x, 0);
+ return true;
+ }
+ return const_vec_duplicate_p (x, elt);
+}
+
+/* If X is a vector constant with a duplicated element value, return that
+ element value, otherwise return X. */
+
+template <typename T>
+inline T
+unwrap_const_vec_duplicate (T x)
+{
+ if (const_vec_duplicate_p (x))
+ x = CONST_VECTOR_ELT (x, 0);
+ return x;
+}
+
+/* In emit-rtl.cc. */
+extern wide_int const_vector_int_elt (const_rtx, unsigned int);
+extern rtx const_vector_elt (const_rtx, unsigned int);
+extern bool const_vec_series_p_1 (const_rtx, rtx *, rtx *);
+
+/* Return true if X is an integer constant vector that contains a linear
+ series of the form:
+
+ { B, B + S, B + 2 * S, B + 3 * S, ... }
+
+ for a nonzero S. Store B and S in *BASE_OUT and *STEP_OUT on sucess. */
+
+inline bool
+const_vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
+{
+ if (GET_CODE (x) == CONST_VECTOR
+ && CONST_VECTOR_NPATTERNS (x) == 1
+ && !CONST_VECTOR_DUPLICATE_P (x))
+ return const_vec_series_p_1 (x, base_out, step_out);
+ return false;
+}
+
+/* Return true if X is a vector that contains a linear series of the
+ form:
+
+ { B, B + S, B + 2 * S, B + 3 * S, ... }
+
+ where B and S are constant or nonconstant. Store B and S in
+ *BASE_OUT and *STEP_OUT on sucess. */
+
+inline bool
+vec_series_p (const_rtx x, rtx *base_out, rtx *step_out)
+{
+ if (GET_CODE (x) == VEC_SERIES)
+ {
+ *base_out = XEXP (x, 0);
+ *step_out = XEXP (x, 1);
+ return true;
+ }
+ return const_vec_series_p (x, base_out, step_out);
+}
+
+/* Return true if CONST_VECTORs X and Y, which are known to have the same mode,
+ also have the same encoding. This means that they are equal whenever their
+ operands are equal. */
+
+inline bool
+same_vector_encodings_p (const_rtx x, const_rtx y)
+{
+ /* Don't be fussy about the encoding of constant-length vectors,
+ since XVECEXP (X, 0) and XVECEXP (Y, 0) list all the elements anyway. */
+ if (poly_uint64 (CONST_VECTOR_NUNITS (x)).is_constant ())
+ return true;
+
+ return (CONST_VECTOR_NPATTERNS (x) == CONST_VECTOR_NPATTERNS (y)
+ && (CONST_VECTOR_NELTS_PER_PATTERN (x)
+ == CONST_VECTOR_NELTS_PER_PATTERN (y)));
+}
+
+/* Return the unpromoted (outer) mode of SUBREG_PROMOTED_VAR_P subreg X. */
+
+inline scalar_int_mode
+subreg_unpromoted_mode (rtx x)
+{
+ gcc_checking_assert (SUBREG_PROMOTED_VAR_P (x));
+ return as_a <scalar_int_mode> (GET_MODE (x));
+}
+
+/* Return the promoted (inner) mode of SUBREG_PROMOTED_VAR_P subreg X. */
+
+inline scalar_int_mode
+subreg_promoted_mode (rtx x)
+{
+ gcc_checking_assert (SUBREG_PROMOTED_VAR_P (x));
+ return as_a <scalar_int_mode> (GET_MODE (SUBREG_REG (x)));
+}
+
+/* In emit-rtl.cc */
+extern rtvec gen_rtvec_v (int, rtx *);
+extern rtvec gen_rtvec_v (int, rtx_insn **);
+extern rtx gen_reg_rtx (machine_mode);
+extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, poly_int64);
+extern rtx gen_reg_rtx_offset (rtx, machine_mode, int);
+extern rtx gen_reg_rtx_and_attrs (rtx);
+extern rtx_code_label *gen_label_rtx (void);
+extern rtx gen_lowpart_common (machine_mode, rtx);
+
+/* In cse.cc */
+extern rtx gen_lowpart_if_possible (machine_mode, rtx);
+
+/* In emit-rtl.cc */
+extern rtx gen_highpart (machine_mode, rtx);
+extern rtx gen_highpart_mode (machine_mode, machine_mode, rtx);
+extern rtx operand_subword (rtx, poly_uint64, int, machine_mode);
+
+/* In emit-rtl.cc */
+extern rtx operand_subword_force (rtx, poly_uint64, machine_mode);
+extern int subreg_lowpart_p (const_rtx);
+extern poly_uint64 subreg_size_lowpart_offset (poly_uint64, poly_uint64);
+
+/* Return true if a subreg of mode OUTERMODE would only access part of
+ an inner register with mode INNERMODE. The other bits of the inner
+ register would then be "don't care" on read. The behavior for writes
+ depends on REGMODE_NATURAL_SIZE; bits in the same REGMODE_NATURAL_SIZE-d
+ chunk would be clobbered but other bits would be preserved. */
+
+inline bool
+partial_subreg_p (machine_mode outermode, machine_mode innermode)
+{
+ /* Modes involved in a subreg must be ordered. In particular, we must
+ always know at compile time whether the subreg is paradoxical. */
+ poly_int64 outer_prec = GET_MODE_PRECISION (outermode);
+ poly_int64 inner_prec = GET_MODE_PRECISION (innermode);
+ gcc_checking_assert (ordered_p (outer_prec, inner_prec));
+ return maybe_lt (outer_prec, inner_prec);
+}
+
+/* Likewise return true if X is a subreg that is smaller than the inner
+ register. Use read_modify_subreg_p to test whether writing to such
+ a subreg preserves any part of the inner register. */
+
+inline bool
+partial_subreg_p (const_rtx x)
+{
+ if (GET_CODE (x) != SUBREG)
+ return false;
+ return partial_subreg_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
+/* Return true if a subreg with the given outer and inner modes is
+ paradoxical. */
+
+inline bool
+paradoxical_subreg_p (machine_mode outermode, machine_mode innermode)
+{
+ /* Modes involved in a subreg must be ordered. In particular, we must
+ always know at compile time whether the subreg is paradoxical. */
+ poly_int64 outer_prec = GET_MODE_PRECISION (outermode);
+ poly_int64 inner_prec = GET_MODE_PRECISION (innermode);
+ gcc_checking_assert (ordered_p (outer_prec, inner_prec));
+ return maybe_gt (outer_prec, inner_prec);
+}
+
+/* Return true if X is a paradoxical subreg, false otherwise. */
+
+inline bool
+paradoxical_subreg_p (const_rtx x)
+{
+ if (GET_CODE (x) != SUBREG)
+ return false;
+ return paradoxical_subreg_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
+/* Return the SUBREG_BYTE for an OUTERMODE lowpart of an INNERMODE value. */
+
+inline poly_uint64
+subreg_lowpart_offset (machine_mode outermode, machine_mode innermode)
+{
+ return subreg_size_lowpart_offset (GET_MODE_SIZE (outermode),
+ GET_MODE_SIZE (innermode));
+}
+
+/* Given that a subreg has outer mode OUTERMODE and inner mode INNERMODE,
+ return the smaller of the two modes if they are different sizes,
+ otherwise return the outer mode. */
+
+inline machine_mode
+narrower_subreg_mode (machine_mode outermode, machine_mode innermode)
+{
+ return paradoxical_subreg_p (outermode, innermode) ? innermode : outermode;
+}
+
+/* Given that a subreg has outer mode OUTERMODE and inner mode INNERMODE,
+ return the mode that is big enough to hold both the outer and inner
+ values. Prefer the outer mode in the event of a tie. */
+
+inline machine_mode
+wider_subreg_mode (machine_mode outermode, machine_mode innermode)
+{
+ return partial_subreg_p (outermode, innermode) ? innermode : outermode;
+}
+
+/* Likewise for subreg X. */
+
+inline machine_mode
+wider_subreg_mode (const_rtx x)
+{
+ return wider_subreg_mode (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
+extern poly_uint64 subreg_size_highpart_offset (poly_uint64, poly_uint64);
+
+/* Return the SUBREG_BYTE for an OUTERMODE highpart of an INNERMODE value. */
+
+inline poly_uint64
+subreg_highpart_offset (machine_mode outermode, machine_mode innermode)
+{
+ return subreg_size_highpart_offset (GET_MODE_SIZE (outermode),
+ GET_MODE_SIZE (innermode));
+}
+
+extern poly_int64 byte_lowpart_offset (machine_mode, machine_mode);
+extern poly_int64 subreg_memory_offset (machine_mode, machine_mode,
+ poly_uint64);
+extern poly_int64 subreg_memory_offset (const_rtx);
+extern rtx make_safe_from (rtx, rtx);
+extern rtx convert_memory_address_addr_space_1 (scalar_int_mode, rtx,
+ addr_space_t, bool, bool);
+extern rtx convert_memory_address_addr_space (scalar_int_mode, rtx,
+ addr_space_t);
+#define convert_memory_address(to_mode,x) \
+ convert_memory_address_addr_space ((to_mode), (x), ADDR_SPACE_GENERIC)
+extern const char *get_insn_name (int);
+extern rtx_insn *get_last_insn_anywhere (void);
+extern rtx_insn *get_first_nonnote_insn (void);
+extern rtx_insn *get_last_nonnote_insn (void);
+extern void start_sequence (void);
+extern void push_to_sequence (rtx_insn *);
+extern void push_to_sequence2 (rtx_insn *, rtx_insn *);
+extern void end_sequence (void);
+#if TARGET_SUPPORTS_WIDE_INT == 0
+extern double_int rtx_to_double_int (const_rtx);
+#endif
+extern void cwi_output_hex (FILE *, const_rtx);
+#if TARGET_SUPPORTS_WIDE_INT == 0
+extern rtx immed_double_const (HOST_WIDE_INT, HOST_WIDE_INT,
+ machine_mode);
+#endif
+extern rtx immed_wide_int_const (const poly_wide_int_ref &, machine_mode);
+
+/* In varasm.cc */
+extern rtx force_const_mem (machine_mode, rtx);
+
+/* In varasm.cc */
+
+struct function;
+extern rtx get_pool_constant (const_rtx);
+extern rtx get_pool_constant_mark (rtx, bool *);
+extern fixed_size_mode get_pool_mode (const_rtx);
+extern rtx simplify_subtraction (rtx);
+extern void decide_function_section (tree);
+
+/* In emit-rtl.cc */
+extern rtx_insn *emit_insn_before (rtx, rtx_insn *);
+extern rtx_insn *emit_insn_before_noloc (rtx, rtx_insn *, basic_block);
+extern rtx_insn *emit_insn_before_setloc (rtx, rtx_insn *, location_t);
+extern rtx_jump_insn *emit_jump_insn_before (rtx, rtx_insn *);
+extern rtx_jump_insn *emit_jump_insn_before_noloc (rtx, rtx_insn *);
+extern rtx_jump_insn *emit_jump_insn_before_setloc (rtx, rtx_insn *,
+ location_t);
+extern rtx_insn *emit_call_insn_before (rtx, rtx_insn *);
+extern rtx_insn *emit_call_insn_before_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_call_insn_before_setloc (rtx, rtx_insn *, location_t);
+extern rtx_insn *emit_debug_insn_before (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_before_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_before_setloc (rtx, rtx_insn *, location_t);
+extern rtx_barrier *emit_barrier_before (rtx_insn *);
+extern rtx_code_label *emit_label_before (rtx_code_label *, rtx_insn *);
+extern rtx_note *emit_note_before (enum insn_note, rtx_insn *);
+extern rtx_insn *emit_insn_after (rtx, rtx_insn *);
+extern rtx_insn *emit_insn_after_noloc (rtx, rtx_insn *, basic_block);
+extern rtx_insn *emit_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_jump_insn *emit_jump_insn_after (rtx, rtx_insn *);
+extern rtx_jump_insn *emit_jump_insn_after_noloc (rtx, rtx_insn *);
+extern rtx_jump_insn *emit_jump_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_insn *emit_call_insn_after (rtx, rtx_insn *);
+extern rtx_insn *emit_call_insn_after_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_call_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_insn *emit_debug_insn_after (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_after_noloc (rtx, rtx_insn *);
+extern rtx_insn *emit_debug_insn_after_setloc (rtx, rtx_insn *, location_t);
+extern rtx_barrier *emit_barrier_after (rtx_insn *);
+extern rtx_insn *emit_label_after (rtx_insn *, rtx_insn *);
+extern rtx_note *emit_note_after (enum insn_note, rtx_insn *);
+extern rtx_insn *emit_insn (rtx);
+extern rtx_insn *emit_debug_insn (rtx);
+extern rtx_insn *emit_jump_insn (rtx);
+extern rtx_insn *emit_call_insn (rtx);
+extern rtx_code_label *emit_label (rtx);
+extern rtx_jump_table_data *emit_jump_table_data (rtx);
+extern rtx_barrier *emit_barrier (void);
+extern rtx_note *emit_note (enum insn_note);
+extern rtx_note *emit_note_copy (rtx_note *);
+extern rtx_insn *gen_clobber (rtx);
+extern rtx_insn *emit_clobber (rtx);
+extern rtx_insn *gen_use (rtx);
+extern rtx_insn *emit_use (rtx);
+extern rtx_insn *make_insn_raw (rtx);
+extern void add_function_usage_to (rtx, rtx);
+extern rtx_call_insn *last_call_insn (void);
+extern rtx_insn *previous_insn (rtx_insn *);
+extern rtx_insn *next_insn (rtx_insn *);
+extern rtx_insn *prev_nonnote_insn (rtx_insn *);
+extern rtx_insn *next_nonnote_insn (rtx_insn *);
+extern rtx_insn *prev_nondebug_insn (rtx_insn *);
+extern rtx_insn *next_nondebug_insn (rtx_insn *);
+extern rtx_insn *prev_nonnote_nondebug_insn (rtx_insn *);
+extern rtx_insn *prev_nonnote_nondebug_insn_bb (rtx_insn *);
+extern rtx_insn *next_nonnote_nondebug_insn (rtx_insn *);
+extern rtx_insn *next_nonnote_nondebug_insn_bb (rtx_insn *);
+extern rtx_insn *prev_real_insn (rtx_insn *);
+extern rtx_insn *next_real_insn (rtx_insn *);
+extern rtx_insn *prev_real_nondebug_insn (rtx_insn *);
+extern rtx_insn *next_real_nondebug_insn (rtx);
+extern rtx_insn *prev_active_insn (rtx_insn *);
+extern rtx_insn *next_active_insn (rtx_insn *);
+extern int active_insn_p (const rtx_insn *);
+
+/* In emit-rtl.cc */
+extern int insn_line (const rtx_insn *);
+extern const char * insn_file (const rtx_insn *);
+extern tree insn_scope (const rtx_insn *);
+extern expanded_location insn_location (const rtx_insn *);
+extern location_t prologue_location, epilogue_location;
+
+/* In jump.cc */
+extern enum rtx_code reverse_condition (enum rtx_code);
+extern enum rtx_code reverse_condition_maybe_unordered (enum rtx_code);
+extern enum rtx_code swap_condition (enum rtx_code);
+extern enum rtx_code unsigned_condition (enum rtx_code);
+extern enum rtx_code signed_condition (enum rtx_code);
+extern void mark_jump_label (rtx, rtx_insn *, int);
+
+/* Return true if integer comparison operator CODE interprets its operands
+ as unsigned. */
+
+inline bool
+unsigned_condition_p (enum rtx_code code)
+{
+ return unsigned_condition (code) == code;
+}
+
+/* In jump.cc */
+extern rtx_insn *delete_related_insns (rtx);
+
+/* In recog.cc */
+extern rtx *find_constant_term_loc (rtx *);
+
+/* In emit-rtl.cc */
+extern rtx_insn *try_split (rtx, rtx_insn *, int);
+
+/* In insn-recog.cc (generated by genrecog). */
+extern rtx_insn *split_insns (rtx, rtx_insn *);
+
+/* In simplify-rtx.cc */
+
+/* A class that records the context in which a simplification
+ is being mode. */
+class simplify_context
+{
+public:
+ rtx simplify_unary_operation (rtx_code, machine_mode, rtx, machine_mode);
+ rtx simplify_binary_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_ternary_operation (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_relational_operation (rtx_code, machine_mode, machine_mode,
+ rtx, rtx);
+ rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+
+ rtx lowpart_subreg (machine_mode, rtx, machine_mode);
+
+ rtx simplify_merge_mask (rtx, rtx, int);
+
+ rtx simplify_gen_unary (rtx_code, machine_mode, rtx, machine_mode);
+ rtx simplify_gen_binary (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_gen_ternary (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_gen_relational (rtx_code, machine_mode, machine_mode, rtx, rtx);
+ rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+ rtx simplify_gen_vec_select (rtx, unsigned int);
+
+ /* Tracks the level of MEM nesting for the value being simplified:
+ 0 means the value is not in a MEM, >0 means it is. This is needed
+ because the canonical representation of multiplication is different
+ inside a MEM than outside. */
+ unsigned int mem_depth = 0;
+
+ /* Tracks number of simplify_associative_operation calls performed during
+ outermost simplify* call. */
+ unsigned int assoc_count = 0;
+
+ /* Limit for the above number, return NULL from
+ simplify_associative_operation after we reach that assoc_count. */
+ static const unsigned int max_assoc_count = 64;
+
+private:
+ rtx simplify_truncation (machine_mode, rtx, machine_mode);
+ rtx simplify_byte_swapping_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_associative_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_distributive_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_logical_relational_operation (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_binary_operation_series (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_distribute_over_subregs (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_shift_const_int (rtx_code, machine_mode, rtx, unsigned int);
+ rtx simplify_plus_minus (rtx_code, machine_mode, rtx, rtx);
+ rtx simplify_cond_clz_ctz (rtx, rtx_code, rtx, rtx);
+
+ rtx simplify_unary_operation_1 (rtx_code, machine_mode, rtx);
+ rtx simplify_binary_operation_1 (rtx_code, machine_mode, rtx, rtx, rtx, rtx);
+ rtx simplify_ternary_operation_1 (rtx_code, machine_mode, machine_mode,
+ rtx, rtx, rtx);
+ rtx simplify_relational_operation_1 (rtx_code, machine_mode, machine_mode,
+ rtx, rtx);
+};
+
+inline rtx
+simplify_unary_operation (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
+{
+ return simplify_context ().simplify_unary_operation (code, mode, op,
+ op_mode);
+}
+
+inline rtx
+simplify_binary_operation (rtx_code code, machine_mode mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_binary_operation (code, mode, op0, op1);
+}
+
+inline rtx
+simplify_ternary_operation (rtx_code code, machine_mode mode,
+ machine_mode op0_mode, rtx op0, rtx op1, rtx op2)
+{
+ return simplify_context ().simplify_ternary_operation (code, mode, op0_mode,
+ op0, op1, op2);
+}
+
+inline rtx
+simplify_relational_operation (rtx_code code, machine_mode mode,
+ machine_mode op_mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_relational_operation (code, mode,
+ op_mode, op0, op1);
+}
+
+inline rtx
+simplify_subreg (machine_mode outermode, rtx op, machine_mode innermode,
+ poly_uint64 byte)
+{
+ return simplify_context ().simplify_subreg (outermode, op, innermode, byte);
+}
+
+inline rtx
+simplify_gen_unary (rtx_code code, machine_mode mode, rtx op,
+ machine_mode op_mode)
+{
+ return simplify_context ().simplify_gen_unary (code, mode, op, op_mode);
+}
+
+inline rtx
+simplify_gen_binary (rtx_code code, machine_mode mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_gen_binary (code, mode, op0, op1);
+}
+
+inline rtx
+simplify_gen_ternary (rtx_code code, machine_mode mode, machine_mode op0_mode,
+ rtx op0, rtx op1, rtx op2)
+{
+ return simplify_context ().simplify_gen_ternary (code, mode, op0_mode,
+ op0, op1, op2);
+}
+
+inline rtx
+simplify_gen_relational (rtx_code code, machine_mode mode,
+ machine_mode op_mode, rtx op0, rtx op1)
+{
+ return simplify_context ().simplify_gen_relational (code, mode, op_mode,
+ op0, op1);
+}
+
+inline rtx
+simplify_gen_subreg (machine_mode outermode, rtx op, machine_mode innermode,
+ poly_uint64 byte)
+{
+ return simplify_context ().simplify_gen_subreg (outermode, op,
+ innermode, byte);
+}
+
+inline rtx
+simplify_gen_vec_select (rtx op, unsigned int index)
+{
+ return simplify_context ().simplify_gen_vec_select (op, index);
+}
+
+inline rtx
+lowpart_subreg (machine_mode outermode, rtx op, machine_mode innermode)
+{
+ return simplify_context ().lowpart_subreg (outermode, op, innermode);
+}
+
+extern rtx simplify_const_unary_operation (enum rtx_code, machine_mode,
+ rtx, machine_mode);
+extern rtx simplify_const_binary_operation (enum rtx_code, machine_mode,
+ rtx, rtx);
+extern rtx simplify_const_relational_operation (enum rtx_code,
+ machine_mode, rtx, rtx);
+extern rtx simplify_replace_fn_rtx (rtx, const_rtx,
+ rtx (*fn) (rtx, const_rtx, void *), void *);
+extern rtx simplify_replace_rtx (rtx, const_rtx, rtx);
+extern rtx simplify_rtx (const_rtx);
+extern rtx avoid_constant_pool_reference (rtx);
+extern rtx delegitimize_mem_from_attrs (rtx);
+extern bool mode_signbit_p (machine_mode, const_rtx);
+extern bool val_signbit_p (machine_mode, unsigned HOST_WIDE_INT);
+extern bool val_signbit_known_set_p (machine_mode,
+ unsigned HOST_WIDE_INT);
+extern bool val_signbit_known_clear_p (machine_mode,
+ unsigned HOST_WIDE_INT);
+
+/* In reginfo.cc */
+extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
+ const predefined_function_abi *);
+extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &);
+
+/* In emit-rtl.cc */
+extern rtx set_for_reg_notes (rtx);
+extern rtx set_unique_reg_note (rtx, enum reg_note, rtx);
+extern rtx set_dst_reg_note (rtx, enum reg_note, rtx, rtx);
+extern void set_insn_deleted (rtx_insn *);
+
+/* Functions in rtlanal.cc */
+
+extern rtx single_set_2 (const rtx_insn *, const_rtx);
+extern rtx simple_regno_set (rtx, unsigned int);
+extern bool contains_symbol_ref_p (const_rtx);
+extern bool contains_symbolic_reference_p (const_rtx);
+extern bool contains_constant_pool_address_p (const_rtx);
+extern void add_auto_inc_notes (rtx_insn *, rtx);
+
+/* Handle the cheap and common cases inline for performance. */
+
+inline rtx single_set (const rtx_insn *insn)
+{
+ if (!INSN_P (insn))
+ return NULL_RTX;
+
+ if (GET_CODE (PATTERN (insn)) == SET)
+ return PATTERN (insn);
+
+ /* Defer to the more expensive case. */
+ return single_set_2 (insn, PATTERN (insn));
+}
+
+extern scalar_int_mode get_address_mode (rtx mem);
+extern int rtx_addr_can_trap_p (const_rtx);
+extern bool nonzero_address_p (const_rtx);
+extern int rtx_unstable_p (const_rtx);
+extern bool rtx_varies_p (const_rtx, bool);
+extern bool rtx_addr_varies_p (const_rtx, bool);
+extern rtx get_call_rtx_from (const rtx_insn *);
+extern tree get_call_fndecl (const rtx_insn *);
+extern HOST_WIDE_INT get_integer_term (const_rtx);
+extern rtx get_related_value (const_rtx);
+extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT);
+extern void split_const (rtx, rtx *, rtx *);
+extern rtx strip_offset (rtx, poly_int64_pod *);
+extern poly_int64 get_args_size (const_rtx);
+extern bool unsigned_reg_p (rtx);
+extern int reg_mentioned_p (const_rtx, const_rtx);
+extern int count_occurrences (const_rtx, const_rtx, int);
+extern int reg_referenced_p (const_rtx, const_rtx);
+extern int reg_used_between_p (const_rtx, const rtx_insn *, const rtx_insn *);
+extern int reg_set_between_p (const_rtx, const rtx_insn *, const rtx_insn *);
+extern int commutative_operand_precedence (rtx);
+extern bool swap_commutative_operands_p (rtx, rtx);
+extern int modified_between_p (const_rtx, const rtx_insn *, const rtx_insn *);
+extern int no_labels_between_p (const rtx_insn *, const rtx_insn *);
+extern int modified_in_p (const_rtx, const_rtx);
+extern int reg_set_p (const_rtx, const_rtx);
+extern int multiple_sets (const_rtx);
+extern int set_noop_p (const_rtx);
+extern int noop_move_p (const rtx_insn *);
+extern bool refers_to_regno_p (unsigned int, unsigned int, const_rtx, rtx *);
+extern int reg_overlap_mentioned_p (const_rtx, const_rtx);
+extern const_rtx set_of (const_rtx, const_rtx);
+extern void record_hard_reg_sets (rtx, const_rtx, void *);
+extern void record_hard_reg_uses (rtx *, void *);
+extern void find_all_hard_regs (const_rtx, HARD_REG_SET *);
+extern void find_all_hard_reg_sets (const rtx_insn *, HARD_REG_SET *, bool);
+extern void note_pattern_stores (const_rtx,
+ void (*) (rtx, const_rtx, void *), void *);
+extern void note_stores (const rtx_insn *,
+ void (*) (rtx, const_rtx, void *), void *);
+extern void note_uses (rtx *, void (*) (rtx *, void *), void *);
+extern int dead_or_set_p (const rtx_insn *, const_rtx);
+extern int dead_or_set_regno_p (const rtx_insn *, unsigned int);
+extern rtx find_reg_note (const_rtx, enum reg_note, const_rtx);
+extern rtx find_regno_note (const_rtx, enum reg_note, unsigned int);
+extern rtx find_reg_equal_equiv_note (const_rtx);
+extern rtx find_constant_src (const rtx_insn *);
+extern int find_reg_fusage (const_rtx, enum rtx_code, const_rtx);
+extern int find_regno_fusage (const_rtx, enum rtx_code, unsigned int);
+extern rtx alloc_reg_note (enum reg_note, rtx, rtx);
+extern void add_reg_note (rtx, enum reg_note, rtx);
+extern void add_int_reg_note (rtx_insn *, enum reg_note, int);
+extern void add_args_size_note (rtx_insn *, poly_int64);
+extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
+extern rtx duplicate_reg_note (rtx);
+extern void remove_note (rtx_insn *, const_rtx);
+extern bool remove_reg_equal_equiv_notes (rtx_insn *, bool = false);
+extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
+extern int side_effects_p (const_rtx);
+extern int volatile_refs_p (const_rtx);
+extern int volatile_insn_p (const_rtx);
+extern int may_trap_p_1 (const_rtx, unsigned);
+extern int may_trap_p (const_rtx);
+extern int may_trap_or_fault_p (const_rtx);
+extern bool can_throw_internal (const_rtx);
+extern bool can_throw_external (const_rtx);
+extern bool insn_could_throw_p (const_rtx);
+extern bool insn_nothrow_p (const_rtx);
+extern bool can_nonlocal_goto (const rtx_insn *);
+extern void copy_reg_eh_region_note_forward (rtx, rtx_insn *, rtx);
+extern void copy_reg_eh_region_note_backward (rtx, rtx_insn *, rtx);
+extern rtx replace_rtx (rtx, rtx, rtx, bool = false);
+extern void replace_label (rtx *, rtx, rtx, bool);
+extern void replace_label_in_insn (rtx_insn *, rtx_insn *, rtx_insn *, bool);
+extern bool rtx_referenced_p (const_rtx, const_rtx);
+extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **);
+extern rtx tablejump_casesi_pattern (const rtx_insn *insn);
+extern int computed_jump_p (const rtx_insn *);
+extern bool tls_referenced_p (const_rtx);
+extern bool contains_mem_rtx_p (rtx x);
+extern bool register_asm_p (const_rtx);
+
+/* Overload for refers_to_regno_p for checking a single register. */
+inline bool
+refers_to_regno_p (unsigned int regnum, const_rtx x, rtx* loc = NULL)
+{
+ return refers_to_regno_p (regnum, regnum + 1, x, loc);
+}
+
+/* Callback for for_each_inc_dec, to process the autoinc operation OP
+ within MEM that sets DEST to SRC + SRCOFF, or SRC if SRCOFF is
+ NULL. The callback is passed the same opaque ARG passed to
+ for_each_inc_dec. Return zero to continue looking for other
+ autoinc operations or any other value to interrupt the traversal and
+ return that value to the caller of for_each_inc_dec. */
+typedef int (*for_each_inc_dec_fn) (rtx mem, rtx op, rtx dest, rtx src,
+ rtx srcoff, void *arg);
+extern int for_each_inc_dec (rtx, for_each_inc_dec_fn, void *arg);
+
+typedef int (*rtx_equal_p_callback_function) (const_rtx *, const_rtx *,
+ rtx *, rtx *);
+extern int rtx_equal_p_cb (const_rtx, const_rtx,
+ rtx_equal_p_callback_function);
+
+typedef int (*hash_rtx_callback_function) (const_rtx, machine_mode, rtx *,
+ machine_mode *);
+extern unsigned hash_rtx_cb (const_rtx, machine_mode, int *, int *,
+ bool, hash_rtx_callback_function);
+
+extern rtx regno_use_in (unsigned int, rtx);
+extern int auto_inc_p (const_rtx);
+extern bool in_insn_list_p (const rtx_insn_list *, const rtx_insn *);
+extern void remove_node_from_expr_list (const_rtx, rtx_expr_list **);
+extern void remove_node_from_insn_list (const rtx_insn *, rtx_insn_list **);
+extern int loc_mentioned_in_p (rtx *, const_rtx);
+extern rtx_insn *find_first_parameter_load (rtx_insn *, rtx_insn *);
+extern bool keep_with_call_p (const rtx_insn *);
+extern bool label_is_jump_target_p (const_rtx, const rtx_insn *);
+extern int pattern_cost (rtx, bool);
+extern int insn_cost (rtx_insn *, bool);
+extern unsigned seq_cost (const rtx_insn *, bool);
+
+/* Given an insn and condition, return a canonical description of
+ the test being made. */
+extern rtx canonicalize_condition (rtx_insn *, rtx, int, rtx_insn **, rtx,
+ int, int);
+
+/* Given a JUMP_INSN, return a canonical description of the test
+ being made. */
+extern rtx get_condition (rtx_insn *, rtx_insn **, int, int);
+
+/* Information about a subreg of a hard register. */
+struct subreg_info
+{
+ /* Offset of first hard register involved in the subreg. */
+ int offset;
+ /* Number of hard registers involved in the subreg. In the case of
+ a paradoxical subreg, this is the number of registers that would
+ be modified by writing to the subreg; some of them may be don't-care
+ when reading from the subreg. */
+ int nregs;
+ /* Whether this subreg can be represented as a hard reg with the new
+ mode (by adding OFFSET to the original hard register). */
+ bool representable_p;
+};
+
+extern void subreg_get_info (unsigned int, machine_mode,
+ poly_uint64, machine_mode,
+ struct subreg_info *);
+
+/* lists.cc */
+
+extern void free_EXPR_LIST_list (rtx_expr_list **);
+extern void free_INSN_LIST_list (rtx_insn_list **);
+extern void free_EXPR_LIST_node (rtx);
+extern void free_INSN_LIST_node (rtx);
+extern rtx_insn_list *alloc_INSN_LIST (rtx, rtx);
+extern rtx_insn_list *copy_INSN_LIST (rtx_insn_list *);
+extern rtx_insn_list *concat_INSN_LIST (rtx_insn_list *, rtx_insn_list *);
+extern rtx_expr_list *alloc_EXPR_LIST (int, rtx, rtx);
+extern void remove_free_INSN_LIST_elem (rtx_insn *, rtx_insn_list **);
+extern rtx remove_list_elem (rtx, rtx *);
+extern rtx_insn *remove_free_INSN_LIST_node (rtx_insn_list **);
+extern rtx remove_free_EXPR_LIST_node (rtx_expr_list **);
+
+
+/* reginfo.cc */
+
+/* Resize reg info. */
+extern bool resize_reg_info (void);
+/* Free up register info memory. */
+extern void free_reg_info (void);
+extern void init_subregs_of_mode (void);
+extern void finish_subregs_of_mode (void);
+extern void reginfo_cc_finalize (void);
+
+/* recog.cc */
+extern rtx extract_asm_operands (rtx);
+extern int asm_noperands (const_rtx);
+extern const char *decode_asm_operands (rtx, rtx *, rtx **, const char **,
+ machine_mode *, location_t *);
+extern void get_referenced_operands (const char *, bool *, unsigned int);
+
+extern enum reg_class reg_preferred_class (int);
+extern enum reg_class reg_alternate_class (int);
+extern enum reg_class reg_allocno_class (int);
+extern void setup_reg_classes (int, enum reg_class, enum reg_class,
+ enum reg_class);
+
+extern void split_all_insns (void);
+extern unsigned int split_all_insns_noflow (void);
+
+#define MAX_SAVED_CONST_INT 64
+extern GTY(()) rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
+
+#define const0_rtx (const_int_rtx[MAX_SAVED_CONST_INT])
+#define const1_rtx (const_int_rtx[MAX_SAVED_CONST_INT+1])
+#define const2_rtx (const_int_rtx[MAX_SAVED_CONST_INT+2])
+#define constm1_rtx (const_int_rtx[MAX_SAVED_CONST_INT-1])
+extern GTY(()) rtx const_true_rtx;
+
+extern GTY(()) rtx const_tiny_rtx[4][(int) MAX_MACHINE_MODE];
+
+/* Returns a constant 0 rtx in mode MODE. Integer modes are treated the
+ same as VOIDmode. */
+
+#define CONST0_RTX(MODE) (const_tiny_rtx[0][(int) (MODE)])
+
+/* Likewise, for the constants 1 and 2 and -1. */
+
+#define CONST1_RTX(MODE) (const_tiny_rtx[1][(int) (MODE)])
+#define CONST2_RTX(MODE) (const_tiny_rtx[2][(int) (MODE)])
+#define CONSTM1_RTX(MODE) (const_tiny_rtx[3][(int) (MODE)])
+
+extern GTY(()) rtx pc_rtx;
+extern GTY(()) rtx ret_rtx;
+extern GTY(()) rtx simple_return_rtx;
+extern GTY(()) rtx_insn *invalid_insn_rtx;
+
+/* If HARD_FRAME_POINTER_REGNUM is defined, then a special dummy reg
+ is used to represent the frame pointer. This is because the
+ hard frame pointer and the automatic variables are separated by an amount
+ that cannot be determined until after register allocation. We can assume
+ that in this case ELIMINABLE_REGS will be defined, one action of which
+ will be to eliminate FRAME_POINTER_REGNUM into HARD_FRAME_POINTER_REGNUM. */
+#ifndef HARD_FRAME_POINTER_REGNUM
+#define HARD_FRAME_POINTER_REGNUM FRAME_POINTER_REGNUM
+#endif
+
+#ifndef HARD_FRAME_POINTER_IS_FRAME_POINTER
+#define HARD_FRAME_POINTER_IS_FRAME_POINTER \
+ (HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM)
+#endif
+
+#ifndef HARD_FRAME_POINTER_IS_ARG_POINTER
+#define HARD_FRAME_POINTER_IS_ARG_POINTER \
+ (HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM)
+#endif
+
+/* Index labels for global_rtl. */
+enum global_rtl_index
+{
+ GR_STACK_POINTER,
+ GR_FRAME_POINTER,
+/* For register elimination to work properly these hard_frame_pointer_rtx,
+ frame_pointer_rtx, and arg_pointer_rtx must be the same if they refer to
+ the same register. */
+#if FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
+ GR_ARG_POINTER = GR_FRAME_POINTER,
+#endif
+#if HARD_FRAME_POINTER_IS_FRAME_POINTER
+ GR_HARD_FRAME_POINTER = GR_FRAME_POINTER,
+#else
+ GR_HARD_FRAME_POINTER,
+#endif
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+#if HARD_FRAME_POINTER_IS_ARG_POINTER
+ GR_ARG_POINTER = GR_HARD_FRAME_POINTER,
+#else
+ GR_ARG_POINTER,
+#endif
+#endif
+ GR_VIRTUAL_INCOMING_ARGS,
+ GR_VIRTUAL_STACK_ARGS,
+ GR_VIRTUAL_STACK_DYNAMIC,
+ GR_VIRTUAL_OUTGOING_ARGS,
+ GR_VIRTUAL_CFA,
+ GR_VIRTUAL_PREFERRED_STACK_BOUNDARY,
+
+ GR_MAX
+};
+
+/* Target-dependent globals. */
+struct GTY(()) target_rtl {
+ /* All references to the hard registers in global_rtl_index go through
+ these unique rtl objects. On machines where the frame-pointer and
+ arg-pointer are the same register, they use the same unique object.
+
+ After register allocation, other rtl objects which used to be pseudo-regs
+ may be clobbered to refer to the frame-pointer register.
+ But references that were originally to the frame-pointer can be
+ distinguished from the others because they contain frame_pointer_rtx.
+
+ When to use frame_pointer_rtx and hard_frame_pointer_rtx is a little
+ tricky: until register elimination has taken place hard_frame_pointer_rtx
+ should be used if it is being set, and frame_pointer_rtx otherwise. After
+ register elimination hard_frame_pointer_rtx should always be used.
+ On machines where the two registers are same (most) then these are the
+ same. */
+ rtx x_global_rtl[GR_MAX];
+
+ /* A unique representation of (REG:Pmode PIC_OFFSET_TABLE_REGNUM). */
+ rtx x_pic_offset_table_rtx;
+
+ /* A unique representation of (REG:Pmode RETURN_ADDRESS_POINTER_REGNUM).
+ This is used to implement __builtin_return_address for some machines;
+ see for instance the MIPS port. */
+ rtx x_return_address_pointer_rtx;
+
+ /* Commonly used RTL for hard registers. These objects are not
+ necessarily unique, so we allocate them separately from global_rtl.
+ They are initialized once per compilation unit, then copied into
+ regno_reg_rtx at the beginning of each function. */
+ rtx x_initial_regno_reg_rtx[FIRST_PSEUDO_REGISTER];
+
+ /* A sample (mem:M stack_pointer_rtx) rtx for each mode M. */
+ rtx x_top_of_stack[MAX_MACHINE_MODE];
+
+ /* Static hunks of RTL used by the aliasing code; these are treated
+ as persistent to avoid unnecessary RTL allocations. */
+ rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER];
+
+ /* The default memory attributes for each mode. */
+ class mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
+
+ /* Track if RTL has been initialized. */
+ bool target_specific_initialized;
+};
+
+extern GTY(()) struct target_rtl default_target_rtl;
+#if SWITCHABLE_TARGET
+extern struct target_rtl *this_target_rtl;
+#else
+#define this_target_rtl (&default_target_rtl)
+#endif
+
+#define global_rtl \
+ (this_target_rtl->x_global_rtl)
+#define pic_offset_table_rtx \
+ (this_target_rtl->x_pic_offset_table_rtx)
+#define return_address_pointer_rtx \
+ (this_target_rtl->x_return_address_pointer_rtx)
+#define top_of_stack \
+ (this_target_rtl->x_top_of_stack)
+#define mode_mem_attrs \
+ (this_target_rtl->x_mode_mem_attrs)
+
+/* All references to certain hard regs, except those created
+ by allocating pseudo regs into them (when that's possible),
+ go through these unique rtx objects. */
+#define stack_pointer_rtx (global_rtl[GR_STACK_POINTER])
+#define frame_pointer_rtx (global_rtl[GR_FRAME_POINTER])
+#define hard_frame_pointer_rtx (global_rtl[GR_HARD_FRAME_POINTER])
+#define arg_pointer_rtx (global_rtl[GR_ARG_POINTER])
+
+#ifndef GENERATOR_FILE
+/* Return the attributes of a MEM rtx. */
+static inline const class mem_attrs *
+get_mem_attrs (const_rtx x)
+{
+ class mem_attrs *attrs;
+
+ attrs = MEM_ATTRS (x);
+ if (!attrs)
+ attrs = mode_mem_attrs[(int) GET_MODE (x)];
+ return attrs;
+}
+#endif
+
+/* Include the RTL generation functions. */
+
+#ifndef GENERATOR_FILE
+#include "genrtl.h"
+#undef gen_rtx_ASM_INPUT
+#define gen_rtx_ASM_INPUT(MODE, ARG0) \
+ gen_rtx_fmt_si (ASM_INPUT, (MODE), (ARG0), 0)
+#define gen_rtx_ASM_INPUT_loc(MODE, ARG0, LOC) \
+ gen_rtx_fmt_si (ASM_INPUT, (MODE), (ARG0), (LOC))
+#endif
+
+/* There are some RTL codes that require special attention; the
+ generation functions included above do the raw handling. If you
+ add to this list, modify special_rtx in gengenrtl.cc as well. */
+
+extern rtx_expr_list *gen_rtx_EXPR_LIST (machine_mode, rtx, rtx);
+extern rtx_insn_list *gen_rtx_INSN_LIST (machine_mode, rtx, rtx);
+extern rtx_insn *
+gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
+ basic_block bb, rtx pattern, int location, int code,
+ rtx reg_notes);
+extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
+extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
+extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
+extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
+extern rtx gen_raw_REG (machine_mode, unsigned int);
+#define alloca_raw_REG(mode, regno) \
+ init_raw_REG (rtx_alloca (REG), (mode), (regno))
+extern rtx gen_rtx_REG (machine_mode, unsigned int);
+extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
+extern rtx gen_rtx_MEM (machine_mode, rtx);
+extern rtx gen_rtx_VAR_LOCATION (machine_mode, tree, rtx,
+ enum var_init_status);
+
+#ifdef GENERATOR_FILE
+#define PUT_MODE(RTX, MODE) PUT_MODE_RAW (RTX, MODE)
+#else
+static inline void
+PUT_MODE (rtx x, machine_mode mode)
+{
+ if (REG_P (x))
+ set_mode_and_regno (x, mode, REGNO (x));
+ else
+ PUT_MODE_RAW (x, mode);
+}
+#endif
+
+#define GEN_INT(N) gen_rtx_CONST_INT (VOIDmode, (N))
+
+/* Virtual registers are used during RTL generation to refer to locations into
+ the stack frame when the actual location isn't known until RTL generation
+ is complete. The routine instantiate_virtual_regs replaces these with
+ the proper value, which is normally {frame,arg,stack}_pointer_rtx plus
+ a constant. */
+
+#define FIRST_VIRTUAL_REGISTER (FIRST_PSEUDO_REGISTER)
+
+/* This points to the first word of the incoming arguments passed on the stack,
+ either by the caller or by the callee when pretending it was passed by the
+ caller. */
+
+#define virtual_incoming_args_rtx (global_rtl[GR_VIRTUAL_INCOMING_ARGS])
+
+#define VIRTUAL_INCOMING_ARGS_REGNUM (FIRST_VIRTUAL_REGISTER)
+
+/* If FRAME_GROWS_DOWNWARD, this points to immediately above the first
+ variable on the stack. Otherwise, it points to the first variable on
+ the stack. */
+
+#define virtual_stack_vars_rtx (global_rtl[GR_VIRTUAL_STACK_ARGS])
+
+#define VIRTUAL_STACK_VARS_REGNUM ((FIRST_VIRTUAL_REGISTER) + 1)
+
+/* This points to the location of dynamically-allocated memory on the stack
+ immediately after the stack pointer has been adjusted by the amount
+ desired. */
+
+#define virtual_stack_dynamic_rtx (global_rtl[GR_VIRTUAL_STACK_DYNAMIC])
+
+#define VIRTUAL_STACK_DYNAMIC_REGNUM ((FIRST_VIRTUAL_REGISTER) + 2)
+
+/* This points to the location in the stack at which outgoing arguments should
+ be written when the stack is pre-pushed (arguments pushed using push
+ insns always use sp). */
+
+#define virtual_outgoing_args_rtx (global_rtl[GR_VIRTUAL_OUTGOING_ARGS])
+
+#define VIRTUAL_OUTGOING_ARGS_REGNUM ((FIRST_VIRTUAL_REGISTER) + 3)
+
+/* This points to the Canonical Frame Address of the function. This
+ should correspond to the CFA produced by INCOMING_FRAME_SP_OFFSET,
+ but is calculated relative to the arg pointer for simplicity; the
+ frame pointer nor stack pointer are necessarily fixed relative to
+ the CFA until after reload. */
+
+#define virtual_cfa_rtx (global_rtl[GR_VIRTUAL_CFA])
+
+#define VIRTUAL_CFA_REGNUM ((FIRST_VIRTUAL_REGISTER) + 4)
+
+#define LAST_VIRTUAL_POINTER_REGISTER ((FIRST_VIRTUAL_REGISTER) + 4)
+
+/* This is replaced by crtl->preferred_stack_boundary / BITS_PER_UNIT
+ when finalized. */
+
+#define virtual_preferred_stack_boundary_rtx \
+ (global_rtl[GR_VIRTUAL_PREFERRED_STACK_BOUNDARY])
+
+#define VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM \
+ ((FIRST_VIRTUAL_REGISTER) + 5)
+
+#define LAST_VIRTUAL_REGISTER ((FIRST_VIRTUAL_REGISTER) + 5)
+
+/* Nonzero if REGNUM is a pointer into the stack frame. */
+#define REGNO_PTR_FRAME_P(REGNUM) \
+ ((REGNUM) == STACK_POINTER_REGNUM \
+ || (REGNUM) == FRAME_POINTER_REGNUM \
+ || (REGNUM) == HARD_FRAME_POINTER_REGNUM \
+ || (REGNUM) == ARG_POINTER_REGNUM \
+ || ((REGNUM) >= FIRST_VIRTUAL_REGISTER \
+ && (REGNUM) <= LAST_VIRTUAL_POINTER_REGISTER))
+
+/* REGNUM never really appearing in the INSN stream. */
+#define INVALID_REGNUM (~(unsigned int) 0)
+
+/* REGNUM for which no debug information can be generated. */
+#define IGNORED_DWARF_REGNUM (INVALID_REGNUM - 1)
+
+extern rtx output_constant_def (tree, int);
+extern rtx lookup_constant_def (tree);
+
+/* Nonzero after end of reload pass.
+ Set to 1 or 0 by reload1.cc. */
+
+extern int reload_completed;
+
+/* Nonzero after thread_prologue_and_epilogue_insns has run. */
+extern int epilogue_completed;
+
+/* Set to 1 while reload_as_needed is operating.
+ Required by some machines to handle any generated moves differently. */
+
+extern int reload_in_progress;
+
+/* Set to 1 while in lra. */
+extern int lra_in_progress;
+
+/* This macro indicates whether you may create a new
+ pseudo-register. */
+
+#define can_create_pseudo_p() (!reload_in_progress && !reload_completed)
+
+#ifdef STACK_REGS
+/* Nonzero after end of regstack pass.
+ Set to 1 or 0 by reg-stack.cc. */
+extern int regstack_completed;
+#endif
+
+/* If this is nonzero, we do not bother generating VOLATILE
+ around volatile memory references, and we are willing to
+ output indirect addresses. If cse is to follow, we reject
+ indirect addresses so a useful potential cse is generated;
+ if it is used only once, instruction combination will produce
+ the same indirect address eventually. */
+extern int cse_not_expected;
+
+/* Translates rtx code to tree code, for those codes needed by
+ real_arithmetic. The function returns an int because the caller may not
+ know what `enum tree_code' means. */
+
+extern int rtx_to_tree_code (enum rtx_code);
+
+/* In cse.cc */
+extern int delete_trivially_dead_insns (rtx_insn *, int);
+extern int exp_equiv_p (const_rtx, const_rtx, int, bool);
+extern unsigned hash_rtx (const_rtx x, machine_mode, int *, int *, bool);
+
+/* In dse.cc */
+extern bool check_for_inc_dec (rtx_insn *insn);
+
+/* In jump.cc */
+extern int comparison_dominates_p (enum rtx_code, enum rtx_code);
+extern bool jump_to_label_p (const rtx_insn *);
+extern int condjump_p (const rtx_insn *);
+extern int any_condjump_p (const rtx_insn *);
+extern int any_uncondjump_p (const rtx_insn *);
+extern rtx pc_set (const rtx_insn *);
+extern rtx condjump_label (const rtx_insn *);
+extern int simplejump_p (const rtx_insn *);
+extern int returnjump_p (const rtx_insn *);
+extern int eh_returnjump_p (rtx_insn *);
+extern int onlyjump_p (const rtx_insn *);
+extern int invert_jump_1 (rtx_jump_insn *, rtx);
+extern int invert_jump (rtx_jump_insn *, rtx, int);
+extern int rtx_renumbered_equal_p (const_rtx, const_rtx);
+extern int true_regnum (const_rtx);
+extern unsigned int reg_or_subregno (const_rtx);
+extern int redirect_jump_1 (rtx_insn *, rtx);
+extern void redirect_jump_2 (rtx_jump_insn *, rtx, rtx, int, int);
+extern int redirect_jump (rtx_jump_insn *, rtx, int);
+extern void rebuild_jump_labels (rtx_insn *);
+extern void rebuild_jump_labels_chain (rtx_insn *);
+extern rtx reversed_comparison (const_rtx, machine_mode);
+extern enum rtx_code reversed_comparison_code (const_rtx, const rtx_insn *);
+extern enum rtx_code reversed_comparison_code_parts (enum rtx_code, const_rtx,
+ const_rtx, const rtx_insn *);
+extern void delete_for_peephole (rtx_insn *, rtx_insn *);
+extern int condjump_in_parallel_p (const rtx_insn *);
+
+/* In emit-rtl.cc. */
+extern int max_reg_num (void);
+extern int max_label_num (void);
+extern int get_first_label_num (void);
+extern void maybe_set_first_label_num (rtx_code_label *);
+extern void delete_insns_since (rtx_insn *);
+extern void mark_reg_pointer (rtx, int);
+extern void mark_user_reg (rtx);
+extern void reset_used_flags (rtx);
+extern void set_used_flags (rtx);
+extern void reorder_insns (rtx_insn *, rtx_insn *, rtx_insn *);
+extern void reorder_insns_nobb (rtx_insn *, rtx_insn *, rtx_insn *);
+extern int get_max_insn_count (void);
+extern int in_sequence_p (void);
+extern void init_emit (void);
+extern void init_emit_regs (void);
+extern void init_derived_machine_modes (void);
+extern void init_emit_once (void);
+extern void push_topmost_sequence (void);
+extern void pop_topmost_sequence (void);
+extern void set_new_first_and_last_insn (rtx_insn *, rtx_insn *);
+extern unsigned int unshare_all_rtl (void);
+extern void unshare_all_rtl_again (rtx_insn *);
+extern void unshare_all_rtl_in_chain (rtx_insn *);
+extern void verify_rtl_sharing (void);
+extern void add_insn (rtx_insn *);
+extern void add_insn_before (rtx_insn *, rtx_insn *, basic_block);
+extern void add_insn_after (rtx_insn *, rtx_insn *, basic_block);
+extern void remove_insn (rtx_insn *);
+extern rtx_insn *emit (rtx, bool = true);
+extern void emit_insn_at_entry (rtx);
+extern rtx gen_lowpart_SUBREG (machine_mode, rtx);
+extern rtx gen_const_mem (machine_mode, rtx);
+extern rtx gen_frame_mem (machine_mode, rtx);
+extern rtx gen_tmp_stack_mem (machine_mode, rtx);
+extern bool validate_subreg (machine_mode, machine_mode,
+ const_rtx, poly_uint64);
+
+/* In combine.cc */
+extern unsigned int extended_count (const_rtx, machine_mode, int);
+extern rtx remove_death (unsigned int, rtx_insn *);
+extern void dump_combine_stats (FILE *);
+extern void dump_combine_total_stats (FILE *);
+extern rtx make_compound_operation (rtx, enum rtx_code);
+
+/* In sched-rgn.cc. */
+extern void schedule_insns (void);
+
+/* In sched-ebb.cc. */
+extern void schedule_ebbs (void);
+
+/* In sel-sched-dump.cc. */
+extern void sel_sched_fix_param (const char *param, const char *val);
+
+/* In print-rtl.cc */
+extern const char *print_rtx_head;
+extern void debug (const rtx_def &ref);
+extern void debug (const rtx_def *ptr);
+extern void debug_rtx (const_rtx);
+extern void debug_rtx_list (const rtx_insn *, int);
+extern void debug_rtx_range (const rtx_insn *, const rtx_insn *);
+extern const rtx_insn *debug_rtx_find (const rtx_insn *, int);
+extern void print_mem_expr (FILE *, const_tree);
+extern void print_rtl (FILE *, const_rtx);
+extern void print_simple_rtl (FILE *, const_rtx);
+extern int print_rtl_single (FILE *, const_rtx);
+extern int print_rtl_single_with_indent (FILE *, const_rtx, int);
+extern void print_inline_rtx (FILE *, const_rtx, int);
+
+/* In stmt.cc */
+extern void expand_null_return (void);
+extern void expand_naked_return (void);
+extern void emit_jump (rtx);
+
+/* Memory operation built-ins differ by return value. Mapping
+ of the enum values is following:
+ - RETURN_BEGIN - return destination, e.g. memcpy
+ - RETURN_END - return destination + n, e.g. mempcpy
+ - RETURN_END_MINUS_ONE - return a pointer to the terminating
+ null byte of the string, e.g. strcpy
+*/
+
+enum memop_ret
+{
+ RETURN_BEGIN,
+ RETURN_END,
+ RETURN_END_MINUS_ONE
+};
+
+/* In expr.cc */
+extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
+ unsigned int, memop_ret);
+extern poly_int64 find_args_size_adjust (rtx_insn *);
+extern poly_int64 fixup_args_size_notes (rtx_insn *, rtx_insn *, poly_int64);
+
+/* In expmed.cc */
+extern void init_expmed (void);
+extern void expand_inc (rtx, rtx);
+extern void expand_dec (rtx, rtx);
+
+/* In lower-subreg.cc */
+extern void init_lower_subreg (void);
+
+/* In gcse.cc */
+extern bool can_copy_p (machine_mode);
+extern bool can_assign_to_reg_without_clobbers_p (rtx, machine_mode);
+extern rtx_insn *prepare_copy_insn (rtx, rtx);
+
+/* In cprop.cc */
+extern rtx fis_get_condition (rtx_insn *);
+
+/* In ira.cc */
+extern HARD_REG_SET eliminable_regset;
+extern void mark_elimination (int, int);
+
+/* In reginfo.cc */
+extern int reg_classes_intersect_p (reg_class_t, reg_class_t);
+extern int reg_class_subset_p (reg_class_t, reg_class_t);
+extern void globalize_reg (tree, int);
+extern void init_reg_modes_target (void);
+extern void init_regs (void);
+extern void reinit_regs (void);
+extern void init_fake_stack_mems (void);
+extern void save_register_info (void);
+extern void init_reg_sets (void);
+extern void regclass (rtx, int);
+extern void reg_scan (rtx_insn *, unsigned int);
+extern void fix_register (const char *, int, int);
+extern const HARD_REG_SET *valid_mode_changes_for_regno (unsigned int);
+
+/* In reload1.cc */
+extern int function_invariant_p (const_rtx);
+
+/* In calls.cc */
+enum libcall_type
+{
+ LCT_NORMAL = 0,
+ LCT_CONST = 1,
+ LCT_PURE = 2,
+ LCT_NORETURN = 3,
+ LCT_THROW = 4,
+ LCT_RETURNS_TWICE = 5
+};
+
+extern rtx emit_library_call_value_1 (int, rtx, rtx, enum libcall_type,
+ machine_mode, int, rtx_mode_t *);
+
+/* Output a library call and discard the returned value. FUN is the
+ address of the function, as a SYMBOL_REF rtx, and OUTMODE is the mode
+ of the (discarded) return value. FN_TYPE is LCT_NORMAL for `normal'
+ calls, LCT_CONST for `const' calls, LCT_PURE for `pure' calls, or
+ another LCT_ value for other types of library calls.
+
+ There are different overloads of this function for different numbers
+ of arguments. In each case the argument value is followed by its mode. */
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode)
+{
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 0, NULL);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode)
+{
+ rtx_mode_t args[] = { rtx_mode_t (arg1, arg1_mode) };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 1, args);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode)
+ };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 2, args);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode)
+ };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 3, args);
+}
+
+inline void
+emit_library_call (rtx fun, libcall_type fn_type, machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode,
+ rtx arg4, machine_mode arg4_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode),
+ rtx_mode_t (arg4, arg4_mode)
+ };
+ emit_library_call_value_1 (0, fun, NULL_RTX, fn_type, outmode, 4, args);
+}
+
+/* Like emit_library_call, but return the value produced by the call.
+ Use VALUE to store the result if it is nonnull, otherwise pick a
+ convenient location. */
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode)
+{
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 0, NULL);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode)
+{
+ rtx_mode_t args[] = { rtx_mode_t (arg1, arg1_mode) };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 1, args);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode)
+ };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 2, args);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode)
+ };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 3, args);
+}
+
+inline rtx
+emit_library_call_value (rtx fun, rtx value, libcall_type fn_type,
+ machine_mode outmode,
+ rtx arg1, machine_mode arg1_mode,
+ rtx arg2, machine_mode arg2_mode,
+ rtx arg3, machine_mode arg3_mode,
+ rtx arg4, machine_mode arg4_mode)
+{
+ rtx_mode_t args[] = {
+ rtx_mode_t (arg1, arg1_mode),
+ rtx_mode_t (arg2, arg2_mode),
+ rtx_mode_t (arg3, arg3_mode),
+ rtx_mode_t (arg4, arg4_mode)
+ };
+ return emit_library_call_value_1 (1, fun, value, fn_type, outmode, 4, args);
+}
+
+/* In varasm.cc */
+extern void init_varasm_once (void);
+
+extern rtx make_debug_expr_from_rtl (const_rtx);
+
+/* In read-rtl.cc */
+#ifdef GENERATOR_FILE
+extern bool read_rtx (const char *, vec<rtx> *);
+#endif
+
+/* In alias.cc */
+extern rtx canon_rtx (rtx);
+extern int true_dependence (const_rtx, machine_mode, const_rtx);
+extern rtx get_addr (rtx);
+extern int canon_true_dependence (const_rtx, machine_mode, rtx,
+ const_rtx, rtx);
+extern int read_dependence (const_rtx, const_rtx);
+extern int anti_dependence (const_rtx, const_rtx);
+extern int canon_anti_dependence (const_rtx, bool,
+ const_rtx, machine_mode, rtx);
+extern int output_dependence (const_rtx, const_rtx);
+extern int canon_output_dependence (const_rtx, bool,
+ const_rtx, machine_mode, rtx);
+extern int may_alias_p (const_rtx, const_rtx);
+extern void init_alias_target (void);
+extern void init_alias_analysis (void);
+extern void end_alias_analysis (void);
+extern void vt_equate_reg_base_value (const_rtx, const_rtx);
+extern bool memory_modified_in_insn_p (const_rtx, const_rtx);
+extern bool may_be_sp_based_p (rtx);
+extern rtx gen_hard_reg_clobber (machine_mode, unsigned int);
+extern rtx get_reg_known_value (unsigned int);
+extern bool get_reg_known_equiv_p (unsigned int);
+extern rtx get_reg_base_value (unsigned int);
+extern rtx extract_mem_from_operand (rtx);
+
+#ifdef STACK_REGS
+extern int stack_regs_mentioned (const_rtx insn);
+#endif
+
+/* In toplev.cc */
+extern GTY(()) rtx stack_limit_rtx;
+
+/* In var-tracking.cc */
+extern unsigned int variable_tracking_main (void);
+extern void delete_vta_debug_insns (bool);
+
+/* In stor-layout.cc. */
+extern void get_mode_bounds (scalar_int_mode, int,
+ scalar_int_mode, rtx *, rtx *);
+
+/* In loop-iv.cc */
+extern rtx canon_condition (rtx);
+extern void simplify_using_condition (rtx, rtx *, bitmap);
+
+/* In final.cc */
+extern unsigned int compute_alignments (void);
+extern void update_alignments (vec<rtx> &);
+extern int asm_str_count (const char *templ);
+
+struct rtl_hooks
+{
+ rtx (*gen_lowpart) (machine_mode, rtx);
+ rtx (*gen_lowpart_no_emit) (machine_mode, rtx);
+ rtx (*reg_nonzero_bits) (const_rtx, scalar_int_mode, scalar_int_mode,
+ unsigned HOST_WIDE_INT *);
+ rtx (*reg_num_sign_bit_copies) (const_rtx, scalar_int_mode, scalar_int_mode,
+ unsigned int *);
+ bool (*reg_truncated_to_mode) (machine_mode, const_rtx);
+
+ /* Whenever you add entries here, make sure you adjust rtlhooks-def.h. */
+};
+
+/* Each pass can provide its own. */
+extern struct rtl_hooks rtl_hooks;
+
+/* ... but then it has to restore these. */
+extern const struct rtl_hooks general_rtl_hooks;
+
+/* Keep this for the nonce. */
+#define gen_lowpart rtl_hooks.gen_lowpart
+
+extern void insn_locations_init (void);
+extern void insn_locations_finalize (void);
+extern void set_curr_insn_location (location_t);
+extern location_t curr_insn_location (void);
+extern void set_insn_locations (rtx_insn *, location_t);
+
+/* rtl-error.cc */
+extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void _fatal_insn (const char *, const_rtx, const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+
+#define fatal_insn(msgid, insn) \
+ _fatal_insn (msgid, insn, __FILE__, __LINE__, __FUNCTION__)
+#define fatal_insn_not_found(insn) \
+ _fatal_insn_not_found (insn, __FILE__, __LINE__, __FUNCTION__)
+
+/* reginfo.cc */
+extern tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER];
+
+/* Information about the function that is propagated by the RTL backend.
+ Available only for functions that has been already assembled. */
+
+struct GTY(()) cgraph_rtl_info {
+ unsigned int preferred_incoming_stack_boundary;
+
+ /* Which registers the function clobbers, either directly or by
+ calling another function. */
+ HARD_REG_SET function_used_regs;
+};
+
+/* If loads from memories of mode MODE always sign or zero extend,
+ return SIGN_EXTEND or ZERO_EXTEND as appropriate. Return UNKNOWN
+ otherwise. */
+
+inline rtx_code
+load_extend_op (machine_mode mode)
+{
+ scalar_int_mode int_mode;
+ if (is_a <scalar_int_mode> (mode, &int_mode)
+ && GET_MODE_PRECISION (int_mode) < BITS_PER_WORD)
+ return LOAD_EXTEND_OP (int_mode);
+ return UNKNOWN;
+}
+
+/* If X is a PLUS of a base and a constant offset, add the constant to *OFFSET
+ and return the base. Return X otherwise. */
+
+inline rtx
+strip_offset_and_add (rtx x, poly_int64_pod *offset)
+{
+ if (GET_CODE (x) == PLUS)
+ {
+ poly_int64 suboffset;
+ x = strip_offset (x, &suboffset);
+ *offset = poly_uint64 (*offset) + suboffset;
+ }
+ return x;
+}
+
+/* Return true if X is an operation that always operates on the full
+ registers for WORD_REGISTER_OPERATIONS architectures. */
+
+inline bool
+word_register_operation_p (const_rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ case ROTATE:
+ case ROTATERT:
+ case SIGN_EXTRACT:
+ case ZERO_EXTRACT:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+/* Holds an rtx comparison to simplify passing many parameters pertaining to a
+ single comparison. */
+
+struct rtx_comparison {
+ rtx_code code;
+ rtx op0, op1;
+ machine_mode mode;
+};
+
+/* gtype-desc.cc. */
+extern void gt_ggc_mx (rtx &);
+extern void gt_pch_nx (rtx &);
+extern void gt_pch_nx (rtx &, gt_pointer_operator, void *);
+
+#endif /* ! GCC_RTL_H */
diff --git a/support/cpp/gcc/sanitizer.def b/support/cpp/gcc/sanitizer.def
new file mode 100644
index 000000000..4c71858d5
--- /dev/null
+++ b/support/cpp/gcc/sanitizer.def
@@ -0,0 +1,669 @@
+/* This file contains the definitions and documentation for the
+ Address Sanitizer and Thread Sanitizer builtins used in the GNU compiler.
+ 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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_BUILTIN_STUB(ENUM, NAME)
+ DEF_SANITIZER_BUILTIN (ENUM, NAME, TYPE, ATTRS)
+
+ See builtins.def for details.
+ The builtins are created by the C-family of FEs in c-family/c-common.cc,
+ for other FEs by asan.cc. */
+
+/* This has to come before all the sanitizer builtins. */
+DEF_BUILTIN_STUB(BEGIN_SANITIZER_BUILTINS, (const char *)0)
+
+/* Address Sanitizer */
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_VERSION_MISMATCH_CHECK,
+ "__asan_version_mismatch_check_v8",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+/* Do not reorder the BUILT_IN_ASAN_{REPORT,CHECK}* builtins, e.g. cfgcleanup.cc
+ relies on this order. */
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2, "__asan_report_load2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4, "__asan_report_load4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD_N, "__asan_report_load_n",
+ BT_FN_VOID_PTR_PTRMODE,
+ ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4, "__asan_report_store4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n",
+ BT_FN_VOID_PTR_PTRMODE,
+ ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1_NOABORT,
+ "__asan_report_load1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD2_NOABORT,
+ "__asan_report_load2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD4_NOABORT,
+ "__asan_report_load4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8_NOABORT,
+ "__asan_report_load8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16_NOABORT,
+ "__asan_report_load16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD_N_NOABORT,
+ "__asan_report_load_n_noabort",
+ BT_FN_VOID_PTR_PTRMODE,
+ ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1_NOABORT,
+ "__asan_report_store1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2_NOABORT,
+ "__asan_report_store2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE4_NOABORT,
+ "__asan_report_store4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8_NOABORT,
+ "__asan_report_store8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16_NOABORT,
+ "__asan_report_store16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N_NOABORT,
+ "__asan_report_store_n_noabort",
+ BT_FN_VOID_PTR_PTRMODE,
+ ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD4, "__asan_load4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD8, "__asan_load8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD16, "__asan_load16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOADN, "__asan_loadN",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE1, "__asan_store1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE2, "__asan_store2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE4, "__asan_store4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE8, "__asan_store8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE16, "__asan_store16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STOREN, "__asan_storeN",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1_NOABORT, "__asan_load1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2_NOABORT, "__asan_load2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD4_NOABORT, "__asan_load4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD8_NOABORT, "__asan_load8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD16_NOABORT, "__asan_load16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOADN_NOABORT, "__asan_loadN_noabort",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE1_NOABORT, "__asan_store1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE2_NOABORT, "__asan_store2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE4_NOABORT, "__asan_store4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE8_NOABORT, "__asan_store8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE16_NOABORT, "__asan_store16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STOREN_NOABORT, "__asan_storeN_noabort",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS,
+ "__asan_register_globals",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNREGISTER_GLOBALS,
+ "__asan_unregister_globals",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_HANDLE_NO_RETURN,
+ "__asan_handle_no_return",
+ BT_FN_VOID, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT,
+ "__asan_before_dynamic_init",
+ BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_AFTER_DYNAMIC_INIT,
+ "__asan_after_dynamic_init",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_POISON_STACK_MEMORY,
+ "__asan_poison_stack_memory",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNPOISON_STACK_MEMORY,
+ "__asan_unpoison_stack_memory",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_ALLOCA_POISON, "__asan_alloca_poison",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_ALLOCAS_UNPOISON, "__asan_allocas_unpoison",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_POINTER_COMPARE, "__sanitizer_ptr_cmp",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_POINTER_SUBTRACT, "__sanitizer_ptr_sub",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+
+/* Hardware Address Sanitizer. */
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_INIT, "__hwasan_init",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD1, "__hwasan_load1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD2, "__hwasan_load2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD4, "__hwasan_load4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD8, "__hwasan_load8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD16, "__hwasan_load16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOADN, "__hwasan_loadN",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE1, "__hwasan_store1",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE2, "__hwasan_store2",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE4, "__hwasan_store4",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE8, "__hwasan_store8",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE16, "__hwasan_store16",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STOREN, "__hwasan_storeN",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD1_NOABORT, "__hwasan_load1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD2_NOABORT, "__hwasan_load2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD4_NOABORT, "__hwasan_load4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD8_NOABORT, "__hwasan_load8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOAD16_NOABORT, "__hwasan_load16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_LOADN_NOABORT, "__hwasan_loadN_noabort",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE1_NOABORT, "__hwasan_store1_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE2_NOABORT, "__hwasan_store2_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE4_NOABORT, "__hwasan_store4_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE8_NOABORT, "__hwasan_store8_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STORE16_NOABORT,
+ "__hwasan_store16_noabort",
+ BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_STOREN_NOABORT, "__hwasan_storeN_noabort",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_TAG_MISMATCH4, "__hwasan_tag_mismatch4",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_HANDLE_LONGJMP, "__hwasan_handle_longjmp",
+ BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_TAG_PTR, "__hwasan_tag_pointer",
+ BT_FN_PTR_CONST_PTR_UINT8, ATTR_TMPURE_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_HWASAN_TAG_MEM, "__hwasan_tag_memory",
+ BT_FN_VOID_PTR_UINT8_PTRMODE, ATTR_NOTHROW_LIST)
+
+/* Thread Sanitizer */
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_FUNC_ENTRY, "__tsan_func_entry",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_FUNC_EXIT, "__tsan_func_exit",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VPTR_UPDATE, "__tsan_vptr_update",
+ BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ1, "__tsan_read1",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ2, "__tsan_read2",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ4, "__tsan_read4",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ8, "__tsan_read8",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ16, "__tsan_read16",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE1, "__tsan_write1",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE2, "__tsan_write2",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE4, "__tsan_write4",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE8, "__tsan_write8",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE16, "__tsan_write16",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_READ_RANGE, "__tsan_read_range",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_RANGE, "__tsan_write_range",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_READ1, "__tsan_volatile_read1",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_READ2, "__tsan_volatile_read2",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_READ4, "__tsan_volatile_read4",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_READ8, "__tsan_volatile_read8",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_READ16, "__tsan_volatile_read16",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_WRITE1, "__tsan_volatile_write1",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_WRITE2, "__tsan_volatile_write2",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_WRITE4, "__tsan_volatile_write4",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_WRITE8, "__tsan_volatile_write8",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_VOLATILE_WRITE16, "__tsan_volatile_write16",
+ BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_LOAD,
+ "__tsan_atomic8_load",
+ BT_FN_I1_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_LOAD,
+ "__tsan_atomic16_load",
+ BT_FN_I2_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_LOAD,
+ "__tsan_atomic32_load",
+ BT_FN_I4_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_LOAD,
+ "__tsan_atomic64_load",
+ BT_FN_I8_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_LOAD,
+ "__tsan_atomic128_load",
+ BT_FN_I16_CONST_VPTR_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_STORE,
+ "__tsan_atomic8_store",
+ BT_FN_VOID_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_STORE,
+ "__tsan_atomic16_store",
+ BT_FN_VOID_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_STORE,
+ "__tsan_atomic32_store",
+ BT_FN_VOID_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_STORE,
+ "__tsan_atomic64_store",
+ BT_FN_VOID_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_STORE,
+ "__tsan_atomic128_store",
+ BT_FN_VOID_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_EXCHANGE,
+ "__tsan_atomic8_exchange",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_EXCHANGE,
+ "__tsan_atomic16_exchange",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_EXCHANGE,
+ "__tsan_atomic32_exchange",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_EXCHANGE,
+ "__tsan_atomic64_exchange",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_EXCHANGE,
+ "__tsan_atomic128_exchange",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_FETCH_ADD,
+ "__tsan_atomic8_fetch_add",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_FETCH_ADD,
+ "__tsan_atomic16_fetch_add",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_FETCH_ADD,
+ "__tsan_atomic32_fetch_add",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_FETCH_ADD,
+ "__tsan_atomic64_fetch_add",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_FETCH_ADD,
+ "__tsan_atomic128_fetch_add",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_FETCH_SUB,
+ "__tsan_atomic8_fetch_sub",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_FETCH_SUB,
+ "__tsan_atomic16_fetch_sub",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_FETCH_SUB,
+ "__tsan_atomic32_fetch_sub",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_FETCH_SUB,
+ "__tsan_atomic64_fetch_sub",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_FETCH_SUB,
+ "__tsan_atomic128_fetch_sub",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_FETCH_AND,
+ "__tsan_atomic8_fetch_and",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_FETCH_AND,
+ "__tsan_atomic16_fetch_and",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_FETCH_AND,
+ "__tsan_atomic32_fetch_and",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_FETCH_AND,
+ "__tsan_atomic64_fetch_and",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_FETCH_AND,
+ "__tsan_atomic128_fetch_and",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_FETCH_OR,
+ "__tsan_atomic8_fetch_or",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_FETCH_OR,
+ "__tsan_atomic16_fetch_or",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_FETCH_OR,
+ "__tsan_atomic32_fetch_or",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_FETCH_OR,
+ "__tsan_atomic64_fetch_or",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_FETCH_OR,
+ "__tsan_atomic128_fetch_or",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_FETCH_XOR,
+ "__tsan_atomic8_fetch_xor",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_FETCH_XOR,
+ "__tsan_atomic16_fetch_xor",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_FETCH_XOR,
+ "__tsan_atomic32_fetch_xor",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_FETCH_XOR,
+ "__tsan_atomic64_fetch_xor",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_FETCH_XOR,
+ "__tsan_atomic128_fetch_xor",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_FETCH_NAND,
+ "__tsan_atomic8_fetch_nand",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_FETCH_NAND,
+ "__tsan_atomic16_fetch_nand",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_FETCH_NAND,
+ "__tsan_atomic32_fetch_nand",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_FETCH_NAND,
+ "__tsan_atomic64_fetch_nand",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_FETCH_NAND,
+ "__tsan_atomic128_fetch_nand",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_COMPARE_EXCHANGE_STRONG,
+ "__tsan_atomic8_compare_exchange_strong",
+ BT_FN_BOOL_VPTR_PTR_I1_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_COMPARE_EXCHANGE_STRONG,
+ "__tsan_atomic16_compare_exchange_strong",
+ BT_FN_BOOL_VPTR_PTR_I2_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_COMPARE_EXCHANGE_STRONG,
+ "__tsan_atomic32_compare_exchange_strong",
+ BT_FN_BOOL_VPTR_PTR_I4_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_COMPARE_EXCHANGE_STRONG,
+ "__tsan_atomic64_compare_exchange_strong",
+ BT_FN_BOOL_VPTR_PTR_I8_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_COMPARE_EXCHANGE_STRONG,
+ "__tsan_atomic128_compare_exchange_strong",
+ BT_FN_BOOL_VPTR_PTR_I16_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC8_COMPARE_EXCHANGE_WEAK,
+ "__tsan_atomic8_compare_exchange_weak",
+ BT_FN_BOOL_VPTR_PTR_I1_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC16_COMPARE_EXCHANGE_WEAK,
+ "__tsan_atomic16_compare_exchange_weak",
+ BT_FN_BOOL_VPTR_PTR_I2_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC32_COMPARE_EXCHANGE_WEAK,
+ "__tsan_atomic32_compare_exchange_weak",
+ BT_FN_BOOL_VPTR_PTR_I4_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC64_COMPARE_EXCHANGE_WEAK,
+ "__tsan_atomic64_compare_exchange_weak",
+ BT_FN_BOOL_VPTR_PTR_I8_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC128_COMPARE_EXCHANGE_WEAK,
+ "__tsan_atomic128_compare_exchange_weak",
+ BT_FN_BOOL_VPTR_PTR_I16_INT_INT,
+ ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC_THREAD_FENCE,
+ "__tsan_atomic_thread_fence",
+ BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_ATOMIC_SIGNAL_FENCE,
+ "__tsan_atomic_signal_fence",
+ BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+
+/* Undefined Behavior Sanitizer */
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW,
+ "__ubsan_handle_divrem_overflow",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS,
+ "__ubsan_handle_shift_out_of_bounds",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE,
+ "__ubsan_handle_builtin_unreachable",
+ BT_FN_VOID_PTR,
+ ATTR_COLD_CONST_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MISSING_RETURN,
+ "__ubsan_handle_missing_return",
+ BT_FN_VOID_PTR,
+ ATTR_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE,
+ "__ubsan_handle_vla_bound_not_positive",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1,
+ "__ubsan_handle_type_mismatch_v1",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW,
+ "__ubsan_handle_add_overflow",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW,
+ "__ubsan_handle_sub_overflow",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW,
+ "__ubsan_handle_mul_overflow",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW,
+ "__ubsan_handle_negate_overflow",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE,
+ "__ubsan_handle_load_invalid_value",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW,
+ "__ubsan_handle_pointer_overflow",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT,
+ "__ubsan_handle_divrem_overflow_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT,
+ "__ubsan_handle_shift_out_of_bounds_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE_ABORT,
+ "__ubsan_handle_vla_bound_not_positive_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT,
+ "__ubsan_handle_type_mismatch_v1_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_ADD_OVERFLOW_ABORT,
+ "__ubsan_handle_add_overflow_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_SUB_OVERFLOW_ABORT,
+ "__ubsan_handle_sub_overflow_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MUL_OVERFLOW_ABORT,
+ "__ubsan_handle_mul_overflow_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NEGATE_OVERFLOW_ABORT,
+ "__ubsan_handle_negate_overflow_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT,
+ "__ubsan_handle_load_invalid_value_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_POINTER_OVERFLOW_ABORT,
+ "__ubsan_handle_pointer_overflow_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW,
+ "__ubsan_handle_float_cast_overflow",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT,
+ "__ubsan_handle_float_cast_overflow_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS,
+ "__ubsan_handle_out_of_bounds",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT,
+ "__ubsan_handle_out_of_bounds_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_ARG,
+ "__ubsan_handle_nonnull_arg",
+ BT_FN_VOID_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT,
+ "__ubsan_handle_nonnull_arg_abort",
+ BT_FN_VOID_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1,
+ "__ubsan_handle_nonnull_return_v1",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT,
+ "__ubsan_handle_nonnull_return_v1_abort",
+ BT_FN_VOID_PTR_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN,
+ "__ubsan_handle_invalid_builtin",
+ BT_FN_VOID_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_INVALID_BUILTIN_ABORT,
+ "__ubsan_handle_invalid_builtin_abort",
+ BT_FN_VOID_PTR,
+ ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS,
+ "__ubsan_handle_dynamic_type_cache_miss",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_DYNAMIC_TYPE_CACHE_MISS_ABORT,
+ "__ubsan_handle_dynamic_type_cache_miss_abort",
+ BT_FN_VOID_PTR_PTR_PTR,
+ ATTR_COLD_NOTHROW_LEAF_LIST)
+
+/* Sanitizer coverage */
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_PC,
+ "__sanitizer_cov_trace_pc",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP1,
+ "__sanitizer_cov_trace_cmp1",
+ BT_FN_VOID_UINT8_UINT8, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP2,
+ "__sanitizer_cov_trace_cmp2",
+ BT_FN_VOID_UINT16_UINT16, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP4,
+ "__sanitizer_cov_trace_cmp4",
+ BT_FN_VOID_UINT32_UINT32, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMP8,
+ "__sanitizer_cov_trace_cmp8",
+ BT_FN_VOID_UINT64_UINT64, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP1,
+ "__sanitizer_cov_trace_const_cmp1",
+ BT_FN_VOID_UINT8_UINT8, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP2,
+ "__sanitizer_cov_trace_const_cmp2",
+ BT_FN_VOID_UINT16_UINT16, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP4,
+ "__sanitizer_cov_trace_const_cmp4",
+ BT_FN_VOID_UINT32_UINT32, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CONST_CMP8,
+ "__sanitizer_cov_trace_const_cmp8",
+ BT_FN_VOID_UINT64_UINT64, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMPF,
+ "__sanitizer_cov_trace_cmpf",
+ BT_FN_VOID_FLOAT_FLOAT, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_CMPD,
+ "__sanitizer_cov_trace_cmpd",
+ BT_FN_VOID_DOUBLE_DOUBLE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_SANITIZER_COV_TRACE_SWITCH,
+ "__sanitizer_cov_trace_switch",
+ BT_FN_VOID_UINT64_PTR, ATTR_NOTHROW_LEAF_LIST)
+
+/* This has to come after all the sanitizer builtins. */
+DEF_BUILTIN_STUB(END_SANITIZER_BUILTINS, (const char *)0)
diff --git a/support/cpp/gcc/sbitmap.cc b/support/cpp/gcc/sbitmap.cc
new file mode 100644
index 000000000..5ac2b6d0f
--- /dev/null
+++ b/support/cpp/gcc/sbitmap.cc
@@ -0,0 +1,1007 @@
+/* Simple bitmaps.
+ 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.
+
+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 "sbitmap.h"
+#include "selftest.h"
+
+typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
+typedef const SBITMAP_ELT_TYPE *const_sbitmap_ptr;
+
+/* Return the size in bytes of a bitmap MAP. */
+
+static inline unsigned int sbitmap_size_bytes (const_sbitmap map)
+{
+ return map->size * sizeof (SBITMAP_ELT_TYPE);
+}
+
+
+/* Bitmap manipulation routines. */
+
+/* Allocate a simple bitmap of N_ELMS bits. */
+
+sbitmap
+sbitmap_alloc (unsigned int n_elms)
+{
+ unsigned int bytes, size, amt;
+ sbitmap bmap;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ amt = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+ bmap = (sbitmap) xmalloc (amt);
+ bmap->n_bits = n_elms;
+ bmap->size = size;
+ return bmap;
+}
+
+/* Resize a simple bitmap BMAP to N_ELMS bits. If increasing the
+ size of BMAP, clear the new bits to zero if the DEF argument
+ is zero, and set them to one otherwise. */
+
+sbitmap
+sbitmap_resize (sbitmap bmap, unsigned int n_elms, int def)
+{
+ unsigned int bytes, size, amt;
+ unsigned int last_bit;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ if (bytes > sbitmap_size_bytes (bmap))
+ {
+ amt = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+ bmap = (sbitmap) xrealloc (bmap, amt);
+ }
+
+ if (n_elms > bmap->n_bits)
+ {
+ if (def)
+ {
+ memset (bmap->elms + bmap->size, -1,
+ bytes - sbitmap_size_bytes (bmap));
+
+ /* Set the new bits if the original last element. */
+ last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[bmap->size - 1]
+ |= ~((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
+
+ /* Clear the unused bit in the new last element. */
+ last_bit = n_elms % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[size - 1]
+ &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+ }
+ else
+ memset (bmap->elms + bmap->size, 0, bytes - sbitmap_size_bytes (bmap));
+ }
+ else if (n_elms < bmap->n_bits)
+ {
+ /* Clear the surplus bits in the last word. */
+ last_bit = n_elms % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[size - 1]
+ &= (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+ }
+
+ bmap->n_bits = n_elms;
+ bmap->size = size;
+ return bmap;
+}
+
+/* Re-allocate a simple bitmap of N_ELMS bits. New storage is uninitialized. */
+
+sbitmap
+sbitmap_realloc (sbitmap src, unsigned int n_elms)
+{
+ unsigned int bytes, size, amt;
+ sbitmap bmap;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ amt = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+
+ if (sbitmap_size_bytes (src) >= bytes)
+ {
+ src->n_bits = n_elms;
+ return src;
+ }
+
+ bmap = (sbitmap) xrealloc (src, amt);
+ bmap->n_bits = n_elms;
+ bmap->size = size;
+ return bmap;
+}
+
+/* Allocate a vector of N_VECS bitmaps of N_ELMS bits. */
+
+sbitmap *
+sbitmap_vector_alloc (unsigned int n_vecs, unsigned int n_elms)
+{
+ unsigned int i, size;
+ size_t amt, bytes, vector_bytes, elm_bytes, offset;
+ sbitmap *bitmap_vector;
+
+ size = SBITMAP_SET_SIZE (n_elms);
+ bytes = size * sizeof (SBITMAP_ELT_TYPE);
+ elm_bytes = (sizeof (struct simple_bitmap_def)
+ + bytes - sizeof (SBITMAP_ELT_TYPE));
+ vector_bytes = n_vecs * sizeof (sbitmap *);
+
+ /* Round up `vector_bytes' to account for the alignment requirements
+ of an sbitmap. One could allocate the vector-table and set of sbitmaps
+ separately, but that requires maintaining two pointers or creating
+ a cover struct to hold both pointers (so our result is still just
+ one pointer). Neither is a bad idea, but this is simpler for now. */
+ {
+ /* Based on DEFAULT_ALIGNMENT computation in obstack.c. */
+ struct { char x; SBITMAP_ELT_TYPE y; } align;
+ int alignment = (char *) & align.y - & align.x;
+ vector_bytes = (vector_bytes + alignment - 1) & ~ (alignment - 1);
+ }
+
+ amt = vector_bytes + (n_vecs * elm_bytes);
+ bitmap_vector = (sbitmap *) xmalloc (amt);
+
+ for (i = 0, offset = vector_bytes; i < n_vecs; i++, offset += elm_bytes)
+ {
+ sbitmap b = (sbitmap) ((char *) bitmap_vector + offset);
+
+ bitmap_vector[i] = b;
+ b->n_bits = n_elms;
+ b->size = size;
+ }
+
+ return bitmap_vector;
+}
+
+/* Copy sbitmap SRC to DST. */
+
+void
+bitmap_copy (sbitmap dst, const_sbitmap src)
+{
+ gcc_checking_assert (src->size <= dst->size);
+
+ memcpy (dst->elms, src->elms, sizeof (SBITMAP_ELT_TYPE) * dst->size);
+}
+
+/* Determine if a == b. */
+int
+bitmap_equal_p (const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+
+ return !memcmp (a->elms, b->elms, sizeof (SBITMAP_ELT_TYPE) * a->size);
+}
+
+/* Return true if the bitmap is empty. */
+
+bool
+bitmap_empty_p (const_sbitmap bmap)
+{
+ unsigned int i;
+ for (i=0; i<bmap->size; i++)
+ if (bmap->elms[i])
+ return false;
+
+ return true;
+}
+
+/* Clear COUNT bits from START in BMAP. */
+
+void
+bitmap_clear_range (sbitmap bmap, unsigned int start, unsigned int count)
+{
+ if (count == 0)
+ return;
+
+ bitmap_check_index (bmap, start + count - 1);
+
+ unsigned int start_word = start / SBITMAP_ELT_BITS;
+ unsigned int start_bitno = start % SBITMAP_ELT_BITS;
+
+ /* Clearing less than a full word, starting at the beginning of a word. */
+ if (start_bitno == 0 && count < SBITMAP_ELT_BITS)
+ {
+ SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
+ bmap->elms[start_word] &= ~mask;
+ return;
+ }
+
+ unsigned int end_word = (start + count) / SBITMAP_ELT_BITS;
+ unsigned int end_bitno = (start + count) % SBITMAP_ELT_BITS;
+
+ /* Clearing starts somewhere in the middle of the first word. Clear up to
+ the end of the first word or the end of the requested region, whichever
+ comes first. */
+ if (start_bitno != 0)
+ {
+ unsigned int nbits = ((start_word == end_word)
+ ? end_bitno - start_bitno
+ : SBITMAP_ELT_BITS - start_bitno);
+ SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << nbits) - 1;
+ mask <<= start_bitno;
+ bmap->elms[start_word] &= ~mask;
+ start_word++;
+ count -= nbits;
+ }
+
+ if (count == 0)
+ return;
+
+ /* Now clear words at a time until we hit a partial word. */
+ unsigned int nwords = (end_word - start_word);
+ if (nwords)
+ {
+ memset (&bmap->elms[start_word], 0, nwords * sizeof (SBITMAP_ELT_TYPE));
+ count -= nwords * sizeof (SBITMAP_ELT_TYPE) * BITS_PER_UNIT;
+ start_word += nwords;
+ }
+
+ if (count == 0)
+ return;
+
+ /* Now handle residuals in the last word. */
+ SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
+ bmap->elms[start_word] &= ~mask;
+}
+
+/* Set COUNT bits from START in BMAP. */
+void
+bitmap_set_range (sbitmap bmap, unsigned int start, unsigned int count)
+{
+ if (count == 0)
+ return;
+
+ bitmap_check_index (bmap, start + count - 1);
+
+ unsigned int start_word = start / SBITMAP_ELT_BITS;
+ unsigned int start_bitno = start % SBITMAP_ELT_BITS;
+
+ /* Setting less than a full word, starting at the beginning of a word. */
+ if (start_bitno == 0 && count < SBITMAP_ELT_BITS)
+ {
+ SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
+ bmap->elms[start_word] |= mask;
+ return;
+ }
+
+ unsigned int end_word = (start + count) / SBITMAP_ELT_BITS;
+ unsigned int end_bitno = (start + count) % SBITMAP_ELT_BITS;
+
+ /* Setting starts somewhere in the middle of the first word. Set up to
+ the end of the first word or the end of the requested region, whichever
+ comes first. */
+ if (start_bitno != 0)
+ {
+ unsigned int nbits = ((start_word == end_word)
+ ? end_bitno - start_bitno
+ : SBITMAP_ELT_BITS - start_bitno);
+ SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << nbits) - 1;
+ mask <<= start_bitno;
+ bmap->elms[start_word] |= mask;
+ start_word++;
+ count -= nbits;
+ }
+
+ if (count == 0)
+ return;
+
+ /* Now set words at a time until we hit a partial word. */
+ unsigned int nwords = (end_word - start_word);
+ if (nwords)
+ {
+ memset (&bmap->elms[start_word], 0xff,
+ nwords * sizeof (SBITMAP_ELT_TYPE));
+ count -= nwords * sizeof (SBITMAP_ELT_TYPE) * BITS_PER_UNIT;
+ start_word += nwords;
+ }
+
+ if (count == 0)
+ return;
+
+ /* Now handle residuals in the last word. */
+ SBITMAP_ELT_TYPE mask = ((SBITMAP_ELT_TYPE)1 << count) - 1;
+ bmap->elms[start_word] |= mask;
+}
+
+/* Return TRUE if any bit between START and END inclusive is set within
+ the simple bitmap BMAP. Return FALSE otherwise. */
+
+bool
+bitmap_bit_in_range_p (const_sbitmap bmap, unsigned int start, unsigned int end)
+{
+ gcc_checking_assert (start <= end);
+ bitmap_check_index (bmap, end);
+
+ unsigned int start_word = start / SBITMAP_ELT_BITS;
+ unsigned int start_bitno = start % SBITMAP_ELT_BITS;
+
+ unsigned int end_word = end / SBITMAP_ELT_BITS;
+ unsigned int end_bitno = end % SBITMAP_ELT_BITS;
+
+ /* Check beginning of first word if different from zero. */
+ if (start_bitno != 0)
+ {
+ SBITMAP_ELT_TYPE high_mask = ~(SBITMAP_ELT_TYPE)0;
+ if (start_word == end_word && end_bitno + 1 < SBITMAP_ELT_BITS)
+ high_mask = ((SBITMAP_ELT_TYPE)1 << (end_bitno + 1)) - 1;
+
+ SBITMAP_ELT_TYPE low_mask = ((SBITMAP_ELT_TYPE)1 << start_bitno) - 1;
+ SBITMAP_ELT_TYPE mask = high_mask - low_mask;
+ if (bmap->elms[start_word] & mask)
+ return true;
+ start_word++;
+ }
+
+ if (start_word > end_word)
+ return false;
+
+ /* Now test words at a time until we hit a partial word. */
+ unsigned int nwords = (end_word - start_word);
+ while (nwords)
+ {
+ if (bmap->elms[start_word])
+ return true;
+ start_word++;
+ nwords--;
+ }
+
+ /* Now handle residuals in the last word. */
+ SBITMAP_ELT_TYPE mask = ~(SBITMAP_ELT_TYPE)0;
+ if (end_bitno + 1 < SBITMAP_ELT_BITS)
+ mask = ((SBITMAP_ELT_TYPE)1 << (end_bitno + 1)) - 1;
+ return (bmap->elms[start_word] & mask) != 0;
+}
+
+#if GCC_VERSION < 3400
+/* Table of number of set bits in a character, indexed by value of char. */
+static const unsigned char popcount_table[] =
+{
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
+};
+
+static unsigned long
+sbitmap_popcount (SBITMAP_ELT_TYPE a)
+{
+ unsigned long ret = 0;
+ unsigned i;
+
+ /* Just do this the table way for now */
+ for (i = 0; i < HOST_BITS_PER_WIDEST_FAST_INT; i += 8)
+ ret += popcount_table[(a >> i) & 0xff];
+ return ret;
+}
+#endif
+
+/* Count and return the number of bits set in the bitmap BMAP. */
+
+unsigned int
+bitmap_count_bits (const_sbitmap bmap)
+{
+ unsigned int count = 0;
+ for (unsigned int i = 0; i < bmap->size; i++)
+ if (bmap->elms[i])
+ {
+#if GCC_VERSION < 3400
+ count += sbitmap_popcount (bmap->elms[i]);
+#else
+# if HOST_BITS_PER_WIDEST_FAST_INT == HOST_BITS_PER_LONG
+ count += __builtin_popcountl (bmap->elms[i]);
+# elif HOST_BITS_PER_WIDEST_FAST_INT == HOST_BITS_PER_LONGLONG
+ count += __builtin_popcountll (bmap->elms[i]);
+# else
+ count += __builtin_popcount (bmap->elms[i]);
+# endif
+#endif
+ }
+ return count;
+}
+
+/* Zero all elements in a bitmap. */
+
+void
+bitmap_clear (sbitmap bmap)
+{
+ memset (bmap->elms, 0, sbitmap_size_bytes (bmap));
+}
+
+/* Set all elements in a bitmap to ones. */
+
+void
+bitmap_ones (sbitmap bmap)
+{
+ unsigned int last_bit;
+
+ memset (bmap->elms, -1, sbitmap_size_bytes (bmap));
+
+ last_bit = bmap->n_bits % SBITMAP_ELT_BITS;
+ if (last_bit)
+ bmap->elms[bmap->size - 1]
+ = (SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit);
+}
+
+/* Zero a vector of N_VECS bitmaps. */
+
+void
+bitmap_vector_clear (sbitmap *bmap, unsigned int n_vecs)
+{
+ unsigned int i;
+
+ for (i = 0; i < n_vecs; i++)
+ bitmap_clear (bmap[i]);
+}
+
+/* Set a vector of N_VECS bitmaps to ones. */
+
+void
+bitmap_vector_ones (sbitmap *bmap, unsigned int n_vecs)
+{
+ unsigned int i;
+
+ for (i = 0; i < n_vecs; i++)
+ bitmap_ones (bmap[i]);
+}
+
+/* Set DST to be A union (B - C).
+ DST = A | (B & ~C).
+ Returns true if any change is made. */
+
+bool
+bitmap_ior_and_compl (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, c);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ const_sbitmap_ptr cp = c->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ const SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & ~*cp++);
+ changed |= *dstp ^ tmp;
+ *dstp++ = tmp;
+ }
+
+ return changed != 0;
+}
+
+/* Set bitmap DST to the bitwise negation of the bitmap SRC. */
+
+void
+bitmap_not (sbitmap dst, const_sbitmap src)
+{
+ bitmap_check_sizes (src, dst);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr srcp = src->elms;
+ unsigned int last_bit;
+
+ for (i = 0; i < n; i++)
+ *dstp++ = ~*srcp++;
+
+ /* Zero all bits past n_bits, by ANDing dst with bitmap_ones. */
+ last_bit = src->n_bits % SBITMAP_ELT_BITS;
+ if (last_bit)
+ dst->elms[n-1] = dst->elms[n-1]
+ & ((SBITMAP_ELT_TYPE)-1 >> (SBITMAP_ELT_BITS - last_bit));
+}
+
+/* Set the bits in DST to be the difference between the bits
+ in A and the bits in B. i.e. dst = a & (~b). */
+
+void
+bitmap_and_compl (sbitmap dst, const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, dst);
+
+ unsigned int i, dst_size = dst->size;
+ unsigned int min_size = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+
+ /* A should be at least as large as DEST, to have a defined source. */
+ gcc_assert (a->size >= dst_size);
+ /* If minuend is smaller, we simply pretend it to be zero bits, i.e.
+ only copy the subtrahend into dest. */
+ if (b->size < min_size)
+ min_size = b->size;
+ for (i = 0; i < min_size; i++)
+ *dstp++ = *ap++ & (~*bp++);
+ /* Now fill the rest of dest from A, if B was too short.
+ This makes sense only when destination and A differ. */
+ if (dst != a && i != dst_size)
+ for (; i < dst_size; i++)
+ *dstp++ = *ap++;
+}
+
+/* Return true if there are any bits set in A are also set in B.
+ Return false otherwise. */
+
+bool
+bitmap_intersect_p (const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ unsigned int i, n;
+
+ n = MIN (a->size, b->size);
+ for (i = 0; i < n; i++)
+ if ((*ap++ & *bp++) != 0)
+ return true;
+
+ return false;
+}
+
+/* Set DST to be (A and B).
+ Return nonzero if any change is made. */
+
+bool
+bitmap_and (sbitmap dst, const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, dst);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ const SBITMAP_ELT_TYPE tmp = *ap++ & *bp++;
+ SBITMAP_ELT_TYPE wordchanged = *dstp ^ tmp;
+ *dstp++ = tmp;
+ changed |= wordchanged;
+ }
+ return changed != 0;
+}
+
+/* Set DST to be (A xor B)).
+ Return nonzero if any change is made. */
+
+bool
+bitmap_xor (sbitmap dst, const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, dst);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ const SBITMAP_ELT_TYPE tmp = *ap++ ^ *bp++;
+ SBITMAP_ELT_TYPE wordchanged = *dstp ^ tmp;
+ *dstp++ = tmp;
+ changed |= wordchanged;
+ }
+ return changed != 0;
+}
+
+/* Set DST to be (A or B)).
+ Return nonzero if any change is made. */
+
+bool
+bitmap_ior (sbitmap dst, const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, dst);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ const SBITMAP_ELT_TYPE tmp = *ap++ | *bp++;
+ SBITMAP_ELT_TYPE wordchanged = *dstp ^ tmp;
+ *dstp++ = tmp;
+ changed |= wordchanged;
+ }
+ return changed != 0;
+}
+
+/* Return nonzero if A is a subset of B. */
+
+bool
+bitmap_subset_p (const_sbitmap a, const_sbitmap b)
+{
+ bitmap_check_sizes (a, b);
+
+ unsigned int i, n = a->size;
+ const_sbitmap_ptr ap, bp;
+
+ for (ap = a->elms, bp = b->elms, i = 0; i < n; i++, ap++, bp++)
+ if ((*ap | *bp) != *bp)
+ return false;
+
+ return true;
+}
+
+/* Set DST to be (A or (B and C)).
+ Return nonzero if any change is made. */
+
+bool
+bitmap_or_and (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, c);
+ bitmap_check_sizes (c, dst);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ const_sbitmap_ptr cp = c->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ const SBITMAP_ELT_TYPE tmp = *ap++ | (*bp++ & *cp++);
+ changed |= *dstp ^ tmp;
+ *dstp++ = tmp;
+ }
+
+ return changed != 0;
+}
+
+/* Set DST to be (A and (B or C)).
+ Return nonzero if any change is made. */
+
+bool
+bitmap_and_or (sbitmap dst, const_sbitmap a, const_sbitmap b, const_sbitmap c)
+{
+ bitmap_check_sizes (a, b);
+ bitmap_check_sizes (b, c);
+ bitmap_check_sizes (c, dst);
+
+ unsigned int i, n = dst->size;
+ sbitmap_ptr dstp = dst->elms;
+ const_sbitmap_ptr ap = a->elms;
+ const_sbitmap_ptr bp = b->elms;
+ const_sbitmap_ptr cp = c->elms;
+ SBITMAP_ELT_TYPE changed = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ const SBITMAP_ELT_TYPE tmp = *ap++ & (*bp++ | *cp++);
+ changed |= *dstp ^ tmp;
+ *dstp++ = tmp;
+ }
+
+ return changed != 0;
+}
+
+/* Return number of first bit set in the bitmap, -1 if none. */
+
+int
+bitmap_first_set_bit (const_sbitmap bmap)
+{
+ unsigned int n = 0;
+ sbitmap_iterator sbi;
+
+ EXECUTE_IF_SET_IN_BITMAP (bmap, 0, n, sbi)
+ return n;
+ return -1;
+}
+
+/* Return number of last bit set in the bitmap, -1 if none. */
+
+int
+bitmap_last_set_bit (const_sbitmap bmap)
+{
+ int i;
+ const SBITMAP_ELT_TYPE *const ptr = bmap->elms;
+
+ for (i = bmap->size - 1; i >= 0; i--)
+ {
+ const SBITMAP_ELT_TYPE word = ptr[i];
+
+ if (word != 0)
+ {
+ unsigned int index = (i + 1) * SBITMAP_ELT_BITS - 1;
+ SBITMAP_ELT_TYPE mask
+ = (SBITMAP_ELT_TYPE) 1 << (SBITMAP_ELT_BITS - 1);
+
+ while (1)
+ {
+ if ((word & mask) != 0)
+ return index;
+
+ mask >>= 1;
+ index--;
+ }
+ }
+ }
+
+ return -1;
+}
+
+void
+dump_bitmap (FILE *file, const_sbitmap bmap)
+{
+ unsigned int i, n, j;
+ unsigned int set_size = bmap->size;
+ unsigned int total_bits = bmap->n_bits;
+
+ fprintf (file, " ");
+ for (i = n = 0; i < set_size && n < total_bits; i++)
+ for (j = 0; j < SBITMAP_ELT_BITS && n < total_bits; j++, n++)
+ {
+ if (n != 0 && n % 10 == 0)
+ fprintf (file, " ");
+
+ fprintf (file, "%d",
+ (bmap->elms[i] & ((SBITMAP_ELT_TYPE) 1 << j)) != 0);
+ }
+
+ fprintf (file, "\n");
+}
+
+DEBUG_FUNCTION void
+debug_raw (simple_bitmap_def &ref)
+{
+ dump_bitmap (stderr, &ref);
+}
+
+DEBUG_FUNCTION void
+debug_raw (simple_bitmap_def *ptr)
+{
+ if (ptr)
+ debug_raw (*ptr);
+ else
+ fprintf (stderr, "<nil>\n");
+}
+
+void
+dump_bitmap_file (FILE *file, const_sbitmap bmap)
+{
+ unsigned int i, pos;
+
+ fprintf (file, "n_bits = %d, set = {", bmap->n_bits);
+
+ for (pos = 30, i = 0; i < bmap->n_bits; i++)
+ if (bitmap_bit_p (bmap, i))
+ {
+ if (pos > 70)
+ {
+ fprintf (file, "\n ");
+ pos = 0;
+ }
+
+ fprintf (file, "%d ", i);
+ pos += 2 + (i >= 10) + (i >= 100) + (i >= 1000);
+ }
+
+ fprintf (file, "}\n");
+}
+
+DEBUG_FUNCTION void
+debug_bitmap (const_sbitmap bmap)
+{
+ dump_bitmap_file (stderr, bmap);
+}
+
+DEBUG_FUNCTION void
+debug (simple_bitmap_def &ref)
+{
+ dump_bitmap_file (stderr, &ref);
+}
+
+DEBUG_FUNCTION void
+debug (simple_bitmap_def *ptr)
+{
+ if (ptr)
+ debug (*ptr);
+ else
+ fprintf (stderr, "<nil>\n");
+}
+
+void
+dump_bitmap_vector (FILE *file, const char *title, const char *subtitle,
+ sbitmap *bmaps, int n_maps)
+{
+ int i;
+
+ fprintf (file, "%s\n", title);
+ for (i = 0; i < n_maps; i++)
+ {
+ fprintf (file, "%s %d\n", subtitle, i);
+ dump_bitmap (file, bmaps[i]);
+ }
+
+ fprintf (file, "\n");
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for sbitmaps. */
+
+/* Checking function that uses both bitmap_bit_in_range_p and
+ loop of bitmap_bit_p and verifies consistent results. */
+
+static bool
+bitmap_bit_in_range_p_checking (sbitmap s, unsigned int start,
+ unsigned end)
+{
+ bool r1 = bitmap_bit_in_range_p (s, start, end);
+ bool r2 = false;
+
+ for (unsigned int i = start; i <= end; i++)
+ if (bitmap_bit_p (s, i))
+ {
+ r2 = true;
+ break;
+ }
+
+ ASSERT_EQ (r1, r2);
+ return r1;
+}
+
+/* Verify bitmap_set_range functions for sbitmap. */
+
+static void
+test_set_range ()
+{
+ sbitmap s = sbitmap_alloc (16);
+ bitmap_clear (s);
+
+ bitmap_set_range (s, 0, 1);
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 0, 0));
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 1, 15));
+ bitmap_set_range (s, 15, 1);
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 1, 14));
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 15, 15));
+ sbitmap_free (s);
+
+ s = sbitmap_alloc (1024);
+ bitmap_clear (s);
+ bitmap_set_range (s, 512, 1);
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 0, 511));
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 513, 1023));
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 512, 512));
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 508, 512));
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 508, 513));
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 508, 511));
+
+ bitmap_clear (s);
+ bitmap_set_range (s, 512, 64);
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 0, 511));
+ ASSERT_FALSE (bitmap_bit_in_range_p_checking (s, 512 + 64, 1023));
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 512, 512));
+ ASSERT_TRUE (bitmap_bit_in_range_p_checking (s, 512 + 63, 512 + 63));
+ sbitmap_free (s);
+}
+
+/* Verify bitmap_bit_in_range_p functions for sbitmap. */
+
+static void
+test_bit_in_range ()
+{
+ sbitmap s = sbitmap_alloc (1024);
+ bitmap_clear (s);
+
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 512, 1023));
+ bitmap_set_bit (s, 100);
+
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 512, 1023));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 99));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 101, 1023));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 100));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 64, 100));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 100, 100));
+ ASSERT_TRUE (bitmap_bit_p (s, 100));
+
+ sbitmap_free (s);
+
+ s = sbitmap_alloc (64);
+ bitmap_clear (s);
+ bitmap_set_bit (s, 63);
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 63));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 63));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 63, 63));
+ ASSERT_TRUE (bitmap_bit_p (s, 63));
+ sbitmap_free (s);
+
+ s = sbitmap_alloc (1024);
+ bitmap_clear (s);
+ bitmap_set_bit (s, 128);
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 127));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 129, 1023));
+
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 128));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 128));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 128, 255));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 128, 254));
+ ASSERT_TRUE (bitmap_bit_p (s, 128));
+
+ bitmap_clear (s);
+ bitmap_set_bit (s, 8);
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 8));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 12));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 63));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 127));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 512));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 8, 8));
+ ASSERT_TRUE (bitmap_bit_p (s, 8));
+
+ bitmap_clear (s);
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 0));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 8));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 63));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 1, 63));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 0, 256));
+
+ bitmap_set_bit (s, 0);
+ bitmap_set_bit (s, 16);
+ bitmap_set_bit (s, 32);
+ bitmap_set_bit (s, 48);
+ bitmap_set_bit (s, 64);
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 0, 0));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 1, 16));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 48, 63));
+ ASSERT_TRUE (bitmap_bit_in_range_p (s, 64, 64));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 1, 15));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 17, 31));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 49, 63));
+ ASSERT_FALSE (bitmap_bit_in_range_p (s, 65, 1023));
+ sbitmap_free (s);
+}
+
+/* Run all of the selftests within this file. */
+
+void
+sbitmap_cc_tests ()
+{
+ test_set_range ();
+ test_bit_in_range ();
+}
+
+} // namespace selftest
+#endif /* CHECKING_P */
diff --git a/support/cpp/gcc/sbitmap.h b/support/cpp/gcc/sbitmap.h
new file mode 100644
index 000000000..229ddfb3a
--- /dev/null
+++ b/support/cpp/gcc/sbitmap.h
@@ -0,0 +1,321 @@
+/* Simple bitmaps.
+ 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.
+
+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_SBITMAP_H
+#define GCC_SBITMAP_H
+
+/* Implementation of sets using simple bitmap vectors.
+
+ This set representation is suitable for non-sparse sets with a known
+ (a priori) universe. The set is represented as a simple array of the
+ host's fastest unsigned integer. For a given member I in the set:
+ - the element for I will be at sbitmap[I / (bits per element)]
+ - the position for I within element is I % (bits per element)
+
+ This representation is very space-efficient for large non-sparse sets
+ with random access patterns.
+
+ The following operations can be performed in O(1) time:
+
+ * set_size : SBITMAP_SIZE
+ * member_p : bitmap_bit_p
+ * add_member : bitmap_set_bit
+ * remove_member : bitmap_clear_bit
+
+ Most other operations on this set representation are O(U) where U is
+ the size of the set universe:
+
+ * clear : bitmap_clear
+ * choose_one : bitmap_first_set_bit /
+ bitmap_last_set_bit
+ * forall : EXECUTE_IF_SET_IN_BITMAP
+ * set_copy : bitmap_copy
+ * set_intersection : bitmap_and
+ * set_union : bitmap_ior
+ * set_difference : bitmap_and_compl
+ * set_disjuction : (not implemented)
+ * set_compare : bitmap_equal_p
+ * bit_in_range_p : bitmap_bit_in_range_p
+
+ Some operations on 3 sets that occur frequently in data flow problems
+ are also implemented:
+
+ * A | (B & C) : bitmap_or_and
+ * A | (B & ~C) : bitmap_ior_and_compl
+ * A & (B | C) : bitmap_and_or
+
+ Most of the set functions have two variants: One that returns non-zero
+ if members were added or removed from the target set, and one that just
+ performs the operation without feedback. The former operations are a
+ bit more expensive but the result can often be used to avoid iterations
+ on other sets.
+
+ Allocating a bitmap is done with sbitmap_alloc, and resizing is
+ performed with sbitmap_resize.
+
+ The storage requirements for simple bitmap sets is O(U) where U is the
+ size of the set universe (colloquially the number of bits in the bitmap).
+
+ This set representation works well for relatively small data flow problems
+ (there are special routines for that, see sbitmap_vector_*). The set
+ operations can be vectorized and there is almost no computating overhead,
+ so that even sparse simple bitmap sets outperform dedicated sparse set
+ representations like linked-list bitmaps. For larger problems, the size
+ overhead of simple bitmap sets gets too high and other set representations
+ have to be used. */
+
+#define SBITMAP_ELT_BITS (HOST_BITS_PER_WIDEST_FAST_INT * 1u)
+#define SBITMAP_ELT_TYPE unsigned HOST_WIDEST_FAST_INT
+
+struct simple_bitmap_def
+{
+ unsigned int n_bits; /* Number of bits. */
+ unsigned int size; /* Size in elements. */
+ SBITMAP_ELT_TYPE elms[1]; /* The elements. */
+};
+
+/* Return the set size needed for N elements. */
+#define SBITMAP_SET_SIZE(N) (((N) + SBITMAP_ELT_BITS - 1) / SBITMAP_ELT_BITS)
+
+/* Return the number of bits in BITMAP. */
+#define SBITMAP_SIZE(BITMAP) ((BITMAP)->n_bits)
+
+/* Verify that access at INDEX in bitmap MAP is valid. */
+
+static inline void
+bitmap_check_index (const_sbitmap map, int index)
+{
+ gcc_checking_assert (index >= 0);
+ gcc_checking_assert ((unsigned int)index < map->n_bits);
+}
+
+/* Verify that bitmaps A and B have same size. */
+
+static inline void
+bitmap_check_sizes (const_sbitmap a, const_sbitmap b)
+{
+ gcc_checking_assert (a->n_bits == b->n_bits);
+}
+
+/* Test if bit number bitno in the bitmap is set. */
+static inline bool
+bitmap_bit_p (const_sbitmap map, int bitno)
+{
+ bitmap_check_index (map, bitno);
+
+ size_t i = bitno / SBITMAP_ELT_BITS;
+ unsigned int s = bitno % SBITMAP_ELT_BITS;
+ return (map->elms[i] >> s) & (SBITMAP_ELT_TYPE) 1;
+}
+
+/* Set bit number BITNO in the sbitmap MAP.
+ Return true if the bit changed. */
+
+static inline bool
+bitmap_set_bit (sbitmap map, int bitno)
+{
+ bitmap_check_index (map, bitno);
+
+ size_t i = bitno / SBITMAP_ELT_BITS;
+ unsigned int s = bitno % SBITMAP_ELT_BITS;
+ if (map->elms[i] & ((SBITMAP_ELT_TYPE) 1 << s))
+ return false;
+ map->elms[i] |= (SBITMAP_ELT_TYPE) 1 << s;
+ return true;
+}
+
+/* Reset bit number BITNO in the sbitmap MAP.
+ Return true if the bit changed. */
+
+static inline bool
+bitmap_clear_bit (sbitmap map, int bitno)
+{
+ bitmap_check_index (map, bitno);
+
+ size_t i = bitno / SBITMAP_ELT_BITS;
+ unsigned int s = bitno % SBITMAP_ELT_BITS;
+ if (!(map->elms[i] & ((SBITMAP_ELT_TYPE) 1 << s)))
+ return false;
+ map->elms[i] &= ~((SBITMAP_ELT_TYPE) 1 << s);
+ return true;
+}
+
+/* The iterator for sbitmap. */
+struct sbitmap_iterator {
+ /* The pointer to the first word of the bitmap. */
+ const SBITMAP_ELT_TYPE *ptr;
+
+ /* The size of the bitmap. */
+ unsigned int size;
+
+ /* The current word index. */
+ unsigned int word_num;
+
+ /* The current bit index (not modulo SBITMAP_ELT_BITS). */
+ unsigned int bit_num;
+
+ /* The words currently visited. */
+ SBITMAP_ELT_TYPE word;
+};
+
+/* Initialize the iterator I with sbitmap BMP and the initial index
+ MIN. */
+
+static inline void
+bmp_iter_set_init (sbitmap_iterator *i, const_sbitmap bmp,
+ unsigned int min, unsigned *bit_no ATTRIBUTE_UNUSED)
+{
+ i->word_num = min / (unsigned int) SBITMAP_ELT_BITS;
+ i->bit_num = min;
+ i->size = bmp->size;
+ i->ptr = bmp->elms;
+
+ if (i->word_num >= i->size)
+ i->word = 0;
+ else
+ i->word = (i->ptr[i->word_num]
+ >> (i->bit_num % (unsigned int) SBITMAP_ELT_BITS));
+}
+
+/* Return true if we have more bits to visit, in which case *N is set
+ to the index of the bit to be visited. Otherwise, return
+ false. */
+
+static inline bool
+bmp_iter_set (sbitmap_iterator *i, unsigned int *n)
+{
+ /* Skip words that are zeros. */
+ for (; i->word == 0; i->word = i->ptr[i->word_num])
+ {
+ i->word_num++;
+
+ /* If we have reached the end, break. */
+ if (i->word_num >= i->size)
+ return false;
+
+ i->bit_num = i->word_num * SBITMAP_ELT_BITS;
+ }
+
+ /* Skip bits that are zero. */
+ for (; (i->word & 1) == 0; i->word >>= 1)
+ i->bit_num++;
+
+ *n = i->bit_num;
+
+ return true;
+}
+
+/* Advance to the next bit. */
+
+static inline void
+bmp_iter_next (sbitmap_iterator *i, unsigned *bit_no ATTRIBUTE_UNUSED)
+{
+ i->word >>= 1;
+ i->bit_num++;
+}
+
+/* Loop over all elements of SBITMAP, starting with MIN. In each
+ iteration, N is set to the index of the bit being visited. ITER is
+ an instance of sbitmap_iterator used to iterate the bitmap. */
+
+#ifndef EXECUTE_IF_SET_IN_BITMAP
+/* See bitmap.h for the other definition of EXECUTE_IF_SET_IN_BITMAP. */
+#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, ITER) \
+ for (bmp_iter_set_init (&(ITER), (BITMAP), (MIN), &(BITNUM)); \
+ bmp_iter_set (&(ITER), &(BITNUM)); \
+ bmp_iter_next (&(ITER), &(BITNUM)))
+#endif
+
+inline void sbitmap_free (sbitmap map)
+{
+ free (map);
+}
+
+inline void sbitmap_vector_free (sbitmap * vec)
+{
+ free (vec);
+}
+
+extern void dump_bitmap (FILE *, const_sbitmap);
+extern void debug_raw (const simple_bitmap_def &ref);
+extern void debug_raw (const simple_bitmap_def *ptr);
+extern void dump_bitmap_file (FILE *, const_sbitmap);
+extern void debug (const simple_bitmap_def &ref);
+extern void debug (const simple_bitmap_def *ptr);
+extern void dump_bitmap_vector (FILE *, const char *, const char *, sbitmap *,
+ int);
+extern sbitmap sbitmap_alloc (unsigned int);
+extern sbitmap *sbitmap_vector_alloc (unsigned int, unsigned int);
+extern sbitmap sbitmap_resize (sbitmap, unsigned int, int);
+extern void bitmap_copy (sbitmap, const_sbitmap);
+extern int bitmap_equal_p (const_sbitmap, const_sbitmap);
+extern unsigned int bitmap_count_bits (const_sbitmap);
+extern bool bitmap_empty_p (const_sbitmap);
+extern void bitmap_clear (sbitmap);
+extern void bitmap_clear_range (sbitmap, unsigned, unsigned);
+extern void bitmap_set_range (sbitmap, unsigned, unsigned);
+extern void bitmap_ones (sbitmap);
+extern void bitmap_vector_clear (sbitmap *, unsigned int);
+extern void bitmap_vector_ones (sbitmap *, unsigned int);
+
+extern bool bitmap_ior_and_compl (sbitmap, const_sbitmap,
+ const_sbitmap, const_sbitmap);
+extern void bitmap_and_compl (sbitmap, const_sbitmap, const_sbitmap);
+extern void bitmap_not (sbitmap, const_sbitmap);
+extern bool bitmap_or_and (sbitmap, const_sbitmap,
+ const_sbitmap, const_sbitmap);
+extern bool bitmap_and_or (sbitmap, const_sbitmap,
+ const_sbitmap, const_sbitmap);
+extern bool bitmap_intersect_p (const_sbitmap, const_sbitmap);
+extern bool bitmap_and (sbitmap, const_sbitmap, const_sbitmap);
+extern bool bitmap_ior (sbitmap, const_sbitmap, const_sbitmap);
+extern bool bitmap_xor (sbitmap, const_sbitmap, const_sbitmap);
+extern bool bitmap_subset_p (const_sbitmap, const_sbitmap);
+extern bool bitmap_bit_in_range_p (const_sbitmap, unsigned int, unsigned int);
+
+extern int bitmap_first_set_bit (const_sbitmap);
+extern int bitmap_last_set_bit (const_sbitmap);
+
+extern void debug_bitmap (const_sbitmap);
+extern sbitmap sbitmap_realloc (sbitmap, unsigned int);
+
+/* a class that ties the lifetime of a sbitmap to its scope. */
+class auto_sbitmap
+{
+public:
+ explicit auto_sbitmap (unsigned int size) :
+ m_bitmap (sbitmap_alloc (size)) {}
+ ~auto_sbitmap () { sbitmap_free (m_bitmap); }
+
+ /* Allow calling sbitmap functions on our bitmap. */
+ operator sbitmap () { return m_bitmap; }
+ operator const_sbitmap () const { return m_bitmap; }
+
+private:
+ /* Prevent making a copy that refers to our sbitmap. */
+ auto_sbitmap (const auto_sbitmap &);
+ auto_sbitmap &operator = (const auto_sbitmap &);
+ auto_sbitmap (auto_sbitmap &&);
+ auto_sbitmap &operator = (auto_sbitmap &&);
+
+ /* The bitmap we are managing. */
+ sbitmap m_bitmap;
+};
+
+#endif /* ! GCC_SBITMAP_H */
diff --git a/support/cpp/gcc/selftest-diagnostic.cc b/support/cpp/gcc/selftest-diagnostic.cc
new file mode 100644
index 000000000..f0e615e49
--- /dev/null
+++ b/support/cpp/gcc/selftest-diagnostic.cc
@@ -0,0 +1,64 @@
+/* Selftest support for diagnostics.
+ Copyright (C) 2016-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 "diagnostic.h"
+#include "selftest.h"
+#include "selftest-diagnostic.h"
+
+/* The selftest code should entirely disappear in a production
+ configuration, hence we guard all of it with #if CHECKING_P. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Implementation of class selftest::test_diagnostic_context. */
+
+test_diagnostic_context::test_diagnostic_context ()
+{
+ diagnostic_initialize (this, 0);
+ show_caret = true;
+ show_labels_p = true;
+ show_column = true;
+ start_span = start_span_cb;
+ min_margin_width = 6;
+}
+
+test_diagnostic_context::~test_diagnostic_context ()
+{
+ diagnostic_finish (this);
+}
+
+/* Implementation of diagnostic_start_span_fn, hiding the
+ real filename (to avoid printing the names of tempfiles). */
+
+void
+test_diagnostic_context::start_span_cb (diagnostic_context *context,
+ expanded_location exploc)
+{
+ exploc.file = "FILENAME";
+ default_diagnostic_start_span_fn (context, exploc);
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/support/cpp/gcc/selftest-diagnostic.h b/support/cpp/gcc/selftest-diagnostic.h
new file mode 100644
index 000000000..a2047026c
--- /dev/null
+++ b/support/cpp/gcc/selftest-diagnostic.h
@@ -0,0 +1,49 @@
+/* Selftest support for diagnostics.
+ Copyright (C) 2016-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_SELFTEST_DIAGNOSTIC_H
+#define GCC_SELFTEST_DIAGNOSTIC_H
+
+/* The selftest code should entirely disappear in a production
+ configuration, hence we guard all of it with #if CHECKING_P. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Convenience subclass of diagnostic_context for testing
+ the diagnostic subsystem. */
+
+class test_diagnostic_context : public diagnostic_context
+{
+ public:
+ test_diagnostic_context ();
+ ~test_diagnostic_context ();
+
+ /* Implementation of diagnostic_start_span_fn, hiding the
+ real filename (to avoid printing the names of tempfiles). */
+ static void
+ start_span_cb (diagnostic_context *context, expanded_location exploc);
+};
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_SELFTEST_DIAGNOSTIC_H */
diff --git a/support/cpp/gcc/selftest.cc b/support/cpp/gcc/selftest.cc
new file mode 100644
index 000000000..89abfba5e
--- /dev/null
+++ b/support/cpp/gcc/selftest.cc
@@ -0,0 +1,426 @@
+/* A self-testing framework, for use by -fself-test.
+ Copyright (C) 2015-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 "selftest.h"
+#include "intl.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+int num_passes;
+
+/* Record the successful outcome of some aspect of a test. */
+
+void
+pass (const location &/*loc*/, const char */*msg*/)
+{
+ num_passes++;
+}
+
+/* Report the failed outcome of some aspect of a test and abort. */
+
+void
+fail (const location &loc, const char *msg)
+{
+ fprintf (stderr,"%s:%i: %s: FAIL: %s\n", loc.m_file, loc.m_line,
+ loc.m_function, msg);
+ abort ();
+}
+
+/* As "fail", but using printf-style formatted output. */
+
+void
+fail_formatted (const location &loc, const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf (stderr, "%s:%i: %s: FAIL: ", loc.m_file, loc.m_line,
+ loc.m_function);
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+ fprintf (stderr, "\n");
+ abort ();
+}
+
+/* Implementation detail of ASSERT_STREQ.
+ Compare val1 and val2 with strcmp. They ought
+ to be non-NULL; fail gracefully if either or both are NULL. */
+
+void
+assert_streq (const location &loc,
+ const char *desc_val1, const char *desc_val2,
+ const char *val1, const char *val2)
+{
+ /* If val1 or val2 are NULL, fail with a custom error message. */
+ if (val1 == NULL)
+ if (val2 == NULL)
+ fail_formatted (loc, "ASSERT_STREQ (%s, %s) val1=NULL val2=NULL",
+ desc_val1, desc_val2);
+ else
+ fail_formatted (loc, "ASSERT_STREQ (%s, %s) val1=NULL val2=\"%s\"",
+ desc_val1, desc_val2, val2);
+ else
+ if (val2 == NULL)
+ fail_formatted (loc, "ASSERT_STREQ (%s, %s) val1=\"%s\" val2=NULL",
+ desc_val1, desc_val2, val1);
+ else
+ {
+ if (strcmp (val1, val2) == 0)
+ pass (loc, "ASSERT_STREQ");
+ else
+ fail_formatted (loc, "ASSERT_STREQ (%s, %s)\n val1=\"%s\"\n val2=\"%s\"\n",
+ desc_val1, desc_val2, val1, val2);
+ }
+}
+
+/* Implementation detail of ASSERT_STR_CONTAINS.
+ Use strstr to determine if val_needle is within val_haystack.
+ ::selftest::pass if it is found.
+ ::selftest::fail if it is not found. */
+
+void
+assert_str_contains (const location &loc,
+ const char *desc_haystack,
+ const char *desc_needle,
+ const char *val_haystack,
+ const char *val_needle)
+{
+ /* If val_haystack is NULL, fail with a custom error message. */
+ if (val_haystack == NULL)
+ fail_formatted (loc, "ASSERT_STR_CONTAINS (%s, %s) haystack=NULL",
+ desc_haystack, desc_needle);
+
+ /* If val_needle is NULL, fail with a custom error message. */
+ if (val_needle == NULL)
+ fail_formatted (loc,
+ "ASSERT_STR_CONTAINS (%s, %s) haystack=\"%s\" needle=NULL",
+ desc_haystack, desc_needle, val_haystack);
+
+ const char *test = strstr (val_haystack, val_needle);
+ if (test)
+ pass (loc, "ASSERT_STR_CONTAINS");
+ else
+ fail_formatted
+ (loc, "ASSERT_STR_CONTAINS (%s, %s) haystack=\"%s\" needle=\"%s\"",
+ desc_haystack, desc_needle, val_haystack, val_needle);
+}
+
+/* Implementation detail of ASSERT_STR_STARTSWITH.
+ Determine if VAL_STR starts with VAL_PREFIX.
+ ::selftest::pass if VAL_STR does start with VAL_PREFIX.
+ ::selftest::fail if it does not, or either is NULL (using
+ DESC_STR and DESC_PREFIX in the error message). */
+
+void
+assert_str_startswith (const location &loc,
+ const char *desc_str,
+ const char *desc_prefix,
+ const char *val_str,
+ const char *val_prefix)
+{
+ /* If val_str is NULL, fail with a custom error message. */
+ if (val_str == NULL)
+ fail_formatted (loc, "ASSERT_STR_STARTSWITH (%s, %s) str=NULL",
+ desc_str, desc_prefix);
+
+ /* If val_prefix is NULL, fail with a custom error message. */
+ if (val_prefix == NULL)
+ fail_formatted (loc,
+ "ASSERT_STR_STARTSWITH (%s, %s) str=\"%s\" prefix=NULL",
+ desc_str, desc_prefix, val_str);
+
+ if (startswith (val_str, val_prefix))
+ pass (loc, "ASSERT_STR_STARTSWITH");
+ else
+ fail_formatted
+ (loc, "ASSERT_STR_STARTSWITH (%s, %s) str=\"%s\" prefix=\"%s\"",
+ desc_str, desc_prefix, val_str, val_prefix);
+}
+
+
+/* Constructor. Generate a name for the file. */
+
+named_temp_file::named_temp_file (const char *suffix)
+{
+ m_filename = make_temp_file (suffix);
+ ASSERT_NE (m_filename, NULL);
+}
+
+/* Destructor. Delete the tempfile. */
+
+named_temp_file::~named_temp_file ()
+{
+ unlink (m_filename);
+ diagnostics_file_cache_forcibly_evict_file (m_filename);
+ free (m_filename);
+}
+
+/* Constructor. Create a tempfile using SUFFIX, and write CONTENT to
+ it. Abort if anything goes wrong, using LOC as the effective
+ location in the problem report. */
+
+temp_source_file::temp_source_file (const location &loc,
+ const char *suffix,
+ const char *content)
+: named_temp_file (suffix)
+{
+ FILE *out = fopen (get_filename (), "w");
+ if (!out)
+ fail_formatted (loc, "unable to open tempfile: %s", get_filename ());
+ fprintf (out, "%s", content);
+ fclose (out);
+}
+
+/* As above, but with a size, to allow for NUL bytes in CONTENT. */
+
+temp_source_file::temp_source_file (const location &loc,
+ const char *suffix,
+ const char *content,
+ size_t sz)
+: named_temp_file (suffix)
+{
+ FILE *out = fopen (get_filename (), "w");
+ if (!out)
+ fail_formatted (loc, "unable to open tempfile: %s", get_filename ());
+ fwrite (content, sz, 1, out);
+ fclose (out);
+}
+
+/* Avoid introducing locale-specific differences in the results
+ by hardcoding open_quote and close_quote. */
+
+auto_fix_quotes::auto_fix_quotes ()
+{
+ m_saved_open_quote = open_quote;
+ m_saved_close_quote = close_quote;
+ open_quote = "`";
+ close_quote = "'";
+}
+
+/* Restore old values of open_quote and close_quote. */
+
+auto_fix_quotes::~auto_fix_quotes ()
+{
+ open_quote = m_saved_open_quote;
+ close_quote = m_saved_close_quote;
+}
+
+/* Read the contents of PATH into memory, returning a 0-terminated buffer
+ that must be freed by the caller.
+ Fail (and abort) if there are any problems, with LOC as the reported
+ location of the failure. */
+
+char *
+read_file (const location &loc, const char *path)
+{
+ FILE *f_in = fopen (path, "r");
+ if (!f_in)
+ fail_formatted (loc, "unable to open file: %s", path);
+
+ /* Read content, allocating FIXME. */
+ char *result = NULL;
+ size_t total_sz = 0;
+ size_t alloc_sz = 0;
+ char buf[4096];
+ size_t iter_sz_in;
+
+ while ( (iter_sz_in = fread (buf, 1, sizeof (buf), f_in)) )
+ {
+ gcc_assert (alloc_sz >= total_sz);
+ size_t old_total_sz = total_sz;
+ total_sz += iter_sz_in;
+ /* Allow 1 extra byte for 0-termination. */
+ if (alloc_sz < (total_sz + 1))
+ {
+ size_t new_alloc_sz = alloc_sz ? alloc_sz * 2: total_sz + 1;
+ result = (char *)xrealloc (result, new_alloc_sz);
+ alloc_sz = new_alloc_sz;
+ }
+ memcpy (result + old_total_sz, buf, iter_sz_in);
+ }
+
+ if (!feof (f_in))
+ fail_formatted (loc, "error reading from %s: %s", path,
+ xstrerror (errno));
+
+ fclose (f_in);
+
+ /* 0-terminate the buffer. */
+ gcc_assert (total_sz < alloc_sz);
+ result[total_sz] = '\0';
+
+ return result;
+}
+
+/* The path of SRCDIR/testsuite/selftests. */
+
+const char *path_to_selftest_files = NULL;
+
+/* Convert a path relative to SRCDIR/testsuite/selftests
+ to a real path (either absolute, or relative to pwd).
+ The result should be freed by the caller. */
+
+char *
+locate_file (const char *name)
+{
+ ASSERT_NE (NULL, path_to_selftest_files);
+ return concat (path_to_selftest_files, "/", name, NULL);
+}
+
+/* selftest::test_runner's ctor. */
+
+test_runner::test_runner (const char *name)
+: m_name (name),
+ m_start_time (get_run_time ())
+{
+}
+
+/* selftest::test_runner's dtor. Print a summary line to stderr. */
+
+test_runner::~test_runner ()
+{
+ /* Finished running tests. */
+ long finish_time = get_run_time ();
+ long elapsed_time = finish_time - m_start_time;
+
+ fprintf (stderr,
+ "%s: %i pass(es) in %ld.%06ld seconds\n",
+ m_name, num_passes,
+ elapsed_time / 1000000, elapsed_time % 1000000);
+}
+
+/* Selftests for libiberty. */
+
+/* Verify that xstrndup generates EXPECTED when called on SRC and N. */
+
+static void
+assert_xstrndup_eq (const char *expected, const char *src, size_t n)
+{
+ char *buf = xstrndup (src, n);
+ ASSERT_STREQ (expected, buf);
+ free (buf);
+}
+
+/* Verify that xstrndup works as expected. */
+
+static void
+test_xstrndup ()
+{
+ assert_xstrndup_eq ("", "test", 0);
+ assert_xstrndup_eq ("t", "test", 1);
+ assert_xstrndup_eq ("te", "test", 2);
+ assert_xstrndup_eq ("tes", "test", 3);
+ assert_xstrndup_eq ("test", "test", 4);
+ assert_xstrndup_eq ("test", "test", 5);
+
+ /* Test on an string without zero termination. */
+ const char src[4] = {'t', 'e', 's', 't'};
+ assert_xstrndup_eq ("", src, 0);
+ assert_xstrndup_eq ("t", src, 1);
+ assert_xstrndup_eq ("te", src, 2);
+ assert_xstrndup_eq ("tes", src, 3);
+ assert_xstrndup_eq ("test", src, 4);
+}
+
+/* Run selftests for libiberty. */
+
+static void
+test_libiberty ()
+{
+ test_xstrndup ();
+}
+
+/* Selftests for the selftest system itself. */
+
+/* Sanity-check the ASSERT_ macros with various passing cases. */
+
+static void
+test_assertions ()
+{
+ ASSERT_TRUE (true);
+ ASSERT_FALSE (false);
+ ASSERT_EQ (1, 1);
+ ASSERT_EQ_AT (SELFTEST_LOCATION, 1, 1);
+ ASSERT_NE (1, 2);
+ ASSERT_GT (2, 1);
+ ASSERT_GT_AT (SELFTEST_LOCATION, 2, 1);
+ ASSERT_LT (1, 2);
+ ASSERT_LT_AT (SELFTEST_LOCATION, 1, 2);
+ ASSERT_STREQ ("test", "test");
+ ASSERT_STREQ_AT (SELFTEST_LOCATION, "test", "test");
+ ASSERT_STR_CONTAINS ("foo bar baz", "bar");
+}
+
+/* Verify named_temp_file. */
+
+static void
+test_named_temp_file ()
+{
+ named_temp_file t (".txt");
+ FILE *f = fopen (t.get_filename (), "w");
+ if (!f)
+ fail_formatted (SELFTEST_LOCATION,
+ "unable to open %s for writing", t.get_filename ());
+ fclose (f);
+}
+
+/* Verify read_file (and also temp_source_file). */
+
+static void
+test_read_file ()
+{
+ temp_source_file t (SELFTEST_LOCATION, "test1.s",
+ "\tjmp\t.L2\n");
+ char *buf = read_file (SELFTEST_LOCATION, t.get_filename ());
+ ASSERT_STREQ ("\tjmp\t.L2\n", buf);
+ free (buf);
+}
+
+/* Verify locate_file (and read_file). */
+
+static void
+test_locate_file ()
+{
+ char *path = locate_file ("example.txt");
+ char *buf = read_file (SELFTEST_LOCATION, path);
+ ASSERT_STREQ ("example of a selftest file\n", buf);
+ free (buf);
+ free (path);
+}
+
+/* Run all of the selftests within this file. */
+
+void
+selftest_cc_tests ()
+{
+ test_libiberty ();
+ test_assertions ();
+ test_named_temp_file ();
+ test_read_file ();
+ test_locate_file ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/support/cpp/gcc/selftest.h b/support/cpp/gcc/selftest.h
new file mode 100644
index 000000000..7568a6d24
--- /dev/null
+++ b/support/cpp/gcc/selftest.h
@@ -0,0 +1,491 @@
+/* A self-testing framework, for use by -fself-test.
+ Copyright (C) 2015-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_SELFTEST_H
+#define GCC_SELFTEST_H
+
+/* The selftest code should entirely disappear in a production
+ configuration, hence we guard all of it with #if CHECKING_P. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* A struct describing the source-location of a selftest, to make it
+ easier to track down failing tests. */
+
+class location
+{
+public:
+ location (const char *file, int line, const char *function)
+ : m_file (file), m_line (line), m_function (function) {}
+
+ const char *m_file;
+ int m_line;
+ const char *m_function;
+};
+
+/* A macro for use in selftests and by the ASSERT_ macros below,
+ constructing a selftest::location for the current source location. */
+
+#define SELFTEST_LOCATION \
+ (::selftest::location (__FILE__, __LINE__, __FUNCTION__))
+
+/* The entrypoint for running all tests. */
+
+extern void run_tests ();
+
+/* Record the successful outcome of some aspect of the test. */
+
+extern void pass (const location &loc, const char *msg);
+
+/* Report the failed outcome of some aspect of the test and abort. */
+
+extern void fail (const location &loc, const char *msg)
+ ATTRIBUTE_NORETURN;
+
+/* As "fail", but using printf-style formatted output. */
+
+extern void fail_formatted (const location &loc, const char *fmt, ...)
+ ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
+
+/* Implementation detail of ASSERT_STREQ. */
+
+extern void assert_streq (const location &loc,
+ const char *desc_val1, const char *desc_val2,
+ const char *val1, const char *val2);
+
+/* Implementation detail of ASSERT_STR_CONTAINS. */
+
+extern void assert_str_contains (const location &loc,
+ const char *desc_haystack,
+ const char *desc_needle,
+ const char *val_haystack,
+ const char *val_needle);
+
+/* Implementation detail of ASSERT_STR_STARTSWITH. */
+
+extern void assert_str_startswith (const location &loc,
+ const char *desc_str,
+ const char *desc_prefix,
+ const char *val_str,
+ const char *val_prefix);
+
+
+/* A named temporary file for use in selftests.
+ Usable for writing out files, and as the base class for
+ temp_source_file.
+ The file is unlinked in the destructor. */
+
+class named_temp_file
+{
+ public:
+ named_temp_file (const char *suffix);
+ ~named_temp_file ();
+ const char *get_filename () const { return m_filename; }
+
+ private:
+ char *m_filename;
+};
+
+/* A class for writing out a temporary sourcefile for use in selftests
+ of input handling. */
+
+class temp_source_file : public named_temp_file
+{
+ public:
+ temp_source_file (const location &loc, const char *suffix,
+ const char *content);
+ temp_source_file (const location &loc, const char *suffix,
+ const char *content, size_t sz);
+};
+
+/* RAII-style class for avoiding introducing locale-specific differences
+ in strings containing localized quote marks, by temporarily overriding
+ the "open_quote" and "close_quote" globals to something hardcoded.
+
+ Specifically, the C locale's values are used:
+ - open_quote becomes "`"
+ - close_quote becomes "'"
+ for the lifetime of the object. */
+
+class auto_fix_quotes
+{
+ public:
+ auto_fix_quotes ();
+ ~auto_fix_quotes ();
+
+ private:
+ const char *m_saved_open_quote;
+ const char *m_saved_close_quote;
+};
+
+/* Various selftests involving location-handling require constructing a
+ line table and one or more line maps within it.
+
+ For maximum test coverage we want to run these tests with a variety
+ of situations:
+ - line_table->default_range_bits: some frontends use a non-zero value
+ and others use zero
+ - the fallback modes within line-map.cc: there are various threshold
+ values for location_t beyond line-map.cc changes
+ behavior (disabling of the range-packing optimization, disabling
+ of column-tracking). We can exercise these by starting the line_table
+ at interesting values at or near these thresholds.
+
+ The following struct describes a particular case within our test
+ matrix. */
+
+class line_table_case;
+
+/* A class for overriding the global "line_table" within a selftest,
+ restoring its value afterwards. At most one instance of this
+ class can exist at once, due to the need to keep the old value
+ of line_table as a GC root. */
+
+class line_table_test
+{
+ public:
+ /* Default constructor. Override "line_table", using sane defaults
+ for the temporary line_table. */
+ line_table_test ();
+
+ /* Constructor. Override "line_table", using the case described by C. */
+ line_table_test (const line_table_case &c);
+
+ /* Destructor. Restore the saved line_table. */
+ ~line_table_test ();
+};
+
+/* Helper function for selftests that need a function decl. */
+
+extern tree make_fndecl (tree return_type,
+ const char *name,
+ vec <tree> &param_types,
+ bool is_variadic = false);
+
+/* Run TESTCASE multiple times, once for each case in our test matrix. */
+
+extern void
+for_each_line_table_case (void (*testcase) (const line_table_case &));
+
+/* Read the contents of PATH into memory, returning a 0-terminated buffer
+ that must be freed by the caller.
+ Fail (and abort) if there are any problems, with LOC as the reported
+ location of the failure. */
+
+extern char *read_file (const location &loc, const char *path);
+
+/* Convert a path relative to SRCDIR/gcc/testsuite/selftests
+ to a real path (either absolute, or relative to pwd).
+ The result should be freed by the caller. */
+
+extern char *locate_file (const char *path);
+
+/* The path of SRCDIR/testsuite/selftests. */
+
+extern const char *path_to_selftest_files;
+
+/* selftest::test_runner is an implementation detail of selftest::run_tests,
+ exposed here to allow plugins to run their own suites of tests. */
+
+class test_runner
+{
+ public:
+ test_runner (const char *name);
+ ~test_runner ();
+
+ private:
+ const char *m_name;
+ long m_start_time;
+};
+
+/* Declarations for specific families of tests (by source file), in
+ alphabetical order. */
+extern void attribs_cc_tests ();
+extern void bitmap_cc_tests ();
+extern void cgraph_cc_tests ();
+extern void convert_cc_tests ();
+extern void diagnostic_format_json_cc_tests ();
+extern void diagnostic_show_locus_cc_tests ();
+extern void digraph_cc_tests ();
+extern void dumpfile_cc_tests ();
+extern void edit_context_cc_tests ();
+extern void et_forest_cc_tests ();
+extern void fibonacci_heap_cc_tests ();
+extern void fold_const_cc_tests ();
+extern void function_tests_cc_tests ();
+extern void ggc_tests_cc_tests ();
+extern void gimple_cc_tests ();
+extern void hash_map_tests_cc_tests ();
+extern void hash_set_tests_cc_tests ();
+extern void input_cc_tests ();
+extern void json_cc_tests ();
+extern void optinfo_emit_json_cc_tests ();
+extern void opts_cc_tests ();
+extern void ordered_hash_map_tests_cc_tests ();
+extern void predict_cc_tests ();
+extern void pretty_print_cc_tests ();
+extern void range_tests ();
+extern void range_op_tests ();
+extern void gimple_range_tests ();
+extern void read_rtl_function_cc_tests ();
+extern void rtl_tests_cc_tests ();
+extern void sbitmap_cc_tests ();
+extern void selftest_cc_tests ();
+extern void simplify_rtx_cc_tests ();
+extern void spellcheck_cc_tests ();
+extern void spellcheck_tree_cc_tests ();
+extern void splay_tree_cc_tests ();
+extern void sreal_cc_tests ();
+extern void store_merging_cc_tests ();
+extern void tree_cc_tests ();
+extern void tree_cfg_cc_tests ();
+extern void tree_diagnostic_path_cc_tests ();
+extern void tristate_cc_tests ();
+extern void typed_splay_tree_cc_tests ();
+extern void vec_cc_tests ();
+extern void vec_perm_indices_cc_tests ();
+extern void wide_int_cc_tests ();
+extern void opt_suggestions_cc_tests ();
+extern void dbgcnt_cc_tests ();
+extern void ipa_modref_tree_cc_tests ();
+
+extern int num_passes;
+
+} /* end of namespace selftest. */
+
+/* Macros for writing tests. */
+
+/* Evaluate EXPR and coerce to bool, calling
+ ::selftest::pass if it is true,
+ ::selftest::fail if it false. */
+
+#define ASSERT_TRUE(EXPR) \
+ ASSERT_TRUE_AT (SELFTEST_LOCATION, (EXPR))
+
+/* Like ASSERT_TRUE, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_TRUE_AT(LOC, EXPR) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_TRUE (" #EXPR ")"; \
+ bool actual_ = (EXPR); \
+ if (actual_) \
+ ::selftest::pass ((LOC), desc_); \
+ else \
+ ::selftest::fail ((LOC), desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate EXPR and coerce to bool, calling
+ ::selftest::pass if it is false,
+ ::selftest::fail if it true. */
+
+#define ASSERT_FALSE(EXPR) \
+ ASSERT_FALSE_AT (SELFTEST_LOCATION, (EXPR))
+
+/* Like ASSERT_FALSE, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_FALSE_AT(LOC, EXPR) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_FALSE (" #EXPR ")"; \
+ bool actual_ = (EXPR); \
+ if (actual_) \
+ ::selftest::fail ((LOC), desc_); \
+ else \
+ ::selftest::pass ((LOC), desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate VAL1 and VAL2 and compare them with ==, calling
+ ::selftest::pass if they are equal,
+ ::selftest::fail if they are non-equal. */
+
+#define ASSERT_EQ(VAL1, VAL2) \
+ ASSERT_EQ_AT ((SELFTEST_LOCATION), (VAL1), (VAL2))
+
+/* Like ASSERT_EQ, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_EQ_AT(LOC, VAL1, VAL2) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_EQ (" #VAL1 ", " #VAL2 ")"; \
+ if ((VAL1) == (VAL2)) \
+ ::selftest::pass ((LOC), desc_); \
+ else \
+ ::selftest::fail ((LOC), desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate VAL1 and VAL2 and compare them with known_eq, calling
+ ::selftest::pass if they are always equal,
+ ::selftest::fail if they might be non-equal. */
+
+#define ASSERT_KNOWN_EQ(VAL1, VAL2) \
+ ASSERT_KNOWN_EQ_AT ((SELFTEST_LOCATION), (VAL1), (VAL2))
+
+/* Like ASSERT_KNOWN_EQ, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_KNOWN_EQ_AT(LOC, VAL1, VAL2) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc = "ASSERT_KNOWN_EQ (" #VAL1 ", " #VAL2 ")"; \
+ if (known_eq (VAL1, VAL2)) \
+ ::selftest::pass ((LOC), desc); \
+ else \
+ ::selftest::fail ((LOC), desc); \
+ SELFTEST_END_STMT
+
+/* Evaluate VAL1 and VAL2 and compare them with !=, calling
+ ::selftest::pass if they are non-equal,
+ ::selftest::fail if they are equal. */
+
+#define ASSERT_NE(VAL1, VAL2) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_NE (" #VAL1 ", " #VAL2 ")"; \
+ if ((VAL1) != (VAL2)) \
+ ::selftest::pass (SELFTEST_LOCATION, desc_); \
+ else \
+ ::selftest::fail (SELFTEST_LOCATION, desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate VAL1 and VAL2 and compare them with maybe_ne, calling
+ ::selftest::pass if they might be non-equal,
+ ::selftest::fail if they are known to be equal. */
+
+#define ASSERT_MAYBE_NE(VAL1, VAL2) \
+ ASSERT_MAYBE_NE_AT ((SELFTEST_LOCATION), (VAL1), (VAL2))
+
+/* Like ASSERT_MAYBE_NE, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_MAYBE_NE_AT(LOC, VAL1, VAL2) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc = "ASSERT_MAYBE_NE (" #VAL1 ", " #VAL2 ")"; \
+ if (maybe_ne (VAL1, VAL2)) \
+ ::selftest::pass ((LOC), desc); \
+ else \
+ ::selftest::fail ((LOC), desc); \
+ SELFTEST_END_STMT
+
+/* Evaluate LHS and RHS and compare them with >, calling
+ ::selftest::pass if LHS > RHS,
+ ::selftest::fail otherwise. */
+
+#define ASSERT_GT(LHS, RHS) \
+ ASSERT_GT_AT ((SELFTEST_LOCATION), (LHS), (RHS))
+
+/* Like ASSERT_GT, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_GT_AT(LOC, LHS, RHS) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_GT (" #LHS ", " #RHS ")"; \
+ if ((LHS) > (RHS)) \
+ ::selftest::pass ((LOC), desc_); \
+ else \
+ ::selftest::fail ((LOC), desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate LHS and RHS and compare them with <, calling
+ ::selftest::pass if LHS < RHS,
+ ::selftest::fail otherwise. */
+
+#define ASSERT_LT(LHS, RHS) \
+ ASSERT_LT_AT ((SELFTEST_LOCATION), (LHS), (RHS))
+
+/* Like ASSERT_LT, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_LT_AT(LOC, LHS, RHS) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_LT (" #LHS ", " #RHS ")"; \
+ if ((LHS) < (RHS)) \
+ ::selftest::pass ((LOC), desc_); \
+ else \
+ ::selftest::fail ((LOC), desc_); \
+ SELFTEST_END_STMT
+
+/* Evaluate VAL1 and VAL2 and compare them with strcmp, calling
+ ::selftest::pass if they are equal (and both are non-NULL),
+ ::selftest::fail if they are non-equal, or are both NULL. */
+
+#define ASSERT_STREQ(VAL1, VAL2) \
+ SELFTEST_BEGIN_STMT \
+ ::selftest::assert_streq (SELFTEST_LOCATION, #VAL1, #VAL2, \
+ (VAL1), (VAL2)); \
+ SELFTEST_END_STMT
+
+/* Like ASSERT_STREQ, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_STREQ_AT(LOC, VAL1, VAL2) \
+ SELFTEST_BEGIN_STMT \
+ ::selftest::assert_streq ((LOC), #VAL1, #VAL2, \
+ (VAL1), (VAL2)); \
+ SELFTEST_END_STMT
+
+/* Evaluate HAYSTACK and NEEDLE and use strstr to determine if NEEDLE
+ is within HAYSTACK.
+ ::selftest::pass if NEEDLE is found.
+ ::selftest::fail if it is not found. */
+
+#define ASSERT_STR_CONTAINS(HAYSTACK, NEEDLE) \
+ SELFTEST_BEGIN_STMT \
+ ::selftest::assert_str_contains (SELFTEST_LOCATION, #HAYSTACK, #NEEDLE, \
+ (HAYSTACK), (NEEDLE)); \
+ SELFTEST_END_STMT
+
+/* Like ASSERT_STR_CONTAINS, but treat LOC as the effective location of the
+ selftest. */
+
+#define ASSERT_STR_CONTAINS_AT(LOC, HAYSTACK, NEEDLE) \
+ SELFTEST_BEGIN_STMT \
+ ::selftest::assert_str_contains (LOC, #HAYSTACK, #NEEDLE, \
+ (HAYSTACK), (NEEDLE)); \
+ SELFTEST_END_STMT
+
+/* Evaluate STR and PREFIX and determine if STR starts with PREFIX.
+ ::selftest::pass if STR does start with PREFIX.
+ ::selftest::fail if does not, or either is NULL. */
+
+#define ASSERT_STR_STARTSWITH(STR, PREFIX) \
+ SELFTEST_BEGIN_STMT \
+ ::selftest::assert_str_startswith (SELFTEST_LOCATION, #STR, #PREFIX, \
+ (STR), (PREFIX)); \
+ SELFTEST_END_STMT
+
+/* Evaluate PRED1 (VAL1), calling ::selftest::pass if it is true,
+ ::selftest::fail if it is false. */
+
+#define ASSERT_PRED1(PRED1, VAL1) \
+ SELFTEST_BEGIN_STMT \
+ const char *desc_ = "ASSERT_PRED1 (" #PRED1 ", " #VAL1 ")"; \
+ bool actual_ = (PRED1) (VAL1); \
+ if (actual_) \
+ ::selftest::pass (SELFTEST_LOCATION, desc_); \
+ else \
+ ::selftest::fail (SELFTEST_LOCATION, desc_); \
+ SELFTEST_END_STMT
+
+#define SELFTEST_BEGIN_STMT do {
+#define SELFTEST_END_STMT } while (0)
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_SELFTEST_H */
diff --git a/support/cpp/gcc/signop.h b/support/cpp/gcc/signop.h
new file mode 100644
index 000000000..88733a6e6
--- /dev/null
+++ b/support/cpp/gcc/signop.h
@@ -0,0 +1,33 @@
+/* Operations with SIGNED and UNSIGNED. -*- C++ -*-
+ 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/>. */
+
+#ifndef SIGNOP_H
+#define SIGNOP_H
+
+/* This type is used for the large number of functions that produce
+ different results depending on if the operands are signed types or
+ unsigned types. The signedness of a tree type can be found by
+ using the TYPE_SIGN macro. */
+
+enum signop {
+ SIGNED,
+ UNSIGNED
+};
+
+#endif
diff --git a/support/cpp/gcc/sort.cc b/support/cpp/gcc/sort.cc
new file mode 100644
index 000000000..a2b6444c7
--- /dev/null
+++ b/support/cpp/gcc/sort.cc
@@ -0,0 +1,310 @@
+/* Platform-independent deterministic sort function.
+ Copyright (C) 2018-2022 Free Software Foundation, Inc.
+ Contributed by Alexander Monakov.
+
+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 implements a sort function suitable for GCC use cases:
+ - signature-compatible to C qsort, but relaxed contract:
+ - may apply the comparator to elements in a temporary buffer
+ - may abort on allocation failure
+ - deterministic (but not necessarily stable)
+ - fast, especially for common cases (0-5 elements of size 8 or 4)
+
+ The implementation uses a network sort for up to 5 elements and
+ a merge sort on top of that. Neither stage has branches depending on
+ comparator result, trading extra arithmetic for branch mispredictions. */
+
+#ifdef GENERATOR_FILE
+#include "bconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include "system.h"
+
+#define likely(cond) __builtin_expect ((cond), 1)
+
+#ifdef __GNUC__
+#define noinline __attribute__ ((__noinline__))
+#else
+#define noinline
+#endif
+
+/* C-style qsort comparator function type. */
+typedef int cmp_fn (const void *, const void *);
+
+/* Structure holding read-mostly (read-only in netsort) context. */
+struct sort_ctx
+{
+ cmp_fn *cmp; // pointer to comparator
+ char *out; // output buffer
+ size_t n; // number of elements
+ size_t size; // element size
+ size_t nlim; // limit for network sort
+};
+
+/* Like sort_ctx, but for use with qsort_r-style comparators. Several
+ functions in this file are templates that work with either context type. */
+struct sort_r_ctx
+{
+ void *data;
+ sort_r_cmp_fn *cmp_;
+ char *out;
+ size_t n;
+ size_t size;
+ size_t nlim;
+ int cmp (const void *a, const void *b)
+ {
+ return cmp_ (a, b, data);
+ }
+};
+
+/* Helper for netsort. Permute, possibly in-place, 2 or 3 elements,
+ placing E0 to C->OUT, E1 to C->OUT + C->SIZE, and so on. */
+template<typename sort_ctx>
+static void
+reorder23 (sort_ctx *c, char *e0, char *e1, char *e2)
+{
+#define REORDER_23(TYPE, STRIDE, OFFSET) \
+do { \
+ TYPE t0, t1; \
+ memcpy (&t0, e0 + OFFSET, sizeof (TYPE)); \
+ memcpy (&t1, e1 + OFFSET, sizeof (TYPE)); \
+ char *out = c->out + OFFSET; \
+ if (likely (c->n == 3)) \
+ memmove (out + 2*STRIDE, e2 + OFFSET, sizeof (TYPE));\
+ memcpy (out, &t0, sizeof (TYPE)); out += STRIDE; \
+ memcpy (out, &t1, sizeof (TYPE)); \
+} while (0)
+
+ if (likely (c->size == sizeof (size_t)))
+ REORDER_23 (size_t, sizeof (size_t), 0);
+ else if (likely (c->size == sizeof (int)))
+ REORDER_23 (int, sizeof (int), 0);
+ else
+ {
+ size_t offset = 0, step = sizeof (size_t);
+ for (; offset + step <= c->size; offset += step)
+ REORDER_23 (size_t, c->size, offset);
+ for (; offset < c->size; offset++)
+ REORDER_23 (char, c->size, offset);
+ }
+}
+
+/* Like reorder23, but permute 4 or 5 elements. */
+template<typename sort_ctx>
+static void
+reorder45 (sort_ctx *c, char *e0, char *e1, char *e2, char *e3, char *e4)
+{
+#define REORDER_45(TYPE, STRIDE, OFFSET) \
+do { \
+ TYPE t0, t1, t2, t3; \
+ memcpy (&t0, e0 + OFFSET, sizeof (TYPE)); \
+ memcpy (&t1, e1 + OFFSET, sizeof (TYPE)); \
+ memcpy (&t2, e2 + OFFSET, sizeof (TYPE)); \
+ memcpy (&t3, e3 + OFFSET, sizeof (TYPE)); \
+ char *out = c->out + OFFSET; \
+ if (likely (c->n == 5)) \
+ memmove (out + 4*STRIDE, e4 + OFFSET, sizeof (TYPE));\
+ memcpy (out, &t0, sizeof (TYPE)); out += STRIDE; \
+ memcpy (out, &t1, sizeof (TYPE)); out += STRIDE; \
+ memcpy (out, &t2, sizeof (TYPE)); out += STRIDE; \
+ memcpy (out, &t3, sizeof (TYPE)); \
+} while (0)
+
+ if (likely (c->size == sizeof (size_t)))
+ REORDER_45 (size_t, sizeof (size_t), 0);
+ else if (likely(c->size == sizeof (int)))
+ REORDER_45 (int, sizeof (int), 0);
+ else
+ {
+ size_t offset = 0, step = sizeof (size_t);
+ for (; offset + step <= c->size; offset += step)
+ REORDER_45 (size_t, c->size, offset);
+ for (; offset < c->size; offset++)
+ REORDER_45 (char, c->size, offset);
+ }
+}
+
+/* Helper for netsort. Invoke comparator CMP on E0 and E1.
+ Return E0^E1 if E0 compares less than E1, zero otherwise.
+ This is noinline to avoid code growth and confine invocation
+ to a single call site, assisting indirect branch prediction. */
+template<typename sort_ctx>
+noinline static intptr_t
+cmp1 (char *e0, char *e1, sort_ctx *c)
+{
+ intptr_t x = (intptr_t)e0 ^ (intptr_t)e1;
+ return x & (c->cmp (e0, e1) >> 31);
+}
+
+/* Execute network sort on 2 to 5 elements from IN, placing them into C->OUT.
+ IN may be equal to C->OUT, in which case elements are sorted in place. */
+template<typename sort_ctx>
+static void
+netsort (char *in, sort_ctx *c)
+{
+#define CMP(e0, e1) \
+do { \
+ intptr_t x = cmp1 (e1, e0, c); \
+ e0 = (char *)((intptr_t)e0 ^ x); \
+ e1 = (char *)((intptr_t)e1 ^ x); \
+} while (0)
+
+ char *e0 = in, *e1 = e0 + c->size, *e2 = e1 + c->size;
+ CMP (e0, e1);
+ if (likely (c->n == 3))
+ {
+ CMP (e1, e2);
+ CMP (e0, e1);
+ }
+ if (c->n <= 3)
+ return reorder23 (c, e0, e1, e2);
+ char *e3 = e2 + c->size, *e4 = e3 + c->size;
+ if (likely (c->n == 5))
+ {
+ CMP (e3, e4);
+ CMP (e2, e4);
+ }
+ CMP (e2, e3);
+ if (likely (c->n == 5))
+ {
+ CMP (e0, e3);
+ CMP (e1, e4);
+ }
+ CMP (e0, e2);
+ CMP (e1, e3);
+ CMP (e1, e2);
+ reorder45 (c, e0, e1, e2, e3, e4);
+}
+
+/* Execute merge sort on N elements from IN, placing them into OUT,
+ using TMP as temporary storage if IN is equal to OUT.
+ This is a stable sort if netsort is used only for 2 or 3 elements. */
+template<typename sort_ctx>
+static void
+mergesort (char *in, sort_ctx *c, size_t n, char *out, char *tmp)
+{
+ if (likely (n <= c->nlim))
+ {
+ c->out = out;
+ c->n = n;
+ return netsort (in, c);
+ }
+ size_t nl = n / 2, nr = n - nl, sz = nl * c->size;
+ char *mid = in + sz, *r = out + sz, *l = in == out ? tmp : in;
+ /* Sort the right half, outputting to right half of OUT. */
+ mergesort (mid, c, nr, r, tmp);
+ /* Sort the left half, leaving left half of OUT free. */
+ mergesort (in, c, nl, l, mid);
+ /* Merge sorted halves given by L, R to [OUT, END). */
+#define MERGE_ELTSIZE(SIZE) \
+do { \
+ intptr_t mr = c->cmp (r, l) >> 31; \
+ intptr_t lr = (intptr_t)l ^ (intptr_t)r; \
+ lr = (intptr_t)l ^ (lr & mr); \
+ out = (char *)memcpy (out, (char *)lr, SIZE); \
+ out += SIZE; \
+ r += mr & SIZE; \
+ if (r == out) return; \
+ l += ~mr & SIZE; \
+} while (r != end)
+
+ if (likely (c->cmp(r, l + (r - out) - c->size) < 0))
+ {
+ char *end = out + n * c->size;
+ if (sizeof (size_t) == 8 && likely (c->size == 8))
+ MERGE_ELTSIZE (8);
+ else if (likely (c->size == 4))
+ MERGE_ELTSIZE (4);
+ else
+ MERGE_ELTSIZE (c->size);
+ }
+ memcpy (out, l, r - out);
+}
+
+#if CHECKING_P
+/* Adapter for using two-argument comparators in functions expecting the
+ three-argument sort_r_cmp_fn type. */
+static int
+cmp2to3 (const void *a, const void *b, void *c)
+{
+ return ((cmp_fn *)c) (a, b);
+}
+#endif
+
+/* Replacement for C qsort. */
+void
+gcc_qsort (void *vbase, size_t n, size_t size, cmp_fn *cmp)
+{
+ if (n < 2)
+ return;
+ size_t nlim = 5;
+ bool stable = (ssize_t) size < 0;
+ if (stable)
+ nlim = 3, size = ~size;
+ char *base = (char *)vbase;
+ sort_ctx c = {cmp, base, n, size, nlim};
+ long long scratch[32];
+ size_t bufsz = (n / 2) * size;
+ void *buf = bufsz <= sizeof scratch ? scratch : xmalloc (bufsz);
+ mergesort (base, &c, n, base, (char *)buf);
+ if (buf != scratch)
+ free (buf);
+#if CHECKING_P
+ qsort_chk (vbase, n, size, cmp2to3, (void*)cmp);
+#endif
+}
+
+/* Substitute for Glibc qsort_r. */
+void
+gcc_sort_r (void *vbase, size_t n, size_t size, sort_r_cmp_fn *cmp, void *data)
+{
+ if (n < 2)
+ return;
+ size_t nlim = 5;
+ bool stable = (ssize_t) size < 0;
+ if (stable)
+ nlim = 3, size = ~size;
+ char *base = (char *)vbase;
+ sort_r_ctx c = {data, cmp, base, n, size, nlim};
+ long long scratch[32];
+ size_t bufsz = (n / 2) * size;
+ void *buf = bufsz <= sizeof scratch ? scratch : xmalloc (bufsz);
+ mergesort (base, &c, n, base, (char *)buf);
+ if (buf != scratch)
+ free (buf);
+#if CHECKING_P
+ qsort_chk (vbase, n, size, cmp, data);
+#endif
+}
+
+/* Stable sort, signature-compatible to C qsort. */
+void
+gcc_stablesort (void *vbase, size_t n, size_t size, cmp_fn *cmp)
+{
+ gcc_qsort (vbase, n, ~size, cmp);
+}
+
+/* Stable sort, signature-compatible to Glibc qsort_r. */
+void
+gcc_stablesort_r (void *vbase, size_t n, size_t size, sort_r_cmp_fn *cmp,
+ void *data)
+{
+ gcc_sort_r (vbase, n, ~size, cmp, data);
+}
diff --git a/support/cpp/gcc/spellcheck-tree.h b/support/cpp/gcc/spellcheck-tree.h
new file mode 100644
index 000000000..a584d26f7
--- /dev/null
+++ b/support/cpp/gcc/spellcheck-tree.h
@@ -0,0 +1,51 @@
+/* Find near-matches for identifiers.
+ Copyright (C) 2015-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_SPELLCHECK_TREE_H
+#define GCC_SPELLCHECK_TREE_H
+
+#include "spellcheck.h"
+
+/* spellcheck-tree.cc */
+
+extern edit_distance_t
+get_edit_distance (tree ident_s, tree ident_t);
+
+extern tree
+find_closest_identifier (tree target, const auto_vec<tree> *candidates);
+
+/* Specialization of edit_distance_traits for identifiers. */
+
+template <>
+struct edit_distance_traits<tree>
+{
+ static size_t get_length (tree id)
+ {
+ gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
+ return IDENTIFIER_LENGTH (id);
+ }
+
+ static const char *get_string (tree id)
+ {
+ gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
+ return IDENTIFIER_POINTER (id);
+ }
+};
+
+#endif /* GCC_SPELLCHECK_TREE_H */
diff --git a/support/cpp/gcc/spellcheck.cc b/support/cpp/gcc/spellcheck.cc
new file mode 100644
index 000000000..3e58344f5
--- /dev/null
+++ b/support/cpp/gcc/spellcheck.cc
@@ -0,0 +1,529 @@
+/* Find near-matches for strings.
+ Copyright (C) 2015-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 "tree.h"
+#include "spellcheck.h"
+#include "selftest.h"
+
+/* Cost of a case transformation. */
+#define CASE_COST 1
+
+/* Cost of another kind of edit. */
+#define BASE_COST 2
+
+/* Get the edit distance between the two strings: the minimal
+ number of edits that are needed to change one string into another,
+ where edits can be one-character insertions, removals, or substitutions,
+ or transpositions of two adjacent characters (counting as one "edit").
+
+ This implementation uses a modified variant of the Wagner-Fischer
+ algorithm for the Damerau-Levenshtein distance; specifically, the
+ "optimal string alignment distance" or "restricted edit distance"
+ variant. This implementation has been further modified to take
+ case into account. */
+
+edit_distance_t
+get_edit_distance (const char *s, int len_s,
+ const char *t, int len_t)
+{
+ const bool debug = false;
+
+ if (debug)
+ {
+ printf ("s: \"%s\" (len_s=%i)\n", s, len_s);
+ printf ("t: \"%s\" (len_t=%i)\n", t, len_t);
+ }
+
+ if (len_s == 0)
+ return BASE_COST * len_t;
+ if (len_t == 0)
+ return BASE_COST * len_s;
+
+ /* We effectively build a matrix where each (i, j) contains the
+ distance between the prefix strings s[0:j] and t[0:i].
+ Rather than actually build an (len_t + 1) * (len_s + 1) matrix,
+ we simply keep track of the last two rows, v_one_ago and v_two_ago,
+ and a new row, v_next, which avoids an (len_t + 1) * (len_s + 1)
+ allocation and memory accesses in favor of three (len_s + 1)
+ allocations. These could potentially be
+ statically-allocated if we impose a maximum length on the
+ strings of interest. */
+ edit_distance_t *v_two_ago = new edit_distance_t[len_s + 1];
+ edit_distance_t *v_one_ago = new edit_distance_t[len_s + 1];
+ edit_distance_t *v_next = new edit_distance_t[len_s + 1];
+
+ /* The first row is for the case of an empty target string, which
+ we can reach by deleting every character in the source string. */
+ for (int i = 0; i < len_s + 1; i++)
+ v_one_ago[i] = i * BASE_COST;
+
+ /* Build successive rows. */
+ for (int i = 0; i < len_t; i++)
+ {
+ if (debug)
+ {
+ printf ("i:%i v_one_ago = ", i);
+ for (int j = 0; j < len_s + 1; j++)
+ printf ("%i ", v_one_ago[j]);
+ printf ("\n");
+ }
+
+ /* The initial column is for the case of an empty source string; we
+ can reach prefixes of the target string of length i
+ by inserting i characters. */
+ v_next[0] = (i + 1) * BASE_COST;
+
+ /* Build the rest of the row by considering neighbors to
+ the north, west and northwest. */
+ for (int j = 0; j < len_s; j++)
+ {
+ edit_distance_t cost;
+
+ if (s[j] == t[i])
+ cost = 0;
+ else if (TOLOWER (s[j]) == TOLOWER (t[i]))
+ cost = CASE_COST;
+ else
+ cost = BASE_COST;
+ edit_distance_t deletion = v_next[j] + BASE_COST;
+ edit_distance_t insertion = v_one_ago[j + 1] + BASE_COST;
+ edit_distance_t substitution = v_one_ago[j] + cost;
+ edit_distance_t cheapest = MIN (deletion, insertion);
+ cheapest = MIN (cheapest, substitution);
+ if (i > 0 && j > 0 && s[j] == t[i - 1] && s[j - 1] == t[i])
+ {
+ edit_distance_t transposition = v_two_ago[j - 1] + BASE_COST;
+ cheapest = MIN (cheapest, transposition);
+ }
+ v_next[j + 1] = cheapest;
+ }
+
+ /* Prepare to move on to next row. */
+ for (int j = 0; j < len_s + 1; j++)
+ {
+ v_two_ago[j] = v_one_ago[j];
+ v_one_ago[j] = v_next[j];
+ }
+ }
+
+ if (debug)
+ {
+ printf ("final v_next = ");
+ for (int j = 0; j < len_s + 1; j++)
+ printf ("%i ", v_next[j]);
+ printf ("\n");
+ }
+
+ edit_distance_t result = v_next[len_s];
+ delete[] v_two_ago;
+ delete[] v_one_ago;
+ delete[] v_next;
+ return result;
+}
+
+/* Get the edit distance between two nil-terminated strings. */
+
+edit_distance_t
+get_edit_distance (const char *s, const char *t)
+{
+ return get_edit_distance (s, strlen (s), t, strlen (t));
+}
+
+/* Given TARGET, a non-NULL string, and CANDIDATES, a non-NULL ptr to
+ an autovec of non-NULL strings, determine which element within
+ CANDIDATES has the lowest edit distance to TARGET. If there are
+ multiple elements with the same minimal distance, the first in the
+ vector wins.
+
+ If more than half of the letters were misspelled, the suggestion is
+ likely to be meaningless, so return NULL for this case. */
+
+const char *
+find_closest_string (const char *target,
+ const auto_vec<const char *> *candidates)
+{
+ gcc_assert (target);
+ gcc_assert (candidates);
+
+ int i;
+ const char *candidate;
+ best_match<const char *, const char *> bm (target);
+ FOR_EACH_VEC_ELT (*candidates, i, candidate)
+ {
+ gcc_assert (candidate);
+ bm.consider (candidate);
+ }
+
+ return bm.get_best_meaningful_candidate ();
+}
+
+/* Generate the maximum edit distance for which we consider a suggestion
+ to be meaningful, given a goal of length GOAL_LEN and a candidate of
+ length CANDIDATE_LEN.
+
+ This is a third of the length of the candidate or of the goal,
+ whichever is bigger. */
+
+edit_distance_t
+get_edit_distance_cutoff (size_t goal_len, size_t candidate_len)
+{
+ size_t max_length = MAX (goal_len, candidate_len);
+ size_t min_length = MIN (goal_len, candidate_len);
+
+ gcc_assert (max_length >= min_length);
+
+ /* Special case: don't offer suggestions for a pair of
+ length == 1 strings (or empty strings). */
+ if (max_length <= 1)
+ return 0;
+
+ /* If the lengths are close, then round down. */
+ if (max_length - min_length <= 1)
+ /* ...but allow an edit distance of at least 1. */
+ return BASE_COST * MAX (max_length / 3, 1);
+
+ /* Otherwise, round up (thus giving a little extra leeway to some cases
+ involving insertions/deletions). */
+ return BASE_COST * (max_length + 2) / 3;
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests. */
+
+/* Verify that get_edit_distance (A, B) equals the expected value. */
+
+static void
+test_get_edit_distance_one_way (const char *a, const char *b,
+ edit_distance_t expected)
+{
+ edit_distance_t actual = get_edit_distance (a, b);
+ ASSERT_EQ (actual, expected);
+}
+
+/* Verify that both
+ get_edit_distance (A, B)
+ and
+ get_edit_distance (B, A)
+ equal the expected value, to ensure that the function is symmetric. */
+
+static void
+test_get_edit_distance_both_ways (const char *a, const char *b,
+ edit_distance_t expected)
+{
+ test_get_edit_distance_one_way (a, b, expected);
+ test_get_edit_distance_one_way (b, a, expected);
+}
+
+/* Verify get_edit_distance for a variety of pairs of pre-canned
+ inputs, comparing against known-good values. */
+
+static void
+test_edit_distances ()
+{
+ test_get_edit_distance_both_ways ("", "nonempty",
+ BASE_COST * strlen ("nonempty"));
+ test_get_edit_distance_both_ways ("saturday", "sunday",
+ BASE_COST * 3);
+ test_get_edit_distance_both_ways ("foo", "m_foo", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("hello_world", "HelloWorld", 4);
+ test_get_edit_distance_both_ways
+ ("the quick brown fox jumps over the lazy dog", "dog", BASE_COST * 40);
+ test_get_edit_distance_both_ways
+ ("the quick brown fox jumps over the lazy dog",
+ "the quick brown dog jumps over the lazy fox",
+ BASE_COST * 4);
+ test_get_edit_distance_both_ways
+ ("Lorem ipsum dolor sit amet, consectetur adipiscing elit,",
+ "All your base are belong to us",
+ BASE_COST * 44);
+ test_get_edit_distance_both_ways ("foo", "FOO", 3);
+ test_get_edit_distance_both_ways ("fee", "deed", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("coorzd1", "coordx1", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("assert", "sqrt", BASE_COST * 3);
+ test_get_edit_distance_both_ways ("PATH_MAX", "INT8_MAX", BASE_COST * 3);
+ test_get_edit_distance_both_ways ("time", "nice", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("bar", "carg", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("gtk_widget_show_all",
+ "GtkWidgetShowAll", 10);
+ test_get_edit_distance_both_ways ("m_bar", "bar", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("MACRO", "MACRAME", BASE_COST * 3);
+ test_get_edit_distance_both_ways ("ab", "ac", BASE_COST * 1);
+ test_get_edit_distance_both_ways ("ab", "a", BASE_COST * 1);
+ test_get_edit_distance_both_ways ("a", "b", BASE_COST * 1);
+ test_get_edit_distance_both_ways ("nanl", "name", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("char", "bar", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("-optimize", "fsanitize", BASE_COST * 5);
+ test_get_edit_distance_both_ways ("__DATE__", "__i386__", BASE_COST * 4);
+
+ /* Examples where transposition helps. */
+ test_get_edit_distance_both_ways ("ab", "ba", BASE_COST * 1);
+ test_get_edit_distance_both_ways ("ba", "abc", BASE_COST * 2);
+ test_get_edit_distance_both_ways ("coorzd1", "coordz1", BASE_COST * 1);
+ test_get_edit_distance_both_ways ("abcdefghijklmnopqrstuvwxyz",
+ "bacdefghijklmnopqrstuvwxzy",
+ BASE_COST * 2);
+ test_get_edit_distance_both_ways ("saturday", "sundya", BASE_COST * 4);
+ test_get_edit_distance_both_ways ("signed", "singed", BASE_COST * 1);
+}
+
+/* Subroutine of test_get_edit_distance_cutoff, for emulating the
+ spellchecking cutoff in up to GCC 8. */
+
+static edit_distance_t
+get_old_cutoff (size_t goal_len, size_t candidate_len)
+{
+ return BASE_COST * MAX (goal_len, candidate_len) / 2;
+}
+
+/* Verify that the cutoff for "meaningfulness" of suggestions is at least as
+ conservative as in older GCC releases.
+
+ This should ensure that we don't offer additional meaningless
+ suggestions (apart from those for which transposition has helped). */
+
+static void
+test_get_edit_distance_cutoff ()
+{
+ for (size_t goal_len = 0; goal_len < 30; goal_len++)
+ for (size_t candidate_len = 0; candidate_len < 30; candidate_len++)
+ ASSERT_TRUE (get_edit_distance_cutoff (goal_len, candidate_len)
+ <= get_old_cutoff (goal_len, candidate_len));
+}
+
+/* Assert that CANDIDATE is offered as a suggestion for TARGET. */
+
+static void
+assert_suggested_for (const location &loc, const char *candidate,
+ const char *target)
+{
+ auto_vec<const char *> candidates;
+ candidates.safe_push (candidate);
+ ASSERT_EQ_AT (loc, candidate, find_closest_string (target, &candidates));
+}
+
+/* Assert that CANDIDATE is offered as a suggestion for TARGET. */
+
+#define ASSERT_SUGGESTED_FOR(CANDIDATE, TARGET) \
+ SELFTEST_BEGIN_STMT \
+ assert_suggested_for (SELFTEST_LOCATION, CANDIDATE, TARGET); \
+ SELFTEST_END_STMT
+
+/* Assert that CANDIDATE is not offered as a suggestion for TARGET. */
+
+static void
+assert_not_suggested_for (const location &loc, const char *candidate,
+ const char *target)
+{
+ auto_vec<const char *> candidates;
+ candidates.safe_push (candidate);
+ ASSERT_EQ_AT (loc, NULL, find_closest_string (target, &candidates));
+}
+
+/* Assert that CANDIDATE is not offered as a suggestion for TARGET. */
+
+#define ASSERT_NOT_SUGGESTED_FOR(CANDIDATE, TARGET) \
+ SELFTEST_BEGIN_STMT \
+ assert_not_suggested_for (SELFTEST_LOCATION, CANDIDATE, TARGET); \
+ SELFTEST_END_STMT
+
+/* Verify that we offer varous suggestions that are meaningful,
+ and that we don't offer various other ones that aren't (PR c/82967). */
+
+static void
+test_suggestions ()
+{
+ /* Good suggestions. */
+
+ ASSERT_SUGGESTED_FOR ("m_bar", "bar");
+ // dist == 2, max_length == 5, min_length == 3
+
+ ASSERT_SUGGESTED_FOR ("MACRO", "MACRAME");
+ // dist == 3, max_length == 7, min_length == 5
+
+ ASSERT_SUGGESTED_FOR ("gtk_widget_show_all", "GtkWidgetShowAll");
+ // dist == 7, max_length == 16, min_length = 19
+
+ ASSERT_SUGGESTED_FOR ("ab", "ac");
+ // dist == 1, max_length == min_length = 2
+
+ ASSERT_SUGGESTED_FOR ("ab", "a");
+ // dist == 1, max_length == 2, min_length = 1
+
+ /* Bad suggestions. */
+
+ ASSERT_NOT_SUGGESTED_FOR ("a", "b");
+ // dist == 1, max_length == min_length = 1
+
+ ASSERT_NOT_SUGGESTED_FOR ("sqrt", "assert");
+ // dist == 3, max_length 6, min_length == 4
+
+ ASSERT_NOT_SUGGESTED_FOR ("INT8_MAX", "PATH_MAX");
+ // dist == 3, max_length == min_length == 8
+
+ ASSERT_NOT_SUGGESTED_FOR ("nice", "time");
+ ASSERT_NOT_SUGGESTED_FOR ("nanl", "name");
+ // dist == 2, max_length == min_length == 4
+
+ ASSERT_NOT_SUGGESTED_FOR ("carg", "bar");
+ ASSERT_NOT_SUGGESTED_FOR ("char", "bar");
+ // dist == 2, max_length == 4, min_length == 3
+
+ ASSERT_NOT_SUGGESTED_FOR ("-optimize", "fsanitize");
+ // dist == 5, max_length == min_length == 9
+
+ ASSERT_NOT_SUGGESTED_FOR ("__DATE__", "__i386__");
+ // dist == 4, max_length == min_length == 8
+
+ ASSERT_NOT_SUGGESTED_FOR ("start_input_device", "InputDevice");
+ // dist == 9, max_length == 18, min_length == 11
+}
+
+/* Verify that find_closest_string is sane. */
+
+static void
+test_find_closest_string ()
+{
+ auto_vec<const char *> candidates;
+
+ /* Verify that it can handle an empty vec. */
+ ASSERT_EQ (NULL, find_closest_string ("", &candidates));
+
+ /* Verify that it works sanely for non-empty vecs. */
+ candidates.safe_push ("apple");
+ candidates.safe_push ("banana");
+ candidates.safe_push ("cherry");
+
+ ASSERT_STREQ ("apple", find_closest_string ("app", &candidates));
+ ASSERT_STREQ ("banana", find_closest_string ("banyan", &candidates));
+ ASSERT_STREQ ("cherry", find_closest_string ("berry", &candidates));
+ ASSERT_EQ (NULL, find_closest_string ("not like the others", &candidates));
+
+ /* The order of the vec can matter, but it should not matter for these
+ inputs. */
+ candidates.truncate (0);
+ candidates.safe_push ("cherry");
+ candidates.safe_push ("banana");
+ candidates.safe_push ("apple");
+ ASSERT_STREQ ("apple", find_closest_string ("app", &candidates));
+ ASSERT_STREQ ("banana", find_closest_string ("banyan", &candidates));
+ ASSERT_STREQ ("cherry", find_closest_string ("berry", &candidates));
+ ASSERT_EQ (NULL, find_closest_string ("not like the others", &candidates));
+
+ /* If the goal string somehow makes it into the candidate list, offering
+ it as a suggestion will be nonsensical. Verify that we don't offer such
+ suggestions. */
+ ASSERT_EQ (NULL, find_closest_string ("banana", &candidates));
+
+ /* Example from PR 69968 where transposition helps. */
+ candidates.truncate (0);
+ candidates.safe_push("coordx");
+ candidates.safe_push("coordy");
+ candidates.safe_push("coordz");
+ candidates.safe_push("coordx1");
+ candidates.safe_push("coordy1");
+ candidates.safe_push("coordz1");
+ ASSERT_STREQ ("coordz1", find_closest_string ("coorzd1", &candidates));
+
+ candidates.truncate (0);
+ candidates.safe_push ("DWARF_GNAT_ENCODINGS_GDB");
+ candidates.safe_push ("DWARF_GNAT_ENCODINGS_ALL");
+ candidates.safe_push ("DWARF_GNAT_ENCODINGS_MINIMAL");
+ ASSERT_STREQ ("DWARF_GNAT_ENCODINGS_ALL",
+ find_closest_string ("DWARF_GNAT_ENCODINGS_all",
+ &candidates));
+
+ /* The same as the previous test, but with a different order of
+ candidates. */
+ candidates.truncate (0);
+ candidates.safe_push ("DWARF_GNAT_ENCODINGS_ALL");
+ candidates.safe_push ("DWARF_GNAT_ENCODINGS_GDB");
+ candidates.safe_push ("DWARF_GNAT_ENCODINGS_MINIMAL");
+ ASSERT_STREQ ("DWARF_GNAT_ENCODINGS_ALL",
+ find_closest_string ("DWARF_GNAT_ENCODINGS_all",
+ &candidates));
+}
+
+/* Test data for test_metric_conditions. */
+
+static const char * const test_data[] = {
+ "",
+ "foo",
+ "food",
+ "boo",
+ "1234567890123456789012345678901234567890123456789012345678901234567890",
+ "abc",
+ "ac",
+ "ca",
+};
+
+/* Verify that get_edit_distance appears to be a sane distance function,
+ even though it doesn't satisfy the conditions for being a metric. (This
+ is because the triangle inequality fails to hold: the distance between
+ "ca" and "ac" is 1, and so is the distance between "abc" and "ac", but
+ the distance between "abc" and "ca" is 3. Algorithms that calculate the
+ true Levenshtein-Damerau metric are much more expensive.) */
+
+static void
+test_metric_conditions ()
+{
+ const int num_test_cases = sizeof (test_data) / sizeof (test_data[0]);
+
+ for (int i = 0; i < num_test_cases; i++)
+ {
+ for (int j = 0; j < num_test_cases; j++)
+ {
+ edit_distance_t dist_ij
+ = get_edit_distance (test_data[i], test_data[j]);
+
+ /* Identity of indiscernibles: d(i, j) > 0 iff i == j. */
+ if (i == j)
+ ASSERT_EQ (dist_ij, 0);
+ else
+ ASSERT_TRUE (dist_ij > 0);
+
+ /* Symmetry: d(i, j) == d(j, i). */
+ edit_distance_t dist_ji
+ = get_edit_distance (test_data[j], test_data[i]);
+ ASSERT_EQ (dist_ij, dist_ji);
+ }
+ }
+}
+
+/* Run all of the selftests within this file. */
+
+void
+spellcheck_cc_tests ()
+{
+ test_edit_distances ();
+ test_get_edit_distance_cutoff ();
+ test_suggestions ();
+ test_find_closest_string ();
+ test_metric_conditions ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/support/cpp/gcc/spellcheck.h b/support/cpp/gcc/spellcheck.h
new file mode 100644
index 000000000..c5a47d442
--- /dev/null
+++ b/support/cpp/gcc/spellcheck.h
@@ -0,0 +1,221 @@
+/* Find near-matches for strings and identifiers.
+ Copyright (C) 2015-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_SPELLCHECK_H
+#define GCC_SPELLCHECK_H
+
+typedef unsigned int edit_distance_t;
+const edit_distance_t MAX_EDIT_DISTANCE = UINT_MAX;
+
+/* spellcheck.cc */
+extern edit_distance_t
+get_edit_distance (const char *s, int len_s,
+ const char *t, int len_t);
+
+extern edit_distance_t
+get_edit_distance (const char *s, const char *t);
+
+extern const char *
+find_closest_string (const char *target,
+ const auto_vec<const char *> *candidates);
+
+/* A traits class for describing a string-like type usable by
+ class best_match.
+ Specializations should provide the implementations of the following:
+
+ static size_t get_length (TYPE);
+ static const char *get_string (TYPE);
+
+ get_string should return a non-NULL ptr, which does not need to be
+ 0-terminated. */
+
+template <typename TYPE>
+struct edit_distance_traits {
+ static size_t get_length (TYPE const&)
+ {
+ gcc_assert (0);
+ return 0;
+ }
+ static const char *get_string (TYPE const&)
+ {
+ gcc_assert (0);
+ return 0;
+ }
+};
+
+/* Specialization of edit_distance_traits for C-style strings. */
+
+template <>
+struct edit_distance_traits<const char *>
+{
+ static size_t get_length (const char *str)
+ {
+ gcc_assert (str);
+ return strlen (str);
+ }
+
+ static const char *get_string (const char *str)
+ {
+ gcc_assert (str);
+ return str;
+ }
+};
+
+extern edit_distance_t get_edit_distance_cutoff (size_t goal_len,
+ size_t candidate_len);
+
+/* A type for use when determining the best match against a string,
+ expressed as a template so that we can match against various
+ string-like types (const char *, frontend identifiers, and preprocessor
+ macros).
+
+ This type accumulates the best possible match against GOAL_TYPE for
+ a sequence of elements of CANDIDATE_TYPE, whilst minimizing the
+ number of calls to get_edit_distance and to
+ edit_distance_traits<T>::get_length. */
+
+template <typename GOAL_TYPE, typename CANDIDATE_TYPE>
+class best_match
+{
+ public:
+ typedef GOAL_TYPE goal_t;
+ typedef CANDIDATE_TYPE candidate_t;
+ typedef edit_distance_traits<goal_t> goal_traits;
+ typedef edit_distance_traits<candidate_t> candidate_traits;
+
+ /* Constructor. */
+
+ best_match (GOAL_TYPE goal,
+ edit_distance_t best_distance_so_far = MAX_EDIT_DISTANCE)
+ : 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)
+ {}
+
+ /* Compare the edit distance between CANDIDATE and m_goal,
+ and if it's the best so far, record it. */
+
+ void consider (candidate_t candidate)
+ {
+ size_t candidate_len = candidate_traits::get_length (candidate);
+
+ /* Calculate a lower bound on the candidate's distance to the goal,
+ based on the difference in lengths; it will require at least
+ this many insertions/deletions. */
+ edit_distance_t min_candidate_distance
+ = abs ((ssize_t)candidate_len - (ssize_t)m_goal_len);
+
+ /* If the candidate's length is sufficiently different to that
+ of the goal string, then the number of insertions/deletions
+ may be >= the best distance so far. If so, we can reject
+ the candidate immediately without needing to compute
+ the exact distance, since it won't be an improvement. */
+ if (min_candidate_distance >= m_best_distance)
+ return;
+
+ /* If the candidate will be unable to beat the criterion in
+ get_best_meaningful_candidate, reject it without computing
+ the exact distance. */
+ edit_distance_t cutoff = get_cutoff (candidate_len);
+ if (min_candidate_distance > cutoff)
+ return;
+
+ /* Otherwise, compute the distance and see if the candidate
+ has beaten the previous best value. */
+ edit_distance_t dist
+ = get_edit_distance (m_goal, m_goal_len,
+ candidate_traits::get_string (candidate),
+ candidate_len);
+ if (dist < m_best_distance)
+ {
+ m_best_distance = dist;
+ m_best_candidate = candidate;
+ m_best_candidate_len = candidate_len;
+ }
+ }
+
+ /* Assuming that BEST_CANDIDATE is known to be better than
+ m_best_candidate, update (without recomputing the edit distance to
+ the goal). */
+
+ void set_best_so_far (CANDIDATE_TYPE best_candidate,
+ edit_distance_t best_distance,
+ size_t best_candidate_len)
+ {
+ gcc_assert (best_distance < m_best_distance);
+ m_best_candidate = best_candidate;
+ m_best_distance = best_distance;
+ m_best_candidate_len = best_candidate_len;
+ }
+
+ /* Generate the maximum edit distance for which we consider a suggestion
+ to be meaningful, given a candidate of length CANDIDATE_LEN. */
+
+ edit_distance_t get_cutoff (size_t candidate_len) const
+ {
+ return ::get_edit_distance_cutoff (m_goal_len, candidate_len);
+ }
+
+ /* Get the best candidate so far, but applying a filter to ensure
+ that we return NULL if none of the candidates are close to the goal,
+ to avoid offering nonsensical suggestions to the user. */
+
+ candidate_t get_best_meaningful_candidate () const
+ {
+ /* If the edit distance is too high, the suggestion is likely to be
+ meaningless. */
+ if (m_best_candidate)
+ {
+ edit_distance_t cutoff = get_cutoff (m_best_candidate_len);
+ if (m_best_distance > cutoff)
+ return NULL;
+ }
+
+ /* If the goal string somehow makes it into the candidate list, offering
+ it as a suggestion will be nonsensical e.g.
+ 'constexpr' does not name a type; did you mean 'constexpr'?
+ Ultimately such suggestions are due to bugs in constructing the
+ candidate list, but as a band-aid, do not offer suggestions for
+ distance == 0 (where candidate == goal). */
+ if (m_best_distance == 0)
+ return NULL;
+
+ return m_best_candidate;
+ }
+
+ /* Get the closest candidate so far, without applying any filtering. */
+
+ candidate_t blithely_get_best_candidate () const
+ {
+ return m_best_candidate;
+ }
+
+ edit_distance_t get_best_distance () const { return m_best_distance; }
+ size_t get_best_candidate_length () const { return m_best_candidate_len; }
+
+ private:
+ const 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;
+};
+
+#endif /* GCC_SPELLCHECK_H */
diff --git a/support/cpp/gcc/ssa-iterators.h b/support/cpp/gcc/ssa-iterators.h
new file mode 100644
index 000000000..0a52e8283
--- /dev/null
+++ b/support/cpp/gcc/ssa-iterators.h
@@ -0,0 +1,1013 @@
+/* Header file for SSA iterators.
+ Copyright (C) 2013-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/>. */
+
+#if 0 // sdcpp ndef GCC_SSA_ITERATORS_H
+#define GCC_SSA_ITERATORS_H
+
+/* Immediate use lists are used to directly access all uses for an SSA
+ name and get pointers to the statement for each use.
+
+ The structure ssa_use_operand_t consists of PREV and NEXT pointers
+ to maintain the list. A USE pointer, which points to address where
+ the use is located and a LOC pointer which can point to the
+ statement where the use is located, or, in the case of the root
+ node, it points to the SSA name itself.
+
+ The list is anchored by an occurrence of ssa_operand_d *in* the
+ ssa_name node itself (named 'imm_uses'). This node is uniquely
+ identified by having a NULL USE pointer. and the LOC pointer
+ pointing back to the ssa_name node itself. This node forms the
+ base for a circular list, and initially this is the only node in
+ the list.
+
+ Fast iteration allows each use to be examined, but does not allow
+ any modifications to the uses or stmts.
+
+ Normal iteration allows insertion, deletion, and modification. the
+ iterator manages this by inserting a marker node into the list
+ immediately before the node currently being examined in the list.
+ this marker node is uniquely identified by having null stmt *and* a
+ null use pointer.
+
+ When iterating to the next use, the iteration routines check to see
+ if the node after the marker has changed. if it has, then the node
+ following the marker is now the next one to be visited. if not, the
+ marker node is moved past that node in the list (visualize it as
+ bumping the marker node through the list). this continues until
+ the marker node is moved to the original anchor position. the
+ marker node is then removed from the list.
+
+ If iteration is halted early, the marker node must be removed from
+ the list before continuing. */
+struct imm_use_iterator
+{
+ /* This is the current use the iterator is processing. */
+ ssa_use_operand_t *imm_use;
+ /* This marks the last use in the list (use node from SSA_NAME) */
+ ssa_use_operand_t *end_p;
+ /* This node is inserted and used to mark the end of the uses for a stmt. */
+ ssa_use_operand_t iter_node;
+ /* This is the next ssa_name to visit. IMM_USE may get removed before
+ the next one is traversed to, so it must be cached early. */
+ ssa_use_operand_t *next_imm_name;
+};
+
+
+/* Use this iterator when simply looking at stmts. Adding, deleting or
+ modifying stmts will cause this iterator to malfunction. */
+
+#define FOR_EACH_IMM_USE_FAST(DEST, ITER, SSAVAR) \
+ for ((DEST) = first_readonly_imm_use (&(ITER), (SSAVAR)); \
+ !end_readonly_imm_use_p (&(ITER)); \
+ (void) ((DEST) = next_readonly_imm_use (&(ITER))))
+
+/* Forward declare for use in the class below. */
+static inline void end_imm_use_stmt_traverse (imm_use_iterator *);
+
+/* arrange to automatically call, upon descruction, end_imm_use_stmt_traverse
+ with a given pointer to imm_use_iterator. */
+struct auto_end_imm_use_stmt_traverse
+{
+ imm_use_iterator *imm;
+ auto_end_imm_use_stmt_traverse (imm_use_iterator *imm)
+ : imm (imm) {}
+ ~auto_end_imm_use_stmt_traverse ()
+ { end_imm_use_stmt_traverse (imm); }
+};
+
+/* Use this iterator to visit each stmt which has a use of SSAVAR. The
+ destructor of the auto_end_imm_use_stmt_traverse object deals with removing
+ ITER from SSAVAR's IMM_USE list even when leaving the scope early. */
+
+#define FOR_EACH_IMM_USE_STMT(STMT, ITER, SSAVAR) \
+ for (struct auto_end_imm_use_stmt_traverse \
+ auto_end_imm_use_stmt_traverse \
+ ((((STMT) = first_imm_use_stmt (&(ITER), (SSAVAR))), \
+ &(ITER))); \
+ !end_imm_use_stmt_p (&(ITER)); \
+ (void) ((STMT) = next_imm_use_stmt (&(ITER))))
+
+/* Use this iterator in combination with FOR_EACH_IMM_USE_STMT to
+ get access to each occurrence of ssavar on the stmt returned by
+ that iterator.. for instance:
+
+ FOR_EACH_IMM_USE_STMT (stmt, iter, ssavar)
+ {
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ {
+ SET_USE (use_p, blah);
+ }
+ update_stmt (stmt);
+ } */
+
+#define FOR_EACH_IMM_USE_ON_STMT(DEST, ITER) \
+ for ((DEST) = first_imm_use_on_stmt (&(ITER)); \
+ !end_imm_use_on_stmt_p (&(ITER)); \
+ (void) ((DEST) = next_imm_use_on_stmt (&(ITER))))
+
+
+
+extern bool single_imm_use_1 (const ssa_use_operand_t *head,
+ use_operand_p *use_p, gimple **stmt);
+
+
+enum ssa_op_iter_type {
+ ssa_op_iter_none = 0,
+ ssa_op_iter_tree,
+ ssa_op_iter_use,
+ ssa_op_iter_def
+};
+
+/* This structure is used in the operand iterator loops. It contains the
+ items required to determine which operand is retrieved next. During
+ optimization, this structure is scalarized, and any unused fields are
+ optimized away, resulting in little overhead. */
+
+struct ssa_op_iter
+{
+ enum ssa_op_iter_type iter_type;
+ bool done;
+ int flags;
+ unsigned i;
+ unsigned numops;
+ use_optype_p uses;
+ gimple *stmt;
+};
+
+/* NOTE: Keep these in sync with doc/tree-ssa.texi. */
+/* These flags are used to determine which operands are returned during
+ execution of the loop. */
+#define SSA_OP_USE 0x01 /* Real USE operands. */
+#define SSA_OP_DEF 0x02 /* Real DEF operands. */
+#define SSA_OP_VUSE 0x04 /* VUSE operands. */
+#define SSA_OP_VDEF 0x08 /* VDEF operands. */
+/* These are commonly grouped operand flags. */
+#define SSA_OP_VIRTUAL_USES (SSA_OP_VUSE)
+#define SSA_OP_VIRTUAL_DEFS (SSA_OP_VDEF)
+#define SSA_OP_ALL_VIRTUALS (SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_DEFS)
+#define SSA_OP_ALL_USES (SSA_OP_VIRTUAL_USES | SSA_OP_USE)
+#define SSA_OP_ALL_DEFS (SSA_OP_VIRTUAL_DEFS | SSA_OP_DEF)
+#define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS)
+
+/* This macro executes a loop over the operands of STMT specified in FLAG,
+ returning each operand as a 'tree' in the variable TREEVAR. ITER is an
+ ssa_op_iter structure used to control the loop. */
+#define FOR_EACH_SSA_TREE_OPERAND(TREEVAR, STMT, ITER, FLAGS) \
+ for (TREEVAR = op_iter_init_tree (&(ITER), STMT, FLAGS); \
+ !op_iter_done (&(ITER)); \
+ (void) (TREEVAR = op_iter_next_tree (&(ITER))))
+
+/* This macro executes a loop over the operands of STMT specified in FLAG,
+ returning each operand as a 'use_operand_p' in the variable USEVAR.
+ ITER is an ssa_op_iter structure used to control the loop. */
+#define FOR_EACH_SSA_USE_OPERAND(USEVAR, STMT, ITER, FLAGS) \
+ for (USEVAR = op_iter_init_use (&(ITER), STMT, FLAGS); \
+ !op_iter_done (&(ITER)); \
+ USEVAR = op_iter_next_use (&(ITER)))
+
+/* This macro executes a loop over the operands of STMT specified in FLAG,
+ returning each operand as a 'def_operand_p' in the variable DEFVAR.
+ ITER is an ssa_op_iter structure used to control the loop. */
+#define FOR_EACH_SSA_DEF_OPERAND(DEFVAR, STMT, ITER, FLAGS) \
+ for (DEFVAR = op_iter_init_def (&(ITER), STMT, FLAGS); \
+ !op_iter_done (&(ITER)); \
+ DEFVAR = op_iter_next_def (&(ITER)))
+
+/* This macro will execute a loop over all the arguments of a PHI which
+ match FLAGS. A use_operand_p is always returned via USEVAR. FLAGS
+ can be either SSA_OP_USE or SSA_OP_VIRTUAL_USES or SSA_OP_ALL_USES. */
+#define FOR_EACH_PHI_ARG(USEVAR, STMT, ITER, FLAGS) \
+ for ((USEVAR) = op_iter_init_phiuse (&(ITER), STMT, FLAGS); \
+ !op_iter_done (&(ITER)); \
+ (USEVAR) = op_iter_next_use (&(ITER)))
+
+
+/* This macro will execute a loop over a stmt, regardless of whether it is
+ a real stmt or a PHI node, looking at the USE nodes matching FLAGS. */
+#define FOR_EACH_PHI_OR_STMT_USE(USEVAR, STMT, ITER, FLAGS) \
+ for ((USEVAR) = (gimple_code (STMT) == GIMPLE_PHI \
+ ? op_iter_init_phiuse (&(ITER), \
+ as_a <gphi *> (STMT), \
+ FLAGS) \
+ : op_iter_init_use (&(ITER), STMT, FLAGS)); \
+ !op_iter_done (&(ITER)); \
+ (USEVAR) = op_iter_next_use (&(ITER)))
+
+/* This macro will execute a loop over a stmt, regardless of whether it is
+ a real stmt or a PHI node, looking at the DEF nodes matching FLAGS. */
+#define FOR_EACH_PHI_OR_STMT_DEF(DEFVAR, STMT, ITER, FLAGS) \
+ for ((DEFVAR) = (gimple_code (STMT) == GIMPLE_PHI \
+ ? op_iter_init_phidef (&(ITER), \
+ as_a <gphi *> (STMT), \
+ FLAGS) \
+ : op_iter_init_def (&(ITER), STMT, FLAGS)); \
+ !op_iter_done (&(ITER)); \
+ (DEFVAR) = op_iter_next_def (&(ITER)))
+
+/* This macro returns an operand in STMT as a tree if it is the ONLY
+ operand matching FLAGS. If there are 0 or more than 1 operand matching
+ FLAGS, then NULL_TREE is returned. */
+#define SINGLE_SSA_TREE_OPERAND(STMT, FLAGS) \
+ single_ssa_tree_operand (STMT, FLAGS)
+
+/* This macro returns an operand in STMT as a use_operand_p if it is the ONLY
+ operand matching FLAGS. If there are 0 or more than 1 operand matching
+ FLAGS, then NULL_USE_OPERAND_P is returned. */
+#define SINGLE_SSA_USE_OPERAND(STMT, FLAGS) \
+ single_ssa_use_operand (STMT, FLAGS)
+
+/* This macro returns an operand in STMT as a def_operand_p if it is the ONLY
+ operand matching FLAGS. If there are 0 or more than 1 operand matching
+ FLAGS, then NULL_DEF_OPERAND_P is returned. */
+#define SINGLE_SSA_DEF_OPERAND(STMT, FLAGS) \
+ single_ssa_def_operand (STMT, FLAGS)
+
+/* This macro returns TRUE if there are no operands matching FLAGS in STMT. */
+#define ZERO_SSA_OPERANDS(STMT, FLAGS) zero_ssa_operands (STMT, FLAGS)
+
+/* This macro counts the number of operands in STMT matching FLAGS. */
+#define NUM_SSA_OPERANDS(STMT, FLAGS) num_ssa_operands (STMT, FLAGS)
+
+
+/* Delink an immediate_uses node from its chain. */
+static inline void
+delink_imm_use (ssa_use_operand_t *linknode)
+{
+ /* Return if this node is not in a list. */
+ if (linknode->prev == NULL)
+ return;
+
+ linknode->prev->next = linknode->next;
+ linknode->next->prev = linknode->prev;
+ linknode->prev = NULL;
+ linknode->next = NULL;
+}
+
+/* Link ssa_imm_use node LINKNODE into the chain for LIST. */
+static inline void
+link_imm_use_to_list (ssa_use_operand_t *linknode, ssa_use_operand_t *list)
+{
+ /* Link the new node at the head of the list. If we are in the process of
+ traversing the list, we won't visit any new nodes added to it. */
+ linknode->prev = list;
+ linknode->next = list->next;
+ list->next->prev = linknode;
+ list->next = linknode;
+}
+
+/* Link ssa_imm_use node LINKNODE into the chain for DEF. */
+static inline void
+link_imm_use (ssa_use_operand_t *linknode, tree def)
+{
+ ssa_use_operand_t *root;
+
+ if (!def || TREE_CODE (def) != SSA_NAME)
+ linknode->prev = NULL;
+ else
+ {
+ root = &(SSA_NAME_IMM_USE_NODE (def));
+ if (linknode->use)
+ gcc_checking_assert (*(linknode->use) == def);
+ link_imm_use_to_list (linknode, root);
+ }
+}
+
+/* Set the value of a use pointed to by USE to VAL. */
+static inline void
+set_ssa_use_from_ptr (use_operand_p use, tree val)
+{
+ delink_imm_use (use);
+ *(use->use) = val;
+ link_imm_use (use, val);
+}
+
+/* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occurring
+ in STMT. */
+static inline void
+link_imm_use_stmt (ssa_use_operand_t *linknode, tree def, gimple *stmt)
+{
+ if (stmt)
+ link_imm_use (linknode, def);
+ else
+ link_imm_use (linknode, NULL);
+ linknode->loc.stmt = stmt;
+}
+
+/* Relink a new node in place of an old node in the list. */
+static inline void
+relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old)
+{
+ /* The node one had better be in the same list. */
+ gcc_checking_assert (*(old->use) == *(node->use));
+ node->prev = old->prev;
+ node->next = old->next;
+ if (old->prev)
+ {
+ old->prev->next = node;
+ old->next->prev = node;
+ /* Remove the old node from the list. */
+ old->prev = NULL;
+ }
+}
+
+/* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occurring
+ in STMT. */
+static inline void
+relink_imm_use_stmt (ssa_use_operand_t *linknode, ssa_use_operand_t *old,
+ gimple *stmt)
+{
+ if (stmt)
+ relink_imm_use (linknode, old);
+ else
+ link_imm_use (linknode, NULL);
+ linknode->loc.stmt = stmt;
+}
+
+
+/* Return true is IMM has reached the end of the immediate use list. */
+static inline bool
+end_readonly_imm_use_p (const imm_use_iterator *imm)
+{
+ return (imm->imm_use == imm->end_p);
+}
+
+/* Initialize iterator IMM to process the list for VAR. */
+static inline use_operand_p
+first_readonly_imm_use (imm_use_iterator *imm, tree var)
+{
+ imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
+ imm->imm_use = imm->end_p->next;
+ imm->iter_node.next = imm->imm_use->next;
+ if (end_readonly_imm_use_p (imm))
+ return NULL_USE_OPERAND_P;
+ return imm->imm_use;
+}
+
+/* Bump IMM to the next use in the list. */
+static inline use_operand_p
+next_readonly_imm_use (imm_use_iterator *imm)
+{
+ use_operand_p old = imm->imm_use;
+
+ /* If this assertion fails, it indicates the 'next' pointer has changed
+ since the last bump. This indicates that the list is being modified
+ via stmt changes, or SET_USE, or somesuch thing, and you need to be
+ using the SAFE version of the iterator. */
+ if (flag_checking)
+ {
+ gcc_assert (imm->iter_node.next == old->next);
+ imm->iter_node.next = old->next->next;
+ }
+
+ imm->imm_use = old->next;
+ if (end_readonly_imm_use_p (imm))
+ return NULL_USE_OPERAND_P;
+ return imm->imm_use;
+}
+
+
+/* Return true if VAR has no nondebug uses. */
+static inline bool
+has_zero_uses (const_tree var)
+{
+ const ssa_use_operand_t *const head = &(SSA_NAME_IMM_USE_NODE (var));
+ const ssa_use_operand_t *ptr;
+
+ for (ptr = head->next; ptr != head; ptr = ptr->next)
+ if (USE_STMT (ptr) && !is_gimple_debug (USE_STMT (ptr)))
+ return false;
+
+ return true;
+}
+
+/* Return true if VAR has a single nondebug use. */
+static inline bool
+has_single_use (const_tree var)
+{
+ const ssa_use_operand_t *const head = &(SSA_NAME_IMM_USE_NODE (var));
+ const ssa_use_operand_t *ptr;
+ bool single = false;
+
+ for (ptr = head->next; ptr != head; ptr = ptr->next)
+ if (USE_STMT(ptr) && !is_gimple_debug (USE_STMT (ptr)))
+ {
+ if (single)
+ return false;
+ else
+ single = true;
+ }
+
+ return single;
+}
+
+/* If VAR has only a single immediate nondebug use, return true, and
+ set USE_P and STMT to the use pointer and stmt of occurrence. */
+static inline bool
+single_imm_use (const_tree var, use_operand_p *use_p, gimple **stmt)
+{
+ const ssa_use_operand_t *const ptr = &(SSA_NAME_IMM_USE_NODE (var));
+
+ /* If there aren't any uses whatsoever, we're done. */
+ if (ptr == ptr->next)
+ {
+ return_false:
+ *use_p = NULL_USE_OPERAND_P;
+ *stmt = NULL;
+ return false;
+ }
+
+ /* If there's a single use, check that it's not a debug stmt. */
+ if (ptr == ptr->next->next)
+ {
+ if (USE_STMT (ptr->next) && !is_gimple_debug (USE_STMT (ptr->next)))
+ {
+ *use_p = ptr->next;
+ *stmt = ptr->next->loc.stmt;
+ return true;
+ }
+ else
+ goto return_false;
+ }
+
+ return single_imm_use_1 (ptr, use_p, stmt);
+}
+
+/* Return the number of nondebug immediate uses of VAR. */
+static inline unsigned int
+num_imm_uses (const_tree var)
+{
+ const ssa_use_operand_t *const start = &(SSA_NAME_IMM_USE_NODE (var));
+ const ssa_use_operand_t *ptr;
+ unsigned int num = 0;
+
+ if (!MAY_HAVE_DEBUG_BIND_STMTS)
+ {
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ if (USE_STMT (ptr))
+ num++;
+ }
+ else
+ for (ptr = start->next; ptr != start; ptr = ptr->next)
+ if (USE_STMT (ptr) && !is_gimple_debug (USE_STMT (ptr)))
+ num++;
+
+ return num;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* The following set of routines are used to iterator over various type of
+ SSA operands. */
+
+/* Return true if PTR is finished iterating. */
+static inline bool
+op_iter_done (const ssa_op_iter *ptr)
+{
+ return ptr->done;
+}
+
+/* Get the next iterator use value for PTR. */
+static inline use_operand_p
+op_iter_next_use (ssa_op_iter *ptr)
+{
+ use_operand_p use_p;
+ gcc_checking_assert (ptr->iter_type == ssa_op_iter_use);
+ if (ptr->uses)
+ {
+ use_p = USE_OP_PTR (ptr->uses);
+ ptr->uses = ptr->uses->next;
+ return use_p;
+ }
+ if (ptr->i < ptr->numops)
+ {
+ return PHI_ARG_DEF_PTR (ptr->stmt, (ptr->i)++);
+ }
+ ptr->done = true;
+ return NULL_USE_OPERAND_P;
+}
+
+/* Get the next iterator def value for PTR. */
+static inline def_operand_p
+op_iter_next_def (ssa_op_iter *ptr)
+{
+ gcc_checking_assert (ptr->iter_type == ssa_op_iter_def);
+ if (ptr->flags & SSA_OP_VDEF)
+ {
+ tree *p;
+ ptr->flags &= ~SSA_OP_VDEF;
+ p = gimple_vdef_ptr (ptr->stmt);
+ if (p && *p)
+ return p;
+ }
+ if (ptr->flags & SSA_OP_DEF)
+ {
+ while (ptr->i < ptr->numops)
+ {
+ tree *val = gimple_op_ptr (ptr->stmt, ptr->i);
+ ptr->i++;
+ if (*val)
+ {
+ if (TREE_CODE (*val) == TREE_LIST)
+ val = &TREE_VALUE (*val);
+ if (TREE_CODE (*val) == SSA_NAME
+ || is_gimple_reg (*val))
+ return val;
+ }
+ }
+ ptr->flags &= ~SSA_OP_DEF;
+ }
+
+ ptr->done = true;
+ return NULL_DEF_OPERAND_P;
+}
+
+/* Get the next iterator tree value for PTR. */
+static inline tree
+op_iter_next_tree (ssa_op_iter *ptr)
+{
+ tree val;
+ gcc_checking_assert (ptr->iter_type == ssa_op_iter_tree);
+ if (ptr->uses)
+ {
+ val = USE_OP (ptr->uses);
+ ptr->uses = ptr->uses->next;
+ return val;
+ }
+ if (ptr->flags & SSA_OP_VDEF)
+ {
+ ptr->flags &= ~SSA_OP_VDEF;
+ if ((val = gimple_vdef (ptr->stmt)))
+ return val;
+ }
+ if (ptr->flags & SSA_OP_DEF)
+ {
+ while (ptr->i < ptr->numops)
+ {
+ val = gimple_op (ptr->stmt, ptr->i);
+ ptr->i++;
+ if (val)
+ {
+ if (TREE_CODE (val) == TREE_LIST)
+ val = TREE_VALUE (val);
+ if (TREE_CODE (val) == SSA_NAME
+ || is_gimple_reg (val))
+ return val;
+ }
+ }
+ ptr->flags &= ~SSA_OP_DEF;
+ }
+
+ ptr->done = true;
+ return NULL_TREE;
+}
+
+
+/* This functions clears the iterator PTR, and marks it done. This is normally
+ used to prevent warnings in the compile about might be uninitialized
+ components. */
+
+static inline void
+clear_and_done_ssa_iter (ssa_op_iter *ptr)
+{
+ ptr->i = 0;
+ ptr->numops = 0;
+ ptr->uses = NULL;
+ ptr->iter_type = ssa_op_iter_none;
+ ptr->stmt = NULL;
+ ptr->done = true;
+ ptr->flags = 0;
+}
+
+/* Initialize the iterator PTR to the virtual defs in STMT. */
+static inline void
+op_iter_init (ssa_op_iter *ptr, gimple *stmt, int flags)
+{
+ /* PHI nodes require a different iterator initialization path. We
+ do not support iterating over virtual defs or uses without
+ iterating over defs or uses at the same time. */
+ gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI
+ && (!(flags & SSA_OP_VDEF) || (flags & SSA_OP_DEF))
+ && (!(flags & SSA_OP_VUSE) || (flags & SSA_OP_USE)));
+ ptr->numops = 0;
+ if (flags & (SSA_OP_DEF | SSA_OP_VDEF))
+ {
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_ASSIGN:
+ case GIMPLE_CALL:
+ ptr->numops = 1;
+ break;
+ case GIMPLE_ASM:
+ ptr->numops = gimple_asm_noutputs (as_a <gasm *> (stmt));
+ break;
+ case GIMPLE_TRANSACTION:
+ ptr->numops = 0;
+ flags &= ~SSA_OP_DEF;
+ break;
+ default:
+ ptr->numops = 0;
+ flags &= ~(SSA_OP_DEF | SSA_OP_VDEF);
+ break;
+ }
+ }
+ ptr->uses = (flags & (SSA_OP_USE|SSA_OP_VUSE)) ? gimple_use_ops (stmt) : NULL;
+ if (!(flags & SSA_OP_VUSE)
+ && ptr->uses
+ && gimple_vuse (stmt) != NULL_TREE)
+ ptr->uses = ptr->uses->next;
+ ptr->done = false;
+ ptr->i = 0;
+
+ ptr->stmt = stmt;
+ ptr->flags = flags;
+}
+
+/* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
+ the first use. */
+static inline use_operand_p
+op_iter_init_use (ssa_op_iter *ptr, gimple *stmt, int flags)
+{
+ gcc_checking_assert ((flags & SSA_OP_ALL_DEFS) == 0
+ && (flags & SSA_OP_USE));
+ op_iter_init (ptr, stmt, flags);
+ ptr->iter_type = ssa_op_iter_use;
+ return op_iter_next_use (ptr);
+}
+
+/* Initialize iterator PTR to the def operands in STMT based on FLAGS. Return
+ the first def. */
+static inline def_operand_p
+op_iter_init_def (ssa_op_iter *ptr, gimple *stmt, int flags)
+{
+ gcc_checking_assert ((flags & SSA_OP_ALL_USES) == 0
+ && (flags & SSA_OP_DEF));
+ op_iter_init (ptr, stmt, flags);
+ ptr->iter_type = ssa_op_iter_def;
+ return op_iter_next_def (ptr);
+}
+
+/* Initialize iterator PTR to the operands in STMT based on FLAGS. Return
+ the first operand as a tree. */
+static inline tree
+op_iter_init_tree (ssa_op_iter *ptr, gimple *stmt, int flags)
+{
+ op_iter_init (ptr, stmt, flags);
+ ptr->iter_type = ssa_op_iter_tree;
+ return op_iter_next_tree (ptr);
+}
+
+
+/* If there is a single operand in STMT matching FLAGS, return it. Otherwise
+ return NULL. */
+static inline tree
+single_ssa_tree_operand (gimple *stmt, int flags)
+{
+ tree var;
+ ssa_op_iter iter;
+
+ var = op_iter_init_tree (&iter, stmt, flags);
+ if (op_iter_done (&iter))
+ return NULL_TREE;
+ op_iter_next_tree (&iter);
+ if (op_iter_done (&iter))
+ return var;
+ return NULL_TREE;
+}
+
+
+/* If there is a single operand in STMT matching FLAGS, return it. Otherwise
+ return NULL. */
+static inline use_operand_p
+single_ssa_use_operand (gimple *stmt, int flags)
+{
+ use_operand_p var;
+ ssa_op_iter iter;
+
+ var = op_iter_init_use (&iter, stmt, flags);
+ if (op_iter_done (&iter))
+ return NULL_USE_OPERAND_P;
+ op_iter_next_use (&iter);
+ if (op_iter_done (&iter))
+ return var;
+ return NULL_USE_OPERAND_P;
+}
+
+/* Return the single virtual use operand in STMT if present. Otherwise
+ return NULL. */
+static inline use_operand_p
+ssa_vuse_operand (gimple *stmt)
+{
+ if (! gimple_vuse (stmt))
+ return NULL_USE_OPERAND_P;
+ return USE_OP_PTR (gimple_use_ops (stmt));
+}
+
+
+/* If there is a single operand in STMT matching FLAGS, return it. Otherwise
+ return NULL. */
+static inline def_operand_p
+single_ssa_def_operand (gimple *stmt, int flags)
+{
+ def_operand_p var;
+ ssa_op_iter iter;
+
+ var = op_iter_init_def (&iter, stmt, flags);
+ if (op_iter_done (&iter))
+ return NULL_DEF_OPERAND_P;
+ op_iter_next_def (&iter);
+ if (op_iter_done (&iter))
+ return var;
+ return NULL_DEF_OPERAND_P;
+}
+
+
+/* Return true if there are zero operands in STMT matching the type
+ given in FLAGS. */
+static inline bool
+zero_ssa_operands (gimple *stmt, int flags)
+{
+ ssa_op_iter iter;
+
+ op_iter_init_tree (&iter, stmt, flags);
+ return op_iter_done (&iter);
+}
+
+
+/* Return the number of operands matching FLAGS in STMT. */
+static inline int
+num_ssa_operands (gimple *stmt, int flags)
+{
+ ssa_op_iter iter;
+ tree t;
+ int num = 0;
+
+ gcc_checking_assert (gimple_code (stmt) != GIMPLE_PHI);
+ FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, flags)
+ num++;
+ return num;
+}
+
+/* If there is a single DEF in the PHI node which matches FLAG, return it.
+ Otherwise return NULL_DEF_OPERAND_P. */
+static inline tree
+single_phi_def (gphi *stmt, int flags)
+{
+ tree def = PHI_RESULT (stmt);
+ if ((flags & SSA_OP_DEF) && is_gimple_reg (def))
+ return def;
+ if ((flags & SSA_OP_VIRTUAL_DEFS) && !is_gimple_reg (def))
+ return def;
+ return NULL_TREE;
+}
+
+/* Initialize the iterator PTR for uses matching FLAGS in PHI. FLAGS should
+ be either SSA_OP_USES or SSA_OP_VIRTUAL_USES. */
+static inline use_operand_p
+op_iter_init_phiuse (ssa_op_iter *ptr, gphi *phi, int flags)
+{
+ tree phi_def = gimple_phi_result (phi);
+ int comp;
+
+ clear_and_done_ssa_iter (ptr);
+ ptr->done = false;
+
+ gcc_checking_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0);
+
+ comp = (is_gimple_reg (phi_def) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES);
+
+ /* If the PHI node doesn't the operand type we care about, we're done. */
+ if ((flags & comp) == 0)
+ {
+ ptr->done = true;
+ return NULL_USE_OPERAND_P;
+ }
+
+ ptr->stmt = phi;
+ ptr->numops = gimple_phi_num_args (phi);
+ ptr->iter_type = ssa_op_iter_use;
+ ptr->flags = flags;
+ return op_iter_next_use (ptr);
+}
+
+
+/* Start an iterator for a PHI definition. */
+
+static inline def_operand_p
+op_iter_init_phidef (ssa_op_iter *ptr, gphi *phi, int flags)
+{
+ tree phi_def = PHI_RESULT (phi);
+ int comp;
+
+ clear_and_done_ssa_iter (ptr);
+ ptr->done = false;
+
+ gcc_checking_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0);
+
+ comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS);
+
+ /* If the PHI node doesn't have the operand type we care about,
+ we're done. */
+ if ((flags & comp) == 0)
+ {
+ ptr->done = true;
+ return NULL_DEF_OPERAND_P;
+ }
+
+ ptr->iter_type = ssa_op_iter_def;
+ /* The first call to op_iter_next_def will terminate the iterator since
+ all the fields are NULL. Simply return the result here as the first and
+ therefore only result. */
+ return PHI_RESULT_PTR (phi);
+}
+
+/* Return true is IMM has reached the end of the immediate use stmt list. */
+
+static inline bool
+end_imm_use_stmt_p (const imm_use_iterator *imm)
+{
+ return (imm->imm_use == imm->end_p);
+}
+
+/* Finished the traverse of an immediate use stmt list IMM by removing the
+ placeholder node from the list. */
+
+static inline void
+end_imm_use_stmt_traverse (imm_use_iterator *imm)
+{
+ delink_imm_use (&(imm->iter_node));
+}
+
+/* Immediate use traversal of uses within a stmt require that all the
+ uses on a stmt be sequentially listed. This routine is used to build up
+ this sequential list by adding USE_P to the end of the current list
+ currently delimited by HEAD and LAST_P. The new LAST_P value is
+ returned. */
+
+static inline use_operand_p
+move_use_after_head (use_operand_p use_p, use_operand_p head,
+ use_operand_p last_p)
+{
+ gcc_checking_assert (USE_FROM_PTR (use_p) == USE_FROM_PTR (head));
+ /* Skip head when we find it. */
+ if (use_p != head)
+ {
+ /* If use_p is already linked in after last_p, continue. */
+ if (last_p->next == use_p)
+ last_p = use_p;
+ else
+ {
+ /* Delink from current location, and link in at last_p. */
+ delink_imm_use (use_p);
+ link_imm_use_to_list (use_p, last_p);
+ last_p = use_p;
+ }
+ }
+ return last_p;
+}
+
+
+/* This routine will relink all uses with the same stmt as HEAD into the list
+ immediately following HEAD for iterator IMM. */
+
+static inline void
+link_use_stmts_after (use_operand_p head, imm_use_iterator *imm)
+{
+ use_operand_p use_p;
+ use_operand_p last_p = head;
+ gimple *head_stmt = USE_STMT (head);
+ tree use = USE_FROM_PTR (head);
+ ssa_op_iter op_iter;
+ int flag;
+
+ /* Only look at virtual or real uses, depending on the type of HEAD. */
+ flag = (is_gimple_reg (use) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES);
+
+ if (gphi *phi = dyn_cast <gphi *> (head_stmt))
+ {
+ FOR_EACH_PHI_ARG (use_p, phi, op_iter, flag)
+ if (USE_FROM_PTR (use_p) == use)
+ last_p = move_use_after_head (use_p, head, last_p);
+ }
+ else
+ {
+ if (flag == SSA_OP_USE)
+ {
+ FOR_EACH_SSA_USE_OPERAND (use_p, head_stmt, op_iter, flag)
+ if (USE_FROM_PTR (use_p) == use)
+ last_p = move_use_after_head (use_p, head, last_p);
+ }
+ else if ((use_p = gimple_vuse_op (head_stmt)) != NULL_USE_OPERAND_P)
+ {
+ if (USE_FROM_PTR (use_p) == use)
+ last_p = move_use_after_head (use_p, head, last_p);
+ }
+ }
+ /* Link iter node in after last_p. */
+ if (imm->iter_node.prev != NULL)
+ delink_imm_use (&imm->iter_node);
+ link_imm_use_to_list (&(imm->iter_node), last_p);
+}
+
+/* Initialize IMM to traverse over uses of VAR. Return the first statement. */
+static inline gimple *
+first_imm_use_stmt (imm_use_iterator *imm, tree var)
+{
+ imm->end_p = &(SSA_NAME_IMM_USE_NODE (var));
+ imm->imm_use = imm->end_p->next;
+ imm->next_imm_name = NULL_USE_OPERAND_P;
+
+ /* iter_node is used as a marker within the immediate use list to indicate
+ where the end of the current stmt's uses are. Initialize it to NULL
+ stmt and use, which indicates a marker node. */
+ imm->iter_node.prev = NULL_USE_OPERAND_P;
+ imm->iter_node.next = NULL_USE_OPERAND_P;
+ imm->iter_node.loc.stmt = NULL;
+ imm->iter_node.use = NULL;
+
+ if (end_imm_use_stmt_p (imm))
+ return NULL;
+
+ link_use_stmts_after (imm->imm_use, imm);
+
+ return USE_STMT (imm->imm_use);
+}
+
+/* Bump IMM to the next stmt which has a use of var. */
+
+static inline gimple *
+next_imm_use_stmt (imm_use_iterator *imm)
+{
+ imm->imm_use = imm->iter_node.next;
+ if (end_imm_use_stmt_p (imm))
+ {
+ if (imm->iter_node.prev != NULL)
+ delink_imm_use (&imm->iter_node);
+ return NULL;
+ }
+
+ link_use_stmts_after (imm->imm_use, imm);
+ return USE_STMT (imm->imm_use);
+}
+
+/* This routine will return the first use on the stmt IMM currently refers
+ to. */
+
+static inline use_operand_p
+first_imm_use_on_stmt (imm_use_iterator *imm)
+{
+ imm->next_imm_name = imm->imm_use->next;
+ return imm->imm_use;
+}
+
+/* Return TRUE if the last use on the stmt IMM refers to has been visited. */
+
+static inline bool
+end_imm_use_on_stmt_p (const imm_use_iterator *imm)
+{
+ return (imm->imm_use == &(imm->iter_node));
+}
+
+/* Bump to the next use on the stmt IMM refers to, return NULL if done. */
+
+static inline use_operand_p
+next_imm_use_on_stmt (imm_use_iterator *imm)
+{
+ imm->imm_use = imm->next_imm_name;
+ if (end_imm_use_on_stmt_p (imm))
+ return NULL_USE_OPERAND_P;
+ else
+ {
+ imm->next_imm_name = imm->imm_use->next;
+ return imm->imm_use;
+ }
+}
+
+/* Delink all immediate_use information for STMT. */
+static inline void
+delink_stmt_imm_use (gimple *stmt)
+{
+ ssa_op_iter iter;
+ use_operand_p use_p;
+
+ if (ssa_operands_active (cfun))
+ FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
+ delink_imm_use (use_p);
+}
+
+#endif /* GCC_TREE_SSA_ITERATORS_H */
diff --git a/support/cpp/gcc/ssa.h b/support/cpp/gcc/ssa.h
new file mode 100644
index 000000000..b0351a435
--- /dev/null
+++ b/support/cpp/gcc/ssa.h
@@ -0,0 +1,34 @@
+/* Common SSA files
+ Copyright (C) 2015-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_SSA_H
+#define GCC_SSA_H
+
+/* This is an aggregation header file. This means it should contain only
+ other include files. */
+
+#include "stringpool.h"
+#include "gimple-ssa.h"
+#include "tree-vrp.h"
+#include "range.h"
+#include "tree-ssanames.h"
+#include "tree-phinodes.h"
+#include "ssa-iterators.h"
+
+#endif /* GCC_SSA_H */
diff --git a/support/cpp/gcc/statistics.h b/support/cpp/gcc/statistics.h
new file mode 100644
index 000000000..c0ce48600
--- /dev/null
+++ b/support/cpp/gcc/statistics.h
@@ -0,0 +1,71 @@
+/* Memory and optimization statistics helpers.
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Cygnus Solutions.
+
+ 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_STATISTICS
+#define GCC_STATISTICS
+
+#if ! defined GATHER_STATISTICS
+#error GATHER_STATISTICS must be defined
+#endif
+
+#define GCC_MEM_STAT_ARGUMENTS const char * ARG_UNUSED (_loc_name), int ARG_UNUSED (_loc_line), const char * ARG_UNUSED (_loc_function)
+#if GATHER_STATISTICS
+#define ALONE_MEM_STAT_DECL GCC_MEM_STAT_ARGUMENTS
+#define ALONE_FINAL_MEM_STAT_DECL ALONE_MEM_STAT_DECL
+#define ALONE_PASS_MEM_STAT _loc_name, _loc_line, _loc_function
+#define ALONE_FINAL_PASS_MEM_STAT ALONE_PASS_MEM_STAT
+#define ALONE_MEM_STAT_INFO __FILE__, __LINE__, __FUNCTION__
+#define MEM_STAT_DECL , ALONE_MEM_STAT_DECL
+#define FINAL_MEM_STAT_DECL , ALONE_FINAL_MEM_STAT_DECL
+#define PASS_MEM_STAT , ALONE_PASS_MEM_STAT
+#define FINAL_PASS_MEM_STAT , ALONE_FINAL_PASS_MEM_STAT
+#define MEM_STAT_INFO , ALONE_MEM_STAT_INFO
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+#define ALONE_CXX_MEM_STAT_INFO const char * _loc_name = __builtin_FILE (), int _loc_line = __builtin_LINE (), const char * _loc_function = __builtin_FUNCTION ()
+#else
+#define ALONE_CXX_MEM_STAT_INFO const char * _loc_name = __FILE__, int _loc_line = __LINE__, const char * _loc_function = NULL
+#endif
+#define CXX_MEM_STAT_INFO , ALONE_CXX_MEM_STAT_INFO
+#else
+#define ALONE_MEM_STAT_DECL void
+#define ALONE_FINAL_MEM_STAT_DECL GCC_MEM_STAT_ARGUMENTS
+#define ALONE_PASS_MEM_STAT
+#define ALONE_FINAL_PASS_MEM_STAT 0,0,0
+#define ALONE_MEM_STAT_INFO
+#define MEM_STAT_DECL
+#define FINAL_MEM_STAT_DECL , ALONE_FINAL_MEM_STAT_DECL
+#define PASS_MEM_STAT
+#define FINAL_PASS_MEM_STAT , ALONE_FINAL_PASS_MEM_STAT
+#define MEM_STAT_INFO ALONE_MEM_STAT_INFO
+#define ALONE_CXX_MEM_STAT_INFO
+#define CXX_MEM_STAT_INFO
+#endif
+
+struct function;
+
+/* In statistics.cc */
+extern void statistics_early_init (void);
+extern void statistics_init (void);
+extern void statistics_fini (void);
+extern void statistics_fini_pass (void);
+extern void statistics_counter_event (struct function *, const char *, int);
+extern void statistics_histogram_event (struct function *, const char *, int);
+
+#endif
diff --git a/support/cpp/gcc/stmt.h b/support/cpp/gcc/stmt.h
new file mode 100644
index 000000000..06e15c86a
--- /dev/null
+++ b/support/cpp/gcc/stmt.h
@@ -0,0 +1,53 @@
+/* Declarations and data structures for stmt.cc.
+ Copyright (C) 2013-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_STMT_H
+#define GCC_STMT_H
+
+extern void expand_label (tree);
+extern bool parse_output_constraint (const char **, int, int, int,
+ bool *, bool *, bool *);
+extern bool parse_input_constraint (const char **, int, int, int, int,
+ const char * const *, bool *, bool *);
+extern tree resolve_asm_operand_names (tree, tree, tree, tree);
+#ifdef HARD_CONST
+/* Silly ifdef to avoid having all includers depend on hard-reg-set.h. */
+extern tree tree_overlaps_hard_reg_set (tree, HARD_REG_SET *);
+#endif
+
+/* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary.
+ If label was deleted, the corresponding note
+ (NOTE_INSN_DELETED{_DEBUG,}_LABEL) insn will be returned. */
+extern rtx_insn *label_rtx (tree);
+
+/* As label_rtx, but additionally the label is placed on the forced label
+ list of its containing function (i.e. it is treated as reachable even
+ if how is not obvious). */
+extern rtx_insn *force_label_rtx (tree);
+
+/* As label_rtx, but checks that label was not deleted. */
+extern rtx_code_label *jump_target_rtx (tree);
+
+/* Expand a GIMPLE_SWITCH statement. */
+extern void expand_case (gswitch *);
+
+/* Like expand_case but special-case for SJLJ exception dispatching. */
+extern void expand_sjlj_dispatch_table (rtx, vec<tree> );
+
+#endif // GCC_STMT_H
diff --git a/support/cpp/gcc/stor-layout.h b/support/cpp/gcc/stor-layout.h
new file mode 100644
index 000000000..d1c110f8b
--- /dev/null
+++ b/support/cpp/gcc/stor-layout.h
@@ -0,0 +1,117 @@
+/* Definitions and declarations for stor-layout.cc.
+ Copyright (C) 2013-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/>. */
+
+#if 0 // sdcpp ndef GCC_STOR_LAYOUT_H
+#define GCC_STOR_LAYOUT_H
+
+extern void set_min_and_max_values_for_integral_type (tree, int, signop);
+extern void fixup_signed_type (tree);
+extern unsigned int update_alignment_for_field (record_layout_info, tree,
+ unsigned int);
+extern record_layout_info start_record_layout (tree);
+extern tree bit_from_pos (tree, tree);
+extern tree byte_from_pos (tree, tree);
+extern void pos_from_bit (tree *, tree *, unsigned int, tree);
+extern void normalize_offset (tree *, tree *, unsigned int);
+extern tree rli_size_unit_so_far (record_layout_info);
+extern tree rli_size_so_far (record_layout_info);
+extern void normalize_rli (record_layout_info);
+extern void place_field (record_layout_info, tree);
+extern void compute_record_mode (tree);
+extern void finish_bitfield_layout (tree);
+extern void finish_record_layout (record_layout_info, int);
+extern unsigned int element_precision (const_tree);
+extern void finalize_size_functions (void);
+extern void fixup_unsigned_type (tree);
+extern void initialize_sizetypes (void);
+
+/* Finish up a builtin RECORD_TYPE. Give it a name and provide its
+ fields. Optionally specify an alignment, and then lay it out. */
+extern void finish_builtin_struct (tree, const char *, tree, tree);
+
+/* Given a VAR_DECL, PARM_DECL, RESULT_DECL or FIELD_DECL node,
+ calculates the DECL_SIZE, DECL_SIZE_UNIT, DECL_ALIGN and DECL_MODE
+ fields. Call this only once for any given decl node.
+
+ Second argument is the boundary that this field can be assumed to
+ be starting at (in bits). Zero means it can be assumed aligned
+ on any boundary that may be needed. */
+extern void layout_decl (tree, unsigned);
+
+/* Given a ..._TYPE node, calculate the TYPE_SIZE, TYPE_SIZE_UNIT,
+ TYPE_ALIGN and TYPE_MODE fields. If called more than once on one
+ node, does nothing except for the first time. */
+extern void layout_type (tree);
+
+/* Return the least alignment in bytes required for type TYPE. */
+extern unsigned int min_align_of_type (tree);
+
+/* Construct various nodes representing fract or accum data types. */
+extern tree make_fract_type (int, int, int);
+extern tree make_accum_type (int, int, int);
+
+#define make_signed_fract_type(P) make_fract_type (P, 0, 0)
+#define make_unsigned_fract_type(P) make_fract_type (P, 1, 0)
+#define make_sat_signed_fract_type(P) make_fract_type (P, 0, 1)
+#define make_sat_unsigned_fract_type(P) make_fract_type (P, 1, 1)
+#define make_signed_accum_type(P) make_accum_type (P, 0, 0)
+#define make_unsigned_accum_type(P) make_accum_type (P, 1, 0)
+#define make_sat_signed_accum_type(P) make_accum_type (P, 0, 1)
+#define make_sat_unsigned_accum_type(P) make_accum_type (P, 1, 1)
+
+#define make_or_reuse_signed_fract_type(P) \
+ make_or_reuse_fract_type (P, 0, 0)
+#define make_or_reuse_unsigned_fract_type(P) \
+ make_or_reuse_fract_type (P, 1, 0)
+#define make_or_reuse_sat_signed_fract_type(P) \
+ make_or_reuse_fract_type (P, 0, 1)
+#define make_or_reuse_sat_unsigned_fract_type(P) \
+ make_or_reuse_fract_type (P, 1, 1)
+#define make_or_reuse_signed_accum_type(P) \
+ make_or_reuse_accum_type (P, 0, 0)
+#define make_or_reuse_unsigned_accum_type(P) \
+ make_or_reuse_accum_type (P, 1, 0)
+#define make_or_reuse_sat_signed_accum_type(P) \
+ make_or_reuse_accum_type (P, 0, 1)
+#define make_or_reuse_sat_unsigned_accum_type(P) \
+ make_or_reuse_accum_type (P, 1, 1)
+
+extern tree make_signed_type (int);
+extern tree make_unsigned_type (int);
+
+/* Return the mode for data of a given size SIZE and mode class CLASS.
+ If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
+ The value is BLKmode if no other mode is found. This is like
+ mode_for_size, but is passed a tree. */
+extern opt_machine_mode mode_for_size_tree (const_tree, enum mode_class, int);
+
+extern tree bitwise_type_for_mode (machine_mode);
+
+/* Given a VAR_DECL, PARM_DECL or RESULT_DECL, clears the results of
+ a previous call to layout_decl and calls it again. */
+extern void relayout_decl (tree);
+
+/* variable_size (EXP) is like save_expr (EXP) except that it
+ is for the special case of something that is part of a
+ variable size for a data type. It makes special arrangements
+ to compute the value at the right time when the data type
+ belongs to a function parameter. */
+extern tree variable_size (tree);
+
+#endif // GCC_STOR_LAYOUT_H
diff --git a/support/cpp/gcc/stringpool.h b/support/cpp/gcc/stringpool.h
new file mode 100644
index 000000000..5e301c601
--- /dev/null
+++ b/support/cpp/gcc/stringpool.h
@@ -0,0 +1,43 @@
+/* Declarations and definitons for stringpool.cc.
+ Copyright (C) 2013-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_STRINGPOOL_H
+#define GCC_STRINGPOOL_H
+
+/* Return the (unique) IDENTIFIER_NODE node for a given name.
+ The name is supplied as a char *. */
+extern tree get_identifier (const char *);
+
+/* If an identifier with the name TEXT (a null-terminated string) has
+ previously been referred to, return that node; otherwise return
+ NULL_TREE. */
+extern tree maybe_get_identifier (const char *);
+
+/* Identical to get_identifier, except that the length is assumed
+ known. */
+extern tree get_identifier_with_length (const char *, size_t);
+
+#if GCC_VERSION >= 3000
+#define get_identifier(str) \
+ (__builtin_constant_p (str) \
+ ? get_identifier_with_length ((str), strlen (str)) \
+ : get_identifier (str))
+#endif
+
+#endif // GCC_STRINGPOOL_H
diff --git a/support/cpp/gcc/substring-locations.h b/support/cpp/gcc/substring-locations.h
new file mode 100644
index 000000000..1ad188a80
--- /dev/null
+++ b/support/cpp/gcc/substring-locations.h
@@ -0,0 +1,126 @@
+/* Source locations within string literals.
+ Copyright (C) 2016-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_SUBSTRING_LOCATIONS_H
+#define GCC_SUBSTRING_LOCATIONS_H
+
+/* The substring_loc class encapsulates information on the source location
+ of a range of characters within a STRING_CST.
+
+ If needed by a diagnostic, the actual location_t of the substring_loc
+ can be calculated by calling its get_location method. This calls a
+ langhook, since this is inherently frontend-specific. For the C family
+ of frontends, it calls back into libcpp to reparse the strings. This
+ gets the location information "on demand", rather than storing the
+ location information in the initial lex for every string. Thus the
+ substring_loc can also be thought of as a deferred call into libcpp,
+ to allow the non-trivial work of reparsing the string to be delayed
+ until we actually need it (to emit a diagnostic for a particular range
+ of characters).
+
+ substring_loc::get_location returns NULL if it succeeds, or an
+ error message if it fails. Error messages are intended for GCC
+ developers (to help debugging) rather than for end-users.
+
+ The easiest way to use a substring_loc is via the format_warning_* APIs,
+ which gracefully handle failure of substring_loc::get_location by using
+ the location of the string as a whole if substring-information is
+ unavailable. */
+
+class substring_loc
+{
+ public:
+ /* Constructor. FMT_STRING_LOC is the location of the string as
+ a whole. STRING_TYPE is the type of the string. It should be an
+ ARRAY_TYPE of INTEGER_TYPE, or a POINTER_TYPE to such an ARRAY_TYPE.
+ CARET_IDX, START_IDX, and END_IDX are offsets from the start
+ of the string data. */
+ substring_loc (location_t fmt_string_loc, tree string_type,
+ int caret_idx, int start_idx, int end_idx)
+ : m_fmt_string_loc (fmt_string_loc), m_string_type (string_type),
+ m_caret_idx (caret_idx), m_start_idx (start_idx), m_end_idx (end_idx) {}
+
+ void set_caret_index (int caret_idx) { m_caret_idx = caret_idx; }
+
+ const char *get_location (location_t *out_loc) const;
+
+ location_t get_fmt_string_loc () const { return m_fmt_string_loc; }
+ tree get_string_type () const { return m_string_type; }
+ int get_caret_idx () const { return m_caret_idx; }
+ int get_start_idx () const { return m_start_idx; }
+ int get_end_idx () const { return m_end_idx; }
+
+ private:
+ location_t m_fmt_string_loc;
+ tree m_string_type;
+ int m_caret_idx;
+ int m_start_idx;
+ int m_end_idx;
+};
+
+/* A bundle of state for emitting a diagnostic relating to a format string. */
+
+class format_string_diagnostic_t
+{
+ public:
+ format_string_diagnostic_t (const substring_loc &fmt_loc,
+ const range_label *fmt_label,
+ location_t param_loc,
+ const range_label *param_label,
+ const char *corrected_substring);
+
+ /* Functions for emitting a warning about a format string. */
+
+ bool emit_warning_va (int opt, const char *gmsgid, va_list *ap) const
+ ATTRIBUTE_GCC_DIAG (3, 0);
+
+ bool emit_warning_n_va (int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid, va_list *ap) const
+ ATTRIBUTE_GCC_DIAG (4, 0) ATTRIBUTE_GCC_DIAG (5, 0);
+
+ bool emit_warning (int opt, const char *gmsgid, ...) const
+ ATTRIBUTE_GCC_DIAG (3, 4);
+
+ bool emit_warning_n (int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid,
+ const char *plural_gmsgid, ...) const
+ ATTRIBUTE_GCC_DIAG (4, 6) ATTRIBUTE_GCC_DIAG (5, 6);
+
+ private:
+ const substring_loc &m_fmt_loc;
+ const range_label *m_fmt_label;
+ location_t m_param_loc;
+ const range_label *m_param_label;
+ const char *m_corrected_substring;
+};
+
+
+/* Implementation detail, for use when implementing
+ LANG_HOOKS_GET_SUBSTRING_LOCATION. */
+
+extern const char *get_location_within_string (cpp_reader *pfile,
+ string_concat_db *concats,
+ location_t strloc,
+ enum cpp_ttype type,
+ int caret_idx,
+ int start_idx, int end_idx,
+ location_t *out_loc);
+
+#endif /* ! GCC_SUBSTRING_LOCATIONS_H */
diff --git a/support/cpp/gcc/symtab-clones.h b/support/cpp/gcc/symtab-clones.h
new file mode 100644
index 000000000..9ac950970
--- /dev/null
+++ b/support/cpp/gcc/symtab-clones.h
@@ -0,0 +1,77 @@
+/* Representation of adjustment made to virtual clones in the symbol table.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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_SYMTAB_CLONES_H
+#define GCC_SYMTAB_CLONES_H
+
+struct GTY(()) clone_info
+{
+ /* Constructor. */
+ clone_info ()
+ : tree_map (NULL),
+ param_adjustments (NULL)
+ {
+ }
+ /* Constants discovered by IPA-CP, i.e. which parameter should be replaced
+ with what. */
+ vec<ipa_replace_map *, va_gc> *tree_map;
+ /* Parameter modification that IPA-SRA decided to perform. */
+ ipa_param_adjustments *param_adjustments;
+
+ /* Return clone_info, if available. */
+ static clone_info *get (cgraph_node *node);
+
+ /* Return clone_info possibly creating new one. */
+ static clone_info *get_create (cgraph_node *node);
+
+ /* Remove clone_info. */
+ static void remove (cgraph_node *node);
+
+ /* Release all clone_infos. */
+ static void release (void);
+};
+
+/* Return clone_info, if available. */
+inline clone_info *
+clone_info::get (cgraph_node *node)
+{
+ if (!symtab->m_clones)
+ return NULL;
+ return symtab->m_clones->get (node);
+}
+
+
+/* Remove clone_info association for NODE. */
+inline void
+clone_info::remove (cgraph_node *node)
+{
+ symtab->m_clones->remove (node);
+}
+
+/* Free clone info summaries. */
+inline void
+clone_info::release ()
+{
+ if (symtab->m_clones)
+ ggc_delete (symtab->m_clones);
+ symtab->m_clones = NULL;
+}
+
+#endif /* GCC_SYMTAB_CLONES_H */
diff --git a/support/cpp/gcc/symtab-thunks.h b/support/cpp/gcc/symtab-thunks.h
new file mode 100644
index 000000000..89718fa21
--- /dev/null
+++ b/support/cpp/gcc/symtab-thunks.h
@@ -0,0 +1,173 @@
+/* Representation of thunks inside symbol table.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+ Contributed by Jan Hubicka
+
+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_SYMTAB_THUNKS_H
+#define GCC_SYMTAB_THUNKS_H
+
+/* This symbol annotation holds information about thunk.
+
+ Thunks are basically wrappers around methods which are introduced in case
+ of multiple inheritance in order to adjust the value of the "this" pointer
+ or of the returned value.
+
+ In the case of this-adjusting thunks, each back-end can override the
+ can_output_mi_thunk/output_mi_thunk target hooks to generate a minimal thunk
+ (with a tail call for instance) directly as assembly. For the default hook
+ or for the case where the can_output_mi_thunk hooks return false, the thunk
+ is gimplified and lowered using the regular machinery. */
+
+struct GTY(()) thunk_info {
+ /* Constructor. */
+ thunk_info ()
+ : fixed_offset (0),
+ virtual_value (0),
+ indirect_offset (0),
+ alias (NULL),
+ this_adjusting (false),
+ virtual_offset_p (false)
+ {
+ }
+ /* Copy constructor. */
+ thunk_info (const thunk_info &t)
+ : fixed_offset (t.fixed_offset),
+ virtual_value (t.virtual_value),
+ indirect_offset (t.indirect_offset),
+ alias (t.alias),
+ this_adjusting (t.this_adjusting),
+ virtual_offset_p (t.virtual_offset_p)
+ {
+ }
+
+ /* Compare for equiality. */
+ bool
+ operator==(const thunk_info &other) const
+ {
+ return fixed_offset == other.fixed_offset
+ && virtual_value == other.virtual_value
+ && indirect_offset == other.indirect_offset
+ && this_adjusting == other.this_adjusting
+ && virtual_offset_p == other.virtual_offset_p;
+ }
+ bool
+ operator!=(const thunk_info &other) const
+ {
+ return !(*this == other);
+ }
+ /* Copy operator. */
+ thunk_info &
+ operator=(const thunk_info &other)
+ {
+ fixed_offset = other.fixed_offset;
+ virtual_value = other.virtual_value;
+ indirect_offset = other.indirect_offset;
+ alias = other.alias;
+ this_adjusting = other.this_adjusting;
+ virtual_offset_p = other.virtual_offset_p;
+ return *this;
+ }
+
+ /* Offset used to adjust "this". */
+ HOST_WIDE_INT fixed_offset;
+
+ /* Offset in the virtual table to get the offset to adjust "this". Valid iff
+ VIRTUAL_OFFSET_P is true. */
+ HOST_WIDE_INT virtual_value;
+
+ /* Offset from "this" to get the offset to adjust "this". Zero means: this
+ offset is to be ignored. */
+ HOST_WIDE_INT indirect_offset;
+
+ /* Thunk target, i.e. the method that this thunk wraps. Depending on the
+ TARGET_USE_LOCAL_THUNK_ALIAS_P macro, this may have to be a new alias. */
+ tree alias;
+
+ /* Nonzero for a "this" adjusting thunk and zero for a result adjusting
+ thunk. */
+ bool this_adjusting;
+
+ /* If true, this thunk is what we call a virtual thunk. In this case:
+ * for this-adjusting thunks, after the FIXED_OFFSET based adjustment is
+ done, add to the result the offset found in the vtable at:
+ vptr + VIRTUAL_VALUE
+ * for result-adjusting thunks, the FIXED_OFFSET adjustment is done after
+ the virtual one. */
+ bool virtual_offset_p;
+
+
+
+ /* Dump thunk_info. */
+ void dump (FILE *);
+
+ /* Stream out thunk_info. */
+ void stream_out (class lto_simple_output_block *);
+
+ /* Stream in trunk_info. */
+ void stream_in (class lto_input_block *);
+
+ hashval_t hash ();
+
+
+
+ /* Return thunk_info, if available. */
+ static thunk_info *get (cgraph_node *node);
+
+ /* Return thunk_info possibly creating new one. */
+ static thunk_info *get_create (cgraph_node *node);
+
+ /* Remove thunk_info. */
+ static void remove (cgraph_node *node);
+
+ /* Add unprocessed thunk. */
+ void register_early (cgraph_node *node);
+
+ /* Attach recorded thunks to cgraph_nodes. */
+ static void process_early_thunks ();
+
+ /* Release all thunk_infos. */
+ static void release (void);
+};
+
+bool expand_thunk (cgraph_node *, bool, bool);
+
+/* Return thunk_info, if available. */
+inline thunk_info *
+thunk_info::get (cgraph_node *node)
+{
+ if (!symtab->m_thunks)
+ return NULL;
+ return symtab->m_thunks->get (node);
+}
+
+/* Remove thunk_info association for NODE. */
+inline void
+thunk_info::remove (cgraph_node *node)
+{
+ symtab->m_thunks->remove (node);
+}
+
+/* Free thunk info summaries. */
+inline void
+thunk_info::release ()
+{
+ if (symtab->m_thunks)
+ ggc_delete (symtab->m_thunks);
+ symtab->m_thunks = NULL;
+}
+#endif /* GCC_SYMTAB_THUNKS_H */
diff --git a/support/cpp/gcc/sync-builtins.def b/support/cpp/gcc/sync-builtins.def
new file mode 100644
index 000000000..7712d87d6
--- /dev/null
+++ b/support/cpp/gcc/sync-builtins.def
@@ -0,0 +1,614 @@
+/* This file contains the definitions and documentation for the
+ synchronization builtins used in the GNU compiler.
+ Copyright (C) 2005-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/>. */
+
+/* Before including this file, you should define a macro:
+
+ DEF_SYNC_BUILTIN (ENUM, NAME, TYPE, ATTRS)
+
+ See builtins.def for details. */
+
+/* Synchronization Primitives. The "_N" version is the one that the user
+ is supposed to be using. It's overloaded, and is resolved to one of the
+ "_1" through "_16" versions, plus some extra casts. */
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_ADD_N, "__sync_fetch_and_add",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_ADD_1, "__sync_fetch_and_add_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_ADD_2, "__sync_fetch_and_add_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_ADD_4, "__sync_fetch_and_add_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_ADD_8, "__sync_fetch_and_add_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_ADD_16, "__sync_fetch_and_add_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_SUB_N, "__sync_fetch_and_sub",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_SUB_1, "__sync_fetch_and_sub_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_SUB_2, "__sync_fetch_and_sub_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_SUB_4, "__sync_fetch_and_sub_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_SUB_8, "__sync_fetch_and_sub_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_SUB_16, "__sync_fetch_and_sub_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_OR_N, "__sync_fetch_and_or",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_OR_1, "__sync_fetch_and_or_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_OR_2, "__sync_fetch_and_or_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_OR_4, "__sync_fetch_and_or_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_OR_8, "__sync_fetch_and_or_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_OR_16, "__sync_fetch_and_or_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_AND_N, "__sync_fetch_and_and",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_AND_1, "__sync_fetch_and_and_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_AND_2, "__sync_fetch_and_and_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_AND_4, "__sync_fetch_and_and_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_AND_8, "__sync_fetch_and_and_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_AND_16, "__sync_fetch_and_and_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_XOR_N, "__sync_fetch_and_xor",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_XOR_1, "__sync_fetch_and_xor_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_XOR_2, "__sync_fetch_and_xor_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_XOR_4, "__sync_fetch_and_xor_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_XOR_8, "__sync_fetch_and_xor_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_XOR_16, "__sync_fetch_and_xor_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_NAND_N, "__sync_fetch_and_nand",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_NAND_1, "__sync_fetch_and_nand_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_NAND_2, "__sync_fetch_and_nand_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_NAND_4, "__sync_fetch_and_nand_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_NAND_8, "__sync_fetch_and_nand_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_FETCH_AND_NAND_16, "__sync_fetch_and_nand_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_ADD_AND_FETCH_N, "__sync_add_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_add_and_fetch_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_add_and_fetch_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_add_and_fetch_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_add_and_fetch_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_ADD_AND_FETCH_16, "__sync_add_and_fetch_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SUB_AND_FETCH_N, "__sync_sub_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SUB_AND_FETCH_1, "__sync_sub_and_fetch_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SUB_AND_FETCH_2, "__sync_sub_and_fetch_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SUB_AND_FETCH_4, "__sync_sub_and_fetch_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SUB_AND_FETCH_8, "__sync_sub_and_fetch_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SUB_AND_FETCH_16, "__sync_sub_and_fetch_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_OR_AND_FETCH_N, "__sync_or_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_OR_AND_FETCH_1, "__sync_or_and_fetch_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_OR_AND_FETCH_2, "__sync_or_and_fetch_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_OR_AND_FETCH_4, "__sync_or_and_fetch_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_OR_AND_FETCH_8, "__sync_or_and_fetch_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_OR_AND_FETCH_16, "__sync_or_and_fetch_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_AND_AND_FETCH_N, "__sync_and_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_AND_AND_FETCH_1, "__sync_and_and_fetch_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_AND_AND_FETCH_2, "__sync_and_and_fetch_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_AND_AND_FETCH_4, "__sync_and_and_fetch_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_AND_AND_FETCH_8, "__sync_and_and_fetch_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_AND_AND_FETCH_16, "__sync_and_and_fetch_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_XOR_AND_FETCH_N, "__sync_xor_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_XOR_AND_FETCH_1, "__sync_xor_and_fetch_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_XOR_AND_FETCH_2, "__sync_xor_and_fetch_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_XOR_AND_FETCH_4, "__sync_xor_and_fetch_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_XOR_AND_FETCH_8, "__sync_xor_and_fetch_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_XOR_AND_FETCH_16, "__sync_xor_and_fetch_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_NAND_AND_FETCH_N, "__sync_nand_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_NAND_AND_FETCH_1, "__sync_nand_and_fetch_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_NAND_AND_FETCH_2, "__sync_nand_and_fetch_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_NAND_AND_FETCH_4, "__sync_nand_and_fetch_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_NAND_AND_FETCH_8, "__sync_nand_and_fetch_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_NAND_AND_FETCH_16, "__sync_nand_and_fetch_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N,
+ "__sync_bool_compare_and_swap",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_1,
+ "__sync_bool_compare_and_swap_1",
+ BT_FN_BOOL_VPTR_I1_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_2,
+ "__sync_bool_compare_and_swap_2",
+ BT_FN_BOOL_VPTR_I2_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_4,
+ "__sync_bool_compare_and_swap_4",
+ BT_FN_BOOL_VPTR_I4_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_8,
+ "__sync_bool_compare_and_swap_8",
+ BT_FN_BOOL_VPTR_I8_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_16,
+ "__sync_bool_compare_and_swap_16",
+ BT_FN_BOOL_VPTR_I16_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N,
+ "__sync_val_compare_and_swap",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_1,
+ "__sync_val_compare_and_swap_1",
+ BT_FN_I1_VPTR_I1_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_2,
+ "__sync_val_compare_and_swap_2",
+ BT_FN_I2_VPTR_I2_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_4,
+ "__sync_val_compare_and_swap_4",
+ BT_FN_I4_VPTR_I4_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_8,
+ "__sync_val_compare_and_swap_8",
+ BT_FN_I8_VPTR_I8_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_16,
+ "__sync_val_compare_and_swap_16",
+ BT_FN_I16_VPTR_I16_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_TEST_AND_SET_N,
+ "__sync_lock_test_and_set",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_TEST_AND_SET_1,
+ "__sync_lock_test_and_set_1",
+ BT_FN_I1_VPTR_I1, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_TEST_AND_SET_2,
+ "__sync_lock_test_and_set_2",
+ BT_FN_I2_VPTR_I2, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_TEST_AND_SET_4,
+ "__sync_lock_test_and_set_4",
+ BT_FN_I4_VPTR_I4, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_TEST_AND_SET_8,
+ "__sync_lock_test_and_set_8",
+ BT_FN_I8_VPTR_I8, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_TEST_AND_SET_16,
+ "__sync_lock_test_and_set_16",
+ BT_FN_I16_VPTR_I16, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_RELEASE_N, "__sync_lock_release",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_RELEASE_1, "__sync_lock_release_1",
+ BT_FN_VOID_VPTR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_RELEASE_2, "__sync_lock_release_2",
+ BT_FN_VOID_VPTR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_RELEASE_4, "__sync_lock_release_4",
+ BT_FN_VOID_VPTR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_RELEASE_8, "__sync_lock_release_8",
+ BT_FN_VOID_VPTR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_LOCK_RELEASE_16, "__sync_lock_release_16",
+ BT_FN_VOID_VPTR, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRONIZE, "__sync_synchronize",
+ BT_FN_VOID, ATTR_NOTHROWCALL_LEAF_LIST)
+
+/* __sync* builtins for the C++ memory model. */
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set",
+ BT_FN_BOOL_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_VPTR_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE,
+ "__atomic_exchange",
+ BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_N,
+ "__atomic_exchange_n",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_1,
+ "__atomic_exchange_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_2,
+ "__atomic_exchange_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_4,
+ "__atomic_exchange_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_8,
+ "__atomic_exchange_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE_16,
+ "__atomic_exchange_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD,
+ "__atomic_load",
+ BT_FN_VOID_SIZE_CONST_VPTR_PTR_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_N,
+ "__atomic_load_n",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_1,
+ "__atomic_load_1",
+ BT_FN_I1_CONST_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_2,
+ "__atomic_load_2",
+ BT_FN_I2_CONST_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_4,
+ "__atomic_load_4",
+ BT_FN_I4_CONST_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_8,
+ "__atomic_load_8",
+ BT_FN_I8_CONST_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_LOAD_16,
+ "__atomic_load_16",
+ BT_FN_I16_CONST_VPTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE,
+ "__atomic_compare_exchange",
+ BT_FN_BOOL_SIZE_VPTR_PTR_PTR_INT_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N,
+ "__atomic_compare_exchange_n",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_1,
+ "__atomic_compare_exchange_1",
+ BT_FN_BOOL_VPTR_PTR_I1_BOOL_INT_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_2,
+ "__atomic_compare_exchange_2",
+ BT_FN_BOOL_VPTR_PTR_I2_BOOL_INT_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4,
+ "__atomic_compare_exchange_4",
+ BT_FN_BOOL_VPTR_PTR_I4_BOOL_INT_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8,
+ "__atomic_compare_exchange_8",
+ BT_FN_BOOL_VPTR_PTR_I8_BOOL_INT_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_16,
+ "__atomic_compare_exchange_16",
+ BT_FN_BOOL_VPTR_PTR_I16_BOOL_INT_INT,
+ ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE,
+ "__atomic_store",
+ BT_FN_VOID_SIZE_VPTR_PTR_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_N,
+ "__atomic_store_n",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_1,
+ "__atomic_store_1",
+ BT_FN_VOID_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_2,
+ "__atomic_store_2",
+ BT_FN_VOID_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_4,
+ "__atomic_store_4",
+ BT_FN_VOID_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_8,
+ "__atomic_store_8",
+ BT_FN_VOID_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_STORE_16,
+ "__atomic_store_16",
+ BT_FN_VOID_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_N,
+ "__atomic_add_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_1,
+ "__atomic_add_fetch_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_2,
+ "__atomic_add_fetch_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_4,
+ "__atomic_add_fetch_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_8,
+ "__atomic_add_fetch_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ADD_FETCH_16,
+ "__atomic_add_fetch_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_N,
+ "__atomic_sub_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_1,
+ "__atomic_sub_fetch_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_2,
+ "__atomic_sub_fetch_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_4,
+ "__atomic_sub_fetch_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_8,
+ "__atomic_sub_fetch_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SUB_FETCH_16,
+ "__atomic_sub_fetch_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_N,
+ "__atomic_and_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_1,
+ "__atomic_and_fetch_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_2,
+ "__atomic_and_fetch_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_4,
+ "__atomic_and_fetch_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_8,
+ "__atomic_and_fetch_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_AND_FETCH_16,
+ "__atomic_and_fetch_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_N,
+ "__atomic_nand_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_1,
+ "__atomic_nand_fetch_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_2,
+ "__atomic_nand_fetch_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_4,
+ "__atomic_nand_fetch_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_8,
+ "__atomic_nand_fetch_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_NAND_FETCH_16,
+ "__atomic_nand_fetch_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_N,
+ "__atomic_xor_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_1,
+ "__atomic_xor_fetch_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_2,
+ "__atomic_xor_fetch_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_4,
+ "__atomic_xor_fetch_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_8,
+ "__atomic_xor_fetch_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_XOR_FETCH_16,
+ "__atomic_xor_fetch_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_N,
+ "__atomic_or_fetch",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_1,
+ "__atomic_or_fetch_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_2,
+ "__atomic_or_fetch_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_4,
+ "__atomic_or_fetch_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_8,
+ "__atomic_or_fetch_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_OR_FETCH_16,
+ "__atomic_or_fetch_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_N,
+ "__atomic_fetch_add",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_1,
+ "__atomic_fetch_add_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_2,
+ "__atomic_fetch_add_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_4,
+ "__atomic_fetch_add_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_8,
+ "__atomic_fetch_add_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_ADD_16,
+ "__atomic_fetch_add_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_N,
+ "__atomic_fetch_sub",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_1,
+ "__atomic_fetch_sub_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_2,
+ "__atomic_fetch_sub_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_4,
+ "__atomic_fetch_sub_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_8,
+ "__atomic_fetch_sub_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_SUB_16,
+ "__atomic_fetch_sub_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_N,
+ "__atomic_fetch_and",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_1,
+ "__atomic_fetch_and_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_2,
+ "__atomic_fetch_and_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_4,
+ "__atomic_fetch_and_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_8,
+ "__atomic_fetch_and_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_AND_16,
+ "__atomic_fetch_and_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_N,
+ "__atomic_fetch_nand",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_1,
+ "__atomic_fetch_nand_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_2,
+ "__atomic_fetch_nand_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_4,
+ "__atomic_fetch_nand_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_8,
+ "__atomic_fetch_nand_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_NAND_16,
+ "__atomic_fetch_nand_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_N,
+ "__atomic_fetch_xor",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_1,
+ "__atomic_fetch_xor_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_2,
+ "__atomic_fetch_xor_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_4,
+ "__atomic_fetch_xor_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_8,
+ "__atomic_fetch_xor_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_XOR_16,
+ "__atomic_fetch_xor_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_N,
+ "__atomic_fetch_or",
+ BT_FN_VOID_VAR, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_1,
+ "__atomic_fetch_or_1",
+ BT_FN_I1_VPTR_I1_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_2,
+ "__atomic_fetch_or_2",
+ BT_FN_I2_VPTR_I2_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_4,
+ "__atomic_fetch_or_4",
+ BT_FN_I4_VPTR_I4_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_8,
+ "__atomic_fetch_or_8",
+ BT_FN_I8_VPTR_I8_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FETCH_OR_16,
+ "__atomic_fetch_or_16",
+ BT_FN_I16_VPTR_I16_INT, ATTR_NOTHROWCALL_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE,
+ "__atomic_always_lock_free",
+ BT_FN_BOOL_SIZE_CONST_VPTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_IS_LOCK_FREE,
+ "__atomic_is_lock_free",
+ BT_FN_BOOL_SIZE_CONST_VPTR, ATTR_CONST_NOTHROW_LEAF_LIST)
+
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_THREAD_FENCE,
+ "__atomic_thread_fence",
+ BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_SIGNAL_FENCE,
+ "__atomic_signal_fence",
+ BT_FN_VOID_INT, ATTR_NOTHROW_LEAF_LIST)
+
+/* This one is actually a function in libatomic and not expected to be
+ inlined, declared here for convenience of targets generating calls
+ to it. */
+DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_FERAISEEXCEPT,
+ "__atomic_feraiseexcept",
+ BT_FN_VOID_INT, ATTR_LEAF_LIST)
diff --git a/support/cpp/gcc/system.h b/support/cpp/gcc/system.h
new file mode 100644
index 000000000..c5562cc49
--- /dev/null
+++ b/support/cpp/gcc/system.h
@@ -0,0 +1,1320 @@
+/* Get common system includes and various definitions and declarations based
+ on autoconf macros.
+ 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_SYSTEM_H
+#define GCC_SYSTEM_H
+
+/* Define this so that inttypes.h defines the PRI?64 macros even
+ when compiling with a C++ compiler. Define it here so in the
+ event inttypes.h gets pulled in by another header it is already
+ defined. */
+#define __STDC_FORMAT_MACROS
+
+/* We must include stdarg.h before stdio.h. */
+#include <stdarg.h>
+
+#ifndef va_copy
+# ifdef __va_copy
+# define va_copy(d,s) __va_copy (d, s)
+# else
+# define va_copy(d,s) ((d) = (s))
+# endif
+#endif
+
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#include <stdio.h>
+
+/* Define a generic NULL if one hasn't already been defined. */
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Use the unlocked open routines from libiberty. */
+
+/* Some of these are #define on some systems, e.g. on AIX to redirect
+ the names to 64bit capable functions for LARGE_FILES support. These
+ redefs are pointless here so we can override them. */
+
+#undef fopen
+#undef freopen
+
+#define fopen(PATH, MODE) fopen_unlocked (PATH, MODE)
+#define fdopen(FILDES, MODE) fdopen_unlocked (FILDES, MODE)
+#define freopen(PATH, MODE, STREAM) freopen_unlocked (PATH, MODE, STREAM)
+
+/* The compiler is not a multi-threaded application and therefore we
+ do not have to use the locking functions. In fact, using the locking
+ functions can cause the compiler to be significantly slower under
+ I/O bound conditions (such as -g -O0 on very large source files).
+
+ HAVE_DECL_PUTC_UNLOCKED actually indicates whether or not the stdio
+ code is multi-thread safe by default. If it is set to 0, then do
+ not worry about using the _unlocked functions.
+
+ fputs_unlocked, fwrite_unlocked, and fprintf_unlocked are
+ extensions and need to be prototyped by hand (since we do not
+ define _GNU_SOURCE). */
+
+#if defined HAVE_DECL_PUTC_UNLOCKED && HAVE_DECL_PUTC_UNLOCKED
+
+# ifdef HAVE_PUTC_UNLOCKED
+# undef putc
+# define putc(C, Stream) putc_unlocked (C, Stream)
+# endif
+# ifdef HAVE_PUTCHAR_UNLOCKED
+# undef putchar
+# define putchar(C) putchar_unlocked (C)
+# endif
+# ifdef HAVE_GETC_UNLOCKED
+# undef getc
+# define getc(Stream) getc_unlocked (Stream)
+# endif
+# ifdef HAVE_GETCHAR_UNLOCKED
+# undef getchar
+# define getchar() getchar_unlocked ()
+# endif
+# ifdef HAVE_FPUTC_UNLOCKED
+# undef fputc
+# define fputc(C, Stream) fputc_unlocked (C, Stream)
+# endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+# ifdef HAVE_CLEARERR_UNLOCKED
+# undef clearerr
+# define clearerr(Stream) clearerr_unlocked (Stream)
+# if defined (HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED
+extern void clearerr_unlocked (FILE *);
+# endif
+# endif
+# ifdef HAVE_FEOF_UNLOCKED
+# undef feof
+# define feof(Stream) feof_unlocked (Stream)
+# if defined (HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED
+extern int feof_unlocked (FILE *);
+# endif
+# endif
+# ifdef HAVE_FILENO_UNLOCKED
+# undef fileno
+# define fileno(Stream) fileno_unlocked (Stream)
+# if defined (HAVE_DECL_FILENO_UNLOCKED) && !HAVE_DECL_FILENO_UNLOCKED
+extern int fileno_unlocked (FILE *);
+# endif
+# endif
+# ifdef HAVE_FFLUSH_UNLOCKED
+# undef fflush
+# define fflush(Stream) fflush_unlocked (Stream)
+# if defined (HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED
+extern int fflush_unlocked (FILE *);
+# endif
+# endif
+# ifdef HAVE_FGETC_UNLOCKED
+# undef fgetc
+# define fgetc(Stream) fgetc_unlocked (Stream)
+# if defined (HAVE_DECL_FGETC_UNLOCKED) && !HAVE_DECL_FGETC_UNLOCKED
+extern int fgetc_unlocked (FILE *);
+# endif
+# endif
+# ifdef HAVE_FGETS_UNLOCKED
+# undef fgets
+# define fgets(S, n, Stream) fgets_unlocked (S, n, Stream)
+# if defined (HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED
+extern char *fgets_unlocked (char *, int, FILE *);
+# endif
+# endif
+# ifdef HAVE_FPUTS_UNLOCKED
+# undef fputs
+# define fputs(String, Stream) fputs_unlocked (String, Stream)
+# if defined (HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED
+extern int fputs_unlocked (const char *, FILE *);
+# endif
+# endif
+# ifdef HAVE_FERROR_UNLOCKED
+# undef ferror
+# define ferror(Stream) ferror_unlocked (Stream)
+# if defined (HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED
+extern int ferror_unlocked (FILE *);
+# endif
+# endif
+# ifdef HAVE_FREAD_UNLOCKED
+# undef fread
+# define fread(Ptr, Size, N, Stream) fread_unlocked (Ptr, Size, N, Stream)
+# if defined (HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED
+extern size_t fread_unlocked (void *, size_t, size_t, FILE *);
+# endif
+# endif
+# ifdef HAVE_FWRITE_UNLOCKED
+# undef fwrite
+# define fwrite(Ptr, Size, N, Stream) fwrite_unlocked (Ptr, Size, N, Stream)
+# if defined (HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED
+extern size_t fwrite_unlocked (const void *, size_t, size_t, FILE *);
+# endif
+# endif
+# ifdef HAVE_FPRINTF_UNLOCKED
+# undef fprintf
+/* We can't use a function-like macro here because we don't know if
+ we have varargs macros. */
+# define fprintf fprintf_unlocked
+# if defined (HAVE_DECL_FPRINTF_UNLOCKED) && !HAVE_DECL_FPRINTF_UNLOCKED
+extern int fprintf_unlocked (FILE *, const char *, ...);
+# endif
+# endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/* ??? Glibc's fwrite/fread_unlocked macros cause
+ "warning: signed and unsigned type in conditional expression". */
+#undef fread_unlocked
+#undef fwrite_unlocked
+
+/* Include <string> before "safe-ctype.h" to avoid GCC poisoning
+ the ctype macros through safe-ctype.h */
+
+#ifdef __cplusplus
+#ifdef INCLUDE_STRING
+# include <string>
+#endif
+#endif
+
+/* There are an extraordinary number of issues with <ctype.h>.
+ The last straw is that it varies with the locale. Use libiberty's
+ replacement instead. */
+#include "safe-ctype.h"
+
+#include <sys/types.h>
+
+#include <errno.h>
+
+#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
+extern int errno;
+#endif
+
+#ifdef __cplusplus
+#if defined (INCLUDE_ALGORITHM) || !defined (HAVE_SWAP_IN_UTILITY)
+# include <algorithm>
+#endif
+#ifdef INCLUDE_LIST
+# include <list>
+#endif
+#ifdef INCLUDE_MAP
+# include <map>
+#endif
+#ifdef INCLUDE_SET
+# include <set>
+#endif
+#ifdef INCLUDE_VECTOR
+# include <vector>
+#endif
+#ifdef INCLUDE_ARRAY
+# include <array>
+#endif
+#ifdef INCLUDE_FUNCTIONAL
+# include <functional>
+#endif
+# include <cstring>
+# include <initializer_list>
+# include <new>
+# include <utility>
+# include <type_traits>
+#endif
+
+/* Some of glibc's string inlines cause warnings. Plus we'd rather
+ rely on (and therefore test) GCC's string builtins. */
+#define __NO_STRING_INLINES
+
+#ifdef STRING_WITH_STRINGS
+# include <string.h>
+# include <strings.h>
+#else
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+# endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+/* When compiling C++ we need to include <cstdlib> as well as <stdlib.h> so
+ that it is processed before we poison "malloc"; otherwise, if a source
+ file uses a standard library header that includes <cstdlib>, we will get
+ an error about 'using std::malloc'. */
+#ifdef __cplusplus
+#include <cstdlib>
+#endif
+
+/* Undef vec_free from AIX stdlib.h header which conflicts with vec.h. */
+#undef vec_free
+
+/* If we don't have an overriding definition, set SUCCESS_EXIT_CODE and
+ FATAL_EXIT_CODE to EXIT_SUCCESS and EXIT_FAILURE respectively,
+ or 0 and 1 if those macros are not defined. */
+#ifndef SUCCESS_EXIT_CODE
+# ifdef EXIT_SUCCESS
+# define SUCCESS_EXIT_CODE EXIT_SUCCESS
+# else
+# define SUCCESS_EXIT_CODE 0
+# endif
+#endif
+
+#ifndef FATAL_EXIT_CODE
+# ifdef EXIT_FAILURE
+# define FATAL_EXIT_CODE EXIT_FAILURE
+# else
+# define FATAL_EXIT_CODE 1
+# endif
+#endif
+
+#define ICE_EXIT_CODE 4
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+/* We use these identifiers later and they appear in some vendor param.h's. */
+# undef PREFETCH
+# undef m_slot
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+/* A macro to determine whether a VALUE lies inclusively within a
+ certain range without evaluating the VALUE more than once. This
+ macro won't warn if the VALUE is unsigned and the LOWER bound is
+ zero, as it would e.g. with "VALUE >= 0 && ...". Note the LOWER
+ bound *is* evaluated twice, and LOWER must not be greater than
+ UPPER. However the bounds themselves can be either positive or
+ negative. */
+#define IN_RANGE(VALUE, LOWER, UPPER) \
+ ((unsigned HOST_WIDE_INT) (VALUE) - (unsigned HOST_WIDE_INT) (LOWER) \
+ <= (unsigned HOST_WIDE_INT) (UPPER) - (unsigned HOST_WIDE_INT) (LOWER))
+
+/* Infrastructure for defining missing _MAX and _MIN macros. Note that
+ macros defined with these cannot be used in #if. */
+
+/* The extra casts work around common compiler bugs. */
+#define INTTYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
+ It is necessary at least when t == time_t. */
+#define INTTYPE_MINIMUM(t) ((t) (INTTYPE_SIGNED (t) \
+ ? (t) 1 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
+#define INTTYPE_MAXIMUM(t) ((t) (~ (t) 0 - INTTYPE_MINIMUM (t)))
+
+/* Use that infrastructure to provide a few constants. */
+#ifndef UCHAR_MAX
+# define UCHAR_MAX INTTYPE_MAXIMUM (unsigned char)
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# ifdef HAVE_TIME_H
+# include <time.h>
+# endif
+# endif
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# ifdef HAVE_SYS_FILE_H
+# include <sys/file.h>
+# endif
+#endif
+
+#ifdef HAVE_SYS_LOCKING_H
+# include <sys/locking.h>
+#endif
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif
+#ifndef F_OK
+# define F_OK 0
+# define X_OK 1
+# define W_OK 2
+# define R_OK 4
+#endif
+#ifndef O_RDONLY
+# define O_RDONLY 0
+#endif
+#ifndef O_WRONLY
+# define O_WRONLY 1
+#endif
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+/* Some systems define these in, e.g., param.h. We undefine these names
+ here to avoid the warnings. We prefer to use our definitions since we
+ know they are correct. */
+
+#undef MIN
+#undef MAX
+#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+/* Returns the least number N such that N * Y >= X. */
+#define CEIL(x,y) (((x) + (y) - 1) / (y))
+
+/* This macro rounds x up to the y boundary. */
+#define ROUND_UP(x,y) (((x) + (y) - 1) & ~((y) - 1))
+
+/* This macro rounds x down to the y boundary. */
+#define ROUND_DOWN(x,y) ((x) & ~((y) - 1))
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(S) ((S) & 0x7f)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(S) (((S) & 0xff) == 0)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
+#endif
+#ifndef WSTOPSIG
+#define WSTOPSIG WEXITSTATUS
+#endif
+#ifndef WCOREDUMP
+#define WCOREDUMP(S) ((S) & WCOREFLG)
+#endif
+#ifndef WCOREFLG
+#define WCOREFLG 0200
+#endif
+
+#include <signal.h>
+#if !defined (SIGCHLD) && defined (SIGCLD)
+# define SIGCHLD SIGCLD
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *)-1)
+#endif
+
+#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+/* The HAVE_DECL_* macros are three-state, undefined, 0 or 1. If they
+ are defined to 0 then we must provide the relevant declaration
+ here. These checks will be in the undefined state while configure
+ is running so be careful to test "defined (HAVE_DECL_*)". */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (HAVE_DECL_ATOF) && !HAVE_DECL_ATOF
+extern double atof (const char *);
+#endif
+
+#if defined (HAVE_DECL_ATOL) && !HAVE_DECL_ATOL
+extern long atol (const char *);
+#endif
+
+#if defined (HAVE_DECL_FREE) && !HAVE_DECL_FREE
+extern void free (void *);
+#endif
+
+#if defined (HAVE_DECL_GETCWD) && !HAVE_DECL_GETCWD
+extern char *getcwd (char *, size_t);
+#endif
+
+#if defined (HAVE_DECL_GETENV) && !HAVE_DECL_GETENV
+extern char *getenv (const char *);
+#endif
+
+#if defined (HAVE_DECL_GETOPT) && !HAVE_DECL_GETOPT
+extern int getopt (int, char * const *, const char *);
+#endif
+
+#if defined (HAVE_DECL_GETPAGESIZE) && !HAVE_DECL_GETPAGESIZE
+extern int getpagesize (void);
+#endif
+
+#if defined (HAVE_DECL_GETWD) && !HAVE_DECL_GETWD
+extern char *getwd (char *);
+#endif
+
+#if defined (HAVE_DECL_SBRK) && !HAVE_DECL_SBRK
+extern void *sbrk (int);
+#endif
+
+#if defined (HAVE_DECL_SETENV) && !HAVE_DECL_SETENV
+int setenv(const char *, const char *, int);
+#endif
+
+#if defined (HAVE_DECL_STRSTR) && !HAVE_DECL_STRSTR
+extern char *strstr (const char *, const char *);
+#endif
+
+#if defined (HAVE_DECL_STPCPY) && !HAVE_DECL_STPCPY
+extern char *stpcpy (char *, const char *);
+#endif
+
+#if defined (HAVE_DECL_UNSETENV) && !HAVE_DECL_UNSETENV
+int unsetenv(const char *);
+#endif
+
+#if defined (HAVE_DECL_MALLOC) && !HAVE_DECL_MALLOC
+extern void *malloc (size_t);
+#endif
+
+#if defined (HAVE_DECL_CALLOC) && !HAVE_DECL_CALLOC
+extern void *calloc (size_t, size_t);
+#endif
+
+#if defined (HAVE_DECL_REALLOC) && !HAVE_DECL_REALLOC
+extern void *realloc (void *, size_t);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifndef SIZE_MAX
+# define SIZE_MAX INTTYPE_MAXIMUM (size_t)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* If the system doesn't provide strsignal, we get it defined in
+ libiberty but no declaration is supplied. */
+#if !defined (HAVE_STRSIGNAL) \
+ || (defined (HAVE_DECL_STRSIGNAL) && !HAVE_DECL_STRSIGNAL)
+# ifndef strsignal
+extern const char *strsignal (int);
+# endif
+#endif
+
+#ifdef HAVE_GETRLIMIT
+# if defined (HAVE_DECL_GETRLIMIT) && !HAVE_DECL_GETRLIMIT
+# ifndef getrlimit
+struct rlimit;
+extern int getrlimit (int, struct rlimit *);
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SETRLIMIT
+# if defined (HAVE_DECL_SETRLIMIT) && !HAVE_DECL_SETRLIMIT
+# ifndef setrlimit
+struct rlimit;
+extern int setrlimit (int, const struct rlimit *);
+# endif
+# endif
+#endif
+
+#if defined (HAVE_DECL_ABORT) && !HAVE_DECL_ABORT
+extern void abort (void);
+#endif
+
+#if defined (HAVE_DECL_SNPRINTF) && !HAVE_DECL_SNPRINTF
+extern int snprintf (char *, size_t, const char *, ...);
+#endif
+
+#if defined (HAVE_DECL_VSNPRINTF) && !HAVE_DECL_VSNPRINTF
+extern int vsnprintf (char *, size_t, const char *, va_list);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* 1 if we have C99 designated initializers. */
+#if !defined(HAVE_DESIGNATED_INITIALIZERS)
+#ifdef __cplusplus
+#define HAVE_DESIGNATED_INITIALIZERS 0
+#else
+#define HAVE_DESIGNATED_INITIALIZERS \
+ ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L))
+#endif
+#endif
+
+#if !defined(HAVE_DESIGNATED_UNION_INITIALIZERS)
+#ifdef __cplusplus
+#define HAVE_DESIGNATED_UNION_INITIALIZERS (GCC_VERSION >= 4007)
+#else
+#define HAVE_DESIGNATED_UNION_INITIALIZERS \
+ ((GCC_VERSION >= 2007) || (__STDC_VERSION__ >= 199901L))
+#endif
+#endif
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+/* Test if something is a normal file. */
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+
+/* Test if something is a directory. */
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+
+/* Test if something is a character special file. */
+#ifndef S_ISCHR
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+
+/* Test if something is a block special file. */
+#ifndef S_ISBLK
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+
+/* Test if something is a socket. */
+#ifndef S_ISSOCK
+# ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+# else
+# define S_ISSOCK(m) 0
+# endif
+#endif
+
+/* Test if something is a FIFO. */
+#ifndef S_ISFIFO
+# ifdef S_IFIFO
+# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+# else
+# define S_ISFIFO(m) 0
+# endif
+#endif
+
+/* Define well known filenos if the system does not define them. */
+#ifndef STDIN_FILENO
+# define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+# define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Some systems have mkdir that takes a single argument. */
+#ifdef MKDIR_TAKES_ONE_ARG
+# define mkdir(a,b) mkdir (a)
+#endif
+
+#ifndef HAVE_KILL
+# define kill(p,s) raise (s)
+#endif
+
+/* Provide a way to print an address via printf. */
+#ifndef HOST_PTR_PRINTF
+#define HOST_PTR_PRINTF "%p"
+#endif /* ! HOST_PTR_PRINTF */
+
+/* By default, colon separates directories in a path. */
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
+#endif
+
+/* Filename handling macros. */
+#include "filenames.h"
+
+/* These should be phased out in favor of IS_DIR_SEPARATOR, where possible. */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# ifdef HAVE_DOS_BASED_FILE_SYSTEM
+# define DIR_SEPARATOR_2 '\\'
+# endif
+#endif
+
+#if defined (ENABLE_PLUGIN) && defined (HAVE_DLFCN_H)
+/* If plugin support is enabled, we could use libdl. */
+#include <dlfcn.h>
+#endif
+
+/* Do not introduce a gmp.h dependency on the build system. */
+#ifndef GENERATOR_FILE
+#include <gmp.h>
+#endif
+
+/* Get libiberty declarations. */
+#include "libiberty.h"
+
+#undef FFS /* Some systems predefine this symbol; don't let it interfere. */
+#undef FLOAT /* Likewise. */
+#undef ABS /* Likewise. */
+#undef PC /* Likewise. */
+
+/* Provide a default for the HOST_BIT_BUCKET.
+ This suffices for POSIX-like hosts. */
+
+#ifndef HOST_BIT_BUCKET
+#define HOST_BIT_BUCKET "/dev/null"
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
+#endif
+
+/* Various error reporting routines want to use __FUNCTION__. */
+#if (GCC_VERSION < 2007)
+#ifndef __FUNCTION__
+#define __FUNCTION__ "?"
+#endif /* ! __FUNCTION__ */
+#endif
+
+/* __builtin_expect(A, B) evaluates to A, but notifies the compiler that
+ the most likely value of A is B. This feature was added at some point
+ between 2.95 and 3.0. Let's use 3.0 as the lower bound for now. */
+#if (GCC_VERSION < 3000)
+#define __builtin_expect(a, b) (a)
+#endif
+
+/* Some of the headers included by <memory> can use "abort" within a
+ namespace, e.g. "_VSTD::abort();", which fails after we use the
+ preprocessor to redefine "abort" as "fancy_abort" below. */
+
+#ifdef INCLUDE_MEMORY
+# include <memory>
+#endif
+
+#ifdef INCLUDE_MALLOC_H
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
+#include <malloc.h>
+#endif
+#endif
+
+#ifdef INCLUDE_ISL
+#ifdef HAVE_isl
+#include <isl/options.h>
+#include <isl/ctx.h>
+#include <isl/val.h>
+#include <isl/set.h>
+#include <isl/union_set.h>
+#include <isl/map.h>
+#include <isl/union_map.h>
+#include <isl/aff.h>
+#include <isl/constraint.h>
+#include <isl/flow.h>
+#include <isl/ilp.h>
+#include <isl/schedule.h>
+#include <isl/ast_build.h>
+#include <isl/schedule_node.h>
+#include <isl/id.h>
+#include <isl/space.h>
+#endif
+#endif
+
+/* Redefine abort to report an internal error w/o coredump, and
+ reporting the location of the error in the source file. */
+extern void fancy_abort (const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
+
+/* Use gcc_assert(EXPR) to test invariants. */
+#if ENABLE_ASSERT_CHECKING
+#define gcc_assert(EXPR) \
+ ((void)(!(EXPR) ? fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0 : 0))
+#elif (GCC_VERSION >= 4005)
+#define gcc_assert(EXPR) \
+ ((void)(__builtin_expect (!(EXPR), 0) ? __builtin_unreachable (), 0 : 0))
+#else
+/* Include EXPR, so that unused variable warnings do not occur. */
+#define gcc_assert(EXPR) ((void)(0 && (EXPR)))
+#endif
+
+#if CHECKING_P
+#define gcc_checking_assert(EXPR) gcc_assert (EXPR)
+#else
+/* N.B.: in release build EXPR is not evaluated. */
+#define gcc_checking_assert(EXPR) ((void)(0 && (EXPR)))
+#endif
+
+#if GCC_VERSION >= 4000
+#define ALWAYS_INLINE inline __attribute__ ((always_inline))
+#else
+#define ALWAYS_INLINE inline
+#endif
+
+#if GCC_VERSION >= 3004
+#define WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
+#else
+#define WARN_UNUSED_RESULT
+#endif
+
+/* Use gcc_unreachable() to mark unreachable locations (like an
+ unreachable default case of a switch. Do not use gcc_assert(0). */
+#if (GCC_VERSION >= 4005) && !ENABLE_ASSERT_CHECKING
+#define gcc_unreachable() __builtin_unreachable ()
+#else
+#define gcc_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
+#endif
+
+#if GCC_VERSION >= 7000 && defined(__has_attribute)
+# if __has_attribute(fallthrough)
+# define gcc_fallthrough() __attribute__((fallthrough))
+# else
+# define gcc_fallthrough()
+# endif
+#else
+# define gcc_fallthrough()
+#endif
+
+#if GCC_VERSION >= 3001
+#define STATIC_CONSTANT_P(X) (__builtin_constant_p (X) && (X))
+#else
+#define STATIC_CONSTANT_P(X) (false && (X))
+#endif
+
+/* static_assert (COND, MESSAGE) is available in C++11 onwards. */
+#if __cplusplus >= 201103L
+#define STATIC_ASSERT(X) \
+ static_assert ((X), #X)
+#else
+#define STATIC_ASSERT(X) \
+ typedef int assertion1[(X) ? 1 : -1] ATTRIBUTE_UNUSED
+#endif
+
+/* Provide a fake boolean type. We make no attempt to use the
+ C99 _Bool, as it may not be available in the bootstrap compiler,
+ and even if it is, it is liable to be buggy.
+ This must be after all inclusion of system headers, as some of
+ them will mess us up. */
+
+#undef TRUE
+#undef FALSE
+
+#ifdef __cplusplus
+ /* Obsolete. */
+# define TRUE true
+# define FALSE false
+#else /* !__cplusplus */
+# undef bool
+# undef true
+# undef false
+
+# define bool unsigned char
+# define true 1
+# define false 0
+
+ /* Obsolete. */
+# define TRUE true
+# define FALSE false
+#endif /* !__cplusplus */
+
+/* Some compilers do not allow the use of unsigned char in bitfields. */
+#define BOOL_BITFIELD unsigned int
+
+/* GCC older than 4.4 have broken C++ value initialization handling, see
+ PR11309, PR30111, PR33916, PR82939 and PR84405 for more details. */
+#if GCC_VERSION > 0 && GCC_VERSION < 4004 && !defined(__clang__)
+# define BROKEN_VALUE_INITIALIZATION
+#endif
+
+/* As the last action in this file, we poison the identifiers that
+ shouldn't be used. Note, luckily gcc-3.0's token-based integrated
+ preprocessor won't trip on poisoned identifiers that arrive from
+ the expansion of macros. E.g. #define strrchr rindex, won't error
+ if rindex is poisoned after this directive is issued and later on
+ strrchr is called.
+
+ Note: We define bypass macros for the few cases where we really
+ want to use the libc memory allocation routines. Otherwise we
+ insist you use the "x" versions from libiberty. */
+
+#define really_call_malloc malloc
+#define really_call_calloc calloc
+#define really_call_realloc realloc
+
+#if defined(FLEX_SCANNER) || defined(YYBISON) || defined(YYBYACC)
+/* Flex and bison use malloc and realloc. Yuk. Note that this means
+ really_call_* cannot be used in a .l or .y file. */
+#define malloc xmalloc
+#define realloc xrealloc
+#endif
+
+#if (GCC_VERSION >= 3000)
+
+/* Note autoconf checks for prototype declarations and includes
+ system.h while doing so. Only poison these tokens if actually
+ compiling gcc, so that the autoconf declaration tests for malloc
+ etc don't spuriously fail. */
+#ifdef IN_GCC
+
+#undef calloc
+#undef strdup
+#undef strndup
+ #pragma GCC poison calloc strdup strndup
+
+#if !defined(FLEX_SCANNER) && !defined(YYBISON)
+#undef malloc
+#undef realloc
+ #pragma GCC poison malloc realloc
+#endif
+
+/* The %m format should be used when GCC's main diagnostic functions
+ supporting %m are available, and xstrerror from libiberty
+ otherwise. */
+#undef strerror
+ #pragma GCC poison strerror
+
+/* loc_t is defined on some systems and too inviting for some
+ programmers to avoid. */
+#undef loc_t
+ #pragma GCC poison loc_t
+
+/* Old target macros that have moved to the target hooks structure. */
+ #pragma GCC poison ASM_OPEN_PAREN ASM_CLOSE_PAREN \
+ FUNCTION_PROLOGUE FUNCTION_EPILOGUE \
+ FUNCTION_END_PROLOGUE FUNCTION_BEGIN_EPILOGUE \
+ DECL_MACHINE_ATTRIBUTES COMP_TYPE_ATTRIBUTES INSERT_ATTRIBUTES \
+ VALID_MACHINE_DECL_ATTRIBUTE VALID_MACHINE_TYPE_ATTRIBUTE \
+ SET_DEFAULT_TYPE_ATTRIBUTES SET_DEFAULT_DECL_ATTRIBUTES \
+ MERGE_MACHINE_TYPE_ATTRIBUTES MERGE_MACHINE_DECL_ATTRIBUTES \
+ MD_INIT_BUILTINS MD_EXPAND_BUILTIN ASM_OUTPUT_CONSTRUCTOR \
+ ASM_OUTPUT_DESTRUCTOR SIGNED_CHAR_SPEC MAX_CHAR_TYPE_SIZE \
+ WCHAR_UNSIGNED UNIQUE_SECTION SELECT_SECTION SELECT_RTX_SECTION \
+ ENCODE_SECTION_INFO STRIP_NAME_ENCODING ASM_GLOBALIZE_LABEL \
+ ASM_OUTPUT_MI_THUNK CONST_COSTS RTX_COSTS DEFAULT_RTX_COSTS \
+ ADDRESS_COST MACHINE_DEPENDENT_REORG ASM_FILE_START ASM_FILE_END \
+ ASM_SIMPLIFY_DWARF_ADDR INIT_TARGET_OPTABS INIT_SUBTARGET_OPTABS \
+ INIT_GOFAST_OPTABS MULSI3_LIBCALL MULDI3_LIBCALL DIVSI3_LIBCALL \
+ DIVDI3_LIBCALL UDIVSI3_LIBCALL UDIVDI3_LIBCALL MODSI3_LIBCALL \
+ MODDI3_LIBCALL UMODSI3_LIBCALL UMODDI3_LIBCALL BUILD_VA_LIST_TYPE \
+ PRETEND_OUTGOING_VARARGS_NAMED STRUCT_VALUE_INCOMING_REGNUM \
+ ASM_OUTPUT_SECTION_NAME PROMOTE_FUNCTION_ARGS PROMOTE_FUNCTION_MODE \
+ STRUCT_VALUE_INCOMING STRICT_ARGUMENT_NAMING \
+ PROMOTE_FUNCTION_RETURN PROMOTE_PROTOTYPES STRUCT_VALUE_REGNUM \
+ SETUP_INCOMING_VARARGS EXPAND_BUILTIN_SAVEREGS \
+ DEFAULT_SHORT_ENUMS SPLIT_COMPLEX_ARGS MD_ASM_CLOBBERS \
+ HANDLE_PRAGMA_REDEFINE_EXTNAME HANDLE_PRAGMA_EXTERN_PREFIX \
+ MUST_PASS_IN_STACK FUNCTION_ARG_PASS_BY_REFERENCE \
+ VECTOR_MODE_SUPPORTED_P TARGET_SUPPORTS_HIDDEN \
+ FUNCTION_ARG_PARTIAL_NREGS ASM_OUTPUT_DWARF_DTPREL \
+ ALLOCATE_INITIAL_VALUE LEGITIMIZE_ADDRESS FRAME_POINTER_REQUIRED \
+ CAN_ELIMINATE TRAMPOLINE_TEMPLATE INITIALIZE_TRAMPOLINE \
+ TRAMPOLINE_ADJUST_ADDRESS STATIC_CHAIN STATIC_CHAIN_INCOMING \
+ RETURN_POPS_ARGS UNITS_PER_SIMD_WORD OVERRIDE_OPTIONS \
+ OPTIMIZATION_OPTIONS CLASS_LIKELY_SPILLED_P \
+ USING_SJLJ_EXCEPTIONS TARGET_UNWIND_INFO \
+ CAN_DEBUG_WITHOUT_FP UNLIKELY_EXECUTED_TEXT_SECTION_NAME \
+ HOT_TEXT_SECTION_NAME LEGITIMATE_CONSTANT_P ALWAYS_STRIP_DOTDOT \
+ OUTPUT_ADDR_CONST_EXTRA SMALL_REGISTER_CLASSES ASM_OUTPUT_IDENT \
+ ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE \
+ LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE \
+ CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P \
+ STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD \
+ HARD_REGNO_CALL_PART_CLOBBERED HARD_REGNO_MODE_OK \
+ MODES_TIEABLE_P FUNCTION_ARG_PADDING SLOW_UNALIGNED_ACCESS \
+ HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE \
+ SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS \
+ TRULY_NOOP_TRUNCATION FUNCTION_ARG_OFFSET CONSTANT_ALIGNMENT \
+ STARTING_FRAME_OFFSET
+
+/* Target macros only used for code built for the target, that have
+ moved to libgcc-tm.h or have never been present elsewhere. */
+ #pragma GCC poison DECLARE_LIBRARY_RENAMES LIBGCC2_GNU_PREFIX \
+ MD_UNWIND_SUPPORT MD_FROB_UPDATE_CONTEXT ENABLE_EXECUTE_STACK \
+ REG_VALUE_IN_UNWIND_CONTEXT ASSUME_EXTENDED_UNWIND_CONTEXT
+
+/* Other obsolete target macros, or macros that used to be in target
+ headers and were not used, and may be obsolete or may never have
+ been used. */
+ #pragma GCC poison INT_ASM_OP ASM_OUTPUT_EH_REGION_BEG CPP_PREDEFINES \
+ ASM_OUTPUT_EH_REGION_END ASM_OUTPUT_LABELREF_AS_INT SMALL_STACK \
+ DOESNT_NEED_UNWINDER EH_TABLE_LOOKUP OBJC_SELECTORS_WITHOUT_LABELS \
+ OMIT_EH_TABLE EASY_DIV_EXPR IMPLICIT_FIX_EXPR \
+ LONGJMP_RESTORE_FROM_STACK MAX_INT_TYPE_SIZE ASM_IDENTIFY_GCC \
+ STDC_VALUE TRAMPOLINE_ALIGN ASM_IDENTIFY_GCC_AFTER_SOURCE \
+ SLOW_ZERO_EXTEND SUBREG_REGNO_OFFSET DWARF_LINE_MIN_INSTR_LENGTH \
+ TRADITIONAL_RETURN_FLOAT NO_BUILTIN_SIZE_TYPE \
+ NO_BUILTIN_PTRDIFF_TYPE NO_BUILTIN_WCHAR_TYPE NO_BUILTIN_WINT_TYPE \
+ BLOCK_PROFILER BLOCK_PROFILER_CODE FUNCTION_BLOCK_PROFILER \
+ FUNCTION_BLOCK_PROFILER_EXIT MACHINE_STATE_SAVE \
+ MACHINE_STATE_RESTORE SCCS_DIRECTIVE SECTION_ASM_OP BYTEORDER \
+ 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_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 \
+ LOAD_ARGS_REVERSED MAX_INTEGER_COMPUTATION_MODE \
+ CONVERT_HARD_REGISTER_TO_SSA_P ASM_OUTPUT_MAIN_SOURCE_FILENAME \
+ FIRST_INSN_ADDRESS TEXT_SECTION SHARED_BSS_SECTION_ASM_OP \
+ PROMOTED_MODE EXPAND_BUILTIN_VA_END \
+ LINKER_DOES_NOT_WORK_WITH_DWARF2 FUNCTION_ARG_KEEP_AS_REFERENCE \
+ GIV_SORT_CRITERION MAX_LONG_TYPE_SIZE MAX_LONG_DOUBLE_TYPE_SIZE \
+ 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 \
+ 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 \
+ 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 \
+ LINK_LIBGCC_SPECIAL DONT_ACCESS_GBLS_AFTER_EPILOGUE \
+ TARGET_OPTIONS TARGET_SWITCHES EXTRA_CC_MODES FINALIZE_PIC \
+ PREDICATE_CODES SPECIAL_MODE_PREDICATES UNALIGNED_WORD_ASM_OP \
+ EXTRA_SECTIONS EXTRA_SECTION_FUNCTIONS READONLY_DATA_SECTION \
+ TARGET_ASM_EXCEPTION_SECTION TARGET_ASM_EH_FRAME_SECTION \
+ SMALL_ARG_MAX ASM_OUTPUT_SHARED_BSS ASM_OUTPUT_SHARED_COMMON \
+ ASM_OUTPUT_SHARED_LOCAL ASM_MAKE_LABEL_LINKONCE \
+ STACK_CHECK_PROBE_INTERVAL STACK_CHECK_PROBE_LOAD \
+ ORDER_REGS_FOR_LOCAL_ALLOC FUNCTION_OUTGOING_VALUE \
+ ASM_DECLARE_CONSTANT_NAME MODIFY_TARGET_NAME SWITCHES_NEED_SPACES \
+ SWITCH_CURTAILS_COMPILATION SWITCH_TAKES_ARG WORD_SWITCH_TAKES_ARG \
+ TARGET_OPTION_TRANSLATE_TABLE HANDLE_PRAGMA_PACK_PUSH_POP \
+ HANDLE_SYSV_PRAGMA HANDLE_PRAGMA_WEAK CONDITIONAL_REGISTER_USAGE \
+ FUNCTION_ARG_BOUNDARY MUST_USE_SJLJ_EXCEPTIONS US_SOFTWARE_GOFAST \
+ USING_SVR4_H SVR4_ASM_SPEC FUNCTION_ARG FUNCTION_ARG_ADVANCE \
+ FUNCTION_INCOMING_ARG IRA_COVER_CLASSES TARGET_VERSION \
+ MACHINE_TYPE TARGET_HAS_TARGETCM ASM_OUTPUT_BSS \
+ SETJMP_VIA_SAVE_AREA FORBIDDEN_INC_DEC_CLASSES \
+ 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 \
+ 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 \
+ UNALIGNED_LONG_ASM_OP UNALIGNED_DOUBLE_INT_ASM_OP \
+ USE_COMMON_FOR_ONE_ONLY IFCVT_EXTRA_FIELDS IFCVT_INIT_EXTRA_FIELDS \
+ CASE_USE_BIT_TESTS FIXUNS_TRUNC_LIKE_FIX_TRUNC \
+ GO_IF_MODE_DEPENDENT_ADDRESS DELAY_SLOTS_FOR_EPILOGUE \
+ ELIGIBLE_FOR_EPILOGUE_DELAY TARGET_C99_FUNCTIONS TARGET_HAS_SINCOS \
+ REG_CLASS_FROM_LETTER CONST_OK_FOR_LETTER_P \
+ CONST_DOUBLE_OK_FOR_LETTER_P EXTRA_CONSTRAINT \
+ REG_CLASS_FROM_CONSTRAINT REG_CLASS_FOR_CONSTRAINT \
+ EXTRA_CONSTRAINT_STR EXTRA_MEMORY_CONSTRAINT \
+ EXTRA_ADDRESS_CONSTRAINT CONST_DOUBLE_OK_FOR_CONSTRAINT_P \
+ CALLER_SAVE_PROFITABLE LARGEST_EXPONENT_IS_NORMAL \
+ ROUND_TOWARDS_ZERO SF_SIZE DF_SIZE XF_SIZE TF_SIZE LIBGCC2_TF_CEXT \
+ LIBGCC2_LONG_DOUBLE_TYPE_SIZE STRUCT_VALUE \
+ EH_FRAME_IN_DATA_SECTION TARGET_FLT_EVAL_METHOD_NON_DEFAULT \
+ JCR_SECTION_NAME TARGET_USE_JCR_SECTION SDB_DEBUGGING_INFO \
+ SDB_DEBUG NO_IMPLICIT_EXTERN_C NOTICE_UPDATE_CC \
+ CC_STATUS_MDEP_INIT CC_STATUS_MDEP CC_STATUS
+
+/* Hooks that are no longer used. */
+ #pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
+ LANG_HOOKS_MARK_TREE LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES \
+ LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS \
+ LANG_HOOKS_PUSHLEVEL LANG_HOOKS_SET_BLOCK \
+ LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \
+ LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \
+ TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN \
+ LANG_HOOKS_MISSING_ARGUMENT LANG_HOOKS_HASH_TYPES \
+ TARGET_HANDLE_OFAST TARGET_OPTION_OPTIMIZATION \
+ TARGET_IRA_COVER_CLASSES TARGET_HELP \
+ TARGET_HANDLE_PRAGMA_EXTERN_PREFIX \
+ TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN \
+ TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD \
+ TARGET_MD_ASM_CLOBBERS TARGET_RELAXED_ORDERING \
+ EXTENDED_SDB_BASIC_TYPES TARGET_INVALID_PARAMETER_TYPE \
+ TARGET_INVALID_RETURN_TYPE
+
+/* Arrays that were deleted in favor of a functional interface. */
+ #pragma GCC poison built_in_decls implicit_built_in_decls
+
+/* Hooks into libgcc2. */
+ #pragma GCC poison LIBGCC2_DOUBLE_TYPE_SIZE LIBGCC2_WORDS_BIG_ENDIAN \
+ LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+
+/* Miscellaneous macros that are no longer used. */
+ #pragma GCC poison USE_MAPPED_LOCATION GET_ENVIRONMENT
+
+/* Libiberty macros that are no longer used in GCC. */
+#undef ANSI_PROTOTYPES
+#undef PTR_CONST
+#undef LONG_DOUBLE
+#undef VPARAMS
+#undef VA_OPEN
+#undef VA_FIXEDARG
+#undef VA_CLOSE
+#undef VA_START
+ #pragma GCC poison ANSI_PROTOTYPES PTR_CONST LONG_DOUBLE VPARAMS VA_OPEN \
+ VA_FIXEDARG VA_CLOSE VA_START
+#endif /* IN_GCC */
+
+/* Front ends should never have to include middle-end headers. Enforce
+ this by poisoning the header double-include protection defines. */
+#ifdef IN_GCC_FRONTEND
+#pragma GCC poison GCC_RTL_H GCC_EXCEPT_H GCC_EXPR_H
+#endif
+
+/* Note: not all uses of the `index' token (e.g. variable names and
+ structure members) have been eliminated. */
+#undef bcopy
+#undef bzero
+#undef bcmp
+#undef rindex
+ #pragma GCC poison bcopy bzero bcmp rindex
+
+/* Poison ENABLE_CHECKING macro that should be replaced with
+ 'if (flag_checking)', or with CHECKING_P macro. */
+#pragma GCC poison ENABLE_CHECKING
+
+#endif /* GCC >= 3.0 */
+
+/* This macro allows casting away const-ness to pass -Wcast-qual
+ warnings. DO NOT USE THIS UNLESS YOU REALLY HAVE TO! It should
+ only be used in certain specific cases. One valid case is where
+ the C standard definitions or prototypes force you to. E.g. if you
+ need to free a const object, or if you pass a const string to
+ execv, et al. Another valid use would be in an allocation function
+ that creates const objects that need to be initialized. In some
+ cases we have non-const functions that return the argument
+ (e.g. next_nonnote_insn). Rather than create const shadow
+ functions, we can cast away const-ness in calling these interfaces
+ if we're careful to verify that the called function does indeed not
+ modify its argument and the return value is only used in a const
+ context. (This can be somewhat dangerous as these assumptions can
+ change after the fact). Beyond these uses, most other cases of
+ using this macro should be viewed with extreme caution. */
+
+#ifdef __cplusplus
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast<TOTYPE> (X))
+#else
+#if defined(__GNUC__) && GCC_VERSION > 4000
+/* GCC 4.0.x has a bug where it may ICE on this expression,
+ so does GCC 3.4.x (PR17436). */
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
+#elif defined(__GNUC__)
+static inline char *
+helper_const_non_const_cast (const char *p)
+{
+ union {
+ const char *const_c;
+ char *c;
+ } val;
+ val.const_c = p;
+ return val.c;
+}
+
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) \
+ ((TOTYPE) helper_const_non_const_cast ((const char *) (FROMTYPE) (X)))
+#else
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((TOTYPE)(FROMTYPE)(X))
+#endif
+#endif
+#define CONST_CAST(TYPE,X) CONST_CAST2 (TYPE, const TYPE, (X))
+#define CONST_CAST_TREE(X) CONST_CAST (union tree_node *, (X))
+#define CONST_CAST_RTX(X) CONST_CAST (struct rtx_def *, (X))
+#define CONST_CAST_RTX_INSN(X) CONST_CAST (struct rtx_insn *, (X))
+#define CONST_CAST_BB(X) CONST_CAST (struct basic_block_def *, (X))
+#define CONST_CAST_GIMPLE(X) CONST_CAST (gimple *, (X))
+
+/* Activate certain diagnostics as warnings (not errors via the
+ -Werror flag). */
+#if GCC_VERSION >= 4003
+/* If asserts are disabled, activate -Wuninitialized as a warning (not
+ an error/-Werror). */
+#ifndef ENABLE_ASSERT_CHECKING
+#pragma GCC diagnostic warning "-Wuninitialized"
+#endif
+#endif
+
+#ifdef ENABLE_VALGRIND_ANNOTATIONS
+# ifdef HAVE_VALGRIND_MEMCHECK_H
+# include <valgrind/memcheck.h>
+# elif defined HAVE_MEMCHECK_H
+# include <memcheck.h>
+# else
+# include <valgrind.h>
+# endif
+/* Compatibility macros to let valgrind 3.1 work. */
+# ifndef VALGRIND_MAKE_MEM_NOACCESS
+# define VALGRIND_MAKE_MEM_NOACCESS VALGRIND_MAKE_NOACCESS
+# endif
+# ifndef VALGRIND_MAKE_MEM_DEFINED
+# define VALGRIND_MAKE_MEM_DEFINED VALGRIND_MAKE_READABLE
+# endif
+# ifndef VALGRIND_MAKE_MEM_UNDEFINED
+# define VALGRIND_MAKE_MEM_UNDEFINED VALGRIND_MAKE_WRITABLE
+# endif
+#else
+/* Avoid #ifdef:s when we can help it. */
+#define VALGRIND_DISCARD(x)
+#define VALGRIND_MALLOCLIKE_BLOCK(w,x,y,z)
+#define VALGRIND_FREELIKE_BLOCK(x,y)
+#endif
+
+/* Macros to temporarily ignore some warnings. */
+#if GCC_VERSION >= 6000
+#define GCC_DIAGNOSTIC_STRINGIFY(x) #x
+#define GCC_DIAGNOSTIC_PUSH_IGNORED(x) \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma (GCC_DIAGNOSTIC_STRINGIFY (GCC diagnostic ignored #x))
+#define GCC_DIAGNOSTIC_POP _Pragma ("GCC diagnostic pop")
+#else
+#define GCC_DIAGNOSTIC_PUSH_IGNORED(x)
+#define GCC_DIAGNOSTIC_POP
+#endif
+
+/* In LTO -fwhole-program build we still want to keep the debug functions available
+ for debugger. Mark them as used to prevent removal. */
+#if (GCC_VERSION > 4000)
+#define DEBUG_FUNCTION __attribute__ ((__used__))
+#define DEBUG_VARIABLE __attribute__ ((__used__))
+#else
+#define DEBUG_FUNCTION
+#define DEBUG_VARIABLE
+#endif
+
+/* General macro to extract bit Y of X. */
+#define TEST_BIT(X, Y) (((X) >> (Y)) & 1)
+
+/* Get definitions of HOST_WIDE_INT. */
+#include "hwint.h"
+
+typedef int sort_r_cmp_fn (const void *, const void *, void *);
+void qsort_chk (void *, size_t, size_t, sort_r_cmp_fn *, void *);
+void gcc_sort_r (void *, size_t, size_t, sort_r_cmp_fn *, void *);
+void gcc_qsort (void *, size_t, size_t, int (*)(const void *, const void *));
+void gcc_stablesort (void *, size_t, size_t,
+ int (*)(const void *, const void *));
+void gcc_stablesort_r (void *, size_t, size_t, sort_r_cmp_fn *, void *data);
+/* Redirect four-argument qsort calls to gcc_qsort; one-argument invocations
+ correspond to vec::qsort, and use C qsort internally. */
+#define PP_5th(a1, a2, a3, a4, a5, ...) a5
+#undef qsort
+#define qsort(...) PP_5th (__VA_ARGS__, gcc_qsort, 3, 2, qsort, 0) (__VA_ARGS__)
+
+#define ONE_K 1024
+#define ONE_M (ONE_K * ONE_K)
+#define ONE_G (ONE_K * ONE_M)
+
+/* Display a number as an integer multiple of either:
+ - 1024, if said integer is >= to 10 K (in base 2)
+ - 1024 * 1024, if said integer is >= 10 M in (base 2)
+ */
+#define SIZE_SCALE(x) (((x) < 10 * ONE_K \
+ ? (x) \
+ : ((x) < 10 * ONE_M \
+ ? (x) / ONE_K \
+ : (x) / ONE_M)))
+
+/* For a given integer, display either:
+ - the character 'k', if the number is higher than 10 K (in base 2)
+ but strictly lower than 10 M (in base 2)
+ - the character 'M' if the number is higher than 10 M (in base2)
+ - the charcter ' ' if the number is strictly lower than 10 K */
+#define SIZE_LABEL(x) ((x) < 10 * ONE_K ? ' ' : ((x) < 10 * ONE_M ? 'k' : 'M'))
+
+/* Display an integer amount as multiple of 1K or 1M (in base 2).
+ Display the correct unit (either k, M, or ' ') after the amount, as
+ well. */
+#define SIZE_AMOUNT(size) (uint64_t)SIZE_SCALE (size), SIZE_LABEL (size)
+
+/* Format string particle for printing a SIZE_AMOUNT with N being the width
+ of the number. */
+#define PRsa(n) "%" #n PRIu64 "%c"
+
+/* System headers may define NULL to be an integer (e.g. 0L), which cannot be
+ used safely in certain contexts (e.g. as sentinels). Redefine NULL to
+ nullptr in order to make it safer. Note that this might confuse system
+ headers, however, by convention they must not be included after this point.
+*/
+#ifdef __cplusplus
+#undef NULL
+#define NULL nullptr
+#endif
+
+/* Return true if STR string starts with PREFIX. */
+
+static inline bool
+startswith (const char *str, const char *prefix)
+{
+ return strncmp (str, prefix, strlen (prefix)) == 0;
+}
+
+/* Return true if STR string ends with SUFFIX. */
+
+static inline bool
+endswith (const char *str, const char *suffix)
+{
+ size_t str_len = strlen (str);
+ size_t suffix_len = strlen (suffix);
+ if (str_len < suffix_len)
+ return false;
+
+ return memcmp (str + str_len - suffix_len, suffix, suffix_len) == 0;
+}
+
+#endif /* ! GCC_SYSTEM_H */
diff --git a/support/cpp/gcc/target-globals.h b/support/cpp/gcc/target-globals.h
new file mode 100644
index 000000000..235238486
--- /dev/null
+++ b/support/cpp/gcc/target-globals.h
@@ -0,0 +1,95 @@
+/* Target-dependent globals.
+ Copyright (C) 2010-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 TARGET_GLOBALS_H
+#define TARGET_GLOBALS_H 1
+
+#if SWITCHABLE_TARGET
+extern class target_flag_state *this_target_flag_state;
+extern struct target_regs *this_target_regs;
+extern struct target_rtl *this_target_rtl;
+extern struct target_recog *this_target_recog;
+extern struct target_hard_regs *this_target_hard_regs;
+extern struct target_function_abi_info *this_target_function_abi_info;
+extern struct target_reload *this_target_reload;
+extern struct target_expmed *this_target_expmed;
+extern struct target_optabs *this_target_optabs;
+extern struct target_libfuncs *this_target_libfuncs;
+extern struct target_cfgloop *this_target_cfgloop;
+extern struct target_ira *this_target_ira;
+extern class target_ira_int *this_target_ira_int;
+extern struct target_builtins *this_target_builtins;
+extern struct target_gcse *this_target_gcse;
+extern struct target_bb_reorder *this_target_bb_reorder;
+extern struct target_lower_subreg *this_target_lower_subreg;
+#endif
+
+class GTY(()) target_globals {
+public:
+ ~target_globals ();
+
+ class target_flag_state *GTY((skip)) flag_state;
+ struct target_regs *GTY((skip)) regs;
+ struct target_rtl *rtl;
+ struct target_recog *GTY((skip)) recog;
+ struct target_hard_regs *GTY((skip)) hard_regs;
+ struct target_function_abi_info *GTY((skip)) function_abi_info;
+ struct target_reload *GTY((skip)) reload;
+ struct target_expmed *GTY((skip)) expmed;
+ struct target_optabs *GTY((skip)) optabs;
+ struct target_libfuncs *libfuncs;
+ struct target_cfgloop *GTY((skip)) cfgloop;
+ struct target_ira *GTY((skip)) ira;
+ class target_ira_int *GTY((skip)) ira_int;
+ struct target_builtins *GTY((skip)) builtins;
+ struct target_gcse *GTY((skip)) gcse;
+ struct target_bb_reorder *GTY((skip)) bb_reorder;
+ struct target_lower_subreg *GTY((skip)) lower_subreg;
+};
+
+#if SWITCHABLE_TARGET
+extern class target_globals default_target_globals;
+
+extern class target_globals *save_target_globals (void);
+extern class target_globals *save_target_globals_default_opts (void);
+
+static inline void
+restore_target_globals (class target_globals *g)
+{
+ this_target_flag_state = g->flag_state;
+ this_target_regs = g->regs;
+ this_target_rtl = g->rtl;
+ this_target_recog = g->recog;
+ this_target_hard_regs = g->hard_regs;
+ this_target_function_abi_info = g->function_abi_info;
+ this_target_reload = g->reload;
+ this_target_expmed = g->expmed;
+ this_target_optabs = g->optabs;
+ this_target_libfuncs = g->libfuncs;
+ this_target_cfgloop = g->cfgloop;
+ this_target_ira = g->ira;
+ this_target_ira_int = g->ira_int;
+ this_target_builtins = g->builtins;
+ this_target_gcse = g->gcse;
+ this_target_bb_reorder = g->bb_reorder;
+ this_target_lower_subreg = g->lower_subreg;
+}
+#endif
+
+#endif
diff --git a/support/cpp/gcc/target-hooks-macros.h b/support/cpp/gcc/target-hooks-macros.h
new file mode 100644
index 000000000..a179fe718
--- /dev/null
+++ b/support/cpp/gcc/target-hooks-macros.h
@@ -0,0 +1,80 @@
+/* Common macros for target hook definitions.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* The following macros should be provided by the including file:
+
+ DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT): Define a function-valued hook.
+ DEFHOOKPOD(NAME, DOC, TYPE, INIT): Define a piece-of-data 'hook'. */
+
+/* Defaults for optional macros:
+ DEFHOOKPODX(NAME, TYPE, INIT): Like DEFHOOKPOD, but share documentation
+ with the previous 'hook'. */
+#ifndef DEFHOOKPODX
+#define DEFHOOKPODX(NAME, TYPE, INIT) DEFHOOKPOD (NAME, 0, TYPE, INIT)
+#endif
+
+/* HOOKSTRUCT(FRAGMENT): Declarator fragments to encapsulate all the
+ members into a struct gcc_target, which in turn contains several
+ sub-structs. */
+#ifndef HOOKSTRUCT
+#define HOOKSTRUCT(FRAGMENT)
+#endif
+/* HOOK_VECTOR: Start a struct declaration, which then gets its own initializer.
+ HOOK_VECTOR_END: Close a struct declaration, providing a member declarator
+ name for nested use. */
+#ifndef HOOK_VECTOR_1
+#define HOOK_VECTOR_1(NAME, FRAGMENT) HOOKSTRUCT (FRAGMENT)
+#endif
+#define HOOK_VECTOR(INIT_NAME, SNAME) HOOK_VECTOR_1 (INIT_NAME, struct SNAME {)
+#define HOOK_VECTOR_END(DECL_NAME) HOOK_VECTOR_1(,} DECL_NAME ;)
+
+/* FIXME: For pre-existing hooks, we can't place the documentation in the
+ documentation field here till we get permission from the FSF to include
+ it in GPLed software - the target hook documentation is so far only
+ available under the GFDL. */
+
+/* A hook should generally be documented by a string in the DOC parameter,
+ which should contain texinfo markup. If the documentation is only available
+ under the GPL, but not under the GFDL, put it in a comment above the hook
+ definition. If the function declaration is available both under GPL and
+ GFDL, but the documentation is only available under the GFDL, put the
+ documentaton in tm.texi.in, heading with @hook <hookname> and closing
+ the paragraph with @end deftypefn / deftypevr as appropriate, and marking
+ the next autogenerated hook with @hook <hookname>.
+ In both these cases, leave the DOC string empty, i.e. "".
+ Sometimes, for some historic reason the function declaration
+ has to be documented differently
+ than what it is. In that case, use DEFHOOK_UNDOC to suppress auto-generation
+ of documentation. DEFHOOK_UNDOC takes a DOC string which it ignores, so
+ you can put GPLed documentation string there if you have hopes that you
+ can clear the declaration & documentation for GFDL distribution later,
+ in which case you can then simply change the DEFHOOK_UNDOC to DEFHOOK
+ to turn on the autogeneration of the documentation.
+
+ A documentation string of "*" means not to emit any documentation at all,
+ and is mainly used internally for DEFHOOK_UNDOC. It should generally not
+ be used otherwise, but it has its use for exceptional cases where automatic
+ documentation is not wanted, and the real documentation is elsewere, like
+ for TARGET_ASM_{,UN}ALIGNED_INT_OP, which are hooks only for implementation
+ purposes; they refer to structs, the components of which are documented as
+ separate hooks TARGET_ASM_{,UN}ALIGNED_[HSDT]I_OP.
+ A DOC string of 0 is for internal use of DEFHOOKPODX and special table
+ entries only. */
+
+/* Empty macro arguments are undefined in C90, so use an empty macro
+ to close top-level hook structures. */
+#define C90_EMPTY_HACK
diff --git a/support/cpp/gcc/target-insns.def b/support/cpp/gcc/target-insns.def
new file mode 100644
index 000000000..de8c0092f
--- /dev/null
+++ b/support/cpp/gcc/target-insns.def
@@ -0,0 +1,108 @@
+/* Target instruction definitions.
+ Copyright (C) 2015-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+/* This file has one entry for each public pattern name that the target
+ can provide. It is only used if no distinction between operand modes
+ is necessary. If separate patterns are needed for different modes
+ (so as to distinguish addition of QImode values from addition of
+ HImode values, for example) then an optab should be used instead.
+
+ Each entry has the form:
+
+ DEF_TARGET_INSN (name, prototype)
+
+ where NAME is the name of the pattern and PROTOTYPE is its C prototype.
+ The prototype should use parameter names of the form "x0", "x1", etc.
+ for the operands that the .md pattern is required to have, followed by
+ parameter names of the form "optN" for operands that the .md pattern
+ may choose to ignore. Patterns that never take operands should have
+ a prototype "(void)".
+
+ Pattern names should be documented in md.texi rather than here. */
+DEF_TARGET_INSN (allocate_stack, (rtx x0, rtx x1))
+DEF_TARGET_INSN (atomic_test_and_set, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (builtin_longjmp, (rtx x0))
+DEF_TARGET_INSN (builtin_setjmp_receiver, (rtx x0))
+DEF_TARGET_INSN (builtin_setjmp_setup, (rtx x0))
+DEF_TARGET_INSN (canonicalize_funcptr_for_compare, (rtx x0, rtx x1))
+DEF_TARGET_INSN (call, (rtx x0, rtx opt1, rtx opt2, rtx opt3))
+DEF_TARGET_INSN (call_pop, (rtx x0, rtx opt1, rtx opt2, rtx opt3))
+DEF_TARGET_INSN (call_value, (rtx x0, rtx x1, rtx opt2, rtx opt3, rtx opt4))
+DEF_TARGET_INSN (call_value_pop, (rtx x0, rtx x1, rtx opt2, rtx opt3,
+ rtx opt4))
+DEF_TARGET_INSN (casesi, (rtx x0, rtx x1, rtx x2, rtx x3, rtx x4))
+DEF_TARGET_INSN (check_stack, (rtx x0))
+DEF_TARGET_INSN (clear_cache, (rtx x0, rtx x1))
+DEF_TARGET_INSN (doloop_begin, (rtx x0, rtx x1))
+DEF_TARGET_INSN (doloop_end, (rtx x0, rtx x1))
+DEF_TARGET_INSN (eh_return, (rtx x0))
+DEF_TARGET_INSN (epilogue, (void))
+DEF_TARGET_INSN (exception_receiver, (void))
+DEF_TARGET_INSN (extv, (rtx x0, rtx x1, rtx x2, rtx x3))
+DEF_TARGET_INSN (extzv, (rtx x0, rtx x1, rtx x2, rtx x3))
+DEF_TARGET_INSN (indirect_jump, (rtx x0))
+DEF_TARGET_INSN (insv, (rtx x0, rtx x1, rtx x2, rtx x3))
+DEF_TARGET_INSN (jump, (rtx x0))
+DEF_TARGET_INSN (load_multiple, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (mem_thread_fence, (rtx x0))
+DEF_TARGET_INSN (memory_barrier, (void))
+DEF_TARGET_INSN (memory_blockage, (void))
+DEF_TARGET_INSN (movstr, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (nonlocal_goto, (rtx x0, rtx x1, rtx x2, rtx x3))
+DEF_TARGET_INSN (nonlocal_goto_receiver, (void))
+DEF_TARGET_INSN (oacc_dim_pos, (rtx x0, rtx x1))
+DEF_TARGET_INSN (oacc_dim_size, (rtx x0, rtx x1))
+DEF_TARGET_INSN (oacc_fork, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (oacc_join, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (omp_simt_enter, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (omp_simt_exit, (rtx x0))
+DEF_TARGET_INSN (omp_simt_lane, (rtx x0))
+DEF_TARGET_INSN (omp_simt_last_lane, (rtx x0, rtx x1))
+DEF_TARGET_INSN (omp_simt_ordered, (rtx x0, rtx x1))
+DEF_TARGET_INSN (omp_simt_vote_any, (rtx x0, rtx x1))
+DEF_TARGET_INSN (omp_simt_xchg_bfly, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (omp_simt_xchg_idx, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (prefetch, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (probe_stack, (rtx x0))
+DEF_TARGET_INSN (probe_stack_address, (rtx x0))
+DEF_TARGET_INSN (prologue, (void))
+DEF_TARGET_INSN (ptr_extend, (rtx x0, rtx x1))
+DEF_TARGET_INSN (reload_load_address, (rtx x0, rtx x1))
+DEF_TARGET_INSN (restore_stack_block, (rtx x0, rtx x1))
+DEF_TARGET_INSN (restore_stack_function, (rtx x0, rtx x1))
+DEF_TARGET_INSN (restore_stack_nonlocal, (rtx x0, rtx x1))
+DEF_TARGET_INSN (return, (void))
+DEF_TARGET_INSN (save_stack_block, (rtx x0, rtx x1))
+DEF_TARGET_INSN (save_stack_function, (rtx x0, rtx x1))
+DEF_TARGET_INSN (save_stack_nonlocal, (rtx x0, rtx x1))
+DEF_TARGET_INSN (sibcall, (rtx x0, rtx opt1, rtx opt2, rtx opt3))
+DEF_TARGET_INSN (sibcall_epilogue, (void))
+DEF_TARGET_INSN (sibcall_value, (rtx x0, rtx x1, rtx opt2, rtx opt3,
+ rtx opt4))
+DEF_TARGET_INSN (simple_return, (void))
+DEF_TARGET_INSN (split_stack_prologue, (void))
+DEF_TARGET_INSN (split_stack_space_check, (rtx x0, rtx x1))
+DEF_TARGET_INSN (stack_protect_combined_set, (rtx x0, rtx x1))
+DEF_TARGET_INSN (stack_protect_set, (rtx x0, rtx x1))
+DEF_TARGET_INSN (stack_protect_combined_test, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (stack_protect_test, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (store_multiple, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (tablejump, (rtx x0, rtx x1))
+DEF_TARGET_INSN (trap, (void))
+DEF_TARGET_INSN (unique, (void))
+DEF_TARGET_INSN (untyped_call, (rtx x0, rtx x1, rtx x2))
+DEF_TARGET_INSN (untyped_return, (rtx x0, rtx x1))
diff --git a/support/cpp/gcc/target.def b/support/cpp/gcc/target.def
new file mode 100644
index 000000000..d85adf36a
--- /dev/null
+++ b/support/cpp/gcc/target.def
@@ -0,0 +1,7116 @@
+/* Target hook definitions.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+/* See target-hooks-macros.h for details of macros that should be
+ provided by the including file, and how to use them here. */
+#include "target-hooks-macros.h"
+
+#undef HOOK_TYPE
+#define HOOK_TYPE "Target Hook"
+
+HOOK_VECTOR (TARGET_INITIALIZER, gcc_target)
+
+/* Functions that output assembler for the target. */
+#define HOOK_PREFIX "TARGET_ASM_"
+HOOK_VECTOR (TARGET_ASM_OUT, asm_out)
+
+/* Opening and closing parentheses for asm expression grouping. */
+DEFHOOKPOD
+(open_paren,
+ "These target hooks are C string constants, describing the syntax in the\n\
+assembler for grouping arithmetic expressions. If not overridden, they\n\
+default to normal parentheses, which is correct for most assemblers.",
+ const char *, "(")
+DEFHOOKPODX (close_paren, const char *, ")")
+
+/* Assembler instructions for creating various kinds of integer object. */
+DEFHOOKPOD
+(byte_op,
+ "@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_HI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_PSI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_SI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_PDI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_DI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_PTI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_ALIGNED_TI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_HI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_PSI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_SI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_PDI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_DI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_PTI_OP\n\
+@deftypevrx {Target Hook} {const char *} TARGET_ASM_UNALIGNED_TI_OP\n\
+These hooks specify assembly directives for creating certain kinds\n\
+of integer object. The @code{TARGET_ASM_BYTE_OP} directive creates a\n\
+byte-sized object, the @code{TARGET_ASM_ALIGNED_HI_OP} one creates an\n\
+aligned two-byte object, and so on. Any of the hooks may be\n\
+@code{NULL}, indicating that no suitable directive is available.\n\
+\n\
+The compiler will print these strings at the start of a new line,\n\
+followed immediately by the object's initial value. In most cases,\n\
+the string should contain a tab, a pseudo-op, and then another tab.",
+ const char *, "\t.byte\t")
+DEFHOOKPOD (aligned_op, "*", struct asm_int_op, TARGET_ASM_ALIGNED_INT_OP)
+DEFHOOKPOD (unaligned_op, "*", struct asm_int_op, TARGET_ASM_UNALIGNED_INT_OP)
+
+/* Try to output the assembler code for an integer object whose
+ value is given by X. SIZE is the size of the object in bytes and
+ ALIGNED_P indicates whether it is aligned. Return true if
+ successful. Only handles cases for which BYTE_OP, ALIGNED_OP
+ and UNALIGNED_OP are NULL. */
+DEFHOOK
+(integer,
+ "The @code{assemble_integer} function uses this hook to output an\n\
+integer object. @var{x} is the object's value, @var{size} is its size\n\
+in bytes and @var{aligned_p} indicates whether it is aligned. The\n\
+function should return @code{true} if it was able to output the\n\
+object. If it returns false, @code{assemble_integer} will try to\n\
+split the object into smaller parts.\n\
+\n\
+The default implementation of this hook will use the\n\
+@code{TARGET_ASM_BYTE_OP} family of strings, returning @code{false}\n\
+when the relevant string is @code{NULL}.",
+ /* Only handles cases for which BYTE_OP, ALIGNED_OP and UNALIGNED_OP are
+ NULL. */
+ bool, (rtx x, unsigned int size, int aligned_p),
+ default_assemble_integer)
+
+/* Assembly strings required after the .cfi_startproc label. */
+DEFHOOK
+(post_cfi_startproc,
+ "This target hook is used to emit assembly strings required by the target\n\
+after the .cfi_startproc directive. The first argument is the file stream to\n\
+write the strings to and the second argument is the function\'s declaration. The\n\
+expected use is to add more .cfi_* directives.\n\
+\n\
+The default is to not output any assembly strings.",
+ void, (FILE *, tree),
+ hook_void_FILEptr_tree)
+
+/* Notify the backend that we have completed emitting the data for a
+ decl. */
+DEFHOOK
+(decl_end,
+ "Define this hook if the target assembler requires a special marker to\n\
+terminate an initialized variable declaration.",
+ void, (void),
+ hook_void_void)
+
+/* Output code that will globalize a label. */
+DEFHOOK
+(globalize_label,
+ "This target hook is a function to output to the stdio stream\n\
+@var{stream} some commands that will make the label @var{name} global;\n\
+that is, available for reference from other files.\n\
+\n\
+The default implementation relies on a proper definition of\n\
+@code{GLOBAL_ASM_OP}.",
+ void, (FILE *stream, const char *name),
+ default_globalize_label)
+
+/* Output code that will globalize a declaration. */
+DEFHOOK
+(globalize_decl_name,
+ "This target hook is a function to output to the stdio stream\n\
+@var{stream} some commands that will make the name associated with @var{decl}\n\
+global; that is, available for reference from other files.\n\
+\n\
+The default implementation uses the TARGET_ASM_GLOBALIZE_LABEL target hook.",
+ void, (FILE *stream, tree decl), default_globalize_decl_name)
+
+/* Output code that will declare an external variable. */
+DEFHOOK
+(assemble_undefined_decl,
+ "This target hook is a function to output to the stdio stream\n\
+@var{stream} some commands that will declare the name associated with\n\
+@var{decl} which is not defined in the current translation unit. Most\n\
+assemblers do not require anything to be output in this case.",
+ void, (FILE *stream, const char *name, const_tree decl),
+ hook_void_FILEptr_constcharptr_const_tree)
+
+/* Output code that will emit a label for unwind info, if this
+ target requires such labels. Second argument is the decl the
+ unwind info is associated with, third is a boolean: true if
+ this is for exception handling, fourth is a boolean: true if
+ this is only a placeholder for an omitted FDE. */
+DEFHOOK
+(emit_unwind_label,
+ "This target hook emits a label at the beginning of each FDE@. It\n\
+should be defined on targets where FDEs need special labels, and it\n\
+should write the appropriate label, for the FDE associated with the\n\
+function declaration @var{decl}, to the stdio stream @var{stream}.\n\
+The third argument, @var{for_eh}, is a boolean: true if this is for an\n\
+exception table. The fourth argument, @var{empty}, is a boolean:\n\
+true if this is a placeholder label for an omitted FDE@.\n\
+\n\
+The default is that FDEs are not given nonlocal labels.",
+ void, (FILE *stream, tree decl, int for_eh, int empty),
+ default_emit_unwind_label)
+
+/* Output code that will emit a label to divide up the exception table. */
+DEFHOOK
+(emit_except_table_label,
+ "This target hook emits a label at the beginning of the exception table.\n\
+It should be defined on targets where it is desirable for the table\n\
+to be broken up according to function.\n\
+\n\
+The default is that no label is emitted.",
+ void, (FILE *stream),
+ default_emit_except_table_label)
+
+/* Emit a directive for setting the personality for the function. */
+DEFHOOK
+(emit_except_personality,
+ "If the target implements @code{TARGET_ASM_UNWIND_EMIT}, this hook may be\n\
+used to emit a directive to install a personality hook into the unwind\n\
+info. This hook should not be used if dwarf2 unwind info is used.",
+ void, (rtx personality),
+ NULL)
+
+/* If necessary, modify personality and LSDA references to handle
+ indirection. This is used when the assembler supports CFI directives. */
+DEFHOOK
+(make_eh_symbol_indirect,
+ "If necessary, modify personality and LSDA references to handle indirection.\n\
+The original symbol is in @code{origsymbol} and if @code{pubvis} is true\n\
+the symbol is visible outside the TU.",
+ rtx, (rtx origsymbol, bool pubvis),
+ NULL)
+
+/* Emit any directives required to unwind this instruction. */
+DEFHOOK
+(unwind_emit,
+ "This target hook emits assembly directives required to unwind the\n\
+given instruction. This is only used when @code{TARGET_EXCEPT_UNWIND_INFO}\n\
+returns @code{UI_TARGET}.",
+ void, (FILE *stream, rtx_insn *insn),
+ NULL)
+
+DEFHOOKPOD
+(unwind_emit_before_insn,
+ "True if the @code{TARGET_ASM_UNWIND_EMIT} hook should be called before\n\
+the assembly for @var{insn} has been emitted, false if the hook should\n\
+be called afterward.",
+ bool, true)
+
+/* Return true if the target needs extra instructions to restore the current
+ frame address after a DW_CFA_restore_state opcode. */
+DEFHOOK
+(should_restore_cfa_state,
+ "For DWARF-based unwind frames, two CFI instructions provide for save and\n\
+restore of register state. GCC maintains the current frame address (CFA)\n\
+separately from the register bank but the unwinder in libgcc preserves this\n\
+state along with the registers (and this is expected by the code that writes\n\
+the unwind frames). This hook allows the target to specify that the CFA data\n\
+is not saved/restored along with the registers by the target unwinder so that\n\
+suitable additional instructions should be emitted to restore it.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Generate an internal label.
+ For now this is just a wrapper for ASM_GENERATE_INTERNAL_LABEL. */
+DEFHOOK_UNDOC
+(generate_internal_label,
+ "",
+ void, (char *buf, const char *prefix, unsigned long labelno),
+ default_generate_internal_label)
+
+/* Output an internal label. */
+DEFHOOK
+(internal_label,
+ "A function to output to the stdio stream @var{stream} a label whose\n\
+name is made from the string @var{prefix} and the number @var{labelno}.\n\
+\n\
+It is absolutely essential that these labels be distinct from the labels\n\
+used for user-level functions and variables. Otherwise, certain programs\n\
+will have name conflicts with internal labels.\n\
+\n\
+It is desirable to exclude internal labels from the symbol table of the\n\
+object file. Most assemblers have a naming convention for labels that\n\
+should be excluded; on many systems, the letter @samp{L} at the\n\
+beginning of a label has this effect. You should find out what\n\
+convention your system uses, and follow it.\n\
+\n\
+The default version of this function utilizes @code{ASM_GENERATE_INTERNAL_LABEL}.",
+ void, (FILE *stream, const char *prefix, unsigned long labelno),
+ default_internal_label)
+
+/* Output label for the constant. */
+DEFHOOK
+(declare_constant_name,
+ "A target hook to output to the stdio stream @var{file} any text necessary\n\
+for declaring the name @var{name} of a constant which is being defined. This\n\
+target hook is responsible for outputting the label definition (perhaps using\n\
+@code{assemble_label}). The argument @var{exp} is the value of the constant,\n\
+and @var{size} is the size of the constant in bytes. The @var{name}\n\
+will be an internal label.\n\
+\n\
+The default version of this target hook, define the @var{name} in the\n\
+usual manner as a label (by means of @code{assemble_label}).\n\
+\n\
+You may wish to use @code{ASM_OUTPUT_TYPE_DIRECTIVE} in this target hook.",
+ void, (FILE *file, const char *name, const_tree expr, HOST_WIDE_INT size),
+ default_asm_declare_constant_name)
+
+/* Emit a ttype table reference to a typeinfo object. */
+DEFHOOK
+(ttype,
+ "This hook is used to output a reference from a frame unwinding table to\n\
+the type_info object identified by @var{sym}. It should return @code{true}\n\
+if the reference was output. Returning @code{false} will cause the\n\
+reference to be output using the normal Dwarf2 routines.",
+ bool, (rtx sym),
+ hook_bool_rtx_false)
+
+/* Emit an assembler directive to set visibility for the symbol
+ associated with the tree decl. */
+DEFHOOK
+(assemble_visibility,
+ "This target hook is a function to output to @var{asm_out_file} some\n\
+commands that will make the symbol(s) associated with @var{decl} have\n\
+hidden, protected or internal visibility as specified by @var{visibility}.",
+ void, (tree decl, int visibility),
+ default_assemble_visibility)
+
+DEFHOOK
+(print_patchable_function_entry,
+ "Generate a patchable area at the function start, consisting of\n\
+@var{patch_area_size} NOP instructions. If the target supports named\n\
+sections and if @var{record_p} is true, insert a pointer to the current\n\
+location in the table of patchable functions. The default implementation\n\
+of the hook places the table of pointers in the special section named\n\
+@code{__patchable_function_entries}.",
+ void, (FILE *file, unsigned HOST_WIDE_INT patch_area_size, bool record_p),
+ default_print_patchable_function_entry)
+
+/* Output the assembler code for entry to a function. */
+DEFHOOK
+(function_prologue,
+ "If defined, a function that outputs the assembler code for entry to a\n\
+function. The prologue is responsible for setting up the stack frame,\n\
+initializing the frame pointer register, saving registers that must be\n\
+saved, and allocating @var{size} additional bytes of storage for the\n\
+local variables. @var{file} is a stdio stream to which the assembler\n\
+code should be output.\n\
+\n\
+The label for the beginning of the function need not be output by this\n\
+macro. That has already been done when the macro is run.\n\
+\n\
+@findex regs_ever_live\n\
+To determine which registers to save, the macro can refer to the array\n\
+@code{regs_ever_live}: element @var{r} is nonzero if hard register\n\
+@var{r} is used anywhere within the function. This implies the function\n\
+prologue should save register @var{r}, provided it is not one of the\n\
+call-used registers. (@code{TARGET_ASM_FUNCTION_EPILOGUE} must likewise use\n\
+@code{regs_ever_live}.)\n\
+\n\
+On machines that have ``register windows'', the function entry code does\n\
+not save on the stack the registers that are in the windows, even if\n\
+they are supposed to be preserved by function calls; instead it takes\n\
+appropriate steps to ``push'' the register stack, if any non-call-used\n\
+registers are used in the function.\n\
+\n\
+@findex frame_pointer_needed\n\
+On machines where functions may or may not have frame-pointers, the\n\
+function entry code must vary accordingly; it must set up the frame\n\
+pointer if one is wanted, and not otherwise. To determine whether a\n\
+frame pointer is in wanted, the macro can refer to the variable\n\
+@code{frame_pointer_needed}. The variable's value will be 1 at run\n\
+time in a function that needs a frame pointer. @xref{Elimination}.\n\
+\n\
+The function entry code is responsible for allocating any stack space\n\
+required for the function. This stack space consists of the regions\n\
+listed below. In most cases, these regions are allocated in the\n\
+order listed, with the last listed region closest to the top of the\n\
+stack (the lowest address if @code{STACK_GROWS_DOWNWARD} is defined, and\n\
+the highest address if it is not defined). You can use a different order\n\
+for a machine if doing so is more convenient or required for\n\
+compatibility reasons. Except in cases where required by standard\n\
+or by a debugger, there is no reason why the stack layout used by GCC\n\
+need agree with that used by other compilers for a machine.",
+ void, (FILE *file),
+ default_function_pro_epilogue)
+
+/* Output the assembler code for end of prologue. */
+DEFHOOK
+(function_end_prologue,
+ "If defined, a function that outputs assembler code at the end of a\n\
+prologue. This should be used when the function prologue is being\n\
+emitted as RTL, and you have some extra assembler that needs to be\n\
+emitted. @xref{prologue instruction pattern}.",
+ void, (FILE *file),
+ no_asm_to_stream)
+
+/* Output the assembler code for start of epilogue. */
+DEFHOOK
+(function_begin_epilogue,
+ "If defined, a function that outputs assembler code at the start of an\n\
+epilogue. This should be used when the function epilogue is being\n\
+emitted as RTL, and you have some extra assembler that needs to be\n\
+emitted. @xref{epilogue instruction pattern}.",
+ void, (FILE *file),
+ no_asm_to_stream)
+
+/* Output the assembler code for function exit. */
+DEFHOOK
+(function_epilogue,
+ "If defined, a function that outputs the assembler code for exit from a\n\
+function. The epilogue is responsible for restoring the saved\n\
+registers and stack pointer to their values when the function was\n\
+called, and returning control to the caller. This macro takes the\n\
+same argument as the macro @code{TARGET_ASM_FUNCTION_PROLOGUE}, and the\n\
+registers to restore are determined from @code{regs_ever_live} and\n\
+@code{CALL_USED_REGISTERS} in the same way.\n\
+\n\
+On some machines, there is a single instruction that does all the work\n\
+of returning from the function. On these machines, give that\n\
+instruction the name @samp{return} and do not define the macro\n\
+@code{TARGET_ASM_FUNCTION_EPILOGUE} at all.\n\
+\n\
+Do not define a pattern named @samp{return} if you want the\n\
+@code{TARGET_ASM_FUNCTION_EPILOGUE} to be used. If you want the target\n\
+switches to control whether return instructions or epilogues are used,\n\
+define a @samp{return} pattern with a validity condition that tests the\n\
+target switches appropriately. If the @samp{return} pattern's validity\n\
+condition is false, epilogues will be used.\n\
+\n\
+On machines where functions may or may not have frame-pointers, the\n\
+function exit code must vary accordingly. Sometimes the code for these\n\
+two cases is completely different. To determine whether a frame pointer\n\
+is wanted, the macro can refer to the variable\n\
+@code{frame_pointer_needed}. The variable's value will be 1 when compiling\n\
+a function that needs a frame pointer.\n\
+\n\
+Normally, @code{TARGET_ASM_FUNCTION_PROLOGUE} and\n\
+@code{TARGET_ASM_FUNCTION_EPILOGUE} must treat leaf functions specially.\n\
+The C variable @code{current_function_is_leaf} is nonzero for such a\n\
+function. @xref{Leaf Functions}.\n\
+\n\
+On some machines, some functions pop their arguments on exit while\n\
+others leave that for the caller to do. For example, the 68020 when\n\
+given @option{-mrtd} pops arguments in functions that take a fixed\n\
+number of arguments.\n\
+\n\
+@findex pops_args\n\
+@findex crtl->args.pops_args\n\
+Your definition of the macro @code{RETURN_POPS_ARGS} decides which\n\
+functions pop their own arguments. @code{TARGET_ASM_FUNCTION_EPILOGUE}\n\
+needs to know what was decided. The number of bytes of the current\n\
+function's arguments that this function should pop is available in\n\
+@code{crtl->args.pops_args}. @xref{Scalar Return}.",
+ void, (FILE *file),
+ default_function_pro_epilogue)
+
+/* Initialize target-specific sections. */
+DEFHOOK
+(init_sections,
+ "Define this hook if you need to do something special to set up the\n\
+@file{varasm.cc} sections, or if your target has some special sections\n\
+of its own that you need to create.\n\
+\n\
+GCC calls this hook after processing the command line, but before writing\n\
+any assembly code, and before calling any of the section-returning hooks\n\
+described below.",
+ void, (void),
+ hook_void_void)
+
+/* Tell assembler to change to section NAME with attributes FLAGS.
+ If DECL is non-NULL, it is the VAR_DECL or FUNCTION_DECL with
+ which this section is associated. */
+DEFHOOK
+(named_section,
+ "Output assembly directives to switch to section @var{name}. The section\n\
+should have attributes as specified by @var{flags}, which is a bit mask\n\
+of the @code{SECTION_*} flags defined in @file{output.h}. If @var{decl}\n\
+is non-NULL, it is the @code{VAR_DECL} or @code{FUNCTION_DECL} with which\n\
+this section is associated.",
+ void, (const char *name, unsigned int flags, tree decl),
+ default_no_named_section)
+
+/* Tell assembler what section attributes to assign this elf section
+ declaration, using their numerical value. */
+DEFHOOK
+(elf_flags_numeric,
+ "This hook can be used to encode ELF section flags for which no letter\n\
+code has been defined in the assembler. It is called by\n\
+@code{default_asm_named_section} whenever the section flags need to be\n\
+emitted in the assembler output. If the hook returns true, then the\n\
+numerical value for ELF section flags should be calculated from\n\
+@var{flags} and saved in @var{*num}; the value is printed out instead of the\n\
+normal sequence of letter codes. If the hook is not defined, or if it\n\
+returns false, then @var{num} is ignored and the traditional letter sequence\n\
+is emitted.",
+ bool, (unsigned int flags, unsigned int *num),
+ hook_bool_uint_uintp_false)
+
+/* Return preferred text (sub)section for function DECL.
+ Main purpose of this function is to separate cold, normal and hot
+ functions. STARTUP is true when function is known to be used only
+ at startup (from static constructors or it is main()).
+ EXIT is true when function is known to be used only at exit
+ (from static destructors).
+ Return NULL if function should go to default text section. */
+DEFHOOK
+(function_section,
+ "Return preferred text (sub)section for function @var{decl}.\n\
+Main purpose of this function is to separate cold, normal and hot\n\
+functions. @var{startup} is true when function is known to be used only\n\
+at startup (from static constructors or it is @code{main()}).\n\
+@var{exit} is true when function is known to be used only at exit\n\
+(from static destructors).\n\
+Return NULL if function should go to default text section.",
+ section *, (tree decl, enum node_frequency freq, bool startup, bool exit),
+ default_function_section)
+
+/* Output the assembler code for function exit. */
+DEFHOOK
+(function_switched_text_sections,
+ "Used by the target to emit any assembler directives or additional\n\
+labels needed when a function is partitioned between different\n\
+sections. Output should be written to @var{file}. The function\n\
+decl is available as @var{decl} and the new section is `cold' if\n\
+@var{new_is_cold} is @code{true}.",
+ void, (FILE *file, tree decl, bool new_is_cold),
+ default_function_switched_text_sections)
+
+/* Return a mask describing how relocations should be treated when
+ selecting sections. Bit 1 should be set if global relocations
+ should be placed in a read-write section; bit 0 should be set if
+ local relocations should be placed in a read-write section. */
+DEFHOOK
+(reloc_rw_mask,
+ "Return a mask describing how relocations should be treated when\n\
+selecting sections. Bit 1 should be set if global relocations\n\
+should be placed in a read-write section; bit 0 should be set if\n\
+local relocations should be placed in a read-write section.\n\
+\n\
+The default version of this function returns 3 when @option{-fpic}\n\
+is in effect, and 0 otherwise. The hook is typically redefined\n\
+when the target cannot support (some kinds of) dynamic relocations\n\
+in read-only sections even in executables.",
+ int, (void),
+ default_reloc_rw_mask)
+
+ /* Return a flag for either generating ADDR_DIF_VEC table
+ or ADDR_VEC table for jumps in case of -fPIC/-fPIE. */
+DEFHOOK
+(generate_pic_addr_diff_vec,
+"Return true to generate ADDR_DIF_VEC table\n\
+or false to generate ADDR_VEC table for jumps in case of -fPIC.\n\
+\n\
+The default version of this function returns true if flag_pic\n\
+equals true and false otherwise",
+ bool, (void),
+ default_generate_pic_addr_diff_vec)
+
+ /* Return a section for EXP. It may be a DECL or a constant. RELOC
+ is nonzero if runtime relocations must be applied; bit 1 will be
+ set if the runtime relocations require non-local name resolution.
+ ALIGN is the required alignment of the data. */
+DEFHOOK
+(select_section,
+ "Return the section into which @var{exp} should be placed. You can\n\
+assume that @var{exp} is either a @code{VAR_DECL} node or a constant of\n\
+some sort. @var{reloc} indicates whether the initial value of @var{exp}\n\
+requires link-time relocations. Bit 0 is set when variable contains\n\
+local relocations only, while bit 1 is set for global relocations.\n\
+@var{align} is the constant alignment in bits.\n\
+\n\
+The default version of this function takes care of putting read-only\n\
+variables in @code{readonly_data_section}.\n\
+\n\
+See also @var{USE_SELECT_SECTION_FOR_FUNCTIONS}.",
+ section *, (tree exp, int reloc, unsigned HOST_WIDE_INT align),
+ default_select_section)
+
+/* Return a section for X. MODE is X's mode and ALIGN is its
+ alignment in bits. */
+DEFHOOK
+(select_rtx_section,
+ "Return the section into which a constant @var{x}, of mode @var{mode},\n\
+should be placed. You can assume that @var{x} is some kind of\n\
+constant in RTL@. The argument @var{mode} is redundant except in the\n\
+case of a @code{const_int} rtx. @var{align} is the constant alignment\n\
+in bits.\n\
+\n\
+The default version of this function takes care of putting symbolic\n\
+constants in @code{flag_pic} mode in @code{data_section} and everything\n\
+else in @code{readonly_data_section}.",
+ section *, (machine_mode mode, rtx x, unsigned HOST_WIDE_INT align),
+ default_select_rtx_section)
+
+/* Select a unique section name for DECL. RELOC is the same as
+ for SELECT_SECTION. */
+DEFHOOK
+(unique_section,
+ "Build up a unique section name, expressed as a @code{STRING_CST} node,\n\
+and assign it to @samp{DECL_SECTION_NAME (@var{decl})}.\n\
+As with @code{TARGET_ASM_SELECT_SECTION}, @var{reloc} indicates whether\n\
+the initial value of @var{exp} requires link-time relocations.\n\
+\n\
+The default version of this function appends the symbol name to the\n\
+ELF section name that would normally be used for the symbol. For\n\
+example, the function @code{foo} would be placed in @code{.text.foo}.\n\
+Whatever the actual target object format, this is often good enough.",
+ void, (tree decl, int reloc),
+ default_unique_section)
+
+/* Return the readonly data or relocated readonly data section
+ associated with function DECL. */
+DEFHOOK
+(function_rodata_section,
+ "Return the readonly data or reloc readonly data section associated with\n\
+@samp{DECL_SECTION_NAME (@var{decl})}. @var{relocatable} selects the latter\n\
+over the former.\n\
+The default version of this function selects @code{.gnu.linkonce.r.name} if\n\
+the function's section is @code{.gnu.linkonce.t.name}, @code{.rodata.name}\n\
+or @code{.data.rel.ro.name} if function is in @code{.text.name}, and\n\
+the normal readonly-data or reloc readonly data section otherwise.",
+ section *, (tree decl, bool relocatable),
+ default_function_rodata_section)
+
+/* Nonnull if the target wants to override the default ".rodata" prefix
+ for mergeable data sections. */
+DEFHOOKPOD
+(mergeable_rodata_prefix,
+ "Usually, the compiler uses the prefix @code{\".rodata\"} to construct\n\
+section names for mergeable constant data. Define this macro to override\n\
+the string if a different section name should be used.",
+ const char *, ".rodata")
+
+/* Return the section to be used for transactional memory clone tables. */
+DEFHOOK
+(tm_clone_table_section,
+ "Return the section that should be used for transactional memory clone\n\
+tables.",
+ section *, (void), default_clone_table_section)
+
+/* Output a constructor for a symbol with a given priority. */
+DEFHOOK
+(constructor,
+ "If defined, a function that outputs assembler code to arrange to call\n\
+the function referenced by @var{symbol} at initialization time.\n\
+\n\
+Assume that @var{symbol} is a @code{SYMBOL_REF} for a function taking\n\
+no arguments and with no return value. If the target supports initialization\n\
+priorities, @var{priority} is a value between 0 and @code{MAX_INIT_PRIORITY};\n\
+otherwise it must be @code{DEFAULT_INIT_PRIORITY}.\n\
+\n\
+If this macro is not defined by the target, a suitable default will\n\
+be chosen if (1) the target supports arbitrary section names, (2) the\n\
+target defines @code{CTORS_SECTION_ASM_OP}, or (3) @code{USE_COLLECT2}\n\
+is not defined.",
+ void, (rtx symbol, int priority), NULL)
+
+/* Output a destructor for a symbol with a given priority. */
+DEFHOOK
+(destructor,
+ "This is like @code{TARGET_ASM_CONSTRUCTOR} but used for termination\n\
+functions rather than initialization functions.",
+ void, (rtx symbol, int priority), NULL)
+
+/* Output the assembler code for a thunk function. THUNK_DECL is the
+ declaration for the thunk function itself, FUNCTION is the decl for
+ the target function. DELTA is an immediate constant offset to be
+ added to THIS. If VCALL_OFFSET is nonzero, the word at
+ *(*this + vcall_offset) should be added to THIS. */
+DEFHOOK
+(output_mi_thunk,
+ "A function that outputs the assembler code for a thunk\n\
+function, used to implement C++ virtual function calls with multiple\n\
+inheritance. The thunk acts as a wrapper around a virtual function,\n\
+adjusting the implicit object parameter before handing control off to\n\
+the real function.\n\
+\n\
+First, emit code to add the integer @var{delta} to the location that\n\
+contains the incoming first argument. Assume that this argument\n\
+contains a pointer, and is the one used to pass the @code{this} pointer\n\
+in C++. This is the incoming argument @emph{before} the function prologue,\n\
+e.g.@: @samp{%o0} on a sparc. The addition must preserve the values of\n\
+all other incoming arguments.\n\
+\n\
+Then, if @var{vcall_offset} is nonzero, an additional adjustment should be\n\
+made after adding @code{delta}. In particular, if @var{p} is the\n\
+adjusted pointer, the following adjustment should be made:\n\
+\n\
+@smallexample\n\
+p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]\n\
+@end smallexample\n\
+\n\
+After the additions, emit code to jump to @var{function}, which is a\n\
+@code{FUNCTION_DECL}. This is a direct pure jump, not a call, and does\n\
+not touch the return address. Hence returning from @var{FUNCTION} will\n\
+return to whoever called the current @samp{thunk}.\n\
+\n\
+The effect must be as if @var{function} had been called directly with\n\
+the adjusted first argument. This macro is responsible for emitting all\n\
+of the code for a thunk function; @code{TARGET_ASM_FUNCTION_PROLOGUE}\n\
+and @code{TARGET_ASM_FUNCTION_EPILOGUE} are not invoked.\n\
+\n\
+The @var{thunk_fndecl} is redundant. (@var{delta} and @var{function}\n\
+have already been extracted from it.) It might possibly be useful on\n\
+some targets, but probably not.\n\
+\n\
+If you do not define this macro, the target-independent code in the C++\n\
+front end will generate a less efficient heavyweight thunk that calls\n\
+@var{function} instead of jumping to it. The generic approach does\n\
+not support varargs.",
+ void, (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset, tree function),
+ NULL)
+
+/* Determine whether output_mi_thunk would succeed. */
+/* ??? Ideally, this hook would not exist, and success or failure
+ would be returned from output_mi_thunk directly. But there's
+ too much undo-able setup involved in invoking output_mi_thunk.
+ Could be fixed by making output_mi_thunk emit rtl instead of
+ text to the output file. */
+DEFHOOK
+(can_output_mi_thunk,
+ "A function that returns true if TARGET_ASM_OUTPUT_MI_THUNK would be able\n\
+to output the assembler code for the thunk function specified by the\n\
+arguments it is passed, and false otherwise. In the latter case, the\n\
+generic approach will be used by the C++ front end, with the limitations\n\
+previously exposed.",
+ bool, (const_tree thunk_fndecl, HOST_WIDE_INT delta,
+ HOST_WIDE_INT vcall_offset, const_tree function),
+ hook_bool_const_tree_hwi_hwi_const_tree_false)
+
+/* Output any boilerplate text needed at the beginning of a
+ translation unit. */
+DEFHOOK
+(file_start,
+ "Output to @code{asm_out_file} any text which the assembler expects to\n\
+find at the beginning of a file. The default behavior is controlled\n\
+by two flags, documented below. Unless your target's assembler is\n\
+quite unusual, if you override the default, you should call\n\
+@code{default_file_start} at some point in your target hook. This\n\
+lets other target files rely on these variables.",
+ void, (void),
+ default_file_start)
+
+/* Output any boilerplate text needed at the end of a translation unit. */
+DEFHOOK
+(file_end,
+ "Output to @code{asm_out_file} any text which the assembler expects\n\
+to find at the end of a file. The default is to output nothing.",
+ void, (void),
+ hook_void_void)
+
+/* Output any boilerplate text needed at the beginning of an
+ LTO output stream. */
+DEFHOOK
+(lto_start,
+ "Output to @code{asm_out_file} any text which the assembler expects\n\
+to find at the start of an LTO section. The default is to output\n\
+nothing.",
+ void, (void),
+ hook_void_void)
+
+/* Output any boilerplate text needed at the end of an
+ LTO output stream. */
+DEFHOOK
+(lto_end,
+ "Output to @code{asm_out_file} any text which the assembler expects\n\
+to find at the end of an LTO section. The default is to output\n\
+nothing.",
+ void, (void),
+ hook_void_void)
+
+/* Output any boilerplace text needed at the end of a
+ translation unit before debug and unwind info is emitted. */
+DEFHOOK
+(code_end,
+ "Output to @code{asm_out_file} any text which is needed before emitting\n\
+unwind info and debug info at the end of a file. Some targets emit\n\
+here PIC setup thunks that cannot be emitted at the end of file,\n\
+because they couldn't have unwind info then. The default is to output\n\
+nothing.",
+ void, (void),
+ hook_void_void)
+
+/* Output an assembler pseudo-op to declare a library function name
+ external. */
+DEFHOOK
+(external_libcall,
+ "This target hook is a function to output to @var{asm_out_file} an assembler\n\
+pseudo-op to declare a library function name external. The name of the\n\
+library function is given by @var{symref}, which is a @code{symbol_ref}.",
+ void, (rtx symref),
+ default_external_libcall)
+
+/* Output an assembler directive to mark decl live. This instructs
+ linker to not dead code strip this symbol. */
+DEFHOOK
+(mark_decl_preserved,
+ "This target hook is a function to output to @var{asm_out_file} an assembler\n\
+directive to annotate @var{symbol} as used. The Darwin target uses the\n\
+.no_dead_code_strip directive.",
+ void, (const char *symbol),
+ hook_void_constcharptr)
+
+/* Output a record of the command line switches that have been passed. */
+DEFHOOK
+(record_gcc_switches,
+ "Provides the target with the ability to record the gcc command line\n\
+switches provided as argument.\n\
+\n\
+By default this hook is set to NULL, but an example implementation is\n\
+provided for ELF based targets. Called @var{elf_record_gcc_switches},\n\
+it records the switches as ASCII text inside a new, string mergeable\n\
+section in the assembler output file. The name of the new section is\n\
+provided by the @code{TARGET_ASM_RECORD_GCC_SWITCHES_SECTION} target\n\
+hook.",
+ void, (const char *),
+ NULL)
+
+/* The name of the section that the example ELF implementation of
+ record_gcc_switches will use to store the information. Target
+ specific versions of record_gcc_switches may or may not use
+ this information. */
+DEFHOOKPOD
+(record_gcc_switches_section,
+ "This is the name of the section that will be created by the example\n\
+ELF implementation of the @code{TARGET_ASM_RECORD_GCC_SWITCHES} target\n\
+hook.",
+ const char *, ".GCC.command.line")
+
+/* Output the definition of a section anchor. */
+DEFHOOK
+(output_anchor,
+ "Write the assembly code to define section anchor @var{x}, which is a\n\
+@code{SYMBOL_REF} for which @samp{SYMBOL_REF_ANCHOR_P (@var{x})} is true.\n\
+The hook is called with the assembly output position set to the beginning\n\
+of @code{SYMBOL_REF_BLOCK (@var{x})}.\n\
+\n\
+If @code{ASM_OUTPUT_DEF} is available, the hook's default definition uses\n\
+it to define the symbol as @samp{. + SYMBOL_REF_BLOCK_OFFSET (@var{x})}.\n\
+If @code{ASM_OUTPUT_DEF} is not available, the hook's default definition\n\
+is @code{NULL}, which disables the use of section anchors altogether.",
+ void, (rtx x),
+ default_asm_output_anchor)
+
+DEFHOOK
+(output_ident,
+ "Output a string based on @var{name}, suitable for the @samp{#ident}\n\
+directive, or the equivalent directive or pragma in non-C-family languages.\n\
+If this hook is not defined, nothing is output for the @samp{#ident}\n\
+directive.",
+ void, (const char *name),
+ hook_void_constcharptr)
+
+/* Output a DTP-relative reference to a TLS symbol. */
+DEFHOOK
+(output_dwarf_dtprel,
+ "If defined, this target hook is a function which outputs a DTP-relative\n\
+reference to the given TLS symbol of the specified size.",
+ void, (FILE *file, int size, rtx x),
+ NULL)
+
+/* Some target machines need to postscan each insn after it is output. */
+DEFHOOK
+(final_postscan_insn,
+ "If defined, this target hook is a function which is executed just after the\n\
+output of assembler code for @var{insn}, to change the mode of the assembler\n\
+if necessary.\n\
+\n\
+Here the argument @var{opvec} is the vector containing the operands\n\
+extracted from @var{insn}, and @var{noperands} is the number of\n\
+elements of the vector which contain meaningful data for this insn.\n\
+The contents of this vector are what was used to convert the insn\n\
+template into assembler code, so you can change the assembler mode\n\
+by checking the contents of the vector.",
+ void, (FILE *file, rtx_insn *insn, rtx *opvec, int noperands),
+ NULL)
+
+/* Emit the trampoline template. This hook may be NULL. */
+DEFHOOK
+(trampoline_template,
+ "This hook is called by @code{assemble_trampoline_template} to output,\n\
+on the stream @var{f}, assembler code for a block of data that contains\n\
+the constant parts of a trampoline. This code should not include a\n\
+label---the label is taken care of automatically.\n\
+\n\
+If you do not define this hook, it means no template is needed\n\
+for the target. Do not define this hook on systems where the block move\n\
+code to copy the trampoline into place would be larger than the code\n\
+to generate it on the spot.",
+ void, (FILE *f),
+ NULL)
+
+DEFHOOK
+(output_source_filename,
+ "Output DWARF debugging information which indicates that filename\n\
+@var{name} is the current source file to the stdio stream @var{file}.\n\
+\n\
+This target hook need not be defined if the standard form of output\n\
+for the file format in use is appropriate.",
+ void ,(FILE *file, const char *name),
+ default_asm_output_source_filename)
+
+DEFHOOK
+(output_addr_const_extra,
+ "A target hook to recognize @var{rtx} patterns that @code{output_addr_const}\n\
+can't deal with, and output assembly code to @var{file} corresponding to\n\
+the pattern @var{x}. This may be used to allow machine-dependent\n\
+@code{UNSPEC}s to appear within constants.\n\
+\n\
+If target hook fails to recognize a pattern, it must return @code{false},\n\
+so that a standard error message is printed. If it prints an error message\n\
+itself, by calling, for example, @code{output_operand_lossage}, it may just\n\
+return @code{true}.",
+ bool, (FILE *file, rtx x),
+ hook_bool_FILEptr_rtx_false)
+
+/* ??? The TARGET_PRINT_OPERAND* hooks are part of the asm_out struct,
+ even though that is not reflected in the macro name to override their
+ initializers. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+/* Emit a machine-specific insn operand. */
+/* ??? tm.texi only documents the old macro PRINT_OPERAND,
+ not this hook, and uses a different name for the argument FILE. */
+DEFHOOK_UNDOC
+(print_operand,
+ "",
+ void, (FILE *file, rtx x, int code),
+ default_print_operand)
+
+/* Emit a machine-specific memory address. */
+/* ??? tm.texi only documents the old macro PRINT_OPERAND_ADDRESS,
+ not this hook, and uses different argument names. */
+DEFHOOK_UNDOC
+(print_operand_address,
+ "",
+ void, (FILE *file, machine_mode mode, rtx addr),
+ default_print_operand_address)
+
+/* Determine whether CODE is a valid punctuation character for the
+ `print_operand' hook. */
+/* ??? tm.texi only documents the old macro PRINT_OPERAND_PUNCT_VALID_P,
+ not this hook. */
+DEFHOOK_UNDOC
+(print_operand_punct_valid_p,
+ "",
+ bool ,(unsigned char code),
+ default_print_operand_punct_valid_p)
+
+/* Given a symbol name, perform same mangling as assemble_name and
+ ASM_OUTPUT_LABELREF, returning result as an IDENTIFIER_NODE. */
+DEFHOOK
+(mangle_assembler_name,
+ "Given a symbol @var{name}, perform same mangling as @code{varasm.cc}'s\n\
+@code{assemble_name}, but in memory rather than to a file stream, returning\n\
+result as an @code{IDENTIFIER_NODE}. Required for correct LTO symtabs. The\n\
+default implementation calls the @code{TARGET_STRIP_NAME_ENCODING} hook and\n\
+then prepends the @code{USER_LABEL_PREFIX}, if any.",
+ tree, (const char *name),
+ default_mangle_assembler_name)
+
+HOOK_VECTOR_END (asm_out)
+
+/* Functions relating to instruction scheduling. All of these
+ default to null pointers, which haifa-sched.cc looks for and handles. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_SCHED_"
+HOOK_VECTOR (TARGET_SCHED, sched)
+
+/* Given the current cost, COST, of an insn, INSN, calculate and
+ return a new cost based on its relationship to DEP_INSN through
+ the dependence LINK. The default is to make no adjustment. */
+DEFHOOK
+(adjust_cost,
+ "This function corrects the value of @var{cost} based on the\n\
+relationship between @var{insn} and @var{dep_insn} through a\n\
+dependence of type dep_type, and strength @var{dw}. It should return the new\n\
+value. The default is to make no adjustment to @var{cost}. This can be\n\
+used for example to specify to the scheduler using the traditional pipeline\n\
+description that an output- or anti-dependence does not incur the same cost\n\
+as a data-dependence. If the scheduler using the automaton based pipeline\n\
+description, the cost of anti-dependence is zero and the cost of\n\
+output-dependence is maximum of one and the difference of latency\n\
+times of the first and the second insns. If these values are not\n\
+acceptable, you could use the hook to modify them too. See also\n\
+@pxref{Processor pipeline description}.",
+ int, (rtx_insn *insn, int dep_type1, rtx_insn *dep_insn, int cost,
+ unsigned int dw),
+ NULL)
+
+/* Adjust the priority of an insn as you see fit. Returns the new priority. */
+DEFHOOK
+(adjust_priority,
+ "This hook adjusts the integer scheduling priority @var{priority} of\n\
+@var{insn}. It should return the new priority. Increase the priority to\n\
+execute @var{insn} earlier, reduce the priority to execute @var{insn}\n\
+later. Do not define this hook if you do not need to adjust the\n\
+scheduling priorities of insns.",
+ int, (rtx_insn *insn, int priority), NULL)
+
+/* Function which returns the maximum number of insns that can be
+ scheduled in the same machine cycle. This must be constant
+ over an entire compilation. The default is 1. */
+DEFHOOK
+(issue_rate,
+ "This hook returns the maximum number of instructions that can ever\n\
+issue at the same time on the target machine. The default is one.\n\
+Although the insn scheduler can define itself the possibility of issue\n\
+an insn on the same cycle, the value can serve as an additional\n\
+constraint to issue insns on the same simulated processor cycle (see\n\
+hooks @samp{TARGET_SCHED_REORDER} and @samp{TARGET_SCHED_REORDER2}).\n\
+This value must be constant over the entire compilation. If you need\n\
+it to vary depending on what the instructions are, you must use\n\
+@samp{TARGET_SCHED_VARIABLE_ISSUE}.",
+ int, (void), NULL)
+
+/* Calculate how much this insn affects how many more insns we
+ can emit this cycle. Default is they all cost the same. */
+DEFHOOK
+(variable_issue,
+ "This hook is executed by the scheduler after it has scheduled an insn\n\
+from the ready list. It should return the number of insns which can\n\
+still be issued in the current cycle. The default is\n\
+@samp{@w{@var{more} - 1}} for insns other than @code{CLOBBER} and\n\
+@code{USE}, which normally are not counted against the issue rate.\n\
+You should define this hook if some insns take more machine resources\n\
+than others, so that fewer insns can follow them in the same cycle.\n\
+@var{file} is either a null pointer, or a stdio stream to write any\n\
+debug output to. @var{verbose} is the verbose level provided by\n\
+@option{-fsched-verbose-@var{n}}. @var{insn} is the instruction that\n\
+was scheduled.",
+ int, (FILE *file, int verbose, rtx_insn *insn, int more), NULL)
+
+/* Initialize machine-dependent scheduling code. */
+DEFHOOK
+(init,
+ "This hook is executed by the scheduler at the beginning of each block of\n\
+instructions that are to be scheduled. @var{file} is either a null\n\
+pointer, or a stdio stream to write any debug output to. @var{verbose}\n\
+is the verbose level provided by @option{-fsched-verbose-@var{n}}.\n\
+@var{max_ready} is the maximum number of insns in the current scheduling\n\
+region that can be live at the same time. This can be used to allocate\n\
+scratch space if it is needed, e.g.@: by @samp{TARGET_SCHED_REORDER}.",
+ void, (FILE *file, int verbose, int max_ready), NULL)
+
+/* Finalize machine-dependent scheduling code. */
+DEFHOOK
+(finish,
+ "This hook is executed by the scheduler at the end of each block of\n\
+instructions that are to be scheduled. It can be used to perform\n\
+cleanup of any actions done by the other scheduling hooks. @var{file}\n\
+is either a null pointer, or a stdio stream to write any debug output\n\
+to. @var{verbose} is the verbose level provided by\n\
+@option{-fsched-verbose-@var{n}}.",
+ void, (FILE *file, int verbose), NULL)
+
+ /* Initialize machine-dependent function wide scheduling code. */
+DEFHOOK
+(init_global,
+ "This hook is executed by the scheduler after function level initializations.\n\
+@var{file} is either a null pointer, or a stdio stream to write any debug output to.\n\
+@var{verbose} is the verbose level provided by @option{-fsched-verbose-@var{n}}.\n\
+@var{old_max_uid} is the maximum insn uid when scheduling begins.",
+ void, (FILE *file, int verbose, int old_max_uid), NULL)
+
+/* Finalize machine-dependent function wide scheduling code. */
+DEFHOOK
+(finish_global,
+ "This is the cleanup hook corresponding to @code{TARGET_SCHED_INIT_GLOBAL}.\n\
+@var{file} is either a null pointer, or a stdio stream to write any debug output to.\n\
+@var{verbose} is the verbose level provided by @option{-fsched-verbose-@var{n}}.",
+ void, (FILE *file, int verbose), NULL)
+
+/* Reorder insns in a machine-dependent fashion, in two different
+ places. Default does nothing. */
+DEFHOOK
+(reorder,
+ "This hook is executed by the scheduler after it has scheduled the ready\n\
+list, to allow the machine description to reorder it (for example to\n\
+combine two small instructions together on @samp{VLIW} machines).\n\
+@var{file} is either a null pointer, or a stdio stream to write any\n\
+debug output to. @var{verbose} is the verbose level provided by\n\
+@option{-fsched-verbose-@var{n}}. @var{ready} is a pointer to the ready\n\
+list of instructions that are ready to be scheduled. @var{n_readyp} is\n\
+a pointer to the number of elements in the ready list. The scheduler\n\
+reads the ready list in reverse order, starting with\n\
+@var{ready}[@var{*n_readyp} @minus{} 1] and going to @var{ready}[0]. @var{clock}\n\
+is the timer tick of the scheduler. You may modify the ready list and\n\
+the number of ready insns. The return value is the number of insns that\n\
+can issue this cycle; normally this is just @code{issue_rate}. See also\n\
+@samp{TARGET_SCHED_REORDER2}.",
+ int, (FILE *file, int verbose, rtx_insn **ready, int *n_readyp, int clock), NULL)
+
+DEFHOOK
+(reorder2,
+ "Like @samp{TARGET_SCHED_REORDER}, but called at a different time. That\n\
+function is called whenever the scheduler starts a new cycle. This one\n\
+is called once per iteration over a cycle, immediately after\n\
+@samp{TARGET_SCHED_VARIABLE_ISSUE}; it can reorder the ready list and\n\
+return the number of insns to be scheduled in the same cycle. Defining\n\
+this hook can be useful if there are frequent situations where\n\
+scheduling one insn causes other insns to become ready in the same\n\
+cycle. These other insns can then be taken into account properly.",
+ int, (FILE *file, int verbose, rtx_insn **ready, int *n_readyp, int clock), NULL)
+
+DEFHOOK
+(macro_fusion_p,
+ "This hook is used to check whether target platform supports macro fusion.",
+ bool, (void), NULL)
+
+DEFHOOK
+(macro_fusion_pair_p,
+ "This hook is used to check whether two insns should be macro fused for\n\
+a target microarchitecture. If this hook returns true for the given insn pair\n\
+(@var{prev} and @var{curr}), the scheduler will put them into a sched\n\
+group, and they will not be scheduled apart. The two insns will be either\n\
+two SET insns or a compare and a conditional jump and this hook should\n\
+validate any dependencies needed to fuse the two insns together.",
+ bool, (rtx_insn *prev, rtx_insn *curr), NULL)
+
+/* The following member value is a pointer to a function called
+ after evaluation forward dependencies of insns in chain given
+ by two parameter values (head and tail correspondingly). */
+DEFHOOK
+(dependencies_evaluation_hook,
+ "This hook is called after evaluation forward dependencies of insns in\n\
+chain given by two parameter values (@var{head} and @var{tail}\n\
+correspondingly) but before insns scheduling of the insn chain. For\n\
+example, it can be used for better insn classification if it requires\n\
+analysis of dependencies. This hook can use backward and forward\n\
+dependencies of the insn scheduler because they are already\n\
+calculated.",
+ void, (rtx_insn *head, rtx_insn *tail), NULL)
+
+/* The values of the following four members are pointers to functions
+ used to simplify the automaton descriptions. dfa_pre_cycle_insn and
+ dfa_post_cycle_insn give functions returning insns which are used to
+ change the pipeline hazard recognizer state when the new simulated
+ processor cycle correspondingly starts and finishes. The function
+ defined by init_dfa_pre_cycle_insn and init_dfa_post_cycle_insn are
+ used to initialize the corresponding insns. The default values of
+ the members result in not changing the automaton state when the
+ new simulated processor cycle correspondingly starts and finishes. */
+
+DEFHOOK
+(init_dfa_pre_cycle_insn,
+ "The hook can be used to initialize data used by the previous hook.",
+ void, (void), NULL)
+
+DEFHOOK
+(dfa_pre_cycle_insn,
+ "The hook returns an RTL insn. The automaton state used in the\n\
+pipeline hazard recognizer is changed as if the insn were scheduled\n\
+when the new simulated processor cycle starts. Usage of the hook may\n\
+simplify the automaton pipeline description for some @acronym{VLIW}\n\
+processors. If the hook is defined, it is used only for the automaton\n\
+based pipeline description. The default is not to change the state\n\
+when the new simulated processor cycle starts.",
+ rtx, (void), NULL)
+
+DEFHOOK
+(init_dfa_post_cycle_insn,
+ "The hook is analogous to @samp{TARGET_SCHED_INIT_DFA_PRE_CYCLE_INSN} but\n\
+used to initialize data used by the previous hook.",
+ void, (void), NULL)
+
+DEFHOOK
+(dfa_post_cycle_insn,
+ "The hook is analogous to @samp{TARGET_SCHED_DFA_PRE_CYCLE_INSN} but used\n\
+to changed the state as if the insn were scheduled when the new\n\
+simulated processor cycle finishes.",
+ rtx_insn *, (void), NULL)
+
+/* The values of the following two members are pointers to
+ functions used to simplify the automaton descriptions.
+ dfa_pre_advance_cycle and dfa_post_advance_cycle are getting called
+ immediately before and after cycle is advanced. */
+
+DEFHOOK
+(dfa_pre_advance_cycle,
+ "The hook to notify target that the current simulated cycle is about to finish.\n\
+The hook is analogous to @samp{TARGET_SCHED_DFA_PRE_CYCLE_INSN} but used\n\
+to change the state in more complicated situations - e.g., when advancing\n\
+state on a single insn is not enough.",
+ void, (void), NULL)
+
+DEFHOOK
+(dfa_post_advance_cycle,
+ "The hook to notify target that new simulated cycle has just started.\n\
+The hook is analogous to @samp{TARGET_SCHED_DFA_POST_CYCLE_INSN} but used\n\
+to change the state in more complicated situations - e.g., when advancing\n\
+state on a single insn is not enough.",
+ void, (void), NULL)
+
+/* The following member value is a pointer to a function returning value
+ which defines how many insns in queue `ready' will we try for
+ multi-pass scheduling. If the member value is nonzero and the
+ function returns positive value, the DFA based scheduler will make
+ multi-pass scheduling for the first cycle. In other words, we will
+ try to choose ready insn which permits to start maximum number of
+ insns on the same cycle. */
+DEFHOOK
+(first_cycle_multipass_dfa_lookahead,
+ "This hook controls better choosing an insn from the ready insn queue\n\
+for the @acronym{DFA}-based insn scheduler. Usually the scheduler\n\
+chooses the first insn from the queue. If the hook returns a positive\n\
+value, an additional scheduler code tries all permutations of\n\
+@samp{TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ()}\n\
+subsequent ready insns to choose an insn whose issue will result in\n\
+maximal number of issued insns on the same cycle. For the\n\
+@acronym{VLIW} processor, the code could actually solve the problem of\n\
+packing simple insns into the @acronym{VLIW} insn. Of course, if the\n\
+rules of @acronym{VLIW} packing are described in the automaton.\n\
+\n\
+This code also could be used for superscalar @acronym{RISC}\n\
+processors. Let us consider a superscalar @acronym{RISC} processor\n\
+with 3 pipelines. Some insns can be executed in pipelines @var{A} or\n\
+@var{B}, some insns can be executed only in pipelines @var{B} or\n\
+@var{C}, and one insn can be executed in pipeline @var{B}. The\n\
+processor may issue the 1st insn into @var{A} and the 2nd one into\n\
+@var{B}. In this case, the 3rd insn will wait for freeing @var{B}\n\
+until the next cycle. If the scheduler issues the 3rd insn the first,\n\
+the processor could issue all 3 insns per cycle.\n\
+\n\
+Actually this code demonstrates advantages of the automaton based\n\
+pipeline hazard recognizer. We try quickly and easy many insn\n\
+schedules to choose the best one.\n\
+\n\
+The default is no multipass scheduling.",
+ int, (void), NULL)
+
+/* The following member value is pointer to a function controlling
+ what insns from the ready insn queue will be considered for the
+ multipass insn scheduling. If the hook returns zero for insn
+ passed as the parameter, the insn will be not chosen to be issued. */
+DEFHOOK
+(first_cycle_multipass_dfa_lookahead_guard,
+ "\n\
+This hook controls what insns from the ready insn queue will be\n\
+considered for the multipass insn scheduling. If the hook returns\n\
+zero for @var{insn}, the insn will be considered in multipass scheduling.\n\
+Positive return values will remove @var{insn} from consideration on\n\
+the current round of multipass scheduling.\n\
+Negative return values will remove @var{insn} from consideration for given\n\
+number of cycles.\n\
+Backends should be careful about returning non-zero for highest priority\n\
+instruction at position 0 in the ready list. @var{ready_index} is passed\n\
+to allow backends make correct judgements.\n\
+\n\
+The default is that any ready insns can be chosen to be issued.",
+ int, (rtx_insn *insn, int ready_index), NULL)
+
+/* This hook prepares the target for a new round of multipass
+ scheduling.
+ DATA is a pointer to target-specific data used for multipass scheduling.
+ READY_TRY and N_READY represent the current state of search in the
+ optimization space. The target can filter out instructions that
+ should not be tried during current round by setting corresponding
+ elements in READY_TRY to non-zero.
+ FIRST_CYCLE_INSN_P is true if this is the first round of multipass
+ scheduling on current cycle. */
+DEFHOOK
+(first_cycle_multipass_begin,
+ "This hook prepares the target backend for a new round of multipass\n\
+scheduling.",
+ void, (void *data, signed char *ready_try, int n_ready, bool first_cycle_insn_p),
+ NULL)
+
+/* This hook is called when multipass scheduling evaluates instruction INSN.
+ DATA is a pointer to target-specific data that can be used to record effects
+ of INSN on CPU that are not described in DFA.
+ READY_TRY and N_READY represent the current state of search in the
+ optimization space. The target can filter out instructions that
+ should not be tried after issuing INSN by setting corresponding
+ elements in READY_TRY to non-zero.
+ INSN is the instruction being evaluated.
+ PREV_DATA is a pointer to target-specific data corresponding
+ to a state before issuing INSN. */
+DEFHOOK
+(first_cycle_multipass_issue,
+ "This hook is called when multipass scheduling evaluates instruction INSN.",
+ void, (void *data, signed char *ready_try, int n_ready, rtx_insn *insn,
+ const void *prev_data), NULL)
+
+/* This hook is called when multipass scheduling backtracks from evaluation of
+ instruction corresponding to DATA.
+ DATA is a pointer to target-specific data that stores the effects
+ of instruction from which the algorithm backtracks on CPU that are not
+ described in DFA.
+ READY_TRY and N_READY represent the current state of search in the
+ optimization space. The target can filter out instructions that
+ should not be tried after issuing INSN by setting corresponding
+ elements in READY_TRY to non-zero. */
+DEFHOOK
+(first_cycle_multipass_backtrack,
+ "This is called when multipass scheduling backtracks from evaluation of\n\
+an instruction.",
+ void, (const void *data, signed char *ready_try, int n_ready), NULL)
+
+/* This hook notifies the target about the result of the concluded current
+ round of multipass scheduling.
+ DATA is a pointer.
+ If DATA is non-NULL it points to target-specific data used for multipass
+ scheduling which corresponds to instruction at the start of the chain of
+ the winning solution. DATA is NULL when multipass scheduling cannot find
+ a good enough solution on current cycle and decides to retry later,
+ usually after advancing the cycle count. */
+DEFHOOK
+(first_cycle_multipass_end,
+ "This hook notifies the target about the result of the concluded current\n\
+round of multipass scheduling.",
+ void, (const void *data), NULL)
+
+/* This hook is called to initialize target-specific data for multipass
+ scheduling after it has been allocated.
+ DATA is a pointer to target-specific data that stores the effects
+ of instruction from which the algorithm backtracks on CPU that are not
+ described in DFA. */
+DEFHOOK
+(first_cycle_multipass_init,
+ "This hook initializes target-specific data used in multipass scheduling.",
+ void, (void *data), NULL)
+
+/* This hook is called to finalize target-specific data for multipass
+ scheduling before it is deallocated.
+ DATA is a pointer to target-specific data that stores the effects
+ of instruction from which the algorithm backtracks on CPU that are not
+ described in DFA. */
+DEFHOOK
+(first_cycle_multipass_fini,
+ "This hook finalizes target-specific data used in multipass scheduling.",
+ void, (void *data), NULL)
+
+/* The following member value is pointer to a function called by
+ the insn scheduler before issuing insn passed as the third
+ parameter on given cycle. If the hook returns nonzero, the
+ insn is not issued on given processors cycle. Instead of that,
+ the processor cycle is advanced. If the value passed through
+ the last parameter is zero, the insn ready queue is not sorted
+ on the new cycle start as usually. The first parameter passes
+ file for debugging output. The second one passes the scheduler
+ verbose level of the debugging output. The forth and the fifth
+ parameter values are correspondingly processor cycle on which
+ the previous insn has been issued and the current processor cycle. */
+DEFHOOK
+(dfa_new_cycle,
+ "This hook is called by the insn scheduler before issuing @var{insn}\n\
+on cycle @var{clock}. If the hook returns nonzero,\n\
+@var{insn} is not issued on this processor cycle. Instead,\n\
+the processor cycle is advanced. If *@var{sort_p}\n\
+is zero, the insn ready queue is not sorted on the new cycle\n\
+start as usually. @var{dump} and @var{verbose} specify the file and\n\
+verbosity level to use for debugging output.\n\
+@var{last_clock} and @var{clock} are, respectively, the\n\
+processor cycle on which the previous insn has been issued,\n\
+and the current processor cycle.",
+ int, (FILE *dump, int verbose, rtx_insn *insn, int last_clock,
+ int clock, int *sort_p),
+ NULL)
+
+/* The following member value is a pointer to a function called by the
+ insn scheduler. It should return true if there exists a dependence
+ which is considered costly by the target, between the insn
+ DEP_PRO (&_DEP), and the insn DEP_CON (&_DEP). The first parameter is
+ the dep that represents the dependence between the two insns. The
+ second argument is the cost of the dependence as estimated by
+ the scheduler. The last argument is the distance in cycles
+ between the already scheduled insn (first parameter) and the
+ second insn (second parameter). */
+DEFHOOK
+(is_costly_dependence,
+ "This hook is used to define which dependences are considered costly by\n\
+the target, so costly that it is not advisable to schedule the insns that\n\
+are involved in the dependence too close to one another. The parameters\n\
+to this hook are as follows: The first parameter @var{_dep} is the dependence\n\
+being evaluated. The second parameter @var{cost} is the cost of the\n\
+dependence as estimated by the scheduler, and the third\n\
+parameter @var{distance} is the distance in cycles between the two insns.\n\
+The hook returns @code{true} if considering the distance between the two\n\
+insns the dependence between them is considered costly by the target,\n\
+and @code{false} otherwise.\n\
+\n\
+Defining this hook can be useful in multiple-issue out-of-order machines,\n\
+where (a) it's practically hopeless to predict the actual data/resource\n\
+delays, however: (b) there's a better chance to predict the actual grouping\n\
+that will be formed, and (c) correctly emulating the grouping can be very\n\
+important. In such targets one may want to allow issuing dependent insns\n\
+closer to one another---i.e., closer than the dependence distance; however,\n\
+not in cases of ``costly dependences'', which this hooks allows to define.",
+ bool, (struct _dep *_dep, int cost, int distance), NULL)
+
+/* The following member value is a pointer to a function called
+ by the insn scheduler. This hook is called to notify the backend
+ that new instructions were emitted. */
+DEFHOOK
+(h_i_d_extended,
+ "This hook is called by the insn scheduler after emitting a new instruction to\n\
+the instruction stream. The hook notifies a target backend to extend its\n\
+per instruction data structures.",
+ void, (void), NULL)
+
+/* Next 5 functions are for multi-point scheduling. */
+
+/* Allocate memory for scheduler context. */
+DEFHOOK
+(alloc_sched_context,
+ "Return a pointer to a store large enough to hold target scheduling context.",
+ void *, (void), NULL)
+
+/* Fills the context from the local machine scheduler context. */
+DEFHOOK
+(init_sched_context,
+ "Initialize store pointed to by @var{tc} to hold target scheduling context.\n\
+It @var{clean_p} is true then initialize @var{tc} as if scheduler is at the\n\
+beginning of the block. Otherwise, copy the current context into @var{tc}.",
+ void, (void *tc, bool clean_p), NULL)
+
+/* Sets local machine scheduler context to a saved value. */
+DEFHOOK
+(set_sched_context,
+ "Copy target scheduling context pointed to by @var{tc} to the current context.",
+ void, (void *tc), NULL)
+
+/* Clears a scheduler context so it becomes like after init. */
+DEFHOOK
+(clear_sched_context,
+ "Deallocate internal data in target scheduling context pointed to by @var{tc}.",
+ void, (void *tc), NULL)
+
+/* Frees the scheduler context. */
+DEFHOOK
+(free_sched_context,
+ "Deallocate a store for target scheduling context pointed to by @var{tc}.",
+ void, (void *tc), NULL)
+
+/* The following member value is a pointer to a function called
+ by the insn scheduler.
+ The first parameter is an instruction, the second parameter is the type
+ of the requested speculation, and the third parameter is a pointer to the
+ speculative pattern of the corresponding type (set if return value == 1).
+ It should return
+ -1, if there is no pattern, that will satisfy the requested speculation type,
+ 0, if current pattern satisfies the requested speculation type,
+ 1, if pattern of the instruction should be changed to the newly
+ generated one. */
+DEFHOOK
+(speculate_insn,
+ "This hook is called by the insn scheduler when @var{insn} has only\n\
+speculative dependencies and therefore can be scheduled speculatively.\n\
+The hook is used to check if the pattern of @var{insn} has a speculative\n\
+version and, in case of successful check, to generate that speculative\n\
+pattern. The hook should return 1, if the instruction has a speculative form,\n\
+or @minus{}1, if it doesn't. @var{request} describes the type of requested\n\
+speculation. If the return value equals 1 then @var{new_pat} is assigned\n\
+the generated speculative pattern.",
+ int, (rtx_insn *insn, unsigned int dep_status, rtx *new_pat), NULL)
+
+/* The following member value is a pointer to a function called
+ by the insn scheduler. It should return true if the check instruction
+ passed as the parameter needs a recovery block. */
+DEFHOOK
+(needs_block_p,
+ "This hook is called by the insn scheduler during generation of recovery code\n\
+for @var{insn}. It should return @code{true}, if the corresponding check\n\
+instruction should branch to recovery code, or @code{false} otherwise.",
+ bool, (unsigned int dep_status), NULL)
+
+/* The following member value is a pointer to a function called
+ by the insn scheduler. It should return a pattern for the check
+ instruction.
+ The first parameter is a speculative instruction, the second parameter
+ is the label of the corresponding recovery block (or null, if it is a
+ simple check). The third parameter is the kind of speculation that
+ is being performed. */
+DEFHOOK
+(gen_spec_check,
+ "This hook is called by the insn scheduler to generate a pattern for recovery\n\
+check instruction. If @var{mutate_p} is zero, then @var{insn} is a\n\
+speculative instruction for which the check should be generated.\n\
+@var{label} is either a label of a basic block, where recovery code should\n\
+be emitted, or a null pointer, when requested check doesn't branch to\n\
+recovery code (a simple check). If @var{mutate_p} is nonzero, then\n\
+a pattern for a branchy check corresponding to a simple check denoted by\n\
+@var{insn} should be generated. In this case @var{label} can't be null.",
+ rtx, (rtx_insn *insn, rtx_insn *label, unsigned int ds), NULL)
+
+/* The following member value is a pointer to a function that provides
+ information about the speculation capabilities of the target.
+ The parameter is a pointer to spec_info variable. */
+DEFHOOK
+(set_sched_flags,
+ "This hook is used by the insn scheduler to find out what features should be\n\
+enabled/used.\n\
+The structure *@var{spec_info} should be filled in by the target.\n\
+The structure describes speculation types that can be used in the scheduler.",
+ void, (struct spec_info_def *spec_info), NULL)
+
+DEFHOOK_UNDOC
+(get_insn_spec_ds,
+ "Return speculation types of instruction @var{insn}.",
+ unsigned int, (rtx_insn *insn), NULL)
+
+DEFHOOK_UNDOC
+(get_insn_checked_ds,
+ "Return speculation types that are checked for instruction @var{insn}",
+ unsigned int, (rtx_insn *insn), NULL)
+
+DEFHOOK
+(can_speculate_insn,
+ "Some instructions should never be speculated by the schedulers, usually\n\
+ because the instruction is too expensive to get this wrong. Often such\n\
+ instructions have long latency, and often they are not fully modeled in the\n\
+ pipeline descriptions. This hook should return @code{false} if @var{insn}\n\
+ should not be speculated.",
+ bool, (rtx_insn *insn), hook_bool_rtx_insn_true)
+
+DEFHOOK_UNDOC
+(skip_rtx_p,
+ "Return bool if rtx scanning should just skip current layer and\
+ advance to the inner rtxes.",
+ bool, (const_rtx x), NULL)
+
+/* The following member value is a pointer to a function that provides
+ information about the target resource-based lower bound which is
+ used by the swing modulo scheduler. The parameter is a pointer
+ to ddg variable. */
+DEFHOOK
+(sms_res_mii,
+ "This hook is called by the swing modulo scheduler to calculate a\n\
+resource-based lower bound which is based on the resources available in\n\
+the machine and the resources required by each instruction. The target\n\
+backend can use @var{g} to calculate such bound. A very simple lower\n\
+bound will be used in case this hook is not implemented: the total number\n\
+of instructions divided by the issue rate.",
+ int, (struct ddg *g), NULL)
+
+/* The following member value is a function that initializes dispatch
+ schedling and adds instructions to dispatch window according to its
+ parameters. */
+DEFHOOK
+(dispatch_do,
+"This hook is called by Haifa Scheduler. It performs the operation specified\n\
+in its second parameter.",
+void, (rtx_insn *insn, int x),
+hook_void_rtx_insn_int)
+
+/* The following member value is a function that returns true is
+ dispatch schedling is supported in hardware and condition passed
+ as the second parameter is true. */
+DEFHOOK
+(dispatch,
+"This hook is called by Haifa Scheduler. It returns true if dispatch scheduling\n\
+is supported in hardware and the condition specified in the parameter is true.",
+bool, (rtx_insn *insn, int x),
+hook_bool_rtx_insn_int_false)
+
+DEFHOOKPOD
+(exposed_pipeline,
+"True if the processor has an exposed pipeline, which means that not just\n\
+the order of instructions is important for correctness when scheduling, but\n\
+also the latencies of operations.",
+bool, false)
+
+/* The following member value is a function that returns number
+ of operations reassociator should try to put in parallel for
+ statements of the given type. By default 1 is used. */
+DEFHOOK
+(reassociation_width,
+"This hook is called by tree reassociator to determine a level of\n\
+parallelism required in output calculations chain.",
+int, (unsigned int opc, machine_mode mode),
+hook_int_uint_mode_1)
+
+/* The following member value is a function that returns priority for
+ fusion of each instruction via pointer parameters. */
+DEFHOOK
+(fusion_priority,
+"This hook is called by scheduling fusion pass. It calculates fusion\n\
+priorities for each instruction passed in by parameter. The priorities\n\
+are returned via pointer parameters.\n\
+\n\
+@var{insn} is the instruction whose priorities need to be calculated.\n\
+@var{max_pri} is the maximum priority can be returned in any cases.\n\
+@var{fusion_pri} is the pointer parameter through which @var{insn}'s\n\
+fusion priority should be calculated and returned.\n\
+@var{pri} is the pointer parameter through which @var{insn}'s priority\n\
+should be calculated and returned.\n\
+\n\
+Same @var{fusion_pri} should be returned for instructions which should\n\
+be scheduled together. Different @var{pri} should be returned for\n\
+instructions with same @var{fusion_pri}. @var{fusion_pri} is the major\n\
+sort key, @var{pri} is the minor sort key. All instructions will be\n\
+scheduled according to the two priorities. All priorities calculated\n\
+should be between 0 (exclusive) and @var{max_pri} (inclusive). To avoid\n\
+false dependencies, @var{fusion_pri} of instructions which need to be\n\
+scheduled together should be smaller than @var{fusion_pri} of irrelevant\n\
+instructions.\n\
+\n\
+Given below example:\n\
+\n\
+@smallexample\n\
+ ldr r10, [r1, 4]\n\
+ add r4, r4, r10\n\
+ ldr r15, [r2, 8]\n\
+ sub r5, r5, r15\n\
+ ldr r11, [r1, 0]\n\
+ add r4, r4, r11\n\
+ ldr r16, [r2, 12]\n\
+ sub r5, r5, r16\n\
+@end smallexample\n\
+\n\
+On targets like ARM/AArch64, the two pairs of consecutive loads should be\n\
+merged. Since peephole2 pass can't help in this case unless consecutive\n\
+loads are actually next to each other in instruction flow. That's where\n\
+this scheduling fusion pass works. This hook calculates priority for each\n\
+instruction based on its fustion type, like:\n\
+\n\
+@smallexample\n\
+ ldr r10, [r1, 4] ; fusion_pri=99, pri=96\n\
+ add r4, r4, r10 ; fusion_pri=100, pri=100\n\
+ ldr r15, [r2, 8] ; fusion_pri=98, pri=92\n\
+ sub r5, r5, r15 ; fusion_pri=100, pri=100\n\
+ ldr r11, [r1, 0] ; fusion_pri=99, pri=100\n\
+ add r4, r4, r11 ; fusion_pri=100, pri=100\n\
+ ldr r16, [r2, 12] ; fusion_pri=98, pri=88\n\
+ sub r5, r5, r16 ; fusion_pri=100, pri=100\n\
+@end smallexample\n\
+\n\
+Scheduling fusion pass then sorts all ready to issue instructions according\n\
+to the priorities. As a result, instructions of same fusion type will be\n\
+pushed together in instruction flow, like:\n\
+\n\
+@smallexample\n\
+ ldr r11, [r1, 0]\n\
+ ldr r10, [r1, 4]\n\
+ ldr r15, [r2, 8]\n\
+ ldr r16, [r2, 12]\n\
+ add r4, r4, r10\n\
+ sub r5, r5, r15\n\
+ add r4, r4, r11\n\
+ sub r5, r5, r16\n\
+@end smallexample\n\
+\n\
+Now peephole2 pass can simply merge the two pairs of loads.\n\
+\n\
+Since scheduling fusion pass relies on peephole2 to do real fusion\n\
+work, it is only enabled by default when peephole2 is in effect.\n\
+\n\
+This is firstly introduced on ARM/AArch64 targets, please refer to\n\
+the hook implementation for how different fusion types are supported.",
+void, (rtx_insn *insn, int max_pri, int *fusion_pri, int *pri), NULL)
+
+HOOK_VECTOR_END (sched)
+
+/* Functions relating to OpenMP SIMD and __attribute__((simd)) clones. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_SIMD_CLONE_"
+HOOK_VECTOR (TARGET_SIMD_CLONE, simd_clone)
+
+DEFHOOK
+(compute_vecsize_and_simdlen,
+"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\
+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)
+
+DEFHOOK
+(adjust,
+"This hook should add implicit @code{attribute(target(\"...\"))} attribute\n\
+to SIMD clone @var{node} if needed.",
+void, (struct cgraph_node *), NULL)
+
+DEFHOOK
+(usable,
+"This hook should return -1 if SIMD clone @var{node} shouldn't be used\n\
+in vectorized loops in current function, or non-negative number if it is\n\
+usable. In that case, the smaller the number is, the more desirable it is\n\
+to use it.",
+int, (struct cgraph_node *), NULL)
+
+HOOK_VECTOR_END (simd_clone)
+
+/* Functions relating to OpenMP SIMT vectorization transform. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_SIMT_"
+HOOK_VECTOR (TARGET_SIMT, simt)
+
+DEFHOOK
+(vf,
+"Return number of threads in SIMT thread group on the target.",
+int, (void), NULL)
+
+HOOK_VECTOR_END (simt)
+
+/* Functions relating to OpenMP. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_OMP_"
+HOOK_VECTOR (TARGET_OMP, omp)
+
+DEFHOOK
+(device_kind_arch_isa,
+"Return 1 if @var{trait} @var{name} is present in the OpenMP context's\n\
+device trait set, return 0 if not present in any OpenMP context in the\n\
+whole translation unit, or -1 if not present in the current OpenMP context\n\
+but might be present in another OpenMP context in the same TU.",
+int, (enum omp_device_kind_arch_isa trait, const char *name), NULL)
+
+HOOK_VECTOR_END (omp)
+
+/* Functions relating to openacc. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_GOACC_"
+HOOK_VECTOR (TARGET_GOACC, goacc)
+
+DEFHOOK
+(validate_dims,
+"This hook should check the launch dimensions provided for an OpenACC\n\
+compute region, or routine. Defaulted values are represented as -1\n\
+and non-constant values as 0. The @var{fn_level} is negative for the\n\
+function corresponding to the compute region. For a routine it is the\n\
+outermost level at which partitioned execution may be spawned. The hook\n\
+should verify non-default values. If DECL is NULL, global defaults\n\
+are being validated and unspecified defaults should be filled in.\n\
+Diagnostics should be issued as appropriate. Return\n\
+true, if changes have been made. You must override this hook to\n\
+provide dimensions larger than 1.",
+bool, (tree decl, int *dims, int fn_level, unsigned used),
+default_goacc_validate_dims)
+
+DEFHOOK
+(dim_limit,
+"This hook should return the maximum size of a particular dimension,\n\
+or zero if unbounded.",
+int, (int axis),
+default_goacc_dim_limit)
+
+DEFHOOK
+(fork_join,
+"This hook can be used to convert IFN_GOACC_FORK and IFN_GOACC_JOIN\n\
+function calls to target-specific gimple, or indicate whether they\n\
+should be retained. It is executed during the oacc_device_lower pass.\n\
+It should return true, if the call should be retained. It should\n\
+return false, if it is to be deleted (either because target-specific\n\
+gimple has been inserted before it, or there is no need for it).\n\
+The default hook returns false, if there are no RTL expanders for them.",
+bool, (gcall *call, const int *dims, bool is_fork),
+default_goacc_fork_join)
+
+DEFHOOK
+(reduction,
+"This hook is used by the oacc_transform pass to expand calls to the\n\
+@var{GOACC_REDUCTION} internal function, into a sequence of gimple\n\
+instructions. @var{call} is gimple statement containing the call to\n\
+the function. This hook removes statement @var{call} after the\n\
+expanded sequence has been inserted. This hook is also responsible\n\
+for allocating any storage for reductions when necessary.",
+void, (gcall *call),
+default_goacc_reduction)
+
+DEFHOOK
+(adjust_private_decl,
+"This hook, if defined, is used by accelerator target back-ends to adjust\n\
+OpenACC variable declarations that should be made private to the given\n\
+parallelism level (i.e. @code{GOMP_DIM_GANG}, @code{GOMP_DIM_WORKER} or\n\
+@code{GOMP_DIM_VECTOR}). A typical use for this hook is to force variable\n\
+declarations at the @code{gang} level to reside in GPU shared memory.\n\
+@var{loc} may be used for diagnostic purposes.\n\
+\n\
+You may also use the @code{TARGET_GOACC_EXPAND_VAR_DECL} hook if the\n\
+adjusted variable declaration needs to be expanded to RTL in a non-standard\n\
+way.",
+tree, (location_t loc, tree var, int level),
+NULL)
+
+DEFHOOK
+(expand_var_decl,
+"This hook, if defined, is used by accelerator target back-ends to expand\n\
+specially handled kinds of @code{VAR_DECL} expressions. A particular use is\n\
+to place variables with specific attributes inside special accelarator\n\
+memories. A return value of @code{NULL} indicates that the target does not\n\
+handle this @code{VAR_DECL}, and normal RTL expanding is resumed.\n\
+\n\
+Only define this hook if your accelerator target needs to expand certain\n\
+@code{VAR_DECL} nodes in a way that differs from the default. You can also adjust\n\
+private variables at OpenACC device-lowering time using the\n\
+@code{TARGET_GOACC_ADJUST_PRIVATE_DECL} target hook.",
+rtx, (tree var),
+NULL)
+
+DEFHOOK
+(create_worker_broadcast_record,
+"Create a record used to propagate local-variable state from an active\n\
+worker to other workers. A possible implementation might adjust the type\n\
+of REC to place the new variable in shared GPU memory.\n\
+\n\
+Presence of this target hook indicates that middle end neutering/broadcasting\n\
+be used.",
+tree, (tree rec, bool sender, const char *name, unsigned HOST_WIDE_INT offset),
+NULL)
+
+DEFHOOK
+(shared_mem_layout,
+"Lay out a fixed shared-memory region on the target. The LO and HI\n\
+arguments should be set to a range of addresses that can be used for worker\n\
+broadcasting. The dimensions, reduction size and gang-private size\n\
+arguments are for the current offload region.",
+void, (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, int[],
+ unsigned HOST_WIDE_INT[], unsigned HOST_WIDE_INT[]),
+NULL)
+
+HOOK_VECTOR_END (goacc)
+
+/* Functions relating to vectorization. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_VECTORIZE_"
+HOOK_VECTOR (TARGET_VECTORIZE, vectorize)
+
+/* The following member value is a pointer to a function called
+ by the vectorizer, and return the decl of the target builtin
+ function. */
+DEFHOOK
+(builtin_mask_for_load,
+ "This hook should return the DECL of a function @var{f} that given an\n\
+address @var{addr} as an argument returns a mask @var{m} that can be\n\
+used to extract from two vectors the relevant data that resides in\n\
+@var{addr} in case @var{addr} is not properly aligned.\n\
+\n\
+The autovectorizer, when vectorizing a load operation from an address\n\
+@var{addr} that may be unaligned, will generate two vector loads from\n\
+the two aligned addresses around @var{addr}. It then generates a\n\
+@code{REALIGN_LOAD} operation to extract the relevant data from the\n\
+two loaded vectors. The first two arguments to @code{REALIGN_LOAD},\n\
+@var{v1} and @var{v2}, are the two vectors, each of size @var{VS}, and\n\
+the third argument, @var{OFF}, defines how the data will be extracted\n\
+from these two vectors: if @var{OFF} is 0, then the returned vector is\n\
+@var{v2}; otherwise, the returned vector is composed from the last\n\
+@var{VS}-@var{OFF} elements of @var{v1} concatenated to the first\n\
+@var{OFF} elements of @var{v2}.\n\
+\n\
+If this hook is defined, the autovectorizer will generate a call\n\
+to @var{f} (using the DECL tree that this hook returns) and will\n\
+use the return value of @var{f} as the argument @var{OFF} to\n\
+@code{REALIGN_LOAD}. Therefore, the mask @var{m} returned by @var{f}\n\
+should comply with the semantics expected by @code{REALIGN_LOAD}\n\
+described above.\n\
+If this hook is not defined, then @var{addr} will be used as\n\
+the argument @var{OFF} to @code{REALIGN_LOAD}, in which case the low\n\
+log2(@var{VS}) @minus{} 1 bits of @var{addr} will be considered.",
+ tree, (void), NULL)
+
+/* Returns a built-in function that realizes the vectorized version of
+ a target-independent function, or NULL_TREE if not available. */
+DEFHOOK
+(builtin_vectorized_function,
+ "This hook should return the decl of a function that implements the\n\
+vectorized variant of the function with the @code{combined_fn} code\n\
+@var{code} or @code{NULL_TREE} if such a function is not available.\n\
+The return type of the vectorized function shall be of vector type\n\
+@var{vec_type_out} and the argument types should be @var{vec_type_in}.",
+ tree, (unsigned code, tree vec_type_out, tree vec_type_in),
+ default_builtin_vectorized_function)
+
+/* Returns a built-in function that realizes the vectorized version of
+ a target-specific function, or NULL_TREE if not available. */
+DEFHOOK
+(builtin_md_vectorized_function,
+ "This hook should return the decl of a function that implements the\n\
+vectorized variant of target built-in function @code{fndecl}. The\n\
+return type of the vectorized function shall be of vector type\n\
+@var{vec_type_out} and the argument types should be @var{vec_type_in}.",
+ tree, (tree fndecl, tree vec_type_out, tree vec_type_in),
+ default_builtin_md_vectorized_function)
+
+/* Cost of different vector/scalar statements in vectorization cost
+ model. In case of misaligned vector loads and stores the cost depends
+ on the data type and misalignment value. */
+DEFHOOK
+(builtin_vectorization_cost,
+ "Returns cost of different scalar or vector statements for vectorization cost model.\n\
+For vector memory operations the cost may depend on type (@var{vectype}) and\n\
+misalignment value (@var{misalign}).",
+ int, (enum vect_cost_for_stmt type_of_cost, tree vectype, int misalign),
+ default_builtin_vectorization_cost)
+
+DEFHOOK
+(preferred_vector_alignment,
+ "This hook returns the preferred alignment in bits for accesses to\n\
+vectors of type @var{type} in vectorized code. This might be less than\n\
+or greater than the ABI-defined value returned by\n\
+@code{TARGET_VECTOR_ALIGNMENT}. It can be equal to the alignment of\n\
+a single element, in which case the vectorizer will not try to optimize\n\
+for alignment.\n\
+\n\
+The default hook returns @code{TYPE_ALIGN (@var{type})}, which is\n\
+correct for most targets.",
+ poly_uint64, (const_tree type),
+ default_preferred_vector_alignment)
+
+/* Return true if vector alignment is reachable (by peeling N
+ iterations) for the given scalar type. */
+DEFHOOK
+(vector_alignment_reachable,
+ "Return true if vector alignment is reachable (by peeling N iterations)\n\
+for the given scalar type @var{type}. @var{is_packed} is false if the scalar\n\
+access using @var{type} is known to be naturally aligned.",
+ bool, (const_tree type, bool is_packed),
+ default_builtin_vector_alignment_reachable)
+
+DEFHOOK
+(vec_perm_const,
+ "This hook is used to test whether the target can permute up to two\n\
+vectors of mode @var{mode} using the permutation vector @code{sel}, and\n\
+also to emit such a permutation. In the former case @var{in0}, @var{in1}\n\
+and @var{out} are all null. In the latter case @var{in0} and @var{in1} are\n\
+the source vectors and @var{out} is the destination vector; all three are\n\
+operands of mode @var{mode}. @var{in1} is the same as @var{in0} if\n\
+@var{sel} describes a permutation on one vector instead of two.\n\
+\n\
+Return true if the operation is possible, emitting instructions for it\n\
+if rtxes are provided.\n\
+\n\
+@cindex @code{vec_perm@var{m}} instruction pattern\n\
+If the hook returns false for a mode with multibyte elements, GCC will\n\
+try the equivalent byte operation. If that also fails, it will try forcing\n\
+the selector into a register and using the @var{vec_perm@var{mode}}\n\
+instruction pattern. There is no need for the hook to handle these two\n\
+implementation approaches itself.",
+ bool, (machine_mode mode, rtx output, rtx in0, rtx in1,
+ const vec_perm_indices &sel),
+ NULL)
+
+/* Return true if the target supports misaligned store/load of a
+ specific factor denoted in the third parameter. The last parameter
+ is true if the access is defined in a packed struct. */
+DEFHOOK
+(support_vector_misalignment,
+ "This hook should return true if the target supports misaligned vector\n\
+store/load of a specific factor denoted in the @var{misalignment}\n\
+parameter. The vector store/load should be of machine mode @var{mode} and\n\
+the elements in the vectors should be of type @var{type}. @var{is_packed}\n\
+parameter is true if the memory access is defined in a packed struct.",
+ bool,
+ (machine_mode mode, const_tree type, int misalignment, bool is_packed),
+ default_builtin_support_vector_misalignment)
+
+/* Returns the preferred mode for SIMD operations for the specified
+ scalar mode. */
+DEFHOOK
+(preferred_simd_mode,
+ "This hook should return the preferred mode for vectorizing scalar\n\
+mode @var{mode}. The default is\n\
+equal to @code{word_mode}, because the vectorizer can do some\n\
+transformations even in absence of specialized @acronym{SIMD} hardware.",
+ machine_mode,
+ (scalar_mode mode),
+ default_preferred_simd_mode)
+
+/* Returns the preferred mode for splitting SIMD reductions to. */
+DEFHOOK
+(split_reduction,
+ "This hook should return the preferred mode to split the final reduction\n\
+step on @var{mode} to. The reduction is then carried out reducing upper\n\
+against lower halves of vectors recursively until the specified mode is\n\
+reached. The default is @var{mode} which means no splitting.",
+ machine_mode,
+ (machine_mode),
+ default_split_reduction)
+
+/* Returns a mask of vector sizes to iterate over when auto-vectorizing
+ after processing the preferred one derived from preferred_simd_mode. */
+DEFHOOK
+(autovectorize_vector_modes,
+ "If using the mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}\n\
+is not the only approach worth considering, this hook should add one mode to\n\
+@var{modes} for each useful alternative approach. These modes are then\n\
+passed to @code{TARGET_VECTORIZE_RELATED_MODE} to obtain the vector mode\n\
+for a given element mode.\n\
+\n\
+The modes returned in @var{modes} should use the smallest element mode\n\
+possible for the vectorization approach that they represent, preferring\n\
+integer modes over floating-poing modes in the event of a tie. The first\n\
+mode should be the @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE} for its\n\
+element mode.\n\
+\n\
+If @var{all} is true, add suitable vector modes even when they are generally\n\
+not expected to be worthwhile.\n\
+\n\
+The hook returns a bitmask of flags that control how the modes in\n\
+@var{modes} are used. The flags are:\n\
+@table @code\n\
+@item VECT_COMPARE_COSTS\n\
+Tells the loop vectorizer to try all the provided modes and pick the one\n\
+with the lowest cost. By default the vectorizer will choose the first\n\
+mode that works.\n\
+@end table\n\
+\n\
+The hook does not need to do anything if the vector returned by\n\
+@code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE} is the only one relevant\n\
+for autovectorization. The default implementation adds no modes and\n\
+returns 0.",
+ unsigned int,
+ (vector_modes *modes, bool all),
+ default_autovectorize_vector_modes)
+
+DEFHOOK
+(related_mode,
+ "If a piece of code is using vector mode @var{vector_mode} and also wants\n\
+to operate on elements of mode @var{element_mode}, return the vector mode\n\
+it should use for those elements. If @var{nunits} is nonzero, ensure that\n\
+the mode has exactly @var{nunits} elements, otherwise pick whichever vector\n\
+size pairs the most naturally with @var{vector_mode}. Return an empty\n\
+@code{opt_machine_mode} if there is no supported vector mode with the\n\
+required properties.\n\
+\n\
+There is no prescribed way of handling the case in which @var{nunits}\n\
+is zero. One common choice is to pick a vector mode with the same size\n\
+as @var{vector_mode}; this is the natural choice if the target has a\n\
+fixed vector size. Another option is to choose a vector mode with the\n\
+same number of elements as @var{vector_mode}; this is the natural choice\n\
+if the target has a fixed number of elements. Alternatively, the hook\n\
+might choose a middle ground, such as trying to keep the number of\n\
+elements as similar as possible while applying maximum and minimum\n\
+vector sizes.\n\
+\n\
+The default implementation uses @code{mode_for_vector} to find the\n\
+requested mode, returning a mode with the same size as @var{vector_mode}\n\
+when @var{nunits} is zero. This is the correct behavior for most targets.",
+ opt_machine_mode,
+ (machine_mode vector_mode, scalar_mode element_mode, poly_uint64 nunits),
+ default_vectorize_related_mode)
+
+/* Function to get a target mode for a vector mask. */
+DEFHOOK
+(get_mask_mode,
+ "Return the mode to use for a vector mask that holds one boolean\n\
+result for each element of vector mode @var{mode}. The returned mask mode\n\
+can be a vector of integers (class @code{MODE_VECTOR_INT}), a vector of\n\
+booleans (class @code{MODE_VECTOR_BOOL}) or a scalar integer (class\n\
+@code{MODE_INT}). Return an empty @code{opt_machine_mode} if no such\n\
+mask mode exists.\n\
+\n\
+The default implementation returns a @code{MODE_VECTOR_INT} with the\n\
+same size and number of elements as @var{mode}, if such a mode exists.",
+ opt_machine_mode,
+ (machine_mode mode),
+ default_get_mask_mode)
+
+/* Function to say whether a masked operation is expensive when the
+ mask is all zeros. */
+DEFHOOK
+(empty_mask_is_expensive,
+ "This hook returns true if masked internal function @var{ifn} (really of\n\
+type @code{internal_fn}) should be considered expensive when the mask is\n\
+all zeros. GCC can then try to branch around the instruction instead.",
+ bool,
+ (unsigned ifn),
+ default_empty_mask_is_expensive)
+
+/* Target builtin that implements vector gather operation. */
+DEFHOOK
+(builtin_gather,
+ "Target builtin that implements vector gather operation. @var{mem_vectype}\n\
+is the vector type of the load and @var{index_type} is scalar type of\n\
+the index, scaled by @var{scale}.\n\
+The default is @code{NULL_TREE} which means to not vectorize gather\n\
+loads.",
+ tree,
+ (const_tree mem_vectype, const_tree index_type, int scale),
+ NULL)
+
+/* Target builtin that implements vector scatter operation. */
+DEFHOOK
+(builtin_scatter,
+"Target builtin that implements vector scatter operation. @var{vectype}\n\
+is the vector type of the store and @var{index_type} is scalar type of\n\
+the index, scaled by @var{scale}.\n\
+The default is @code{NULL_TREE} which means to not vectorize scatter\n\
+stores.",
+ tree,
+ (const_tree vectype, const_tree index_type, int scale),
+ NULL)
+
+/* Target function to initialize the cost model for a loop or block. */
+DEFHOOK
+(create_costs,
+ "This hook should initialize target-specific data structures in preparation\n\
+for modeling the costs of vectorizing a loop or basic block. The default\n\
+allocates three unsigned integers for accumulating costs for the prologue,\n\
+body, and epilogue of the loop or basic block. If @var{loop_info} is\n\
+non-NULL, it identifies the loop being vectorized; otherwise a single block\n\
+is being vectorized. If @var{costing_for_scalar} is true, it indicates the\n\
+current cost model is for the scalar version of a loop or block; otherwise\n\
+it is for the vector version.",
+ class vector_costs *,
+ (vec_info *vinfo, bool costing_for_scalar),
+ default_vectorize_create_costs)
+
+HOOK_VECTOR_END (vectorize)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+DEFHOOK
+(preferred_else_value,
+ "This hook returns the target's preferred final argument for a call\n\
+to conditional internal function @var{ifn} (really of type\n\
+@code{internal_fn}). @var{type} specifies the return type of the\n\
+function and @var{ops} are the operands to the conditional operation,\n\
+of which there are @var{nops}.\n\
+\n\
+For example, if @var{ifn} is @code{IFN_COND_ADD}, the hook returns\n\
+a value of type @var{type} that should be used when @samp{@var{ops}[0]}\n\
+and @samp{@var{ops}[1]} are conditionally added together.\n\
+\n\
+This hook is only relevant if the target supports conditional patterns\n\
+like @code{cond_add@var{m}}. The default implementation returns a zero\n\
+constant of type @var{type}.",
+ tree,
+ (unsigned ifn, tree type, unsigned nops, tree *ops),
+ default_preferred_else_value)
+
+DEFHOOK
+(record_offload_symbol,
+ "Used when offloaded functions are seen in the compilation unit and no named\n\
+sections are available. It is called once for each symbol that must be\n\
+recorded in the offload function and variable table.",
+ void, (tree),
+ hook_void_tree)
+
+DEFHOOKPOD
+(absolute_biggest_alignment,
+ "If defined, this target hook specifies the absolute biggest alignment\n\
+that a type or variable can have on this machine, otherwise,\n\
+@code{BIGGEST_ALIGNMENT} is used.",
+ HOST_WIDE_INT, BIGGEST_ALIGNMENT)
+
+/* Allow target specific overriding of option settings after options have
+ been changed by an attribute or pragma or when it is reset at the
+ end of the code affected by an attribute or pragma. */
+DEFHOOK
+(override_options_after_change,
+ "This target function is similar to the hook @code{TARGET_OPTION_OVERRIDE}\n\
+but is called when the optimize level is changed via an attribute or\n\
+pragma or when it is reset at the end of the code affected by the\n\
+attribute or pragma. It is not called at the beginning of compilation\n\
+when @code{TARGET_OPTION_OVERRIDE} is called so if you want to perform these\n\
+actions then, you should have @code{TARGET_OPTION_OVERRIDE} call\n\
+@code{TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE}.",
+ void, (void),
+ hook_void_void)
+
+DEFHOOK
+(offload_options,
+ "Used when writing out the list of options into an LTO file. It should\n\
+translate any relevant target-specific options (such as the ABI in use)\n\
+into one of the @option{-foffload} options that exist as a common interface\n\
+to express such options. It should return a string containing these options,\n\
+separated by spaces, which the caller will free.\n",
+char *, (void), hook_charptr_void_null)
+
+DEFHOOK_UNDOC
+(eh_return_filter_mode,
+ "Return machine mode for filter value.",
+ scalar_int_mode, (void),
+ default_eh_return_filter_mode)
+
+/* Return machine mode for libgcc expanded cmp instructions. */
+DEFHOOK
+(libgcc_cmp_return_mode,
+ "This target hook should return the mode to be used for the return value\n\
+of compare instructions expanded to libgcc calls. If not defined\n\
+@code{word_mode} is returned which is the right choice for a majority of\n\
+targets.",
+ scalar_int_mode, (void),
+ default_libgcc_cmp_return_mode)
+
+/* Return machine mode for libgcc expanded shift instructions. */
+DEFHOOK
+(libgcc_shift_count_mode,
+ "This target hook should return the mode to be used for the shift count operand\n\
+of shift instructions expanded to libgcc calls. If not defined\n\
+@code{word_mode} is returned which is the right choice for a majority of\n\
+targets.",
+ scalar_int_mode, (void),
+ default_libgcc_shift_count_mode)
+
+/* Return machine mode to be used for _Unwind_Word type. */
+DEFHOOK
+(unwind_word_mode,
+ "Return machine mode to be used for @code{_Unwind_Word} type.\n\
+The default is to use @code{word_mode}.",
+ scalar_int_mode, (void),
+ default_unwind_word_mode)
+
+/* Given two decls, merge their attributes and return the result. */
+DEFHOOK
+(merge_decl_attributes,
+ "Define this target hook if the merging of decl attributes needs special\n\
+handling. If defined, the result is a list of the combined\n\
+@code{DECL_ATTRIBUTES} of @var{olddecl} and @var{newdecl}.\n\
+@var{newdecl} is a duplicate declaration of @var{olddecl}. Examples of\n\
+when this is needed are when one attribute overrides another, or when an\n\
+attribute is nullified by a subsequent definition. This function may\n\
+call @code{merge_attributes} to handle machine-independent merging.\n\
+\n\
+@findex TARGET_DLLIMPORT_DECL_ATTRIBUTES\n\
+If the only target-specific handling you require is @samp{dllimport}\n\
+for Microsoft Windows targets, you should define the macro\n\
+@code{TARGET_DLLIMPORT_DECL_ATTRIBUTES} to @code{1}. The compiler\n\
+will then define a function called\n\
+@code{merge_dllimport_decl_attributes} which can then be defined as\n\
+the expansion of @code{TARGET_MERGE_DECL_ATTRIBUTES}. You can also\n\
+add @code{handle_dll_attribute} in the attribute table for your port\n\
+to perform initial processing of the @samp{dllimport} and\n\
+@samp{dllexport} attributes. This is done in @file{i386/cygwin.h} and\n\
+@file{i386/i386.cc}, for example.",
+ tree, (tree olddecl, tree newdecl),
+ merge_decl_attributes)
+
+/* Given two types, merge their attributes and return the result. */
+DEFHOOK
+(merge_type_attributes,
+ "Define this target hook if the merging of type attributes needs special\n\
+handling. If defined, the result is a list of the combined\n\
+@code{TYPE_ATTRIBUTES} of @var{type1} and @var{type2}. It is assumed\n\
+that @code{comptypes} has already been called and returned 1. This\n\
+function may call @code{merge_attributes} to handle machine-independent\n\
+merging.",
+ tree, (tree type1, tree type2),
+ merge_type_attributes)
+
+/* Table of machine attributes and functions to handle them.
+ Ignored if NULL. */
+DEFHOOKPOD
+(attribute_table,
+ "If defined, this target hook points to an array of @samp{struct\n\
+attribute_spec} (defined in @file{tree-core.h}) specifying the machine\n\
+specific attributes for this target and some of the restrictions on the\n\
+entities to which these attributes are applied and the arguments they\n\
+take.",
+ const struct attribute_spec *, NULL)
+
+/* Return true iff attribute NAME expects a plain identifier as its first
+ argument. */
+DEFHOOK
+(attribute_takes_identifier_p,
+ "If defined, this target hook is a function which returns true if the\n\
+machine-specific attribute named @var{name} expects an identifier\n\
+given as its first argument to be passed on as a plain identifier, not\n\
+subjected to name lookup. If this is not defined, the default is\n\
+false for all machine-specific attributes.",
+ bool, (const_tree name),
+ hook_bool_const_tree_false)
+
+/* Return zero if the attributes on TYPE1 and TYPE2 are incompatible,
+ one if they are compatible and two if they are nearly compatible
+ (which causes a warning to be generated). */
+DEFHOOK
+(comp_type_attributes,
+ "If defined, this target hook is a function which returns zero if the attributes on\n\
+@var{type1} and @var{type2} are incompatible, one if they are compatible,\n\
+and two if they are nearly compatible (which causes a warning to be\n\
+generated). If this is not defined, machine-specific attributes are\n\
+supposed always to be compatible.",
+ int, (const_tree type1, const_tree type2),
+ hook_int_const_tree_const_tree_1)
+
+/* Assign default attributes to the newly defined TYPE. */
+DEFHOOK
+(set_default_type_attributes,
+ "If defined, this target hook is a function which assigns default attributes to\n\
+the newly defined @var{type}.",
+ void, (tree type),
+ hook_void_tree)
+
+/* Insert attributes on the newly created DECL. */
+DEFHOOK
+(insert_attributes,
+ "Define this target hook if you want to be able to add attributes to a decl\n\
+when it is being created. This is normally useful for back ends which\n\
+wish to implement a pragma by using the attributes which correspond to\n\
+the pragma's effect. The @var{node} argument is the decl which is being\n\
+created. The @var{attr_ptr} argument is a pointer to the attribute list\n\
+for this decl. The list itself should not be modified, since it may be\n\
+shared with other decls, but attributes may be chained on the head of\n\
+the list and @code{*@var{attr_ptr}} modified to point to the new\n\
+attributes, or a copy of the list may be made if further changes are\n\
+needed.",
+ void, (tree node, tree *attr_ptr),
+ hook_void_tree_treeptr)
+
+/* Perform additional target-specific processing of generic attributes. */
+DEFHOOK
+(handle_generic_attribute,
+ "Define this target hook if you want to be able to perform additional\n\
+target-specific processing of an attribute which is handled generically\n\
+by a front end. The arguments are the same as those which are passed to\n\
+attribute handlers. So far this only affects the @var{noinit} and\n\
+@var{section} attribute.",
+ tree, (tree *node, tree name, tree args, int flags, bool *no_add_attrs),
+ hook_tree_treeptr_tree_tree_int_boolptr_null)
+
+/* Return true if FNDECL (which has at least one machine attribute)
+ can be inlined despite its machine attributes, false otherwise. */
+DEFHOOK
+(function_attribute_inlinable_p,
+ "@cindex inlining\n\
+This target hook returns @code{true} if it is OK to inline @var{fndecl}\n\
+into the current function, despite its having target-specific\n\
+attributes, @code{false} otherwise. By default, if a function has a\n\
+target specific attribute attached to it, it will not be inlined.",
+ bool, (const_tree fndecl),
+ hook_bool_const_tree_false)
+
+/* Return true if bitfields in RECORD_TYPE should follow the
+ Microsoft Visual C++ bitfield layout rules. */
+DEFHOOK
+(ms_bitfield_layout_p,
+ "This target hook returns @code{true} if bit-fields in the given\n\
+@var{record_type} are to be laid out following the rules of Microsoft\n\
+Visual C/C++, namely: (i) a bit-field won't share the same storage\n\
+unit with the previous bit-field if their underlying types have\n\
+different sizes, and the bit-field will be aligned to the highest\n\
+alignment of the underlying types of itself and of the previous\n\
+bit-field; (ii) a zero-sized bit-field will affect the alignment of\n\
+the whole enclosing structure, even if it is unnamed; except that\n\
+(iii) a zero-sized bit-field will be disregarded unless it follows\n\
+another bit-field of nonzero size. If this hook returns @code{true},\n\
+other macros that control bit-field layout are ignored.\n\
+\n\
+When a bit-field is inserted into a packed record, the whole size\n\
+of the underlying type is used by one or more same-size adjacent\n\
+bit-fields (that is, if its long:3, 32 bits is used in the record,\n\
+and any additional adjacent long bit-fields are packed into the same\n\
+chunk of 32 bits. However, if the size changes, a new field of that\n\
+size is allocated). In an unpacked record, this is the same as using\n\
+alignment, but not equivalent when packing.\n\
+\n\
+If both MS bit-fields and @samp{__attribute__((packed))} are used,\n\
+the latter will take precedence. If @samp{__attribute__((packed))} is\n\
+used on a single field when MS bit-fields are in use, it will take\n\
+precedence for that field, but the alignment of the rest of the structure\n\
+may affect its placement.",
+ bool, (const_tree record_type),
+ hook_bool_const_tree_false)
+
+/* For now this is only an interface to WORDS_BIG_ENDIAN for
+ target-independent code like the front ends, need performance testing
+ before switching completely to the target hook. */
+DEFHOOK_UNDOC
+(words_big_endian,
+ "",
+ bool, (void),
+ targhook_words_big_endian)
+
+/* Likewise for FLOAT_WORDS_BIG_ENDIAN. */
+DEFHOOK_UNDOC
+(float_words_big_endian,
+ "",
+ bool, (void),
+ targhook_float_words_big_endian)
+
+DEFHOOK
+(float_exceptions_rounding_supported_p,
+ "Returns true if the target supports IEEE 754 floating-point exceptions\n\
+and rounding modes, false otherwise. This is intended to relate to the\n\
+@code{float} and @code{double} types, but not necessarily @code{long double}.\n\
+By default, returns true if the @code{adddf3} instruction pattern is\n\
+available and false otherwise, on the assumption that hardware floating\n\
+point supports exceptions and rounding modes but software floating point\n\
+does not.",
+ bool, (void),
+ default_float_exceptions_rounding_supported_p)
+
+/* True if the target supports decimal floating point. */
+DEFHOOK
+(decimal_float_supported_p,
+ "Returns true if the target supports decimal floating point.",
+ bool, (void),
+ default_decimal_float_supported_p)
+
+/* True if the target supports fixed-point. */
+DEFHOOK
+(fixed_point_supported_p,
+ "Returns true if the target supports fixed-point arithmetic.",
+ bool, (void),
+ default_fixed_point_supported_p)
+
+/* Return true if anonymous bitfields affect structure alignment. */
+DEFHOOK
+(align_anon_bitfield,
+ "When @code{PCC_BITFIELD_TYPE_MATTERS} is true this hook will determine\n\
+whether unnamed bitfields affect the alignment of the containing\n\
+structure. The hook should return true if the structure should inherit\n\
+the alignment requirements of an unnamed bitfield's type.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Return true if volatile bitfields should use the narrowest type possible.
+ Return false if they should use the container type. */
+DEFHOOK
+(narrow_volatile_bitfield,
+ "This target hook should return @code{true} if accesses to volatile bitfields\n\
+should use the narrowest mode possible. It should return @code{false} if\n\
+these accesses should use the bitfield container type.\n\
+\n\
+The default is @code{false}.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Set up target-specific built-in functions. */
+DEFHOOK
+(init_builtins,
+ "Define this hook if you have any machine-specific built-in functions\n\
+that need to be defined. It should be a function that performs the\n\
+necessary setup.\n\
+\n\
+Machine specific built-in functions can be useful to expand special machine\n\
+instructions that would otherwise not normally be generated because\n\
+they have no equivalent in the source language (for example, SIMD vector\n\
+instructions or prefetch instructions).\n\
+\n\
+To create a built-in function, call the function\n\
+@code{lang_hooks.builtin_function}\n\
+which is defined by the language front end. You can use any type nodes set\n\
+up by @code{build_common_tree_nodes};\n\
+only language front ends that use those two functions will call\n\
+@samp{TARGET_INIT_BUILTINS}.",
+ void, (void),
+ hook_void_void)
+
+/* Initialize (if INITIALIZE_P is true) and return the target-specific
+ built-in function decl for CODE.
+ Return NULL if that is not possible. Return error_mark_node if CODE
+ is outside of the range of valid target builtin function codes. */
+DEFHOOK
+(builtin_decl,
+ "Define this hook if you have any machine-specific built-in functions\n\
+that need to be defined. It should be a function that returns the\n\
+builtin function declaration for the builtin function code @var{code}.\n\
+If there is no such builtin and it cannot be initialized at this time\n\
+if @var{initialize_p} is true the function should return @code{NULL_TREE}.\n\
+If @var{code} is out of range the function should return\n\
+@code{error_mark_node}.",
+ tree, (unsigned code, bool initialize_p), NULL)
+
+/* Expand a target-specific builtin. */
+DEFHOOK
+(expand_builtin,
+ "\n\
+Expand a call to a machine specific built-in function that was set up by\n\
+@samp{TARGET_INIT_BUILTINS}. @var{exp} is the expression for the\n\
+function call; the result should go to @var{target} if that is\n\
+convenient, and have mode @var{mode} if that is convenient.\n\
+@var{subtarget} may be used as the target for computing one of\n\
+@var{exp}'s operands. @var{ignore} is nonzero if the value is to be\n\
+ignored. This function should return the result of the call to the\n\
+built-in function.",
+ rtx,
+ (tree exp, rtx target, rtx subtarget, machine_mode mode, int ignore),
+ default_expand_builtin)
+
+/* Select a replacement for a target-specific builtin. This is done
+ *before* regular type checking, and so allows the target to
+ implement a crude form of function overloading. The result is a
+ complete expression that implements the operation. PARAMS really
+ has type VEC(tree,gc)*, but we don't want to include tree.h here. */
+DEFHOOK
+(resolve_overloaded_builtin,
+ "Select a replacement for a machine specific built-in function that\n\
+was set up by @samp{TARGET_INIT_BUILTINS}. This is done\n\
+@emph{before} regular type checking, and so allows the target to\n\
+implement a crude form of function overloading. @var{fndecl} is the\n\
+declaration of the built-in function. @var{arglist} is the list of\n\
+arguments passed to the built-in function. The result is a\n\
+complete expression that implements the operation, usually\n\
+another @code{CALL_EXPR}.\n\
+@var{arglist} really has type @samp{VEC(tree,gc)*}",
+ tree, (unsigned int /*location_t*/ loc, tree fndecl, void *arglist), NULL)
+
+DEFHOOK
+(check_builtin_call,
+ "Perform semantic checking on a call to a machine-specific built-in\n\
+function after its arguments have been constrained to the function\n\
+signature. Return true if the call is valid, otherwise report an error\n\
+and return false.\n\
+\n\
+This hook is called after @code{TARGET_RESOLVE_OVERLOADED_BUILTIN}.\n\
+The call was originally to built-in function @var{orig_fndecl},\n\
+but after the optional @code{TARGET_RESOLVE_OVERLOADED_BUILTIN}\n\
+step is now to built-in function @var{fndecl}. @var{loc} is the\n\
+location of the call and @var{args} is an array of function arguments,\n\
+of which there are @var{nargs}. @var{arg_loc} specifies the location\n\
+of each argument.",
+ bool, (location_t loc, vec<location_t> arg_loc, tree fndecl,
+ tree orig_fndecl, unsigned int nargs, tree *args),
+ NULL)
+
+/* Fold a target-specific builtin to a tree valid for both GIMPLE
+ and GENERIC. */
+DEFHOOK
+(fold_builtin,
+ "Fold a call to a machine specific built-in function that was set up by\n\
+@samp{TARGET_INIT_BUILTINS}. @var{fndecl} is the declaration of the\n\
+built-in function. @var{n_args} is the number of arguments passed to\n\
+the function; the arguments themselves are pointed to by @var{argp}.\n\
+The result is another tree, valid for both GIMPLE and GENERIC,\n\
+containing a simplified expression for the call's result. If\n\
+@var{ignore} is true the value will be ignored.",
+ tree, (tree fndecl, int n_args, tree *argp, bool ignore),
+ hook_tree_tree_int_treep_bool_null)
+
+/* Fold a target-specific builtin to a valid GIMPLE tree. */
+DEFHOOK
+(gimple_fold_builtin,
+ "Fold a call to a machine specific built-in function that was set up\n\
+by @samp{TARGET_INIT_BUILTINS}. @var{gsi} points to the gimple\n\
+statement holding the function call. Returns true if any change\n\
+was made to the GIMPLE stream.",
+ bool, (gimple_stmt_iterator *gsi),
+ hook_bool_gsiptr_false)
+
+/* Target hook is used to compare the target attributes in two functions to
+ determine which function's features get higher priority. This is used
+ during function multi-versioning to figure out the order in which two
+ versions must be dispatched. A function version with a higher priority
+ is checked for dispatching earlier. DECL1 and DECL2 are
+ the two function decls that will be compared. It returns positive value
+ if DECL1 is higher priority, negative value if DECL2 is higher priority
+ and 0 if they are the same. */
+DEFHOOK
+(compare_version_priority,
+ "This hook is used to compare the target attributes in two functions to\n\
+determine which function's features get higher priority. This is used\n\
+during function multi-versioning to figure out the order in which two\n\
+versions must be dispatched. A function version with a higher priority\n\
+is checked for dispatching earlier. @var{decl1} and @var{decl2} are\n\
+ the two function decls that will be compared.",
+ int, (tree decl1, tree decl2), NULL)
+
+/* Target hook is used to generate the dispatcher logic to invoke the right
+ function version at run-time for a given set of function versions.
+ ARG points to the callgraph node of the dispatcher function whose body
+ must be generated. */
+DEFHOOK
+(generate_version_dispatcher_body,
+ "This hook is used to generate the dispatcher logic to invoke the right\n\
+function version at run-time for a given set of function versions.\n\
+@var{arg} points to the callgraph node of the dispatcher function whose\n\
+body must be generated.",
+ tree, (void *arg), NULL)
+
+/* Target hook is used to get the dispatcher function for a set of function
+ versions. The dispatcher function is called to invoke the right function
+ version at run-time. DECL is one version from a set of semantically
+ identical versions. */
+DEFHOOK
+(get_function_versions_dispatcher,
+ "This hook is used to get the dispatcher function for a set of function\n\
+versions. The dispatcher function is called to invoke the right function\n\
+version at run-time. @var{decl} is one version from a set of semantically\n\
+identical versions.",
+ tree, (void *decl), NULL)
+
+/* Returns a code for a target-specific builtin that implements
+ reciprocal of a target-specific function, or NULL_TREE if not available. */
+DEFHOOK
+(builtin_reciprocal,
+ "This hook should return the DECL of a function that implements the\n\
+reciprocal of the machine-specific builtin function @var{fndecl}, or\n\
+@code{NULL_TREE} if such a function is not available.",
+ tree, (tree fndecl),
+ default_builtin_reciprocal)
+
+/* For a vendor-specific TYPE, return a pointer to a statically-allocated
+ string containing the C++ mangling for TYPE. In all other cases, return
+ NULL. */
+DEFHOOK
+(mangle_type,
+ "If your target defines any fundamental types, or any types your target\n\
+uses should be mangled differently from the default, define this hook\n\
+to return the appropriate encoding for these types as part of a C++\n\
+mangled name. The @var{type} argument is the tree structure representing\n\
+the type to be mangled. The hook may be applied to trees which are\n\
+not target-specific fundamental types; it should return @code{NULL}\n\
+for all such types, as well as arguments it does not recognize. If the\n\
+return value is not @code{NULL}, it must point to a statically-allocated\n\
+string constant.\n\
+\n\
+Target-specific fundamental types might be new fundamental types or\n\
+qualified versions of ordinary fundamental types. Encode new\n\
+fundamental types as @samp{@w{u @var{n} @var{name}}}, where @var{name}\n\
+is the name used for the type in source code, and @var{n} is the\n\
+length of @var{name} in decimal. Encode qualified versions of\n\
+ordinary types as @samp{@w{U @var{n} @var{name} @var{code}}}, where\n\
+@var{name} is the name used for the type qualifier in source code,\n\
+@var{n} is the length of @var{name} as above, and @var{code} is the\n\
+code used to represent the unqualified version of this type. (See\n\
+@code{write_builtin_type} in @file{cp/mangle.cc} for the list of\n\
+codes.) In both cases the spaces are for clarity; do not include any\n\
+spaces in your string.\n\
+\n\
+This hook is applied to types prior to typedef resolution. If the mangled\n\
+name for a particular type depends only on that type's main variant, you\n\
+can perform typedef resolution yourself using @code{TYPE_MAIN_VARIANT}\n\
+before mangling.\n\
+\n\
+The default version of this hook always returns @code{NULL}, which is\n\
+appropriate for a target that does not define any new fundamental\n\
+types.",
+ const char *, (const_tree type),
+ hook_constcharptr_const_tree_null)
+
+/* Make any adjustments to libfunc names needed for this target. */
+DEFHOOK
+(init_libfuncs,
+ "This hook should declare additional library routines or rename\n\
+existing ones, using the functions @code{set_optab_libfunc} and\n\
+@code{init_one_libfunc} defined in @file{optabs.cc}.\n\
+@code{init_optabs} calls this macro after initializing all the normal\n\
+library routines.\n\
+\n\
+The default is to do nothing. Most ports don't need to define this hook.",
+ void, (void),
+ hook_void_void)
+
+ /* Add a __gnu_ prefix to library functions rather than just __. */
+DEFHOOKPOD
+(libfunc_gnu_prefix,
+ "If false (the default), internal library routines start with two\n\
+underscores. If set to true, these routines start with @code{__gnu_}\n\
+instead. E.g., @code{__muldi3} changes to @code{__gnu_muldi3}. This\n\
+currently only affects functions defined in @file{libgcc2.c}. If this\n\
+is set to true, the @file{tm.h} file must also\n\
+@code{#define LIBGCC2_GNU_PREFIX}.",
+ bool, false)
+
+/* Given a decl, a section name, and whether the decl initializer
+ has relocs, choose attributes for the section. */
+/* ??? Should be merged with SELECT_SECTION and UNIQUE_SECTION. */
+DEFHOOK
+(section_type_flags,
+ "Choose a set of section attributes for use by @code{TARGET_ASM_NAMED_SECTION}\n\
+based on a variable or function decl, a section name, and whether or not the\n\
+declaration's initializer may contain runtime relocations. @var{decl} may be\n\
+null, in which case read-write data should be assumed.\n\
+\n\
+The default version of this function handles choosing code vs data,\n\
+read-only vs read-write data, and @code{flag_pic}. You should only\n\
+need to override this if your target has special flags that might be\n\
+set via @code{__attribute__}.",
+ unsigned int, (tree decl, const char *name, int reloc),
+ default_section_type_flags)
+
+DEFHOOK
+(libc_has_function,
+ "This hook determines whether a function from a class of functions\n\
+@var{fn_class} is present in the target C library. If @var{type} is NULL,\n\
+the caller asks for support for all standard (float, double, long double)\n\
+types. If @var{type} is non-NULL, the caller asks for support for a\n\
+specific type.",
+ bool, (enum function_class fn_class, tree type),
+ default_libc_has_function)
+
+DEFHOOK
+(libc_has_fast_function,
+ "This hook determines whether a function from a class of functions\n\
+@code{(enum function_class)}@var{fcode} has a fast implementation.",
+ bool, (int fcode),
+ default_libc_has_fast_function)
+
+/* True if new jumps cannot be created, to replace existing ones or
+ not, at the current point in the compilation. */
+DEFHOOK
+(cannot_modify_jumps_p,
+ "This target hook returns @code{true} past the point in which new jump\n\
+instructions could be created. On machines that require a register for\n\
+every jump such as the SHmedia ISA of SH5, this point would typically be\n\
+reload, so this target hook should be defined to a function such as:\n\
+\n\
+@smallexample\n\
+static bool\n\
+cannot_modify_jumps_past_reload_p ()\n\
+@{\n\
+ return (reload_completed || reload_in_progress);\n\
+@}\n\
+@end smallexample",
+ bool, (void),
+ hook_bool_void_false)
+
+/* True if FOLLOWER may be modified to follow FOLLOWEE. */
+DEFHOOK
+(can_follow_jump,
+ "FOLLOWER and FOLLOWEE are JUMP_INSN instructions;\n\
+return true if FOLLOWER may be modified to follow FOLLOWEE;\n\
+false, if it can't.\n\
+For example, on some targets, certain kinds of branches can't be made to\n\
+follow through a hot/cold partitioning.",
+ bool, (const rtx_insn *follower, const rtx_insn *followee),
+ hook_bool_const_rtx_insn_const_rtx_insn_true)
+
+/* Return true if the target supports conditional execution. */
+DEFHOOK
+(have_conditional_execution,
+ "This target hook returns true if the target supports conditional execution.\n\
+This target hook is required only when the target has several different\n\
+modes and they have different conditional execution capability, such as ARM.",
+ bool, (void),
+ default_have_conditional_execution)
+
+DEFHOOK
+(gen_ccmp_first,
+ "This function prepares to emit a comparison insn for the first compare in a\n\
+ sequence of conditional comparisions. It returns an appropriate comparison\n\
+ with @code{CC} for passing to @code{gen_ccmp_next} or @code{cbranch_optab}.\n\
+ The insns to prepare the compare are saved in @var{prep_seq} and the compare\n\
+ insns are saved in @var{gen_seq}. They will be emitted when all the\n\
+ compares in the conditional comparision are generated without error.\n\
+ @var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}.",
+ rtx, (rtx_insn **prep_seq, rtx_insn **gen_seq, int code, tree op0, tree op1),
+ NULL)
+
+DEFHOOK
+(gen_ccmp_next,
+ "This function prepares to emit a conditional comparison within a sequence\n\
+ of conditional comparisons. It returns an appropriate comparison with\n\
+ @code{CC} for passing to @code{gen_ccmp_next} or @code{cbranch_optab}.\n\
+ The insns to prepare the compare are saved in @var{prep_seq} and the compare\n\
+ insns are saved in @var{gen_seq}. They will be emitted when all the\n\
+ compares in the conditional comparision are generated without error. The\n\
+ @var{prev} expression is the result of a prior call to @code{gen_ccmp_first}\n\
+ or @code{gen_ccmp_next}. It may return @code{NULL} if the combination of\n\
+ @var{prev} and this comparison is not supported, otherwise the result must\n\
+ be appropriate for passing to @code{gen_ccmp_next} or @code{cbranch_optab}.\n\
+ @var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}.\n\
+ @var{bit_code} is @code{AND} or @code{IOR}, which is the op on the compares.",
+ rtx, (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev, int cmp_code, tree op0, tree op1, int bit_code),
+ NULL)
+
+DEFHOOK
+(gen_memset_scratch_rtx,
+ "This hook should return an rtx for a scratch register in @var{mode} to\n\
+be used when expanding memset calls. The backend can use a hard scratch\n\
+register to avoid stack realignment when expanding memset. The default\n\
+is @code{gen_reg_rtx}.",
+ rtx, (machine_mode mode),
+ gen_reg_rtx)
+
+/* Return a new value for loop unroll size. */
+DEFHOOK
+(loop_unroll_adjust,
+ "This target hook returns a new value for the number of times @var{loop}\n\
+should be unrolled. The parameter @var{nunroll} is the number of times\n\
+the loop is to be unrolled. The parameter @var{loop} is a pointer to\n\
+the loop, which is going to be checked for unrolling. This target hook\n\
+is required only when the target has special constraints like maximum\n\
+number of memory accesses.",
+ unsigned, (unsigned nunroll, class loop *loop),
+ NULL)
+
+/* True if X is a legitimate MODE-mode immediate operand. */
+DEFHOOK
+(legitimate_constant_p,
+ "This hook returns true if @var{x} is a legitimate constant for a\n\
+@var{mode}-mode immediate operand on the target machine. You can assume that\n\
+@var{x} satisfies @code{CONSTANT_P}, so you need not check this.\n\
+\n\
+The default definition returns true.",
+ bool, (machine_mode mode, rtx x),
+ hook_bool_mode_rtx_true)
+
+/* True if X is a TLS operand whose value should be pre-computed. */
+DEFHOOK
+(precompute_tls_p,
+ "This hook returns true if @var{x} is a TLS operand on the target\n\
+machine that should be pre-computed when used as the argument in a call.\n\
+You can assume that @var{x} satisfies @code{CONSTANT_P}, so you need not \n\
+check this.\n\
+\n\
+The default definition returns false.",
+ bool, (machine_mode mode, rtx x),
+ hook_bool_mode_rtx_false)
+
+/* True if the constant X cannot be placed in the constant pool. */
+DEFHOOK
+(cannot_force_const_mem,
+ "This hook should return true if @var{x} is of a form that cannot (or\n\
+should not) be spilled to the constant pool. @var{mode} is the mode\n\
+of @var{x}.\n\
+\n\
+The default version of this hook returns false.\n\
+\n\
+The primary reason to define this hook is to prevent reload from\n\
+deciding that a non-legitimate constant would be better reloaded\n\
+from the constant pool instead of spilling and reloading a register\n\
+holding the constant. This restriction is often true of addresses\n\
+of TLS symbols for various targets.",
+ bool, (machine_mode mode, rtx x),
+ hook_bool_mode_rtx_false)
+
+DEFHOOK_UNDOC
+(cannot_copy_insn_p,
+ "True if the insn @var{x} cannot be duplicated.",
+ bool, (rtx_insn *), NULL)
+
+/* True if X is considered to be commutative. */
+DEFHOOK
+(commutative_p,
+ "This target hook returns @code{true} if @var{x} is considered to be commutative.\n\
+Usually, this is just COMMUTATIVE_P (@var{x}), but the HP PA doesn't consider\n\
+PLUS to be commutative inside a MEM@. @var{outer_code} is the rtx code\n\
+of the enclosing rtl, if known, otherwise it is UNKNOWN.",
+ bool, (const_rtx x, int outer_code),
+ hook_bool_const_rtx_commutative_p)
+
+/* True if ADDR is an address-expression whose effect depends
+ on the mode of the memory reference it is used in. */
+DEFHOOK
+(mode_dependent_address_p,
+ "This hook returns @code{true} if memory address @var{addr} in address\n\
+space @var{addrspace} can have\n\
+different meanings depending on the machine mode of the memory\n\
+reference it is used for or if the address is valid for some modes\n\
+but not others.\n\
+\n\
+Autoincrement and autodecrement addresses typically have mode-dependent\n\
+effects because the amount of the increment or decrement is the size\n\
+of the operand being addressed. Some machines have other mode-dependent\n\
+addresses. Many RISC machines have no mode-dependent addresses.\n\
+\n\
+You may assume that @var{addr} is a valid address for the machine.\n\
+\n\
+The default version of this hook returns @code{false}.",
+ bool, (const_rtx addr, addr_space_t addrspace),
+ default_mode_dependent_address_p)
+
+/* Given an invalid address X for a given machine mode, try machine-specific
+ ways to make it legitimate. Return X or an invalid address on failure. */
+DEFHOOK
+(legitimize_address,
+ "This hook is given an invalid memory address @var{x} for an\n\
+operand of mode @var{mode} and should try to return a valid memory\n\
+address.\n\
+\n\
+@findex break_out_memory_refs\n\
+@var{x} will always be the result of a call to @code{break_out_memory_refs},\n\
+and @var{oldx} will be the operand that was given to that function to produce\n\
+@var{x}.\n\
+\n\
+The code of the hook should not alter the substructure of\n\
+@var{x}. If it transforms @var{x} into a more legitimate form, it\n\
+should return the new @var{x}.\n\
+\n\
+It is not necessary for this hook to come up with a legitimate address,\n\
+with the exception of native TLS addresses (@pxref{Emulated TLS}).\n\
+The compiler has standard ways of doing so in all cases. In fact, if\n\
+the target supports only emulated TLS, it\n\
+is safe to omit this hook or make it return @var{x} if it cannot find\n\
+a valid way to legitimize the address. But often a machine-dependent\n\
+strategy can generate better code.",
+ rtx, (rtx x, rtx oldx, machine_mode mode),
+ default_legitimize_address)
+
+/* Given an address RTX, undo the effects of LEGITIMIZE_ADDRESS. */
+DEFHOOK
+(delegitimize_address,
+ "This hook is used to undo the possibly obfuscating effects of the\n\
+@code{LEGITIMIZE_ADDRESS} and @code{LEGITIMIZE_RELOAD_ADDRESS} target\n\
+macros. Some backend implementations of these macros wrap symbol\n\
+references inside an @code{UNSPEC} rtx to represent PIC or similar\n\
+addressing modes. This target hook allows GCC's optimizers to understand\n\
+the semantics of these opaque @code{UNSPEC}s by converting them back\n\
+into their original form.",
+ rtx, (rtx x),
+ delegitimize_mem_from_attrs)
+
+/* Given an RTX, return true if it is not ok to emit it into debug info
+ section. */
+DEFHOOK
+(const_not_ok_for_debug_p,
+ "This hook should return true if @var{x} should not be emitted into\n\
+debug sections.",
+ bool, (rtx x),
+ default_const_not_ok_for_debug_p)
+
+/* Given an address RTX, say whether it is valid. */
+DEFHOOK
+(legitimate_address_p,
+ "A function that returns whether @var{x} (an RTX) is a legitimate memory\n\
+address on the target machine for a memory operand of mode @var{mode}.\n\
+\n\
+Legitimate addresses are defined in two variants: a strict variant and a\n\
+non-strict one. The @var{strict} parameter chooses which variant is\n\
+desired by the caller.\n\
+\n\
+The strict variant is used in the reload pass. It must be defined so\n\
+that any pseudo-register that has not been allocated a hard register is\n\
+considered a memory reference. This is because in contexts where some\n\
+kind of register is required, a pseudo-register with no hard register\n\
+must be rejected. For non-hard registers, the strict variant should look\n\
+up the @code{reg_renumber} array; it should then proceed using the hard\n\
+register number in the array, or treat the pseudo as a memory reference\n\
+if the array holds @code{-1}.\n\
+\n\
+The non-strict variant is used in other passes. It must be defined to\n\
+accept all pseudo-registers in every context where some kind of\n\
+register is required.\n\
+\n\
+Normally, constant addresses which are the sum of a @code{symbol_ref}\n\
+and an integer are stored inside a @code{const} RTX to mark them as\n\
+constant. Therefore, there is no need to recognize such sums\n\
+specifically as legitimate addresses. Normally you would simply\n\
+recognize any @code{const} as legitimate.\n\
+\n\
+Usually @code{PRINT_OPERAND_ADDRESS} is not prepared to handle constant\n\
+sums that are not marked with @code{const}. It assumes that a naked\n\
+@code{plus} indicates indexing. If so, then you @emph{must} reject such\n\
+naked constant sums as illegitimate addresses, so that none of them will\n\
+be given to @code{PRINT_OPERAND_ADDRESS}.\n\
+\n\
+@cindex @code{TARGET_ENCODE_SECTION_INFO} and address validation\n\
+On some machines, whether a symbolic address is legitimate depends on\n\
+the section that the address refers to. On these machines, define the\n\
+target hook @code{TARGET_ENCODE_SECTION_INFO} to store the information\n\
+into the @code{symbol_ref}, and then check for it here. When you see a\n\
+@code{const}, you will have to look inside it to find the\n\
+@code{symbol_ref} in order to determine the section. @xref{Assembler\n\
+Format}.\n\
+\n\
+@cindex @code{GO_IF_LEGITIMATE_ADDRESS}\n\
+Some ports are still using a deprecated legacy substitute for\n\
+this hook, the @code{GO_IF_LEGITIMATE_ADDRESS} macro. This macro\n\
+has this syntax:\n\
+\n\
+@example\n\
+#define GO_IF_LEGITIMATE_ADDRESS (@var{mode}, @var{x}, @var{label})\n\
+@end example\n\
+\n\
+@noindent\n\
+and should @code{goto @var{label}} if the address @var{x} is a valid\n\
+address on the target machine for a memory operand of mode @var{mode}.\n\
+\n\
+@findex REG_OK_STRICT\n\
+Compiler source files that want to use the strict variant of this\n\
+macro define the macro @code{REG_OK_STRICT}. You should use an\n\
+@code{#ifdef REG_OK_STRICT} conditional to define the strict variant in\n\
+that case and the non-strict variant otherwise.\n\
+\n\
+Using the hook is usually simpler because it limits the number of\n\
+files that are recompiled when changes are made.",
+ bool, (machine_mode mode, rtx x, bool strict),
+ default_legitimate_address_p)
+
+/* True if the given constant can be put into an object_block. */
+DEFHOOK
+(use_blocks_for_constant_p,
+ "This hook should return true if pool entries for constant @var{x} can\n\
+be placed in an @code{object_block} structure. @var{mode} is the mode\n\
+of @var{x}.\n\
+\n\
+The default version returns false for all constants.",
+ bool, (machine_mode mode, const_rtx x),
+ hook_bool_mode_const_rtx_false)
+
+/* True if the given decl can be put into an object_block. */
+DEFHOOK
+(use_blocks_for_decl_p,
+ "This hook should return true if pool entries for @var{decl} should\n\
+be placed in an @code{object_block} structure.\n\
+\n\
+The default version returns true for all decls.",
+ bool, (const_tree decl),
+ hook_bool_const_tree_true)
+
+/* The minimum and maximum byte offsets for anchored addresses. */
+DEFHOOKPOD
+(min_anchor_offset,
+ "The minimum offset that should be applied to a section anchor.\n\
+On most targets, it should be the smallest offset that can be\n\
+applied to a base register while still giving a legitimate address\n\
+for every mode. The default value is 0.",
+ HOST_WIDE_INT, 0)
+
+DEFHOOKPOD
+(max_anchor_offset,
+ "Like @code{TARGET_MIN_ANCHOR_OFFSET}, but the maximum (inclusive)\n\
+offset that should be applied to section anchors. The default\n\
+value is 0.",
+ HOST_WIDE_INT, 0)
+
+/* True if section anchors can be used to access the given symbol. */
+DEFHOOK
+(use_anchors_for_symbol_p,
+ "Return true if GCC should attempt to use anchors to access @code{SYMBOL_REF}\n\
+@var{x}. You can assume @samp{SYMBOL_REF_HAS_BLOCK_INFO_P (@var{x})} and\n\
+@samp{!SYMBOL_REF_ANCHOR_P (@var{x})}.\n\
+\n\
+The default version is correct for most targets, but you might need to\n\
+intercept this hook to handle things like target-specific attributes\n\
+or target-specific sections.",
+ bool, (const_rtx x),
+ default_use_anchors_for_symbol_p)
+
+/* True if target supports indirect functions. */
+DEFHOOK
+(has_ifunc_p,
+ "It returns true if the target supports GNU indirect functions.\n\
+The support includes the assembler, linker and dynamic linker.\n\
+The default value of this hook is based on target's libc.",
+ bool, (void),
+ default_has_ifunc_p)
+
+/* True if it is OK to reference indirect function resolvers locally. */
+DEFHOOK
+(ifunc_ref_local_ok,
+ "Return true if it is OK to reference indirect function resolvers\n\
+locally. The default is to return false.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* True if it is OK to do sibling call optimization for the specified
+ call expression EXP. DECL will be the called function, or NULL if
+ this is an indirect call. */
+DEFHOOK
+(function_ok_for_sibcall,
+ "True if it is OK to do sibling call optimization for the specified\n\
+call expression @var{exp}. @var{decl} will be the called function,\n\
+or @code{NULL} if this is an indirect call.\n\
+\n\
+It is not uncommon for limitations of calling conventions to prevent\n\
+tail calls to functions outside the current unit of translation, or\n\
+during PIC compilation. The hook is used to enforce these restrictions,\n\
+as the @code{sibcall} md pattern cannot fail, or fall over to a\n\
+``normal'' call. The criteria for successful sibling call optimization\n\
+may vary greatly between different architectures.",
+ bool, (tree decl, tree exp),
+ hook_bool_tree_tree_false)
+
+/* Establish appropriate back-end context for processing the function
+ FNDECL. The argument might be NULL to indicate processing at top
+ level, outside of any function scope. */
+DEFHOOK
+(set_current_function,
+ "The compiler invokes this hook whenever it changes its current function\n\
+context (@code{cfun}). You can define this function if\n\
+the back end needs to perform any initialization or reset actions on a\n\
+per-function basis. For example, it may be used to implement function\n\
+attributes that affect register usage or code generation patterns.\n\
+The argument @var{decl} is the declaration for the new function context,\n\
+and may be null to indicate that the compiler has left a function context\n\
+and is returning to processing at the top level.\n\
+The default hook function does nothing.\n\
+\n\
+GCC sets @code{cfun} to a dummy function context during initialization of\n\
+some parts of the back end. The hook function is not invoked in this\n\
+situation; you need not worry about the hook being invoked recursively,\n\
+or when the back end is in a partially-initialized state.\n\
+@code{cfun} might be @code{NULL} to indicate processing at top level,\n\
+outside of any function scope.",
+ void, (tree decl), hook_void_tree)
+
+/* True if EXP should be placed in a "small data" section. */
+DEFHOOK
+(in_small_data_p,
+ "Returns true if @var{exp} should be placed into a ``small data'' section.\n\
+The default version of this hook always returns false.",
+ bool, (const_tree exp),
+ hook_bool_const_tree_false)
+
+/* True if EXP names an object for which name resolution must resolve
+ to the current executable or shared library. */
+DEFHOOK
+(binds_local_p,
+ "Returns true if @var{exp} names an object for which name resolution\n\
+rules must resolve to the current ``module'' (dynamic shared library\n\
+or executable image).\n\
+\n\
+The default version of this hook implements the name resolution rules\n\
+for ELF, which has a looser model of global name binding than other\n\
+currently supported object file formats.",
+ bool, (const_tree exp),
+ default_binds_local_p)
+
+/* Check if profiling code is before or after prologue. */
+DEFHOOK
+(profile_before_prologue,
+ "It returns true if target wants profile code emitted before prologue.\n\n\
+The default version of this hook use the target macro\n\
+@code{PROFILE_BEFORE_PROLOGUE}.",
+ bool, (void),
+ default_profile_before_prologue)
+
+/* Return true if a leaf function should stay leaf even with profiling
+ enabled. */
+DEFHOOK
+(keep_leaf_when_profiled,
+ "This target hook returns true if the target wants the leaf flag for\n\
+the current function to stay true even if it calls mcount. This might\n\
+make sense for targets using the leaf flag only to determine whether a\n\
+stack frame needs to be generated or not and for which the call to\n\
+mcount is generated before the function prologue.",
+ bool, (void),
+ default_keep_leaf_when_profiled)
+
+/* Modify and return the identifier of a DECL's external name,
+ originally identified by ID, as required by the target,
+ (eg, append @nn to windows32 stdcall function names).
+ The default is to return ID without modification. */
+DEFHOOK
+(mangle_decl_assembler_name,
+ "Define this hook if you need to postprocess the assembler name generated\n\
+by target-independent code. The @var{id} provided to this hook will be\n\
+the computed name (e.g., the macro @code{DECL_NAME} of the @var{decl} in C,\n\
+or the mangled name of the @var{decl} in C++). The return value of the\n\
+hook is an @code{IDENTIFIER_NODE} for the appropriate mangled name on\n\
+your target system. The default implementation of this hook just\n\
+returns the @var{id} provided.",
+ tree, (tree decl, tree id),
+ default_mangle_decl_assembler_name)
+
+/* Do something target-specific to record properties of the DECL into
+ the associated SYMBOL_REF. */
+DEFHOOK
+(encode_section_info,
+ "Define this hook if references to a symbol or a constant must be\n\
+treated differently depending on something about the variable or\n\
+function named by the symbol (such as what section it is in).\n\
+\n\
+The hook is executed immediately after rtl has been created for\n\
+@var{decl}, which may be a variable or function declaration or\n\
+an entry in the constant pool. In either case, @var{rtl} is the\n\
+rtl in question. Do @emph{not} use @code{DECL_RTL (@var{decl})}\n\
+in this hook; that field may not have been initialized yet.\n\
+\n\
+In the case of a constant, it is safe to assume that the rtl is\n\
+a @code{mem} whose address is a @code{symbol_ref}. Most decls\n\
+will also have this form, but that is not guaranteed. Global\n\
+register variables, for instance, will have a @code{reg} for their\n\
+rtl. (Normally the right thing to do with such unusual rtl is\n\
+leave it alone.)\n\
+\n\
+The @var{new_decl_p} argument will be true if this is the first time\n\
+that @code{TARGET_ENCODE_SECTION_INFO} has been invoked on this decl. It will\n\
+be false for subsequent invocations, which will happen for duplicate\n\
+declarations. Whether or not anything must be done for the duplicate\n\
+declaration depends on whether the hook examines @code{DECL_ATTRIBUTES}.\n\
+@var{new_decl_p} is always true when the hook is called for a constant.\n\
+\n\
+@cindex @code{SYMBOL_REF_FLAG}, in @code{TARGET_ENCODE_SECTION_INFO}\n\
+The usual thing for this hook to do is to record flags in the\n\
+@code{symbol_ref}, using @code{SYMBOL_REF_FLAG} or @code{SYMBOL_REF_FLAGS}.\n\
+Historically, the name string was modified if it was necessary to\n\
+encode more than one bit of information, but this practice is now\n\
+discouraged; use @code{SYMBOL_REF_FLAGS}.\n\
+\n\
+The default definition of this hook, @code{default_encode_section_info}\n\
+in @file{varasm.cc}, sets a number of commonly-useful bits in\n\
+@code{SYMBOL_REF_FLAGS}. Check whether the default does what you need\n\
+before overriding it.",
+ void, (tree decl, rtx rtl, int new_decl_p),
+ default_encode_section_info)
+
+/* Undo the effects of encode_section_info on the symbol string. */
+DEFHOOK
+(strip_name_encoding,
+ "Decode @var{name} and return the real name part, sans\n\
+the characters that @code{TARGET_ENCODE_SECTION_INFO}\n\
+may have added.",
+ const char *, (const char *name),
+ default_strip_name_encoding)
+
+/* If shift optabs for MODE are known to always truncate the shift count,
+ return the mask that they apply. Return 0 otherwise. */
+DEFHOOK
+(shift_truncation_mask,
+ "This function describes how the standard shift patterns for @var{mode}\n\
+deal with shifts by negative amounts or by more than the width of the mode.\n\
+@xref{shift patterns}.\n\
+\n\
+On many machines, the shift patterns will apply a mask @var{m} to the\n\
+shift count, meaning that a fixed-width shift of @var{x} by @var{y} is\n\
+equivalent to an arbitrary-width shift of @var{x} by @var{y & m}. If\n\
+this is true for mode @var{mode}, the function should return @var{m},\n\
+otherwise it should return 0. A return value of 0 indicates that no\n\
+particular behavior is guaranteed.\n\
+\n\
+Note that, unlike @code{SHIFT_COUNT_TRUNCATED}, this function does\n\
+@emph{not} apply to general shift rtxes; it applies only to instructions\n\
+that are generated by the named shift patterns.\n\
+\n\
+The default implementation of this function returns\n\
+@code{GET_MODE_BITSIZE (@var{mode}) - 1} if @code{SHIFT_COUNT_TRUNCATED}\n\
+and 0 otherwise. This definition is always safe, but if\n\
+@code{SHIFT_COUNT_TRUNCATED} is false, and some shift patterns\n\
+nevertheless truncate the shift count, you may get better code\n\
+by overriding it.",
+ unsigned HOST_WIDE_INT, (machine_mode mode),
+ default_shift_truncation_mask)
+
+/* Return the number of divisions in the given MODE that should be present,
+ so that it is profitable to turn the division into a multiplication by
+ the reciprocal. */
+DEFHOOK
+(min_divisions_for_recip_mul,
+ "When @option{-ffast-math} is in effect, GCC tries to optimize\n\
+divisions by the same divisor, by turning them into multiplications by\n\
+the reciprocal. This target hook specifies the minimum number of divisions\n\
+that should be there for GCC to perform the optimization for a variable\n\
+of mode @var{mode}. The default implementation returns 3 if the machine\n\
+has an instruction for the division, and 2 if it does not.",
+ unsigned int, (machine_mode mode),
+ default_min_divisions_for_recip_mul)
+
+DEFHOOK
+(truly_noop_truncation,
+ "This hook returns true if it is safe to ``convert'' a value of\n\
+@var{inprec} bits to one of @var{outprec} bits (where @var{outprec} is\n\
+smaller than @var{inprec}) by merely operating on it as if it had only\n\
+@var{outprec} bits. The default returns true unconditionally, which\n\
+is correct for most machines. When @code{TARGET_TRULY_NOOP_TRUNCATION}\n\
+returns false, the machine description should provide a @code{trunc}\n\
+optab to specify the RTL that performs the required truncation.\n\
+\n\
+If @code{TARGET_MODES_TIEABLE_P} returns false for a pair of modes,\n\
+suboptimal code can result if this hook returns true for the corresponding\n\
+mode sizes. Making this hook return false in such cases may improve things.",
+ bool, (poly_uint64 outprec, poly_uint64 inprec),
+ hook_bool_puint64_puint64_true)
+
+/* If the representation of integral MODE is such that values are
+ always sign-extended to a wider mode MODE_REP then return
+ SIGN_EXTEND. Return UNKNOWN otherwise. */
+/* Note that the return type ought to be RTX_CODE, but that's not
+ necessarily defined at this point. */
+DEFHOOK
+(mode_rep_extended,
+ "The representation of an integral mode can be such that the values\n\
+are always extended to a wider integral mode. Return\n\
+@code{SIGN_EXTEND} if values of @var{mode} are represented in\n\
+sign-extended form to @var{rep_mode}. Return @code{UNKNOWN}\n\
+otherwise. (Currently, none of the targets use zero-extended\n\
+representation this way so unlike @code{LOAD_EXTEND_OP},\n\
+@code{TARGET_MODE_REP_EXTENDED} is expected to return either\n\
+@code{SIGN_EXTEND} or @code{UNKNOWN}. Also no target extends\n\
+@var{mode} to @var{rep_mode} so that @var{rep_mode} is not the next\n\
+widest integral mode and currently we take advantage of this fact.)\n\
+\n\
+Similarly to @code{LOAD_EXTEND_OP} you may return a non-@code{UNKNOWN}\n\
+value even if the extension is not performed on certain hard registers\n\
+as long as for the @code{REGNO_REG_CLASS} of these hard registers\n\
+@code{TARGET_CAN_CHANGE_MODE_CLASS} returns false.\n\
+\n\
+Note that @code{TARGET_MODE_REP_EXTENDED} and @code{LOAD_EXTEND_OP}\n\
+describe two related properties. If you define\n\
+@code{TARGET_MODE_REP_EXTENDED (mode, word_mode)} you probably also want\n\
+to define @code{LOAD_EXTEND_OP (mode)} to return the same type of\n\
+extension.\n\
+\n\
+In order to enforce the representation of @code{mode},\n\
+@code{TARGET_TRULY_NOOP_TRUNCATION} should return false when truncating to\n\
+@code{mode}.",
+ int, (scalar_int_mode mode, scalar_int_mode rep_mode),
+ default_mode_rep_extended)
+
+DEFHOOK
+(setjmp_preserves_nonvolatile_regs_p,
+ "On some targets, it is assumed that the compiler will spill all pseudos\n\
+ that are live across a call to @code{setjmp}, while other targets treat\n\
+ @code{setjmp} calls as normal function calls.\n\
+ \n\
+ This hook returns false if @code{setjmp} calls do not preserve all\n\
+ non-volatile registers so that gcc that must spill all pseudos that are\n\
+ live across @code{setjmp} calls. Define this to return true if the\n\
+ target does not need to spill all pseudos live across @code{setjmp} calls.\n\
+ The default implementation conservatively assumes all pseudos must be\n\
+ spilled across @code{setjmp} calls.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* True if MODE is valid for a pointer in __attribute__((mode("MODE"))). */
+DEFHOOK
+(valid_pointer_mode,
+ "Define this to return nonzero if the port can handle pointers\n\
+with machine mode @var{mode}. The default version of this\n\
+hook returns true for both @code{ptr_mode} and @code{Pmode}.",
+ bool, (scalar_int_mode mode),
+ default_valid_pointer_mode)
+
+/* Disambiguate with errno. */
+DEFHOOK
+(ref_may_alias_errno,
+ "Define this to return nonzero if the memory reference @var{ref}\n\
+may alias with the system C library errno location. The default\n\
+version of this hook assumes the system C library errno location\n\
+is either a declaration of type int or accessed by dereferencing\n\
+a pointer to int.",
+ bool, (ao_ref *ref),
+ default_ref_may_alias_errno)
+
+/* Support for named address spaces. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_ADDR_SPACE_"
+HOOK_VECTOR (TARGET_ADDR_SPACE_HOOKS, addr_space)
+
+/* MODE to use for a pointer into another address space. */
+DEFHOOK
+(pointer_mode,
+ "Define this to return the machine mode to use for pointers to\n\
+@var{address_space} if the target supports named address spaces.\n\
+The default version of this hook returns @code{ptr_mode}.",
+ scalar_int_mode, (addr_space_t address_space),
+ default_addr_space_pointer_mode)
+
+/* MODE to use for an address in another address space. */
+DEFHOOK
+(address_mode,
+ "Define this to return the machine mode to use for addresses in\n\
+@var{address_space} if the target supports named address spaces.\n\
+The default version of this hook returns @code{Pmode}.",
+ scalar_int_mode, (addr_space_t address_space),
+ default_addr_space_address_mode)
+
+/* True if MODE is valid for a pointer in __attribute__((mode("MODE")))
+ in another address space. */
+DEFHOOK
+(valid_pointer_mode,
+ "Define this to return nonzero if the port can handle pointers\n\
+with machine mode @var{mode} to address space @var{as}. This target\n\
+hook is the same as the @code{TARGET_VALID_POINTER_MODE} target hook,\n\
+except that it includes explicit named address space support. The default\n\
+version of this hook returns true for the modes returned by either the\n\
+@code{TARGET_ADDR_SPACE_POINTER_MODE} or @code{TARGET_ADDR_SPACE_ADDRESS_MODE}\n\
+target hooks for the given address space.",
+ bool, (scalar_int_mode mode, addr_space_t as),
+ default_addr_space_valid_pointer_mode)
+
+/* True if an address is a valid memory address to a given named address
+ space for a given mode. */
+DEFHOOK
+(legitimate_address_p,
+ "Define this to return true if @var{exp} is a valid address for mode\n\
+@var{mode} in the named address space @var{as}. The @var{strict}\n\
+parameter says whether strict addressing is in effect after reload has\n\
+finished. This target hook is the same as the\n\
+@code{TARGET_LEGITIMATE_ADDRESS_P} target hook, except that it includes\n\
+explicit named address space support.",
+ bool, (machine_mode mode, rtx exp, bool strict, addr_space_t as),
+ default_addr_space_legitimate_address_p)
+
+/* Return an updated address to convert an invalid pointer to a named
+ address space to a valid one. If NULL_RTX is returned use machine
+ independent methods to make the address valid. */
+DEFHOOK
+(legitimize_address,
+ "Define this to modify an invalid address @var{x} to be a valid address\n\
+with mode @var{mode} in the named address space @var{as}. This target\n\
+hook is the same as the @code{TARGET_LEGITIMIZE_ADDRESS} target hook,\n\
+except that it includes explicit named address space support.",
+ rtx, (rtx x, rtx oldx, machine_mode mode, addr_space_t as),
+ default_addr_space_legitimize_address)
+
+/* True if one named address space is a subset of another named address. */
+DEFHOOK
+(subset_p,
+ "Define this to return whether the @var{subset} named address space is\n\
+contained within the @var{superset} named address space. Pointers to\n\
+a named address space that is a subset of another named address space\n\
+will be converted automatically without a cast if used together in\n\
+arithmetic operations. Pointers to a superset address space can be\n\
+converted to pointers to a subset address space via explicit casts.",
+ bool, (addr_space_t subset, addr_space_t superset),
+ default_addr_space_subset_p)
+
+/* True if 0 is a valid address in the address space, or false if
+ 0 is a NULL in the address space. */
+DEFHOOK
+(zero_address_valid,
+ "Define this to modify the default handling of address 0 for the\n\
+address space. Return true if 0 should be considered a valid address.",
+ bool, (addr_space_t as),
+ default_addr_space_zero_address_valid)
+
+/* Function to convert an rtl expression from one address space to another. */
+DEFHOOK
+(convert,
+ "Define this to convert the pointer expression represented by the RTL\n\
+@var{op} with type @var{from_type} that points to a named address\n\
+space to a new pointer expression with type @var{to_type} that points\n\
+to a different named address space. When this hook it called, it is\n\
+guaranteed that one of the two address spaces is a subset of the other,\n\
+as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.",
+ rtx, (rtx op, tree from_type, tree to_type),
+ default_addr_space_convert)
+
+/* Function to encode an address space into dwarf. */
+DEFHOOK
+(debug,
+ "Define this to define how the address space is encoded in dwarf.\n\
+The result is the value to be used with @code{DW_AT_address_class}.",
+ int, (addr_space_t as),
+ default_addr_space_debug)
+
+/* Function to emit custom diagnostic if an address space is used. */
+DEFHOOK
+(diagnose_usage,
+ "Define this hook if the availability of an address space depends on\n\
+command line options and some diagnostics should be printed when the\n\
+address space is used. This hook is called during parsing and allows\n\
+to emit a better diagnostic compared to the case where the address space\n\
+was not registered with @code{c_register_addr_space}. @var{as} is\n\
+the address space as registered with @code{c_register_addr_space}.\n\
+@var{loc} is the location of the address space qualifier token.\n\
+The default implementation does nothing.",
+ void, (addr_space_t as, location_t loc),
+ default_addr_space_diagnose_usage)
+
+HOOK_VECTOR_END (addr_space)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+DEFHOOK
+(lower_local_decl_alignment,
+ "Define this hook to lower alignment of local, parm or result\n\
+decl @samp{(@var{decl})}.",
+ void, (tree decl),
+ hook_void_tree)
+
+DEFHOOK
+(static_rtx_alignment,
+ "This hook returns the preferred alignment in bits for a\n\
+statically-allocated rtx, such as a constant pool entry. @var{mode}\n\
+is the mode of the rtx. The default implementation returns\n\
+@samp{GET_MODE_ALIGNMENT (@var{mode})}.",
+ HOST_WIDE_INT, (machine_mode mode),
+ default_static_rtx_alignment)
+
+DEFHOOK
+(constant_alignment,
+ "This hook returns the alignment in bits of a constant that is being\n\
+placed in memory. @var{constant} is the constant and @var{basic_align}\n\
+is the alignment that the object would ordinarily have.\n\
+\n\
+The default definition just returns @var{basic_align}.\n\
+\n\
+The typical use of this hook is to increase alignment for string\n\
+constants to be word aligned so that @code{strcpy} calls that copy\n\
+constants can be done inline. The function\n\
+@code{constant_alignment_word_strings} provides such a definition.",
+ HOST_WIDE_INT, (const_tree constant, HOST_WIDE_INT basic_align),
+ default_constant_alignment)
+
+DEFHOOK
+(translate_mode_attribute,
+ "Define this hook if during mode attribute processing, the port should\n\
+translate machine_mode @var{mode} to another mode. For example, rs6000's\n\
+@code{KFmode}, when it is the same as @code{TFmode}.\n\
+\n\
+The default version of the hook returns that mode that was passed in.",
+ machine_mode, (machine_mode mode),
+ default_translate_mode_attribute)
+
+/* True if MODE is valid for the target. By "valid", we mean able to
+ be manipulated in non-trivial ways. In particular, this means all
+ the arithmetic is supported. */
+DEFHOOK
+(scalar_mode_supported_p,
+ "Define this to return nonzero if the port is prepared to handle\n\
+insns involving scalar mode @var{mode}. For a scalar mode to be\n\
+considered supported, all the basic arithmetic and comparisons\n\
+must work.\n\
+\n\
+The default version of this hook returns true for any mode\n\
+required to handle the basic C types (as defined by the port).\n\
+Included here are the double-word arithmetic supported by the\n\
+code in @file{optabs.cc}.",
+ bool, (scalar_mode mode),
+ default_scalar_mode_supported_p)
+
+/* Similarly for vector modes. "Supported" here is less strict. At
+ least some operations are supported; need to check optabs or builtins
+ for further details. */
+DEFHOOK
+(vector_mode_supported_p,
+ "Define this to return nonzero if the port is prepared to handle\n\
+insns involving vector mode @var{mode}. At the very least, it\n\
+must have move patterns for this mode.",
+ bool, (machine_mode mode),
+ hook_bool_mode_false)
+
+DEFHOOK
+(compatible_vector_types_p,
+ "Return true if there is no target-specific reason for treating\n\
+vector types @var{type1} and @var{type2} as distinct types. The caller\n\
+has already checked for target-independent reasons, meaning that the\n\
+types are known to have the same mode, to have the same number of elements,\n\
+and to have what the caller considers to be compatible element types.\n\
+\n\
+The main reason for defining this hook is to reject pairs of types\n\
+that are handled differently by the target's calling convention.\n\
+For example, when a new @var{N}-bit vector architecture is added\n\
+to a target, the target may want to handle normal @var{N}-bit\n\
+@code{VECTOR_TYPE} arguments and return values in the same way as\n\
+before, to maintain backwards compatibility. However, it may also\n\
+provide new, architecture-specific @code{VECTOR_TYPE}s that are passed\n\
+and returned in a more efficient way. It is then important to maintain\n\
+a distinction between the ``normal'' @code{VECTOR_TYPE}s and the new\n\
+architecture-specific ones.\n\
+\n\
+The default implementation returns true, which is correct for most targets.",
+ bool, (const_tree type1, const_tree type2),
+ hook_bool_const_tree_const_tree_true)
+
+DEFHOOK
+(vector_alignment,
+ "This hook can be used to define the alignment for a vector of type\n\
+@var{type}, in order to comply with a platform ABI. The default is to\n\
+require natural alignment for vector types. The alignment returned by\n\
+this hook must be a power-of-two multiple of the default alignment of\n\
+the vector element type.",
+ HOST_WIDE_INT, (const_tree type),
+ default_vector_alignment)
+
+DEFHOOK
+(array_mode,
+ "Return the mode that GCC should use for an array that has\n\
+@var{nelems} elements, with each element having mode @var{mode}.\n\
+Return no mode if the target has no special requirements. In the\n\
+latter case, GCC looks for an integer mode of the appropriate size\n\
+if available and uses BLKmode otherwise. Usually the search for the\n\
+integer mode is limited to @code{MAX_FIXED_MODE_SIZE}, but the\n\
+@code{TARGET_ARRAY_MODE_SUPPORTED_P} hook allows a larger mode to be\n\
+used in specific cases.\n\
+\n\
+The main use of this hook is to specify that an array of vectors should\n\
+also have a vector mode. The default implementation returns no mode.",
+ opt_machine_mode, (machine_mode mode, unsigned HOST_WIDE_INT nelems),
+ hook_optmode_mode_uhwi_none)
+
+/* True if we should try to use a scalar mode to represent an array,
+ overriding the usual MAX_FIXED_MODE limit. */
+DEFHOOK
+(array_mode_supported_p,
+ "Return true if GCC should try to use a scalar mode to store an array\n\
+of @var{nelems} elements, given that each element has mode @var{mode}.\n\
+Returning true here overrides the usual @code{MAX_FIXED_MODE} limit\n\
+and allows GCC to use any defined integer mode.\n\
+\n\
+One use of this hook is to support vector load and store operations\n\
+that operate on several homogeneous vectors. For example, ARM NEON\n\
+has operations like:\n\
+\n\
+@smallexample\n\
+int8x8x3_t vld3_s8 (const int8_t *)\n\
+@end smallexample\n\
+\n\
+where the return type is defined as:\n\
+\n\
+@smallexample\n\
+typedef struct int8x8x3_t\n\
+@{\n\
+ int8x8_t val[3];\n\
+@} int8x8x3_t;\n\
+@end smallexample\n\
+\n\
+If this hook allows @code{val} to have a scalar mode, then\n\
+@code{int8x8x3_t} can have the same mode. GCC can then store\n\
+@code{int8x8x3_t}s in registers rather than forcing them onto the stack.",
+ bool, (machine_mode mode, unsigned HOST_WIDE_INT nelems),
+ hook_bool_mode_uhwi_false)
+
+DEFHOOK
+(libgcc_floating_mode_supported_p,
+ "Define this to return nonzero if libgcc provides support for the \n\
+floating-point mode @var{mode}, which is known to pass \n\
+@code{TARGET_SCALAR_MODE_SUPPORTED_P}. The default version of this \n\
+hook returns true for all of @code{SFmode}, @code{DFmode}, \n\
+@code{XFmode} and @code{TFmode}, if such modes exist.",
+ bool, (scalar_float_mode mode),
+ default_libgcc_floating_mode_supported_p)
+
+DEFHOOK
+(floatn_mode,
+ "Define this to return the machine mode to use for the type \n\
+@code{_Float@var{n}}, if @var{extended} is false, or the type \n\
+@code{_Float@var{n}x}, if @var{extended} is true. If such a type is not\n\
+supported, return @code{opt_scalar_float_mode ()}. The default version of\n\
+this hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for\n\
+@code{_Float64} and @code{_Float32x} and @code{TFmode} for \n\
+@code{_Float128}, if those modes exist and satisfy the requirements for \n\
+those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and \n\
+@code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it \n\
+returns the first of @code{XFmode} and @code{TFmode} that exists and \n\
+satisfies the same requirements; for other types, it returns \n\
+@code{opt_scalar_float_mode ()}. The hook is only called for values\n\
+of @var{n} and @var{extended} that are valid according to\n\
+ISO/IEC TS 18661-3:2015; that is, @var{n} is one of 32, 64, 128, or,\n\
+if @var{extended} is false, 16 or greater than 128 and a multiple of 32.",
+ opt_scalar_float_mode, (int n, bool extended),
+ default_floatn_mode)
+
+DEFHOOK
+(floatn_builtin_p,
+ "Define this to return true if the @code{_Float@var{n}} and\n\
+@code{_Float@var{n}x} built-in functions should implicitly enable the\n\
+built-in function without the @code{__builtin_} prefix in addition to the\n\
+normal built-in function with the @code{__builtin_} prefix. The default is\n\
+to only enable built-in functions without the @code{__builtin_} prefix for\n\
+the GNU C langauge. In strict ANSI/ISO mode, the built-in function without\n\
+the @code{__builtin_} prefix is not enabled. The argument @code{FUNC} is the\n\
+@code{enum built_in_function} id of the function to be enabled.",
+ bool, (int func),
+ default_floatn_builtin_p)
+
+/* Compute cost of moving data from a register of class FROM to one of
+ TO, using MODE. */
+DEFHOOK
+(register_move_cost,
+ "This target hook should return the cost of moving data of mode @var{mode}\n\
+from a register in class @var{from} to one in class @var{to}. The classes\n\
+are expressed using the enumeration values such as @code{GENERAL_REGS}.\n\
+A value of 2 is the default; other values are interpreted relative to\n\
+that.\n\
+\n\
+It is not required that the cost always equal 2 when @var{from} is the\n\
+same as @var{to}; on some machines it is expensive to move between\n\
+registers if they are not general registers.\n\
+\n\
+If reload sees an insn consisting of a single @code{set} between two\n\
+hard registers, and if @code{TARGET_REGISTER_MOVE_COST} applied to their\n\
+classes returns a value of 2, reload does not check to ensure that the\n\
+constraints of the insn are met. Setting a cost of other than 2 will\n\
+allow reload to verify that the constraints are met. You should do this\n\
+if the @samp{mov@var{m}} pattern's constraints do not allow such copying.\n\
+\n\
+The default version of this function returns 2.",
+ int, (machine_mode mode, reg_class_t from, reg_class_t to),
+ default_register_move_cost)
+
+/* Compute cost of moving registers to/from memory. */
+/* ??? Documenting the argument types for this hook requires a GFDL
+ license grant. Also, the documentation uses a different name for RCLASS. */
+DEFHOOK
+(memory_move_cost,
+ "This target hook should return the cost of moving data of mode @var{mode}\n\
+between a register of class @var{rclass} and memory; @var{in} is @code{false}\n\
+if the value is to be written to memory, @code{true} if it is to be read in.\n\
+This cost is relative to those in @code{TARGET_REGISTER_MOVE_COST}.\n\
+If moving between registers and memory is more expensive than between two\n\
+registers, you should add this target hook to express the relative cost.\n\
+\n\
+If you do not add this target hook, GCC uses a default cost of 4 plus\n\
+the cost of copying via a secondary reload register, if one is\n\
+needed. If your machine requires a secondary reload register to copy\n\
+between memory and a register of @var{rclass} but the reload mechanism is\n\
+more complex than copying via an intermediate, use this target hook to\n\
+reflect the actual cost of the move.\n\
+\n\
+GCC defines the function @code{memory_move_secondary_cost} if\n\
+secondary reloads are needed. It computes the costs due to copying via\n\
+a secondary register. If your machine copies from memory using a\n\
+secondary register in the conventional way but the default base value of\n\
+4 is not correct for your machine, use this target hook to add some other\n\
+value to the result of that function. The arguments to that function\n\
+are the same as to this target hook.",
+ int, (machine_mode mode, reg_class_t rclass, bool in),
+ default_memory_move_cost)
+
+DEFHOOK
+(use_by_pieces_infrastructure_p,
+ "GCC will attempt several strategies when asked to copy between\n\
+two areas of memory, or to set, clear or store to memory, for example\n\
+when copying a @code{struct}. The @code{by_pieces} infrastructure\n\
+implements such memory operations as a sequence of load, store or move\n\
+insns. Alternate strategies are to expand the\n\
+@code{cpymem} or @code{setmem} optabs, to emit a library call, or to emit\n\
+unit-by-unit, loop-based operations.\n\
+\n\
+This target hook should return true if, for a memory operation with a\n\
+given @var{size} and @var{alignment}, using the @code{by_pieces}\n\
+infrastructure is expected to result in better code generation.\n\
+Both @var{size} and @var{alignment} are measured in terms of storage\n\
+units.\n\
+\n\
+The parameter @var{op} is one of: @code{CLEAR_BY_PIECES},\n\
+@code{MOVE_BY_PIECES}, @code{SET_BY_PIECES}, @code{STORE_BY_PIECES} or\n\
+@code{COMPARE_BY_PIECES}. These describe the type of memory operation\n\
+under consideration.\n\
+\n\
+The parameter @var{speed_p} is true if the code is currently being\n\
+optimized for speed rather than size.\n\
+\n\
+Returning true for higher values of @var{size} can improve code generation\n\
+for speed if the target does not provide an implementation of the\n\
+@code{cpymem} or @code{setmem} standard names, if the @code{cpymem} or\n\
+@code{setmem} implementation would be more expensive than a sequence of\n\
+insns, or if the overhead of a library call would dominate that of\n\
+the body of the memory operation.\n\
+\n\
+Returning true for higher values of @code{size} may also cause an increase\n\
+in code size, for example where the number of insns emitted to perform a\n\
+move would be greater than that of a library call.",
+ bool, (unsigned HOST_WIDE_INT size, unsigned int alignment,
+ enum by_pieces_operation op, bool speed_p),
+ default_use_by_pieces_infrastructure_p)
+
+DEFHOOK
+(overlap_op_by_pieces_p,
+ "This target hook should return true if when the @code{by_pieces}\n\
+infrastructure is used, an offset adjusted unaligned memory operation\n\
+in the smallest integer mode for the last piece operation of a memory\n\
+region can be generated to avoid doing more than one smaller operations.",
+ bool, (void),
+ hook_bool_void_false)
+
+DEFHOOK
+(compare_by_pieces_branch_ratio,
+ "When expanding a block comparison in MODE, gcc can try to reduce the\n\
+number of branches at the expense of more memory operations. This hook\n\
+allows the target to override the default choice. It should return the\n\
+factor by which branches should be reduced over the plain expansion with\n\
+one comparison per @var{mode}-sized piece. A port can also prevent a\n\
+particular mode from being used for block comparisons by returning a\n\
+negative number from this hook.",
+ int, (machine_mode mode),
+ default_compare_by_pieces_branch_ratio)
+
+DEFHOOK
+(slow_unaligned_access,
+ "This hook returns true if memory accesses described by the\n\
+@var{mode} and @var{alignment} parameters have a cost many times greater\n\
+than aligned accesses, for example if they are emulated in a trap handler.\n\
+This hook is invoked only for unaligned accesses, i.e.@: when\n\
+@code{@var{alignment} < GET_MODE_ALIGNMENT (@var{mode})}.\n\
+\n\
+When this hook returns true, the compiler will act as if\n\
+@code{STRICT_ALIGNMENT} were true when generating code for block\n\
+moves. This can cause significantly more instructions to be produced.\n\
+Therefore, do not make this hook return true if unaligned accesses only\n\
+add a cycle or two to the time for a memory access.\n\
+\n\
+The hook must return true whenever @code{STRICT_ALIGNMENT} is true.\n\
+The default implementation returns @code{STRICT_ALIGNMENT}.",
+ bool, (machine_mode mode, unsigned int align),
+ default_slow_unaligned_access)
+
+DEFHOOK
+(optab_supported_p,
+ "Return true if the optimizers should use optab @var{op} with\n\
+modes @var{mode1} and @var{mode2} for optimization type @var{opt_type}.\n\
+The optab is known to have an associated @file{.md} instruction\n\
+whose C condition is true. @var{mode2} is only meaningful for conversion\n\
+optabs; for direct optabs it is a copy of @var{mode1}.\n\
+\n\
+For example, when called with @var{op} equal to @code{rint_optab} and\n\
+@var{mode1} equal to @code{DFmode}, the hook should say whether the\n\
+optimizers should use optab @code{rintdf2}.\n\
+\n\
+The default hook returns true for all inputs.",
+ bool, (int op, machine_mode mode1, machine_mode mode2,
+ optimization_type opt_type),
+ default_optab_supported_p)
+
+/* True for MODE if the target expects that registers in this mode will
+ be allocated to registers in a small register class. The compiler is
+ allowed to use registers explicitly used in the rtl as spill registers
+ but it should prevent extending the lifetime of these registers. */
+DEFHOOK
+(small_register_classes_for_mode_p,
+ "Define this to return nonzero for machine modes for which the port has\n\
+small register classes. If this target hook returns nonzero for a given\n\
+@var{mode}, the compiler will try to minimize the lifetime of registers\n\
+in @var{mode}. The hook may be called with @code{VOIDmode} as argument.\n\
+In this case, the hook is expected to return nonzero if it returns nonzero\n\
+for any mode.\n\
+\n\
+On some machines, it is risky to let hard registers live across arbitrary\n\
+insns. Typically, these machines have instructions that require values\n\
+to be in specific registers (like an accumulator), and reload will fail\n\
+if the required hard register is used for another purpose across such an\n\
+insn.\n\
+\n\
+Passes before reload do not know which hard registers will be used\n\
+in an instruction, but the machine modes of the registers set or used in\n\
+the instruction are already known. And for some machines, register\n\
+classes are small for, say, integer registers but not for floating point\n\
+registers. For example, the AMD x86-64 architecture requires specific\n\
+registers for the legacy x86 integer instructions, but there are many\n\
+SSE registers for floating point operations. On such targets, a good\n\
+strategy may be to return nonzero from this hook for @code{INTEGRAL_MODE_P}\n\
+machine modes but zero for the SSE register classes.\n\
+\n\
+The default version of this hook returns false for any mode. It is always\n\
+safe to redefine this hook to return with a nonzero value. But if you\n\
+unnecessarily define it, you will reduce the amount of optimizations\n\
+that can be performed in some cases. If you do not define this hook\n\
+to return a nonzero value when it is required, the compiler will run out\n\
+of spill registers and print a fatal error message.",
+ bool, (machine_mode mode),
+ hook_bool_mode_false)
+
+/* Register number for a flags register. Only needs to be defined if the
+ target is constrainted to use post-reload comparison elimination. */
+DEFHOOKPOD
+(flags_regnum,
+ "If the target has a dedicated flags register, and it needs to use the\n\
+post-reload comparison elimination pass, or the delay slot filler pass,\n\
+then this value should be set appropriately.",
+unsigned int, INVALID_REGNUM)
+
+/* Compute a (partial) cost for rtx X. Return true if the complete
+ cost has been computed, and false if subexpressions should be
+ scanned. In either case, *TOTAL contains the cost result. */
+/* Note that OUTER_CODE ought to be RTX_CODE, but that's
+ not necessarily defined at this point. */
+DEFHOOK
+(rtx_costs,
+ "This target hook describes the relative costs of RTL expressions.\n\
+\n\
+The cost may depend on the precise form of the expression, which is\n\
+available for examination in @var{x}, and the fact that @var{x} appears\n\
+as operand @var{opno} of an expression with rtx code @var{outer_code}.\n\
+That is, the hook can assume that there is some rtx @var{y} such\n\
+that @samp{GET_CODE (@var{y}) == @var{outer_code}} and such that\n\
+either (a) @samp{XEXP (@var{y}, @var{opno}) == @var{x}} or\n\
+(b) @samp{XVEC (@var{y}, @var{opno})} contains @var{x}.\n\
+\n\
+@var{mode} is @var{x}'s machine mode, or for cases like @code{const_int} that\n\
+do not have a mode, the mode in which @var{x} is used.\n\
+\n\
+In implementing this hook, you can use the construct\n\
+@code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast\n\
+instructions.\n\
+\n\
+On entry to the hook, @code{*@var{total}} contains a default estimate\n\
+for the cost of the expression. The hook should modify this value as\n\
+necessary. Traditionally, the default costs are @code{COSTS_N_INSNS (5)}\n\
+for multiplications, @code{COSTS_N_INSNS (7)} for division and modulus\n\
+operations, and @code{COSTS_N_INSNS (1)} for all other operations.\n\
+\n\
+When optimizing for code size, i.e.@: when @code{speed} is\n\
+false, this target hook should be used to estimate the relative\n\
+size cost of an expression, again relative to @code{COSTS_N_INSNS}.\n\
+\n\
+The hook returns true when all subexpressions of @var{x} have been\n\
+processed, and false when @code{rtx_cost} should recurse.",
+ bool, (rtx x, machine_mode mode, int outer_code, int opno, int *total, bool speed),
+ hook_bool_rtx_mode_int_int_intp_bool_false)
+
+/* Compute the cost of X, used as an address. Never called with
+ invalid addresses. */
+DEFHOOK
+(address_cost,
+ "This hook computes the cost of an addressing mode that contains\n\
+@var{address}. If not defined, the cost is computed from\n\
+the @var{address} expression and the @code{TARGET_RTX_COST} hook.\n\
+\n\
+For most CISC machines, the default cost is a good approximation of the\n\
+true cost of the addressing mode. However, on RISC machines, all\n\
+instructions normally have the same length and execution time. Hence\n\
+all addresses will have equal costs.\n\
+\n\
+In cases where more than one form of an address is known, the form with\n\
+the lowest cost will be used. If multiple forms have the same, lowest,\n\
+cost, the one that is the most complex will be used.\n\
+\n\
+For example, suppose an address that is equal to the sum of a register\n\
+and a constant is used twice in the same basic block. When this macro\n\
+is not defined, the address will be computed in a register and memory\n\
+references will be indirect through that register. On machines where\n\
+the cost of the addressing mode containing the sum is no higher than\n\
+that of a simple indirect reference, this will produce an additional\n\
+instruction and possibly require an additional register. Proper\n\
+specification of this macro eliminates this overhead for such machines.\n\
+\n\
+This hook is never called with an invalid address.\n\
+\n\
+On machines where an address involving more than one register is as\n\
+cheap as an address computation involving only one register, defining\n\
+@code{TARGET_ADDRESS_COST} to reflect this can cause two registers to\n\
+be live over a region of code where only one would have been if\n\
+@code{TARGET_ADDRESS_COST} were not defined in that manner. This effect\n\
+should be considered in the definition of this macro. Equivalent costs\n\
+should probably only be given to addresses with different numbers of\n\
+registers on machines with lots of registers.",
+ int, (rtx address, machine_mode mode, addr_space_t as, bool speed),
+ default_address_cost)
+
+/* Compute a cost for INSN. */
+DEFHOOK
+(insn_cost,
+ "This target hook describes the relative costs of RTL instructions.\n\
+\n\
+In implementing this hook, you can use the construct\n\
+@code{COSTS_N_INSNS (@var{n})} to specify a cost equal to @var{n} fast\n\
+instructions.\n\
+\n\
+When optimizing for code size, i.e.@: when @code{speed} is\n\
+false, this target hook should be used to estimate the relative\n\
+size cost of an expression, again relative to @code{COSTS_N_INSNS}.",
+ int, (rtx_insn *insn, bool speed), NULL)
+
+/* Give a cost, in RTX Costs units, for an edge. Like BRANCH_COST, but with
+ well defined units. */
+DEFHOOK
+(max_noce_ifcvt_seq_cost,
+ "This hook returns a value in the same units as @code{TARGET_RTX_COSTS},\n\
+giving the maximum acceptable cost for a sequence generated by the RTL\n\
+if-conversion pass when conditional execution is not available.\n\
+The RTL if-conversion pass attempts to convert conditional operations\n\
+that would require a branch to a series of unconditional operations and\n\
+@code{mov@var{mode}cc} insns. This hook returns the maximum cost of the\n\
+unconditional instructions and the @code{mov@var{mode}cc} insns.\n\
+RTL if-conversion is cancelled if the cost of the converted sequence\n\
+is greater than the value returned by this hook.\n\
+\n\
+@code{e} is the edge between the basic block containing the conditional\n\
+branch to the basic block which would be executed if the condition\n\
+were true.\n\
+\n\
+The default implementation of this hook uses the\n\
+@code{max-rtl-if-conversion-[un]predictable} parameters if they are set,\n\
+and uses a multiple of @code{BRANCH_COST} otherwise.",
+unsigned int, (edge e),
+default_max_noce_ifcvt_seq_cost)
+
+/* Return true if the given instruction sequence is a good candidate
+ as a replacement for the if-convertible sequence. */
+DEFHOOK
+(noce_conversion_profitable_p,
+ "This hook returns true if the instruction sequence @code{seq} is a good\n\
+candidate as a replacement for the if-convertible sequence described in\n\
+@code{if_info}.",
+bool, (rtx_insn *seq, struct noce_if_info *if_info),
+default_noce_conversion_profitable_p)
+
+/* Return true if new_addr should be preferred over the existing address used by
+ memref in insn. */
+DEFHOOK
+(new_address_profitable_p,
+ "Return @code{true} if it is profitable to replace the address in\n\
+@var{memref} with @var{new_addr}. This allows targets to prevent the\n\
+scheduler from undoing address optimizations. The instruction containing the\n\
+memref is @var{insn}. The default implementation returns @code{true}.",
+bool, (rtx memref, rtx_insn * insn, rtx new_addr),
+default_new_address_profitable_p)
+
+DEFHOOK
+(estimated_poly_value,
+ "Return an estimate of the runtime value of @var{val}, for use in\n\
+things like cost calculations or profiling frequencies. @var{kind} is used\n\
+to ask for the minimum, maximum, and likely estimates of the value through\n\
+the @code{POLY_VALUE_MIN}, @code{POLY_VALUE_MAX} and\n\
+@code{POLY_VALUE_LIKELY} values. The default\n\
+implementation returns the lowest possible value of @var{val}.",
+ HOST_WIDE_INT, (poly_int64 val, poly_value_estimate_kind kind),
+ default_estimated_poly_value)
+
+/* Permit speculative instructions in delay slots during delayed-branch
+ scheduling. */
+DEFHOOK
+(no_speculation_in_delay_slots_p,
+ "This predicate controls the use of the eager delay slot filler to disallow\n\
+speculatively executed instructions being placed in delay slots. Targets\n\
+such as certain MIPS architectures possess both branches with and without\n\
+delay slots. As the eager delay slot filler can decrease performance,\n\
+disabling it is beneficial when ordinary branches are available. Use of\n\
+delay slot branches filled using the basic filler is often still desirable\n\
+as the delay slot can hide a pipeline bubble.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Return where to allocate pseudo for a given hard register initial value. */
+DEFHOOK
+(allocate_initial_value,
+ "\n\
+When the initial value of a hard register has been copied in a pseudo\n\
+register, it is often not necessary to actually allocate another register\n\
+to this pseudo register, because the original hard register or a stack slot\n\
+it has been saved into can be used. @code{TARGET_ALLOCATE_INITIAL_VALUE}\n\
+is called at the start of register allocation once for each hard register\n\
+that had its initial value copied by using\n\
+@code{get_func_hard_reg_initial_val} or @code{get_hard_reg_initial_val}.\n\
+Possible values are @code{NULL_RTX}, if you don't want\n\
+to do any special allocation, a @code{REG} rtx---that would typically be\n\
+the hard register itself, if it is known not to be clobbered---or a\n\
+@code{MEM}.\n\
+If you are returning a @code{MEM}, this is only a hint for the allocator;\n\
+it might decide to use another register anyways.\n\
+You may use @code{current_function_is_leaf} or \n\
+@code{REG_N_SETS} in the hook to determine if the hard\n\
+register in question will not be clobbered.\n\
+The default value of this hook is @code{NULL}, which disables any special\n\
+allocation.",
+ rtx, (rtx hard_reg), NULL)
+
+/* Return nonzero if evaluating UNSPEC X might cause a trap.
+ FLAGS has the same meaning as in rtlanal.cc: may_trap_p_1. */
+DEFHOOK
+(unspec_may_trap_p,
+ "This target hook returns nonzero if @var{x}, an @code{unspec} or\n\
+@code{unspec_volatile} operation, might cause a trap. Targets can use\n\
+this hook to enhance precision of analysis for @code{unspec} and\n\
+@code{unspec_volatile} operations. You may call @code{may_trap_p_1}\n\
+to analyze inner elements of @var{x} in which case @var{flags} should be\n\
+passed along.",
+ int, (const_rtx x, unsigned flags),
+ default_unspec_may_trap_p)
+
+/* Given a register, this hook should return a parallel of registers
+ to represent where to find the register pieces. Define this hook
+ if the register and its mode are represented in Dwarf in
+ non-contiguous locations, or if the register should be
+ represented in more than one register in Dwarf. Otherwise, this
+ hook should return NULL_RTX. */
+DEFHOOK
+(dwarf_register_span,
+ "Given a register, this hook should return a parallel of registers to\n\
+represent where to find the register pieces. Define this hook if the\n\
+register and its mode are represented in Dwarf in non-contiguous\n\
+locations, or if the register should be represented in more than one\n\
+register in Dwarf. Otherwise, this hook should return @code{NULL_RTX}.\n\
+If not defined, the default is to return @code{NULL_RTX}.",
+ rtx, (rtx reg),
+ hook_rtx_rtx_null)
+
+/* Given a register return the mode of the corresponding DWARF frame
+ register. */
+DEFHOOK
+(dwarf_frame_reg_mode,
+ "Given a register, this hook should return the mode which the\n\
+corresponding Dwarf frame register should have. This is normally\n\
+used to return a smaller mode than the raw mode to prevent call\n\
+clobbered parts of a register altering the frame register size",
+ machine_mode, (int regno),
+ default_dwarf_frame_reg_mode)
+
+/* If expand_builtin_init_dwarf_reg_sizes needs to fill in table
+ entries not corresponding directly to registers below
+ FIRST_PSEUDO_REGISTER, this hook should generate the necessary
+ code, given the address of the table. */
+DEFHOOK
+(init_dwarf_reg_sizes_extra,
+ "If some registers are represented in Dwarf-2 unwind information in\n\
+multiple pieces, define this hook to fill in information about the\n\
+sizes of those pieces in the table used by the unwinder at runtime.\n\
+It will be called by @code{expand_builtin_init_dwarf_reg_sizes} after\n\
+filling in a single size corresponding to each hard register;\n\
+@var{address} is the address of the table.",
+ void, (tree address),
+ hook_void_tree)
+
+/* Fetch the fixed register(s) which hold condition codes, for
+ targets where it makes sense to look for duplicate assignments to
+ the condition codes. This should return true if there is such a
+ register, false otherwise. The arguments should be set to the
+ fixed register numbers. Up to two condition code registers are
+ supported. If there is only one for this target, the int pointed
+ at by the second argument should be set to -1. */
+DEFHOOK
+(fixed_condition_code_regs,
+ "On targets which use a hard\n\
+register rather than a pseudo-register to hold condition codes, the\n\
+regular CSE passes are often not able to identify cases in which the\n\
+hard register is set to a common value. Use this hook to enable a\n\
+small pass which optimizes such cases. This hook should return true\n\
+to enable this pass, and it should set the integers to which its\n\
+arguments point to the hard register numbers used for condition codes.\n\
+When there is only one such register, as is true on most systems, the\n\
+integer pointed to by @var{p2} should be set to\n\
+@code{INVALID_REGNUM}.\n\
+\n\
+The default version of this hook returns false.",
+ bool, (unsigned int *p1, unsigned int *p2),
+ hook_bool_uintp_uintp_false)
+
+/* If two condition code modes are compatible, return a condition
+ code mode which is compatible with both, such that a comparison
+ done in the returned mode will work for both of the original
+ modes. If the condition code modes are not compatible, return
+ VOIDmode. */
+DEFHOOK
+(cc_modes_compatible,
+ "On targets which use multiple condition code modes in class\n\
+@code{MODE_CC}, it is sometimes the case that a comparison can be\n\
+validly done in more than one mode. On such a system, define this\n\
+target hook to take two mode arguments and to return a mode in which\n\
+both comparisons may be validly done. If there is no such mode,\n\
+return @code{VOIDmode}.\n\
+\n\
+The default version of this hook checks whether the modes are the\n\
+same. If they are, it returns that mode. If they are different, it\n\
+returns @code{VOIDmode}.",
+ machine_mode, (machine_mode m1, machine_mode m2),
+ default_cc_modes_compatible)
+
+/* Do machine-dependent code transformations. Called just before
+ delayed-branch scheduling. */
+DEFHOOK
+(machine_dependent_reorg,
+ "If non-null, this hook performs a target-specific pass over the\n\
+instruction stream. The compiler will run it at all optimization levels,\n\
+just before the point at which it normally does delayed-branch scheduling.\n\
+\n\
+The exact purpose of the hook varies from target to target. Some use\n\
+it to do transformations that are necessary for correctness, such as\n\
+laying out in-function constant pools or avoiding hardware hazards.\n\
+Others use it as an opportunity to do some machine-dependent optimizations.\n\
+\n\
+You need not implement the hook if it has nothing to do. The default\n\
+definition is null.",
+ void, (void), NULL)
+
+/* Create the __builtin_va_list type. */
+DEFHOOK
+(build_builtin_va_list,
+ "This hook returns a type node for @code{va_list} for the target.\n\
+The default version of the hook returns @code{void*}.",
+ tree, (void),
+ std_build_builtin_va_list)
+
+/* Enumerate the va list variants. */
+DEFHOOK
+(enum_va_list_p,
+ "This target hook is used in function @code{c_common_nodes_and_builtins}\n\
+to iterate through the target specific builtin types for va_list. The\n\
+variable @var{idx} is used as iterator. @var{pname} has to be a pointer\n\
+to a @code{const char *} and @var{ptree} a pointer to a @code{tree} typed\n\
+variable.\n\
+The arguments @var{pname} and @var{ptree} are used to store the result of\n\
+this macro and are set to the name of the va_list builtin type and its\n\
+internal type.\n\
+If the return value of this macro is zero, then there is no more element.\n\
+Otherwise the @var{IDX} should be increased for the next call of this\n\
+macro to iterate through all types.",
+ int, (int idx, const char **pname, tree *ptree),
+ NULL)
+
+/* Get the cfun/fndecl calling abi __builtin_va_list type. */
+DEFHOOK
+(fn_abi_va_list,
+ "This hook returns the va_list type of the calling convention specified by\n\
+@var{fndecl}.\n\
+The default version of this hook returns @code{va_list_type_node}.",
+ tree, (tree fndecl),
+ std_fn_abi_va_list)
+
+/* Get the __builtin_va_list type dependent on input type. */
+DEFHOOK
+(canonical_va_list_type,
+ "This hook returns the va_list type of the calling convention specified by the\n\
+type of @var{type}. If @var{type} is not a valid va_list type, it returns\n\
+@code{NULL_TREE}.",
+ tree, (tree type),
+ std_canonical_va_list_type)
+
+/* ??? Documenting this hook requires a GFDL license grant. */
+DEFHOOK_UNDOC
+(expand_builtin_va_start,
+"Expand the @code{__builtin_va_start} builtin.",
+ void, (tree valist, rtx nextarg), NULL)
+
+/* Gimplifies a VA_ARG_EXPR. */
+DEFHOOK
+(gimplify_va_arg_expr,
+ "This hook performs target-specific gimplification of\n\
+@code{VA_ARG_EXPR}. The first two parameters correspond to the\n\
+arguments to @code{va_arg}; the latter two are as in\n\
+@code{gimplify.cc:gimplify_expr}.",
+ tree, (tree valist, tree type, gimple_seq *pre_p, gimple_seq *post_p),
+ std_gimplify_va_arg_expr)
+
+/* Validity-checking routines for PCH files, target-specific.
+ get_pch_validity returns a pointer to the data to be stored,
+ and stores the size in its argument. pch_valid_p gets the same
+ information back and returns NULL if the PCH is valid,
+ or an error message if not. */
+DEFHOOK
+(get_pch_validity,
+ "This hook returns a pointer to the data needed by\n\
+@code{TARGET_PCH_VALID_P} and sets\n\
+@samp{*@var{sz}} to the size of the data in bytes.",
+ void *, (size_t *sz),
+ default_get_pch_validity)
+
+DEFHOOK
+(pch_valid_p,
+ "This hook checks whether the options used to create a PCH file are\n\
+compatible with the current settings. It returns @code{NULL}\n\
+if so and a suitable error message if not. Error messages will\n\
+be presented to the user and must be localized using @samp{_(@var{msg})}.\n\
+\n\
+@var{data} is the data that was returned by @code{TARGET_GET_PCH_VALIDITY}\n\
+when the PCH file was created and @var{sz} is the size of that data in bytes.\n\
+It's safe to assume that the data was created by the same version of the\n\
+compiler, so no format checking is needed.\n\
+\n\
+The default definition of @code{default_pch_valid_p} should be\n\
+suitable for most targets.",
+ const char *, (const void *data, size_t sz),
+ default_pch_valid_p)
+
+DEFHOOK
+(prepare_pch_save,
+ "Called before writing out a PCH file. If the target has some\n\
+garbage-collected data that needs to be in a particular state on PCH loads,\n\
+it can use this hook to enforce that state. Very few targets need\n\
+to do anything here.",
+ void, (void),
+ hook_void_void)
+
+/* If nonnull, this function checks whether a PCH file with the
+ given set of target flags can be used. It returns NULL if so,
+ otherwise it returns an error message. */
+DEFHOOK
+(check_pch_target_flags,
+ "If this hook is nonnull, the default implementation of\n\
+@code{TARGET_PCH_VALID_P} will use it to check for compatible values\n\
+of @code{target_flags}. @var{pch_flags} specifies the value that\n\
+@code{target_flags} had when the PCH file was created. The return\n\
+value is the same as for @code{TARGET_PCH_VALID_P}.",
+ const char *, (int pch_flags), NULL)
+
+/* True if the compiler should give an enum type only as many
+ bytes as it takes to represent the range of possible values of
+ that type. */
+DEFHOOK
+(default_short_enums,
+ "This target hook should return true if the compiler should give an\n\
+@code{enum} type only as many bytes as it takes to represent the range\n\
+of possible values of that type. It should return false if all\n\
+@code{enum} types should be allocated like @code{int}.\n\
+\n\
+The default is to return false.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* This target hook returns an rtx that is used to store the address
+ of the current frame into the built-in setjmp buffer. */
+DEFHOOK
+(builtin_setjmp_frame_value,
+ "This target hook should return an rtx that is used to store\n\
+the address of the current frame into the built in @code{setjmp} buffer.\n\
+The default value, @code{virtual_stack_vars_rtx}, is correct for most\n\
+machines. One reason you may need to define this target hook is if\n\
+@code{hard_frame_pointer_rtx} is the appropriate value on your machine.",
+ rtx, (void),
+ default_builtin_setjmp_frame_value)
+
+/* This target hook should manipulate the outputs, inputs, constraints,
+ and clobbers the port wishes for pre-processing the asm. */
+DEFHOOK
+(md_asm_adjust,
+ "This target hook may add @dfn{clobbers} to @var{clobbers} and\n\
+@var{clobbered_regs} for any hard regs the port wishes to automatically\n\
+clobber for an asm. The @var{outputs} and @var{inputs} may be inspected\n\
+to avoid clobbering a register that is already used by the asm. @var{loc}\n\
+is the source location of the asm.\n\
+\n\
+It may modify the @var{outputs}, @var{inputs}, @var{input_modes}, and\n\
+@var{constraints} as necessary for other pre-processing. In this case the\n\
+return value is a sequence of insns to emit after the asm. Note that\n\
+changes to @var{inputs} must be accompanied by the corresponding changes\n\
+to @var{input_modes}.",
+ rtx_insn *,
+ (vec<rtx>& outputs, vec<rtx>& inputs, vec<machine_mode>& input_modes,
+ vec<const char *>& constraints, vec<rtx>& clobbers,
+ HARD_REG_SET& clobbered_regs, location_t loc),
+ NULL)
+
+/* This target hook allows the backend to specify a calling convention
+ in the debug information. This function actually returns an
+ enum dwarf_calling_convention, but because of forward declarations
+ and not wanting to include dwarf2.h everywhere target.h is included
+ the function is being declared as an int. */
+DEFHOOK
+(dwarf_calling_convention,
+ "Define this to enable the dwarf attribute @code{DW_AT_calling_convention} to\n\
+be emitted for each function. Instead of an integer return the enum\n\
+value for the @code{DW_CC_} tag.",
+ int, (const_tree function),
+ hook_int_const_tree_0)
+
+/* This target hook allows the backend to emit frame-related insns that
+ contain UNSPECs or UNSPEC_VOLATILEs. The call frame debugging info
+ engine will invoke it on insns of the form
+ (set (reg) (unspec [...] UNSPEC_INDEX))
+ and
+ (set (reg) (unspec_volatile [...] UNSPECV_INDEX))
+ to let the backend emit the call frame instructions. */
+DEFHOOK
+(dwarf_handle_frame_unspec,
+ "This target hook allows the backend to emit frame-related insns that\n\
+contain UNSPECs or UNSPEC_VOLATILEs. The DWARF 2 call frame debugging\n\
+info engine will invoke it on insns of the form\n\
+@smallexample\n\
+(set (reg) (unspec [@dots{}] UNSPEC_INDEX))\n\
+@end smallexample\n\
+and\n\
+@smallexample\n\
+(set (reg) (unspec_volatile [@dots{}] UNSPECV_INDEX)).\n\
+@end smallexample\n\
+to let the backend emit the call frame instructions. @var{label} is\n\
+the CFI label attached to the insn, @var{pattern} is the pattern of\n\
+the insn and @var{index} is @code{UNSPEC_INDEX} or @code{UNSPECV_INDEX}.",
+ void, (const char *label, rtx pattern, int index), NULL)
+
+DEFHOOK
+(dwarf_poly_indeterminate_value,
+ "Express the value of @code{poly_int} indeterminate @var{i} as a DWARF\n\
+expression, with @var{i} counting from 1. Return the number of a DWARF\n\
+register @var{R} and set @samp{*@var{factor}} and @samp{*@var{offset}} such\n\
+that the value of the indeterminate is:\n\
+@smallexample\n\
+value_of(@var{R}) / @var{factor} - @var{offset}\n\
+@end smallexample\n\
+\n\
+A target only needs to define this hook if it sets\n\
+@samp{NUM_POLY_INT_COEFFS} to a value greater than 1.",
+ unsigned int, (unsigned int i, unsigned int *factor, int *offset),
+ default_dwarf_poly_indeterminate_value)
+
+/* ??? Documenting this hook requires a GFDL license grant. */
+DEFHOOK_UNDOC
+(stdarg_optimize_hook,
+"Perform architecture specific checking of statements gimplified\
+ from @code{VA_ARG_EXPR}. @var{stmt} is the statement. Returns true if\
+ the statement doesn't need to be checked for @code{va_list} references.",
+ bool, (struct stdarg_info *ai, const gimple *stmt), NULL)
+
+/* This target hook allows the operating system to override the DECL
+ that represents the external variable that contains the stack
+ protection guard variable. The type of this DECL is ptr_type_node. */
+DEFHOOK
+(stack_protect_guard,
+ "This hook returns a @code{DECL} node for the external variable to use\n\
+for the stack protection guard. This variable is initialized by the\n\
+runtime to some random value and is used to initialize the guard value\n\
+that is placed at the top of the local stack frame. The type of this\n\
+variable must be @code{ptr_type_node}.\n\
+\n\
+The default version of this hook creates a variable called\n\
+@samp{__stack_chk_guard}, which is normally defined in @file{libgcc2.c}.",
+ tree, (void),
+ default_stack_protect_guard)
+
+/* This target hook allows the operating system to override the CALL_EXPR
+ that is invoked when a check vs the guard variable fails. */
+DEFHOOK
+(stack_protect_fail,
+ "This hook returns a @code{CALL_EXPR} that alerts the runtime that the\n\
+stack protect guard variable has been modified. This expression should\n\
+involve a call to a @code{noreturn} function.\n\
+\n\
+The default version of this hook invokes a function called\n\
+@samp{__stack_chk_fail}, taking no arguments. This function is\n\
+normally defined in @file{libgcc2.c}.",
+ tree, (void),
+ default_external_stack_protect_fail)
+
+/* This target hook allows the operating system to disable the default stack
+ protector runtime support. */
+DEFHOOK
+(stack_protect_runtime_enabled_p,
+ "Returns true if the target wants GCC's default stack protect runtime support,\n\
+otherwise return false. The default implementation always returns true.",
+ bool, (void),
+ hook_bool_void_true)
+
+DEFHOOK
+(have_speculation_safe_value,
+"This hook is used to determine the level of target support for\n\
+ @code{__builtin_speculation_safe_value}. If called with an argument\n\
+ of false, it returns true if the target has been modified to support\n\
+ this builtin. If called with an argument of true, it returns true\n\
+ if the target requires active mitigation execution might be speculative.\n\
+ \n\
+ The default implementation returns false if the target does not define\n\
+ a pattern named @code{speculation_barrier}. Else it returns true\n\
+ for the first case and whether the pattern is enabled for the current\n\
+ compilation for the second case.\n\
+ \n\
+ For targets that have no processors that can execute instructions\n\
+ speculatively an alternative implemenation of this hook is available:\n\
+ simply redefine this hook to @code{speculation_safe_value_not_needed}\n\
+ along with your other target hooks.",
+bool, (bool active), default_have_speculation_safe_value)
+
+DEFHOOK
+(speculation_safe_value,
+"This target hook can be used to generate a target-specific code\n\
+ sequence that implements the @code{__builtin_speculation_safe_value}\n\
+ built-in function. The function must always return @var{val} in\n\
+ @var{result} in mode @var{mode} when the cpu is not executing\n\
+ speculatively, but must never return that when speculating until it\n\
+ is known that the speculation will not be unwound. The hook supports\n\
+ two primary mechanisms for implementing the requirements. The first\n\
+ is to emit a speculation barrier which forces the processor to wait\n\
+ until all prior speculative operations have been resolved; the second\n\
+ is to use a target-specific mechanism that can track the speculation\n\
+ state and to return @var{failval} if it can determine that\n\
+ speculation must be unwound at a later time.\n\
+ \n\
+ The default implementation simply copies @var{val} to @var{result} and\n\
+ emits a @code{speculation_barrier} instruction if that is defined.",
+rtx, (machine_mode mode, rtx result, rtx val, rtx failval),
+ default_speculation_safe_value)
+
+DEFHOOK
+(predict_doloop_p,
+ "Return true if we can predict it is possible to use a low-overhead loop\n\
+for a particular loop. The parameter @var{loop} is a pointer to the loop.\n\
+This target hook is required only when the target supports low-overhead\n\
+loops, and will help ivopts to make some decisions.\n\
+The default version of this hook returns false.",
+ bool, (class loop *loop),
+ default_predict_doloop_p)
+
+DEFHOOKPOD
+(have_count_reg_decr_p,
+ "Return true if the target supports hardware count register for decrement\n\
+and branch.\n\
+The default value is false.",
+ bool, false)
+
+DEFHOOKPOD
+(doloop_cost_for_generic,
+ "One IV candidate dedicated for doloop is introduced in IVOPTs, we can\n\
+calculate the computation cost of adopting it to any generic IV use by\n\
+function get_computation_cost as before. But for targets which have\n\
+hardware count register support for decrement and branch, it may have to\n\
+move IV value from hardware count register to general purpose register\n\
+while doloop IV candidate is used for generic IV uses. It probably takes\n\
+expensive penalty. This hook allows target owners to define the cost for\n\
+this especially for generic IV uses.\n\
+The default value is zero.",
+ int64_t, 0)
+
+DEFHOOKPOD
+(doloop_cost_for_address,
+ "One IV candidate dedicated for doloop is introduced in IVOPTs, we can\n\
+calculate the computation cost of adopting it to any address IV use by\n\
+function get_computation_cost as before. But for targets which have\n\
+hardware count register support for decrement and branch, it may have to\n\
+move IV value from hardware count register to general purpose register\n\
+while doloop IV candidate is used for address IV uses. It probably takes\n\
+expensive penalty. This hook allows target owners to define the cost for\n\
+this escpecially for address IV uses.\n\
+The default value is zero.",
+ int64_t, 0)
+
+DEFHOOK
+(can_use_doloop_p,
+ "Return true if it is possible to use low-overhead loops (@code{doloop_end}\n\
+and @code{doloop_begin}) for a particular loop. @var{iterations} gives the\n\
+exact number of iterations, or 0 if not known. @var{iterations_max} gives\n\
+the maximum number of iterations, or 0 if not known. @var{loop_depth} is\n\
+the nesting depth of the loop, with 1 for innermost loops, 2 for loops that\n\
+contain innermost loops, and so on. @var{entered_at_top} is true if the\n\
+loop is only entered from the top.\n\
+\n\
+This hook is only used if @code{doloop_end} is available. The default\n\
+implementation returns true. You can use @code{can_use_doloop_if_innermost}\n\
+if the loop must be the innermost, and if there are no other restrictions.",
+ bool, (const widest_int &iterations, const widest_int &iterations_max,
+ unsigned int loop_depth, bool entered_at_top),
+ hook_bool_wint_wint_uint_bool_true)
+
+/* Returns NULL if target supports the insn within a doloop block,
+ otherwise it returns an error message. */
+DEFHOOK
+(invalid_within_doloop,
+ "\n\
+Take an instruction in @var{insn} and return NULL if it is valid within a\n\
+low-overhead loop, otherwise return a string explaining why doloop\n\
+could not be applied.\n\
+\n\
+Many targets use special registers for low-overhead looping. For any\n\
+instruction that clobbers these this function should return a string indicating\n\
+the reason why the doloop could not be applied.\n\
+By default, the RTL loop optimizer does not use a present doloop pattern for\n\
+loops containing function calls or branch on table instructions.",
+ const char *, (const rtx_insn *insn),
+ default_invalid_within_doloop)
+
+/* Returns the machine mode which the target prefers for doloop IV. */
+DEFHOOK
+(preferred_doloop_mode,
+"This hook takes a @var{mode} for a doloop IV, where @code{mode} is the\n\
+original mode for the operation. If the target prefers an alternate\n\
+@code{mode} for the operation, then this hook should return that mode;\n\
+otherwise the original @code{mode} should be returned. For example, on a\n\
+64-bit target, @code{DImode} might be preferred over @code{SImode}. Both the\n\
+original and the returned modes should be @code{MODE_INT}.",
+ machine_mode,
+ (machine_mode mode),
+ default_preferred_doloop_mode)
+
+/* Returns true for a legitimate combined insn. */
+DEFHOOK
+(legitimate_combined_insn,
+"Take an instruction in @var{insn} and return @code{false} if the instruction\n\
+is not appropriate as a combination of two or more instructions. The\n\
+default is to accept all instructions.",
+ bool, (rtx_insn *insn),
+ hook_bool_rtx_insn_true)
+
+DEFHOOK
+(valid_dllimport_attribute_p,
+"@var{decl} is a variable or function with @code{__attribute__((dllimport))}\n\
+specified. Use this hook if the target needs to add extra validation\n\
+checks to @code{handle_dll_attribute}.",
+ bool, (const_tree decl),
+ hook_bool_const_tree_true)
+
+/* If non-zero, align constant anchors in CSE to a multiple of this
+ value. */
+DEFHOOKPOD
+(const_anchor,
+ "On some architectures it can take multiple instructions to synthesize\n\
+a constant. If there is another constant already in a register that\n\
+is close enough in value then it is preferable that the new constant\n\
+is computed from this register using immediate addition or\n\
+subtraction. We accomplish this through CSE. Besides the value of\n\
+the constant we also add a lower and an upper constant anchor to the\n\
+available expressions. These are then queried when encountering new\n\
+constants. The anchors are computed by rounding the constant up and\n\
+down to a multiple of the value of @code{TARGET_CONST_ANCHOR}.\n\
+@code{TARGET_CONST_ANCHOR} should be the maximum positive value\n\
+accepted by immediate-add plus one. We currently assume that the\n\
+value of @code{TARGET_CONST_ANCHOR} is a power of 2. For example, on\n\
+MIPS, where add-immediate takes a 16-bit signed value,\n\
+@code{TARGET_CONST_ANCHOR} is set to @samp{0x8000}. The default value\n\
+is zero, which disables this optimization.",
+ unsigned HOST_WIDE_INT, 0)
+
+/* Defines, which target-dependent bits (upper 16) are used by port */
+DEFHOOK
+(memmodel_check,
+ "Validate target specific memory model mask bits. When NULL no target specific\n\
+memory model bits are allowed.",
+ unsigned HOST_WIDE_INT, (unsigned HOST_WIDE_INT val), NULL)
+
+/* Defines an offset bitwise ored into shifted address to get corresponding
+ Address Sanitizer shadow address, or -1 if Address Sanitizer is not
+ supported by the target. */
+DEFHOOK
+(asan_shadow_offset,
+ "Return the offset bitwise ored into shifted address to get corresponding\n\
+Address Sanitizer shadow memory address. NULL if Address Sanitizer is not\n\
+supported by the target. May return 0 if Address Sanitizer is not supported\n\
+by a subtarget.",
+ unsigned HOST_WIDE_INT, (void),
+ NULL)
+
+/* Functions relating to calls - argument passing, returns, etc. */
+/* Members of struct call have no special macro prefix. */
+HOOK_VECTOR (TARGET_CALLS, calls)
+
+DEFHOOK
+(promote_function_mode,
+ "Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or\n\
+function return values. The target hook should return the new mode\n\
+and possibly change @code{*@var{punsignedp}} if the promotion should\n\
+change signedness. This function is called only for scalar @emph{or\n\
+pointer} types.\n\
+\n\
+@var{for_return} allows to distinguish the promotion of arguments and\n\
+return values. If it is @code{1}, a return value is being promoted and\n\
+@code{TARGET_FUNCTION_VALUE} must perform the same promotions done here.\n\
+If it is @code{2}, the returned mode should be that of the register in\n\
+which an incoming parameter is copied, or the outgoing result is computed;\n\
+then the hook should return the same mode as @code{promote_mode}, though\n\
+the signedness may be different.\n\
+\n\
+@var{type} can be NULL when promoting function arguments of libcalls.\n\
+\n\
+The default is to not promote arguments and return values. You can\n\
+also define the hook to @code{default_promote_function_mode_always_promote}\n\
+if you would like to apply the same rules given by @code{PROMOTE_MODE}.",
+ machine_mode, (const_tree type, machine_mode mode, int *punsignedp,
+ const_tree funtype, int for_return),
+ default_promote_function_mode)
+
+DEFHOOK
+(promote_prototypes,
+ "This target hook returns @code{true} if an argument declared in a\n\
+prototype as an integral type smaller than @code{int} should actually be\n\
+passed as an @code{int}. In addition to avoiding errors in certain\n\
+cases of mismatch, it also makes for better code on certain machines.\n\
+The default is to not promote prototypes.",
+ bool, (const_tree fntype),
+ hook_bool_const_tree_false)
+
+DEFHOOK
+(struct_value_rtx,
+ "This target hook should return the location of the structure value\n\
+address (normally a @code{mem} or @code{reg}), or 0 if the address is\n\
+passed as an ``invisible'' first argument. Note that @var{fndecl} may\n\
+be @code{NULL}, for libcalls. You do not need to define this target\n\
+hook if the address is always passed as an ``invisible'' first\n\
+argument.\n\
+\n\
+On some architectures the place where the structure value address\n\
+is found by the called function is not the same place that the\n\
+caller put it. This can be due to register windows, or it could\n\
+be because the function prologue moves it to a different place.\n\
+@var{incoming} is @code{1} or @code{2} when the location is needed in\n\
+the context of the called function, and @code{0} in the context of\n\
+the caller.\n\
+\n\
+If @var{incoming} is nonzero and the address is to be found on the\n\
+stack, return a @code{mem} which refers to the frame pointer. If\n\
+@var{incoming} is @code{2}, the result is being used to fetch the\n\
+structure value address at the beginning of a function. If you need\n\
+to emit adjusting code, you should do it at this point.",
+ rtx, (tree fndecl, int incoming),
+ hook_rtx_tree_int_null)
+
+DEFHOOKPOD
+(omit_struct_return_reg,
+ "Normally, when a function returns a structure by memory, the address\n\
+is passed as an invisible pointer argument, but the compiler also\n\
+arranges to return the address from the function like it would a normal\n\
+pointer return value. Define this to true if that behavior is\n\
+undesirable on your target.",
+ bool, false)
+
+DEFHOOK
+(return_in_memory,
+ "This target hook should return a nonzero value to say to return the\n\
+function value in memory, just as large structures are always returned.\n\
+Here @var{type} will be the data type of the value, and @var{fntype}\n\
+will be the type of the function doing the returning, or @code{NULL} for\n\
+libcalls.\n\
+\n\
+Note that values of mode @code{BLKmode} must be explicitly handled\n\
+by this function. Also, the option @option{-fpcc-struct-return}\n\
+takes effect regardless of this macro. On most systems, it is\n\
+possible to leave the hook undefined; this causes a default\n\
+definition to be used, whose value is the constant 1 for @code{BLKmode}\n\
+values, and 0 otherwise.\n\
+\n\
+Do not use this hook to indicate that structures and unions should always\n\
+be returned in memory. You should instead use @code{DEFAULT_PCC_STRUCT_RETURN}\n\
+to indicate this.",
+ bool, (const_tree type, const_tree fntype),
+ default_return_in_memory)
+
+DEFHOOK
+(return_in_msb,
+ "This hook should return true if values of type @var{type} are returned\n\
+at the most significant end of a register (in other words, if they are\n\
+padded at the least significant end). You can assume that @var{type}\n\
+is returned in a register; the caller is required to check this.\n\
+\n\
+Note that the register provided by @code{TARGET_FUNCTION_VALUE} must\n\
+be able to hold the complete return value. For example, if a 1-, 2-\n\
+or 3-byte structure is returned at the most significant end of a\n\
+4-byte register, @code{TARGET_FUNCTION_VALUE} should provide an\n\
+@code{SImode} rtx.",
+ bool, (const_tree type),
+ hook_bool_const_tree_false)
+
+/* Return true if a parameter must be passed by reference. TYPE may
+ be null if this is a libcall. CA may be null if this query is
+ from __builtin_va_arg. */
+DEFHOOK
+(pass_by_reference,
+ "This target hook should return @code{true} if argument @var{arg} at the\n\
+position indicated by @var{cum} should be passed by reference. This\n\
+predicate is queried after target independent reasons for being\n\
+passed by reference, such as @code{TREE_ADDRESSABLE (@var{arg}.type)}.\n\
+\n\
+If the hook returns true, a copy of that argument is made in memory and a\n\
+pointer to the argument is passed instead of the argument itself.\n\
+The pointer is passed in whatever way is appropriate for passing a pointer\n\
+to that type.",
+ bool,
+ (cumulative_args_t cum, const function_arg_info &arg),
+ hook_bool_CUMULATIVE_ARGS_arg_info_false)
+
+DEFHOOK
+(expand_builtin_saveregs,
+ "If defined, this hook produces the machine-specific code for a call to\n\
+@code{__builtin_saveregs}. This code will be moved to the very\n\
+beginning of the function, before any parameter access are made. The\n\
+return value of this function should be an RTX that contains the value\n\
+to use as the return of @code{__builtin_saveregs}.",
+ rtx, (void),
+ default_expand_builtin_saveregs)
+
+/* Returns pretend_argument_size. */
+DEFHOOK
+(setup_incoming_varargs,
+ "This target hook offers an alternative to using\n\
+@code{__builtin_saveregs} and defining the hook\n\
+@code{TARGET_EXPAND_BUILTIN_SAVEREGS}. Use it to store the anonymous\n\
+register arguments into the stack so that all the arguments appear to\n\
+have been passed consecutively on the stack. Once this is done, you can\n\
+use the standard implementation of varargs that works for machines that\n\
+pass all their arguments on the stack.\n\
+\n\
+The argument @var{args_so_far} points to the @code{CUMULATIVE_ARGS} data\n\
+structure, containing the values that are obtained after processing the\n\
+named arguments. The argument @var{arg} describes the last of these named\n\
+arguments.\n\
+\n\
+The target hook should do two things: first, push onto the stack all the\n\
+argument registers @emph{not} used for the named arguments, and second,\n\
+store the size of the data thus pushed into the @code{int}-valued\n\
+variable pointed to by @var{pretend_args_size}. The value that you\n\
+store here will serve as additional offset for setting up the stack\n\
+frame.\n\
+\n\
+Because you must generate code to push the anonymous arguments at\n\
+compile time without knowing their data types,\n\
+@code{TARGET_SETUP_INCOMING_VARARGS} is only useful on machines that\n\
+have just a single category of argument register and use it uniformly\n\
+for all data types.\n\
+\n\
+If the argument @var{second_time} is nonzero, it means that the\n\
+arguments of the function are being analyzed for the second time. This\n\
+happens for an inline function, which is not actually compiled until the\n\
+end of the source file. The hook @code{TARGET_SETUP_INCOMING_VARARGS} should\n\
+not generate any instructions in this case.",
+ void, (cumulative_args_t args_so_far, const function_arg_info &arg,
+ int *pretend_args_size, int second_time),
+ default_setup_incoming_varargs)
+
+DEFHOOK
+(call_args,
+ "While generating RTL for a function call, this target hook is invoked once\n\
+for each argument passed to the function, either a register returned by\n\
+@code{TARGET_FUNCTION_ARG} or a memory location. It is called just\n\
+before the point where argument registers are stored. The type of the\n\
+function to be called is also passed as the second argument; it is\n\
+@code{NULL_TREE} for libcalls. The @code{TARGET_END_CALL_ARGS} hook is\n\
+invoked just after the code to copy the return reg has been emitted.\n\
+This functionality can be used to perform special setup of call argument\n\
+registers if a target needs it.\n\
+For functions without arguments, the hook is called once with @code{pc_rtx}\n\
+passed instead of an argument register.\n\
+Most ports do not need to implement anything for this hook.",
+ void, (rtx, tree),
+ hook_void_rtx_tree)
+
+DEFHOOK
+(end_call_args,
+ "This target hook is invoked while generating RTL for a function call,\n\
+just after the point where the return reg is copied into a pseudo. It\n\
+signals that all the call argument and return registers for the just\n\
+emitted call are now no longer in use.\n\
+Most ports do not need to implement anything for this hook.",
+ void, (void),
+ hook_void_void)
+
+DEFHOOK
+(push_argument,
+ "This target hook returns @code{true} if push instructions will be\n\
+used to pass outgoing arguments. When the push instruction usage is\n\
+optional, @var{npush} is nonzero to indicate the number of bytes to\n\
+push. Otherwise, @var{npush} is zero. If the target machine does not\n\
+have a push instruction or push instruction should be avoided,\n\
+@code{false} should be returned. That directs GCC to use an alternate\n\
+strategy: to allocate the entire argument block and then store the\n\
+arguments into it. If this target hook may return @code{true},\n\
+@code{PUSH_ROUNDING} must be defined.",
+ bool, (unsigned int npush),
+ default_push_argument)
+
+DEFHOOK
+(strict_argument_naming,
+ "Define this hook to return @code{true} if the location where a function\n\
+argument is passed depends on whether or not it is a named argument.\n\
+\n\
+This hook controls how the @var{named} argument to @code{TARGET_FUNCTION_ARG}\n\
+is set for varargs and stdarg functions. If this hook returns\n\
+@code{true}, the @var{named} argument is always true for named\n\
+arguments, and false for unnamed arguments. If it returns @code{false},\n\
+but @code{TARGET_PRETEND_OUTGOING_VARARGS_NAMED} returns @code{true},\n\
+then all arguments are treated as named. Otherwise, all named arguments\n\
+except the last are treated as named.\n\
+\n\
+You need not define this hook if it always returns @code{false}.",
+ bool, (cumulative_args_t ca),
+ hook_bool_CUMULATIVE_ARGS_false)
+
+/* Returns true if we should use
+ targetm.calls.setup_incoming_varargs() and/or
+ targetm.calls.strict_argument_naming(). */
+DEFHOOK
+(pretend_outgoing_varargs_named,
+ "If you need to conditionally change ABIs so that one works with\n\
+@code{TARGET_SETUP_INCOMING_VARARGS}, but the other works like neither\n\
+@code{TARGET_SETUP_INCOMING_VARARGS} nor @code{TARGET_STRICT_ARGUMENT_NAMING} was\n\
+defined, then define this hook to return @code{true} if\n\
+@code{TARGET_SETUP_INCOMING_VARARGS} is used, @code{false} otherwise.\n\
+Otherwise, you should not define this hook.",
+ bool, (cumulative_args_t ca),
+ default_pretend_outgoing_varargs_named)
+
+/* Given a complex type T, return true if a parameter of type T
+ should be passed as two scalars. */
+DEFHOOK
+(split_complex_arg,
+ "This hook should return true if parameter of type @var{type} are passed\n\
+as two scalar parameters. By default, GCC will attempt to pack complex\n\
+arguments into the target's word size. Some ABIs require complex arguments\n\
+to be split and treated as their individual components. For example, on\n\
+AIX64, complex floats should be passed in a pair of floating point\n\
+registers, even though a complex float would fit in one 64-bit floating\n\
+point register.\n\
+\n\
+The default value of this hook is @code{NULL}, which is treated as always\n\
+false.",
+ bool, (const_tree type), NULL)
+
+/* Return true if type T, mode MODE, may not be passed in registers,
+ but must be passed on the stack. */
+/* ??? This predicate should be applied strictly after pass-by-reference.
+ Need audit to verify that this is the case. */
+DEFHOOK
+(must_pass_in_stack,
+ "This target hook should return @code{true} if we should not pass @var{arg}\n\
+solely in registers. The file @file{expr.h} defines a\n\
+definition that is usually appropriate, refer to @file{expr.h} for additional\n\
+documentation.",
+ bool, (const function_arg_info &arg),
+ must_pass_in_stack_var_size_or_pad)
+
+/* Return true if type TYPE, mode MODE, which is passed by reference,
+ should have the object copy generated by the callee rather than
+ the caller. It is never called for TYPE requiring constructors. */
+DEFHOOK
+(callee_copies,
+ "The function argument described by the parameters to this hook is\n\
+known to be passed by reference. The hook should return true if the\n\
+function argument should be copied by the callee instead of copied\n\
+by the caller.\n\
+\n\
+For any argument for which the hook returns true, if it can be\n\
+determined that the argument is not modified, then a copy need\n\
+not be generated.\n\
+\n\
+The default version of this hook always returns false.",
+ bool,
+ (cumulative_args_t cum, const function_arg_info &arg),
+ hook_bool_CUMULATIVE_ARGS_arg_info_false)
+
+/* Return zero for arguments passed entirely on the stack or entirely
+ in registers. If passed in both, return the number of bytes passed
+ in registers; the balance is therefore passed on the stack. */
+DEFHOOK
+(arg_partial_bytes,
+ "This target hook returns the number of bytes at the beginning of an\n\
+argument that must be put in registers. The value must be zero for\n\
+arguments that are passed entirely in registers or that are entirely\n\
+pushed on the stack.\n\
+\n\
+On some machines, certain arguments must be passed partially in\n\
+registers and partially in memory. On these machines, typically the\n\
+first few words of arguments are passed in registers, and the rest\n\
+on the stack. If a multi-word argument (a @code{double} or a\n\
+structure) crosses that boundary, its first few words must be passed\n\
+in registers and the rest must be pushed. This macro tells the\n\
+compiler when this occurs, and how many bytes should go in registers.\n\
+\n\
+@code{TARGET_FUNCTION_ARG} for these arguments should return the first\n\
+register to be used by the caller for this argument; likewise\n\
+@code{TARGET_FUNCTION_INCOMING_ARG}, for the called function.",
+ int, (cumulative_args_t cum, const function_arg_info &arg),
+ hook_int_CUMULATIVE_ARGS_arg_info_0)
+
+/* Update the state in CA to advance past an argument in the
+ argument list. The values MODE, TYPE, and NAMED describe that
+ argument. */
+DEFHOOK
+(function_arg_advance,
+ "This hook updates the summarizer variable pointed to by @var{ca} to\n\
+advance past argument @var{arg} in the argument list. Once this is done,\n\
+the variable @var{cum} is suitable for analyzing the @emph{following}\n\
+argument with @code{TARGET_FUNCTION_ARG}, etc.\n\
+\n\
+This hook need not do anything if the argument in question was passed\n\
+on the stack. The compiler knows how to track the amount of stack space\n\
+used for arguments without any special help.",
+ void,
+ (cumulative_args_t ca, const function_arg_info &arg),
+ default_function_arg_advance)
+
+DEFHOOK
+(function_arg_offset,
+ "This hook returns the number of bytes to add to the offset of an\n\
+argument of type @var{type} and mode @var{mode} when passed in memory.\n\
+This is needed for the SPU, which passes @code{char} and @code{short}\n\
+arguments in the preferred slot that is in the middle of the quad word\n\
+instead of starting at the top. The default implementation returns 0.",
+ HOST_WIDE_INT, (machine_mode mode, const_tree type),
+ default_function_arg_offset)
+
+DEFHOOK
+(function_arg_padding,
+ "This hook determines whether, and in which direction, to pad out\n\
+an argument of mode @var{mode} and type @var{type}. It returns\n\
+@code{PAD_UPWARD} to insert padding above the argument, @code{PAD_DOWNWARD}\n\
+to insert padding below the argument, or @code{PAD_NONE} to inhibit padding.\n\
+\n\
+The @emph{amount} of padding is not controlled by this hook, but by\n\
+@code{TARGET_FUNCTION_ARG_ROUND_BOUNDARY}. It is always just enough\n\
+to reach the next multiple of that boundary.\n\
+\n\
+This hook has a default definition that is right for most systems.\n\
+For little-endian machines, the default is to pad upward. For\n\
+big-endian machines, the default is to pad downward for an argument of\n\
+constant size shorter than an @code{int}, and upward otherwise.",
+ pad_direction, (machine_mode mode, const_tree type),
+ default_function_arg_padding)
+
+/* Return zero if the argument described by the state of CA should
+ be placed on a stack, or a hard register in which to store the
+ argument. The values MODE, TYPE, and NAMED describe that
+ argument. */
+DEFHOOK
+(function_arg,
+ "Return an RTX indicating whether function argument @var{arg} is passed\n\
+in a register and if so, which register. Argument @var{ca} summarizes all\n\
+the previous arguments.\n\
+\n\
+The return value is usually either a @code{reg} RTX for the hard\n\
+register in which to pass the argument, or zero to pass the argument\n\
+on the stack.\n\
+\n\
+The value of the expression can also be a @code{parallel} RTX@. This is\n\
+used when an argument is passed in multiple locations. The mode of the\n\
+@code{parallel} should be the mode of the entire argument. The\n\
+@code{parallel} holds any number of @code{expr_list} pairs; each one\n\
+describes where part of the argument is passed. In each\n\
+@code{expr_list} the first operand must be a @code{reg} RTX for the hard\n\
+register in which to pass this part of the argument, and the mode of the\n\
+register RTX indicates how large this part of the argument is. The\n\
+second operand of the @code{expr_list} is a @code{const_int} which gives\n\
+the offset in bytes into the entire argument of where this part starts.\n\
+As a special exception the first @code{expr_list} in the @code{parallel}\n\
+RTX may have a first operand of zero. This indicates that the entire\n\
+argument is also stored on the stack.\n\
+\n\
+The last time this hook is called, it is called with @code{MODE ==\n\
+VOIDmode}, and its result is passed to the @code{call} or @code{call_value}\n\
+pattern as operands 2 and 3 respectively.\n\
+\n\
+@cindex @file{stdarg.h} and register arguments\n\
+The usual way to make the ISO library @file{stdarg.h} work on a\n\
+machine where some arguments are usually passed in registers, is to\n\
+cause nameless arguments to be passed on the stack instead. This is\n\
+done by making @code{TARGET_FUNCTION_ARG} return 0 whenever\n\
+@var{named} is @code{false}.\n\
+\n\
+@cindex @code{TARGET_MUST_PASS_IN_STACK}, and @code{TARGET_FUNCTION_ARG}\n\
+@cindex @code{REG_PARM_STACK_SPACE}, and @code{TARGET_FUNCTION_ARG}\n\
+You may use the hook @code{targetm.calls.must_pass_in_stack}\n\
+in the definition of this macro to determine if this argument is of a\n\
+type that must be passed in the stack. If @code{REG_PARM_STACK_SPACE}\n\
+is not defined and @code{TARGET_FUNCTION_ARG} returns nonzero for such an\n\
+argument, the compiler will abort. If @code{REG_PARM_STACK_SPACE} is\n\
+defined, the argument will be computed in the stack and then loaded into\n\
+a register.",
+ rtx, (cumulative_args_t ca, const function_arg_info &arg),
+ default_function_arg)
+
+DEFHOOK
+(function_incoming_arg,
+ "Define this hook if the caller and callee on the target have different\n\
+views of where arguments are passed. Also define this hook if there are\n\
+functions that are never directly called, but are invoked by the hardware\n\
+and which have nonstandard calling conventions.\n\
+\n\
+In this case @code{TARGET_FUNCTION_ARG} computes the register in\n\
+which the caller passes the value, and\n\
+@code{TARGET_FUNCTION_INCOMING_ARG} should be defined in a similar\n\
+fashion to tell the function being called where the arguments will\n\
+arrive.\n\
+\n\
+@code{TARGET_FUNCTION_INCOMING_ARG} can also return arbitrary address\n\
+computation using hard register, which can be forced into a register,\n\
+so that it can be used to pass special arguments.\n\
+\n\
+If @code{TARGET_FUNCTION_INCOMING_ARG} is not defined,\n\
+@code{TARGET_FUNCTION_ARG} serves both purposes.",
+ rtx, (cumulative_args_t ca, const function_arg_info &arg),
+ default_function_incoming_arg)
+
+DEFHOOK
+(function_arg_boundary,
+ "This hook returns the alignment boundary, in bits, of an argument\n\
+with the specified mode and type. The default hook returns\n\
+@code{PARM_BOUNDARY} for all arguments.",
+ unsigned int, (machine_mode mode, const_tree type),
+ default_function_arg_boundary)
+
+DEFHOOK
+(function_arg_round_boundary,
+ "Normally, the size of an argument is rounded up to @code{PARM_BOUNDARY},\n\
+which is the default value for this hook. You can define this hook to\n\
+return a different value if an argument size must be rounded to a larger\n\
+value.",
+ unsigned int, (machine_mode mode, const_tree type),
+ default_function_arg_round_boundary)
+
+/* Return the diagnostic message string if function without a prototype
+ is not allowed for this 'val' argument; NULL otherwise. */
+DEFHOOK
+(invalid_arg_for_unprototyped_fn,
+ "If defined, this macro returns the diagnostic message when it is\n\
+illegal to pass argument @var{val} to function @var{funcdecl}\n\
+with prototype @var{typelist}.",
+ const char *, (const_tree typelist, const_tree funcdecl, const_tree val),
+ hook_invalid_arg_for_unprototyped_fn)
+
+/* Return an rtx for the return value location of the function
+ specified by FN_DECL_OR_TYPE with a return type of RET_TYPE. */
+DEFHOOK
+(function_value,
+ "\n\
+Define this to return an RTX representing the place where a function\n\
+returns or receives a value of data type @var{ret_type}, a tree node\n\
+representing a data type. @var{fn_decl_or_type} is a tree node\n\
+representing @code{FUNCTION_DECL} or @code{FUNCTION_TYPE} of a\n\
+function being called. If @var{outgoing} is false, the hook should\n\
+compute the register in which the caller will see the return value.\n\
+Otherwise, the hook should return an RTX representing the place where\n\
+a function returns a value.\n\
+\n\
+On many machines, only @code{TYPE_MODE (@var{ret_type})} is relevant.\n\
+(Actually, on most machines, scalar values are returned in the same\n\
+place regardless of mode.) The value of the expression is usually a\n\
+@code{reg} RTX for the hard register where the return value is stored.\n\
+The value can also be a @code{parallel} RTX, if the return value is in\n\
+multiple places. See @code{TARGET_FUNCTION_ARG} for an explanation of the\n\
+@code{parallel} form. Note that the callee will populate every\n\
+location specified in the @code{parallel}, but if the first element of\n\
+the @code{parallel} contains the whole return value, callers will use\n\
+that element as the canonical location and ignore the others. The m68k\n\
+port uses this type of @code{parallel} to return pointers in both\n\
+@samp{%a0} (the canonical location) and @samp{%d0}.\n\
+\n\
+If @code{TARGET_PROMOTE_FUNCTION_RETURN} returns true, you must apply\n\
+the same promotion rules specified in @code{PROMOTE_MODE} if\n\
+@var{valtype} is a scalar type.\n\
+\n\
+If the precise function being called is known, @var{func} is a tree\n\
+node (@code{FUNCTION_DECL}) for it; otherwise, @var{func} is a null\n\
+pointer. This makes it possible to use a different value-returning\n\
+convention for specific functions when all their calls are\n\
+known.\n\
+\n\
+Some target machines have ``register windows'' so that the register in\n\
+which a function returns its value is not the same as the one in which\n\
+the caller sees the value. For such machines, you should return\n\
+different RTX depending on @var{outgoing}.\n\
+\n\
+@code{TARGET_FUNCTION_VALUE} is not used for return values with\n\
+aggregate data types, because these are returned in another way. See\n\
+@code{TARGET_STRUCT_VALUE_RTX} and related macros, below.",
+ rtx, (const_tree ret_type, const_tree fn_decl_or_type, bool outgoing),
+ default_function_value)
+
+/* Return the rtx for the result of a libcall of mode MODE,
+ calling the function FN_NAME. */
+DEFHOOK
+(libcall_value,
+ "Define this hook if the back-end needs to know the name of the libcall\n\
+function in order to determine where the result should be returned.\n\
+\n\
+The mode of the result is given by @var{mode} and the name of the called\n\
+library function is given by @var{fun}. The hook should return an RTX\n\
+representing the place where the library function result will be returned.\n\
+\n\
+If this hook is not defined, then LIBCALL_VALUE will be used.",
+ rtx, (machine_mode mode, const_rtx fun),
+ default_libcall_value)
+
+/* Return true if REGNO is a possible register number for
+ a function value as seen by the caller. */
+DEFHOOK
+(function_value_regno_p,
+ "A target hook that return @code{true} if @var{regno} is the number of a hard\n\
+register in which the values of called function may come back.\n\
+\n\
+A register whose use for returning values is limited to serving as the\n\
+second of a pair (for a value of type @code{double}, say) need not be\n\
+recognized by this target hook.\n\
+\n\
+If the machine has register windows, so that the caller and the called\n\
+function use different registers for the return value, this target hook\n\
+should recognize only the caller's register numbers.\n\
+\n\
+If this hook is not defined, then FUNCTION_VALUE_REGNO_P will be used.",
+ bool, (const unsigned int regno),
+ default_function_value_regno_p)
+
+DEFHOOK
+(fntype_abi,
+ "Return the ABI used by a function with type @var{type}; see the\n\
+definition of @code{predefined_function_abi} for details of the ABI\n\
+descriptor. Targets only need to define this hook if they support\n\
+interoperability between several ABIs in the same translation unit.",
+ const predefined_function_abi &, (const_tree type),
+ NULL)
+
+DEFHOOK
+(insn_callee_abi,
+ "This hook returns a description of the ABI used by the target of\n\
+call instruction @var{insn}; see the definition of\n\
+@code{predefined_function_abi} for details of the ABI descriptor.\n\
+Only the global function @code{insn_callee_abi} should call this hook\n\
+directly.\n\
+\n\
+Targets only need to define this hook if they support\n\
+interoperability between several ABIs in the same translation unit.",
+ const predefined_function_abi &, (const rtx_insn *insn),
+ NULL)
+
+/* ??? Documenting this hook requires a GFDL license grant. */
+DEFHOOK_UNDOC
+(internal_arg_pointer,
+"Return an rtx for the argument pointer incoming to the\
+ current function.",
+ rtx, (void),
+ default_internal_arg_pointer)
+
+/* Update the current function stack boundary if needed. */
+DEFHOOK
+(update_stack_boundary,
+ "Define this macro to update the current function stack boundary if\n\
+necessary.",
+ void, (void), NULL)
+
+/* Handle stack alignment and return an rtx for Dynamic Realign
+ Argument Pointer if necessary. */
+DEFHOOK
+(get_drap_rtx,
+ "This hook should return an rtx for Dynamic Realign Argument Pointer (DRAP) if a\n\
+different argument pointer register is needed to access the function's\n\
+argument list due to stack realignment. Return @code{NULL} if no DRAP\n\
+is needed.",
+ rtx, (void), NULL)
+
+/* Generate instruction sequence to zero call used registers. */
+DEFHOOK
+(zero_call_used_regs,
+ "This target hook emits instructions to zero the subset of @var{selected_regs}\n\
+that could conceivably contain values that are useful to an attacker.\n\
+Return the set of registers that were actually cleared.\n\
+\n\
+For most targets, the returned set of registers is a subset of\n\
+@var{selected_regs}, however, for some of the targets (for example MIPS),\n\
+clearing some registers that are in the @var{selected_regs} requires\n\
+clearing other call used registers that are not in the @var{selected_regs},\n\
+under such situation, the returned set of registers must be a subset of all\n\
+call used registers.\n\
+\n\
+The default implementation uses normal move instructions to zero\n\
+all the registers in @var{selected_regs}. Define this hook if the\n\
+target has more efficient ways of zeroing certain registers,\n\
+or if you believe that certain registers would never contain\n\
+values that are useful to an attacker.",
+ HARD_REG_SET, (HARD_REG_SET selected_regs),
+default_zero_call_used_regs)
+
+/* Return true if all function parameters should be spilled to the
+ stack. */
+DEFHOOK
+(allocate_stack_slots_for_args,
+ "When optimization is disabled, this hook indicates whether or not\n\
+arguments should be allocated to stack slots. Normally, GCC allocates\n\
+stacks slots for arguments when not optimizing in order to make\n\
+debugging easier. However, when a function is declared with\n\
+@code{__attribute__((naked))}, there is no stack frame, and the compiler\n\
+cannot safely move arguments from the registers in which they are passed\n\
+to the stack. Therefore, this hook should return true in general, but\n\
+false for naked functions. The default implementation always returns true.",
+ bool, (void),
+ hook_bool_void_true)
+
+/* Return an rtx for the static chain for FNDECL_OR_TYPE. If INCOMING_P
+ is true, then it should be for the callee; otherwise for the caller. */
+DEFHOOK
+(static_chain,
+ "This hook replaces the use of @code{STATIC_CHAIN_REGNUM} et al for\n\
+targets that may use different static chain locations for different\n\
+nested functions. This may be required if the target has function\n\
+attributes that affect the calling conventions of the function and\n\
+those calling conventions use different static chain locations.\n\
+\n\
+The default version of this hook uses @code{STATIC_CHAIN_REGNUM} et al.\n\
+\n\
+If the static chain is passed in memory, this hook should be used to\n\
+provide rtx giving @code{mem} expressions that denote where they are stored.\n\
+Often the @code{mem} expression as seen by the caller will be at an offset\n\
+from the stack pointer and the @code{mem} expression as seen by the callee\n\
+will be at an offset from the frame pointer.\n\
+@findex stack_pointer_rtx\n\
+@findex frame_pointer_rtx\n\
+@findex arg_pointer_rtx\n\
+The variables @code{stack_pointer_rtx}, @code{frame_pointer_rtx}, and\n\
+@code{arg_pointer_rtx} will have been initialized and should be used\n\
+to refer to those items.",
+ rtx, (const_tree fndecl_or_type, bool incoming_p),
+ default_static_chain)
+
+/* Fill in the trampoline at MEM with a call to FNDECL and a
+ static chain value of CHAIN. */
+DEFHOOK
+(trampoline_init,
+ "This hook is called to initialize a trampoline.\n\
+@var{m_tramp} is an RTX for the memory block for the trampoline; @var{fndecl}\n\
+is the @code{FUNCTION_DECL} for the nested function; @var{static_chain} is an\n\
+RTX for the static chain value that should be passed to the function\n\
+when it is called.\n\
+\n\
+If the target defines @code{TARGET_ASM_TRAMPOLINE_TEMPLATE}, then the\n\
+first thing this hook should do is emit a block move into @var{m_tramp}\n\
+from the memory block returned by @code{assemble_trampoline_template}.\n\
+Note that the block move need only cover the constant parts of the\n\
+trampoline. If the target isolates the variable parts of the trampoline\n\
+to the end, not all @code{TRAMPOLINE_SIZE} bytes need be copied.\n\
+\n\
+If the target requires any other actions, such as flushing caches\n\
+(possibly calling function maybe_emit_call_builtin___clear_cache) or\n\
+enabling stack execution, these actions should be performed after\n\
+initializing the trampoline proper.",
+ void, (rtx m_tramp, tree fndecl, rtx static_chain),
+ default_trampoline_init)
+
+/* Emit a call to a function to clear the instruction cache. */
+DEFHOOK
+(emit_call_builtin___clear_cache,
+ "On targets that do not define a @code{clear_cache} insn expander,\n\
+but that define the @code{CLEAR_CACHE_INSN} macro,\n\
+maybe_emit_call_builtin___clear_cache relies on this target hook\n\
+to clear an address range in the instruction cache.\n\
+\n\
+The default implementation calls the @code{__clear_cache} builtin,\n\
+taking the assembler name from the builtin declaration. Overriding\n\
+definitions may call alternate functions, with alternate calling\n\
+conventions, or emit alternate RTX to perform the job.",
+ void, (rtx begin, rtx end),
+ default_emit_call_builtin___clear_cache)
+
+/* Adjust the address of the trampoline in a target-specific way. */
+DEFHOOK
+(trampoline_adjust_address,
+ "This hook should perform any machine-specific adjustment in\n\
+the address of the trampoline. Its argument contains the address of the\n\
+memory block that was passed to @code{TARGET_TRAMPOLINE_INIT}. In case\n\
+the address to be used for a function call should be different from the\n\
+address at which the template was stored, the different address should\n\
+be returned; otherwise @var{addr} should be returned unchanged.\n\
+If this hook is not defined, @var{addr} will be used for function calls.",
+ rtx, (rtx addr), NULL)
+
+DEFHOOKPOD
+(custom_function_descriptors,
+ "If the target can use GCC's generic descriptor mechanism for nested\n\
+functions, define this hook to a power of 2 representing an unused bit\n\
+in function pointers which can be used to differentiate descriptors at\n\
+run time. This value gives the number of bytes by which descriptor\n\
+pointers are misaligned compared to function pointers. For example, on\n\
+targets that require functions to be aligned to a 4-byte boundary, a\n\
+value of either 1 or 2 is appropriate unless the architecture already\n\
+reserves the bit for another purpose, such as on ARM.\n\
+\n\
+Define this hook to 0 if the target implements ABI support for\n\
+function descriptors in its standard calling sequence, like for example\n\
+HPPA or IA-64.\n\
+\n\
+Using descriptors for nested functions\n\
+eliminates the need for trampolines that reside on the stack and require\n\
+it to be made executable.",
+ int, -1)
+
+/* Return the number of bytes of its own arguments that a function
+ pops on returning, or 0 if the function pops no arguments and the
+ caller must therefore pop them all after the function returns. */
+/* ??? tm.texi has no types for the parameters. */
+DEFHOOK
+(return_pops_args,
+ "This target hook returns the number of bytes of its own arguments that\n\
+a function pops on returning, or 0 if the function pops no arguments\n\
+and the caller must therefore pop them all after the function returns.\n\
+\n\
+@var{fundecl} is a C variable whose value is a tree node that describes\n\
+the function in question. Normally it is a node of type\n\
+@code{FUNCTION_DECL} that describes the declaration of the function.\n\
+From this you can obtain the @code{DECL_ATTRIBUTES} of the function.\n\
+\n\
+@var{funtype} is a C variable whose value is a tree node that\n\
+describes the function in question. Normally it is a node of type\n\
+@code{FUNCTION_TYPE} that describes the data type of the function.\n\
+From this it is possible to obtain the data types of the value and\n\
+arguments (if known).\n\
+\n\
+When a call to a library function is being considered, @var{fundecl}\n\
+will contain an identifier node for the library function. Thus, if\n\
+you need to distinguish among various library functions, you can do so\n\
+by their names. Note that ``library function'' in this context means\n\
+a function used to perform arithmetic, whose name is known specially\n\
+in the compiler and was not mentioned in the C code being compiled.\n\
+\n\
+@var{size} is the number of bytes of arguments passed on the\n\
+stack. If a variable number of bytes is passed, it is zero, and\n\
+argument popping will always be the responsibility of the calling function.\n\
+\n\
+On the VAX, all functions always pop their arguments, so the definition\n\
+of this macro is @var{size}. On the 68000, using the standard\n\
+calling convention, no functions pop their arguments, so the value of\n\
+the macro is always 0 in this case. But an alternative calling\n\
+convention is available in which functions that take a fixed number of\n\
+arguments pop them but other functions (such as @code{printf}) pop\n\
+nothing (the caller pops all). When this convention is in use,\n\
+@var{funtype} is examined to determine whether a function takes a fixed\n\
+number of arguments.",
+ poly_int64, (tree fundecl, tree funtype, poly_int64 size),
+ default_return_pops_args)
+
+/* Return a mode wide enough to copy any function value that might be
+ returned. */
+DEFHOOK
+(get_raw_result_mode,
+ "This target hook returns the mode to be used when accessing raw return\n\
+registers in @code{__builtin_return}. Define this macro if the value\n\
+in @var{reg_raw_mode} is not correct.",
+ fixed_size_mode, (int regno),
+ default_get_reg_raw_mode)
+
+/* Return a mode wide enough to copy any argument value that might be
+ passed. */
+DEFHOOK
+(get_raw_arg_mode,
+ "This target hook returns the mode to be used when accessing raw argument\n\
+registers in @code{__builtin_apply_args}. Define this macro if the value\n\
+in @var{reg_raw_mode} is not correct.",
+ fixed_size_mode, (int regno),
+ default_get_reg_raw_mode)
+
+/* Return true if a type is an empty record. */
+DEFHOOK
+(empty_record_p,
+ "This target hook returns true if the type is an empty record. The default\n\
+is to return @code{false}.",
+ bool, (const_tree type),
+ hook_bool_const_tree_false)
+
+/* Warn about the change in empty class parameter passing ABI. */
+DEFHOOK
+(warn_parameter_passing_abi,
+ "This target hook warns about the change in empty class parameter passing\n\
+ABI.",
+ void, (cumulative_args_t ca, tree type),
+ hook_void_CUMULATIVE_ARGS_tree)
+
+HOOK_VECTOR_END (calls)
+
+DEFHOOK
+(use_pseudo_pic_reg,
+ "This hook should return 1 in case pseudo register should be created\n\
+for pic_offset_table_rtx during function expand.",
+ bool, (void),
+ hook_bool_void_false)
+
+DEFHOOK
+(init_pic_reg,
+ "Perform a target dependent initialization of pic_offset_table_rtx.\n\
+This hook is called at the start of register allocation.",
+ void, (void),
+ hook_void_void)
+
+/* Return the diagnostic message string if conversion from FROMTYPE
+ to TOTYPE is not allowed, NULL otherwise. */
+DEFHOOK
+(invalid_conversion,
+ "If defined, this macro returns the diagnostic message when it is\n\
+invalid to convert from @var{fromtype} to @var{totype}, or @code{NULL}\n\
+if validity should be determined by the front end.",
+ const char *, (const_tree fromtype, const_tree totype),
+ hook_constcharptr_const_tree_const_tree_null)
+
+/* Return the diagnostic message string if the unary operation OP is
+ not permitted on TYPE, NULL otherwise. */
+DEFHOOK
+(invalid_unary_op,
+ "If defined, this macro returns the diagnostic message when it is\n\
+invalid to apply operation @var{op} (where unary plus is denoted by\n\
+@code{CONVERT_EXPR}) to an operand of type @var{type}, or @code{NULL}\n\
+if validity should be determined by the front end.",
+ const char *, (int op, const_tree type),
+ hook_constcharptr_int_const_tree_null)
+
+/* Return the diagnostic message string if the binary operation OP
+ is not permitted on TYPE1 and TYPE2, NULL otherwise. */
+DEFHOOK
+(invalid_binary_op,
+ "If defined, this macro returns the diagnostic message when it is\n\
+invalid to apply operation @var{op} to operands of types @var{type1}\n\
+and @var{type2}, or @code{NULL} if validity should be determined by\n\
+the front end.",
+ const char *, (int op, const_tree type1, const_tree type2),
+ hook_constcharptr_int_const_tree_const_tree_null)
+
+/* If values of TYPE are promoted to some other type when used in
+ expressions (analogous to the integer promotions), return that type,
+ or NULL_TREE otherwise. */
+DEFHOOK
+(promoted_type,
+ "If defined, this target hook returns the type to which values of\n\
+@var{type} should be promoted when they appear in expressions,\n\
+analogous to the integer promotions, or @code{NULL_TREE} to use the\n\
+front end's normal promotion rules. This hook is useful when there are\n\
+target-specific types with special promotion rules.\n\
+This is currently used only by the C and C++ front ends.",
+ tree, (const_tree type),
+ hook_tree_const_tree_null)
+
+/* Convert EXPR to TYPE, if target-specific types with special conversion
+ rules are involved. Return the converted expression, or NULL to apply
+ the standard conversion rules. */
+DEFHOOK
+(convert_to_type,
+ "If defined, this hook returns the result of converting @var{expr} to\n\
+@var{type}. It should return the converted expression,\n\
+or @code{NULL_TREE} to apply the front end's normal conversion rules.\n\
+This hook is useful when there are target-specific types with special\n\
+conversion rules.\n\
+This is currently used only by the C and C++ front ends.",
+ tree, (tree type, tree expr),
+ hook_tree_tree_tree_null)
+
+DEFHOOK
+(verify_type_context,
+ "If defined, this hook returns false if there is a target-specific reason\n\
+why type @var{type} cannot be used in the source language context described\n\
+by @var{context}. When @var{silent_p} is false, the hook also reports an\n\
+error against @var{loc} for invalid uses of @var{type}.\n\
+\n\
+Calls to this hook should be made through the global function\n\
+@code{verify_type_context}, which makes the @var{silent_p} parameter\n\
+default to false and also handles @code{error_mark_node}.\n\
+\n\
+The default implementation always returns true.",
+ bool, (location_t loc, type_context_kind context, const_tree type,
+ bool silent_p),
+ NULL)
+
+DEFHOOK
+(can_change_mode_class,
+ "This hook returns true if it is possible to bitcast values held in\n\
+registers of class @var{rclass} from mode @var{from} to mode @var{to}\n\
+and if doing so preserves the low-order bits that are common to both modes.\n\
+The result is only meaningful if @var{rclass} has registers that can hold\n\
+both @code{from} and @code{to}. The default implementation returns true.\n\
+\n\
+As an example of when such bitcasting is invalid, loading 32-bit integer or\n\
+floating-point objects into floating-point registers on Alpha extends them\n\
+to 64 bits. Therefore loading a 64-bit object and then storing it as a\n\
+32-bit object does not store the low-order 32 bits, as would be the case\n\
+for a normal register. Therefore, @file{alpha.h} defines\n\
+@code{TARGET_CAN_CHANGE_MODE_CLASS} to return:\n\
+\n\
+@smallexample\n\
+(GET_MODE_SIZE (from) == GET_MODE_SIZE (to)\n\
+ || !reg_classes_intersect_p (FLOAT_REGS, rclass))\n\
+@end smallexample\n\
+\n\
+Even if storing from a register in mode @var{to} would be valid,\n\
+if both @var{from} and @code{raw_reg_mode} for @var{rclass} are wider\n\
+than @code{word_mode}, then we must prevent @var{to} narrowing the\n\
+mode. This happens when the middle-end assumes that it can load\n\
+or store pieces of an @var{N}-word pseudo, and that the pseudo will\n\
+eventually be allocated to @var{N} @code{word_mode} hard registers.\n\
+Failure to prevent this kind of mode change will result in the\n\
+entire @code{raw_reg_mode} being modified instead of the partial\n\
+value that the middle-end intended.",
+ bool, (machine_mode from, machine_mode to, reg_class_t rclass),
+ hook_bool_mode_mode_reg_class_t_true)
+
+/* Change pseudo allocno class calculated by IRA. */
+DEFHOOK
+(ira_change_pseudo_allocno_class,
+ "A target hook which can change allocno class for given pseudo from\n\
+ allocno and best class calculated by IRA.\n\
+ \n\
+ The default version of this target hook always returns given class.",
+ reg_class_t, (int, reg_class_t, reg_class_t),
+ default_ira_change_pseudo_allocno_class)
+
+/* Return true if we use LRA instead of reload. */
+DEFHOOK
+(lra_p,
+ "A target hook which returns true if we use LRA instead of reload pass.\n\
+\n\
+The default version of this target hook returns true. New ports\n\
+should use LRA, and existing ports are encouraged to convert.",
+ bool, (void),
+ default_lra_p)
+
+/* Return register priority of given hard regno for the current target. */
+DEFHOOK
+(register_priority,
+ "A target hook which returns the register priority number to which the\n\
+register @var{hard_regno} belongs to. The bigger the number, the\n\
+more preferable the hard register usage (when all other conditions are\n\
+the same). This hook can be used to prefer some hard register over\n\
+others in LRA. For example, some x86-64 register usage needs\n\
+additional prefix which makes instructions longer. The hook can\n\
+return lower priority number for such registers make them less favorable\n\
+and as result making the generated code smaller.\n\
+\n\
+The default version of this target hook returns always zero.",
+ int, (int),
+ default_register_priority)
+
+/* Return true if we need register usage leveling. */
+DEFHOOK
+(register_usage_leveling_p,
+ "A target hook which returns true if we need register usage leveling.\n\
+That means if a few hard registers are equally good for the\n\
+assignment, we choose the least used hard register. The register\n\
+usage leveling may be profitable for some targets. Don't use the\n\
+usage leveling for targets with conditional execution or targets\n\
+with big register files as it hurts if-conversion and cross-jumping\n\
+optimizations.\n\
+\n\
+The default version of this target hook returns always false.",
+ bool, (void),
+ default_register_usage_leveling_p)
+
+/* Return true if maximal address displacement can be different. */
+DEFHOOK
+(different_addr_displacement_p,
+ "A target hook which returns true if an address with the same structure\n\
+can have different maximal legitimate displacement. For example, the\n\
+displacement can depend on memory mode or on operand combinations in\n\
+the insn.\n\
+\n\
+The default version of this target hook returns always false.",
+ bool, (void),
+ default_different_addr_displacement_p)
+
+/* Determine class for spilling pseudos of given mode into registers
+ instead of memory. */
+DEFHOOK
+(spill_class,
+ "This hook defines a class of registers which could be used for spilling\n\
+pseudos of the given mode and class, or @code{NO_REGS} if only memory\n\
+should be used. Not defining this hook is equivalent to returning\n\
+@code{NO_REGS} for all inputs.",
+ reg_class_t, (reg_class_t, machine_mode),
+ NULL)
+
+/* Determine an additional allocno class. */
+DEFHOOK
+(additional_allocno_class_p,
+ "This hook should return @code{true} if given class of registers should\n\
+be an allocno class in any way. Usually RA uses only one register\n\
+class from all classes containing the same register set. In some\n\
+complicated cases, you need to have two or more such classes as\n\
+allocno ones for RA correct work. Not defining this hook is\n\
+equivalent to returning @code{false} for all inputs.",
+ bool, (reg_class_t),
+ hook_bool_reg_class_t_false)
+
+DEFHOOK
+(cstore_mode,
+ "This hook defines the machine mode to use for the boolean result of\n\
+conditional store patterns. The ICODE argument is the instruction code\n\
+for the cstore being performed. Not definiting this hook is the same\n\
+as accepting the mode encoded into operand 0 of the cstore expander\n\
+patterns.",
+ scalar_int_mode, (enum insn_code icode),
+ default_cstore_mode)
+
+/* This target hook allows the backend to compute the register pressure
+ classes to use. */
+DEFHOOK
+(compute_pressure_classes,
+ "A target hook which lets a backend compute the set of pressure classes to\n\
+be used by those optimization passes which take register pressure into\n\
+account, as opposed to letting IRA compute them. It returns the number of\n\
+register classes stored in the array @var{pressure_classes}.",
+ int, (enum reg_class *pressure_classes), NULL)
+
+/* True if a structure, union or array with MODE containing FIELD should
+ be accessed using BLKmode. */
+DEFHOOK
+(member_type_forces_blk,
+ "Return true if a structure, union or array containing @var{field} should\n\
+be accessed using @code{BLKMODE}.\n\
+\n\
+If @var{field} is the only field in the structure, @var{mode} is its\n\
+mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the\n\
+case where structures of one field would require the structure's mode to\n\
+retain the field's mode.\n\
+\n\
+Normally, this is not needed.",
+ bool, (const_tree field, machine_mode mode),
+ default_member_type_forces_blk)
+
+/* See tree-ssa-math-opts.cc:divmod_candidate_p for conditions
+ that gate the divod transform. */
+DEFHOOK
+(expand_divmod_libfunc,
+ "Define this hook for enabling divmod transform if the port does not have\n\
+hardware divmod insn but defines target-specific divmod libfuncs.",
+ void, (rtx libfunc, machine_mode mode, rtx op0, rtx op1, rtx *quot, rtx *rem),
+ NULL)
+
+/* Return the class for a secondary reload, and fill in extra information. */
+DEFHOOK
+(secondary_reload,
+ "Many machines have some registers that cannot be copied directly to or\n\
+from memory or even from other types of registers. An example is the\n\
+@samp{MQ} register, which on most machines, can only be copied to or\n\
+from general registers, but not memory. Below, we shall be using the\n\
+term 'intermediate register' when a move operation cannot be performed\n\
+directly, but has to be done by copying the source into the intermediate\n\
+register first, and then copying the intermediate register to the\n\
+destination. An intermediate register always has the same mode as\n\
+source and destination. Since it holds the actual value being copied,\n\
+reload might apply optimizations to re-use an intermediate register\n\
+and eliding the copy from the source when it can determine that the\n\
+intermediate register still holds the required value.\n\
+\n\
+Another kind of secondary reload is required on some machines which\n\
+allow copying all registers to and from memory, but require a scratch\n\
+register for stores to some memory locations (e.g., those with symbolic\n\
+address on the RT, and those with certain symbolic address on the SPARC\n\
+when compiling PIC)@. Scratch registers need not have the same mode\n\
+as the value being copied, and usually hold a different value than\n\
+that being copied. Special patterns in the md file are needed to\n\
+describe how the copy is performed with the help of the scratch register;\n\
+these patterns also describe the number, register class(es) and mode(s)\n\
+of the scratch register(s).\n\
+\n\
+In some cases, both an intermediate and a scratch register are required.\n\
+\n\
+For input reloads, this target hook is called with nonzero @var{in_p},\n\
+and @var{x} is an rtx that needs to be copied to a register of class\n\
+@var{reload_class} in @var{reload_mode}. For output reloads, this target\n\
+hook is called with zero @var{in_p}, and a register of class @var{reload_class}\n\
+needs to be copied to rtx @var{x} in @var{reload_mode}.\n\
+\n\
+If copying a register of @var{reload_class} from/to @var{x} requires\n\
+an intermediate register, the hook @code{secondary_reload} should\n\
+return the register class required for this intermediate register.\n\
+If no intermediate register is required, it should return NO_REGS.\n\
+If more than one intermediate register is required, describe the one\n\
+that is closest in the copy chain to the reload register.\n\
+\n\
+If scratch registers are needed, you also have to describe how to\n\
+perform the copy from/to the reload register to/from this\n\
+closest intermediate register. Or if no intermediate register is\n\
+required, but still a scratch register is needed, describe the\n\
+copy from/to the reload register to/from the reload operand @var{x}.\n\
+\n\
+You do this by setting @code{sri->icode} to the instruction code of a pattern\n\
+in the md file which performs the move. Operands 0 and 1 are the output\n\
+and input of this copy, respectively. Operands from operand 2 onward are\n\
+for scratch operands. These scratch operands must have a mode, and a\n\
+single-register-class\n\
+@c [later: or memory]\n\
+output constraint.\n\
+\n\
+When an intermediate register is used, the @code{secondary_reload}\n\
+hook will be called again to determine how to copy the intermediate\n\
+register to/from the reload operand @var{x}, so your hook must also\n\
+have code to handle the register class of the intermediate operand.\n\
+\n\
+@c [For later: maybe we'll allow multi-alternative reload patterns -\n\
+@c the port maintainer could name a mov<mode> pattern that has clobbers -\n\
+@c and match the constraints of input and output to determine the required\n\
+@c alternative. A restriction would be that constraints used to match\n\
+@c against reloads registers would have to be written as register class\n\
+@c constraints, or we need a new target macro / hook that tells us if an\n\
+@c arbitrary constraint can match an unknown register of a given class.\n\
+@c Such a macro / hook would also be useful in other places.]\n\
+\n\
+\n\
+@var{x} might be a pseudo-register or a @code{subreg} of a\n\
+pseudo-register, which could either be in a hard register or in memory.\n\
+Use @code{true_regnum} to find out; it will return @minus{}1 if the pseudo is\n\
+in memory and the hard register number if it is in a register.\n\
+\n\
+Scratch operands in memory (constraint @code{\"=m\"} / @code{\"=&m\"}) are\n\
+currently not supported. For the time being, you will have to continue\n\
+to use @code{TARGET_SECONDARY_MEMORY_NEEDED} for that purpose.\n\
+\n\
+@code{copy_cost} also uses this target hook to find out how values are\n\
+copied. If you want it to include some extra cost for the need to allocate\n\
+(a) scratch register(s), set @code{sri->extra_cost} to the additional cost.\n\
+Or if two dependent moves are supposed to have a lower cost than the sum\n\
+of the individual moves due to expected fortuitous scheduling and/or special\n\
+forwarding logic, you can set @code{sri->extra_cost} to a negative amount.",
+ reg_class_t,
+ (bool in_p, rtx x, reg_class_t reload_class, machine_mode reload_mode,
+ secondary_reload_info *sri),
+ default_secondary_reload)
+
+DEFHOOK
+(secondary_memory_needed,
+ "Certain machines have the property that some registers cannot be copied\n\
+to some other registers without using memory. Define this hook on\n\
+those machines to return true if objects of mode @var{m} in registers\n\
+of @var{class1} can only be copied to registers of class @var{class2} by\n\
+ storing a register of @var{class1} into memory and loading that memory\n\
+location into a register of @var{class2}. The default definition returns\n\
+false for all inputs.",
+ bool, (machine_mode mode, reg_class_t class1, reg_class_t class2),
+ hook_bool_mode_reg_class_t_reg_class_t_false)
+
+DEFHOOK
+(secondary_memory_needed_mode,
+ "If @code{TARGET_SECONDARY_MEMORY_NEEDED} tells the compiler to use memory\n\
+when moving between two particular registers of mode @var{mode},\n\
+this hook specifies the mode that the memory should have.\n\
+\n\
+The default depends on @code{TARGET_LRA_P}. Without LRA, the default\n\
+is to use a word-sized mode for integral modes that are smaller than a\n\
+a word. This is right thing to do on most machines because it ensures\n\
+that all bits of the register are copied and prevents accesses to the\n\
+registers in a narrower mode, which some machines prohibit for\n\
+floating-point registers.\n\
+\n\
+However, this default behavior is not correct on some machines, such as\n\
+the DEC Alpha, that store short integers in floating-point registers\n\
+differently than in integer registers. On those machines, the default\n\
+widening will not work correctly and you must define this hook to\n\
+suppress that widening in some cases. See the file @file{alpha.cc} for\n\
+details.\n\
+\n\
+With LRA, the default is to use @var{mode} unmodified.",
+ machine_mode, (machine_mode mode),
+ default_secondary_memory_needed_mode)
+
+/* Given an rtx X being reloaded into a reg required to be in class CLASS,
+ return the class of reg to actually use. */
+DEFHOOK
+(preferred_reload_class,
+ "A target hook that places additional restrictions on the register class\n\
+to use when it is necessary to copy value @var{x} into a register in class\n\
+@var{rclass}. The value is a register class; perhaps @var{rclass}, or perhaps\n\
+another, smaller class.\n\
+\n\
+The default version of this hook always returns value of @code{rclass} argument.\n\
+\n\
+Sometimes returning a more restrictive class makes better code. For\n\
+example, on the 68000, when @var{x} is an integer constant that is in range\n\
+for a @samp{moveq} instruction, the value of this macro is always\n\
+@code{DATA_REGS} as long as @var{rclass} includes the data registers.\n\
+Requiring a data register guarantees that a @samp{moveq} will be used.\n\
+\n\
+One case where @code{TARGET_PREFERRED_RELOAD_CLASS} must not return\n\
+@var{rclass} is if @var{x} is a legitimate constant which cannot be\n\
+loaded into some register class. By returning @code{NO_REGS} you can\n\
+force @var{x} into a memory location. For example, rs6000 can load\n\
+immediate values into general-purpose registers, but does not have an\n\
+instruction for loading an immediate value into a floating-point\n\
+register, so @code{TARGET_PREFERRED_RELOAD_CLASS} returns @code{NO_REGS} when\n\
+@var{x} is a floating-point constant. If the constant can't be loaded\n\
+into any kind of register, code generation will be better if\n\
+@code{TARGET_LEGITIMATE_CONSTANT_P} makes the constant illegitimate instead\n\
+of using @code{TARGET_PREFERRED_RELOAD_CLASS}.\n\
+\n\
+If an insn has pseudos in it after register allocation, reload will go\n\
+through the alternatives and call repeatedly @code{TARGET_PREFERRED_RELOAD_CLASS}\n\
+to find the best one. Returning @code{NO_REGS}, in this case, makes\n\
+reload add a @code{!} in front of the constraint: the x86 back-end uses\n\
+this feature to discourage usage of 387 registers when math is done in\n\
+the SSE registers (and vice versa).",
+ reg_class_t,
+ (rtx x, reg_class_t rclass),
+ default_preferred_reload_class)
+
+/* Like TARGET_PREFERRED_RELOAD_CLASS, but for output reloads instead of
+ input reloads. */
+DEFHOOK
+(preferred_output_reload_class,
+ "Like @code{TARGET_PREFERRED_RELOAD_CLASS}, but for output reloads instead of\n\
+input reloads.\n\
+\n\
+The default version of this hook always returns value of @code{rclass}\n\
+argument.\n\
+\n\
+You can also use @code{TARGET_PREFERRED_OUTPUT_RELOAD_CLASS} to discourage\n\
+reload from using some alternatives, like @code{TARGET_PREFERRED_RELOAD_CLASS}.",
+ reg_class_t,
+ (rtx x, reg_class_t rclass),
+ default_preferred_output_reload_class)
+
+DEFHOOK
+(select_early_remat_modes,
+ "On some targets, certain modes cannot be held in registers around a\n\
+standard ABI call and are relatively expensive to spill to the stack.\n\
+The early rematerialization pass can help in such cases by aggressively\n\
+recomputing values after calls, so that they don't need to be spilled.\n\
+\n\
+This hook returns the set of such modes by setting the associated bits\n\
+in @var{modes}. The default implementation selects no modes, which has\n\
+the effect of disabling the early rematerialization pass.",
+ void, (sbitmap modes),
+ default_select_early_remat_modes)
+
+DEFHOOK
+(class_likely_spilled_p,
+ "A target hook which returns @code{true} if pseudos that have been assigned\n\
+to registers of class @var{rclass} would likely be spilled because\n\
+registers of @var{rclass} are needed for spill registers.\n\
+\n\
+The default version of this target hook returns @code{true} if @var{rclass}\n\
+has exactly one register and @code{false} otherwise. On most machines, this\n\
+default should be used. For generally register-starved machines, such as\n\
+i386, or machines with right register constraints, such as SH, this hook\n\
+can be used to avoid excessive spilling.\n\
+\n\
+This hook is also used by some of the global intra-procedural code\n\
+transformations to throtle code motion, to avoid increasing register\n\
+pressure.",
+ bool, (reg_class_t rclass),
+ default_class_likely_spilled_p)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class RCLASS. */
+DEFHOOK
+(class_max_nregs,
+ "A target hook returns the maximum number of consecutive registers\n\
+of class @var{rclass} needed to hold a value of mode @var{mode}.\n\
+\n\
+This is closely related to the macro @code{TARGET_HARD_REGNO_NREGS}.\n\
+In fact, the value returned by @code{TARGET_CLASS_MAX_NREGS (@var{rclass},\n\
+@var{mode})} target hook should be the maximum value of\n\
+@code{TARGET_HARD_REGNO_NREGS (@var{regno}, @var{mode})} for all @var{regno}\n\
+values in the class @var{rclass}.\n\
+\n\
+This target hook helps control the handling of multiple-word values\n\
+in the reload pass.\n\
+\n\
+The default version of this target hook returns the size of @var{mode}\n\
+in words.",
+ unsigned char, (reg_class_t rclass, machine_mode mode),
+ default_class_max_nregs)
+
+DEFHOOK
+(preferred_rename_class,
+ "A target hook that places additional preference on the register\n\
+class to use when it is necessary to rename a register in class\n\
+@var{rclass} to another class, or perhaps @var{NO_REGS}, if no\n\
+preferred register class is found or hook @code{preferred_rename_class}\n\
+is not implemented.\n\
+Sometimes returning a more restrictive class makes better code. For\n\
+example, on ARM, thumb-2 instructions using @code{LO_REGS} may be\n\
+smaller than instructions using @code{GENERIC_REGS}. By returning\n\
+@code{LO_REGS} from @code{preferred_rename_class}, code size can\n\
+be reduced.",
+ reg_class_t, (reg_class_t rclass),
+ default_preferred_rename_class)
+
+/* This target hook allows the backend to avoid unsafe substitution
+ during register allocation. */
+DEFHOOK
+(cannot_substitute_mem_equiv_p,
+ "A target hook which returns @code{true} if @var{subst} can't\n\
+substitute safely pseudos with equivalent memory values during\n\
+register allocation.\n\
+The default version of this target hook returns @code{false}.\n\
+On most machines, this default should be used. For generally\n\
+machines with non orthogonal register usage for addressing, such\n\
+as SH, this hook can be used to avoid excessive spilling.",
+ bool, (rtx subst),
+ hook_bool_rtx_false)
+
+/* This target hook allows the backend to legitimize base plus
+ displacement addressing. */
+DEFHOOK
+(legitimize_address_displacement,
+ "This hook tries to split address offset @var{orig_offset} into\n\
+two parts: one that should be added to the base address to create\n\
+a local anchor point, and an additional offset that can be applied\n\
+to the anchor to address a value of mode @var{mode}. The idea is that\n\
+the local anchor could be shared by other accesses to nearby locations.\n\
+\n\
+The hook returns true if it succeeds, storing the offset of the\n\
+anchor from the base in @var{offset1} and the offset of the final address\n\
+from the anchor in @var{offset2}. The default implementation returns false.",
+ bool, (rtx *offset1, rtx *offset2, poly_int64 orig_offset, machine_mode mode),
+ default_legitimize_address_displacement)
+
+/* This target hook allows the backend to perform additional
+ processing while initializing for variable expansion. */
+DEFHOOK
+(expand_to_rtl_hook,
+ "This hook is called just before expansion into rtl, allowing the target\n\
+to perform additional initializations or analysis before the expansion.\n\
+For example, the rs6000 port uses it to allocate a scratch stack slot\n\
+for use in copying SDmode values between memory and floating point\n\
+registers whenever the function being expanded has any SDmode\n\
+usage.",
+ void, (void),
+ hook_void_void)
+
+/* This target hook allows the backend to perform additional
+ instantiations on rtx that are not actually in insns yet,
+ but will be later. */
+DEFHOOK
+(instantiate_decls,
+ "This hook allows the backend to perform additional instantiations on rtl\n\
+that are not actually in any insns yet, but will be later.",
+ void, (void),
+ hook_void_void)
+
+DEFHOOK
+(hard_regno_nregs,
+ "This hook returns the number of consecutive hard registers, starting\n\
+at register number @var{regno}, required to hold a value of mode\n\
+@var{mode}. This hook must never return zero, even if a register\n\
+cannot hold the requested mode - indicate that with\n\
+@code{TARGET_HARD_REGNO_MODE_OK} and/or\n\
+@code{TARGET_CAN_CHANGE_MODE_CLASS} instead.\n\
+\n\
+The default definition returns the number of words in @var{mode}.",
+ unsigned int, (unsigned int regno, machine_mode mode),
+ default_hard_regno_nregs)
+
+DEFHOOK
+(hard_regno_mode_ok,
+ "This hook returns true if it is permissible to store a value\n\
+of mode @var{mode} in hard register number @var{regno} (or in several\n\
+registers starting with that one). The default definition returns true\n\
+unconditionally.\n\
+\n\
+You need not include code to check for the numbers of fixed registers,\n\
+because the allocation mechanism considers them to be always occupied.\n\
+\n\
+@cindex register pairs\n\
+On some machines, double-precision values must be kept in even/odd\n\
+register pairs. You can implement that by defining this hook to reject\n\
+odd register numbers for such modes.\n\
+\n\
+The minimum requirement for a mode to be OK in a register is that the\n\
+@samp{mov@var{mode}} instruction pattern support moves between the\n\
+register and other hard register in the same class and that moving a\n\
+value into the register and back out not alter it.\n\
+\n\
+Since the same instruction used to move @code{word_mode} will work for\n\
+all narrower integer modes, it is not necessary on any machine for\n\
+this hook to distinguish between these modes, provided you define\n\
+patterns @samp{movhi}, etc., to take advantage of this. This is\n\
+useful because of the interaction between @code{TARGET_HARD_REGNO_MODE_OK}\n\
+and @code{TARGET_MODES_TIEABLE_P}; it is very desirable for all integer\n\
+modes to be tieable.\n\
+\n\
+Many machines have special registers for floating point arithmetic.\n\
+Often people assume that floating point machine modes are allowed only\n\
+in floating point registers. This is not true. Any registers that\n\
+can hold integers can safely @emph{hold} a floating point machine\n\
+mode, whether or not floating arithmetic can be done on it in those\n\
+registers. Integer move instructions can be used to move the values.\n\
+\n\
+On some machines, though, the converse is true: fixed-point machine\n\
+modes may not go in floating registers. This is true if the floating\n\
+registers normalize any value stored in them, because storing a\n\
+non-floating value there would garble it. In this case,\n\
+@code{TARGET_HARD_REGNO_MODE_OK} should reject fixed-point machine modes in\n\
+floating registers. But if the floating registers do not automatically\n\
+normalize, if you can store any bit pattern in one and retrieve it\n\
+unchanged without a trap, then any machine mode may go in a floating\n\
+register, so you can define this hook to say so.\n\
+\n\
+The primary significance of special floating registers is rather that\n\
+they are the registers acceptable in floating point arithmetic\n\
+instructions. However, this is of no concern to\n\
+@code{TARGET_HARD_REGNO_MODE_OK}. You handle it by writing the proper\n\
+constraints for those instructions.\n\
+\n\
+On some machines, the floating registers are especially slow to access,\n\
+so that it is better to store a value in a stack frame than in such a\n\
+register if floating point arithmetic is not being done. As long as the\n\
+floating registers are not in class @code{GENERAL_REGS}, they will not\n\
+be used unless some pattern's constraint asks for one.",
+ bool, (unsigned int regno, machine_mode mode),
+ hook_bool_uint_mode_true)
+
+DEFHOOK
+(modes_tieable_p,
+ "This hook returns true if a value of mode @var{mode1} is accessible\n\
+in mode @var{mode2} without copying.\n\
+\n\
+If @code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode1})} and\n\
+@code{TARGET_HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are always\n\
+the same for any @var{r}, then\n\
+@code{TARGET_MODES_TIEABLE_P (@var{mode1}, @var{mode2})}\n\
+should be true. If they differ for any @var{r}, you should define\n\
+this hook to return false unless some other mechanism ensures the\n\
+accessibility of the value in a narrower mode.\n\
+\n\
+You should define this hook to return true in as many cases as\n\
+possible since doing so will allow GCC to perform better register\n\
+allocation. The default definition returns true unconditionally.",
+ bool, (machine_mode mode1, machine_mode mode2),
+ hook_bool_mode_mode_true)
+
+/* Return true if is OK to use a hard register REGNO as scratch register
+ in peephole2. */
+DEFHOOK
+(hard_regno_scratch_ok,
+ "This target hook should return @code{true} if it is OK to use a hard register\n\
+@var{regno} as scratch reg in peephole2.\n\
+\n\
+One common use of this macro is to prevent using of a register that\n\
+is not saved by a prologue in an interrupt handler.\n\
+\n\
+The default version of this hook always returns @code{true}.",
+ bool, (unsigned int regno),
+ default_hard_regno_scratch_ok)
+
+DEFHOOK
+(hard_regno_call_part_clobbered,
+ "ABIs usually specify that calls must preserve the full contents\n\
+of a particular register, or that calls can alter any part of a\n\
+particular register. This information is captured by the target macro\n\
+@code{CALL_REALLY_USED_REGISTERS}. However, some ABIs specify that calls\n\
+must preserve certain bits of a particular register but can alter others.\n\
+This hook should return true if this applies to at least one of the\n\
+registers in @samp{(reg:@var{mode} @var{regno})}, and if as a result the\n\
+call would alter part of the @var{mode} value. For example, if a call\n\
+preserves the low 32 bits of a 64-bit hard register @var{regno} but can\n\
+clobber the upper 32 bits, this hook should return true for a 64-bit mode\n\
+but false for a 32-bit mode.\n\
+\n\
+The value of @var{abi_id} comes from the @code{predefined_function_abi}\n\
+structure that describes the ABI of the call; see the definition of the\n\
+structure for more details. If (as is usual) the target uses the same ABI\n\
+for all functions in a translation unit, @var{abi_id} is always 0.\n\
+\n\
+The default implementation returns false, which is correct\n\
+for targets that don't have partly call-clobbered registers.",
+ bool, (unsigned int abi_id, unsigned int regno, machine_mode mode),
+ hook_bool_uint_uint_mode_false)
+
+DEFHOOK
+(get_multilib_abi_name,
+ "This hook returns name of multilib ABI name.",
+ const char *, (void),
+ hook_constcharptr_void_null)
+
+/* Return the smallest number of different values for which it is best to
+ use a jump-table instead of a tree of conditional branches. */
+DEFHOOK
+(case_values_threshold,
+ "This function return the smallest number of different values for which it\n\
+is best to use a jump-table instead of a tree of conditional branches.\n\
+The default is four for machines with a @code{casesi} instruction and\n\
+five otherwise. This is best for most machines.",
+ unsigned int, (void),
+ default_case_values_threshold)
+
+DEFHOOK
+(starting_frame_offset,
+ "This hook returns the offset from the frame pointer to the first local\n\
+variable slot to be allocated. If @code{FRAME_GROWS_DOWNWARD}, it is the\n\
+offset to @emph{end} of the first slot allocated, otherwise it is the\n\
+offset to @emph{beginning} of the first slot allocated. The default\n\
+implementation returns 0.",
+ HOST_WIDE_INT, (void),
+ hook_hwi_void_0)
+
+/* Optional callback to advise the target to compute the frame layout. */
+DEFHOOK
+(compute_frame_layout,
+ "This target hook is called once each time the frame layout needs to be\n\
+recalculated. The calculations can be cached by the target and can then\n\
+be used by @code{INITIAL_ELIMINATION_OFFSET} instead of re-computing the\n\
+layout on every invocation of that hook. This is particularly useful\n\
+for targets that have an expensive frame layout function. Implementing\n\
+this callback is optional.",
+ void, (void),
+ hook_void_void)
+
+/* Return true if a function must have and use a frame pointer. */
+DEFHOOK
+(frame_pointer_required,
+ "This target hook should return @code{true} if a function must have and use\n\
+a frame pointer. This target hook is called in the reload pass. If its return\n\
+value is @code{true} the function will have a frame pointer.\n\
+\n\
+This target hook can in principle examine the current function and decide\n\
+according to the facts, but on most machines the constant @code{false} or the\n\
+constant @code{true} suffices. Use @code{false} when the machine allows code\n\
+to be generated with no frame pointer, and doing so saves some time or space.\n\
+Use @code{true} when there is no possible advantage to avoiding a frame\n\
+pointer.\n\
+\n\
+In certain cases, the compiler does not know how to produce valid code\n\
+without a frame pointer. The compiler recognizes those cases and\n\
+automatically gives the function a frame pointer regardless of what\n\
+@code{targetm.frame_pointer_required} returns. You don't need to worry about\n\
+them.\n\
+\n\
+In a function that does not require a frame pointer, the frame pointer\n\
+register can be allocated for ordinary usage, unless you mark it as a\n\
+fixed register. See @code{FIXED_REGISTERS} for more information.\n\
+\n\
+Default return value is @code{false}.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Returns true if the compiler is allowed to try to replace register number
+ from-reg with register number to-reg. */
+DEFHOOK
+(can_eliminate,
+ "This target hook should return @code{true} if the compiler is allowed to\n\
+try to replace register number @var{from_reg} with register number\n\
+@var{to_reg}. This target hook will usually be @code{true}, since most of the\n\
+cases preventing register elimination are things that the compiler already\n\
+knows about.\n\
+\n\
+Default return value is @code{true}.",
+ bool, (const int from_reg, const int to_reg),
+ hook_bool_const_int_const_int_true)
+
+/* Modify any or all of fixed_regs, call_used_regs, global_regs,
+ reg_names, and reg_class_contents to account of the vagaries of the
+ target. */
+DEFHOOK
+(conditional_register_usage,
+ "This hook may conditionally modify five variables\n\
+@code{fixed_regs}, @code{call_used_regs}, @code{global_regs},\n\
+@code{reg_names}, and @code{reg_class_contents}, to take into account\n\
+any dependence of these register sets on target flags. The first three\n\
+of these are of type @code{char []} (interpreted as boolean vectors).\n\
+@code{global_regs} is a @code{const char *[]}, and\n\
+@code{reg_class_contents} is a @code{HARD_REG_SET}. Before the macro is\n\
+called, @code{fixed_regs}, @code{call_used_regs},\n\
+@code{reg_class_contents}, and @code{reg_names} have been initialized\n\
+from @code{FIXED_REGISTERS}, @code{CALL_USED_REGISTERS},\n\
+@code{REG_CLASS_CONTENTS}, and @code{REGISTER_NAMES}, respectively.\n\
+@code{global_regs} has been cleared, and any @option{-ffixed-@var{reg}},\n\
+@option{-fcall-used-@var{reg}} and @option{-fcall-saved-@var{reg}}\n\
+command options have been applied.\n\
+\n\
+@cindex disabling certain registers\n\
+@cindex controlling register usage\n\
+If the usage of an entire class of registers depends on the target\n\
+flags, you may indicate this to GCC by using this macro to modify\n\
+@code{fixed_regs} and @code{call_used_regs} to 1 for each of the\n\
+registers in the classes which should not be used by GCC@. Also make\n\
+@code{define_register_constraint}s return @code{NO_REGS} for constraints\n\
+that shouldn't be used.\n\
+\n\
+(However, if this class is not included in @code{GENERAL_REGS} and all\n\
+of the insn patterns whose constraints permit this class are\n\
+controlled by target switches, then GCC will automatically avoid using\n\
+these registers when the target switches are opposed to them.)",
+ void, (void),
+ hook_void_void)
+
+DEFHOOK
+(stack_clash_protection_alloca_probe_range,
+ "Some targets have an ABI defined interval for which no probing needs to be done.\n\
+When a probe does need to be done this same interval is used as the probe distance\n\
+up when doing stack clash protection for alloca.\n\
+On such targets this value can be set to override the default probing up interval.\n\
+Define this variable to return nonzero if such a probe range is required or zero otherwise.\n\
+Defining this hook also requires your functions which make use of alloca to have at least 8 byes\n\
+of outgoing arguments. If this is not the case the stack will be corrupted.\n\
+You need not define this macro if it would always have the value zero.",
+ HOST_WIDE_INT, (void),
+ default_stack_clash_protection_alloca_probe_range)
+
+
+/* Functions specific to the C family of frontends. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_C_"
+HOOK_VECTOR (TARGET_C, c)
+
+/* ??? Documenting this hook requires a GFDL license grant. */
+DEFHOOK_UNDOC
+(mode_for_suffix,
+"Return machine mode for non-standard constant literal suffix @var{c},\
+ or VOIDmode if non-standard suffixes are unsupported.",
+ machine_mode, (char c),
+ default_mode_for_suffix)
+
+DEFHOOK
+(excess_precision,
+ "Return a value, with the same meaning as the C99 macro\n\
+@code{FLT_EVAL_METHOD} that describes which excess precision should be\n\
+applied. @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\n\
+@code{EXCESS_PRECISION_TYPE_FAST},\n\
+@code{EXCESS_PRECISION_TYPE_STANDARD}, or\n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16}. For\n\
+@code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\n\
+precision and range operations will be implictly evaluated in regardless\n\
+of the excess precision explicitly added. For\n\
+@code{EXCESS_PRECISION_TYPE_STANDARD}, \n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16}, and\n\
+@code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\n\
+explicit excess precision that should be added depending on the\n\
+value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.\n\
+Note that unpredictable explicit excess precision does not make sense,\n\
+so a target should never return @code{FLT_EVAL_METHOD_UNPREDICTABLE}\n\
+when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD},\n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16} or\n\
+@code{EXCESS_PRECISION_TYPE_FAST}.",
+ enum flt_eval_method, (enum excess_precision_type type),
+ default_excess_precision)
+
+HOOK_VECTOR_END (c)
+
+/* Functions specific to the C++ frontend. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_CXX_"
+HOOK_VECTOR (TARGET_CXX, cxx)
+
+/* Return the integer type used for guard variables. */
+DEFHOOK
+(guard_type,
+ "Define this hook to override the integer type used for guard variables.\n\
+These are used to implement one-time construction of static objects. The\n\
+default is long_long_integer_type_node.",
+ tree, (void),
+ default_cxx_guard_type)
+
+/* Return true if only the low bit of the guard should be tested. */
+DEFHOOK
+(guard_mask_bit,
+ "This hook determines how guard variables are used. It should return\n\
+@code{false} (the default) if the first byte should be used. A return value of\n\
+@code{true} indicates that only the least significant bit should be used.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Returns the size of the array cookie for an array of type. */
+DEFHOOK
+(get_cookie_size,
+ "This hook returns the size of the cookie to use when allocating an array\n\
+whose elements have the indicated @var{type}. Assumes that it is already\n\
+known that a cookie is needed. The default is\n\
+@code{max(sizeof (size_t), alignof(type))}, as defined in section 2.7 of the\n\
+IA64/Generic C++ ABI@.",
+ tree, (tree type),
+ default_cxx_get_cookie_size)
+
+/* Returns true if the element size should be stored in the array cookie. */
+DEFHOOK
+(cookie_has_size,
+ "This hook should return @code{true} if the element size should be stored in\n\
+array cookies. The default is to return @code{false}.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Allows backends to perform additional processing when
+ deciding if a class should be exported or imported. */
+DEFHOOK
+(import_export_class,
+ "If defined by a backend this hook allows the decision made to export\n\
+class @var{type} to be overruled. Upon entry @var{import_export}\n\
+will contain 1 if the class is going to be exported, @minus{}1 if it is going\n\
+to be imported and 0 otherwise. This function should return the\n\
+modified value and perform any other actions necessary to support the\n\
+backend's targeted operating system.",
+ int, (tree type, int import_export), NULL)
+
+/* Returns true if constructors and destructors return "this". */
+DEFHOOK
+(cdtor_returns_this,
+ "This hook should return @code{true} if constructors and destructors return\n\
+the address of the object created/destroyed. The default is to return\n\
+@code{false}.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Returns true if the key method for a class can be an inline
+ function, so long as it is not declared inline in the class
+ itself. Returning true is the behavior required by the Itanium C++ ABI. */
+DEFHOOK
+(key_method_may_be_inline,
+ "This hook returns true if the key method for a class (i.e., the method\n\
+which, if defined in the current translation unit, causes the virtual\n\
+table to be emitted) may be an inline function. Under the standard\n\
+Itanium C++ ABI the key method may be an inline function so long as\n\
+the function is not declared inline in the class definition. Under\n\
+some variants of the ABI, an inline function can never be the key\n\
+method. The default is to return @code{true}.",
+ bool, (void),
+ hook_bool_void_true)
+
+DEFHOOK
+(determine_class_data_visibility,
+"@var{decl} is a virtual table, virtual table table, typeinfo object,\n\
+or other similar implicit class data object that will be emitted with\n\
+external linkage in this translation unit. No ELF visibility has been\n\
+explicitly specified. If the target needs to specify a visibility\n\
+other than that of the containing class, use this hook to set\n\
+@code{DECL_VISIBILITY} and @code{DECL_VISIBILITY_SPECIFIED}.",
+ void, (tree decl),
+ hook_void_tree)
+
+/* Returns true (the default) if virtual tables and other
+ similar implicit class data objects are always COMDAT if they
+ have external linkage. If this hook returns false, then
+ class data for classes whose virtual table will be emitted in
+ only one translation unit will not be COMDAT. */
+DEFHOOK
+(class_data_always_comdat,
+ "This hook returns true (the default) if virtual tables and other\n\
+similar implicit class data objects are always COMDAT if they have\n\
+external linkage. If this hook returns false, then class data for\n\
+classes whose virtual table will be emitted in only one translation\n\
+unit will not be COMDAT.",
+ bool, (void),
+ hook_bool_void_true)
+
+/* Returns true (the default) if the RTTI for the basic types,
+ which is always defined in the C++ runtime, should be COMDAT;
+ false if it should not be COMDAT. */
+DEFHOOK
+(library_rtti_comdat,
+ "This hook returns true (the default) if the RTTI information for\n\
+the basic types which is defined in the C++ runtime should always\n\
+be COMDAT, false if it should not be COMDAT.",
+ bool, (void),
+ hook_bool_void_true)
+
+/* Returns true if __aeabi_atexit should be used to register static
+ destructors. */
+DEFHOOK
+(use_aeabi_atexit,
+ "This hook returns true if @code{__aeabi_atexit} (as defined by the ARM EABI)\n\
+should be used to register static destructors when @option{-fuse-cxa-atexit}\n\
+is in effect. The default is to return false to use @code{__cxa_atexit}.",
+ bool, (void),
+ hook_bool_void_false)
+
+/* Returns true if target may use atexit in the same manner as
+ __cxa_atexit to register static destructors. */
+DEFHOOK
+(use_atexit_for_cxa_atexit,
+ "This hook returns true if the target @code{atexit} function can be used\n\
+in the same manner as @code{__cxa_atexit} to register C++ static\n\
+destructors. This requires that @code{atexit}-registered functions in\n\
+shared libraries are run in the correct order when the libraries are\n\
+unloaded. The default is to return false.",
+ bool, (void),
+ hook_bool_void_false)
+
+DEFHOOK
+(adjust_class_at_definition,
+"@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just\n\
+been defined. Use this hook to make adjustments to the class (eg, tweak\n\
+visibility or perform any other required target modifications).",
+ void, (tree type),
+ hook_void_tree)
+
+DEFHOOK
+(decl_mangling_context,
+ "Return target-specific mangling context of @var{decl} or @code{NULL_TREE}.",
+ tree, (const_tree decl),
+ hook_tree_const_tree_null)
+
+HOOK_VECTOR_END (cxx)
+
+/* Functions and data for emulated TLS support. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_EMUTLS_"
+HOOK_VECTOR (TARGET_EMUTLS, emutls)
+
+/* Name of the address and common functions. */
+DEFHOOKPOD
+(get_address,
+ "Contains the name of the helper function that uses a TLS control\n\
+object to locate a TLS instance. The default causes libgcc's\n\
+emulated TLS helper function to be used.",
+ const char *, "__builtin___emutls_get_address")
+
+DEFHOOKPOD
+(register_common,
+ "Contains the name of the helper function that should be used at\n\
+program startup to register TLS objects that are implicitly\n\
+initialized to zero. If this is @code{NULL}, all TLS objects will\n\
+have explicit initializers. The default causes libgcc's emulated TLS\n\
+registration function to be used.",
+ const char *, "__builtin___emutls_register_common")
+
+/* Prefixes for proxy variable and template. */
+DEFHOOKPOD
+(var_section,
+ "Contains the name of the section in which TLS control variables should\n\
+be placed. The default of @code{NULL} allows these to be placed in\n\
+any section.",
+ const char *, NULL)
+
+DEFHOOKPOD
+(tmpl_section,
+ "Contains the name of the section in which TLS initializers should be\n\
+placed. The default of @code{NULL} allows these to be placed in any\n\
+section.",
+ const char *, NULL)
+
+/* Prefixes for proxy variable and template. */
+DEFHOOKPOD
+(var_prefix,
+ "Contains the prefix to be prepended to TLS control variable names.\n\
+The default of @code{NULL} uses a target-specific prefix.",
+ const char *, NULL)
+
+DEFHOOKPOD
+(tmpl_prefix,
+ "Contains the prefix to be prepended to TLS initializer objects. The\n\
+default of @code{NULL} uses a target-specific prefix.",
+ const char *, NULL)
+
+/* Function to generate field definitions of the proxy variable. */
+DEFHOOK
+(var_fields,
+ "Specifies a function that generates the FIELD_DECLs for a TLS control\n\
+object type. @var{type} is the RECORD_TYPE the fields are for and\n\
+@var{name} should be filled with the structure tag, if the default of\n\
+@code{__emutls_object} is unsuitable. The default creates a type suitable\n\
+for libgcc's emulated TLS function.",
+ tree, (tree type, tree *name),
+ default_emutls_var_fields)
+
+/* Function to initialize a proxy variable. */
+DEFHOOK
+(var_init,
+ "Specifies a function that generates the CONSTRUCTOR to initialize a\n\
+TLS control object. @var{var} is the TLS control object, @var{decl}\n\
+is the TLS object and @var{tmpl_addr} is the address of the\n\
+initializer. The default initializes libgcc's emulated TLS control object.",
+ tree, (tree var, tree decl, tree tmpl_addr),
+ default_emutls_var_init)
+
+/* Whether we are allowed to alter the usual alignment of the
+ proxy variable. */
+DEFHOOKPOD
+(var_align_fixed,
+ "Specifies whether the alignment of TLS control variable objects is\n\
+fixed and should not be increased as some backends may do to optimize\n\
+single objects. The default is false.",
+ bool, false)
+
+/* Whether we can emit debug information for TLS vars. */
+DEFHOOKPOD
+(debug_form_tls_address,
+ "Specifies whether a DWARF @code{DW_OP_form_tls_address} location descriptor\n\
+may be used to describe emulated TLS control objects.",
+ bool, false)
+
+HOOK_VECTOR_END (emutls)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_OPTION_"
+HOOK_VECTOR (TARGET_OPTION_HOOKS, target_option_hooks)
+
+/* Function to validate the attribute((target(...))) strings. If
+ the option is validated, the hook should also fill in
+ DECL_FUNCTION_SPECIFIC_TARGET in the function decl node. */
+DEFHOOK
+(valid_attribute_p,
+ "This hook is called to parse @code{attribute(target(\"...\"))}, which\n\
+allows setting target-specific options on individual functions.\n\
+These function-specific options may differ\n\
+from the options specified on the command line. The hook should return\n\
+@code{true} if the options are valid.\n\
+\n\
+The hook should set the @code{DECL_FUNCTION_SPECIFIC_TARGET} field in\n\
+the function declaration to hold a pointer to a target-specific\n\
+@code{struct cl_target_option} structure.",
+ bool, (tree fndecl, tree name, tree args, int flags),
+ default_target_option_valid_attribute_p)
+
+/* Function to save any extra target state in the target options structure. */
+DEFHOOK
+(save,
+ "This hook is called to save any additional target-specific information\n\
+in the @code{struct cl_target_option} structure for function-specific\n\
+options from the @code{struct gcc_options} structure.\n\
+@xref{Option file format}.",
+ void, (struct cl_target_option *ptr, struct gcc_options *opts,
+ struct gcc_options *opts_set), NULL)
+
+/* Function to restore any extra target state from the target options
+ structure. */
+DEFHOOK
+(restore,
+ "This hook is called to restore any additional target-specific\n\
+information in the @code{struct cl_target_option} structure for\n\
+function-specific options to the @code{struct gcc_options} structure.",
+ void, (struct gcc_options *opts, struct gcc_options *opts_set,
+ struct cl_target_option *ptr), NULL)
+
+/* Function to update target-specific option information after being
+ streamed in. */
+DEFHOOK
+(post_stream_in,
+ "This hook is called to update target-specific information in the\n\
+@code{struct cl_target_option} structure after it is streamed in from\n\
+LTO bytecode.",
+ void, (struct cl_target_option *ptr), NULL)
+
+/* Function to print any extra target state from the target options
+ structure. */
+DEFHOOK
+(print,
+ "This hook is called to print any additional target-specific\n\
+information in the @code{struct cl_target_option} structure for\n\
+function-specific options.",
+ void, (FILE *file, int indent, struct cl_target_option *ptr), NULL)
+
+/* Function to parse arguments to be validated for #pragma target, and to
+ change the state if the options are valid. If the first argument is
+ NULL, the second argument specifies the default options to use. Return
+ true if the options are valid, and set the current state. */
+DEFHOOK
+(pragma_parse,
+ "This target hook parses the options for @code{#pragma GCC target}, which\n\
+sets the target-specific options for functions that occur later in the\n\
+input stream. The options accepted should be the same as those handled by the\n\
+@code{TARGET_OPTION_VALID_ATTRIBUTE_P} hook.",
+ bool, (tree args, tree pop_target),
+ default_target_option_pragma_parse)
+
+/* Do option overrides for the target. */
+DEFHOOK
+(override,
+ "Sometimes certain combinations of command options do not make sense on\n\
+a particular target machine. You can override the hook\n\
+@code{TARGET_OPTION_OVERRIDE} to take account of this. This hooks is called\n\
+once just after all the command options have been parsed.\n\
+\n\
+Don't use this hook to turn on various extra optimizations for\n\
+@option{-O}. That is what @code{TARGET_OPTION_OPTIMIZATION} is for.\n\
+\n\
+If you need to do something whenever the optimization level is\n\
+changed via the optimize attribute or pragma, see\n\
+@code{TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE}",
+ void, (void),
+ hook_void_void)
+
+/* This function returns true if DECL1 and DECL2 are versions of the same
+ function. DECL1 and DECL2 are function versions if and only if they
+ have the same function signature and different target specific attributes,
+ that is, they are compiled for different target machines. */
+DEFHOOK
+(function_versions,
+ "This target hook returns @code{true} if @var{DECL1} and @var{DECL2} are\n\
+versions of the same function. @var{DECL1} and @var{DECL2} are function\n\
+versions if and only if they have the same function signature and\n\
+different target specific attributes, that is, they are compiled for\n\
+different target machines.",
+ bool, (tree decl1, tree decl2),
+ hook_bool_tree_tree_false)
+
+/* Function to determine if one function can inline another function. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+DEFHOOK
+(can_inline_p,
+ "This target hook returns @code{false} if the @var{caller} function\n\
+cannot inline @var{callee}, based on target specific information. By\n\
+default, inlining is not allowed if the callee function has function\n\
+specific target options and the caller does not use the same options.",
+ bool, (tree caller, tree callee),
+ default_target_can_inline_p)
+
+DEFHOOK
+(update_ipa_fn_target_info,
+ "Allow target to analyze all gimple statements for the given function to\n\
+record and update some target specific information for inlining. A typical\n\
+example is that a caller with one isa feature disabled is normally not\n\
+allowed to inline a callee with that same isa feature enabled even which is\n\
+attributed by always_inline, but with the conservative analysis on all\n\
+statements of the callee if we are able to guarantee the callee does not\n\
+exploit any instructions from the mismatch isa feature, it would be safe to\n\
+allow the caller to inline the callee.\n\
+@var{info} is one @code{unsigned int} value to record information in which\n\
+one set bit indicates one corresponding feature is detected in the analysis,\n\
+@var{stmt} is the statement being analyzed. Return true if target still\n\
+need to analyze the subsequent statements, otherwise return false to stop\n\
+subsequent analysis.\n\
+The default version of this hook returns false.",
+ bool, (unsigned int& info, const gimple* stmt),
+ default_update_ipa_fn_target_info)
+
+DEFHOOK
+(need_ipa_fn_target_info,
+ "Allow target to check early whether it is necessary to analyze all gimple\n\
+statements in the given function to update target specific information for\n\
+inlining. See hook @code{update_ipa_fn_target_info} for usage example of\n\
+target specific information. This hook is expected to be invoked ahead of\n\
+the iterating with hook @code{update_ipa_fn_target_info}.\n\
+@var{decl} is the function being analyzed, @var{info} is the same as what\n\
+in hook @code{update_ipa_fn_target_info}, target can do one time update\n\
+into @var{info} without iterating for some case. Return true if target\n\
+decides to analyze all gimple statements to collect information, otherwise\n\
+return false.\n\
+The default version of this hook returns false.",
+ bool, (const_tree decl, unsigned int& info),
+ default_need_ipa_fn_target_info)
+
+DEFHOOK
+(relayout_function,
+"This target hook fixes function @var{fndecl} after attributes are processed.\n\
+Default does nothing. On ARM, the default function's alignment is updated\n\
+with the attribute target.",
+ void, (tree fndecl),
+ hook_void_tree)
+
+HOOK_VECTOR_END (target_option)
+
+/* For targets that need to mark extra registers as live on entry to
+ the function, they should define this target hook and set their
+ bits in the bitmap passed in. */
+DEFHOOK
+(extra_live_on_entry,
+ "Add any hard registers to @var{regs} that are live on entry to the\n\
+function. This hook only needs to be defined to provide registers that\n\
+cannot be found by examination of FUNCTION_ARG_REGNO_P, the callee saved\n\
+registers, STATIC_CHAIN_INCOMING_REGNUM, STATIC_CHAIN_REGNUM,\n\
+TARGET_STRUCT_VALUE_RTX, FRAME_POINTER_REGNUM, EH_USES,\n\
+FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM, and the PIC_OFFSET_TABLE_REGNUM.",
+ void, (bitmap regs),
+ hook_void_bitmap)
+
+/* Targets should define this target hook to mark that non-callee clobbers are
+ present in CALL_INSN_FUNCTION_USAGE for all the calls that bind to a local
+ definition. */
+DEFHOOKPOD
+(call_fusage_contains_non_callee_clobbers,
+ "Set to true if each call that binds to a local definition explicitly\n\
+clobbers or sets all non-fixed registers modified by performing the call.\n\
+That is, by the call pattern itself, or by code that might be inserted by the\n\
+linker (e.g.@: stubs, veneers, branch islands), but not including those\n\
+modifiable by the callee. The affected registers may be mentioned explicitly\n\
+in the call pattern, or included as clobbers in CALL_INSN_FUNCTION_USAGE.\n\
+The default version of this hook is set to false. The purpose of this hook\n\
+is to enable the fipa-ra optimization.",
+ bool,
+ false)
+
+/* Fill in additional registers set up by prologue into a regset. */
+DEFHOOK
+(set_up_by_prologue,
+ "This hook should add additional registers that are computed by the prologue\n\
+to the hard regset for shrink-wrapping optimization purposes.",
+ void, (struct hard_reg_set_container *),
+ NULL)
+
+/* For targets that have attributes that can affect whether a
+ function's return statements need checking. For instance a 'naked'
+ function attribute. */
+DEFHOOK
+(warn_func_return,
+ "True if a function's return statements should be checked for matching\n\
+the function's return type. This includes checking for falling off the end\n\
+of a non-void function. Return false if no such check should be made.",
+ bool, (tree),
+ hook_bool_tree_true)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_SHRINK_WRAP_"
+HOOK_VECTOR (TARGET_SHRINK_WRAP_HOOKS, shrink_wrap)
+
+DEFHOOK
+(get_separate_components,
+ "This hook should return an @code{sbitmap} with the bits set for those\n\
+components that can be separately shrink-wrapped in the current function.\n\
+Return @code{NULL} if the current function should not get any separate\n\
+shrink-wrapping.\n\
+Don't define this hook if it would always return @code{NULL}.\n\
+If it is defined, the other hooks in this group have to be defined as well.",
+ sbitmap, (void),
+ NULL)
+
+DEFHOOK
+(components_for_bb,
+ "This hook should return an @code{sbitmap} with the bits set for those\n\
+components where either the prologue component has to be executed before\n\
+the @code{basic_block}, or the epilogue component after it, or both.",
+ sbitmap, (basic_block),
+ NULL)
+
+DEFHOOK
+(disqualify_components,
+ "This hook should clear the bits in the @var{components} bitmap for those\n\
+components in @var{edge_components} that the target cannot handle on edge\n\
+@var{e}, where @var{is_prologue} says if this is for a prologue or an\n\
+epilogue instead.",
+ void, (sbitmap components, edge e, sbitmap edge_components, bool is_prologue),
+ NULL)
+
+DEFHOOK
+(emit_prologue_components,
+ "Emit prologue insns for the components indicated by the parameter.",
+ void, (sbitmap),
+ NULL)
+
+DEFHOOK
+(emit_epilogue_components,
+ "Emit epilogue insns for the components indicated by the parameter.",
+ void, (sbitmap),
+ NULL)
+
+DEFHOOK
+(set_handled_components,
+ "Mark the components in the parameter as handled, so that the\n\
+@code{prologue} and @code{epilogue} named patterns know to ignore those\n\
+components. The target code should not hang on to the @code{sbitmap}, it\n\
+will be deleted after this call.",
+ void, (sbitmap),
+ NULL)
+
+HOOK_VECTOR_END (shrink_wrap)
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+/* Determine the type of unwind info to emit for debugging. */
+DEFHOOK
+(debug_unwind_info,
+ "This hook defines the mechanism that will be used for describing frame\n\
+unwind information to the debugger. Normally the hook will return\n\
+@code{UI_DWARF2} if DWARF 2 debug information is enabled, and\n\
+return @code{UI_NONE} otherwise.\n\
+\n\
+A target may return @code{UI_DWARF2} even when DWARF 2 debug information\n\
+is disabled in order to always output DWARF 2 frame information.\n\
+\n\
+A target may return @code{UI_TARGET} if it has ABI specified unwind tables.\n\
+This will suppress generation of the normal debug frame unwind information.",
+ enum unwind_info_type, (void),
+ default_debug_unwind_info)
+
+DEFHOOK
+(reset_location_view,
+ "This hook, if defined, enables -ginternal-reset-location-views, and\n\
+uses its result to override cases in which the estimated min insn\n\
+length might be nonzero even when a PC advance (i.e., a view reset)\n\
+cannot be taken for granted.\n\
+\n\
+If the hook is defined, it must return a positive value to indicate\n\
+the insn definitely advances the PC, and so the view number can be\n\
+safely assumed to be reset; a negative value to mean the insn\n\
+definitely does not advance the PC, and os the view number must not\n\
+be reset; or zero to decide based on the estimated insn length.\n\
+\n\
+If insn length is to be regarded as reliable, set the hook to\n\
+@code{hook_int_rtx_insn_0}.",
+ int, (rtx_insn *), NULL)
+
+/* The code parameter should be of type enum rtx_code but this is not
+ defined at this time. */
+DEFHOOK
+(canonicalize_comparison,
+ "On some machines not all possible comparisons are defined, but you can\n\
+convert an invalid comparison into a valid one. For example, the Alpha\n\
+does not have a @code{GT} comparison, but you can use an @code{LT}\n\
+comparison instead and swap the order of the operands.\n\
+\n\
+On such machines, implement this hook to do any required conversions.\n\
+@var{code} is the initial comparison code and @var{op0} and @var{op1}\n\
+are the left and right operands of the comparison, respectively. If\n\
+@var{op0_preserve_value} is @code{true} the implementation is not\n\
+allowed to change the value of @var{op0} since the value might be used\n\
+in RTXs which aren't comparisons. E.g. the implementation is not\n\
+allowed to swap operands in that case.\n\
+\n\
+GCC will not assume that the comparison resulting from this macro is\n\
+valid but will see if the resulting insn matches a pattern in the\n\
+@file{md} file.\n\
+\n\
+You need not to implement this hook if it would never change the\n\
+comparison code or operands.",
+ void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
+ default_canonicalize_comparison)
+
+DEFHOOK
+(min_arithmetic_precision,
+ "On some RISC architectures with 64-bit registers, the processor also\n\
+maintains 32-bit condition codes that make it possible to do real 32-bit\n\
+arithmetic, although the operations are performed on the full registers.\n\
+\n\
+On such architectures, defining this hook to 32 tells the compiler to try\n\
+using 32-bit arithmetical operations setting the condition codes instead\n\
+of doing full 64-bit arithmetic.\n\
+\n\
+More generally, define this hook on RISC architectures if you want the\n\
+compiler to try using arithmetical operations setting the condition codes\n\
+with a precision lower than the word precision.\n\
+\n\
+You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not\n\
+defined to 1.",
+ unsigned int, (void), default_min_arithmetic_precision)
+
+DEFHOOKPOD
+(atomic_test_and_set_trueval,
+ "This value should be set if the result written by\n\
+@code{atomic_test_and_set} is not exactly 1, i.e.@: the\n\
+@code{bool} @code{true}.",
+ unsigned char, 1)
+
+/* Return an unsigned int representing the alignment (in bits) of the atomic
+ type which maps to machine MODE. This allows alignment to be overridden
+ as needed. */
+DEFHOOK
+(atomic_align_for_mode,
+"If defined, this function returns an appropriate alignment in bits for an\n\
+atomic object of machine_mode @var{mode}. If 0 is returned then the\n\
+default alignment for the specified mode is used.",
+ unsigned int, (machine_mode mode),
+ hook_uint_mode_0)
+
+DEFHOOK
+(atomic_assign_expand_fenv,
+"ISO C11 requires atomic compound assignments that may raise floating-point\n\
+exceptions to raise exceptions corresponding to the arithmetic operation\n\
+whose result was successfully stored in a compare-and-exchange sequence.\n\
+This requires code equivalent to calls to @code{feholdexcept},\n\
+@code{feclearexcept} and @code{feupdateenv} to be generated at\n\
+appropriate points in the compare-and-exchange sequence. This hook should\n\
+set @code{*@var{hold}} to an expression equivalent to the call to\n\
+@code{feholdexcept}, @code{*@var{clear}} to an expression equivalent to\n\
+the call to @code{feclearexcept} and @code{*@var{update}} to an expression\n\
+equivalent to the call to @code{feupdateenv}. The three expressions are\n\
+@code{NULL_TREE} on entry to the hook and may be left as @code{NULL_TREE}\n\
+if no code is required in a particular place. The default implementation\n\
+leaves all three expressions as @code{NULL_TREE}. The\n\
+@code{__atomic_feraiseexcept} function from @code{libatomic} may be of use\n\
+as part of the code generated in @code{*@var{update}}.",
+ void, (tree *hold, tree *clear, tree *update),
+ default_atomic_assign_expand_fenv)
+
+/* Leave the boolean fields at the end. */
+
+/* True if we can create zeroed data by switching to a BSS section
+ and then using ASM_OUTPUT_SKIP to allocate the space. */
+DEFHOOKPOD
+(have_switchable_bss_sections,
+ "This flag is true if we can create zeroed data by switching to a BSS\n\
+section and then using @code{ASM_OUTPUT_SKIP} to allocate the space.\n\
+This is true on most ELF targets.",
+ bool, false)
+
+/* True if "native" constructors and destructors are supported,
+ false if we're using collect2 for the job. */
+DEFHOOKPOD
+(have_ctors_dtors,
+ "This value is true if the target supports some ``native'' method of\n\
+collecting constructors and destructors to be run at startup and exit.\n\
+It is false if we must use @command{collect2}.",
+ bool, false)
+
+/* True if the target wants DTORs to be run from cxa_atexit. */
+DEFHOOKPOD
+(dtors_from_cxa_atexit,
+ "This value is true if the target wants destructors to be queued to be\n\
+run from __cxa_atexit. If this is the case then, for each priority level,\n\
+a new constructor will be entered that registers the destructors for that\n\
+level with __cxa_atexit (and there will be no destructors emitted).\n\
+It is false the method implied by @code{have_ctors_dtors} is used.",
+ bool, false)
+
+/* True if thread-local storage is supported. */
+DEFHOOKPOD
+(have_tls,
+ "Contains the value true if the target supports thread-local storage.\n\
+The default value is false.",
+ bool, false)
+
+/* True if a small readonly data section is supported. */
+DEFHOOKPOD
+(have_srodata_section,
+ "Contains the value true if the target places read-only\n\
+``small data'' into a separate section. The default value is false.",
+ bool, false)
+
+/* True if EH frame info sections should be zero-terminated. */
+DEFHOOKPOD
+(terminate_dw2_eh_frame_info,
+ "Contains the value true if the target should add a zero word onto the\n\
+end of a Dwarf-2 frame info section when used for exception handling.\n\
+Default value is false if @code{EH_FRAME_SECTION_NAME} is defined, and\n\
+true otherwise.",
+ bool, true)
+
+/* True if #NO_APP should be emitted at the beginning of assembly output. */
+DEFHOOKPOD
+(asm_file_start_app_off,
+ "If this flag is true, the text of the macro @code{ASM_APP_OFF} will be\n\
+printed as the very first line in the assembly file, unless\n\
+@option{-fverbose-asm} is in effect. (If that macro has been defined\n\
+to the empty string, this variable has no effect.) With the normal\n\
+definition of @code{ASM_APP_OFF}, the effect is to notify the GNU\n\
+assembler that it need not bother stripping comments or extra\n\
+whitespace from its input. This allows it to work a bit faster.\n\
+\n\
+The default is false. You should not set it to true unless you have\n\
+verified that your port does not generate any extra whitespace or\n\
+comments that will cause GAS to issue errors in NO_APP mode.",
+ bool, false)
+
+/* True if output_file_directive should be called for main_input_filename
+ at the beginning of assembly output. */
+DEFHOOKPOD
+(asm_file_start_file_directive,
+ "If this flag is true, @code{output_file_directive} will be called\n\
+for the primary source file, immediately after printing\n\
+@code{ASM_APP_OFF} (if that is enabled). Most ELF assemblers expect\n\
+this to be done. The default is false.",
+ bool, false)
+
+/* Returns true if we should generate exception tables for use with the
+ ARM EABI. The effects the encoding of function exception specifications. */
+DEFHOOKPOD
+(arm_eabi_unwinder,
+ "This flag should be set to @code{true} on targets that use an ARM EABI\n\
+based unwinding library, and @code{false} on other targets. This effects\n\
+the format of unwinding tables, and how the unwinder in entered after\n\
+running a cleanup. The default is @code{false}.",
+ bool, false)
+
+DEFHOOKPOD
+(want_debug_pub_sections,
+ "True if the @code{.debug_pubtypes} and @code{.debug_pubnames} sections\n\
+should be emitted. These sections are not used on most platforms, and\n\
+in particular GDB does not use them.",
+ bool, false)
+
+DEFHOOKPOD
+(delay_sched2,
+ "True if sched2 is not to be run at its normal place.\n\
+This usually means it will be run as part of machine-specific reorg.",
+bool, false)
+
+DEFHOOKPOD
+(delay_vartrack,
+ "True if vartrack is not to be run at its normal place.\n\
+This usually means it will be run as part of machine-specific reorg.",
+bool, false)
+
+DEFHOOKPOD
+(no_register_allocation,
+ "True if register allocation and the passes\n\
+following it should not be run. Usually true only for virtual assembler\n\
+targets.",
+bool, false)
+
+/* Leave the boolean fields at the end. */
+
+/* Functions related to mode switching. */
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_MODE_"
+HOOK_VECTOR (TARGET_TOGGLE_, mode_switching)
+
+DEFHOOK
+(emit,
+ "Generate one or more insns to set @var{entity} to @var{mode}.\n\
+@var{hard_reg_live} is the set of hard registers live at the point where\n\
+the insn(s) are to be inserted. @var{prev_moxde} indicates the mode\n\
+to switch from. Sets of a lower numbered entity will be emitted before\n\
+sets of a higher numbered entity to a mode of the same or lower priority.",
+ void, (int entity, int mode, int prev_mode, HARD_REG_SET regs_live), NULL)
+
+DEFHOOK
+(needed,
+ "@var{entity} is an integer specifying a mode-switched entity.\n\
+If @code{OPTIMIZE_MODE_SWITCHING} is defined, you must define this macro\n\
+to return an integer value not larger than the corresponding element\n\
+in @code{NUM_MODES_FOR_MODE_SWITCHING}, to denote the mode that @var{entity}\n\
+must be switched into prior to the execution of @var{insn}.",
+ int, (int entity, rtx_insn *insn), NULL)
+
+DEFHOOK
+(after,
+ "@var{entity} is an integer specifying a mode-switched entity.\n\
+If this macro is defined, it is evaluated for every @var{insn} during mode\n\
+switching. It determines the mode that an insn results\n\
+in (if different from the incoming mode).",
+ int, (int entity, int mode, rtx_insn *insn), NULL)
+
+DEFHOOK
+(entry,
+ "If this macro is defined, it is evaluated for every @var{entity} that\n\
+needs mode switching. It should evaluate to an integer, which is a mode\n\
+that @var{entity} is assumed to be switched to at function entry.\n\
+If @code{TARGET_MODE_ENTRY} is defined then @code{TARGET_MODE_EXIT}\n\
+must be defined.",
+ int, (int entity), NULL)
+
+DEFHOOK
+(exit,
+ "If this macro is defined, it is evaluated for every @var{entity} that\n\
+needs mode switching. It should evaluate to an integer, which is a mode\n\
+that @var{entity} is assumed to be switched to at function exit.\n\
+If @code{TARGET_MODE_EXIT} is defined then @code{TARGET_MODE_ENTRY}\n\
+must be defined.",
+ int, (int entity), NULL)
+
+DEFHOOK
+(priority,
+ "This macro specifies the order in which modes for @var{entity}\n\
+are processed. 0 is the highest priority,\n\
+@code{NUM_MODES_FOR_MODE_SWITCHING[@var{entity}] - 1} the lowest.\n\
+The value of the macro should be an integer designating a mode\n\
+for @var{entity}. For any fixed @var{entity}, @code{mode_priority}\n\
+(@var{entity}, @var{n}) shall be a bijection in 0 @dots{}\n\
+@code{num_modes_for_mode_switching[@var{entity}] - 1}.",
+ int, (int entity, int n), NULL)
+
+HOOK_VECTOR_END (mode_switching)
+
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_MEMTAG_"
+HOOK_VECTOR (TARGET_MEMTAG_, memtag)
+
+DEFHOOK
+(can_tag_addresses,
+ "True if the backend architecture naturally supports ignoring some region\n\
+of pointers. This feature means that @option{-fsanitize=hwaddress} can\n\
+work.\n\
+\n\
+At preset, this feature does not support address spaces. It also requires\n\
+@code{Pmode} to be the same as @code{ptr_mode}.",
+ bool, (), default_memtag_can_tag_addresses)
+
+DEFHOOK
+(tag_size,
+ "Return the size of a tag (in bits) for this platform.\n\
+\n\
+The default returns 8.",
+ uint8_t, (), default_memtag_tag_size)
+
+DEFHOOK
+(granule_size,
+ "Return the size in real memory that each byte in shadow memory refers to.\n\
+I.e. if a variable is @var{X} bytes long in memory, then this hook should\n\
+return the value @var{Y} such that the tag in shadow memory spans\n\
+@var{X}/@var{Y} bytes.\n\
+\n\
+Most variables will need to be aligned to this amount since two variables\n\
+that are neighbors in memory and share a tag granule would need to share\n\
+the same tag.\n\
+\n\
+The default returns 16.",
+ uint8_t, (), default_memtag_granule_size)
+
+DEFHOOK
+(insert_random_tag,
+ "Return an RTX representing the value of @var{untagged} but with a\n\
+(possibly) random tag in it.\n\
+Put that value into @var{target} if it is convenient to do so.\n\
+This function is used to generate a tagged base for the current stack frame.",
+ rtx, (rtx untagged, rtx target), default_memtag_insert_random_tag)
+
+DEFHOOK
+(add_tag,
+ "Return an RTX that represents the result of adding @var{addr_offset} to\n\
+the address in pointer @var{base} and @var{tag_offset} to the tag in pointer\n\
+@var{base}.\n\
+The resulting RTX must either be a valid memory address or be able to get\n\
+put into an operand with @code{force_operand}.\n\
+\n\
+Unlike other memtag hooks, this must return an expression and not emit any\n\
+RTL.",
+ rtx, (rtx base, poly_int64 addr_offset, uint8_t tag_offset),
+ default_memtag_add_tag)
+
+DEFHOOK
+(set_tag,
+ "Return an RTX representing @var{untagged_base} but with the tag @var{tag}.\n\
+Try and store this in @var{target} if convenient.\n\
+@var{untagged_base} is required to have a zero tag when this hook is called.\n\
+The default of this hook is to set the top byte of @var{untagged_base} to\n\
+@var{tag}.",
+ rtx, (rtx untagged_base, rtx tag, rtx target), default_memtag_set_tag)
+
+DEFHOOK
+(extract_tag,
+ "Return an RTX representing the tag stored in @var{tagged_pointer}.\n\
+Store the result in @var{target} if it is convenient.\n\
+The default represents the top byte of the original pointer.",
+ rtx, (rtx tagged_pointer, rtx target), default_memtag_extract_tag)
+
+DEFHOOK
+(untagged_pointer,
+ "Return an RTX representing @var{tagged_pointer} with its tag set to zero.\n\
+Store the result in @var{target} if convenient.\n\
+The default clears the top byte of the original pointer.",
+ rtx, (rtx tagged_pointer, rtx target), default_memtag_untagged_pointer)
+
+HOOK_VECTOR_END (memtag)
+#undef HOOK_PREFIX
+#define HOOK_PREFIX "TARGET_"
+
+#define DEF_TARGET_INSN(NAME, PROTO) \
+ DEFHOOK_UNDOC (have_##NAME, "", bool, (void), false)
+#include "target-insns.def"
+#undef DEF_TARGET_INSN
+
+#define DEF_TARGET_INSN(NAME, PROTO) \
+ DEFHOOK_UNDOC (gen_##NAME, "", rtx_insn *, PROTO, NULL)
+#include "target-insns.def"
+#undef DEF_TARGET_INSN
+
+#define DEF_TARGET_INSN(NAME, PROTO) \
+ DEFHOOKPOD (code_for_##NAME, "*", enum insn_code, CODE_FOR_nothing)
+#include "target-insns.def"
+#undef DEF_TARGET_INSN
+
+DEFHOOK
+(run_target_selftests,
+ "If selftests are enabled, run any selftests for this target.",
+ void, (void),
+ NULL)
+
+DEFHOOK
+(gcov_type_size,
+ "Returns the gcov type size in bits. This type is used for example for\n\
+counters incremented by profiling and code-coverage events. The default\n\
+value is 64, if the type size of long long is greater than 32, otherwise the\n\
+default value is 32. A 64-bit type is recommended to avoid overflows of the\n\
+counters. If the @option{-fprofile-update=atomic} is used, then the\n\
+counters are incremented using atomic operations. Targets not supporting\n\
+64-bit atomic operations may override the default value and request a 32-bit\n\
+type.",
+ HOST_WIDE_INT, (void), default_gcov_type_size)
+
+/* This value represents whether the shadow call stack is implemented on
+ the target platform. */
+DEFHOOKPOD
+(have_shadow_call_stack,
+ "This value is true if the target platform supports\n\
+@option{-fsanitize=shadow-call-stack}. The default value is false.",
+ bool, false)
+
+/* Close the 'struct gcc_target' definition. */
+HOOK_VECTOR_END (C90_EMPTY_HACK)
+
diff --git a/support/cpp/gcc/target.h b/support/cpp/gcc/target.h
new file mode 100644
index 000000000..71d3d9110
--- /dev/null
+++ b/support/cpp/gcc/target.h
@@ -0,0 +1,322 @@
+/* Data structure definitions for a generic GCC target.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding! */
+
+
+/* This file contains a data structure that describes a GCC target.
+ At present it is incomplete, but in future it should grow to
+ contain most or all target machine and target O/S specific
+ information.
+
+ This structure has its initializer declared in target-def.h in the
+ form of large macro TARGET_INITIALIZER that expands to many smaller
+ macros.
+
+ The smaller macros each initialize one component of the structure,
+ and each has a default. Each target should have a file that
+ includes target.h and target-def.h, and overrides any inappropriate
+ defaults by undefining the relevant macro and defining a suitable
+ replacement. That file should then contain the definition of
+ "targetm" like so:
+
+ struct gcc_target targetm = TARGET_INITIALIZER;
+
+ Doing things this way allows us to bring together everything that
+ defines a GCC target. By supplying a default that is appropriate
+ to most targets, we can easily add new items without needing to
+ edit dozens of target configuration files. It should also allow us
+ to gradually reduce the amount of conditional compilation that is
+ scattered throughout GCC. */
+
+#ifndef GCC_TARGET_H
+#define GCC_TARGET_H
+
+#include "insn-codes.h"
+#include "tm.h"
+#include "hard-reg-set.h"
+
+#if 0 // sdcpp
+
+#if CHECKING_P
+
+struct cumulative_args_t { void *magic; void *p; };
+
+#else /* !CHECKING_P */
+
+/* When using a GCC build compiler, we could use
+ __attribute__((transparent_union)) to get cumulative_args_t function
+ arguments passed like scalars where the ABI would mandate a less
+ efficient way of argument passing otherwise. However, that would come
+ at the cost of less type-safe !CHECKING_P compilation. */
+
+union cumulative_args_t { void *p; };
+
+#endif /* !CHECKING_P */
+
+/* Types of memory operation understood by the "by_pieces" infrastructure.
+ Used by the TARGET_USE_BY_PIECES_INFRASTRUCTURE_P target hook and
+ internally by the functions in expr.cc. */
+
+enum by_pieces_operation
+{
+ CLEAR_BY_PIECES,
+ MOVE_BY_PIECES,
+ SET_BY_PIECES,
+ STORE_BY_PIECES,
+ COMPARE_BY_PIECES
+};
+
+extern unsigned HOST_WIDE_INT by_pieces_ninsns (unsigned HOST_WIDE_INT,
+ unsigned int,
+ unsigned int,
+ by_pieces_operation);
+
+/* An example implementation for ELF targets. Defined in varasm.cc */
+extern void elf_record_gcc_switches (const char *);
+
+/* Some places still assume that all pointer or address modes are the
+ standard Pmode and ptr_mode. These optimizations become invalid if
+ the target actually supports multiple different modes. For now,
+ we disable such optimizations on such targets, using this function. */
+extern bool target_default_pointer_address_modes_p (void);
+
+/* For hooks which use the MOVE_RATIO macro, this gives the legacy default
+ behavior. */
+extern unsigned int get_move_ratio (bool);
+
+struct stdarg_info;
+struct spec_info_def;
+struct hard_reg_set_container;
+struct cgraph_node;
+struct cgraph_simd_clone;
+
+/* The struct used by the secondary_reload target hook. */
+struct secondary_reload_info
+{
+ /* icode is actually an enum insn_code, but we don't want to force every
+ file that includes target.h to include optabs.h . */
+ int icode;
+ int extra_cost; /* Cost for using (a) scratch register(s) to be taken
+ into account by copy_cost. */
+ /* The next two members are for the use of the backward
+ compatibility hook. */
+ struct secondary_reload_info *prev_sri;
+ int t_icode; /* Actually an enum insn_code - see above. */
+};
+
+/* This is defined in sched-int.h . */
+struct _dep;
+
+/* This is defined in ddg.h . */
+struct ddg;
+
+/* This is defined in cfgloop.h . */
+class loop;
+
+/* This is defined in ifcvt.h. */
+struct noce_if_info;
+
+/* This is defined in tree-ssa-alias.h. */
+class ao_ref;
+
+/* This is defined in tree-vectorizer.h. */
+class _stmt_vec_info;
+
+/* This is defined in calls.h. */
+class function_arg_info;
+
+/* This is defined in function-abi.h. */
+class predefined_function_abi;
+
+/* These are defined in tree-vect-stmts.cc. */
+extern tree stmt_vectype (class _stmt_vec_info *);
+extern bool stmt_in_inner_loop_p (class vec_info *, class _stmt_vec_info *);
+
+/* Assembler instructions for creating various kinds of integer object. */
+
+struct asm_int_op
+{
+ const char *hi;
+ const char *psi;
+ const char *si;
+ const char *pdi;
+ const char *di;
+ const char *pti;
+ const char *ti;
+};
+
+/* Types of costs for vectorizer cost model. */
+enum vect_cost_for_stmt
+{
+ scalar_stmt,
+ scalar_load,
+ scalar_store,
+ vector_stmt,
+ vector_load,
+ vector_gather_load,
+ unaligned_load,
+ unaligned_store,
+ vector_store,
+ vector_scatter_store,
+ vec_to_scalar,
+ scalar_to_vec,
+ cond_branch_not_taken,
+ cond_branch_taken,
+ vec_perm,
+ vec_promote_demote,
+ vec_construct
+};
+
+/* Separate locations for which the vectorizer cost model should
+ track costs. */
+enum vect_cost_model_location {
+ vect_prologue = 0,
+ vect_body = 1,
+ vect_epilogue = 2
+};
+
+class vec_perm_indices;
+
+/* The type to use for lists of vector sizes. */
+typedef vec<machine_mode> vector_modes;
+
+/* Same, but can be used to construct local lists that are
+ automatically freed. */
+typedef auto_vec<machine_mode, 8> auto_vector_modes;
+
+/* First argument of targetm.omp.device_kind_arch_isa. */
+enum omp_device_kind_arch_isa {
+ omp_device_kind,
+ omp_device_arch,
+ omp_device_isa
+};
+
+/* Flags returned by TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES:
+
+ VECT_COMPARE_COSTS
+ Tells the loop vectorizer to try all the provided modes and
+ pick the one with the lowest cost. By default the vectorizer
+ will choose the first mode that works. */
+const unsigned int VECT_COMPARE_COSTS = 1U << 0;
+
+/* The contexts in which the use of a type T can be checked by
+ TARGET_VERIFY_TYPE_CONTEXT. */
+enum type_context_kind {
+ /* Directly measuring the size of T. */
+ TCTX_SIZEOF,
+
+ /* Directly measuring the alignment of T. */
+ TCTX_ALIGNOF,
+
+ /* Creating objects of type T with static storage duration. */
+ TCTX_STATIC_STORAGE,
+
+ /* Creating objects of type T with thread-local storage duration. */
+ TCTX_THREAD_STORAGE,
+
+ /* Creating a field of type T. */
+ TCTX_FIELD,
+
+ /* Creating an array with elements of type T. */
+ TCTX_ARRAY_ELEMENT,
+
+ /* Adding to or subtracting from a pointer to T, or computing the
+ difference between two pointers when one of them is a pointer to T. */
+ TCTX_POINTER_ARITH,
+
+ /* Dynamically allocating objects of type T. */
+ TCTX_ALLOCATION,
+
+ /* Dynamically deallocating objects of type T. */
+ TCTX_DEALLOCATION,
+
+ /* Throwing or catching an object of type T. */
+ TCTX_EXCEPTIONS,
+
+ /* Capturing objects of type T by value in a closure. */
+ TCTX_CAPTURE_BY_COPY
+};
+
+enum poly_value_estimate_kind
+{
+ POLY_VALUE_MIN,
+ POLY_VALUE_MAX,
+ POLY_VALUE_LIKELY
+};
+
+extern bool verify_type_context (location_t, type_context_kind, const_tree,
+ bool = false);
+
+/* The target structure. This holds all the backend hooks. */
+#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
+#define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS;
+#define DEFHOOK_UNDOC DEFHOOK
+#define HOOKSTRUCT(FRAGMENT) FRAGMENT
+
+#include "target.def"
+
+extern struct gcc_target targetm;
+
+/* Return an estimate of the runtime value of X, for use in things
+ like cost calculations or profiling frequencies. Note that this
+ function should never be used in situations where the actual
+ runtime value is needed for correctness, since the function only
+ provides a rough guess. */
+
+static inline HOST_WIDE_INT
+estimated_poly_value (poly_int64 x,
+ poly_value_estimate_kind kind = POLY_VALUE_LIKELY)
+{
+ if (NUM_POLY_INT_COEFFS == 1)
+ return x.coeffs[0];
+ else
+ return targetm.estimated_poly_value (x, kind);
+}
+
+#ifdef GCC_TM_H
+
+#ifndef CUMULATIVE_ARGS_MAGIC
+#define CUMULATIVE_ARGS_MAGIC ((void *) &targetm.calls)
+#endif
+
+static inline CUMULATIVE_ARGS *
+get_cumulative_args (cumulative_args_t arg)
+{
+#if CHECKING_P
+ gcc_assert (arg.magic == CUMULATIVE_ARGS_MAGIC);
+#endif /* CHECKING_P */
+ return (CUMULATIVE_ARGS *) arg.p;
+}
+
+static inline cumulative_args_t
+pack_cumulative_args (CUMULATIVE_ARGS *arg)
+{
+ cumulative_args_t ret;
+
+#if CHECKING_P
+ ret.magic = CUMULATIVE_ARGS_MAGIC;
+#endif /* CHECKING_P */
+ ret.p = (void *) arg;
+ return ret;
+}
+#endif /* GCC_TM_H */
+
+#endif // sdcpp
+#endif /* GCC_TARGET_H */
diff --git a/support/cpp/gcc/timevar.cc b/support/cpp/gcc/timevar.cc
new file mode 100644
index 000000000..cdbf7517d
--- /dev/null
+++ b/support/cpp/gcc/timevar.cc
@@ -0,0 +1,817 @@
+/* Timing variables for measuring compiler performance.
+ Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ Contributed by Alex Samuel <samuel@codesourcery.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.
+
+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 "timevar.h"
+#include "options.h"
+
+#ifndef HAVE_CLOCK_T
+typedef int clock_t;
+#endif
+
+#ifndef HAVE_STRUCT_TMS
+struct tms
+{
+ clock_t tms_utime;
+ clock_t tms_stime;
+ clock_t tms_cutime;
+ clock_t tms_cstime;
+};
+#endif
+
+#ifndef RUSAGE_SELF
+# define RUSAGE_SELF 0
+#endif
+
+/* Calculation of scale factor to convert ticks to microseconds.
+ We mustn't use CLOCKS_PER_SEC except with clock(). */
+#if HAVE_SYSCONF && defined _SC_CLK_TCK
+# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
+#else
+# ifdef CLK_TCK
+# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
+# else
+# ifdef HZ
+# define TICKS_PER_SECOND HZ /* traditional UNIX */
+# else
+# define TICKS_PER_SECOND 100 /* often the correct value */
+# endif
+# endif
+#endif
+
+/* Prefer times to getrusage to clock (each gives successively less
+ information). */
+#ifdef HAVE_TIMES
+# if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
+ extern clock_t times (struct tms *);
+# endif
+# define USE_TIMES
+# define HAVE_USER_TIME
+# define HAVE_SYS_TIME
+# define HAVE_WALL_TIME
+#else
+#ifdef HAVE_GETRUSAGE
+# if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
+ extern int getrusage (int, struct rusage *);
+# endif
+# define USE_GETRUSAGE
+# define HAVE_USER_TIME
+# define HAVE_SYS_TIME
+#else
+#ifdef HAVE_CLOCK
+# if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
+ extern clock_t clock (void);
+# endif
+# define USE_CLOCK
+# define HAVE_USER_TIME
+#endif
+#endif
+#endif
+
+/* libc is very likely to have snuck a call to sysconf() into one of
+ the underlying constants, and that can be very slow, so we have to
+ precompute them. Whose wonderful idea was it to make all those
+ _constants_ variable at run time, anyway? */
+#ifdef USE_TIMES
+static double ticks_to_msec;
+#define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
+#endif
+
+#ifdef USE_CLOCK
+static double clocks_to_msec;
+#define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
+#endif
+
+/* Non-NULL if timevars should be used. In GCC, this happens with
+ the -ftime-report flag. */
+
+timer *g_timer;
+
+/* Total amount of memory allocated by garbage collector. */
+
+size_t timevar_ggc_mem_total;
+
+/* The amount of memory that will cause us to report the timevar even
+ if the time spent is not significant. */
+
+#define GGC_MEM_BOUND (1 << 20)
+
+/* See timevar.h for an explanation of timing variables. */
+
+static void get_time (struct timevar_time_def *);
+static void timevar_accumulate (struct timevar_time_def *,
+ struct timevar_time_def *,
+ struct timevar_time_def *);
+
+/* The implementation of timing events for jit client code, allowing
+ arbitrary named items to appear on the timing stack. */
+
+class timer::named_items
+{
+ public:
+ named_items (timer *t);
+ ~named_items ();
+
+ void push (const char *item_name);
+ void pop ();
+ void print (FILE *fp, const timevar_time_def *total);
+
+ private:
+ /* Which timer instance does this relate to? */
+ timer *m_timer;
+
+ /* Dictionary, mapping from item names to timevar_def.
+ Note that currently we merely store/compare the raw string
+ pointers provided by client code; we don't take a copy,
+ or use strcmp. */
+ hash_map <const char *, timer::timevar_def> m_hash_map;
+
+ /* The order in which items were originally inserted. */
+ auto_vec <const char *> m_names;
+};
+
+/* The constructor for class timer::named_items. */
+
+timer::named_items::named_items (timer *t)
+: m_timer (t),
+ m_hash_map (),
+ m_names ()
+{
+}
+
+/* The destructor for class timer::named_items. */
+
+timer::named_items::~named_items ()
+{
+}
+
+/* Push the named item onto the timer stack. */
+
+void
+timer::named_items::push (const char *item_name)
+{
+ gcc_assert (item_name);
+
+ bool existed;
+ timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
+ if (!existed)
+ {
+ def->elapsed.user = 0;
+ def->elapsed.sys = 0;
+ def->elapsed.wall = 0;
+ def->name = item_name;
+ def->standalone = 0;
+ m_names.safe_push (item_name);
+ }
+ m_timer->push_internal (def);
+}
+
+/* Pop the top item from the timer stack. */
+
+void
+timer::named_items::pop ()
+{
+ m_timer->pop_internal ();
+}
+
+/* Print the given client item. Helper function for timer::print. */
+
+void
+timer::named_items::print (FILE *fp, const timevar_time_def *total)
+{
+ fprintf (fp, "Client items:\n");
+ for (const char *item_name : m_names)
+ {
+ timer::timevar_def *def = m_hash_map.get (item_name);
+ gcc_assert (def);
+ m_timer->print_row (fp, total, def->name, def->elapsed);
+ }
+}
+
+/* Fill the current times into TIME. The definition of this function
+ also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
+ HAVE_WALL_TIME macros. */
+
+static void
+get_time (struct timevar_time_def *now)
+{
+ now->user = 0;
+ now->sys = 0;
+ now->wall = 0;
+ now->ggc_mem = timevar_ggc_mem_total;
+
+ {
+#ifdef USE_TIMES
+ struct tms tms;
+ now->wall = times (&tms) * ticks_to_msec;
+ now->user = tms.tms_utime * ticks_to_msec;
+ now->sys = tms.tms_stime * ticks_to_msec;
+#endif
+#ifdef USE_GETRUSAGE
+ struct rusage rusage;
+ getrusage (RUSAGE_SELF, &rusage);
+ now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
+ now->sys = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
+#endif
+#ifdef USE_CLOCK
+ now->user = clock () * clocks_to_msec;
+#endif
+ }
+}
+
+/* Add the difference between STOP_TIME and START_TIME to TIMER. */
+
+static void
+timevar_accumulate (struct timevar_time_def *timer,
+ struct timevar_time_def *start_time,
+ struct timevar_time_def *stop_time)
+{
+ timer->user += stop_time->user - start_time->user;
+ timer->sys += stop_time->sys - start_time->sys;
+ timer->wall += stop_time->wall - start_time->wall;
+ timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
+}
+
+/* Class timer's constructor. */
+
+timer::timer () :
+ m_stack (NULL),
+ m_unused_stack_instances (NULL),
+ m_start_time (),
+ m_jit_client_items (NULL)
+{
+ /* Zero all elapsed times. */
+ memset (m_timevars, 0, sizeof (m_timevars));
+
+ /* Initialize the names of timing variables. */
+#define DEFTIMEVAR(identifier__, name__) \
+ m_timevars[identifier__].name = name__;
+#include "timevar.def"
+#undef DEFTIMEVAR
+
+ /* Initialize configuration-specific state.
+ Ideally this would be one-time initialization. */
+#ifdef USE_TIMES
+ ticks_to_msec = TICKS_TO_MSEC;
+#endif
+#ifdef USE_CLOCK
+ clocks_to_msec = CLOCKS_TO_MSEC;
+#endif
+}
+
+/* Class timer's destructor. */
+
+timer::~timer ()
+{
+ timevar_stack_def *iter, *next;
+
+ for (iter = m_stack; iter; iter = next)
+ {
+ next = iter->next;
+ free (iter);
+ }
+ for (iter = m_unused_stack_instances; iter; iter = next)
+ {
+ next = iter->next;
+ free (iter);
+ }
+ for (unsigned i = 0; i < TIMEVAR_LAST; ++i)
+ delete m_timevars[i].children;
+
+ delete m_jit_client_items;
+}
+
+/* Initialize timing variables. */
+
+void
+timevar_init (void)
+{
+ if (g_timer)
+ return;
+
+ g_timer = new timer ();
+}
+
+/* Push TIMEVAR onto the timing stack. No further elapsed time is
+ attributed to the previous topmost timing variable on the stack;
+ subsequent elapsed time is attributed to TIMEVAR, until it is
+ popped or another element is pushed on top.
+
+ TIMEVAR cannot be running as a standalone timer. */
+
+void
+timer::push (timevar_id_t timevar)
+{
+ struct timevar_def *tv = &m_timevars[timevar];
+ push_internal (tv);
+}
+
+/* Push TV onto the timing stack, either one of the builtin ones
+ for a timevar_id_t, or one provided by client code to libgccjit. */
+
+void
+timer::push_internal (struct timevar_def *tv)
+{
+ struct timevar_stack_def *context;
+ struct timevar_time_def now;
+
+ gcc_assert (tv);
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
+ /* Can't push a standalone timer. */
+ gcc_assert (!tv->standalone);
+
+ /* What time is it? */
+ get_time (&now);
+
+ /* If the stack isn't empty, attribute the current elapsed time to
+ the old topmost element. */
+ if (m_stack)
+ timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
+
+ /* Reset the start time; from now on, time is attributed to
+ TIMEVAR. */
+ m_start_time = now;
+
+ /* See if we have a previously-allocated stack instance. If so,
+ take it off the list. If not, malloc a new one. */
+ if (m_unused_stack_instances != NULL)
+ {
+ context = m_unused_stack_instances;
+ m_unused_stack_instances = m_unused_stack_instances->next;
+ }
+ else
+ context = XNEW (struct timevar_stack_def);
+
+ /* Fill it in and put it on the stack. */
+ context->timevar = tv;
+ context->next = m_stack;
+ m_stack = context;
+}
+
+/* Pop the topmost timing variable element off the timing stack. The
+ popped variable must be TIMEVAR. Elapsed time since the that
+ element was pushed on, or since it was last exposed on top of the
+ stack when the element above it was popped off, is credited to that
+ timing variable. */
+
+void
+timer::pop (timevar_id_t timevar)
+{
+ gcc_assert (&m_timevars[timevar] == m_stack->timevar);
+
+ pop_internal ();
+}
+
+/* Pop the topmost item from the stack, either one of the builtin ones
+ for a timevar_id_t, or one provided by client code to libgccjit. */
+
+void
+timer::pop_internal ()
+{
+ struct timevar_time_def now;
+ struct timevar_stack_def *popped = m_stack;
+
+ /* What time is it? */
+ get_time (&now);
+
+ /* Attribute the elapsed time to the element we're popping. */
+ timevar_accumulate (&popped->timevar->elapsed, &m_start_time, &now);
+
+ /* Take the item off the stack. */
+ m_stack = m_stack->next;
+
+ /* Record the elapsed sub-time to the parent as well. */
+ if (m_stack && time_report_details)
+ {
+ if (! m_stack->timevar->children)
+ m_stack->timevar->children = new child_map_t (5);
+ bool existed_p;
+ timevar_time_def &time
+ = m_stack->timevar->children->get_or_insert (popped->timevar, &existed_p);
+ if (! existed_p)
+ memset (&time, 0, sizeof (timevar_time_def));
+ timevar_accumulate (&time, &m_start_time, &now);
+ }
+
+ /* Reset the start time; from now on, time is attributed to the
+ element just exposed on the stack. */
+ m_start_time = now;
+
+ /* Don't delete the stack element; instead, add it to the list of
+ unused elements for later use. */
+ popped->next = m_unused_stack_instances;
+ m_unused_stack_instances = popped;
+}
+
+/* Start timing TIMEVAR independently of the timing stack. Elapsed
+ time until timevar_stop is called for the same timing variable is
+ attributed to TIMEVAR. */
+
+void
+timevar_start (timevar_id_t timevar)
+{
+ if (!g_timer)
+ return;
+
+ g_timer->start (timevar);
+}
+
+/* See timevar_start above. */
+
+void
+timer::start (timevar_id_t timevar)
+{
+ struct timevar_def *tv = &m_timevars[timevar];
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
+ /* Don't allow the same timing variable to be started more than
+ once. */
+ gcc_assert (!tv->standalone);
+ tv->standalone = 1;
+
+ get_time (&tv->start_time);
+}
+
+/* Stop timing TIMEVAR. Time elapsed since timevar_start was called
+ is attributed to it. */
+
+void
+timevar_stop (timevar_id_t timevar)
+{
+ if (!g_timer)
+ return;
+
+ g_timer->stop (timevar);
+}
+
+/* See timevar_stop above. */
+
+void
+timer::stop (timevar_id_t timevar)
+{
+ struct timevar_def *tv = &m_timevars[timevar];
+ struct timevar_time_def now;
+
+ /* TIMEVAR must have been started via timevar_start. */
+ gcc_assert (tv->standalone);
+ tv->standalone = 0; /* Enable a restart. */
+
+ get_time (&now);
+ timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
+}
+
+
+/* Conditionally start timing TIMEVAR independently of the timing stack.
+ If the timer is already running, leave it running and return true.
+ Otherwise, start the timer and return false.
+ Elapsed time until the corresponding timevar_cond_stop
+ is called for the same timing variable is attributed to TIMEVAR. */
+
+bool
+timevar_cond_start (timevar_id_t timevar)
+{
+ if (!g_timer)
+ return false;
+
+ return g_timer->cond_start (timevar);
+}
+
+/* See timevar_cond_start above. */
+
+bool
+timer::cond_start (timevar_id_t timevar)
+{
+ struct timevar_def *tv = &m_timevars[timevar];
+
+ /* Mark this timing variable as used. */
+ tv->used = 1;
+
+ if (tv->standalone)
+ return true; /* The timevar is already running. */
+
+ /* Don't allow the same timing variable
+ to be unconditionally started more than once. */
+ tv->standalone = 1;
+
+ get_time (&tv->start_time);
+ return false; /* The timevar was not already running. */
+}
+
+/* Conditionally stop timing TIMEVAR. The RUNNING parameter must come
+ from the return value of a dynamically matching timevar_cond_start.
+ If the timer had already been RUNNING, do nothing. Otherwise, time
+ elapsed since timevar_cond_start was called is attributed to it. */
+
+void
+timevar_cond_stop (timevar_id_t timevar, bool running)
+{
+ if (!g_timer || running)
+ return;
+
+ g_timer->cond_stop (timevar);
+}
+
+/* See timevar_cond_stop above. */
+
+void
+timer::cond_stop (timevar_id_t timevar)
+{
+ struct timevar_def *tv;
+ struct timevar_time_def now;
+
+ tv = &m_timevars[timevar];
+
+ /* TIMEVAR must have been started via timevar_cond_start. */
+ gcc_assert (tv->standalone);
+ tv->standalone = 0; /* Enable a restart. */
+
+ get_time (&now);
+ timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
+}
+
+/* Push the named item onto the timing stack. */
+
+void
+timer::push_client_item (const char *item_name)
+{
+ gcc_assert (item_name);
+
+ /* Lazily create the named_items instance. */
+ if (!m_jit_client_items)
+ m_jit_client_items = new named_items (this);
+
+ m_jit_client_items->push (item_name);
+}
+
+/* Pop the top-most client item from the timing stack. */
+
+void
+timer::pop_client_item ()
+{
+ gcc_assert (m_jit_client_items);
+ m_jit_client_items->pop ();
+}
+
+/* Validate that phase times are consistent. */
+
+void
+timer::validate_phases (FILE *fp) const
+{
+ unsigned int /* timevar_id_t */ id;
+ const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
+ double phase_user = 0.0;
+ double phase_sys = 0.0;
+ double phase_wall = 0.0;
+ size_t phase_ggc_mem = 0;
+ static char phase_prefix[] = "phase ";
+ const double tolerance = 1.000001; /* One part in a million. */
+
+ for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
+ {
+ const timevar_def *tv = &m_timevars[(timevar_id_t) id];
+
+ /* Don't evaluate timing variables that were never used. */
+ if (!tv->used)
+ continue;
+
+ if (startswith (tv->name, phase_prefix))
+ {
+ phase_user += tv->elapsed.user;
+ phase_sys += tv->elapsed.sys;
+ phase_wall += tv->elapsed.wall;
+ phase_ggc_mem += tv->elapsed.ggc_mem;
+ }
+ }
+
+ if (phase_user > total->user * tolerance
+ || phase_sys > total->sys * tolerance
+ || phase_wall > total->wall * tolerance
+ || phase_ggc_mem > total->ggc_mem * tolerance)
+ {
+
+ fprintf (fp, "Timing error: total of phase timers exceeds total time.\n");
+ if (phase_user > total->user)
+ fprintf (fp, "user %24.18e > %24.18e\n", phase_user, total->user);
+ if (phase_sys > total->sys)
+ fprintf (fp, "sys %24.18e > %24.18e\n", phase_sys, total->sys);
+ if (phase_wall > total->wall)
+ fprintf (fp, "wall %24.18e > %24.18e\n", phase_wall, total->wall);
+ if (phase_ggc_mem > total->ggc_mem)
+ fprintf (fp, "ggc_mem %24lu > %24lu\n", (unsigned long)phase_ggc_mem,
+ (unsigned long)total->ggc_mem);
+ gcc_unreachable ();
+ }
+}
+
+/* Helper function for timer::print. */
+
+void
+timer::print_row (FILE *fp,
+ const timevar_time_def *total,
+ const char *name, const timevar_time_def &elapsed)
+{
+ /* The timing variable name. */
+ fprintf (fp, " %-35s:", name);
+
+#ifdef HAVE_USER_TIME
+ /* Print user-mode time for this process. */
+ fprintf (fp, "%7.2f (%3.0f%%)",
+ elapsed.user,
+ (total->user == 0 ? 0 : elapsed.user / total->user) * 100);
+#endif /* HAVE_USER_TIME */
+
+#ifdef HAVE_SYS_TIME
+ /* Print system-mode time for this process. */
+ fprintf (fp, "%7.2f (%3.0f%%)",
+ elapsed.sys,
+ (total->sys == 0 ? 0 : elapsed.sys / total->sys) * 100);
+#endif /* HAVE_SYS_TIME */
+
+#ifdef HAVE_WALL_TIME
+ /* Print wall clock time elapsed. */
+ fprintf (fp, "%7.2f (%3.0f%%)",
+ elapsed.wall,
+ (total->wall == 0 ? 0 : elapsed.wall / total->wall) * 100);
+#endif /* HAVE_WALL_TIME */
+
+ /* Print the amount of ggc memory allocated. */
+ fprintf (fp, PRsa (6) " (%3.0f%%)",
+ SIZE_AMOUNT (elapsed.ggc_mem),
+ (total->ggc_mem == 0
+ ? 0
+ : (float) elapsed.ggc_mem / total->ggc_mem) * 100);
+
+ putc ('\n', fp);
+}
+
+/* Return whether ELAPSED is all zero. */
+
+bool
+timer::all_zero (const timevar_time_def &elapsed)
+{
+ const double tiny = 5e-3;
+ return (elapsed.user < tiny
+ && elapsed.sys < tiny
+ && elapsed.wall < tiny
+ && elapsed.ggc_mem < GGC_MEM_BOUND);
+}
+
+/* Summarize timing variables to FP. The timing variable TV_TOTAL has
+ a special meaning -- it's considered to be the total elapsed time,
+ for normalizing the others, and is displayed last. */
+
+void
+timer::print (FILE *fp)
+{
+ /* Only print stuff if we have some sort of time information. */
+#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
+ unsigned int /* timevar_id_t */ id;
+ const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
+ struct timevar_time_def now;
+
+ /* Update timing information in case we're calling this from GDB. */
+
+ if (fp == 0)
+ fp = stderr;
+
+ /* What time is it? */
+ get_time (&now);
+
+ /* If the stack isn't empty, attribute the current elapsed time to
+ the old topmost element. */
+ if (m_stack)
+ timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
+
+ /* Reset the start time; from now on, time is attributed to
+ TIMEVAR. */
+ m_start_time = now;
+
+ fprintf (fp, "\n%-35s%16s%14s%14s%14s\n", "Time variable", "usr", "sys",
+ "wall", "GGC");
+ if (m_jit_client_items)
+ fputs ("GCC items:\n", fp);
+ for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
+ {
+ const timevar_def *tv = &m_timevars[(timevar_id_t) id];
+
+ /* Don't print the total execution time here; that goes at the
+ end. */
+ if ((timevar_id_t) id == TV_TOTAL)
+ continue;
+
+ /* Don't print timing variables that were never used. */
+ if (!tv->used)
+ continue;
+
+ bool any_children_with_time = false;
+ if (tv->children)
+ for (child_map_t::iterator i = tv->children->begin ();
+ i != tv->children->end (); ++i)
+ if (! all_zero ((*i).second))
+ {
+ any_children_with_time = true;
+ break;
+ }
+
+ /* Don't print timing variables if we're going to get a row of
+ zeroes. Unless there are children with non-zero time. */
+ if (! any_children_with_time
+ && all_zero (tv->elapsed))
+ continue;
+
+ print_row (fp, total, tv->name, tv->elapsed);
+
+ if (tv->children)
+ for (child_map_t::iterator i = tv->children->begin ();
+ i != tv->children->end (); ++i)
+ {
+ timevar_def *tv2 = (*i).first;
+ /* Don't print timing variables if we're going to get a row of
+ zeroes. */
+ if (! all_zero ((*i).second))
+ {
+ char lname[256];
+ snprintf (lname, 256, "`- %s", tv2->name);
+ print_row (fp, total, lname, (*i).second);
+ }
+ }
+ }
+ if (m_jit_client_items)
+ m_jit_client_items->print (fp, total);
+
+ /* Print total time. */
+ fprintf (fp, " %-35s:", "TOTAL");
+#ifdef HAVE_USER_TIME
+ fprintf (fp, "%7.2f ", total->user);
+#endif
+#ifdef HAVE_SYS_TIME
+ fprintf (fp, "%8.2f ", total->sys);
+#endif
+#ifdef HAVE_WALL_TIME
+ fprintf (fp, "%8.2f ", total->wall);
+#endif
+ fprintf (fp, PRsa (7) "\n", SIZE_AMOUNT (total->ggc_mem));
+
+ if (CHECKING_P || flag_checking)
+ fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
+ if (CHECKING_P)
+ fprintf (fp, "Configure with --enable-checking=release to disable checks.\n");
+#ifndef ENABLE_ASSERT_CHECKING
+ fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n");
+ fprintf (fp, "Configure with --enable-checking=release to enable checks.\n");
+#endif
+
+#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
+ || defined (HAVE_WALL_TIME) */
+
+ validate_phases (fp);
+}
+
+/* Get the name of the topmost item. For use by jit for validating
+ inputs to gcc_jit_timer_pop. */
+const char *
+timer::get_topmost_item_name () const
+{
+ if (m_stack)
+ return m_stack->timevar->name;
+ else
+ return NULL;
+}
+
+/* Prints a message to stderr stating that time elapsed in STR is
+ TOTAL (given in microseconds). */
+
+void
+print_time (const char *str, long total)
+{
+ long all_time = get_run_time ();
+ fprintf (stderr,
+ "time in %s: %ld.%06ld (%ld%%)\n",
+ str, total / 1000000, total % 1000000,
+ all_time == 0 ? 0
+ : (long) (((100.0 * (double) total) / (double) all_time) + .5));
+}
diff --git a/support/cpp/gcc/timevar.def b/support/cpp/gcc/timevar.def
new file mode 100644
index 000000000..2dae5e1c7
--- /dev/null
+++ b/support/cpp/gcc/timevar.def
@@ -0,0 +1,343 @@
+/* This file contains the definitions for timing variables used to
+ measure run-time performance of the compiler.
+ Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ Contributed by Alex Samuel <samuel@codesourcery.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.
+
+ 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 contains timing variable definitions, used by timevar.h
+ and timevar.cc.
+
+ Syntax:
+
+ DEFTIMEVAR (id, name)
+
+ where ID is the enumeral value used to identify the timing
+ variable, and NAME is a character string describing its purpose. */
+
+/* The total execution time. */
+DEFTIMEVAR (TV_TOTAL , "total time")
+/* The compiler phases.
+
+ These must be mutually exclusive, and the NAME field must begin
+ with "phase".
+
+ Also, their sum must be within a millionth of the total time (see
+ validate_phases). */
+DEFTIMEVAR (TV_PHASE_SETUP , "phase setup")
+DEFTIMEVAR (TV_PHASE_PARSING , "phase parsing")
+DEFTIMEVAR (TV_PHASE_DEFERRED , "phase lang. deferred")
+DEFTIMEVAR (TV_PHASE_LATE_PARSING_CLEANUPS, "phase late parsing cleanups")
+DEFTIMEVAR (TV_PHASE_OPT_GEN , "phase opt and generate")
+DEFTIMEVAR (TV_PHASE_LATE_ASM , "phase last asm")
+DEFTIMEVAR (TV_PHASE_STREAM_IN , "phase stream in")
+DEFTIMEVAR (TV_PHASE_STREAM_OUT , "phase stream out")
+DEFTIMEVAR (TV_PHASE_FINALIZE , "phase finalize")
+
+/* Concurrent timers, indicated by "|". */
+DEFTIMEVAR (TV_NAME_LOOKUP , "|name lookup")
+DEFTIMEVAR (TV_OVERLOAD , "|overload resolution")
+
+/* Time spent garbage-collecting. */
+DEFTIMEVAR (TV_GC , "garbage collection")
+
+/* Time spent generating dump files. */
+DEFTIMEVAR (TV_DUMP , "dump files")
+
+/* Time spent saving/restoring PCH state. */
+DEFTIMEVAR (TV_PCH_SAVE , "PCH main state save")
+DEFTIMEVAR (TV_PCH_CPP_SAVE , "PCH preprocessor state save")
+DEFTIMEVAR (TV_PCH_PTR_REALLOC , "PCH pointer reallocation")
+DEFTIMEVAR (TV_PCH_PTR_SORT , "PCH pointer sort")
+DEFTIMEVAR (TV_PCH_RESTORE , "PCH main state restore")
+DEFTIMEVAR (TV_PCH_CPP_RESTORE , "PCH preprocessor state restore")
+
+DEFTIMEVAR (TV_CGRAPH , "callgraph construction")
+DEFTIMEVAR (TV_CGRAPHOPT , "callgraph optimization")
+DEFTIMEVAR (TV_CGRAPH_FUNC_EXPANSION , "callgraph functions expansion")
+DEFTIMEVAR (TV_CGRAPH_IPA_PASSES , "callgraph ipa passes")
+DEFTIMEVAR (TV_IPA_ODR , "ipa ODR types")
+DEFTIMEVAR (TV_IPA_FNSUMMARY , "ipa function summary")
+DEFTIMEVAR (TV_IPA_UNREACHABLE , "ipa dead code removal")
+DEFTIMEVAR (TV_IPA_INHERITANCE , "ipa inheritance graph")
+DEFTIMEVAR (TV_IPA_VIRTUAL_CALL , "ipa virtual call target")
+DEFTIMEVAR (TV_IPA_DEVIRT , "ipa devirtualization")
+DEFTIMEVAR (TV_IPA_CONSTANT_PROP , "ipa cp")
+DEFTIMEVAR (TV_IPA_INLINING , "ipa inlining heuristics")
+DEFTIMEVAR (TV_IPA_FNSPLIT , "ipa function splitting")
+DEFTIMEVAR (TV_IPA_COMDATS , "ipa comdats")
+DEFTIMEVAR (TV_IPA_OPT , "ipa various optimizations")
+DEFTIMEVAR (TV_IPA_LTO_DECOMPRESS , "lto stream decompression")
+DEFTIMEVAR (TV_IPA_LTO_COMPRESS , "lto stream compression")
+DEFTIMEVAR (TV_IPA_LTO_OUTPUT , "lto stream output")
+DEFTIMEVAR (TV_IPA_LTO_GIMPLE_IN , "ipa lto gimple in")
+DEFTIMEVAR (TV_IPA_LTO_GIMPLE_OUT , "ipa lto gimple out")
+DEFTIMEVAR (TV_IPA_LTO_DECL_IN , "ipa lto decl in")
+DEFTIMEVAR (TV_IPA_LTO_DECL_OUT , "ipa lto decl out")
+DEFTIMEVAR (TV_IPA_LTO_CTORS_IN , "ipa lto constructors in")
+DEFTIMEVAR (TV_IPA_LTO_CTORS_OUT , "ipa lto constructors out")
+DEFTIMEVAR (TV_IPA_LTO_CGRAPH_IO , "ipa lto cgraph I/O")
+DEFTIMEVAR (TV_IPA_LTO_DECL_MERGE , "ipa lto decl merge")
+DEFTIMEVAR (TV_IPA_LTO_CGRAPH_MERGE , "ipa lto cgraph merge")
+DEFTIMEVAR (TV_LTO , "lto")
+DEFTIMEVAR (TV_WHOPR_WPA , "whopr wpa")
+DEFTIMEVAR (TV_WHOPR_WPA_IO , "whopr wpa I/O")
+DEFTIMEVAR (TV_WHOPR_PARTITIONING , "whopr partitioning")
+DEFTIMEVAR (TV_WHOPR_LTRANS , "whopr ltrans")
+DEFTIMEVAR (TV_IPA_REFERENCE , "ipa reference")
+DEFTIMEVAR (TV_IPA_PROFILE , "ipa profile")
+DEFTIMEVAR (TV_IPA_AUTOFDO , "auto profile")
+DEFTIMEVAR (TV_IPA_PURE_CONST , "ipa pure const")
+DEFTIMEVAR (TV_IPA_ICF , "ipa icf")
+DEFTIMEVAR (TV_IPA_PTA , "ipa points-to")
+DEFTIMEVAR (TV_IPA_SRA , "ipa SRA")
+DEFTIMEVAR (TV_IPA_FREE_LANG_DATA , "ipa free lang data")
+DEFTIMEVAR (TV_IPA_FREE_INLINE_SUMMARY, "ipa free inline summary")
+DEFTIMEVAR (TV_IPA_MODREF , "ipa modref")
+/* Time spent by constructing CFG. */
+DEFTIMEVAR (TV_CFG , "cfg construction")
+/* Time spent by cleaning up CFG. */
+DEFTIMEVAR (TV_CLEANUP_CFG , "cfg cleanup")
+DEFTIMEVAR (TV_CFG_VERIFY , "CFG verifier")
+DEFTIMEVAR (TV_DELETE_TRIVIALLY_DEAD , "trivially dead code")
+
+/* Time spent in dataflow problems. */
+DEFTIMEVAR (TV_DF_SCAN , "df scan insns")
+DEFTIMEVAR (TV_DF_MD , "df multiple defs")
+DEFTIMEVAR (TV_DF_RD , "df reaching defs")
+DEFTIMEVAR (TV_DF_LR , "df live regs")
+DEFTIMEVAR (TV_DF_LIVE , "df live&initialized regs")
+DEFTIMEVAR (TV_DF_MIR , "df must-initialized regs")
+DEFTIMEVAR (TV_DF_CHAIN , "df use-def / def-use chains")
+DEFTIMEVAR (TV_DF_WORD_LR , "df live reg subwords")
+DEFTIMEVAR (TV_DF_NOTE , "df reg dead/unused notes")
+DEFTIMEVAR (TV_REG_STATS , "register information")
+
+DEFTIMEVAR (TV_ALIAS_ANALYSIS , "alias analysis")
+DEFTIMEVAR (TV_ALIAS_STMT_WALK , "alias stmt walking")
+DEFTIMEVAR (TV_REG_SCAN , "register scan")
+DEFTIMEVAR (TV_REBUILD_JUMP , "rebuild jump labels")
+/* Timing in various stages of the compiler. */
+DEFTIMEVAR (TV_CPP , "preprocessing")
+DEFTIMEVAR (TV_LEX , "lexical analysis")
+DEFTIMEVAR (TV_PARSE_GLOBAL , "parser (global)")
+DEFTIMEVAR (TV_PARSE_STRUCT , "parser struct body")
+DEFTIMEVAR (TV_PARSE_ENUM , "parser enumerator list")
+DEFTIMEVAR (TV_PARSE_FUNC , "parser function body")
+DEFTIMEVAR (TV_PARSE_INLINE , "parser inl. func. body")
+DEFTIMEVAR (TV_PARSE_INMETH , "parser inl. meth. body")
+DEFTIMEVAR (TV_TEMPLATE_INST , "template instantiation")
+DEFTIMEVAR (TV_CONSTEXPR , "constant expression evaluation")
+DEFTIMEVAR (TV_CONSTRAINT_NORM , "constraint normalization")
+DEFTIMEVAR (TV_CONSTRAINT_SAT , "constraint satisfaction")
+DEFTIMEVAR (TV_CONSTRAINT_SUB , "constraint subsumption")
+DEFTIMEVAR (TV_MODULE_IMPORT , "module import")
+DEFTIMEVAR (TV_MODULE_EXPORT , "module export")
+DEFTIMEVAR (TV_MODULE_MAPPER , "module mapper")
+DEFTIMEVAR (TV_FLATTEN_INLINING , "flatten inlining")
+DEFTIMEVAR (TV_EARLY_INLINING , "early inlining heuristics")
+DEFTIMEVAR (TV_INLINE_PARAMETERS , "inline parameters")
+DEFTIMEVAR (TV_INTEGRATION , "integration")
+DEFTIMEVAR (TV_TREE_GIMPLIFY , "tree gimplify")
+DEFTIMEVAR (TV_TREE_EH , "tree eh")
+DEFTIMEVAR (TV_TREE_CFG , "tree CFG construction")
+DEFTIMEVAR (TV_TREE_CLEANUP_CFG , "tree CFG cleanup")
+DEFTIMEVAR (TV_TREE_TAIL_MERGE , "tree tail merge")
+DEFTIMEVAR (TV_TREE_VRP , "tree VRP")
+DEFTIMEVAR (TV_TREE_VRP_THREADER , "tree VRP threader")
+DEFTIMEVAR (TV_TREE_EARLY_VRP , "tree Early VRP")
+DEFTIMEVAR (TV_TREE_COPY_PROP , "tree copy propagation")
+DEFTIMEVAR (TV_FIND_REFERENCED_VARS , "tree find ref. vars")
+DEFTIMEVAR (TV_TREE_PTA , "tree PTA")
+DEFTIMEVAR (TV_TREE_SSA_OTHER , "tree SSA other")
+DEFTIMEVAR (TV_TREE_INTO_SSA , "tree SSA rewrite")
+DEFTIMEVAR (TV_TREE_SSA_INCREMENTAL , "tree SSA incremental")
+DEFTIMEVAR (TV_TREE_OPS , "tree operand scan")
+DEFTIMEVAR (TV_TREE_SSA_DOMINATOR_OPTS , "dominator optimization")
+DEFTIMEVAR (TV_TREE_SSA_THREAD_JUMPS , "backwards jump threading")
+DEFTIMEVAR (TV_TREE_SRA , "tree SRA")
+DEFTIMEVAR (TV_ISOLATE_ERRONEOUS_PATHS , "isolate eroneous paths")
+DEFTIMEVAR (TV_TREE_CCP , "tree CCP")
+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_SINK , "tree code sinking")
+DEFTIMEVAR (TV_TREE_PHIOPT , "tree linearize phis")
+DEFTIMEVAR (TV_TREE_BACKPROP , "tree backward propagate")
+DEFTIMEVAR (TV_TREE_FORWPROP , "tree forward propagate")
+DEFTIMEVAR (TV_TREE_PHIPROP , "tree phiprop")
+DEFTIMEVAR (TV_TREE_DCE , "tree conservative DCE")
+DEFTIMEVAR (TV_TREE_CD_DCE , "tree aggressive DCE")
+DEFTIMEVAR (TV_TREE_CALL_CDCE , "tree buildin call DCE")
+DEFTIMEVAR (TV_TREE_DSE , "tree DSE")
+DEFTIMEVAR (TV_TREE_MERGE_PHI , "PHI merge")
+DEFTIMEVAR (TV_TREE_LOOP , "tree loop optimization")
+DEFTIMEVAR (TV_TREE_NOLOOP , "loopless fn")
+DEFTIMEVAR (TV_TREE_LOOP_BOUNDS , "tree loop bounds")
+DEFTIMEVAR (TV_LIM , "tree loop invariant motion")
+DEFTIMEVAR (TV_LINTERCHANGE , "tree loop interchange")
+DEFTIMEVAR (TV_TREE_LOOP_IVCANON , "tree canonical iv")
+DEFTIMEVAR (TV_SCEV_CONST , "scev constant prop")
+DEFTIMEVAR (TV_TREE_LOOP_UNSWITCH , "tree loop unswitching")
+DEFTIMEVAR (TV_LOOP_SPLIT , "loop splitting")
+DEFTIMEVAR (TV_LOOP_JAM , "unroll and jam")
+DEFTIMEVAR (TV_COMPLETE_UNROLL , "complete unrolling")
+DEFTIMEVAR (TV_SCALAR_CLEANUP , "scalar cleanup")
+DEFTIMEVAR (TV_TREE_PARALLELIZE_LOOPS, "tree parallelize loops")
+DEFTIMEVAR (TV_TREE_VECTORIZATION , "tree vectorization")
+DEFTIMEVAR (TV_TREE_SLP_VECTORIZATION, "tree slp vectorization")
+DEFTIMEVAR (TV_GRAPHITE , "Graphite")
+DEFTIMEVAR (TV_GRAPHITE_TRANSFORMS , "Graphite loop transforms")
+DEFTIMEVAR (TV_GRAPHITE_DATA_DEPS , "Graphite data dep analysis")
+DEFTIMEVAR (TV_GRAPHITE_CODE_GEN , "Graphite code generation")
+DEFTIMEVAR (TV_TREE_LOOP_DISTRIBUTION, "tree loop distribution")
+DEFTIMEVAR (TV_CHECK_DATA_DEPS , "tree check data dependences")
+DEFTIMEVAR (TV_TREE_PREFETCH , "tree prefetching")
+DEFTIMEVAR (TV_TREE_LOOP_IVOPTS , "tree iv optimization")
+DEFTIMEVAR (TV_PREDCOM , "predictive commoning")
+DEFTIMEVAR (TV_TREE_CH , "tree copy headers")
+DEFTIMEVAR (TV_TREE_SSA_UNCPROP , "tree SSA uncprop")
+DEFTIMEVAR (TV_TREE_NRV , "tree NRV optimization")
+DEFTIMEVAR (TV_TREE_COPY_RENAME , "tree rename SSA copies")
+DEFTIMEVAR (TV_TREE_SSA_VERIFY , "tree SSA verifier")
+DEFTIMEVAR (TV_TREE_STMT_VERIFY , "tree STMT verifier")
+DEFTIMEVAR (TV_TREE_SWITCH_CONVERSION, "tree switch conversion")
+DEFTIMEVAR (TV_TREE_SWITCH_LOWERING, "tree switch lowering")
+DEFTIMEVAR (TV_TREE_RECIP , "gimple CSE reciprocals")
+DEFTIMEVAR (TV_TREE_SINCOS , "gimple CSE sin/cos")
+DEFTIMEVAR (TV_TREE_WIDEN_MUL , "gimple widening/fma detection")
+DEFTIMEVAR (TV_TRANS_MEM , "transactional memory")
+DEFTIMEVAR (TV_TREE_STRLEN , "tree strlen optimization")
+DEFTIMEVAR (TV_TREE_MODREF , "tree modref")
+DEFTIMEVAR (TV_CGRAPH_VERIFY , "callgraph verifier")
+DEFTIMEVAR (TV_DOM_FRONTIERS , "dominance frontiers")
+DEFTIMEVAR (TV_DOMINANCE , "dominance computation")
+DEFTIMEVAR (TV_CONTROL_DEPENDENCES , "control dependences")
+DEFTIMEVAR (TV_OUT_OF_SSA , "out of ssa")
+DEFTIMEVAR (TV_VAR_EXPAND , "expand vars")
+DEFTIMEVAR (TV_EXPAND , "expand")
+DEFTIMEVAR (TV_POST_EXPAND , "post expand cleanups")
+DEFTIMEVAR (TV_VARCONST , "varconst")
+DEFTIMEVAR (TV_LOWER_SUBREG , "lower subreg")
+DEFTIMEVAR (TV_JUMP , "jump")
+DEFTIMEVAR (TV_FWPROP , "forward prop")
+DEFTIMEVAR (TV_CSE , "CSE")
+DEFTIMEVAR (TV_DCE , "dead code elimination")
+DEFTIMEVAR (TV_DSE1 , "dead store elim1")
+DEFTIMEVAR (TV_DSE2 , "dead store elim2")
+DEFTIMEVAR (TV_LOOP , "loop analysis")
+DEFTIMEVAR (TV_LOOP_INIT , "loop init")
+DEFTIMEVAR (TV_LOOP_VERSIONING , "loop versioning")
+DEFTIMEVAR (TV_LOOP_MOVE_INVARIANTS , "loop invariant motion")
+DEFTIMEVAR (TV_LOOP_UNROLL , "loop unrolling")
+DEFTIMEVAR (TV_LOOP_DOLOOP , "loop doloop")
+DEFTIMEVAR (TV_LOOP_FINI , "loop fini")
+DEFTIMEVAR (TV_CPROP , "CPROP")
+DEFTIMEVAR (TV_PRE , "PRE")
+DEFTIMEVAR (TV_HOIST , "code hoisting")
+DEFTIMEVAR (TV_LSM , "LSM")
+DEFTIMEVAR (TV_TRACER , "tracer")
+DEFTIMEVAR (TV_WEB , "web")
+DEFTIMEVAR (TV_AUTO_INC_DEC , "auto inc dec")
+DEFTIMEVAR (TV_CSE2 , "CSE 2")
+DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
+DEFTIMEVAR (TV_COMBINE , "combiner")
+DEFTIMEVAR (TV_IFCVT , "if-conversion")
+DEFTIMEVAR (TV_MODE_SWITCH , "mode switching")
+DEFTIMEVAR (TV_SMS , "sms modulo scheduling")
+DEFTIMEVAR (TV_LIVE_RANGE_SHRINKAGE , "live range shrinkage")
+DEFTIMEVAR (TV_SCHED , "scheduling")
+DEFTIMEVAR (TV_EARLY_REMAT , "early rematerialization")
+DEFTIMEVAR (TV_IRA , "integrated RA")
+DEFTIMEVAR (TV_LRA , "LRA non-specific")
+DEFTIMEVAR (TV_LRA_ELIMINATE , "LRA virtuals elimination")
+DEFTIMEVAR (TV_LRA_INHERITANCE , "LRA reload inheritance")
+DEFTIMEVAR (TV_LRA_CREATE_LIVE_RANGES, "LRA create live ranges")
+DEFTIMEVAR (TV_LRA_ASSIGN , "LRA hard reg assignment")
+DEFTIMEVAR (TV_LRA_COALESCE , "LRA coalesce pseudo regs")
+DEFTIMEVAR (TV_LRA_REMAT , "LRA rematerialization")
+DEFTIMEVAR (TV_RELOAD , "reload")
+DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs")
+DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload")
+DEFTIMEVAR (TV_REE , "ree")
+DEFTIMEVAR (TV_THREAD_PROLOGUE_AND_EPILOGUE, "thread pro- & epilogue")
+DEFTIMEVAR (TV_IFCVT2 , "if-conversion 2")
+DEFTIMEVAR (TV_SPLIT_PATHS , "split paths")
+DEFTIMEVAR (TV_COMBINE_STACK_ADJUST , "combine stack adjustments")
+DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2")
+DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers")
+DEFTIMEVAR (TV_SCHED_FUSION , "scheduling fusion")
+DEFTIMEVAR (TV_CPROP_REGISTERS , "hard reg cprop")
+DEFTIMEVAR (TV_SCHED2 , "scheduling 2")
+DEFTIMEVAR (TV_MACH_DEP , "machine dep reorg")
+DEFTIMEVAR (TV_DBR_SCHED , "delay branch sched")
+DEFTIMEVAR (TV_REORDER_BLOCKS , "reorder blocks")
+DEFTIMEVAR (TV_SHORTEN_BRANCH , "shorten branches")
+DEFTIMEVAR (TV_REG_STACK , "reg stack")
+DEFTIMEVAR (TV_FINAL , "final")
+DEFTIMEVAR (TV_VAROUT , "variable output")
+DEFTIMEVAR (TV_SYMOUT , "symout")
+DEFTIMEVAR (TV_VAR_TRACKING , "variable tracking")
+DEFTIMEVAR (TV_VAR_TRACKING_DATAFLOW , "var-tracking dataflow")
+DEFTIMEVAR (TV_VAR_TRACKING_EMIT , "var-tracking emit")
+DEFTIMEVAR (TV_TREE_IFCOMBINE , "tree if-combine")
+DEFTIMEVAR (TV_TREE_IF_TO_SWITCH , "if to switch conversion")
+DEFTIMEVAR (TV_TREE_UNINIT , "uninit var analysis")
+DEFTIMEVAR (TV_PLUGIN_INIT , "plugin initialization")
+DEFTIMEVAR (TV_PLUGIN_RUN , "plugin execution")
+DEFTIMEVAR (TV_GIMPLE_SLSR , "straight-line strength reduction")
+DEFTIMEVAR (TV_GIMPLE_STORE_MERGING , "store merging")
+DEFTIMEVAR (TV_VTABLE_VERIFICATION , "vtable verification")
+DEFTIMEVAR (TV_TREE_UBSAN , "tree ubsan")
+DEFTIMEVAR (TV_INITIALIZE_RTL , "initialize rtl")
+DEFTIMEVAR (TV_GIMPLE_LADDRESS , "address lowering")
+DEFTIMEVAR (TV_TREE_LOOP_IFCVT , "tree loop if-conversion")
+DEFTIMEVAR (TV_WARN_ACCESS , "access analysis")
+
+/* Everything else in rest_of_compilation not included above. */
+DEFTIMEVAR (TV_EARLY_LOCAL , "early local passes")
+DEFTIMEVAR (TV_OPTIMIZE , "unaccounted optimizations")
+DEFTIMEVAR (TV_REST_OF_COMPILATION , "rest of compilation")
+DEFTIMEVAR (TV_POSTRELOAD , "unaccounted post reload")
+DEFTIMEVAR (TV_LATE_COMPILATION , "unaccounted late compilation")
+DEFTIMEVAR (TV_REMOVE_UNUSED , "remove unused locals")
+DEFTIMEVAR (TV_ADDRESS_TAKEN , "address taken")
+DEFTIMEVAR (TV_TODO , "unaccounted todo")
+DEFTIMEVAR (TV_VERIFY_LOOP_CLOSED , "verify loop closed")
+DEFTIMEVAR (TV_VERIFY_RTL_SHARING , "verify RTL sharing")
+DEFTIMEVAR (TV_REBUILD_FREQUENCIES , "rebuild frequencies")
+DEFTIMEVAR (TV_REPAIR_LOOPS , "repair loop structures")
+
+/* Stuff used by libgccjit.so. */
+DEFTIMEVAR (TV_JIT_REPLAY , "replay of JIT client activity")
+DEFTIMEVAR (TV_ASSEMBLE , "assemble JIT code")
+DEFTIMEVAR (TV_LINK , "link JIT code")
+DEFTIMEVAR (TV_LOAD , "load JIT result")
+DEFTIMEVAR (TV_JIT_ACQUIRING_MUTEX , "acquiring JIT mutex")
+DEFTIMEVAR (TV_JIT_CLIENT_CODE , "JIT client code")
+
+/* Analyzer timevars. */
+DEFTIMEVAR (TV_ANALYZER , "analyzer")
+DEFTIMEVAR (TV_ANALYZER_SUPERGRAPH , "analyzer: supergraph")
+DEFTIMEVAR (TV_ANALYZER_STATE_PURGE , "analyzer: state purge")
+DEFTIMEVAR (TV_ANALYZER_PLAN , "analyzer: planning")
+DEFTIMEVAR (TV_ANALYZER_SCC , "analyzer: scc")
+DEFTIMEVAR (TV_ANALYZER_WORKLIST , "analyzer: processing worklist")
+DEFTIMEVAR (TV_ANALYZER_DUMP , "analyzer: dump")
+DEFTIMEVAR (TV_ANALYZER_DIAGNOSTICS , "analyzer: emitting diagnostics")
+DEFTIMEVAR (TV_ANALYZER_SHORTEST_PATHS, "analyzer: shortest paths")
diff --git a/support/cpp/gcc/timevar.h b/support/cpp/gcc/timevar.h
new file mode 100644
index 000000000..5715d69be
--- /dev/null
+++ b/support/cpp/gcc/timevar.h
@@ -0,0 +1,301 @@
+/* Timing variables for measuring compiler performance.
+ Copyright (C) 2000-2022 Free Software Foundation, Inc.
+ Contributed by Alex Samuel <samuel@codesourcery.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.
+
+ 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_TIMEVAR_H
+#define GCC_TIMEVAR_H
+
+/* Timing variables are used to measure elapsed time in various
+ portions of the compiler. Each measures elapsed user, system, and
+ wall-clock time, as appropriate to and supported by the host
+ system.
+
+ Timing variables are defined using the DEFTIMEVAR macro in
+ timevar.def. Each has an enumeral identifier, used when referring
+ to the timing variable in code, and a character string name.
+
+ Timing variables can be used in two ways:
+
+ - On the timing stack, using timevar_push and timevar_pop.
+ Timing variables may be pushed onto the stack; elapsed time is
+ attributed to the topmost timing variable on the stack. When
+ another variable is pushed on, the previous topmost variable is
+ `paused' until the pushed variable is popped back off.
+
+ - As a standalone timer, using timevar_start and timevar_stop.
+ All time elapsed between the two calls is attributed to the
+ variable.
+*/
+
+/* This structure stores the various varieties of time that can be
+ measured. Times are stored in seconds. The time may be an
+ absolute time or a time difference; in the former case, the time
+ base is undefined, except that the difference between two times
+ produces a valid time difference. */
+
+struct timevar_time_def
+{
+ /* User time in this process. */
+ double user;
+
+ /* System time (if applicable for this host platform) in this
+ process. */
+ double sys;
+
+ /* Wall clock time. */
+ double wall;
+
+ /* Garbage collector memory. */
+ size_t ggc_mem;
+};
+
+/* An enumeration of timing variable identifiers. Constructed from
+ the contents of timevar.def. */
+
+#define DEFTIMEVAR(identifier__, name__) \
+ identifier__,
+typedef enum
+{
+ TV_NONE,
+#include "timevar.def"
+ TIMEVAR_LAST
+}
+timevar_id_t;
+#undef DEFTIMEVAR
+
+/* A class to hold all state relating to timing. */
+
+class timer;
+
+/* The singleton instance of timing state.
+
+ This is non-NULL if timevars should be used. In GCC, this happens with
+ the -ftime-report flag. Hence this is NULL for the common,
+ needs-to-be-fast case, with an early reject happening for this being
+ NULL. */
+extern timer *g_timer;
+
+/* Total amount of memory allocated by garbage collector. */
+extern size_t timevar_ggc_mem_total;
+
+extern void timevar_init (void);
+extern void timevar_start (timevar_id_t);
+extern void timevar_stop (timevar_id_t);
+extern bool timevar_cond_start (timevar_id_t);
+extern void timevar_cond_stop (timevar_id_t, bool);
+
+/* The public (within GCC) interface for timing. */
+
+class timer
+{
+ public:
+ timer ();
+ ~timer ();
+
+ void start (timevar_id_t tv);
+ void stop (timevar_id_t tv);
+ void push (timevar_id_t tv);
+ void pop (timevar_id_t tv);
+ bool cond_start (timevar_id_t tv);
+ void cond_stop (timevar_id_t tv);
+
+ void push_client_item (const char *item_name);
+ void pop_client_item ();
+
+ void print (FILE *fp);
+
+ const char *get_topmost_item_name () const;
+
+ private:
+ /* Private member functions. */
+ void validate_phases (FILE *fp) const;
+
+ struct timevar_def;
+ void push_internal (struct timevar_def *tv);
+ void pop_internal ();
+ static void print_row (FILE *fp,
+ const timevar_time_def *total,
+ const char *name, const timevar_time_def &elapsed);
+ static bool all_zero (const timevar_time_def &elapsed);
+
+ private:
+ typedef hash_map<timevar_def *, timevar_time_def> child_map_t;
+
+ /* Private type: a timing variable. */
+ struct timevar_def
+ {
+ /* Elapsed time for this variable. */
+ struct timevar_time_def elapsed;
+
+ /* If this variable is timed independently of the timing stack,
+ using timevar_start, this contains the start time. */
+ struct timevar_time_def start_time;
+
+ /* The name of this timing variable. */
+ const char *name;
+
+ /* Nonzero if this timing variable is running as a standalone
+ timer. */
+ unsigned standalone : 1;
+
+ /* Nonzero if this timing variable was ever started or pushed onto
+ the timing stack. */
+ unsigned used : 1;
+
+ child_map_t *children;
+ };
+
+ /* Private type: an element on the timing stack
+ Elapsed time is attributed to the topmost timing variable on the
+ stack. */
+ struct timevar_stack_def
+ {
+ /* The timing variable at this stack level. */
+ struct timevar_def *timevar;
+
+ /* The next lower timing variable context in the stack. */
+ struct timevar_stack_def *next;
+ };
+
+ /* A class for managing a collection of named timing items, for use
+ e.g. by libgccjit for timing client code. This class is declared
+ inside timevar.cc to avoid everything using timevar.h
+ from needing vec and hash_map. */
+ class named_items;
+
+ private:
+
+ /* Data members (all private). */
+
+ /* Declared timing variables. Constructed from the contents of
+ timevar.def. */
+ timevar_def m_timevars[TIMEVAR_LAST];
+
+ /* The top of the timing stack. */
+ timevar_stack_def *m_stack;
+
+ /* A list of unused (i.e. allocated and subsequently popped)
+ timevar_stack_def instances. */
+ timevar_stack_def *m_unused_stack_instances;
+
+ /* The time at which the topmost element on the timing stack was
+ pushed. Time elapsed since then is attributed to the topmost
+ element. */
+ timevar_time_def m_start_time;
+
+ /* If non-NULL, for use when timing libgccjit's client code. */
+ named_items *m_jit_client_items;
+
+ friend class named_items;
+};
+
+/* Provided for backward compatibility. */
+static inline void
+timevar_push (timevar_id_t tv)
+{
+ if (g_timer)
+ g_timer->push (tv);
+}
+
+static inline void
+timevar_pop (timevar_id_t tv)
+{
+ if (g_timer)
+ g_timer->pop (tv);
+}
+
+// This is a simple timevar wrapper class that pushes a timevar in its
+// constructor and pops the timevar in its destructor.
+class auto_timevar
+{
+ public:
+ auto_timevar (timer *t, timevar_id_t tv)
+ : m_timer (t),
+ m_tv (tv)
+ {
+ if (m_timer)
+ m_timer->push (m_tv);
+ }
+
+ explicit auto_timevar (timevar_id_t tv)
+ : m_timer (g_timer)
+ , m_tv (tv)
+ {
+ if (m_timer)
+ m_timer->push (m_tv);
+ }
+
+ ~auto_timevar ()
+ {
+ if (m_timer)
+ m_timer->pop (m_tv);
+ }
+
+ // Disallow copies.
+ auto_timevar (const auto_timevar &) = delete;
+
+ private:
+ timer *m_timer;
+ timevar_id_t m_tv;
+};
+
+// As above, but use cond_start/stop.
+class auto_cond_timevar
+{
+ public:
+ auto_cond_timevar (timer *t, timevar_id_t tv)
+ : m_timer (t),
+ m_tv (tv)
+ {
+ start ();
+ }
+
+ explicit auto_cond_timevar (timevar_id_t tv)
+ : m_timer (g_timer)
+ , m_tv (tv)
+ {
+ start ();
+ }
+
+ ~auto_cond_timevar ()
+ {
+ if (m_timer && !already_running)
+ m_timer->cond_stop (m_tv);
+ }
+
+ // Disallow copies.
+ auto_cond_timevar (const auto_cond_timevar &) = delete;
+
+ private:
+ void start()
+ {
+ if (m_timer)
+ already_running = m_timer->cond_start (m_tv);
+ else
+ already_running = false;
+ }
+
+ timer *m_timer;
+ timevar_id_t m_tv;
+ bool already_running;
+};
+
+extern void print_time (const char *, long);
+
+#endif /* ! GCC_TIMEVAR_H */
diff --git a/support/cpp/gcc/tm-preds.h b/support/cpp/gcc/tm-preds.h
new file mode 100644
index 000000000..2ba670e8f
--- /dev/null
+++ b/support/cpp/gcc/tm-preds.h
@@ -0,0 +1,5 @@
+// dummy
+
+#ifndef GCC_TM_PREDS_H
+#define GCC_TM_PREDS_H
+#endif
diff --git a/support/cpp/gcc/tm.h b/support/cpp/gcc/tm.h
new file mode 100644
index 000000000..c466cbc1a
--- /dev/null
+++ b/support/cpp/gcc/tm.h
@@ -0,0 +1,37 @@
+// dummy tm.h for sdcpp
+#ifndef GCC_TM_H
+#define GCC_TM_H
+
+// misc stuff scraped together from gcc/config/$target
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#define BYTES_BIG_ENDIAN 0
+// #define UNITS_PER_WORD 1
+#ifndef LIBC_GLIBC
+# define LIBC_GLIBC 1
+#endif
+#ifndef LIBC_UCLIBC
+# define LIBC_UCLIBC 2
+#endif
+#ifndef LIBC_BIONIC
+# define LIBC_BIONIC 3
+#endif
+#ifndef LIBC_MUSL
+# define LIBC_MUSL 4
+#endif
+#ifndef DEFAULT_LIBC
+# define DEFAULT_LIBC LIBC_GLIBC
+#endif
+
+#ifdef IN_GCC
+# include "options.h"
+# include "insn-constants.h"
+#endif
+
+#if defined IN_GCC && !defined GENERATOR_FILE && !defined USED_FOR_TARGET
+# include "insn-flags.h"
+# include "config/dummy/dummy.h"
+#endif
+
+// here?
+#include "defaults.h"
+#endif // guard
diff --git a/support/cpp/gcc/tm_p.h b/support/cpp/gcc/tm_p.h
new file mode 100644
index 000000000..ec357d838
--- /dev/null
+++ b/support/cpp/gcc/tm_p.h
@@ -0,0 +1,6 @@
+#ifndef GCC_TM_P_H
+#define GCC_TM_P_H
+#ifdef IN_GCC
+# include "tm-preds.h"
+#endif
+#endif /* GCC_TM_P_H */
diff --git a/support/cpp/gcc/toplev.cc b/support/cpp/gcc/toplev.cc
new file mode 100644
index 000000000..4d0214ced
--- /dev/null
+++ b/support/cpp/gcc/toplev.cc
@@ -0,0 +1,2487 @@
+/* Top level of GCC compilers (cc1, cc1plus, etc.)
+ 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/>. */
+
+/* This is the top level of cc1/c++.
+ It parses command args, opens files, invokes the various passes
+ in the proper order, and counts the time used by each.
+ Error messages and low-level interface to malloc also handled here. */
+
+#include <iostream>
+#define untested() ( std::cerr << "@@#\n@@@:"<< __FILE__ << ":"<< __LINE__ \
+ <<":" << __func__ << "\n" )
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+// sdcpp #include "gimple.h"
+#include "alloc-pool.h"
+#include "timevar.h"
+#include "memmodel.h"
+#include "insn-config.h"
+#include "ira.h"
+#include "recog.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "varasm.h"
+#include "tree-inline.h"
+#include "version.h"
+#include "flags.h"
+#include "insn-attr.h"
+#include "output.h"
+#include "toplev.h"
+#include "expr.h"
+#include "intl.h"
+#include "tree-diagnostic.h"
+#include "reload.h"
+#include "debug.h"
+#include "common/common-target.h"
+#include "langhooks.h"
+#include "cfgloop.h" /* for init_set_costs */
+#include "hosthooks.h"
+#include "opts.h"
+#include "opts-diagnostic.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "asan.h"
+#include "plugin.h"
+#include "context.h"
+#include "dwarf2out.h"
+#include "tree-vrp.h"
+// sdcpp #include "ipa-prop.h"
+#include "omp-offload.h"
+#include "edit-context.h"
+#include "tree-pass.h"
+#include "dumpfile.h"
+// sdcpp #include "ipa-fnsummary.h"
+#include "print-tree.h"
+// sdcpp #include "ipa-modref-tree.h"
+//sdcpp #include "ipa-modref.h"
+//sdcpp #include "ipa-param-manipulation.h"
+#include "dbgcnt.h"
+#include <cassert>
+
+//sdcpp
+bool flag_wpa = false;
+#if 0 // sdcpp
+#undef DBX_DEBUGGING_INFO
+#undef XCOFF_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
+#undef CTF_DEBUGGING_INFO
+#undef BTF_DEBUGGING_INFO
+
+#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
+#endif // sdcpp
+
+#include "selftest.h"
+
+#ifdef HAVE_isl
+#include <isl/version.h>
+#endif
+
+static void general_init (const char *, bool);
+// sdcpp static void backend_init (void);
+static int lang_dependent_init (const char *);
+static void init_asm_output (const char *);
+static void finalize (bool);
+
+static void crash_signal (int) ATTRIBUTE_NORETURN;
+// sdcpp static void compile_file (void);
+
+/* Decoded options, and number of such options. */
+struct cl_decoded_option *save_decoded_options;
+unsigned int save_decoded_options_count;
+
+/* Vector of saved Optimization decoded command line options. */
+vec<cl_decoded_option> *save_opt_decoded_options;
+
+/* Debug hooks - dependent upon command line options. */
+
+const struct gcc_debug_hooks *debug_hooks;
+
+/* The FUNCTION_DECL for the function currently being compiled,
+ or 0 if between functions. */
+tree current_function_decl;
+
+/* Set to the FUNC_BEGIN label of the current function, or NULL
+ if none. */
+const char * current_function_func_begin_label;
+
+/* A random sequence of characters, unless overridden by user. */
+static const char *flag_random_seed;
+
+/* A local time stamp derived from the time of compilation. It will be
+ zero if the system cannot provide a time. It will be -1u, if the
+ user has specified a particular random seed. */
+unsigned local_tick;
+
+/* Random number for this compilation */
+HOST_WIDE_INT random_seed;
+
+/* -f flags. */
+
+/* When non-NULL, indicates that whenever space is allocated on the
+ stack, the resulting stack pointer must not pass this
+ address---that is, for stacks that grow downward, the stack pointer
+ must always be greater than or equal to this address; for stacks
+ that grow upward, the stack pointer must be less than this address.
+ At present, the rtx may be either a REG or a SYMBOL_REF, although
+ the support provided depends on the backend. */
+rtx stack_limit_rtx;
+
+class target_flag_state default_target_flag_state;
+#if SWITCHABLE_TARGET
+class target_flag_state *this_target_flag_state = &default_target_flag_state;
+#else
+#define this_target_flag_state (&default_target_flag_state)
+#endif
+
+/* The user symbol prefix after having resolved same. */
+const char *user_label_prefix;
+
+/* Output files for assembler code (real compiler output)
+ and debugging dumps. */
+
+FILE *asm_out_file;
+FILE *aux_info_file;
+FILE *callgraph_info_file = NULL;
+static bitmap callgraph_info_external_printed;
+FILE *stack_usage_file = NULL;
+
+/* The current working directory of a translation. It's generally the
+ directory from which compilation was initiated, but a preprocessed
+ file may specify the original directory in which it was
+ created. */
+
+static const char *src_pwd;
+
+/* Initialize src_pwd with the given string, and return true. If it
+ was already initialized, return false. As a special case, it may
+ be called with a NULL argument to test whether src_pwd has NOT been
+ initialized yet. */
+
+bool
+set_src_pwd (const char *pwd)
+{
+ if (src_pwd)
+ {
+ if (strcmp (src_pwd, pwd) == 0)
+ return true;
+ else
+ return false;
+ }
+
+ src_pwd = xstrdup (pwd);
+ return true;
+}
+
+/* Return the directory from which the translation unit was initiated,
+ in case set_src_pwd() was not called before to assign it a
+ different value. */
+
+const char *
+get_src_pwd (void)
+{
+ if (! src_pwd)
+ {
+ src_pwd = getpwd ();
+ if (!src_pwd)
+ src_pwd = ".";
+ }
+
+ return src_pwd;
+}
+
+/* Called when the start of a function definition is parsed,
+ this function prints on stderr the name of the function. */
+#if 0 // sdcpp
+void
+announce_function (tree decl)
+{
+ if (!quiet_flag)
+ {
+ if (rtl_dump_and_exit)
+ fprintf (stderr, "%s ",
+ identifier_to_locale (IDENTIFIER_POINTER (DECL_NAME (decl))));
+ else
+ fprintf (stderr, " %s",
+ identifier_to_locale (lang_hooks.decl_printable_name (decl, 2)));
+ fflush (stderr);
+ pp_needs_newline (global_dc->printer) = true;
+ diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL);
+ }
+}
+#endif
+
+/* Initialize local_tick with the time of day, or -1 if
+ flag_random_seed is set. */
+
+static void
+init_local_tick (void)
+{
+ if (!flag_random_seed)
+ {
+#ifdef HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ local_tick = (unsigned) tv.tv_sec * 1000 + tv.tv_usec / 1000;
+ }
+#else
+ {
+ time_t now = time (NULL);
+
+ if (now != (time_t)-1)
+ local_tick = (unsigned) now;
+ }
+#endif
+ }
+ else
+ local_tick = -1;
+}
+
+/* Obtain the random_seed. Unless NOINIT, initialize it if
+ it's not provided in the command line. */
+
+HOST_WIDE_INT
+get_random_seed (bool noinit)
+{
+ if (!random_seed && !noinit)
+ {
+ int fd = open ("/dev/urandom", O_RDONLY);
+ if (fd >= 0)
+ {
+ if (read (fd, &random_seed, sizeof (random_seed))
+ != sizeof (random_seed))
+ random_seed = 0;
+ close (fd);
+ }
+ if (!random_seed)
+ random_seed = local_tick ^ getpid ();
+ }
+ return random_seed;
+}
+
+/* Set flag_random_seed to VAL, and if non-null, reinitialize random_seed. */
+
+#if 0 // sdcpp
+void
+set_random_seed (const char *val)
+{
+ flag_random_seed = val;
+ if (flag_random_seed)
+ {
+ char *endp;
+
+ /* When the driver passed in a hex number don't crc it again */
+ random_seed = strtoul (flag_random_seed, &endp, 0);
+ if (!(endp > flag_random_seed && *endp == 0))
+ random_seed = crc32_string (0, flag_random_seed);
+ }
+}
+#endif
+
+/* Handler for fatal signals, such as SIGSEGV. These are transformed
+ into ICE messages, which is much more user friendly. In case the
+ error printer crashes, reset the signal to prevent infinite recursion. */
+
+static void
+crash_signal (int signo)
+{
+ signal (signo, SIG_DFL);
+
+ /* If we crashed while processing an ASM statement, then be a little more
+ graceful. It's most likely the user's fault. */
+ if (this_is_asm_operands)
+ {
+ output_operand_lossage ("unrecoverable error");
+ exit (FATAL_EXIT_CODE);
+ }
+
+ assert(false); // sdcpp
+ internal_error ("%s", strsignal (signo));
+}
+
+/* A subroutine of wrapup_global_declarations. We've come to the end of
+ the compilation unit. All deferred variables should be undeferred,
+ and all incomplete decls should be finalized. */
+
+#if 0 // sdcpp
+void
+wrapup_global_declaration_1 (tree decl)
+{
+ /* We're not deferring this any longer. Assignment is conditional to
+ avoid needlessly dirtying PCH pages. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS)
+ && DECL_DEFER_OUTPUT (decl) != 0)
+ DECL_DEFER_OUTPUT (decl) = 0;
+
+ if (VAR_P (decl) && DECL_SIZE (decl) == 0)
+ lang_hooks.finish_incomplete_decl (decl);
+}
+
+/* A subroutine of wrapup_global_declarations. Decide whether or not DECL
+ needs to be output. Return true if it is output. */
+
+bool
+wrapup_global_declaration_2 (tree decl)
+{
+ gcc_assert(false);
+ if (TREE_ASM_WRITTEN (decl) || DECL_EXTERNAL (decl)
+ || (VAR_P (decl) && DECL_HAS_VALUE_EXPR_P (decl)))
+ return false;
+
+ /* Don't write out static consts, unless we still need them.
+
+ We also keep static consts if not optimizing (for debugging),
+ unless the user specified -fno-keep-static-consts.
+ ??? They might be better written into the debug information.
+ This is possible when using DWARF.
+
+ A language processor that wants static constants to be always
+ written out (even if it is not used) is responsible for
+ calling rest_of_decl_compilation itself. E.g. the C front-end
+ calls rest_of_decl_compilation from finish_decl.
+ One motivation for this is that is conventional in some
+ environments to write things like:
+ static const char rcsid[] = "... version string ...";
+ intending to force the string to be in the executable.
+
+ A language processor that would prefer to have unneeded
+ static constants "optimized away" would just defer writing
+ them out until here. E.g. C++ does this, because static
+ constants are often defined in header files.
+
+ ??? A tempting alternative (for both C and C++) would be
+ to force a constant to be written if and only if it is
+ defined in a main file, as opposed to an include file. */
+
+ if (VAR_P (decl) && TREE_STATIC (decl))
+ {
+ varpool_node *node;
+ bool needed = true;
+ node = varpool_node::get (decl);
+
+ if (!node && flag_ltrans)
+ needed = false;
+ else if (node && node->definition)
+ needed = false;
+ else if (node && node->alias)
+ needed = false;
+ else if (!symtab->global_info_ready
+ && (TREE_USED (decl)
+ || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
+ /* needed */;
+ else if (node && node->analyzed)
+ /* needed */;
+ else if (DECL_COMDAT (decl))
+ needed = false;
+ else if (TREE_READONLY (decl) && !TREE_PUBLIC (decl)
+ && (optimize || !flag_keep_static_consts
+ || DECL_ARTIFICIAL (decl)))
+ needed = false;
+
+ if (needed)
+ {
+ rest_of_decl_compilation (decl, 1, 1);
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
+/* Do any final processing required for the declarations in VEC, of
+ which there are LEN. We write out inline functions and variables
+ that have been deferred until this point, but which are required.
+ Returns nonzero if anything was put out. */
+
+bool
+wrapup_global_declarations (tree *vec, int len)
+{
+ (void) vec;
+ (void) len;
+#if 0 // sdcpp
+ bool reconsider, output_something = false;
+ int i;
+
+ for (i = 0; i < len; i++)
+ wrapup_global_declaration_1 (vec[i]);
+
+ /* Now emit any global variables or functions that we have been
+ putting off. We need to loop in case one of the things emitted
+ here references another one which comes earlier in the list. */
+ do
+ {
+ reconsider = false;
+ for (i = 0; i < len; i++)
+ reconsider |= wrapup_global_declaration_2 (vec[i]);
+ if (reconsider)
+ output_something = true;
+ }
+ while (reconsider);
+
+ return output_something;
+#endif // sdcpp
+ return false;
+}
+
+/* Compile an entire translation unit. Write a file of assembly
+ output and various debugging dumps. */
+
+#if 0 // sdcpp
+static void
+compile_file (void)
+{
+ timevar_start (TV_PHASE_PARSING);
+ timevar_push (TV_PARSE_GLOBAL);
+
+ /* Parse entire file and generate initial debug information. */
+ lang_hooks.parse_file ();
+
+ timevar_pop (TV_PARSE_GLOBAL);
+ timevar_stop (TV_PHASE_PARSING);
+
+ if (flag_dump_locations)
+ dump_location_info (stderr);
+
+ free_attr_data ();
+
+ /* Compilation is now finished except for writing
+ what's left of the symbol table output. */
+
+ if (flag_syntax_only || flag_wpa)
+ return;
+
+ /* Reset maximum_field_alignment, it can be adjusted by #pragma pack
+ and this shouldn't influence any types built by the middle-end
+ from now on (like gcov_info_type). */
+ maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
+
+ ggc_protect_identifiers = false;
+
+ /* Run the actual compilation process. */
+ if (!in_lto_p)
+ {
+ timevar_start (TV_PHASE_OPT_GEN);
+ symtab->finalize_compilation_unit ();
+ timevar_stop (TV_PHASE_OPT_GEN);
+ }
+
+ /* Perform any post compilation-proper parser cleanups and
+ processing. This is currently only needed for the C++ parser,
+ which can be hopefully cleaned up so this hook is no longer
+ necessary. */
+ if (lang_hooks.decls.post_compilation_parsing_cleanups)
+ lang_hooks.decls.post_compilation_parsing_cleanups ();
+
+ // sdcpp
+ // dump_context::get ().finish_any_json_writer ();
+
+ if (seen_error ())
+ return;
+
+ timevar_start (TV_PHASE_LATE_ASM);
+
+ /* Compilation unit is finalized. When producing non-fat LTO object, we are
+ basically finished. */
+ if ((in_lto_p && flag_incremental_link != INCREMENTAL_LINK_LTO)
+ || !flag_lto || flag_fat_lto_objects)
+ {
+ /* File-scope initialization for AddressSanitizer. */
+ if (flag_sanitize & SANITIZE_ADDRESS)
+ asan_finish_file ();
+
+ if (flag_sanitize & SANITIZE_THREAD){
+ gcc_assert(0 && "tsan");
+ //tsan_finish_file ();
+ }
+
+ if (gate_hwasan ())
+ hwasan_finish_file ();
+
+ omp_finish_file ();
+
+ output_shared_constant_pool ();
+ output_object_blocks ();
+ finish_tm_clone_pairs ();
+
+ /* Write out any pending weak symbol declarations. */
+ weak_finish ();
+
+ /* This must be at the end before unwind and debug info.
+ Some target ports emit PIC setup thunks here. */
+ insn_locations_init ();
+ targetm.asm_out.code_end ();
+
+ /* Do dbx symbols. */
+ timevar_push (TV_SYMOUT);
+
+#if defined DWARF2_DEBUGGING_INFO || defined DWARF2_UNWIND_INFO
+ dwarf2out_frame_finish ();
+#endif
+
+ debuginfo_start ();
+ (*debug_hooks->finish) (main_input_filename);
+ debuginfo_stop ();
+ timevar_pop (TV_SYMOUT);
+
+ /* Output some stuff at end of file if nec. */
+
+ // sdcpp
+ // dw2_output_indirect_constants ();
+
+ /* Flush any pending external directives. */
+ process_pending_assemble_externals ();
+ }
+
+ /* Let linker plugin know that this is a slim object and must be LTOed
+ even when user did not ask for it. */
+ if (flag_generate_lto && !flag_fat_lto_objects)
+ {
+#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
+ ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE, "__gnu_lto_slim",
+ HOST_WIDE_INT_1U, 8);
+#elif defined ASM_OUTPUT_ALIGNED_COMMON
+ ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_slim",
+ HOST_WIDE_INT_1U, 8);
+#else
+ ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_slim",
+ HOST_WIDE_INT_1U,
+ HOST_WIDE_INT_1U);
+#endif
+ }
+
+ /* Attach a special .ident directive to the end of the file to identify
+ the version of GCC which compiled this code. The format of the .ident
+ string is patterned after the ones produced by native SVR4 compilers. */
+ if (!flag_no_ident)
+ {
+ const char *pkg_version = "(GNU) ";
+ char *ident_str;
+
+ if (strcmp ("(GCC) ", pkgversion_string))
+ pkg_version = pkgversion_string;
+
+ ident_str = ACONCAT (("GCC: ", pkg_version, version_string, NULL));
+ targetm.asm_out.output_ident (ident_str);
+ }
+
+ /* Auto profile finalization. */
+ if (flag_auto_profile)
+ gcc_assert(0 && "profile");
+ // end_auto_profile ();
+
+ /* Invoke registered plugin callbacks. */
+ invoke_plugin_callbacks (PLUGIN_FINISH_UNIT, NULL);
+
+ /* This must be at the end. Some target ports emit end of file directives
+ into the assembly file here, and hence we cannot output anything to the
+ assembly file after this point. */
+ targetm.asm_out.file_end ();
+
+ timevar_stop (TV_PHASE_LATE_ASM);
+}
+#endif // sdcpp
+
+/* Print version information to FILE.
+ Each line begins with INDENT (for the case where FILE is the
+ assembler output file).
+
+ If SHOW_GLOBAL_STATE is true (for cc1 etc), we are within the compiler
+ proper and can print pertinent state (e.g. params and plugins).
+
+ If SHOW_GLOBAL_STATE is false (for use by libgccjit), we are outside the
+ compiler, and we don't hold the mutex on the compiler's global state:
+ we can't print params and plugins, since they might not be initialized,
+ or might be being manipulated by a compile running in another
+ thread. */
+
+void
+print_version (FILE *file, const char *indent, bool show_global_state)
+{
+ static const char fmt1[] =
+#ifdef __GNUC__
+ N_("%s%s%s %sversion %s (%s)\n%s\tcompiled by GNU C version %s, ")
+#else
+ N_("%s%s%s %sversion %s (%s) compiled by CC, ")
+#endif
+ ;
+ (void) show_global_state;
+#if 0 // sdcpp
+ static const char fmt2[] =
+ N_("GMP version %s, MPFR version %s, MPC version %s, isl version %s\n");
+ static const char fmt3[] =
+ N_("%s%swarning: %s header version %s differs from library version %s.\n");
+ static const char fmt4[] =
+ N_("%s%sGGC heuristics: --param ggc-min-expand=%d --param ggc-min-heapsize=%d\n");
+#endif
+#ifndef __VERSION__
+#define __VERSION__ "[?]"
+#endif
+ fprintf (file,
+ file == stderr ? _(fmt1) : fmt1,
+ indent, *indent != 0 ? " " : "",
+ lang_hooks.name, pkgversion_string, version_string, TARGET_NAME,
+ indent, __VERSION__);
+
+ /* We need to stringify the GMP macro values. Ugh, gmp_version has
+ two string formats, "i.j.k" and "i.j" when k is zero. As of
+ gmp-4.3.0, GMP always uses the 3 number format. */
+#define GCC_GMP_STRINGIFY_VERSION3(X) #X
+#define GCC_GMP_STRINGIFY_VERSION2(X) GCC_GMP_STRINGIFY_VERSION3 (X)
+#define GCC_GMP_VERSION_NUM(X,Y,Z) (((X) << 16L) | ((Y) << 8) | (Z))
+#define GCC_GMP_VERSION \
+ GCC_GMP_VERSION_NUM(__GNU_MP_VERSION, __GNU_MP_VERSION_MINOR, __GNU_MP_VERSION_PATCHLEVEL)
+#if GCC_GMP_VERSION < GCC_GMP_VERSION_NUM(4,3,0) && __GNU_MP_VERSION_PATCHLEVEL == 0
+#define GCC_GMP_STRINGIFY_VERSION \
+ GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION) "." \
+ GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION_MINOR)
+#else
+#define GCC_GMP_STRINGIFY_VERSION \
+ GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION) "." \
+ GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION_MINOR) "." \
+ GCC_GMP_STRINGIFY_VERSION2 (__GNU_MP_VERSION_PATCHLEVEL)
+#endif
+#if 0 // sdcpp
+ fprintf (file,
+ file == stderr ? _(fmt2) : fmt2,
+ GCC_GMP_STRINGIFY_VERSION, MPFR_VERSION_STRING, MPC_VERSION_STRING,
+#ifndef HAVE_isl
+ "none"
+#else
+ isl_version ()
+#endif
+ );
+ if (strcmp (GCC_GMP_STRINGIFY_VERSION, gmp_version))
+ fprintf (file,
+ file == stderr ? _(fmt3) : fmt3,
+ indent, *indent != 0 ? " " : "",
+ "GMP", GCC_GMP_STRINGIFY_VERSION, gmp_version);
+ if (strcmp (MPFR_VERSION_STRING, mpfr_get_version ()))
+ fprintf (file,
+ file == stderr ? _(fmt3) : fmt3,
+ indent, *indent != 0 ? " " : "",
+ "MPFR", MPFR_VERSION_STRING, mpfr_get_version ());
+ if (strcmp (MPC_VERSION_STRING, mpc_get_version ()))
+ fprintf (file,
+ file == stderr ? _(fmt3) : fmt3,
+ indent, *indent != 0 ? " " : "",
+ "MPC", MPC_VERSION_STRING, mpc_get_version ());
+
+ if (show_global_state)
+ {
+ fprintf (file,
+ file == stderr ? _(fmt4) : fmt4,
+ indent, *indent != 0 ? " " : "",
+ param_ggc_min_expand, param_ggc_min_heapsize);
+
+ print_plugins_versions (file, indent);
+ }
+#endif
+}
+
+
+
+/* Open assembly code output file. Do this even if -fsyntax-only is
+ on, because then the driver will have provided the name of a
+ temporary file or bit bucket for us. NAME is the file specified on
+ the command line, possibly NULL. */
+static void
+init_asm_output (const char *name)
+{
+ if (name == NULL && asm_file_name == 0)
+ asm_out_file = stdout;
+ else
+ {
+ if (asm_file_name == 0)
+ {
+ int len = strlen (dump_base_name);
+ char *dumpname = XNEWVEC (char, len + 6);
+
+ memcpy (dumpname, dump_base_name, len + 1);
+ strip_off_ending (dumpname, len);
+ strcat (dumpname, ".s");
+ asm_file_name = dumpname;
+ }
+ if (!strcmp (asm_file_name, "-"))
+ asm_out_file = stdout;
+ else if (!canonical_filename_eq (asm_file_name, name)
+ || !strcmp (asm_file_name, HOST_BIT_BUCKET))
+ asm_out_file = fopen (asm_file_name, "w");
+ else
+ /* Use UNKOWN_LOCATION to prevent gcc from printing the first
+ line in the current file. */
+ fatal_error (UNKNOWN_LOCATION,
+ "input file %qs is the same as output file",
+ asm_file_name);
+ if (asm_out_file == 0)
+ fatal_error (UNKNOWN_LOCATION,
+ "cannot open %qs for writing: %m", asm_file_name);
+ }
+
+#if 0 // sdcpp
+ if (!flag_syntax_only)
+ {
+ targetm.asm_out.file_start ();
+
+ if (flag_record_gcc_switches)
+ {
+ if (targetm.asm_out.record_gcc_switches)
+ {
+ const char *str
+ = gen_producer_string (lang_hooks.name,
+ save_decoded_options,
+ save_decoded_options_count);
+ targetm.asm_out.record_gcc_switches (str);
+ }
+ else
+ inform (UNKNOWN_LOCATION,
+ "%<-frecord-gcc-switches%> is not supported by "
+ "the current target");
+ }
+
+ if (flag_verbose_asm)
+ {
+ print_version (asm_out_file, ASM_COMMENT_START, true);
+ fputs (ASM_COMMENT_START, asm_out_file);
+ fputs (" options passed: ", asm_out_file);
+ char *cmdline = gen_command_line_string (save_decoded_options,
+ save_decoded_options_count);
+ fputs (cmdline, asm_out_file);
+ free (cmdline);
+ fputc ('\n', asm_out_file);
+ }
+ }
+#endif // sdcpp
+}
+
+/* A helper function; used as the reallocator function for cpp's line
+ table. */
+static void *
+realloc_for_line_map (void *ptr, size_t len)
+{
+ return ggc_realloc (ptr, len);
+}
+
+/* A helper function: used as the allocator function for
+ identifier_to_locale. */
+static void *
+alloc_for_identifier_to_locale (size_t len)
+{
+ return ggc_alloc_atomic (len);
+}
+
+#if 0 // sdcpp
+/* Output stack usage information. */
+static void
+output_stack_usage_1 (FILE *cf)
+{
+ static bool warning_issued = false;
+ enum stack_usage_kind_type { STATIC = 0, DYNAMIC, DYNAMIC_BOUNDED };
+ const char *stack_usage_kind_str[] = {
+ "static",
+ "dynamic",
+ "dynamic,bounded"
+ };
+ HOST_WIDE_INT stack_usage = current_function_static_stack_size;
+ enum stack_usage_kind_type stack_usage_kind;
+
+ if (stack_usage < 0)
+ {
+ if (!warning_issued)
+ {
+ warning (0, "stack usage computation not supported for this target");
+ warning_issued = true;
+ }
+ return;
+ }
+
+ stack_usage_kind = STATIC;
+
+ /* Add the maximum amount of space pushed onto the stack. */
+ if (maybe_ne (current_function_pushed_stack_size, 0))
+ {
+ HOST_WIDE_INT extra;
+ if (current_function_pushed_stack_size.is_constant (&extra))
+ {
+ stack_usage += extra;
+ stack_usage_kind = DYNAMIC_BOUNDED;
+ }
+ else
+ {
+ extra = constant_lower_bound (current_function_pushed_stack_size);
+ stack_usage += extra;
+ stack_usage_kind = DYNAMIC;
+ }
+ }
+
+ /* Now on to the tricky part: dynamic stack allocation. */
+ if (current_function_allocates_dynamic_stack_space)
+ {
+ if (stack_usage_kind != DYNAMIC)
+ {
+ if (current_function_has_unbounded_dynamic_stack_size)
+ stack_usage_kind = DYNAMIC;
+ else
+ stack_usage_kind = DYNAMIC_BOUNDED;
+ }
+
+ /* Add the size even in the unbounded case, this can't hurt. */
+ stack_usage += current_function_dynamic_stack_size;
+ }
+
+ if (cf && flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE)
+ fprintf (cf, "\\n" HOST_WIDE_INT_PRINT_DEC " bytes (%s)",
+ stack_usage,
+ stack_usage_kind_str[stack_usage_kind]);
+
+ if (stack_usage_file)
+ {
+ print_decl_identifier (stack_usage_file, current_function_decl,
+ PRINT_DECL_ORIGIN | PRINT_DECL_NAME);
+ fprintf (stack_usage_file, "\t" HOST_WIDE_INT_PRINT_DEC"\t%s\n",
+ stack_usage, stack_usage_kind_str[stack_usage_kind]);
+ }
+
+ if (warn_stack_usage >= 0 && warn_stack_usage < HOST_WIDE_INT_MAX)
+ {
+ const location_t loc = DECL_SOURCE_LOCATION (current_function_decl);
+
+ if (stack_usage_kind == DYNAMIC)
+ warning_at (loc, OPT_Wstack_usage_, "stack usage might be unbounded");
+ else if (stack_usage > warn_stack_usage)
+ {
+ if (stack_usage_kind == DYNAMIC_BOUNDED)
+ warning_at (loc,
+ OPT_Wstack_usage_, "stack usage might be %wu bytes",
+ stack_usage);
+ else
+ warning_at (loc, OPT_Wstack_usage_, "stack usage is %wu bytes",
+ stack_usage);
+ }
+ }
+}
+
+/* Dump placeholder node for indirect calls in VCG format. */
+
+#define INDIRECT_CALL_NAME "__indirect_call"
+
+static void
+dump_final_node_vcg_start (FILE *f, tree decl)
+{
+ fputs ("node: { title: \"", f);
+ if (decl)
+ print_decl_identifier (f, decl, PRINT_DECL_UNIQUE_NAME);
+ else
+ fputs (INDIRECT_CALL_NAME, f);
+ fputs ("\" label: \"", f);
+ if (decl)
+ {
+ print_decl_identifier (f, decl, PRINT_DECL_NAME);
+ fputs ("\\n", f);
+ print_decl_identifier (f, decl, PRINT_DECL_ORIGIN);
+ }
+ else
+ fputs ("Indirect Call Placeholder", f);
+}
+#endif // sdcpp
+
+/* Dump final cgraph edge in VCG format. */
+
+#if 0 //sdcpp
+static void
+dump_final_callee_vcg (FILE *f, location_t location, tree callee)
+{
+ if ((!callee || DECL_EXTERNAL (callee))
+ && bitmap_set_bit (callgraph_info_external_printed,
+ callee ? DECL_UID (callee) + 1 : 0))
+ {
+ dump_final_node_vcg_start (f, callee);
+ fputs ("\" shape : ellipse }\n", f);
+ }
+
+ fputs ("edge: { sourcename: \"", f);
+ print_decl_identifier (f, current_function_decl, PRINT_DECL_UNIQUE_NAME);
+ fputs ("\" targetname: \"", f);
+ if (callee)
+ print_decl_identifier (f, callee, PRINT_DECL_UNIQUE_NAME);
+ else
+ fputs (INDIRECT_CALL_NAME, f);
+ if (LOCATION_LOCUS (location) != UNKNOWN_LOCATION)
+ {
+ expanded_location loc;
+ fputs ("\" label: \"", f);
+ loc = expand_location (location);
+ fprintf (f, "%s:%d:%d", loc.file, loc.line, loc.column);
+ }
+ fputs ("\" }\n", f);
+}
+#endif // sdcpp
+
+/* Dump final cgraph node in VCG format. */
+
+#if 0 // sdcpp
+static void
+dump_final_node_vcg (FILE *f)
+{
+ dump_final_node_vcg_start (f, current_function_decl);
+
+ if (flag_stack_usage_info
+ || (flag_callgraph_info & CALLGRAPH_INFO_STACK_USAGE))
+ output_stack_usage_1 (f);
+
+ if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
+ {
+ fprintf (f, "\\n%u dynamic objects", vec_safe_length (cfun->su->dallocs));
+
+ unsigned i;
+ callinfo_dalloc *cda;
+ FOR_EACH_VEC_SAFE_ELT (cfun->su->dallocs, i, cda)
+ {
+ expanded_location loc = expand_location (cda->location);
+ fprintf (f, "\\n %s", cda->name);
+ fprintf (f, " %s:%d:%d", loc.file, loc.line, loc.column);
+ }
+
+ vec_free (cfun->su->dallocs);
+ cfun->su->dallocs = NULL;
+ }
+
+ fputs ("\" }\n", f);
+
+ unsigned i;
+ callinfo_callee *c;
+ FOR_EACH_VEC_SAFE_ELT (cfun->su->callees, i, c)
+ dump_final_callee_vcg (f, c->location, c->decl);
+ vec_free (cfun->su->callees);
+ cfun->su->callees = NULL;
+}
+
+/* Output stack usage and callgraph info, as requested. */
+void
+output_stack_usage (void)
+{
+ if (flag_callgraph_info)
+ dump_final_node_vcg (callgraph_info_file);
+ else
+ output_stack_usage_1 (NULL);
+}
+#endif // sdcpp
+
+/* Open an auxiliary output file. */
+static FILE *
+open_auxiliary_file (const char *ext)
+{
+ char *filename;
+ FILE *file;
+
+ filename = concat (aux_base_name, ".", ext, NULL);
+ file = fopen (filename, "w");
+ if (!file)
+ fatal_error (input_location, "cannot open %s for writing: %m", filename);
+ free (filename);
+ return file;
+}
+
+/* Alternative diagnostics callback for reentered ICE reporting. */
+
+static void
+internal_error_reentered (diagnostic_context *, const char *, va_list *)
+{
+ /* Flush the dump file if emergency_dump_function itself caused an ICE. */
+ if (dump_file)
+ fflush (dump_file);
+}
+
+/* Auxiliary callback for the diagnostics code. */
+
+static void
+internal_error_function (diagnostic_context *, const char *, va_list *)
+{
+ global_dc->internal_error = internal_error_reentered;
+ warn_if_plugins ();
+ emergency_dump_function ();
+}
+
+/* Initialization of the front end environment, before command line
+ options are parsed. Signal handlers, internationalization etc.
+ ARGV0 is main's argv[0]. */
+static void
+general_init (const char *argv0, bool init_signals)
+{
+ const char *p;
+
+ p = argv0 + strlen (argv0);
+ while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
+ --p;
+ progname = p;
+
+ xmalloc_set_program_name (progname);
+
+ hex_init ();
+
+ /* Unlock the stdio streams. */
+ unlock_std_streams ();
+
+ gcc_init_libintl ();
+
+ identifier_to_locale_alloc = alloc_for_identifier_to_locale;
+ identifier_to_locale_free = ggc_free;
+
+ /* Initialize the diagnostics reporting machinery, so option parsing
+ can give warnings and errors. */
+ diagnostic_initialize (global_dc, N_OPTS);
+ global_dc->lang_mask = lang_hooks.option_lang_mask ();
+ /* Set a default printer. Language specific initializations will
+ override it later. */
+ tree_diagnostics_defaults (global_dc);
+
+ global_dc->show_caret
+ = global_options_init.x_flag_diagnostics_show_caret;
+ global_dc->show_labels_p
+ = global_options_init.x_flag_diagnostics_show_labels;
+ global_dc->show_line_numbers_p
+ = global_options_init.x_flag_diagnostics_show_line_numbers;
+ global_dc->show_cwe
+ = global_options_init.x_flag_diagnostics_show_cwe;
+ global_dc->path_format
+ = (enum diagnostic_path_format)global_options_init.x_flag_diagnostics_path_format;
+ global_dc->show_path_depths
+ = global_options_init.x_flag_diagnostics_show_path_depths;
+ global_dc->show_option_requested
+ = global_options_init.x_flag_diagnostics_show_option;
+ global_dc->min_margin_width
+ = global_options_init.x_diagnostics_minimum_margin_width;
+ global_dc->show_column
+ = global_options_init.x_flag_show_column;
+ global_dc->internal_error = internal_error_function;
+ global_dc->option_enabled = option_enabled;
+ global_dc->option_state = &global_options;
+ global_dc->option_name = option_name;
+ global_dc->get_option_url = get_option_url;
+
+ if (init_signals && 0)
+ {
+ /* Trap fatal signals, e.g. SIGSEGV, and convert them to ICE messages. */
+#ifdef SIGSEGV
+ signal (SIGSEGV, crash_signal);
+#endif
+#ifdef SIGILL
+ signal (SIGILL, crash_signal);
+#endif
+#ifdef SIGBUS
+ signal (SIGBUS, crash_signal);
+#endif
+#ifdef SIGABRT
+ signal (SIGABRT, crash_signal);
+#endif
+#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
+ signal (SIGIOT, crash_signal);
+#endif
+#ifdef SIGFPE
+ signal (SIGFPE, crash_signal);
+#endif
+
+ /* Other host-specific signal setup. */
+ // sdcpp (*host_hooks.extra_signals)();
+ }
+
+ /* Initialize the garbage-collector, string pools and tree type hash
+ table. */
+ init_ggc ();
+ init_stringpool ();
+ input_location = UNKNOWN_LOCATION;
+
+ line_table = ggc_alloc<line_maps> ();
+ linemap_init (line_table, BUILTINS_LOCATION);
+ line_table->reallocator = realloc_for_line_map;
+ line_table->round_alloc_size = ggc_round_alloc_size;
+ line_table->default_range_bits = 5;
+ // sdcpp init_ttree ();
+
+ /* Initialize register usage now so switches may override. */
+ // sdcpp init_reg_sets ();
+
+ /* Create the singleton holder for global state. This creates the
+ dump manager. */
+ g = new gcc::context ();
+
+ /* Allow languages and middle-end to register their dumps before the
+ optimization passes. */
+ g->get_dumps ()->register_dumps ();
+
+ /* Create the passes. */
+ //sdcpp
+// g->set_passes (new gcc::pass_manager (g));
+
+ // sdcpp symtab = new (ggc_alloc <symbol_table> ()) symbol_table ();
+
+ statistics_early_init ();
+ // sdcpp debuginfo_early_init ();
+}
+
+/* Return true if the current target supports -fsection-anchors. */
+
+static bool
+target_supports_section_anchors_p (void)
+{
+#if 0 // sdcpp
+ if (targetm.min_anchor_offset == 0 && targetm.max_anchor_offset == 0)
+ return false;
+
+ if (targetm.asm_out.output_anchor == NULL)
+ return false;
+
+ return true;
+#else // sdcpp
+ return false;
+#endif // sdcpp
+}
+
+/* Parse "N[:M][:...]" into struct align_flags A.
+ VALUES contains parsed values (in reverse order), all processed
+ values are popped. */
+
+static void
+read_log_maxskip (auto_vec<unsigned> &values, align_flags_tuple *a)
+{
+ unsigned n = values.pop ();
+ if (n != 0)
+ a->log = floor_log2 (n * 2 - 1);
+
+ if (values.is_empty ())
+ a->maxskip = n ? n - 1 : 0;
+ else
+ {
+ unsigned m = values.pop ();
+ /* -falign-foo=N:M means M-1 max bytes of padding, not M. */
+ if (m > 0)
+ m--;
+ a->maxskip = m;
+ }
+
+ /* Normalize the tuple. */
+ a->normalize ();
+}
+
+/* Parse "N[:M[:N2[:M2]]]" string FLAG into a pair of struct align_flags. */
+
+static void
+parse_N_M (const char *flag, align_flags &a)
+{
+ if (flag)
+ {
+ static hash_map <nofree_string_hash, align_flags> cache;
+ align_flags *entry = cache.get (flag);
+ if (entry)
+ {
+ a = *entry;
+ return;
+ }
+
+ auto_vec<unsigned> result_values;
+ bool r = parse_and_check_align_values (flag, NULL, result_values, false,
+ UNKNOWN_LOCATION);
+ if (!r)
+ return;
+
+ /* Reverse values for easier manipulation. */
+ result_values.reverse ();
+
+ read_log_maxskip (result_values, &a.levels[0]);
+ if (!result_values.is_empty ())
+ read_log_maxskip (result_values, &a.levels[1]);
+#ifdef SUBALIGN_LOG
+ else
+ {
+ /* N2[:M2] is not specified. This arch has a default for N2.
+ Before -falign-foo=N:M:N2:M2 was introduced, x86 had a tweak.
+ -falign-functions=N with N > 8 was adding secondary alignment.
+ -falign-functions=10 was emitting this before every function:
+ .p2align 4,,9
+ .p2align 3
+ Now this behavior (and more) can be explicitly requested:
+ -falign-functions=16:10:8
+ Retain old behavior if N2 is missing: */
+
+ int align = 1 << a.levels[0].log;
+ int subalign = 1 << SUBALIGN_LOG;
+
+ if (a.levels[0].log > SUBALIGN_LOG
+ && a.levels[0].maxskip >= subalign - 1)
+ {
+ /* Set N2 unless subalign can never have any effect. */
+ if (align > a.levels[0].maxskip + 1)
+ {
+ a.levels[1].log = SUBALIGN_LOG;
+ a.levels[1].normalize ();
+ }
+ }
+ }
+#endif
+
+ /* Cache seen value. */
+ cache.put (flag, a);
+ }
+}
+
+/* Process -falign-foo=N[:M[:N2[:M2]]] options. */
+
+void
+parse_alignment_opts (void)
+{
+ parse_N_M (str_align_loops, align_loops);
+ parse_N_M (str_align_jumps, align_jumps);
+ parse_N_M (str_align_labels, align_labels);
+ parse_N_M (str_align_functions, align_functions);
+}
+
+/* Process the options that have been parsed. */
+static void
+process_options (bool no_backend)
+{
+ const char *language_string = lang_hooks.name;
+
+ // sdcpp maximum_field_alignment = initial_max_fld_align * BITS_PER_UNIT;
+
+ /* Some machines may reject certain combinations of options. */
+ location_t saved_location = input_location;
+ input_location = UNKNOWN_LOCATION;
+ // sdcc targetm.target_option.override ();
+ input_location = saved_location;
+
+ if (flag_diagnostics_generate_patch)
+ global_dc->edit_context_ptr = new edit_context ();
+
+ /* Avoid any informative notes in the second run of -fcompare-debug. */
+ if (flag_compare_debug)
+ diagnostic_inhibit_notes (global_dc);
+
+ if (flag_section_anchors && !target_supports_section_anchors_p ())
+ {
+ warning_at (UNKNOWN_LOCATION, OPT_fsection_anchors,
+ "this target does not support %qs",
+ "-fsection-anchors");
+ flag_section_anchors = 0;
+ }
+
+#if 0 // sdcc
+ if (flag_short_enums == 2)
+ flag_short_enums = targetm.default_short_enums ();
+#endif
+
+ /* Set aux_base_name if not already set. */
+ if (aux_base_name)
+ ;
+ else if (dump_base_name)
+ {
+ const char *name = dump_base_name;
+ int nlen, len;
+
+ if (dump_base_ext && (len = strlen (dump_base_ext))
+ && (nlen = strlen (name)) && nlen > len
+ && strcmp (name + nlen - len, dump_base_ext) == 0)
+ {
+ char *p = xstrndup (name, nlen - len);
+ name = p;
+ }
+
+ aux_base_name = name;
+ }
+ else
+ aux_base_name = "gccaux";
+
+#ifndef HAVE_isl
+ if (flag_graphite
+ || flag_loop_nest_optimize
+ || flag_graphite_identity
+ || flag_loop_parallelize_all)
+ sorry ("Graphite loop optimizations cannot be used (isl is not available) "
+ "(%<-fgraphite%>, %<-fgraphite-identity%>, "
+ "%<-floop-nest-optimize%>, %<-floop-parallelize-all%>)");
+#endif
+
+ if (flag_cf_protection != CF_NONE
+ && !(flag_cf_protection & CF_SET))
+ {
+ if (flag_cf_protection == CF_FULL)
+ {
+ error_at (UNKNOWN_LOCATION,
+ "%<-fcf-protection=full%> is not supported for this "
+ "target");
+ flag_cf_protection = CF_NONE;
+ }
+ if (flag_cf_protection == CF_BRANCH)
+ {
+ error_at (UNKNOWN_LOCATION,
+ "%<-fcf-protection=branch%> is not supported for this "
+ "target");
+ flag_cf_protection = CF_NONE;
+ }
+ if (flag_cf_protection == CF_RETURN)
+ {
+ error_at (UNKNOWN_LOCATION,
+ "%<-fcf-protection=return%> is not supported for this "
+ "target");
+ flag_cf_protection = CF_NONE;
+ }
+ }
+
+ /* One region RA really helps to decrease the code size. */
+ if (!OPTION_SET_P (flag_ira_region))
+ flag_ira_region
+ = optimize_size || !optimize ? IRA_REGION_ONE : IRA_REGION_MIXED;
+
+ if (!abi_version_at_least (2))
+ {
+ /* -fabi-version=1 support was removed after GCC 4.9. */
+ error_at (UNKNOWN_LOCATION,
+ "%<-fabi-version=1%> is no longer supported");
+ flag_abi_version = 2;
+ }
+
+ if (flag_non_call_exceptions)
+ flag_asynchronous_unwind_tables = 1;
+ if (flag_asynchronous_unwind_tables)
+ flag_unwind_tables = 1;
+
+ if (flag_value_profile_transformations)
+ flag_profile_values = 1;
+
+ /* Warn about options that are not supported on this machine. */
+#ifndef INSN_SCHEDULING
+ if (flag_schedule_insns || flag_schedule_insns_after_reload)
+ warning_at (UNKNOWN_LOCATION, 0,
+ "instruction scheduling not supported on this target machine");
+#endif
+ if (!DELAY_SLOTS && flag_delayed_branch)
+ warning_at (UNKNOWN_LOCATION, 0,
+ "this target machine does not have delayed branches");
+
+ user_label_prefix = USER_LABEL_PREFIX;
+ if (flag_leading_underscore != -1)
+ {
+ /* If the default prefix is more complicated than "" or "_",
+ issue a warning and ignore this option. */
+ if (user_label_prefix[0] == 0 ||
+ (user_label_prefix[0] == '_' && user_label_prefix[1] == 0))
+ {
+ user_label_prefix = flag_leading_underscore ? "_" : "";
+ }
+ else
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-f%sleading-underscore%> not supported on this "
+ "target machine", flag_leading_underscore ? "" : "no-");
+ }
+
+ /* If we are in verbose mode, write out the version and maybe all the
+ option flags in use. */
+ if (version_flag)
+ {
+ print_version (stderr, "", true);
+ if (!quiet_flag)
+ {
+ fputs ("options passed: ", stderr);
+ char *cmdline = gen_command_line_string (save_decoded_options,
+ save_decoded_options_count);
+
+ fputs (cmdline, stderr);
+ free (cmdline);
+ fputc ('\n', stderr);
+ }
+ }
+
+ /* CTF is supported for only C at this time. */
+ if (!lang_GNU_C ()
+ && ctf_debug_info_level > CTFINFO_LEVEL_NONE)
+ {
+ /* Compiling with -flto results in frontend language of GNU GIMPLE. It
+ is not useful to warn in that case. */
+ if (!startswith (lang_hooks.name, "GNU GIMPLE"))
+ inform (UNKNOWN_LOCATION,
+ "CTF debug info requested, but not supported for %qs frontend",
+ language_string);
+ ctf_debug_info_level = CTFINFO_LEVEL_NONE;
+ }
+
+ if (flag_dump_final_insns && !flag_syntax_only && !no_backend)
+ {
+ FILE *final_output = fopen (flag_dump_final_insns, "w");
+ if (!final_output)
+ {
+ error_at (UNKNOWN_LOCATION,
+ "could not open final insn dump file %qs: %m",
+ flag_dump_final_insns);
+ flag_dump_final_insns = NULL;
+ }
+ else if (fclose (final_output))
+ {
+ error_at (UNKNOWN_LOCATION,
+ "could not close zeroed insn dump file %qs: %m",
+ flag_dump_final_insns);
+ flag_dump_final_insns = NULL;
+ }
+ }
+
+ /* A lot of code assumes write_symbols == NO_DEBUG if the debugging
+ level is 0. */
+ if (debug_info_level == DINFO_LEVEL_NONE
+ && 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 0 // sdcpp
+#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;
+#endif
+#ifdef CTF_DEBUGGING_INFO
+ else if (ctf_debuginfo_p ())
+ debug_hooks = &dwarf2_debug_hooks;
+#endif
+#ifdef BTF_DEBUGGING_INFO
+ else if (btf_debuginfo_p ())
+ debug_hooks = &dwarf2_debug_hooks;
+#endif
+#ifdef VMS_DEBUGGING_INFO
+ else if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+ debug_hooks = &vmsdbg_debug_hooks;
+#endif
+#ifdef DWARF2_LINENO_DEBUGGING_INFO
+ else if (write_symbols == DWARF2_DEBUG)
+ debug_hooks = &dwarf2_lineno_debug_hooks;
+#endif
+#endif // sdcpp
+ else
+ {
+ gcc_assert (debug_set_count (write_symbols) <= 1);
+ error_at (UNKNOWN_LOCATION,
+ "target system does not support the %qs debug format",
+ debug_type_names[debug_set_to_format (write_symbols)]);
+ }
+
+ /* We know which debug output will be used so we can set flag_var_tracking
+ and flag_var_tracking_uninit if the user has not specified them. */
+ if (debug_info_level < DINFO_LEVEL_NORMAL
+ || !dwarf_debuginfo_p ()
+ || debug_hooks->var_location == do_nothing_debug_hooks.var_location)
+ {
+ if ((OPTION_SET_P (flag_var_tracking) && flag_var_tracking == 1)
+ || (OPTION_SET_P (flag_var_tracking_uninit)
+ && flag_var_tracking_uninit == 1))
+ {
+ if (debug_info_level < DINFO_LEVEL_NORMAL)
+ warning_at (UNKNOWN_LOCATION, 0,
+ "variable tracking requested, but useless unless "
+ "producing debug info");
+ else
+ warning_at (UNKNOWN_LOCATION, 0,
+ "variable tracking requested, but not supported "
+ "by this debug format");
+ }
+ flag_var_tracking = 0;
+ flag_var_tracking_uninit = 0;
+ flag_var_tracking_assignments = 0;
+ }
+
+ /* The debug hooks are used to implement -fdump-go-spec because it
+ gives a simple and stable API for all the information we need to
+ dump. */
+ if (flag_dump_go_spec != NULL)
+ debug_hooks = dump_go_spec_init (flag_dump_go_spec, debug_hooks);
+
+ if (!OPTION_SET_P (dwarf2out_as_loc_support))
+ dwarf2out_as_loc_support = dwarf2out_default_as_loc_support ();
+ if (!OPTION_SET_P (dwarf2out_as_locview_support))
+ dwarf2out_as_locview_support = dwarf2out_default_as_locview_support ();
+
+ if (!OPTION_SET_P (debug_variable_location_views))
+ {
+ debug_variable_location_views
+ = (flag_var_tracking
+ && debug_info_level >= DINFO_LEVEL_NORMAL
+ && dwarf_debuginfo_p ()
+ && !dwarf_strict
+ && dwarf2out_as_loc_support
+ && dwarf2out_as_locview_support);
+ }
+ else if (debug_variable_location_views == -1 && dwarf_version != 5)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "without %<-gdwarf-5%>, "
+ "%<-gvariable-location-views=incompat5%> "
+ "is equivalent to %<-gvariable-location-views%>");
+ debug_variable_location_views = 1;
+ }
+
+#if 0 // sdcpp
+ if (debug_internal_reset_location_views == 2)
+ {
+ debug_internal_reset_location_views
+ = (debug_variable_location_views
+ && targetm.reset_location_view);
+ }
+ else if (debug_internal_reset_location_views
+ && !debug_variable_location_views)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-ginternal-reset-location-views%> is forced disabled "
+ "without %<-gvariable-location-views%>");
+ debug_internal_reset_location_views = 0;
+ }
+#endif // sdcpp
+
+ if (!OPTION_SET_P (debug_inline_points))
+ debug_inline_points = debug_variable_location_views;
+ else if (debug_inline_points && !debug_nonbind_markers_p)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-ginline-points%> is forced disabled without "
+ "%<-gstatement-frontiers%>");
+ debug_inline_points = 0;
+ }
+
+ if (!OPTION_SET_P (flag_tree_cselim))
+ {
+ if (HAVE_conditional_move)
+ flag_tree_cselim = 1;
+ else
+ flag_tree_cselim = 0;
+ }
+
+ /* If auxiliary info generation is desired, open the output file.
+ This goes in the same directory as the source file--unlike
+ all the other output files. */
+ if (flag_gen_aux_info)
+ {
+ aux_info_file = fopen (aux_info_file_name, "w");
+ if (aux_info_file == 0)
+ fatal_error (UNKNOWN_LOCATION,
+ "cannot open %s: %m", aux_info_file_name);
+ }
+
+#if 0 // sdcpp
+ if (!targetm_common.have_named_sections)
+ {
+ if (flag_function_sections)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-ffunction-sections%> not supported for this target");
+ flag_function_sections = 0;
+ }
+ if (flag_data_sections)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fdata-sections%> not supported for this target");
+ flag_data_sections = 0;
+ }
+ }
+
+ if (flag_prefetch_loop_arrays > 0 && !targetm.code_for_prefetch)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fprefetch-loop-arrays%> not supported for this target");
+ flag_prefetch_loop_arrays = 0;
+ }
+ else if (flag_prefetch_loop_arrays > 0 && !targetm.have_prefetch ())
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fprefetch-loop-arrays%> not supported for this target "
+ "(try %<-march%> switches)");
+ flag_prefetch_loop_arrays = 0;
+ }
+#endif // sdcpp
+
+ /* This combination of options isn't handled for i386 targets and doesn't
+ make much sense anyway, so don't allow it. */
+ if (flag_prefetch_loop_arrays > 0 && optimize_size)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fprefetch-loop-arrays%> is not supported with %<-Os%>");
+ flag_prefetch_loop_arrays = 0;
+ }
+
+ /* The presence of IEEE signaling NaNs, implies all math can trap. */
+ if (flag_signaling_nans)
+ flag_trapping_math = 1;
+
+ /* We cannot reassociate if we want traps or signed zeros. */
+ if (flag_associative_math && (flag_trapping_math || flag_signed_zeros))
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fassociative-math%> disabled; other options take "
+ "precedence");
+ flag_associative_math = 0;
+ }
+
+ /* -fstack-clash-protection is not currently supported on targets
+ where the stack grows up. */
+ if (flag_stack_clash_protection && !STACK_GROWS_DOWNWARD)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fstack-clash-protection%> is not supported on targets "
+ "where the stack grows from lower to higher addresses");
+ flag_stack_clash_protection = 0;
+ }
+
+ /* We cannot support -fstack-check= and -fstack-clash-protection at
+ the same time. */
+ if (flag_stack_check != NO_STACK_CHECK && flag_stack_clash_protection)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fstack-check=%> and %<-fstack-clash_protection%> are "
+ "mutually exclusive; disabling %<-fstack-check=%>");
+ flag_stack_check = NO_STACK_CHECK;
+ }
+
+ /* Targets must be able to place spill slots at lower addresses. If the
+ target already uses a soft frame pointer, the transition is trivial. */
+ if (!FRAME_GROWS_DOWNWARD && flag_stack_protect)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fstack-protector%> not supported for this target");
+ flag_stack_protect = 0;
+ }
+ if (!flag_stack_protect)
+ warn_stack_protect = 0;
+
+ /* Address Sanitizer needs porting to each target architecture. */
+
+ if ((flag_sanitize & SANITIZE_ADDRESS)
+ && !FRAME_GROWS_DOWNWARD)
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fsanitize=address%> and %<-fsanitize=kernel-address%> "
+ "are not supported for this target");
+ flag_sanitize &= ~SANITIZE_ADDRESS;
+ }
+
+#if 0 // sdcpp
+ if ((flag_sanitize & SANITIZE_USER_ADDRESS)
+ && ((targetm.asan_shadow_offset == NULL)
+ || (targetm.asan_shadow_offset () == 0)))
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fsanitize=address%> not supported for this target");
+ flag_sanitize &= ~SANITIZE_ADDRESS;
+ }
+
+ if ((flag_sanitize & SANITIZE_KERNEL_ADDRESS)
+ && (targetm.asan_shadow_offset == NULL
+ && !asan_shadow_offset_set_p ()))
+ {
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-fsanitize=kernel-address%> with stack protection "
+ "is not supported without %<-fasan-shadow-offset=%> "
+ "for this target");
+ flag_sanitize &= ~SANITIZE_ADDRESS;
+ }
+
+ /* HWAsan requires top byte ignore feature in the backend. */
+ if (flag_sanitize & SANITIZE_HWADDRESS
+ && ! targetm.memtag.can_tag_addresses ())
+ {
+ warning_at (UNKNOWN_LOCATION, 0, "%qs is not supported for this target",
+ "-fsanitize=hwaddress");
+ flag_sanitize &= ~SANITIZE_HWADDRESS;
+ }
+
+ if (flag_sanitize & SANITIZE_SHADOW_CALL_STACK)
+ {
+ if (!targetm.have_shadow_call_stack)
+ sorry ("%<-fsanitize=shadow-call-stack%> not supported "
+ "in current platform");
+ else if (flag_exceptions)
+ error_at (UNKNOWN_LOCATION, "%<-fsanitize=shadow-call-stack%> "
+ "requires %<-fno-exceptions%>");
+ }
+#endif // sdcpp
+
+ HOST_WIDE_INT patch_area_size, patch_area_start;
+ parse_and_check_patch_area (flag_patchable_function_entry, false,
+ &patch_area_size, &patch_area_start);
+
+#if 0 // sdcpp
+ /* Do not use IPA optimizations for register allocation if profiler is active
+ or patchable function entries are inserted for run-time instrumentation
+ or port does not emit prologue and epilogue as RTL. */
+ if (profile_flag || patch_area_size
+ || !targetm.have_prologue () || !targetm.have_epilogue ())
+ flag_ipa_ra = 0;
+#endif
+
+ /* Enable -Werror=coverage-mismatch when -Werror and -Wno-error
+ have not been set. */
+ if (!OPTION_SET_P (warnings_are_errors))
+ {
+ if (warn_coverage_mismatch
+ && (global_dc->classify_diagnostic[OPT_Wcoverage_mismatch] ==
+ DK_UNSPECIFIED))
+ diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_mismatch,
+ DK_ERROR, UNKNOWN_LOCATION);
+ if (warn_coverage_invalid_linenum
+ && (global_dc->classify_diagnostic[OPT_Wcoverage_invalid_line_number] ==
+ DK_UNSPECIFIED))
+ diagnostic_classify_diagnostic (global_dc, OPT_Wcoverage_invalid_line_number,
+ DK_ERROR, UNKNOWN_LOCATION);
+ }
+
+#if 0 // sdcpp
+ /* Save the current optimization options. */
+ optimization_default_node
+ = build_optimization_node (&global_options, &global_options_set);
+ optimization_current_node = optimization_default_node;
+#endif
+
+ if (flag_checking >= 2)
+ hash_table_sanitize_eq_limit
+ = param_hash_table_verification_limit;
+
+ if (flag_large_source_files)
+ line_table->default_range_bits = 0;
+
+ diagnose_options (&global_options, &global_options_set, UNKNOWN_LOCATION);
+
+ /* Please don't change global_options after this point, those changes won't
+ be reflected in optimization_{default,current}_node. */
+}
+
+#if 0 // sdcpp
+/* This function can be called multiple times to reinitialize the compiler
+ back end when register classes or instruction sets have changed,
+ before each function. */
+static void
+backend_init_target (void)
+{
+ /* This depends on stack_pointer_rtx. */
+ init_fake_stack_mems ();
+
+ /* Sets static_base_value[HARD_FRAME_POINTER_REGNUM], which is
+ mode-dependent. */
+ init_alias_target ();
+
+ /* Depends on HARD_FRAME_POINTER_REGNUM. */
+ if (!ira_use_lra_p)
+ init_reload ();
+
+ /* Depends on the enabled attribute. */
+ recog_init ();
+
+ /* The following initialization functions need to generate rtl, so
+ provide a dummy function context for them. */
+ init_dummy_function_start ();
+
+ /* rtx_cost is mode-dependent, so cached values need to be recomputed
+ on a mode change. */
+ init_expmed ();
+ init_lower_subreg ();
+ init_set_costs ();
+
+ init_expr_target ();
+ ira_init ();
+
+ /* We may need to recompute regno_save_code[] and regno_restore_code[]
+ after a mode change as well. */
+ caller_save_initialized_p = false;
+
+ expand_dummy_function_end ();
+}
+#endif // sdcpp
+
+/* Initialize the compiler back end. This function is called only once,
+ when starting the compiler. */
+#if 0 // sdcpp
+static void
+backend_init (void)
+{
+ init_emit_once ();
+
+ init_rtlanal ();
+ init_inline_once ();
+ init_varasm_once ();
+ save_register_info ();
+
+ /* Middle end needs this initialization for default mem attributes
+ used by early calls to make_decl_rtl. */
+ init_emit_regs ();
+
+ /* Middle end needs this initialization for mode tables used to assign
+ modes to vector variables. */
+ init_regs ();
+}
+
+#endif // sdcpp
+/* Initialize things that are both lang-dependent and target-dependent.
+ This function can be called more than once if target parameters change. */
+static void
+lang_dependent_init_target (void)
+{
+ /* This creates various _DECL nodes, so needs to be called after the
+ front end is initialized. It also depends on the HAVE_xxx macros
+ generated from the target machine description. */
+ gcc_assert(0 && "optabs");
+ // init_optabs ();
+
+// sdcpp gcc_assert (!this_target_rtl->target_specific_initialized);
+}
+
+/* Perform initializations that are lang-dependent or target-dependent.
+ but matters only for late optimizations and RTL generation. */
+
+#if 0 // sdcpp
+static int rtl_initialized;
+
+void
+initialize_rtl (void)
+{
+ auto_timevar tv (g_timer, TV_INITIALIZE_RTL);
+
+ /* Initialization done just once per compilation, but delayed
+ till code generation. */
+ if (!rtl_initialized)
+ ira_init_once ();
+ rtl_initialized = true;
+
+ /* Target specific RTL backend initialization. */
+ if (!this_target_rtl->target_specific_initialized)
+ {
+ backend_init_target ();
+ this_target_rtl->target_specific_initialized = true;
+ }
+}
+#endif
+
+/* Language-dependent initialization. Returns nonzero on success. */
+static int
+lang_dependent_init (const char *name)
+{
+ location_t save_loc = input_location;
+ if (!dump_base_name)
+ {
+ dump_base_name = name && name[0] ? name : "gccdump";
+
+ /* We do not want to derive a non-empty dumpbase-ext from an
+ explicit -dumpbase argument, only from a defaulted
+ dumpbase. */
+ if (!dump_base_ext)
+ {
+ const char *base = lbasename (dump_base_name);
+ const char *ext = strrchr (base, '.');
+ if (ext)
+ dump_base_ext = ext;
+ }
+ }
+
+ /* Other front-end initialization. */
+ input_location = BUILTINS_LOCATION;
+ if (lang_hooks.init () == 0)
+ return 0;
+ assert(false);
+ input_location = save_loc;
+
+ if (!flag_wpa)
+ {
+ init_asm_output (name);
+
+ if (!flag_generate_lto && !flag_compare_debug)
+ {
+ /* If stack usage information is desired, open the output file. */
+ if (flag_stack_usage)
+ stack_usage_file = open_auxiliary_file ("su");
+
+ /* If call graph information is desired, open the output file. */
+ if (flag_callgraph_info)
+ {
+ callgraph_info_file = open_auxiliary_file ("ci");
+ /* Write the file header. */
+ fprintf (callgraph_info_file,
+ "graph: { title: \"%s\"\n", main_input_filename);
+ bitmap_obstack_initialize (NULL);
+ callgraph_info_external_printed = BITMAP_ALLOC (NULL);
+ }
+ }
+ else
+ flag_stack_usage = flag_callgraph_info = false;
+ }
+
+ /* This creates various _DECL nodes, so needs to be called after the
+ front end is initialized. */
+ init_eh ();
+
+ /* Do the target-specific parts of the initialization. */
+ lang_dependent_init_target ();
+
+ if (!flag_wpa)
+ {
+ /* If dbx symbol table desired, initialize writing it and output the
+ predefined types. */
+ timevar_push (TV_SYMOUT);
+
+ /* Now we have the correct original filename, we can initialize
+ debug output. */
+ (*debug_hooks->init) (name);
+
+ timevar_pop (TV_SYMOUT);
+ }
+
+ return 1;
+}
+
+
+/* Reinitialize everything when target parameters, such as register usage,
+ have changed. */
+void
+target_reinit (void)
+{
+ //sdcpp
+ gcc_assert(0 && "reinit");
+#if 0
+ struct rtl_data saved_x_rtl;
+ rtx *saved_regno_reg_rtx;
+ tree saved_optimization_current_node;
+ struct target_optabs *saved_this_fn_optabs;
+
+ /* Temporarily switch to the default optimization node, so that
+ *this_target_optabs is set to the default, not reflecting
+ whatever a previous function used for the optimize
+ attribute. */
+ saved_optimization_current_node = optimization_current_node;
+ saved_this_fn_optabs = this_fn_optabs;
+ if (saved_optimization_current_node != optimization_default_node)
+ {
+ optimization_current_node = optimization_default_node;
+ cl_optimization_restore
+ (&global_options, &global_options_set,
+ TREE_OPTIMIZATION (optimization_default_node));
+ }
+ this_fn_optabs = this_target_optabs;
+
+ /* Save *crtl and regno_reg_rtx around the reinitialization
+ to allow target_reinit being called even after prepare_function_start. */
+ saved_regno_reg_rtx = regno_reg_rtx;
+ if (saved_regno_reg_rtx)
+ {
+ saved_x_rtl = *crtl;
+ memset (crtl, '\0', sizeof (*crtl));
+ regno_reg_rtx = NULL;
+ }
+
+ this_target_rtl->target_specific_initialized = false;
+
+ /* This initializes hard_frame_pointer, and calls init_reg_modes_target()
+ to initialize reg_raw_mode[]. */
+ init_emit_regs ();
+
+ /* This invokes target hooks to set fixed_reg[] etc, which is
+ mode-dependent. */
+ init_regs ();
+
+ /* Reinitialize lang-dependent parts. */
+ lang_dependent_init_target ();
+
+ /* Restore the original optimization node. */
+ if (saved_optimization_current_node != optimization_default_node)
+ {
+ optimization_current_node = saved_optimization_current_node;
+ cl_optimization_restore (&global_options, &global_options_set,
+ TREE_OPTIMIZATION (optimization_current_node));
+ }
+ this_fn_optabs = saved_this_fn_optabs;
+
+ /* Restore regno_reg_rtx at the end, as free_after_compilation from
+ expand_dummy_function_end clears it. */
+ if (saved_regno_reg_rtx)
+ {
+ *crtl = saved_x_rtl;
+ regno_reg_rtx = saved_regno_reg_rtx;
+ saved_regno_reg_rtx = NULL;
+ }
+#endif
+}
+
+#if 1 // sdcpp
+void
+dump_memory_report (const char *header)
+{
+ /* Print significant header. */
+ fputc ('\n', stderr);
+ for (unsigned i = 0; i < 80; i++)
+ fputc ('#', stderr);
+ fprintf (stderr, "\n# %-77s#\n", header);
+ for (unsigned i = 0; i < 80; i++)
+ fputc ('#', stderr);
+ fputs ("\n\n", stderr);
+
+ dump_line_table_statistics ();
+ ggc_print_statistics ();
+ fprintf(stderr, "incomplete %s %d\n", __func__, __LINE__);
+#if 0 // sdcpp
+ stringpool_statistics ();
+ dump_tree_statistics ();
+ dump_gimple_statistics ();
+ sdcpp dump_rtx_statistics ();
+ sdcpp dump_alloc_pool_statistics ();
+ sdcpp dump_bitmap_statistics ();
+ sdcpp dump_hash_table_loc_statistics ();
+ sdcpp dump_vec_loc_statistics ();
+ sdcpp dump_ggc_loc_statistics ();
+ sdcpp dump_alias_stats (stderr);
+ sdcpp dump_pta_stats (stderr);
+#endif // sdcpp
+}
+#endif // sdcpp
+
+/* Clean up: close opened files, etc. */
+
+static void
+finalize (bool no_backend)
+{
+ /* Close the dump files. */
+ if (flag_gen_aux_info)
+ {
+ fclose (aux_info_file);
+ aux_info_file = NULL;
+ if (seen_error ())
+ unlink (aux_info_file_name);
+ }
+
+ /* Close non-debugging input and output files. Take special care to note
+ whether fclose returns an error, since the pages might still be on the
+ buffer chain while the file is open. */
+
+ if (asm_out_file)
+ {
+ if (ferror (asm_out_file) != 0)
+ fatal_error (input_location, "error writing to %s: %m", asm_file_name);
+ if (fclose (asm_out_file) != 0)
+ fatal_error (input_location, "error closing %s: %m", asm_file_name);
+ asm_out_file = NULL;
+ }
+
+ if (stack_usage_file)
+ {
+ fclose (stack_usage_file);
+ stack_usage_file = NULL;
+ }
+
+ if (callgraph_info_file)
+ {
+ fputs ("}\n", callgraph_info_file);
+ fclose (callgraph_info_file);
+ callgraph_info_file = NULL;
+ BITMAP_FREE (callgraph_info_external_printed);
+ bitmap_obstack_release (NULL);
+ }
+
+ // sdcpp ??
+ // if (seen_error ())
+ // coverage_remove_note_file ();
+
+ if (!no_backend)
+ {
+ gcc_assert(0 && "passes");
+#if 0 // sdcpp
+ statistics_fini ();
+ debuginfo_fini ();
+ g->get_passes ()->finish_optimization_passes ();
+ lra_finish_once ();
+#endif
+ }
+
+ if (mem_report)
+ dump_memory_report ("Final");
+
+ if (profile_report)
+ dump_profile_report ();
+
+ if (flag_dbg_cnt_list)
+ dbg_cnt_list_all_counters ();
+
+ /* Language-specific end of compilation actions. */
+ lang_hooks.finish ();
+}
+
+#if 0 // sdcpp
+static bool
+standard_type_bitsize (int bitsize)
+{
+ /* As a special exception, we always want __int128 enabled if possible. */
+ if (bitsize == 128)
+ return false;
+ if (bitsize == CHAR_TYPE_SIZE
+ || bitsize == SHORT_TYPE_SIZE
+ || bitsize == INT_TYPE_SIZE
+ || bitsize == LONG_TYPE_SIZE
+ || bitsize == LONG_LONG_TYPE_SIZE)
+ return true;
+ return false;
+}
+#endif // sdcpp
+
+/* Initialize the compiler, and compile the input file. */
+static void
+do_compile (bool no_backend)
+{
+ /* Don't do any more if an error has already occurred. */
+ if (!seen_error ())
+ {
+#if 0 // sdcpp
+ int i;
+
+ timevar_start (TV_PHASE_SETUP);
+
+ if (flag_save_optimization_record)
+ {
+ gcc_assert(0 && "dump"); // sdcpp
+ // dump_context::get ().set_json_writer (new optrecord_json_writer ());
+ }
+
+ /* This must be run always, because it is needed to compute the FP
+ predefined macros, such as __LDBL_MAX__, for targets using non
+ default FP formats. */
+ init_adjust_machine_modes ();
+ init_derived_machine_modes ();
+#endif // sdcpp
+
+ /* This must happen after the backend has a chance to process
+ command line options, but before the parsers are
+ initialized. */
+#if 0 // sdcpp
+ for (i = 0; i < NUM_INT_N_ENTS; i ++)
+ if (targetm.scalar_mode_supported_p (int_n_data[i].m)
+ && ! standard_type_bitsize (int_n_data[i].bitsize))
+ int_n_enabled_p[i] = true;
+ else
+ int_n_enabled_p[i] = false;
+
+ /* Initialize mpfrs exponent range. This is important to get
+ underflow/overflow in a reasonable timeframe. */
+ machine_mode mode;
+ int min_exp = -1;
+ int max_exp = 1;
+ FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+ if (SCALAR_FLOAT_MODE_P (mode))
+ {
+ const real_format *fmt = REAL_MODE_FORMAT (mode);
+ if (fmt)
+ {
+ /* fmt->emin - fmt->p + 1 should be enough but the
+ back-and-forth dance in real_to_decimal_for_mode we
+ do for checking fails due to rounding effects then. */
+ if ((fmt->emin - fmt->p) < min_exp)
+ min_exp = fmt->emin - fmt->p;
+ if (fmt->emax > max_exp)
+ max_exp = fmt->emax;
+ }
+ }
+ /* E.g. mpc_norm assumes it can square a number without bothering with
+ with range scaling, so until that is fixed, double the minimum
+ and maximum exponents, plus add some buffer for arithmetics
+ on the squared numbers. */
+ if (mpfr_set_emin (2 * (min_exp - 1))
+ || mpfr_set_emax (2 * (max_exp + 1)))
+ sorry ("mpfr not configured to handle all floating modes");
+#endif
+
+ /* Set up the back-end if requested. */
+ if (!no_backend) { assert(false);
+ // sdcpp backend_init ();
+ }
+
+ /* Language-dependent initialization. Returns true on success. */
+ if (lang_dependent_init (main_input_filename))
+ gcc_assert(0 && "lang dep");
+#if 0 // scdpp
+ {
+ /* Initialize yet another pass. */
+
+ ggc_protect_identifiers = true;
+
+ symtab->initialize ();
+ init_final (main_input_filename);
+ // sdcpp
+ // coverage_init (aux_base_name);
+ statistics_init ();
+ debuginfo_init ();
+ invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
+
+ timevar_stop (TV_PHASE_SETUP);
+
+ compile_file ();
+ }
+#endif // sdcpp
+ else
+ {
+ timevar_stop (TV_PHASE_SETUP);
+ }
+
+ timevar_start (TV_PHASE_FINALIZE);
+
+ finalize (no_backend);
+
+ timevar_stop (TV_PHASE_FINALIZE);
+ }
+}
+
+toplev::toplev (timer *external_timer,
+ bool init_signals)
+ : m_use_TV_TOTAL (external_timer == NULL),
+ m_init_signals (init_signals)
+{
+ if (external_timer)
+ g_timer = external_timer;
+}
+
+toplev::~toplev ()
+{
+ if (g_timer && m_use_TV_TOTAL)
+ {
+ g_timer->stop (TV_TOTAL);
+ g_timer->print (stderr);
+ delete g_timer;
+ g_timer = NULL;
+ }
+}
+
+/* Potentially call timevar_init (which will create g_timevars if it
+ doesn't already exist). */
+
+void
+toplev::start_timevars ()
+{
+ if (time_report || !quiet_flag || flag_detailed_statistics)
+ timevar_init ();
+
+ timevar_start (TV_TOTAL);
+}
+
+/* Handle -fself-test. */
+
+void
+toplev::run_self_tests ()
+{
+#if CHECKING_P
+ /* Reset some state. */
+ input_location = UNKNOWN_LOCATION;
+ bitmap_obstack_initialize (NULL);
+
+ /* Run the tests; any failures will lead to an abort of the process.
+ Use "make selftests-gdb" to run under the debugger. */
+ ::selftest::run_tests ();
+
+ /* Cleanup. */
+ bitmap_obstack_release (NULL);
+#else
+ inform (UNKNOWN_LOCATION, "self-tests are not enabled in this build");
+#endif /* #if CHECKING_P */
+}
+
+// sdcpp hack
+static void docb()
+{ untested();
+}
+
+/* Entry point of cc1, cc1plus, jc1, f771, etc.
+ Exit code is FATAL_EXIT_CODE if can't open files or if there were
+ any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
+
+ It is not safe to call this function more than once. */
+
+int
+toplev::main (int argc, char **argv)
+{
+ /* Parsing and gimplification sometimes need quite large stack.
+ Increase stack size limits if possible. */
+ stack_limit_increase (64 * 1024 * 1024);
+
+ expandargv (&argc, &argv);
+
+ /* Initialization of GCC's environment, and diagnostics. */
+ general_init (argv[0], m_init_signals);
+
+ /* One-off initialization of options that does not need to be
+ repeated when options are added for particular functions. */
+ init_options_once ();
+ init_opts_obstack ();
+
+ /* Initialize global options structures; this must be repeated for
+ each structure used for parsing options. */
+ init_options_struct (&global_options, &global_options_set);
+ lang_hooks.init_options_struct (&global_options);
+
+ /* Init GGC heuristics must be caller after we initialize
+ options. */
+ init_ggc_heuristics ();
+
+ /* Convert the options to an array. */
+ decode_cmdline_options_to_array_default_mask (argc,
+ CONST_CAST2 (const char **,
+ char **, argv),
+ &save_decoded_options,
+ &save_decoded_options_count);
+
+ /* Save Optimization decoded options. */
+ save_opt_decoded_options = new vec<cl_decoded_option> ();
+ for (unsigned i = 1; i < save_decoded_options_count; ++i)
+ if (save_decoded_options[i].opt_index < cl_options_count
+ && cl_options[save_decoded_options[i].opt_index].flags & CL_OPTIMIZATION)
+ save_opt_decoded_options->safe_push (save_decoded_options[i]);
+
+ /* Perform language-specific options initialization. */
+ lang_hooks.init_options (save_decoded_options_count, save_decoded_options);
+
+ /* Parse the options and do minimal processing; basically just
+ enough to default flags appropriately. */
+ decode_options (&global_options, &global_options_set,
+ save_decoded_options, save_decoded_options_count,
+ UNKNOWN_LOCATION, global_dc,
+ &docb); // (targetm.target_option.override);
+
+ handle_common_deferred_options ();
+
+ init_local_tick ();
+
+ initialize_plugins ();
+
+ if (version_flag)
+ print_version (stderr, "", true);
+
+ if (help_flag)
+ print_plugins_help (stderr, "");
+
+ /* Exit early if we can (e.g. -help). */
+ if (!exit_after_options)
+ {
+ /* Just in case lang_hooks.post_options ends up calling a debug_hook.
+ This can happen with incorrect pre-processed input. */
+ debug_hooks = &do_nothing_debug_hooks;
+ /* Allow the front end to perform consistency checks and do further
+ initialization based on the command line options. This hook also
+ sets the original filename if appropriate (e.g. foo.i -> foo.c)
+ so we can correctly initialize debug output. */
+ bool no_backend = lang_hooks.post_options (&main_input_filename);
+ assert(no_backend);
+
+ process_options (no_backend);
+
+ if (m_use_TV_TOTAL)
+ start_timevars ();
+ do_compile (no_backend);
+
+ if (flag_self_test)
+ { untested();
+ if (no_backend)
+ error_at (UNKNOWN_LOCATION, "self-tests incompatible with %<-E%>");
+ else
+ run_self_tests ();
+ }
+ }
+
+ if (warningcount || errorcount || werrorcount)
+ print_ignored_options ();
+
+ /* Invoke registered plugin callbacks if any. Some plugins could
+ emit some diagnostics here. */
+ invoke_plugin_callbacks (PLUGIN_FINISH, NULL);
+
+ if (flag_diagnostics_generate_patch)
+ {
+ gcc_assert (global_dc->edit_context_ptr);
+
+ pretty_printer pp;
+ pp_show_color (&pp) = pp_show_color (global_dc->printer);
+ global_dc->edit_context_ptr->print_diff (&pp, true);
+ pp_flush (&pp);
+ }
+
+ diagnostic_finish (global_dc);
+
+ finalize_plugins ();
+
+ after_memory_report = true;
+
+ if (seen_error () || werrorcount)
+ return (FATAL_EXIT_CODE);
+
+ return (SUCCESS_EXIT_CODE);
+}
+
+/* For those that want to, this function aims to clean up enough state that
+ you can call toplev::main again. */
+void
+toplev::finalize (void)
+{
+#if 0 // sdcpp
+ rtl_initialized = false;
+ this_target_rtl->target_specific_initialized = false;
+
+ /* Needs to be called before cgraph_cc_finalize since it uses symtab. */
+ // sdcpp ipa_reference_cc_finalize ();
+ ipa_fnsummary_cc_finalize ();
+ ipa_modref_cc_finalize ();
+ ipa_edge_modifications_finalize ();
+
+ cgraph_cc_finalize ();
+ cgraphunit_cc_finalize ();
+ symtab_thunks_cc_finalize ();
+ dwarf2out_cc_finalize ();
+ // sdcpp gcse_cc_finalize ();
+ ipa_cp_cc_finalize ();
+ ira_costs_cc_finalize ();
+ tree_cc_finalize ();
+ reginfo_cc_finalize ();
+#endif // sdcpp
+
+ /* save_decoded_options uses opts_obstack, so these must
+ be cleaned up together. */
+ obstack_free (&opts_obstack, NULL);
+ XDELETEVEC (save_decoded_options);
+ save_decoded_options = NULL;
+ save_decoded_options_count = 0;
+
+ /* Clean up the context (and pass_manager etc). */
+ delete g;
+ g = NULL;
+
+}
diff --git a/support/cpp/gcc/toplev.h b/support/cpp/gcc/toplev.h
new file mode 100644
index 000000000..a82ef8b8f
--- /dev/null
+++ b/support/cpp/gcc/toplev.h
@@ -0,0 +1,102 @@
+/* toplev.h - Various declarations for functions found in toplev.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_TOPLEV_H
+#define GCC_TOPLEV_H
+
+/* Decoded options, and number of such options. */
+extern struct cl_decoded_option *save_decoded_options;
+extern unsigned int save_decoded_options_count;
+extern vec<cl_decoded_option> *save_opt_decoded_options;
+
+class timer;
+
+/* Invoking the compiler. */
+class toplev
+{
+public:
+ toplev (timer *external_timer,
+ bool init_signals);
+ ~toplev ();
+
+ int main (int argc, char **argv);
+
+ void finalize ();
+
+private:
+
+ void start_timevars ();
+
+ void run_self_tests ();
+
+ bool m_use_TV_TOTAL;
+ bool m_init_signals;
+};
+
+extern void rest_of_decl_compilation (tree, int, int);
+extern void rest_of_type_compilation (tree, int);
+extern void init_optimization_passes (void);
+extern bool enable_rtl_dump_file (void);
+
+/* In except.cc. Initialize exception handling. This is used by the Ada
+ and LTO front ends to initialize EH "on demand". See lto-streamer-in.cc
+ and ada/gcc-interface/misc.cc. */
+extern void init_eh (void);
+
+extern void announce_function (tree);
+
+extern void wrapup_global_declaration_1 (tree);
+extern bool wrapup_global_declaration_2 (tree);
+extern bool wrapup_global_declarations (tree *, int);
+
+extern void global_decl_processing (void);
+
+extern void
+dump_memory_report (const char *);
+extern void dump_profile_report (void);
+
+extern void target_reinit (void);
+
+/* A unique local time stamp, might be zero if none is available. */
+extern unsigned local_tick;
+
+/* See toplev.cc. */
+extern int flag_rerun_cse_after_global_opts;
+
+extern void print_version (FILE *, const char *, bool);
+
+/* The hashtable, so that the C front ends can pass it to cpplib. */
+extern struct ht *ident_hash;
+
+/* Functions used to get and set GCC's notion of in what directory
+ compilation was started. */
+
+extern const char *get_src_pwd (void);
+extern bool set_src_pwd (const char *);
+
+/* Functions used to manipulate the random seed. */
+
+extern HOST_WIDE_INT get_random_seed (bool);
+extern void set_random_seed (const char *);
+
+extern void parse_alignment_opts (void);
+
+extern void initialize_rtl (void);
+
+#endif /* ! GCC_TOPLEV_H */
diff --git a/support/cpp/gcc/tree-core.h b/support/cpp/gcc/tree-core.h
new file mode 100644
index 000000000..30fecc61e
--- /dev/null
+++ b/support/cpp/gcc/tree-core.h
@@ -0,0 +1,2331 @@
+/* Core data structures for the 'tree' type.
+ Copyright (C) 1989-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_TREE_CORE_H
+#define GCC_TREE_CORE_H
+
+#include "symtab.h"
+
+/* This file contains all the data structures that define the 'tree' type.
+ There are no accessor macros nor functions in this file. Only the
+ basic data structures, extern declarations and type definitions. */
+
+/*---------------------------------------------------------------------------
+ Forward type declarations. Mostly to avoid including unnecessary headers
+---------------------------------------------------------------------------*/
+struct function;
+struct real_value;
+struct fixed_value;
+struct ptr_info_def;
+struct range_info_def;
+struct die_struct;
+
+
+/*---------------------------------------------------------------------------
+ #defined constants
+---------------------------------------------------------------------------*/
+/* Nonzero if this is a call to a function whose return value depends
+ solely on its arguments, has no side effects, and does not read
+ global memory. This corresponds to TREE_READONLY for function
+ decls. */
+#define ECF_CONST (1 << 0)
+
+/* Nonzero if this is a call to "pure" function (like const function,
+ but may read memory. This corresponds to DECL_PURE_P for function
+ decls. */
+#define ECF_PURE (1 << 1)
+
+/* Nonzero if this is ECF_CONST or ECF_PURE but cannot be proven to no
+ infinite loop. This corresponds to DECL_LOOPING_CONST_OR_PURE_P
+ for function decls.*/
+#define ECF_LOOPING_CONST_OR_PURE (1 << 2)
+
+/* Nonzero if this call will never return. */
+#define ECF_NORETURN (1 << 3)
+
+/* Nonzero if this is a call to malloc or a related function. */
+#define ECF_MALLOC (1 << 4)
+
+/* Nonzero if it is plausible that this is a call to alloca. */
+#define ECF_MAY_BE_ALLOCA (1 << 5)
+
+/* Nonzero if this is a call to a function that won't throw an exception. */
+#define ECF_NOTHROW (1 << 6)
+
+/* Nonzero if this is a call to setjmp or a related function. */
+#define ECF_RETURNS_TWICE (1 << 7)
+
+/* Nonzero if this call replaces the current stack frame. */
+#define ECF_SIBCALL (1 << 8)
+
+/* Function does not read or write memory (but may have side effects, so
+ it does not necessarily fit ECF_CONST). */
+#define ECF_NOVOPS (1 << 9)
+
+/* The function does not lead to calls within current function unit. */
+#define ECF_LEAF (1 << 10)
+
+/* Nonzero if this call returns its first argument. */
+#define ECF_RET1 (1 << 11)
+
+/* Nonzero if this call does not affect transactions. */
+#define ECF_TM_PURE (1 << 12)
+
+/* Nonzero if this call is into the transaction runtime library. */
+#define ECF_TM_BUILTIN (1 << 13)
+
+/* Nonzero if this is an indirect call by descriptor. */
+#define ECF_BY_DESCRIPTOR (1 << 14)
+
+/* Nonzero if this is a cold function. */
+#define ECF_COLD (1 << 15)
+
+/* Call argument flags. */
+
+/* Nonzero if the argument is not used by the function. */
+#define EAF_UNUSED (1 << 1)
+
+/* Following flags come in pairs. First one is about direct dereferences
+ from the parameter, while the second is about memory reachable by
+ recursive dereferences. */
+
+/* Nonzero if memory reached by the argument is not clobbered. */
+#define EAF_NO_DIRECT_CLOBBER (1 << 2)
+#define EAF_NO_INDIRECT_CLOBBER (1 << 3)
+
+/* Nonzero if the argument does not escape. */
+#define EAF_NO_DIRECT_ESCAPE (1 << 4)
+#define EAF_NO_INDIRECT_ESCAPE (1 << 5)
+
+/* Nonzero if the argument does not escape to return value. */
+#define EAF_NOT_RETURNED_DIRECTLY (1 << 6)
+#define EAF_NOT_RETURNED_INDIRECTLY (1 << 7)
+
+/* Nonzero if the argument is not read. */
+#define EAF_NO_DIRECT_READ (1 << 8)
+#define EAF_NO_INDIRECT_READ (1 << 9)
+
+/* Call return flags. */
+/* Mask for the argument number that is returned. Lower two bits of
+ the return flags, encodes argument slots zero to three. */
+#define ERF_RETURN_ARG_MASK (3)
+
+/* Nonzero if the return value is equal to the argument number
+ flags & ERF_RETURN_ARG_MASK. */
+#define ERF_RETURNS_ARG (1 << 2)
+
+/* Nonzero if the return value does not alias with anything. Functions
+ with the malloc attribute have this set on their return value. */
+#define ERF_NOALIAS (1 << 3)
+
+
+/*---------------------------------------------------------------------------
+ Enumerations
+---------------------------------------------------------------------------*/
+/* Codes of tree nodes. */
+#define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM,
+#define END_OF_BASE_TREE_CODES LAST_AND_UNUSED_TREE_CODE,
+
+enum tree_code {
+#include "all-tree.def"
+MAX_TREE_CODES
+};
+
+#undef DEFTREECODE
+#undef END_OF_BASE_TREE_CODES
+
+/* Number of language-independent tree codes. */
+#define NUM_TREE_CODES \
+ ((int) LAST_AND_UNUSED_TREE_CODE)
+
+#define CODE_CONTAINS_STRUCT(CODE, STRUCT) \
+ (tree_contains_struct[(CODE)][(STRUCT)])
+
+
+/* Classify which part of the compiler has defined a given builtin function.
+ Note that we assume below that this is no more than two bits. */
+enum built_in_class {
+ NOT_BUILT_IN = 0,
+ BUILT_IN_FRONTEND,
+ BUILT_IN_MD,
+ BUILT_IN_NORMAL
+};
+
+/* Last marker used for LTO stremaing of built_in_class. We cannot add it
+ to the enum since we need the enumb to fit in 2 bits. */
+#define BUILT_IN_LAST (BUILT_IN_NORMAL + 1)
+
+/* Codes that identify the various built in functions
+ so that expand_call can identify them quickly. */
+#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) ENUM,
+enum built_in_function {
+#include "builtins.def"
+
+#if 0 // sdcpp
+ /* Complex division routines in libgcc. These are done via builtins
+ because emit_library_call_value can't handle complex values. */
+ BUILT_IN_COMPLEX_MUL_MIN,
+ BUILT_IN_COMPLEX_MUL_MAX
+ = BUILT_IN_COMPLEX_MUL_MIN
+ + MAX_MODE_COMPLEX_FLOAT
+ - MIN_MODE_COMPLEX_FLOAT,
+
+ BUILT_IN_COMPLEX_DIV_MIN,
+ BUILT_IN_COMPLEX_DIV_MAX
+ = BUILT_IN_COMPLEX_DIV_MIN
+ + MAX_MODE_COMPLEX_FLOAT
+ - MIN_MODE_COMPLEX_FLOAT,
+
+ /* Upper bound on non-language-specific builtins. */
+#endif // sdcpp
+
+ END_BUILTINS
+};
+
+/* Internal functions. */
+enum internal_fn {
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) IFN_##CODE,
+#include "internal-fn.def"
+ IFN_LAST
+};
+
+/* An enum that combines target-independent built-in functions with
+ internal functions, so that they can be treated in a similar way.
+ The numbers for built-in functions are the same as for the
+ built_in_function enum. The numbers for internal functions
+ start at END_BUITLINS. */
+enum combined_fn {
+#define DEF_BUILTIN(ENUM, N, C, T, LT, B, F, NA, AT, IM, COND) \
+ CFN_##ENUM = int (ENUM),
+#include "builtins.def"
+
+
+#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \
+ CFN_##CODE = int (END_BUILTINS) + int (IFN_##CODE),
+#include "internal-fn.def"
+
+ CFN_LAST
+};
+
+/* Tree code classes. Each tree_code has an associated code class
+ represented by a TREE_CODE_CLASS. */
+enum tree_code_class {
+ tcc_exceptional, /* An exceptional code (fits no category). */
+ tcc_constant, /* A constant. */
+ /* Order of tcc_type and tcc_declaration is important. */
+ tcc_type, /* A type object code. */
+ tcc_declaration, /* A declaration (also serving as variable refs). */
+ tcc_reference, /* A reference to storage. */
+ tcc_comparison, /* A comparison expression. */
+ tcc_unary, /* A unary arithmetic expression. */
+ tcc_binary, /* A binary arithmetic expression. */
+ tcc_statement, /* A statement expression, which have side effects
+ but usually no interesting value. */
+ tcc_vl_exp, /* A function call or other expression with a
+ variable-length operand vector. */
+ tcc_expression /* Any other expression. */
+};
+
+/* OMP_CLAUSE codes. Do not reorder, as this is used to index into
+ the tables omp_clause_num_ops and omp_clause_code_name. */
+enum omp_clause_code {
+ /* Clause zero is special-cased inside the parser
+ (c_parser_omp_variable_list). */
+ OMP_CLAUSE_ERROR = 0,
+
+ /* OpenACC/OpenMP clause: private (variable_list). */
+ OMP_CLAUSE_PRIVATE,
+
+ /* OpenMP clause: shared (variable_list). */
+ OMP_CLAUSE_SHARED,
+
+ /* OpenACC/OpenMP clause: firstprivate (variable_list). */
+ OMP_CLAUSE_FIRSTPRIVATE,
+
+ /* OpenMP clause: lastprivate (variable_list). */
+ OMP_CLAUSE_LASTPRIVATE,
+
+ /* OpenACC/OpenMP clause: reduction (operator:variable_list).
+ OMP_CLAUSE_REDUCTION_CODE: The tree_code of the operator.
+ Operand 1: OMP_CLAUSE_REDUCTION_INIT: Stmt-list to initialize the var.
+ Operand 2: OMP_CLAUSE_REDUCTION_MERGE: Stmt-list to merge private var
+ into the shared one.
+ Operand 3: OMP_CLAUSE_REDUCTION_PLACEHOLDER: A dummy VAR_DECL
+ placeholder used in OMP_CLAUSE_REDUCTION_{INIT,MERGE}.
+ Operand 4: OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER: Another dummy
+ VAR_DECL placeholder, used like the above for C/C++ array
+ reductions. */
+ OMP_CLAUSE_REDUCTION,
+
+ /* OpenMP clause: task_reduction (operator:variable_list). */
+ OMP_CLAUSE_TASK_REDUCTION,
+
+ /* OpenMP clause: in_reduction (operator:variable_list). */
+ OMP_CLAUSE_IN_REDUCTION,
+
+ /* OpenMP clause: copyin (variable_list). */
+ OMP_CLAUSE_COPYIN,
+
+ /* OpenMP clause: copyprivate (variable_list). */
+ OMP_CLAUSE_COPYPRIVATE,
+
+ /* OpenMP clause: linear (variable-list[:linear-step]). */
+ OMP_CLAUSE_LINEAR,
+
+ /* OpenMP clause: affinity([depend-modifier :] variable-list). */
+ OMP_CLAUSE_AFFINITY,
+
+ /* OpenMP clause: aligned (variable-list[:alignment]). */
+ OMP_CLAUSE_ALIGNED,
+
+ /* OpenMP clause: allocate ([allocator:]variable-list). */
+ OMP_CLAUSE_ALLOCATE,
+
+ /* OpenMP clause: depend ({in,out,inout}:variable-list). */
+ OMP_CLAUSE_DEPEND,
+
+ /* OpenMP clause: nontemporal (variable-list). */
+ OMP_CLAUSE_NONTEMPORAL,
+
+ /* OpenMP clause: uniform (argument-list). */
+ OMP_CLAUSE_UNIFORM,
+
+ /* OpenMP clause: to (extended-list).
+ Only when it appears in declare target. */
+ OMP_CLAUSE_TO_DECLARE,
+
+ /* OpenMP clause: link (variable-list). */
+ OMP_CLAUSE_LINK,
+
+ /* OpenMP clause: detach (event-handle). */
+ OMP_CLAUSE_DETACH,
+
+ /* OpenACC clause: use_device (variable-list).
+ OpenMP clause: use_device_ptr (ptr-list). */
+ OMP_CLAUSE_USE_DEVICE_PTR,
+
+ /* OpenMP clause: use_device_addr (variable-list). */
+ OMP_CLAUSE_USE_DEVICE_ADDR,
+
+ /* OpenMP clause: is_device_ptr (variable-list). */
+ OMP_CLAUSE_IS_DEVICE_PTR,
+
+ /* OpenMP clause: inclusive (variable-list). */
+ OMP_CLAUSE_INCLUSIVE,
+
+ /* OpenMP clause: exclusive (variable-list). */
+ OMP_CLAUSE_EXCLUSIVE,
+
+ /* OpenMP clause: from (variable-list). */
+ OMP_CLAUSE_FROM,
+
+ /* OpenMP clause: to (variable-list). */
+ OMP_CLAUSE_TO,
+
+ /* OpenACC clauses: {copy, copyin, copyout, create, delete, deviceptr,
+ device, host (self), present, present_or_copy (pcopy), present_or_copyin
+ (pcopyin), present_or_copyout (pcopyout), present_or_create (pcreate)}
+ (variable-list).
+
+ OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */
+ OMP_CLAUSE_MAP,
+
+ /* OpenMP clause: has_device_addr (variable-list). */
+ OMP_CLAUSE_HAS_DEVICE_ADDR,
+
+ /* Internal structure to hold OpenACC cache directive's variable-list.
+ #pragma acc cache (variable-list). */
+ OMP_CLAUSE__CACHE_,
+
+ /* OpenACC clause: gang [(gang-argument-list)].
+ Where
+ gang-argument-list: [gang-argument-list, ] gang-argument
+ gang-argument: [num:] integer-expression
+ | static: size-expression
+ size-expression: * | integer-expression. */
+ OMP_CLAUSE_GANG,
+
+ /* OpenACC clause: async [(integer-expression)]. */
+ OMP_CLAUSE_ASYNC,
+
+ /* OpenACC clause: wait [(integer-expression-list)]. */
+ OMP_CLAUSE_WAIT,
+
+ /* OpenACC clause: auto. */
+ OMP_CLAUSE_AUTO,
+
+ /* OpenACC clause: seq. */
+ OMP_CLAUSE_SEQ,
+
+ /* Internal clause: temporary for combined loops expansion. */
+ OMP_CLAUSE__LOOPTEMP_,
+
+ /* Internal clause: temporary for task reductions. */
+ OMP_CLAUSE__REDUCTEMP_,
+
+ /* Internal clause: temporary for lastprivate(conditional:). */
+ OMP_CLAUSE__CONDTEMP_,
+
+ /* Internal clause: temporary for inscan reductions. */
+ OMP_CLAUSE__SCANTEMP_,
+
+ /* OpenACC/OpenMP clause: if (scalar-expression). */
+ OMP_CLAUSE_IF,
+
+ /* OpenMP clause: num_threads (integer-expression). */
+ OMP_CLAUSE_NUM_THREADS,
+
+ /* OpenMP clause: schedule. */
+ OMP_CLAUSE_SCHEDULE,
+
+ /* OpenMP clause: nowait. */
+ OMP_CLAUSE_NOWAIT,
+
+ /* OpenMP clause: ordered [(constant-integer-expression)]. */
+ OMP_CLAUSE_ORDERED,
+
+ /* OpenACC/OpenMP clause: default. */
+ OMP_CLAUSE_DEFAULT,
+
+ /* OpenACC/OpenMP clause: collapse (constant-integer-expression). */
+ OMP_CLAUSE_COLLAPSE,
+
+ /* OpenMP clause: untied. */
+ OMP_CLAUSE_UNTIED,
+
+ /* OpenMP clause: final (scalar-expression). */
+ OMP_CLAUSE_FINAL,
+
+ /* OpenMP clause: mergeable. */
+ OMP_CLAUSE_MERGEABLE,
+
+ /* OpenMP clause: device (integer-expression). */
+ OMP_CLAUSE_DEVICE,
+
+ /* OpenMP clause: dist_schedule (static[:chunk-size]). */
+ OMP_CLAUSE_DIST_SCHEDULE,
+
+ /* OpenMP clause: inbranch. */
+ OMP_CLAUSE_INBRANCH,
+
+ /* OpenMP clause: notinbranch. */
+ OMP_CLAUSE_NOTINBRANCH,
+
+ /* OpenMP clause: num_teams(integer-expression). */
+ OMP_CLAUSE_NUM_TEAMS,
+
+ /* OpenMP clause: thread_limit(integer-expression). */
+ OMP_CLAUSE_THREAD_LIMIT,
+
+ /* OpenMP clause: proc_bind ({master,close,spread}). */
+ OMP_CLAUSE_PROC_BIND,
+
+ /* OpenMP clause: safelen (constant-integer-expression). */
+ OMP_CLAUSE_SAFELEN,
+
+ /* OpenMP clause: simdlen (constant-integer-expression). */
+ OMP_CLAUSE_SIMDLEN,
+
+ /* OpenMP clause: device_type ({host,nohost,any}). */
+ OMP_CLAUSE_DEVICE_TYPE,
+
+ /* OpenMP clause: for. */
+ OMP_CLAUSE_FOR,
+
+ /* OpenMP clause: parallel. */
+ OMP_CLAUSE_PARALLEL,
+
+ /* OpenMP clause: sections. */
+ OMP_CLAUSE_SECTIONS,
+
+ /* OpenMP clause: taskgroup. */
+ OMP_CLAUSE_TASKGROUP,
+
+ /* OpenMP clause: priority (integer-expression). */
+ OMP_CLAUSE_PRIORITY,
+
+ /* OpenMP clause: grainsize (integer-expression). */
+ OMP_CLAUSE_GRAINSIZE,
+
+ /* OpenMP clause: num_tasks (integer-expression). */
+ OMP_CLAUSE_NUM_TASKS,
+
+ /* OpenMP clause: nogroup. */
+ OMP_CLAUSE_NOGROUP,
+
+ /* OpenMP clause: threads. */
+ OMP_CLAUSE_THREADS,
+
+ /* OpenMP clause: simd. */
+ OMP_CLAUSE_SIMD,
+
+ /* OpenMP clause: hint (integer-expression). */
+ OMP_CLAUSE_HINT,
+
+ /* OpenMP clause: defaultmap (tofrom: scalar). */
+ OMP_CLAUSE_DEFAULTMAP,
+
+ /* OpenMP clause: order (concurrent). */
+ OMP_CLAUSE_ORDER,
+
+ /* OpenMP clause: bind (binding). */
+ OMP_CLAUSE_BIND,
+
+ /* OpenMP clause: filter (integer-expression). */
+ OMP_CLAUSE_FILTER,
+
+ /* Internally used only clause, holding SIMD uid. */
+ OMP_CLAUSE__SIMDUID_,
+
+ /* Internally used only clause, flag whether this is SIMT simd
+ loop or not. */
+ OMP_CLAUSE__SIMT_,
+
+ /* OpenACC clause: independent. */
+ OMP_CLAUSE_INDEPENDENT,
+
+ /* OpenACC clause: worker [( [num:] integer-expression)]. */
+ OMP_CLAUSE_WORKER,
+
+ /* OpenACC clause: vector [( [length:] integer-expression)]. */
+ OMP_CLAUSE_VECTOR,
+
+ /* OpenACC clause: num_gangs (integer-expression). */
+ OMP_CLAUSE_NUM_GANGS,
+
+ /* OpenACC clause: num_workers (integer-expression). */
+ OMP_CLAUSE_NUM_WORKERS,
+
+ /* OpenACC clause: vector_length (integer-expression). */
+ OMP_CLAUSE_VECTOR_LENGTH,
+
+ /* OpenACC clause: tile ( size-expr-list ). */
+ OMP_CLAUSE_TILE,
+
+ /* OpenACC clause: if_present. */
+ OMP_CLAUSE_IF_PRESENT,
+
+ /* OpenACC clause: finalize. */
+ OMP_CLAUSE_FINALIZE,
+
+ /* OpenACC clause: nohost. */
+ OMP_CLAUSE_NOHOST,
+};
+
+#undef DEFTREESTRUCT
+#define DEFTREESTRUCT(ENUM, NAME) ENUM,
+enum tree_node_structure_enum {
+#include "treestruct.def"
+ LAST_TS_ENUM
+};
+#undef DEFTREESTRUCT
+
+enum omp_clause_schedule_kind {
+ OMP_CLAUSE_SCHEDULE_STATIC,
+ OMP_CLAUSE_SCHEDULE_DYNAMIC,
+ OMP_CLAUSE_SCHEDULE_GUIDED,
+ OMP_CLAUSE_SCHEDULE_AUTO,
+ OMP_CLAUSE_SCHEDULE_RUNTIME,
+ OMP_CLAUSE_SCHEDULE_MASK = (1 << 3) - 1,
+ OMP_CLAUSE_SCHEDULE_MONOTONIC = (1 << 3),
+ OMP_CLAUSE_SCHEDULE_NONMONOTONIC = (1 << 4),
+ OMP_CLAUSE_SCHEDULE_LAST = 2 * OMP_CLAUSE_SCHEDULE_NONMONOTONIC - 1
+};
+
+enum omp_clause_default_kind {
+ OMP_CLAUSE_DEFAULT_UNSPECIFIED,
+ OMP_CLAUSE_DEFAULT_SHARED,
+ OMP_CLAUSE_DEFAULT_NONE,
+ OMP_CLAUSE_DEFAULT_PRIVATE,
+ OMP_CLAUSE_DEFAULT_FIRSTPRIVATE,
+ OMP_CLAUSE_DEFAULT_PRESENT,
+ OMP_CLAUSE_DEFAULT_LAST
+};
+
+enum omp_clause_defaultmap_kind {
+ OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED,
+ OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR,
+ OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE,
+ OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE,
+ OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER,
+ OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK = 7,
+ OMP_CLAUSE_DEFAULTMAP_ALLOC = 1 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_TO = 2 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_FROM = 3 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_TOFROM = 4 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE
+ = 5 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_NONE = 6 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_DEFAULT
+ = 7 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1),
+ OMP_CLAUSE_DEFAULTMAP_MASK = 7 * (OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK + 1)
+};
+
+enum omp_clause_bind_kind {
+ OMP_CLAUSE_BIND_TEAMS,
+ OMP_CLAUSE_BIND_PARALLEL,
+ OMP_CLAUSE_BIND_THREAD
+};
+
+/* memory-order-clause on OpenMP atomic/flush constructs or
+ argument of atomic_default_mem_order clause. */
+enum omp_memory_order {
+ OMP_MEMORY_ORDER_UNSPECIFIED,
+ OMP_MEMORY_ORDER_RELAXED,
+ OMP_MEMORY_ORDER_ACQUIRE,
+ OMP_MEMORY_ORDER_RELEASE,
+ OMP_MEMORY_ORDER_ACQ_REL,
+ OMP_MEMORY_ORDER_SEQ_CST,
+ OMP_MEMORY_ORDER_MASK = 7,
+ OMP_FAIL_MEMORY_ORDER_UNSPECIFIED = OMP_MEMORY_ORDER_UNSPECIFIED * 8,
+ OMP_FAIL_MEMORY_ORDER_RELAXED = OMP_MEMORY_ORDER_RELAXED * 8,
+ OMP_FAIL_MEMORY_ORDER_ACQUIRE = OMP_MEMORY_ORDER_ACQUIRE * 8,
+ OMP_FAIL_MEMORY_ORDER_RELEASE = OMP_MEMORY_ORDER_RELEASE * 8,
+ OMP_FAIL_MEMORY_ORDER_ACQ_REL = OMP_MEMORY_ORDER_ACQ_REL * 8,
+ OMP_FAIL_MEMORY_ORDER_SEQ_CST = OMP_MEMORY_ORDER_SEQ_CST * 8,
+ OMP_FAIL_MEMORY_ORDER_MASK = OMP_MEMORY_ORDER_MASK * 8
+};
+#define OMP_FAIL_MEMORY_ORDER_SHIFT 3
+
+/* There is a TYPE_QUAL value for each type qualifier. They can be
+ combined by bitwise-or to form the complete set of qualifiers for a
+ type. */
+enum cv_qualifier {
+ TYPE_UNQUALIFIED = 0x0,
+ TYPE_QUAL_CONST = 0x1,
+ TYPE_QUAL_VOLATILE = 0x2,
+ TYPE_QUAL_RESTRICT = 0x4,
+ TYPE_QUAL_ATOMIC = 0x8
+};
+
+/* Standard named or nameless data types of the C compiler. */
+enum tree_index {
+ TI_ERROR_MARK,
+ TI_INTQI_TYPE,
+ TI_INTHI_TYPE,
+ TI_INTSI_TYPE,
+ TI_INTDI_TYPE,
+ TI_INTTI_TYPE,
+
+ TI_UINTQI_TYPE,
+ TI_UINTHI_TYPE,
+ TI_UINTSI_TYPE,
+ TI_UINTDI_TYPE,
+ TI_UINTTI_TYPE,
+
+ TI_ATOMICQI_TYPE,
+ TI_ATOMICHI_TYPE,
+ TI_ATOMICSI_TYPE,
+ TI_ATOMICDI_TYPE,
+ TI_ATOMICTI_TYPE,
+
+ TI_UINT16_TYPE,
+ TI_UINT32_TYPE,
+ TI_UINT64_TYPE,
+ TI_UINT128_TYPE,
+
+ TI_VOID,
+
+ TI_INTEGER_ZERO,
+ TI_INTEGER_ONE,
+ TI_INTEGER_THREE,
+ TI_INTEGER_MINUS_ONE,
+ TI_NULL_POINTER,
+
+ TI_SIZE_ZERO,
+ TI_SIZE_ONE,
+
+ TI_BITSIZE_ZERO,
+ TI_BITSIZE_ONE,
+ TI_BITSIZE_UNIT,
+
+ TI_PUBLIC,
+ TI_PROTECTED,
+ TI_PRIVATE,
+
+ TI_BOOLEAN_FALSE,
+ TI_BOOLEAN_TRUE,
+
+ TI_FLOAT_TYPE,
+ TI_DOUBLE_TYPE,
+ TI_LONG_DOUBLE_TYPE,
+
+ /* The _FloatN and _FloatNx types must be consecutive, and in the
+ same sequence as the corresponding complex types, which must also
+ be consecutive; _FloatN must come before _FloatNx; the order must
+ also be the same as in the floatn_nx_types array and the RID_*
+ values in c-common.h. This is so that iterations over these
+ types work as intended. */
+ TI_FLOAT16_TYPE,
+ TI_FLOATN_TYPE_FIRST = TI_FLOAT16_TYPE,
+ TI_FLOATN_NX_TYPE_FIRST = TI_FLOAT16_TYPE,
+ TI_FLOAT32_TYPE,
+ TI_FLOAT64_TYPE,
+ TI_FLOAT128_TYPE,
+ TI_FLOATN_TYPE_LAST = TI_FLOAT128_TYPE,
+#define NUM_FLOATN_TYPES (TI_FLOATN_TYPE_LAST - TI_FLOATN_TYPE_FIRST + 1)
+ TI_FLOAT32X_TYPE,
+ TI_FLOATNX_TYPE_FIRST = TI_FLOAT32X_TYPE,
+ TI_FLOAT64X_TYPE,
+ TI_FLOAT128X_TYPE,
+ TI_FLOATNX_TYPE_LAST = TI_FLOAT128X_TYPE,
+ TI_FLOATN_NX_TYPE_LAST = TI_FLOAT128X_TYPE,
+#define NUM_FLOATNX_TYPES (TI_FLOATNX_TYPE_LAST - TI_FLOATNX_TYPE_FIRST + 1)
+#define NUM_FLOATN_NX_TYPES (TI_FLOATN_NX_TYPE_LAST \
+ - TI_FLOATN_NX_TYPE_FIRST \
+ + 1)
+
+ /* Put the complex types after their component types, so that in (sequential)
+ tree streaming we can assert that their component types have already been
+ handled (see tree-streamer.cc:record_common_node). */
+ TI_COMPLEX_INTEGER_TYPE,
+ TI_COMPLEX_FLOAT_TYPE,
+ TI_COMPLEX_DOUBLE_TYPE,
+ TI_COMPLEX_LONG_DOUBLE_TYPE,
+
+ TI_COMPLEX_FLOAT16_TYPE,
+ TI_COMPLEX_FLOATN_NX_TYPE_FIRST = TI_COMPLEX_FLOAT16_TYPE,
+ TI_COMPLEX_FLOAT32_TYPE,
+ TI_COMPLEX_FLOAT64_TYPE,
+ TI_COMPLEX_FLOAT128_TYPE,
+ TI_COMPLEX_FLOAT32X_TYPE,
+ TI_COMPLEX_FLOAT64X_TYPE,
+ TI_COMPLEX_FLOAT128X_TYPE,
+
+ TI_FLOAT_PTR_TYPE,
+ TI_DOUBLE_PTR_TYPE,
+ TI_LONG_DOUBLE_PTR_TYPE,
+ TI_INTEGER_PTR_TYPE,
+
+ TI_VOID_TYPE,
+ TI_PTR_TYPE,
+ TI_CONST_PTR_TYPE,
+ TI_SIZE_TYPE,
+ TI_PID_TYPE,
+ TI_PTRDIFF_TYPE,
+ TI_VA_LIST_TYPE,
+ TI_VA_LIST_GPR_COUNTER_FIELD,
+ TI_VA_LIST_FPR_COUNTER_FIELD,
+ TI_BOOLEAN_TYPE,
+ TI_FILEPTR_TYPE,
+ TI_CONST_TM_PTR_TYPE,
+ TI_FENV_T_PTR_TYPE,
+ TI_CONST_FENV_T_PTR_TYPE,
+ TI_FEXCEPT_T_PTR_TYPE,
+ TI_CONST_FEXCEPT_T_PTR_TYPE,
+ TI_POINTER_SIZED_TYPE,
+
+ TI_DFLOAT32_TYPE,
+ TI_DFLOAT64_TYPE,
+ TI_DFLOAT128_TYPE,
+
+ TI_VOID_LIST_NODE,
+
+ TI_MAIN_IDENTIFIER,
+
+ TI_SAT_SFRACT_TYPE,
+ TI_SAT_FRACT_TYPE,
+ TI_SAT_LFRACT_TYPE,
+ TI_SAT_LLFRACT_TYPE,
+ TI_SAT_USFRACT_TYPE,
+ TI_SAT_UFRACT_TYPE,
+ TI_SAT_ULFRACT_TYPE,
+ TI_SAT_ULLFRACT_TYPE,
+ TI_SFRACT_TYPE,
+ TI_FRACT_TYPE,
+ TI_LFRACT_TYPE,
+ TI_LLFRACT_TYPE,
+ TI_USFRACT_TYPE,
+ TI_UFRACT_TYPE,
+ TI_ULFRACT_TYPE,
+ TI_ULLFRACT_TYPE,
+ TI_SAT_SACCUM_TYPE,
+ TI_SAT_ACCUM_TYPE,
+ TI_SAT_LACCUM_TYPE,
+ TI_SAT_LLACCUM_TYPE,
+ TI_SAT_USACCUM_TYPE,
+ TI_SAT_UACCUM_TYPE,
+ TI_SAT_ULACCUM_TYPE,
+ TI_SAT_ULLACCUM_TYPE,
+ TI_SACCUM_TYPE,
+ TI_ACCUM_TYPE,
+ TI_LACCUM_TYPE,
+ TI_LLACCUM_TYPE,
+ TI_USACCUM_TYPE,
+ TI_UACCUM_TYPE,
+ TI_ULACCUM_TYPE,
+ TI_ULLACCUM_TYPE,
+ TI_QQ_TYPE,
+ TI_HQ_TYPE,
+ TI_SQ_TYPE,
+ TI_DQ_TYPE,
+ TI_TQ_TYPE,
+ TI_UQQ_TYPE,
+ TI_UHQ_TYPE,
+ TI_USQ_TYPE,
+ TI_UDQ_TYPE,
+ TI_UTQ_TYPE,
+ TI_SAT_QQ_TYPE,
+ TI_SAT_HQ_TYPE,
+ TI_SAT_SQ_TYPE,
+ TI_SAT_DQ_TYPE,
+ TI_SAT_TQ_TYPE,
+ TI_SAT_UQQ_TYPE,
+ TI_SAT_UHQ_TYPE,
+ TI_SAT_USQ_TYPE,
+ TI_SAT_UDQ_TYPE,
+ TI_SAT_UTQ_TYPE,
+ TI_HA_TYPE,
+ TI_SA_TYPE,
+ TI_DA_TYPE,
+ TI_TA_TYPE,
+ TI_UHA_TYPE,
+ TI_USA_TYPE,
+ TI_UDA_TYPE,
+ TI_UTA_TYPE,
+ TI_SAT_HA_TYPE,
+ TI_SAT_SA_TYPE,
+ TI_SAT_DA_TYPE,
+ TI_SAT_TA_TYPE,
+ TI_SAT_UHA_TYPE,
+ TI_SAT_USA_TYPE,
+ TI_SAT_UDA_TYPE,
+ TI_SAT_UTA_TYPE,
+
+ TI_MODULE_HWM,
+ /* Nodes below here change during compilation, and should therefore
+ not be in the C++ module's global tree table. */
+
+ TI_OPTIMIZATION_DEFAULT,
+ TI_OPTIMIZATION_CURRENT,
+ TI_TARGET_OPTION_DEFAULT,
+ TI_TARGET_OPTION_CURRENT,
+ TI_CURRENT_TARGET_PRAGMA,
+ TI_CURRENT_OPTIMIZE_PRAGMA,
+
+ TI_CHREC_DONT_KNOW,
+ TI_CHREC_KNOWN,
+
+ TI_MAX
+};
+
+/* An enumeration of the standard C integer types. These must be
+ ordered so that shorter types appear before longer ones, and so
+ that signed types appear before unsigned ones, for the correct
+ functioning of interpret_integer() in c-lex.cc. */
+enum integer_type_kind {
+ itk_char,
+ itk_signed_char,
+ itk_unsigned_char,
+ itk_short,
+ itk_unsigned_short,
+ itk_int,
+ itk_unsigned_int,
+ itk_long,
+ itk_unsigned_long,
+ itk_long_long,
+ itk_unsigned_long_long,
+
+ itk_intN_0,
+ itk_unsigned_intN_0,
+ itk_intN_1,
+ itk_unsigned_intN_1,
+ itk_intN_2,
+ itk_unsigned_intN_2,
+ itk_intN_3,
+ itk_unsigned_intN_3,
+
+ itk_none
+};
+
+/* A pointer-to-function member type looks like:
+
+ struct {
+ __P __pfn;
+ ptrdiff_t __delta;
+ };
+
+ If __pfn is NULL, it is a NULL pointer-to-member-function.
+
+ (Because the vtable is always the first thing in the object, we
+ don't need its offset.) If the function is virtual, then PFN is
+ one plus twice the index into the vtable; otherwise, it is just a
+ pointer to the function.
+
+ Unfortunately, using the lowest bit of PFN doesn't work in
+ architectures that don't impose alignment requirements on function
+ addresses, or that use the lowest bit to tell one ISA from another,
+ for example. For such architectures, we use the lowest bit of
+ DELTA instead of the lowest bit of the PFN, and DELTA will be
+ multiplied by 2. */
+enum ptrmemfunc_vbit_where_t {
+ ptrmemfunc_vbit_in_pfn,
+ ptrmemfunc_vbit_in_delta
+};
+
+/* Flags that may be passed in the third argument of decl_attributes, and
+ to handler functions for attributes. */
+enum attribute_flags {
+ /* The type passed in is the type of a DECL, and any attributes that
+ should be passed in again to be applied to the DECL rather than the
+ type should be returned. */
+ ATTR_FLAG_DECL_NEXT = 1,
+ /* The type passed in is a function return type, and any attributes that
+ should be passed in again to be applied to the function type rather
+ than the return type should be returned. */
+ ATTR_FLAG_FUNCTION_NEXT = 2,
+ /* The type passed in is an array element type, and any attributes that
+ should be passed in again to be applied to the array type rather
+ than the element type should be returned. */
+ ATTR_FLAG_ARRAY_NEXT = 4,
+ /* The type passed in is a structure, union or enumeration type being
+ created, and should be modified in place. */
+ ATTR_FLAG_TYPE_IN_PLACE = 8,
+ /* The attributes are being applied by default to a library function whose
+ name indicates known behavior, and should be silently ignored if they
+ are not in fact compatible with the function type. */
+ ATTR_FLAG_BUILT_IN = 16,
+ /* A given attribute has been parsed as a C++-11 attribute. */
+ ATTR_FLAG_CXX11 = 32,
+ /* The attribute handler is being invoked with an internal argument
+ that may not otherwise be valid when specified in source code. */
+ ATTR_FLAG_INTERNAL = 64
+};
+
+/* Types used to represent sizes. */
+enum size_type_kind {
+ stk_sizetype, /* Normal representation of sizes in bytes. */
+ stk_ssizetype, /* Signed representation of sizes in bytes. */
+ stk_bitsizetype, /* Normal representation of sizes in bits. */
+ stk_sbitsizetype, /* Signed representation of sizes in bits. */
+ stk_type_kind_last
+};
+
+/* Flags controlling operand_equal_p() behavior. */
+enum operand_equal_flag {
+ OEP_ONLY_CONST = 1,
+ OEP_PURE_SAME = 2,
+ OEP_MATCH_SIDE_EFFECTS = 4,
+ OEP_ADDRESS_OF = 8,
+ /* Internal within operand_equal_p: */
+ OEP_NO_HASH_CHECK = 16,
+ /* Internal within inchash::add_expr: */
+ OEP_HASH_CHECK = 32,
+ /* Makes operand_equal_p handle more expressions: */
+ OEP_LEXICOGRAPHIC = 64,
+ OEP_BITWISE = 128,
+ /* For OEP_ADDRESS_OF of COMPONENT_REFs, only consider same fields as
+ equivalent rather than also different fields with the same offset. */
+ OEP_ADDRESS_OF_SAME_FIELD = 256,
+ /* In conjunction with OEP_LEXICOGRAPHIC considers names of declarations
+ of the same kind. Used to compare VLA bounds involving parameters
+ across redeclarations of the same function. */
+ OEP_DECL_NAME = 512
+};
+
+/* Enum and arrays used for tree allocation stats.
+ Keep in sync with tree.cc:tree_node_kind_names. */
+enum tree_node_kind {
+ d_kind,
+ t_kind,
+ b_kind,
+ s_kind,
+ r_kind,
+ e_kind,
+ c_kind,
+ id_kind,
+ vec_kind,
+ binfo_kind,
+ ssa_name_kind,
+ constr_kind,
+ x_kind,
+ lang_decl,
+ lang_type,
+ omp_clause_kind,
+ all_kinds
+};
+
+enum annot_expr_kind {
+ annot_expr_ivdep_kind,
+ annot_expr_unroll_kind,
+ annot_expr_no_vector_kind,
+ annot_expr_vector_kind,
+ annot_expr_parallel_kind,
+ annot_expr_kind_last
+};
+
+/* The kind of a TREE_CLOBBER_P CONSTRUCTOR node. */
+enum clobber_kind {
+ /* Unspecified, this clobber acts as a store of an undefined value. */
+ CLOBBER_UNDEF,
+ /* This clobber ends the lifetime of the storage. */
+ CLOBBER_EOL,
+ CLOBBER_LAST
+};
+
+/*---------------------------------------------------------------------------
+ Type definitions
+---------------------------------------------------------------------------*/
+/* When processing aliases at the symbol table level, we need the
+ declaration of target. For this reason we need to queue aliases and
+ process them after all declarations has been produced. */
+struct GTY(()) alias_pair {
+ tree decl;
+ tree target;
+};
+
+/* An initialization priority. */
+typedef unsigned short priority_type;
+
+/* The type of a callback function for walking over tree structure. */
+typedef tree (*walk_tree_fn) (tree *, int *, void *);
+
+/* The type of a callback function that represents a custom walk_tree. */
+typedef tree (*walk_tree_lh) (tree *, int *, tree (*) (tree *, int *, void *),
+ void *, hash_set<tree> *);
+
+
+/*---------------------------------------------------------------------------
+ Main data structures
+---------------------------------------------------------------------------*/
+/* A tree node can represent a data type, a variable, an expression
+ or a statement. Each node has a TREE_CODE which says what kind of
+ thing it represents. Some common codes are:
+ INTEGER_TYPE -- represents a type of integers.
+ ARRAY_TYPE -- represents a type of pointer.
+ VAR_DECL -- represents a declared variable.
+ INTEGER_CST -- represents a constant integer value.
+ PLUS_EXPR -- represents a sum (an expression).
+
+ As for the contents of a tree node: there are some fields
+ that all nodes share. Each TREE_CODE has various special-purpose
+ fields as well. The fields of a node are never accessed directly,
+ always through accessor macros. */
+
+/* Every kind of tree node starts with this structure,
+ so all nodes have these fields.
+
+ See the accessor macros, defined below, for documentation of the
+ fields, and the table below which connects the fields and the
+ accessor macros. */
+
+struct GTY(()) tree_base {
+ ENUM_BITFIELD(tree_code) code : 16;
+
+ unsigned side_effects_flag : 1;
+ unsigned constant_flag : 1;
+ unsigned addressable_flag : 1;
+ unsigned volatile_flag : 1;
+ unsigned readonly_flag : 1;
+ unsigned asm_written_flag: 1;
+ unsigned nowarning_flag : 1;
+ unsigned visited : 1;
+
+ unsigned used_flag : 1;
+ unsigned nothrow_flag : 1;
+ unsigned static_flag : 1;
+ unsigned public_flag : 1;
+ unsigned private_flag : 1;
+ unsigned protected_flag : 1;
+ unsigned deprecated_flag : 1;
+ unsigned default_def_flag : 1;
+
+ union {
+ /* The bits in the following structure should only be used with
+ accessor macros that constrain inputs with tree checking. */
+ struct {
+ unsigned lang_flag_0 : 1;
+ unsigned lang_flag_1 : 1;
+ unsigned lang_flag_2 : 1;
+ unsigned lang_flag_3 : 1;
+ unsigned lang_flag_4 : 1;
+ unsigned lang_flag_5 : 1;
+ unsigned lang_flag_6 : 1;
+ unsigned saturating_flag : 1;
+
+ unsigned unsigned_flag : 1;
+ unsigned packed_flag : 1;
+ unsigned user_align : 1;
+ unsigned nameless_flag : 1;
+ unsigned atomic_flag : 1;
+ unsigned unavailable_flag : 1;
+ unsigned spare0 : 2;
+
+ unsigned spare1 : 8;
+
+ /* This field is only used with TREE_TYPE nodes; the only reason it is
+ present in tree_base instead of tree_type is to save space. The size
+ of the field must be large enough to hold addr_space_t values.
+ For CONSTRUCTOR nodes this holds the clobber_kind enum. */
+ unsigned address_space : 8;
+ } bits;
+
+ /* The following fields are present in tree_base to save space. The
+ nodes using them do not require any of the flags above and so can
+ make better use of the 4-byte sized word. */
+
+ /* The number of HOST_WIDE_INTs in an INTEGER_CST. */
+ struct {
+ /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
+ its native precision. */
+ unsigned char unextended;
+
+ /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
+ wider precisions based on its TYPE_SIGN. */
+ unsigned char extended;
+
+ /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
+ offset_int precision, with smaller integers being extended
+ according to their TYPE_SIGN. This is equal to one of the two
+ fields above but is cached for speed. */
+ unsigned char offset;
+ } int_length;
+
+ /* VEC length. This field is only used with TREE_VEC. */
+ int length;
+
+ /* This field is only used with VECTOR_CST. */
+ struct {
+ /* The value of VECTOR_CST_LOG2_NPATTERNS. */
+ unsigned int log2_npatterns : 8;
+
+ /* The value of VECTOR_CST_NELTS_PER_PATTERN. */
+ unsigned int nelts_per_pattern : 8;
+
+ /* For future expansion. */
+ unsigned int unused : 16;
+ } vector_cst;
+
+ /* SSA version number. This field is only used with SSA_NAME. */
+ unsigned int version;
+
+ /* CHREC_VARIABLE. This field is only used with POLYNOMIAL_CHREC. */
+ unsigned int chrec_var;
+
+ /* Internal function code. */
+ enum internal_fn ifn;
+
+ /* OMP_ATOMIC* memory order. */
+ enum omp_memory_order omp_atomic_memory_order;
+
+ /* The following two fields are used for MEM_REF and TARGET_MEM_REF
+ expression trees and specify known data non-dependences. For
+ two memory references in a function they are known to not
+ alias if dependence_info.clique are equal and dependence_info.base
+ are distinct. Clique number zero means there is no information,
+ clique number one is populated from function global information
+ and thus needs no remapping on transforms like loop unrolling. */
+ struct {
+ unsigned short clique;
+ unsigned short base;
+ } dependence_info;
+ } GTY((skip(""))) u;
+};
+
+/* The following table lists the uses of each of the above flags and
+ for which types of nodes they are defined.
+
+ addressable_flag:
+
+ TREE_ADDRESSABLE in
+ VAR_DECL, PARM_DECL, RESULT_DECL, FUNCTION_DECL, LABEL_DECL
+ SSA_NAME
+ all types
+ CONSTRUCTOR, IDENTIFIER_NODE
+ STMT_EXPR
+
+ CALL_EXPR_TAILCALL in
+ CALL_EXPR
+
+ CASE_LOW_SEEN in
+ CASE_LABEL_EXPR
+
+ PREDICT_EXPR_OUTCOME in
+ PREDICT_EXPR
+
+ OMP_CLAUSE_MAP_DECL_MAKE_ADDRESSABLE in
+ OMP_CLAUSE
+
+ static_flag:
+
+ TREE_STATIC in
+ VAR_DECL, FUNCTION_DECL
+ CONSTRUCTOR
+
+ TREE_NO_TRAMPOLINE in
+ ADDR_EXPR
+
+ BINFO_VIRTUAL_P in
+ TREE_BINFO
+
+ TREE_SYMBOL_REFERENCED in
+ IDENTIFIER_NODE
+
+ CLEANUP_EH_ONLY in
+ TARGET_EXPR, WITH_CLEANUP_EXPR
+
+ TRY_CATCH_IS_CLEANUP in
+ TRY_CATCH_EXPR
+
+ ASM_INPUT_P in
+ ASM_EXPR
+
+ TYPE_REF_CAN_ALIAS_ALL in
+ POINTER_TYPE, REFERENCE_TYPE
+
+ CASE_HIGH_SEEN in
+ CASE_LABEL_EXPR
+
+ ENUM_IS_SCOPED in
+ ENUMERAL_TYPE
+
+ TRANSACTION_EXPR_OUTER in
+ TRANSACTION_EXPR
+
+ SSA_NAME_ANTI_RANGE_P in
+ SSA_NAME
+
+ MUST_TAIL_CALL in
+ CALL_EXPR
+
+ public_flag:
+
+ TREE_OVERFLOW in
+ INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST
+
+ TREE_PUBLIC in
+ VAR_DECL, FUNCTION_DECL
+ IDENTIFIER_NODE
+
+ CONSTRUCTOR_NO_CLEARING in
+ CONSTRUCTOR
+
+ ASM_VOLATILE_P in
+ ASM_EXPR
+
+ CALL_EXPR_VA_ARG_PACK in
+ CALL_EXPR
+
+ TYPE_CACHED_VALUES_P in
+ all types
+
+ SAVE_EXPR_RESOLVED_P in
+ SAVE_EXPR
+
+ OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE in
+ OMP_CLAUSE_LASTPRIVATE
+
+ OMP_CLAUSE_PRIVATE_DEBUG in
+ OMP_CLAUSE_PRIVATE
+
+ OMP_CLAUSE_LINEAR_NO_COPYIN in
+ OMP_CLAUSE_LINEAR
+
+ OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION in
+ OMP_CLAUSE_MAP
+
+ OMP_CLAUSE_REDUCTION_OMP_ORIG_REF in
+ OMP_CLAUSE_{,TASK_,IN_}REDUCTION
+
+ OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT in
+ OMP_CLAUSE_USE_DEVICE_PTR
+
+ TRANSACTION_EXPR_RELAXED in
+ TRANSACTION_EXPR
+
+ FALLTHROUGH_LABEL_P in
+ LABEL_DECL
+
+ SSA_NAME_IS_VIRTUAL_OPERAND in
+ SSA_NAME
+
+ EXPR_LOCATION_WRAPPER_P in
+ NON_LVALUE_EXPR, VIEW_CONVERT_EXPR
+
+ private_flag:
+
+ TREE_PRIVATE in
+ all decls
+
+ CALL_EXPR_RETURN_SLOT_OPT in
+ CALL_EXPR
+
+ OMP_SECTION_LAST in
+ OMP_SECTION
+
+ OMP_PARALLEL_COMBINED in
+ OMP_PARALLEL
+
+ OMP_CLAUSE_PRIVATE_OUTER_REF in
+ OMP_CLAUSE_PRIVATE
+
+ OMP_CLAUSE_LINEAR_NO_COPYOUT in
+ OMP_CLAUSE_LINEAR
+
+ TYPE_REF_IS_RVALUE in
+ REFERENCE_TYPE
+
+ ENUM_IS_OPAQUE in
+ ENUMERAL_TYPE
+
+ protected_flag:
+
+ TREE_PROTECTED in
+ BLOCK
+ all decls
+
+ CALL_FROM_THUNK_P and
+ CALL_ALLOCA_FOR_VAR_P and
+ CALL_FROM_NEW_OR_DELETE_P in
+ CALL_EXPR
+
+ OMP_CLAUSE_LINEAR_VARIABLE_STRIDE in
+ OMP_CLAUSE_LINEAR
+
+ ASM_INLINE_P in
+ ASM_EXPR
+
+ side_effects_flag:
+
+ TREE_SIDE_EFFECTS in
+ all expressions
+ all decls
+ all constants
+
+ FORCED_LABEL in
+ LABEL_DECL
+
+ volatile_flag:
+
+ TREE_THIS_VOLATILE in
+ all expressions
+ all decls
+
+ TYPE_VOLATILE in
+ all types
+
+ readonly_flag:
+
+ TREE_READONLY in
+ all expressions
+ all decls
+
+ TYPE_READONLY in
+ all types
+
+ constant_flag:
+
+ TREE_CONSTANT in
+ all expressions
+ all decls
+ all constants
+
+ TYPE_SIZES_GIMPLIFIED in
+ all types
+
+ unsigned_flag:
+
+ TYPE_UNSIGNED in
+ all types
+
+ DECL_UNSIGNED in
+ all decls
+
+ asm_written_flag:
+
+ TREE_ASM_WRITTEN in
+ VAR_DECL, FUNCTION_DECL, TYPE_DECL
+ RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE
+ BLOCK, STRING_CST
+
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI in
+ SSA_NAME
+
+ used_flag:
+
+ TREE_USED in
+ all expressions
+ all decls
+ IDENTIFIER_NODE
+
+ nothrow_flag:
+
+ TREE_NOTHROW in
+ CALL_EXPR
+ FUNCTION_DECL
+
+ TREE_THIS_NOTRAP in
+ INDIRECT_REF, MEM_REF, TARGET_MEM_REF, ARRAY_REF, ARRAY_RANGE_REF
+
+ SSA_NAME_IN_FREE_LIST in
+ SSA_NAME
+
+ DECL_NONALIASED in
+ VAR_DECL
+
+ deprecated_flag:
+
+ TREE_DEPRECATED in
+ all decls
+ all types
+
+ IDENTIFIER_TRANSPARENT_ALIAS in
+ IDENTIFIER_NODE
+
+ SSA_NAME_POINTS_TO_READONLY_MEMORY in
+ SSA_NAME
+
+ unavailable_flag:
+
+ TREE_UNAVAILABLE in
+ all decls
+ all types
+
+ visited:
+
+ TREE_VISITED in
+ all trees (used liberally by many passes)
+
+ saturating_flag:
+
+ TYPE_REVERSE_STORAGE_ORDER in
+ RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE
+
+ TYPE_SATURATING in
+ other types
+
+ VAR_DECL_IS_VIRTUAL_OPERAND in
+ VAR_DECL
+
+ nowarning_flag:
+
+ TREE_NO_WARNING in
+ all expressions
+ all decls
+
+ TYPE_ARTIFICIAL in
+ all types
+
+ default_def_flag:
+
+ TYPE_FINAL_P in
+ RECORD_TYPE, UNION_TYPE and QUAL_UNION_TYPE
+
+ TYPE_VECTOR_OPAQUE in
+ VECTOR_TYPE
+
+ SSA_NAME_IS_DEFAULT_DEF in
+ SSA_NAME
+
+ DECL_NONLOCAL_FRAME in
+ VAR_DECL
+
+ REF_REVERSE_STORAGE_ORDER in
+ BIT_FIELD_REF, MEM_REF
+
+ FUNC_ADDR_BY_DESCRIPTOR in
+ ADDR_EXPR
+
+ CALL_EXPR_BY_DESCRIPTOR in
+ CALL_EXPR
+
+*/
+
+struct GTY(()) tree_typed {
+ struct tree_base base;
+ tree type;
+};
+
+struct GTY(()) tree_common {
+ struct tree_typed typed;
+ tree chain;
+};
+
+struct GTY(()) tree_int_cst {
+ struct tree_typed typed;
+ HOST_WIDE_INT val[1];
+};
+
+
+struct GTY(()) tree_real_cst {
+ struct tree_typed typed;
+ struct real_value * real_cst_ptr;
+};
+
+struct GTY(()) tree_fixed_cst {
+ struct tree_typed typed;
+ struct fixed_value * fixed_cst_ptr;
+};
+
+struct GTY(()) tree_string {
+ struct tree_typed typed;
+ int length;
+ char str[1];
+};
+
+struct GTY(()) tree_complex {
+ struct tree_typed typed;
+ tree real;
+ tree imag;
+};
+
+struct GTY(()) tree_vector {
+ struct tree_typed typed;
+ tree GTY ((length ("vector_cst_encoded_nelts ((tree) &%h)"))) elts[1];
+};
+
+#if 0 // sdcpp
+struct GTY(()) tree_poly_int_cst {
+ struct tree_typed typed;
+ tree coeffs[NUM_POLY_INT_COEFFS];
+};
+#endif // sdcpp
+
+struct GTY(()) tree_identifier {
+ struct tree_common common;
+ struct ht_identifier id;
+};
+
+struct GTY(()) tree_list {
+ struct tree_common common;
+ tree purpose;
+ tree value;
+};
+
+struct GTY(()) tree_vec {
+ struct tree_common common;
+ tree GTY ((length ("TREE_VEC_LENGTH ((tree)&%h)"))) a[1];
+};
+
+/* A single element of a CONSTRUCTOR. VALUE holds the actual value of the
+ element. INDEX can optionally design the position of VALUE: in arrays,
+ it is the index where VALUE has to be placed; in structures, it is the
+ FIELD_DECL of the member. */
+struct GTY(()) constructor_elt {
+ tree index;
+ tree value;
+};
+
+struct GTY(()) tree_constructor {
+ struct tree_typed typed;
+ vec<constructor_elt, va_gc> *elts;
+};
+
+enum omp_clause_depend_kind
+{
+ OMP_CLAUSE_DEPEND_IN,
+ OMP_CLAUSE_DEPEND_OUT,
+ OMP_CLAUSE_DEPEND_INOUT,
+ OMP_CLAUSE_DEPEND_MUTEXINOUTSET,
+ OMP_CLAUSE_DEPEND_SOURCE,
+ OMP_CLAUSE_DEPEND_SINK,
+ OMP_CLAUSE_DEPEND_DEPOBJ,
+ OMP_CLAUSE_DEPEND_LAST
+};
+
+enum omp_clause_proc_bind_kind
+{
+ /* Numbers should match omp_proc_bind_t enum in omp.h. */
+ OMP_CLAUSE_PROC_BIND_FALSE = 0,
+ OMP_CLAUSE_PROC_BIND_TRUE = 1,
+ OMP_CLAUSE_PROC_BIND_PRIMARY = 2,
+ OMP_CLAUSE_PROC_BIND_MASTER = 2,
+ OMP_CLAUSE_PROC_BIND_CLOSE = 3,
+ OMP_CLAUSE_PROC_BIND_SPREAD = 4,
+ OMP_CLAUSE_PROC_BIND_LAST
+};
+
+enum omp_clause_device_type_kind
+{
+ OMP_CLAUSE_DEVICE_TYPE_HOST = 1,
+ OMP_CLAUSE_DEVICE_TYPE_NOHOST = 2,
+ OMP_CLAUSE_DEVICE_TYPE_ANY = 3
+};
+
+enum omp_clause_linear_kind
+{
+ OMP_CLAUSE_LINEAR_DEFAULT,
+ OMP_CLAUSE_LINEAR_REF,
+ OMP_CLAUSE_LINEAR_VAL,
+ OMP_CLAUSE_LINEAR_UVAL
+};
+
+struct GTY(()) tree_exp {
+ struct tree_typed typed;
+ location_t locus;
+ tree GTY ((special ("tree_exp"),
+ desc ("TREE_CODE ((tree) &%0)")))
+ operands[1];
+};
+
+/* Immediate use linking structure. This structure is used for maintaining
+ a doubly linked list of uses of an SSA_NAME. */
+struct GTY(()) ssa_use_operand_t {
+ struct ssa_use_operand_t* GTY((skip(""))) prev;
+ struct ssa_use_operand_t* GTY((skip(""))) next;
+ /* Immediate uses for a given SSA name are maintained as a cyclic
+ list. To recognize the root of this list, the location field
+ needs to point to the original SSA name. Since statements and
+ SSA names are of different data types, we need this union. See
+ the explanation in struct imm_use_iterator. */
+ union { gimple *stmt; tree ssa_name; } GTY((skip(""))) loc;
+ tree *GTY((skip(""))) use;
+};
+
+struct GTY(()) tree_ssa_name {
+ struct tree_typed typed;
+
+ /* _DECL wrapped by this SSA name. */
+ tree var;
+
+ /* Statement that defines this SSA name. */
+ gimple *def_stmt;
+
+ /* Value range information. */
+ union ssa_name_info_type {
+ /* Pointer attributes used for alias analysis. */
+ struct GTY ((tag ("0"))) ptr_info_def *ptr_info;
+ /* Value range attributes used for zero/sign extension elimination. */
+ struct GTY ((tag ("1"))) range_info_def *range_info;
+ } GTY ((desc ("%1.typed.type ?" \
+ "!POINTER_TYPE_P (TREE_TYPE ((tree)&%1)) : 2"))) info;
+
+ /* Immediate uses list for this SSA_NAME. */
+ struct ssa_use_operand_t imm_uses;
+};
+
+struct GTY(()) phi_arg_d {
+ /* imm_use MUST be the first element in struct because we do some
+ pointer arithmetic with it. See phi_arg_index_from_use. */
+ struct ssa_use_operand_t imm_use;
+ tree def;
+ location_t locus;
+};
+
+struct GTY(()) tree_omp_clause {
+ struct tree_common common;
+ location_t locus;
+ enum omp_clause_code code;
+ union omp_clause_subcode {
+ enum omp_clause_default_kind default_kind;
+ enum omp_clause_schedule_kind schedule_kind;
+ enum omp_clause_depend_kind depend_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;
+ enum tree_code reduction_code;
+ enum omp_clause_linear_kind linear_kind;
+ enum tree_code if_modifier;
+ enum omp_clause_defaultmap_kind defaultmap_kind;
+ enum omp_clause_bind_kind bind_kind;
+ enum omp_clause_device_type_kind device_type_kind;
+ } GTY ((skip)) subcode;
+
+ /* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's
+ usage. */
+ gimple_seq gimple_reduction_init;
+ gimple_seq gimple_reduction_merge;
+
+ tree GTY ((length ("omp_clause_num_ops[OMP_CLAUSE_CODE ((tree)&%h)]")))
+ ops[1];
+};
+
+struct GTY(()) tree_block {
+ struct tree_base base;
+ tree chain;
+
+ unsigned block_num;
+
+ location_t locus;
+ location_t end_locus;
+
+ tree vars;
+ vec<tree, va_gc> *nonlocalized_vars;
+
+ tree subblocks;
+ tree supercontext;
+ tree abstract_origin;
+ tree fragment_origin;
+ tree fragment_chain;
+
+ /* Pointer to the DWARF lexical block. */
+ struct die_struct *die;
+};
+
+struct GTY(()) tree_type_common {
+ struct tree_common common;
+ tree size;
+ tree size_unit;
+ tree attributes;
+ unsigned int uid;
+
+ unsigned int precision : 10;
+ unsigned no_force_blk_flag : 1;
+ unsigned needs_constructing_flag : 1;
+ unsigned transparent_aggr_flag : 1;
+ unsigned restrict_flag : 1;
+ unsigned contains_placeholder_bits : 2;
+
+ ENUM_BITFIELD(machine_mode) mode : 8;
+
+ /* TYPE_STRING_FLAG for INTEGER_TYPE and ARRAY_TYPE.
+ TYPE_CXX_ODR_P for RECORD_TYPE and UNION_TYPE. */
+ unsigned string_flag : 1;
+ unsigned lang_flag_0 : 1;
+ unsigned lang_flag_1 : 1;
+ unsigned lang_flag_2 : 1;
+ unsigned lang_flag_3 : 1;
+ unsigned lang_flag_4 : 1;
+ unsigned lang_flag_5 : 1;
+ unsigned lang_flag_6 : 1;
+ unsigned lang_flag_7 : 1;
+
+ /* TYPE_ALIGN in log2; this has to be large enough to hold values
+ of the maximum of BIGGEST_ALIGNMENT and MAX_OFILE_ALIGNMENT,
+ the latter being usually the larger. For ELF it is 8<<28,
+ so we need to store the value 32 (not 31, as we need the zero
+ as well), hence six bits. */
+ unsigned align : 6;
+ unsigned warn_if_not_align : 6;
+ unsigned typeless_storage : 1;
+ unsigned empty_flag : 1;
+ unsigned indivisible_p : 1;
+ unsigned spare : 16;
+
+ alias_set_type alias_set;
+ tree pointer_to;
+ tree reference_to;
+ union tree_type_symtab {
+ int GTY ((tag ("TYPE_SYMTAB_IS_ADDRESS"))) address;
+ struct die_struct * GTY ((tag ("TYPE_SYMTAB_IS_DIE"))) die;
+ } GTY ((desc ("debug_hooks->tree_type_symtab_field"))) symtab;
+ tree canonical;
+ tree next_variant;
+ tree main_variant;
+ tree context;
+ tree name;
+};
+
+struct GTY(()) tree_type_with_lang_specific {
+ struct tree_type_common common;
+ /* Points to a structure whose details depend on the language in use. */
+ struct lang_type *lang_specific;
+};
+
+struct GTY(()) tree_type_non_common {
+ struct tree_type_with_lang_specific with_lang_specific;
+ tree values;
+ tree minval;
+ tree maxval;
+ tree lang_1;
+};
+
+struct GTY (()) tree_binfo {
+ struct tree_common common;
+
+ tree offset;
+ tree vtable;
+ tree virtuals;
+ tree vptr_field;
+ vec<tree, va_gc> *base_accesses;
+ tree inheritance;
+
+ tree vtt_subvtt;
+ tree vtt_vptr;
+
+ vec<tree, va_gc> base_binfos;
+};
+
+struct GTY(()) tree_decl_minimal {
+ struct tree_common common;
+ location_t locus;
+ unsigned int uid;
+ tree name;
+ tree context;
+};
+
+struct GTY(()) tree_decl_common {
+ struct tree_decl_minimal common;
+ tree size;
+
+ ENUM_BITFIELD(machine_mode) mode : 8;
+
+ unsigned nonlocal_flag : 1;
+ unsigned virtual_flag : 1;
+ unsigned ignored_flag : 1;
+ unsigned abstract_flag : 1;
+ unsigned artificial_flag : 1;
+ unsigned preserve_flag: 1;
+ unsigned debug_expr_is_from : 1;
+
+ unsigned lang_flag_0 : 1;
+ unsigned lang_flag_1 : 1;
+ unsigned lang_flag_2 : 1;
+ unsigned lang_flag_3 : 1;
+ unsigned lang_flag_4 : 1;
+ unsigned lang_flag_5 : 1;
+ unsigned lang_flag_6 : 1;
+ unsigned lang_flag_7 : 1;
+ unsigned lang_flag_8 : 1;
+
+ /* In VAR_DECL and PARM_DECL, this is DECL_REGISTER
+ In TRANSLATION_UNIT_DECL, this is TRANSLATION_UNIT_WARN_EMPTY_P.
+ In FIELD_DECL, this is DECL_FIELD_ABI_IGNORED. */
+ unsigned decl_flag_0 : 1;
+ /* In FIELD_DECL, this is DECL_BIT_FIELD
+ In VAR_DECL and FUNCTION_DECL, this is DECL_EXTERNAL.
+ In TYPE_DECL, this is TYPE_DECL_SUPPRESS_DEBUG. */
+ unsigned decl_flag_1 : 1;
+ /* In FIELD_DECL, this is DECL_NONADDRESSABLE_P
+ In VAR_DECL, PARM_DECL and RESULT_DECL, this is
+ DECL_HAS_VALUE_EXPR_P. */
+ unsigned decl_flag_2 : 1;
+ /* In FIELD_DECL, this is DECL_PADDING_P. */
+ unsigned decl_flag_3 : 1;
+ /* Logically, these two would go in a theoretical base shared by var and
+ parm decl. */
+ unsigned not_gimple_reg_flag : 1;
+ /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE. */
+ unsigned decl_by_reference_flag : 1;
+ /* In a VAR_DECL and PARM_DECL, this is DECL_READ_P. */
+ unsigned decl_read_flag : 1;
+ /* In a VAR_DECL or RESULT_DECL, this is DECL_NONSHAREABLE. */
+ /* In a PARM_DECL, this is DECL_HIDDEN_STRING_LENGTH. */
+ unsigned decl_nonshareable_flag : 1;
+
+ /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
+ unsigned int off_align : 6;
+
+ /* DECL_ALIGN. It should have the same size as TYPE_ALIGN. */
+ unsigned int align : 6;
+
+ /* DECL_WARN_IF_NOT_ALIGN. It should have the same size as
+ TYPE_WARN_IF_NOT_ALIGN. */
+ unsigned int warn_if_not_align : 6;
+
+ /* 14 bits unused. */
+
+ /* UID for points-to sets, stable over copying from inlining. */
+ unsigned int pt_uid;
+
+ tree size_unit;
+ tree initial;
+ tree attributes;
+ tree abstract_origin;
+
+ /* Points to a structure whose details depend on the language in use. */
+ struct lang_decl *lang_specific;
+};
+
+struct GTY(()) tree_decl_with_rtl {
+ struct tree_decl_common common;
+ rtx rtl;
+};
+
+struct GTY(()) tree_field_decl {
+ struct tree_decl_common common;
+
+ tree offset;
+ tree bit_field_type;
+ tree qualifier;
+ tree bit_offset;
+ tree fcontext;
+};
+
+struct GTY(()) tree_label_decl {
+ struct tree_decl_with_rtl common;
+ int label_decl_uid;
+ int eh_landing_pad_nr;
+};
+
+struct GTY(()) tree_result_decl {
+ struct tree_decl_with_rtl common;
+};
+
+struct GTY(()) tree_const_decl {
+ struct tree_decl_common common;
+};
+
+struct GTY(()) tree_parm_decl {
+ struct tree_decl_with_rtl common;
+ rtx incoming_rtl;
+};
+
+struct GTY(()) tree_decl_with_vis {
+ struct tree_decl_with_rtl common;
+ tree assembler_name;
+ struct symtab_node *symtab_node;
+
+ /* Belong to VAR_DECL exclusively. */
+ unsigned defer_output : 1;
+ unsigned hard_register : 1;
+ unsigned common_flag : 1;
+ unsigned in_text_section : 1;
+ unsigned in_constant_pool : 1;
+ unsigned dllimport_flag : 1;
+ /* Don't belong to VAR_DECL exclusively. */
+ unsigned weak_flag : 1;
+
+ unsigned seen_in_bind_expr : 1;
+ unsigned comdat_flag : 1;
+ /* Used for FUNCTION_DECL, VAR_DECL and in C++ for TYPE_DECL. */
+ ENUM_BITFIELD(symbol_visibility) visibility : 2;
+ unsigned visibility_specified : 1;
+
+ /* Belong to FUNCTION_DECL exclusively. */
+ unsigned init_priority_p : 1;
+ /* Used by C++ only. Might become a generic decl flag. */
+ unsigned shadowed_for_var_p : 1;
+ /* Belong to FUNCTION_DECL exclusively. */
+ unsigned cxx_constructor : 1;
+ /* Belong to FUNCTION_DECL exclusively. */
+ unsigned cxx_destructor : 1;
+ /* Belong to FUNCTION_DECL exclusively. */
+ unsigned final : 1;
+ /* Belong to FUNCTION_DECL exclusively. */
+ unsigned regdecl_flag : 1;
+ /* 14 unused bits. */
+ /* 32 more unused on 64 bit HW. */
+};
+
+struct GTY(()) tree_var_decl {
+ struct tree_decl_with_vis common;
+};
+
+struct GTY(()) tree_decl_non_common {
+ struct tree_decl_with_vis common;
+ /* Almost all FE's use this. */
+ tree result;
+};
+
+/* Classify a special function declaration type. */
+
+enum function_decl_type
+{
+ NONE,
+ OPERATOR_NEW,
+ OPERATOR_DELETE,
+ LAMBDA_FUNCTION
+
+ /* 0 values left */
+};
+
+/* FUNCTION_DECL inherits from DECL_NON_COMMON because of the use of the
+ arguments/result/saved_tree fields by front ends. It was either inherit
+ FUNCTION_DECL from non_common, or inherit non_common from FUNCTION_DECL,
+ which seemed a bit strange. */
+
+struct GTY(()) tree_function_decl {
+ struct tree_decl_non_common common;
+
+ struct function *f;
+
+ /* Arguments of the function. */
+ tree arguments;
+ /* The personality function. Used for stack unwinding. */
+ tree personality;
+
+ /* Function specific options that are used by this function. */
+ tree function_specific_target; /* target options */
+ tree function_specific_optimization; /* optimization options */
+
+ /* Generic function body. */
+ tree saved_tree;
+ /* Index within a virtual table. */
+ tree vindex;
+
+ /* In a FUNCTION_DECL this is DECL_UNCHECKED_FUNCTION_CODE. */
+ unsigned int function_code;
+
+ ENUM_BITFIELD(built_in_class) built_in_class : 2;
+ unsigned static_ctor_flag : 1;
+ unsigned static_dtor_flag : 1;
+ unsigned uninlinable : 1;
+ unsigned possibly_inlined : 1;
+ unsigned novops_flag : 1;
+ unsigned returns_twice_flag : 1;
+
+ unsigned malloc_flag : 1;
+ unsigned declared_inline_flag : 1;
+ unsigned no_inline_warning_flag : 1;
+ unsigned no_instrument_function_entry_exit : 1;
+ unsigned no_limit_stack : 1;
+ unsigned disregard_inline_limits : 1;
+ unsigned pure_flag : 1;
+ unsigned looping_const_or_pure_flag : 1;
+
+ /* Align the bitfield to boundary of a byte. */
+ ENUM_BITFIELD(function_decl_type) decl_type: 2;
+ unsigned has_debug_args_flag : 1;
+ unsigned versioned_function : 1;
+ unsigned replaceable_operator : 1;
+
+ /* 11 bits left for future expansion. */
+ /* 32 bits on 64-bit HW. */
+};
+
+struct GTY(()) tree_translation_unit_decl {
+ struct tree_decl_common common;
+ /* Source language of this translation unit. Used for DWARF output. */
+ const char *language;
+ /* TODO: Non-optimization used to build this translation unit. */
+ /* TODO: Root of a partial DWARF tree for global types and decls. */
+};
+
+struct GTY(()) tree_type_decl {
+ struct tree_decl_non_common common;
+
+};
+
+struct GTY ((chain_next ("%h.next"), chain_prev ("%h.prev"))) tree_statement_list_node
+ {
+ struct tree_statement_list_node *prev;
+ struct tree_statement_list_node *next;
+ tree stmt;
+};
+
+struct GTY(()) tree_statement_list
+ {
+ struct tree_typed typed;
+ struct tree_statement_list_node *head;
+ struct tree_statement_list_node *tail;
+};
+
+
+/* Optimization options used by a function. */
+
+struct GTY(()) tree_optimization_option {
+ struct tree_base base;
+
+ /* The optimization options used by the user. */
+ struct cl_optimization *opts;
+
+ /* Target optabs for this set of optimization options. This is of
+ type `struct target_optabs *'. */
+ void *GTY ((atomic)) optabs;
+
+ /* The value of this_target_optabs against which the optabs above were
+ generated. */
+ struct target_optabs *GTY ((skip)) base_optabs;
+};
+
+/* Forward declaration, defined in target-globals.h. */
+
+class GTY(()) target_globals;
+
+/* Target options used by a function. */
+
+struct GTY(()) tree_target_option {
+ struct tree_base base;
+
+ /* Target globals for the corresponding target option. */
+ class target_globals *globals;
+
+ /* The optimization options used by the user. */
+ struct cl_target_option *opts;
+};
+
+/* Define the overall contents of a tree node.
+ It may be any of the structures declared above
+ for various types of node. */
+union GTY ((ptr_alias (union lang_tree_node),
+ desc ("tree_node_structure (&%h)"), variable_size)) tree_node {
+ struct tree_base GTY ((tag ("TS_BASE"))) base;
+ struct tree_typed GTY ((tag ("TS_TYPED"))) typed;
+ struct tree_common GTY ((tag ("TS_COMMON"))) common;
+ struct tree_int_cst GTY ((tag ("TS_INT_CST"))) int_cst;
+// sdcpp struct tree_poly_int_cst GTY ((tag ("TS_POLY_INT_CST"))) poly_int_cst;
+ struct tree_real_cst GTY ((tag ("TS_REAL_CST"))) real_cst;
+ struct tree_fixed_cst GTY ((tag ("TS_FIXED_CST"))) fixed_cst;
+ struct tree_vector GTY ((tag ("TS_VECTOR"))) vector;
+ struct tree_string GTY ((tag ("TS_STRING"))) string;
+ struct tree_complex GTY ((tag ("TS_COMPLEX"))) complex;
+ struct tree_identifier GTY ((tag ("TS_IDENTIFIER"))) identifier;
+ struct tree_decl_minimal GTY((tag ("TS_DECL_MINIMAL"))) decl_minimal;
+ struct tree_decl_common GTY ((tag ("TS_DECL_COMMON"))) decl_common;
+ struct tree_decl_with_rtl GTY ((tag ("TS_DECL_WRTL"))) decl_with_rtl;
+ struct tree_decl_non_common GTY ((tag ("TS_DECL_NON_COMMON")))
+ decl_non_common;
+ struct tree_parm_decl GTY ((tag ("TS_PARM_DECL"))) parm_decl;
+ struct tree_decl_with_vis GTY ((tag ("TS_DECL_WITH_VIS"))) decl_with_vis;
+ struct tree_var_decl GTY ((tag ("TS_VAR_DECL"))) var_decl;
+ struct tree_field_decl GTY ((tag ("TS_FIELD_DECL"))) field_decl;
+ struct tree_label_decl GTY ((tag ("TS_LABEL_DECL"))) label_decl;
+ struct tree_result_decl GTY ((tag ("TS_RESULT_DECL"))) result_decl;
+ struct tree_const_decl GTY ((tag ("TS_CONST_DECL"))) const_decl;
+ struct tree_type_decl GTY ((tag ("TS_TYPE_DECL"))) type_decl;
+ struct tree_function_decl GTY ((tag ("TS_FUNCTION_DECL"))) function_decl;
+ struct tree_translation_unit_decl GTY ((tag ("TS_TRANSLATION_UNIT_DECL")))
+ translation_unit_decl;
+ struct tree_type_common GTY ((tag ("TS_TYPE_COMMON"))) type_common;
+ struct tree_type_with_lang_specific GTY ((tag ("TS_TYPE_WITH_LANG_SPECIFIC")))
+ type_with_lang_specific;
+ struct tree_type_non_common GTY ((tag ("TS_TYPE_NON_COMMON")))
+ type_non_common;
+ struct tree_list GTY ((tag ("TS_LIST"))) list;
+ struct tree_vec GTY ((tag ("TS_VEC"))) vec;
+ struct tree_exp GTY ((tag ("TS_EXP"))) exp;
+ struct tree_ssa_name GTY ((tag ("TS_SSA_NAME"))) ssa_name;
+ struct tree_block GTY ((tag ("TS_BLOCK"))) block;
+ struct tree_binfo GTY ((tag ("TS_BINFO"))) binfo;
+ struct tree_statement_list GTY ((tag ("TS_STATEMENT_LIST"))) stmt_list;
+ struct tree_constructor GTY ((tag ("TS_CONSTRUCTOR"))) constructor;
+ struct tree_omp_clause GTY ((tag ("TS_OMP_CLAUSE"))) omp_clause;
+ struct tree_optimization_option GTY ((tag ("TS_OPTIMIZATION"))) optimization;
+ struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
+};
+
+/* Structure describing an attribute and a function to handle it. */
+struct attribute_spec {
+ /* The name of the attribute (without any leading or trailing __),
+ or NULL to mark the end of a table of attributes. */
+ const char *name;
+ /* The minimum length of the list of arguments of the attribute. */
+ int min_length;
+ /* The maximum length of the list of arguments of the attribute
+ (-1 for no maximum). It can also be -2 for fake attributes
+ created for the sake of -Wno-attributes; in that case, we
+ should skip the balanced token sequence when parsing the attribute. */
+ int max_length;
+ /* Whether this attribute requires a DECL. If it does, it will be passed
+ from types of DECLs, function return types and array element types to
+ the DECLs, function types and array types respectively; but when
+ applied to a type in any other circumstances, it will be ignored with
+ a warning. (If greater control is desired for a given attribute,
+ this should be false, and the flags argument to the handler may be
+ used to gain greater control in that case.) */
+ bool decl_required;
+ /* Whether this attribute requires a type. If it does, it will be passed
+ from a DECL to the type of that DECL. */
+ bool type_required;
+ /* Whether this attribute requires a function (or method) type. If it does,
+ it will be passed from a function pointer type to the target type,
+ and from a function return type (which is not itself a function
+ pointer type) to the function type. */
+ bool function_type_required;
+ /* Specifies if attribute affects type's identity. */
+ bool affects_type_identity;
+ /* Function to handle this attribute. NODE points to the node to which
+ the attribute is to be applied. If a DECL, it should be modified in
+ place; if a TYPE, a copy should be created. NAME is the canonicalized
+ name of the attribute i.e. without any leading or trailing underscores.
+ ARGS is the TREE_LIST of the arguments (which may be NULL). FLAGS gives
+ further information about the context of the attribute. Afterwards, the
+ attributes will be added to the DECL_ATTRIBUTES or TYPE_ATTRIBUTES, as
+ appropriate, unless *NO_ADD_ATTRS is set to true (which should be done on
+ error, as well as in any other cases when the attributes should not be
+ added to the DECL or TYPE). Depending on FLAGS, any attributes to be
+ applied to another type or DECL later may be returned;
+ otherwise the return value should be NULL_TREE. This pointer may be
+ NULL if no special handling is required beyond the checks implied
+ by the rest of this structure. */
+ tree (*handler) (tree *node, tree name, tree args,
+ int flags, bool *no_add_attrs);
+
+ /* Specifies the name of an attribute that's mutually exclusive with
+ this one, and whether the relationship applies to the function,
+ variable, or type form of the attribute. */
+ struct exclusions {
+ const char *name;
+ bool function;
+ bool variable;
+ bool type;
+ };
+
+ /* An array of attribute exclusions describing names of other attributes
+ that this attribute is mutually exclusive with. */
+ const exclusions *exclude;
+};
+
+/* These functions allow a front-end to perform a manual layout of a
+ RECORD_TYPE. (For instance, if the placement of subsequent fields
+ depends on the placement of fields so far.) Begin by calling
+ start_record_layout. Then, call place_field for each of the
+ fields. Then, call finish_record_layout. See layout_type for the
+ default way in which these functions are used. */
+typedef struct record_layout_info_s {
+ /* The RECORD_TYPE that we are laying out. */
+ tree t;
+ /* The offset into the record so far, in bytes, not including bits in
+ BITPOS. */
+ tree offset;
+ /* The last known alignment of SIZE. */
+ unsigned int offset_align;
+ /* The bit position within the last OFFSET_ALIGN bits, in bits. */
+ tree bitpos;
+ /* The alignment of the record so far, in bits. */
+ unsigned int record_align;
+ /* The alignment of the record so far, ignoring #pragma pack and
+ __attribute__ ((packed)), in bits. */
+ unsigned int unpacked_align;
+ /* The previous field laid out. */
+ tree prev_field;
+ /* The static variables (i.e., class variables, as opposed to
+ instance variables) encountered in T. */
+ vec<tree, va_gc> *pending_statics;
+ /* Bits remaining in the current alignment group */
+ int remaining_in_alignment;
+ /* True if we've seen a packed field that didn't have normal
+ alignment anyway. */
+ int packed_maybe_necessary;
+} *record_layout_info;
+
+/* Iterator for going through the function arguments. */
+struct function_args_iterator {
+ tree next; /* TREE_LIST pointing to the next argument */
+};
+
+/* Structures to map from a tree to another tree. */
+struct GTY(()) tree_map_base {
+ tree from;
+};
+
+/* Map from a tree to another tree. */
+
+struct GTY((for_user)) tree_map {
+ struct tree_map_base base;
+ unsigned int hash;
+ tree to;
+};
+
+/* Map from a decl tree to another tree. */
+struct GTY((for_user)) tree_decl_map {
+ struct tree_map_base base;
+ tree to;
+};
+
+/* Map from a tree to an int. */
+struct GTY((for_user)) tree_int_map {
+ struct tree_map_base base;
+ unsigned int to;
+};
+
+/* Map from a decl tree to a tree vector. */
+struct GTY((for_user)) tree_vec_map {
+ struct tree_map_base base;
+ vec<tree, va_gc> *to;
+};
+
+/* Abstract iterators for CALL_EXPRs. These static inline definitions
+ have to go towards the end of tree.h so that union tree_node is fully
+ defined by this point. */
+
+/* Structure containing iterator state. */
+struct call_expr_arg_iterator {
+ tree t; /* the call_expr */
+ int n; /* argument count */
+ int i; /* next argument index */
+};
+
+struct const_call_expr_arg_iterator {
+ const_tree t; /* the call_expr */
+ int n; /* argument count */
+ int i; /* next argument index */
+};
+
+/* The builtin_info structure holds the FUNCTION_DECL of the standard builtin
+ function, and flags. */
+struct GTY(()) builtin_info_type {
+ tree decl;
+ /* Whether the user can use <xxx> instead of explicitly using calls
+ to __builtin_<xxx>. */
+ unsigned implicit_p : 1;
+ /* Whether the user has provided a declaration of <xxx>. */
+ unsigned declared_p : 1;
+};
+
+/* Information about a _FloatN or _FloatNx type that may be
+ supported. */
+struct floatn_type_info {
+ /* The number N in the type name. */
+ int n;
+ /* Whether it is an extended type _FloatNx (true) or an interchange
+ type (false). */
+ bool extended;
+};
+
+
+/*---------------------------------------------------------------------------
+ Global variables
+---------------------------------------------------------------------------*/
+/* Matrix describing the structures contained in a given tree code. */
+extern bool tree_contains_struct[MAX_TREE_CODES][64];
+
+/* Class of tree given its code. */
+// extern const enum tree_code_class tree_code_type[];
+
+/* Each tree code class has an associated string representation.
+ These must correspond to the tree_code_class entries. */
+extern const char *const tree_code_class_strings[];
+
+/* Number of argument-words in each kind of tree-node. */
+extern const unsigned char tree_code_length[];
+
+/* Vector of all alias pairs for global symbols. */
+extern GTY(()) vec<alias_pair, va_gc> *alias_pairs;
+
+/* Names of all the built_in classes. */
+extern const char *const built_in_class_names[BUILT_IN_LAST];
+
+/* Names of all the built_in functions. */
+extern const char * built_in_names[(int) END_BUILTINS];
+
+/* Number of operands and names for each OMP_CLAUSE node. */
+extern unsigned const char omp_clause_num_ops[];
+extern const char * const omp_clause_code_name[];
+extern const char *user_omp_clause_code_name (tree, bool);
+
+/* A vector of all translation-units. */
+extern GTY (()) vec<tree, va_gc> *all_translation_units;
+
+/* Vector of standard trees used by the C compiler. */
+// extern GTY(()) tree global_trees[TI_MAX];
+
+/* The standard C integer types. Use integer_type_kind to index into
+ this array. */
+extern GTY(()) tree integer_types[itk_none];
+
+/* Types used to represent sizes. */
+extern GTY(()) tree sizetype_tab[(int) stk_type_kind_last];
+
+/* Arrays for keeping track of tree node statistics. */
+extern uint64_t tree_node_counts[];
+extern uint64_t tree_node_sizes[];
+
+/* True if we are in gimple form and the actions of the folders need to
+ be restricted. False if we are not in gimple form and folding is not
+ restricted to creating gimple expressions. */
+extern bool in_gimple_form;
+
+/* Functional interface to the builtin functions. */
+extern GTY(()) builtin_info_type builtin_info[(int)END_BUILTINS];
+
+/* If nonzero, an upper limit on alignment of structure fields, in bits, */
+extern unsigned int maximum_field_alignment;
+
+/* Points to the FUNCTION_DECL of the function whose body we are reading. */
+extern GTY(()) tree current_function_decl;
+
+/* Nonzero means a FUNC_BEGIN label was emitted. */
+extern GTY(()) const char * current_function_func_begin_label;
+
+/* Information about the _FloatN and _FloatNx types. */
+// extern const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES];
+
+#endif // GCC_TREE_CORE_H
diff --git a/support/cpp/gcc/tree-diagnostic.h b/support/cpp/gcc/tree-diagnostic.h
new file mode 100644
index 000000000..f60f2320e
--- /dev/null
+++ b/support/cpp/gcc/tree-diagnostic.h
@@ -0,0 +1,68 @@
+/* Various declarations for language-independent diagnostics
+ subroutines that are only for use in the compilers proper and not
+ the driver or other programs.
+ Copyright (C) 2000-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_TREE_DIAGNOSTIC_H
+#define GCC_TREE_DIAGNOSTIC_H
+
+/* TREE_BLOCK if the diagnostic is to be reported in some inline
+ function inlined into other function, otherwise NULL. */
+#define diagnostic_abstract_origin(DI) \
+ ((tree) diagnostic_info_auxiliary_data (DI))
+
+/* Function of last diagnostic message; more generally, function such
+ that if next diagnostic message is in it then we don't have to
+ mention the function name. */
+#define diagnostic_last_function(DC) \
+ ((tree) diagnostic_context_auxiliary_data (DC))
+
+/* True if the last function in which a diagnostic was reported is
+ different from the current one. */
+#define diagnostic_last_function_changed(DC, DI) \
+ (diagnostic_last_function (DC) != (diagnostic_abstract_origin (DI) \
+ ? diagnostic_abstract_origin (DI) \
+ : current_function_decl))
+
+/* Remember the current function as being the last one in which we report
+ a diagnostic. */
+#define diagnostic_set_last_function(DC, DI) \
+ diagnostic_context_auxiliary_data (DC) \
+ = (((DI) && diagnostic_abstract_origin (DI)) \
+ ? diagnostic_abstract_origin (DI) \
+ : current_function_decl)
+
+void diagnostic_report_current_function (diagnostic_context *,
+ diagnostic_info *);
+void virt_loc_aware_diagnostic_finalizer (diagnostic_context *,
+ diagnostic_info *);
+
+void tree_diagnostics_defaults (diagnostic_context *context);
+bool default_tree_printer (pretty_printer *, text_info *, const char *,
+ int, bool, bool, bool, bool *, const char **);
+
+extern void default_tree_diagnostic_path_printer (diagnostic_context *,
+ const diagnostic_path *);
+extern json::value *default_tree_make_json_for_path (diagnostic_context *,
+ const diagnostic_path *);
+
+extern void maybe_unwind_expanded_macro_loc (diagnostic_context *context,
+ location_t where);
+
+#endif /* ! GCC_TREE_DIAGNOSTIC_H */
diff --git a/support/cpp/gcc/tree-inline.h b/support/cpp/gcc/tree-inline.h
new file mode 100644
index 000000000..c601cadae
--- /dev/null
+++ b/support/cpp/gcc/tree-inline.h
@@ -0,0 +1,256 @@
+/* Tree inlining hooks and declarations.
+ Copyright (C) 2001-2022 Free Software Foundation, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.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.
+
+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_TREE_INLINE_H
+#define GCC_TREE_INLINE_H
+
+
+struct cgraph_edge;
+
+/* Indicate the desired behavior wrt call graph edges. We can either
+ duplicate the edge (inlining, cloning), move the edge (versioning,
+ parallelization), or move the edges of the clones (saving). */
+
+enum copy_body_cge_which
+{
+ CB_CGE_DUPLICATE,
+ CB_CGE_MOVE,
+ CB_CGE_MOVE_CLONES
+};
+
+typedef int_hash <unsigned short, 0> dependence_hash;
+
+/* Data required for function body duplication. */
+
+struct copy_body_data
+{
+ /* FUNCTION_DECL for function being inlined, or in general the
+ source function providing the original trees. */
+ tree src_fn;
+
+ /* FUNCTION_DECL for function being inlined into, or in general
+ the destination function receiving the new trees. */
+ tree dst_fn;
+
+ /* Callgraph node of the source function. */
+ struct cgraph_node *src_node;
+
+ /* Callgraph node of the destination function. */
+ struct cgraph_node *dst_node;
+
+ /* struct function for function being inlined. Usually this is the same
+ as DECL_STRUCT_FUNCTION (src_fn), but can be different if saved_cfg
+ and saved_eh are in use. */
+ struct function *src_cfun;
+
+ /* The VAR_DECL for the return value. */
+ tree retvar;
+
+ /* The map from local declarations in the inlined function to
+ equivalents in the function into which it is being inlined. */
+ hash_map<tree, tree> *decl_map;
+
+ /* Create a new decl to replace DECL in the destination function. */
+ tree (*copy_decl) (tree, struct copy_body_data *);
+
+ /* Current BLOCK. */
+ tree block;
+
+ /* GIMPLE_CALL if va arg parameter packs should be expanded or NULL
+ is not. */
+ gcall *call_stmt;
+
+ /* > 0 if we are remapping a type currently. */
+ int remapping_type_depth;
+
+ /* Exception landing pad the inlined call lies in. */
+ int eh_lp_nr;
+
+ /* Maps region and landing pad structures from the function being copied
+ to duplicates created within the function we inline into. */
+ hash_map<void *, void *> *eh_map;
+
+ /* We use the same mechanism do all sorts of different things. Rather
+ than enumerating the different cases, we categorize the behavior
+ in the various situations. */
+
+ /* What to do with call graph edges. */
+ enum copy_body_cge_which transform_call_graph_edges;
+
+ /* True if a new CFG should be created. False for inlining, true for
+ everything else. */
+ bool transform_new_cfg;
+
+ /* True if RETURN_EXPRs should be transformed to just the contained
+ MODIFY_EXPR. The branch semantics of the return will be handled
+ by manipulating the CFG rather than a statement. */
+ bool transform_return_to_modify;
+
+ /* True if the parameters of the source function are transformed.
+ Only true for inlining. */
+ bool transform_parameter;
+
+ /* True if this statement will need to be regimplified. */
+ bool regimplify;
+
+ /* True if trees may not be unshared. */
+ bool do_not_unshare;
+
+ /* True if trees should not be folded during the copying. */
+ bool do_not_fold;
+
+ /* True if new declarations may not be created during type remapping. */
+ bool prevent_decl_creation_for_types;
+
+ /* True if the location information will need to be reset. */
+ bool reset_location;
+
+ /* Replace error_mark_node as upper bound of array types with
+ an uninitialized VAR_DECL temporary. */
+ bool adjust_array_error_bounds;
+
+ /* Usually copy_decl callback always creates new decls, in that case
+ we want to remap all variably_modified_type_p types. If this flag
+ is set, remap_type will do further checks to see if remap_decl
+ of any decls mentioned in the type will remap to anything but itself
+ and only in that case will actually remap the type. */
+ bool dont_remap_vla_if_no_change;
+
+ /* Statements that might be possibly folded. */
+ hash_set<gimple *> *statements_to_fold;
+
+ /* Entry basic block to currently copied body. */
+ basic_block entry_bb;
+
+ /* For partial function versioning, bitmap of bbs to be copied,
+ otherwise NULL. */
+ bitmap blocks_to_copy;
+
+ /* Debug statements that need processing. */
+ vec<gdebug *> debug_stmts;
+
+ /* A map from local declarations in the inlined function to
+ equivalents in the function into which it is being inlined,
+ where the originals have been mapped to a value rather than
+ to a variable. */
+ hash_map<tree, tree> *debug_map;
+
+ /* A map from the inlined functions dependence info cliques to
+ equivalents in the function into which it is being inlined. */
+ hash_map<dependence_hash, unsigned short> *dependence_map;
+
+ /* A list of addressable local variables remapped into the caller
+ when inlining a call within an OpenMP SIMD-on-SIMT loop. */
+ vec<tree> *dst_simt_vars;
+
+ /* Basic block to which clobbers for local variables from the inline
+ function that need to live in memory should be added. */
+ basic_block eh_landing_pad_dest;
+
+ /* If clobbers for local variables from the inline function
+ that need to live in memory should be added to EH landing pads
+ outside of the inlined function, this should be the number
+ of basic blocks in the caller before inlining. Zero otherwise. */
+ int add_clobbers_to_eh_landing_pads;
+
+ /* Class managing changes to function parameters and return value planned
+ during IPA stage. */
+ class ipa_param_body_adjustments *param_body_adjs;
+
+ /* Hash set of SSA names that have been killed during call graph edge
+ redirection and should not be introduced into debug statements or NULL if no
+ SSA_NAME was deleted during redirections happened. */
+ hash_set <tree> *killed_new_ssa_names;
+};
+
+/* Weights of constructions for estimate_num_insns. */
+
+struct eni_weights
+{
+ /* Cost per call. */
+ unsigned call_cost;
+
+ /* Cost per indirect call. */
+ unsigned indirect_call_cost;
+
+ /* Cost per call to a target specific builtin */
+ unsigned target_builtin_call_cost;
+
+ /* Cost of "expensive" div and mod operations. */
+ unsigned div_mod_cost;
+
+ /* Cost for omp construct. */
+ unsigned omp_cost;
+
+ /* Cost for tm transaction. */
+ unsigned tm_cost;
+
+ /* Cost of return. */
+ unsigned return_cost;
+
+ /* True when time of statement should be estimated. Thus, the
+ cost of a switch statement is logarithmic rather than linear in number
+ of cases. */
+ bool time_based;
+};
+
+/* Weights that estimate_num_insns uses for heuristics in inlining. */
+
+extern eni_weights eni_inlining_weights;
+
+/* Weights that estimate_num_insns uses to estimate the size of the
+ produced code. */
+
+extern eni_weights eni_size_weights;
+
+/* Weights that estimate_num_insns uses to estimate the time necessary
+ to execute the produced code. */
+
+extern eni_weights eni_time_weights;
+
+/* Function prototypes. */
+void init_inline_once (void);
+extern tree copy_tree_body_r (tree *, int *, void *);
+extern void insert_decl_map (copy_body_data *, tree, tree);
+unsigned int optimize_inline_calls (tree);
+tree maybe_inline_call_in_expr (tree);
+bool tree_inlinable_function_p (tree);
+tree copy_tree_r (tree *, int *, void *);
+tree copy_decl_no_change (tree decl, copy_body_data *id);
+int estimate_move_cost (tree type, bool);
+int estimate_num_insns (gimple *, eni_weights *);
+int estimate_num_insns_fn (tree, eni_weights *);
+int estimate_num_insns_seq (gimple_seq, eni_weights *);
+bool tree_versionable_function_p (tree);
+extern tree remap_decl (tree decl, copy_body_data *id);
+extern tree remap_type (tree type, copy_body_data *id);
+extern gimple_seq copy_gimple_seq_and_replace_locals (gimple_seq seq);
+extern bool debug_find_tree (tree, tree);
+extern tree copy_fn (tree, tree&, tree&);
+extern const char *copy_forbidden (struct function *fun);
+extern tree copy_decl_for_dup_finish (copy_body_data *id, tree decl, tree copy);
+extern tree copy_decl_to_var (tree, copy_body_data *);
+extern tree force_value_to_type (tree type, tree value);
+
+/* This is in tree-inline.cc since the routine uses
+ data structures from the inliner. */
+extern tree build_duplicate_type (tree);
+
+#endif /* GCC_TREE_INLINE_H */
diff --git a/support/cpp/gcc/tree-iterator.h b/support/cpp/gcc/tree-iterator.h
new file mode 100644
index 000000000..5982f19ba
--- /dev/null
+++ b/support/cpp/gcc/tree-iterator.h
@@ -0,0 +1,150 @@
+/* Iterator routines for manipulating GENERIC tree statement list. -*- C++ -*-
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.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.
+
+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 is dependent upon the implementation of tree's. It provides an
+ abstract interface to the tree objects such that if all tree creation and
+ manipulations are done through this interface, we can easily change the
+ implementation of tree's, and not impact other code. */
+
+#if 0 // sdcpp ndef GCC_TREE_ITERATOR_H
+#define GCC_TREE_ITERATOR_H 1
+
+/* Iterator object for GENERIC or GIMPLE TREE statements. */
+
+struct tree_stmt_iterator {
+ struct tree_statement_list_node *ptr;
+ tree container;
+
+ /* No need for user-defined constructors, the implicit definitions (or
+ aggregate initialization) are fine. */
+
+ bool operator== (tree_stmt_iterator b) const
+ { return b.ptr == ptr && b.container == container; }
+ bool operator!= (tree_stmt_iterator b) const { return !(*this == b); }
+ tree_stmt_iterator &operator++ () { ptr = ptr->next; return *this; }
+ tree_stmt_iterator &operator-- () { ptr = ptr->prev; return *this; }
+ tree_stmt_iterator operator++ (int)
+ { tree_stmt_iterator x = *this; ++*this; return x; }
+ tree_stmt_iterator operator-- (int)
+ { tree_stmt_iterator x = *this; --*this; return x; }
+ tree &operator* () { return ptr->stmt; }
+ tree operator* () const { return ptr->stmt; }
+};
+
+static inline tree_stmt_iterator
+tsi_start (tree t)
+{
+ tree_stmt_iterator i;
+
+ i.ptr = STATEMENT_LIST_HEAD (t);
+ i.container = t;
+
+ return i;
+}
+
+static inline tree_stmt_iterator
+tsi_last (tree t)
+{
+ tree_stmt_iterator i;
+
+ i.ptr = STATEMENT_LIST_TAIL (t);
+ i.container = t;
+
+ return i;
+}
+
+static inline bool
+tsi_end_p (tree_stmt_iterator i)
+{
+ return i.ptr == NULL;
+}
+
+static inline bool
+tsi_one_before_end_p (tree_stmt_iterator i)
+{
+ return i.ptr != NULL && i.ptr->next == NULL;
+}
+
+static inline void
+tsi_next (tree_stmt_iterator *i)
+{
+ ++(*i);
+}
+
+static inline void
+tsi_prev (tree_stmt_iterator *i)
+{
+ --(*i);
+}
+
+static inline tree *
+tsi_stmt_ptr (tree_stmt_iterator i)
+{
+ return &(*i);
+}
+
+static inline tree
+tsi_stmt (tree_stmt_iterator i)
+{
+ return *i;
+}
+
+/* Make tree_stmt_iterator work as a C++ range, e.g.
+ for (tree stmt : tsi_range (stmt_list)) { ... } */
+class tsi_range
+{
+ tree t;
+ public:
+ tsi_range (tree t): t(t) { }
+ tree_stmt_iterator begin() const { return tsi_start (t); }
+ tree_stmt_iterator end() const { return { nullptr, t }; }
+};
+
+enum tsi_iterator_update
+{
+ TSI_NEW_STMT, /* Only valid when single statement is added, move
+ iterator to it. */
+ TSI_SAME_STMT, /* Leave the iterator at the same statement. */
+ TSI_CHAIN_START, /* Only valid when chain of statements is added, move
+ iterator to the first statement in the chain. */
+ TSI_CHAIN_END, /* Only valid when chain of statements is added, move
+ iterator to the last statement in the chain. */
+ TSI_CONTINUE_LINKING /* Move iterator to whatever position is suitable for
+ linking other statements/chains of statements in
+ the same direction. */
+};
+
+extern void tsi_link_before (tree_stmt_iterator *, tree,
+ enum tsi_iterator_update);
+extern void tsi_link_after (tree_stmt_iterator *, tree,
+ enum tsi_iterator_update);
+
+extern void tsi_delink (tree_stmt_iterator *);
+
+extern tree alloc_stmt_list (void);
+extern void free_stmt_list (tree);
+extern void append_to_statement_list (tree, tree *);
+extern void append_to_statement_list_force (tree, tree *);
+extern tree expr_first (tree);
+extern tree expr_last (tree);
+extern tree expr_single (tree);
+
+#endif /* GCC_TREE_ITERATOR_H */
diff --git a/support/cpp/gcc/tree-pass.h b/support/cpp/gcc/tree-pass.h
new file mode 100644
index 000000000..606d1d60b
--- /dev/null
+++ b/support/cpp/gcc/tree-pass.h
@@ -0,0 +1,680 @@
+/* Definitions for describing one tree-ssa optimization pass.
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.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.
+
+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_TREE_PASS_H
+#define GCC_TREE_PASS_H 1
+
+#include "timevar.h"
+#include "dumpfile.h"
+
+struct function;
+
+/* Optimization pass type. */
+enum opt_pass_type
+{
+ GIMPLE_PASS,
+ RTL_PASS,
+ SIMPLE_IPA_PASS,
+ IPA_PASS
+};
+
+/* Metadata for a pass, non-varying across all instances of a pass. */
+struct pass_data
+{
+ /* Optimization pass type. */
+ enum opt_pass_type type;
+
+ /* Terse name of the pass used as a fragment of the dump file
+ name. If the name starts with a star, no dump happens. */
+ const char *name;
+
+ /* The -fopt-info optimization group flags as defined in dumpfile.h. */
+ optgroup_flags_t optinfo_flags;
+
+ /* The timevar id associated with this pass. */
+ /* ??? Ideally would be dynamically assigned. */
+ timevar_id_t tv_id;
+
+ /* Sets of properties input and output from this pass. */
+ unsigned int properties_required;
+ unsigned int properties_provided;
+ unsigned int properties_destroyed;
+
+ /* Flags indicating common sets things to do before and after. */
+ unsigned int todo_flags_start;
+ unsigned int todo_flags_finish;
+};
+
+namespace gcc
+{
+ class context;
+} // namespace gcc
+
+/* An instance of a pass. This is also "pass_data" to minimize the
+ changes in existing code. */
+class opt_pass : public pass_data
+{
+public:
+ virtual ~opt_pass () { }
+
+ /* Create a copy of this pass.
+
+ Passes that can have multiple instances must provide their own
+ implementation of this, to ensure that any sharing of state between
+ this instance and the copy is "wired up" correctly.
+
+ The default implementation prints an error message and aborts. */
+ virtual opt_pass *clone ();
+ virtual void set_pass_param (unsigned int, bool);
+
+ /* This pass and all sub-passes are executed only if the function returns
+ true. The default implementation returns true. */
+ virtual bool gate (function *fun);
+
+ /* This is the code to run. If this is not overridden, then there should
+ be sub-passes otherwise this pass does nothing.
+ The return value contains TODOs to execute in addition to those in
+ TODO_flags_finish. */
+ virtual unsigned int execute (function *fun);
+
+protected:
+ opt_pass (const pass_data&, gcc::context *);
+
+public:
+ /* A list of sub-passes to run, dependent on gate predicate. */
+ opt_pass *sub;
+
+ /* Next in the list of passes to run, independent of gate predicate. */
+ opt_pass *next;
+
+ /* Static pass number, used as a fragment of the dump file name. */
+ int static_pass_number;
+
+protected:
+ gcc::context *m_ctxt;
+};
+
+/* Description of GIMPLE pass. */
+class gimple_opt_pass : public opt_pass
+{
+protected:
+ gimple_opt_pass (const pass_data& data, gcc::context *ctxt)
+ : opt_pass (data, ctxt)
+ {
+ }
+};
+
+/* Description of RTL pass. */
+class rtl_opt_pass : public opt_pass
+{
+protected:
+ rtl_opt_pass (const pass_data& data, gcc::context *ctxt)
+ : opt_pass (data, ctxt)
+ {
+ }
+};
+
+struct varpool_node;
+struct cgraph_node;
+struct lto_symtab_encoder_d;
+
+/* Description of IPA pass with generate summary, write, execute, read and
+ transform stages. */
+class ipa_opt_pass_d : public opt_pass
+{
+public:
+ /* IPA passes can analyze function body and variable initializers
+ using this hook and produce summary. */
+ void (*generate_summary) (void);
+
+ /* This hook is used to serialize IPA summaries on disk. */
+ void (*write_summary) (void);
+
+ /* This hook is used to deserialize IPA summaries from disk. */
+ void (*read_summary) (void);
+
+ /* This hook is used to serialize IPA optimization summaries on disk. */
+ void (*write_optimization_summary) (void);
+
+ /* This hook is used to deserialize IPA summaries from disk. */
+ void (*read_optimization_summary) (void);
+
+ /* Hook to convert gimple stmt uids into true gimple statements. The second
+ parameter is an array of statements indexed by their uid. */
+ void (*stmt_fixup) (struct cgraph_node *, gimple **);
+
+ /* Results of interprocedural propagation of an IPA pass is applied to
+ function body via this hook. */
+ unsigned int function_transform_todo_flags_start;
+ unsigned int (*function_transform) (struct cgraph_node *);
+ void (*variable_transform) (varpool_node *);
+
+protected:
+ ipa_opt_pass_d (const pass_data& data, gcc::context *ctxt,
+ void (*generate_summary) (void),
+ void (*write_summary) (void),
+ void (*read_summary) (void),
+ void (*write_optimization_summary) (void),
+ void (*read_optimization_summary) (void),
+ void (*stmt_fixup) (struct cgraph_node *, gimple **),
+ unsigned int function_transform_todo_flags_start,
+ unsigned int (*function_transform) (struct cgraph_node *),
+ void (*variable_transform) (varpool_node *))
+ : opt_pass (data, ctxt),
+ generate_summary (generate_summary),
+ write_summary (write_summary),
+ read_summary (read_summary),
+ write_optimization_summary (write_optimization_summary),
+ read_optimization_summary (read_optimization_summary),
+ stmt_fixup (stmt_fixup),
+ function_transform_todo_flags_start (function_transform_todo_flags_start),
+ function_transform (function_transform),
+ variable_transform (variable_transform)
+ {
+ }
+};
+
+/* Description of simple IPA pass. Simple IPA passes have just one execute
+ hook. */
+class simple_ipa_opt_pass : public opt_pass
+{
+protected:
+ simple_ipa_opt_pass (const pass_data& data, gcc::context *ctxt)
+ : opt_pass (data, ctxt)
+ {
+ }
+};
+
+/* Pass properties. */
+#define PROP_gimple_any (1 << 0) /* entire gimple grammar */
+#define PROP_gimple_lcf (1 << 1) /* lowered control flow */
+#define PROP_gimple_leh (1 << 2) /* lowered eh */
+#define PROP_cfg (1 << 3)
+#define PROP_objsz (1 << 4) /* object sizes computed */
+#define PROP_ssa (1 << 5)
+#define PROP_no_crit_edges (1 << 6)
+#define PROP_rtl (1 << 7)
+#define PROP_gimple_lomp (1 << 8) /* lowered OpenMP directives */
+#define PROP_cfglayout (1 << 9) /* cfglayout mode on RTL */
+#define PROP_gimple_lcx (1 << 10) /* lowered complex */
+#define PROP_loops (1 << 11) /* preserve loop structures */
+#define PROP_gimple_lvec (1 << 12) /* lowered vector */
+#define PROP_gimple_eomp (1 << 13) /* no OpenMP directives */
+#define PROP_gimple_lva (1 << 14) /* No va_arg internal function. */
+#define PROP_gimple_opt_math (1 << 15) /* Disable canonicalization
+ of math functions; the
+ current choices have
+ been optimized. */
+#define PROP_gimple_lomp_dev (1 << 16) /* done omp_device_lower */
+#define PROP_rtl_split_insns (1 << 17) /* RTL has insns split. */
+#define PROP_loop_opts_done (1 << 18) /* SSA loop optimizations
+ have completed. */
+
+#define PROP_gimple \
+ (PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_lomp)
+
+/* To-do flags. */
+#define TODO_do_not_ggc_collect (1 << 1)
+#define TODO_cleanup_cfg (1 << 5)
+#define TODO_verify_il (1 << 6)
+#define TODO_dump_symtab (1 << 7)
+#define TODO_remove_functions (1 << 8)
+#define TODO_rebuild_frequencies (1 << 9)
+
+/* To-do flags for calls to update_ssa. */
+
+/* Update the SSA form inserting PHI nodes for newly exposed symbols
+ and virtual names marked for updating. When updating real names,
+ only insert PHI nodes for a real name O_j in blocks reached by all
+ the new and old definitions for O_j. If the iterated dominance
+ frontier for O_j is not pruned, we may end up inserting PHI nodes
+ in blocks that have one or more edges with no incoming definition
+ for O_j. This would lead to uninitialized warnings for O_j's
+ symbol. */
+#define TODO_update_ssa (1 << 11)
+
+/* Update the SSA form without inserting any new PHI nodes at all.
+ This is used by passes that have either inserted all the PHI nodes
+ themselves or passes that need only to patch use-def and def-def
+ chains for virtuals (e.g., DCE). */
+#define TODO_update_ssa_no_phi (1 << 12)
+
+/* Insert PHI nodes everywhere they are needed. No pruning of the
+ IDF is done. This is used by passes that need the PHI nodes for
+ O_j even if it means that some arguments will come from the default
+ definition of O_j's symbol.
+
+ WARNING: If you need to use this flag, chances are that your pass
+ may be doing something wrong. Inserting PHI nodes for an old name
+ where not all edges carry a new replacement may lead to silent
+ codegen errors or spurious uninitialized warnings. */
+#define TODO_update_ssa_full_phi (1 << 13)
+
+/* Passes that update the SSA form on their own may want to delegate
+ the updating of virtual names to the generic updater. Since FUD
+ chains are easier to maintain, this simplifies the work they need
+ to do. NOTE: If this flag is used, any OLD->NEW mappings for real
+ names are explicitly destroyed and only the symbols marked for
+ renaming are processed. */
+#define TODO_update_ssa_only_virtuals (1 << 14)
+
+/* Some passes leave unused local variables that can be removed from
+ cfun->local_decls. This reduces the size of dump files
+ and the memory footprint for VAR_DECLs. */
+#define TODO_remove_unused_locals (1 << 15)
+
+/* Call df_finish at the end of the pass. This is done after all of
+ the dumpers have been allowed to run so that they have access to
+ the instance before it is destroyed. */
+#define TODO_df_finish (1 << 17)
+
+/* Call df_verify at the end of the pass if checking is enabled. */
+#define TODO_df_verify (1 << 18)
+
+/* Internally used for the first instance of a pass. */
+#define TODO_mark_first_instance (1 << 19)
+
+/* Rebuild aliasing info. */
+#define TODO_rebuild_alias (1 << 20)
+
+/* Rebuild the addressable-vars bitmap and do register promotion. */
+#define TODO_update_address_taken (1 << 21)
+
+/* Rebuild the callgraph edges. */
+#define TODO_rebuild_cgraph_edges (1 << 22)
+
+/* Release function body and stop pass manager. */
+#define TODO_discard_function (1 << 23)
+
+/* Internally used in execute_function_todo(). */
+#define TODO_update_ssa_any \
+ (TODO_update_ssa \
+ | TODO_update_ssa_no_phi \
+ | TODO_update_ssa_full_phi \
+ | TODO_update_ssa_only_virtuals)
+
+#define TODO_verify_all TODO_verify_il
+
+/* To-do flags for pending_TODOs. */
+
+/* Tell the next scalar cleanup pass that there is
+ work for it to do. */
+#define PENDING_TODO_force_next_scalar_cleanup (1 << 1)
+
+/* Register pass info. */
+
+enum pass_positioning_ops
+{
+ PASS_POS_INSERT_AFTER, /* Insert after the reference pass. */
+ PASS_POS_INSERT_BEFORE, /* Insert before the reference pass. */
+ PASS_POS_REPLACE /* Replace the reference pass. */
+};
+
+struct register_pass_info
+{
+ opt_pass *pass; /* New pass to register. */
+ const char *reference_pass_name; /* Name of the reference pass for hooking
+ up the new pass. */
+ int ref_pass_instance_number; /* Insert the pass at the specified
+ instance number of the reference pass.
+ Do it for every instance if it is 0. */
+ enum pass_positioning_ops pos_op; /* how to insert the new pass. */
+};
+
+/* Registers a new pass. Either fill out the register_pass_info or specify
+ the individual parameters. The pass object is expected to have been
+ allocated using operator new and the pass manager takes the ownership of
+ the pass object. */
+extern void register_pass (register_pass_info *);
+extern void register_pass (opt_pass* pass, pass_positioning_ops pos,
+ const char* ref_pass_name, int ref_pass_inst_number);
+
+extern gimple_opt_pass *make_pass_asan (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_asan_O0 (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tsan (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tsan_O0 (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sancov (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sancov_O0 (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_cf (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_refactor_eh (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_eh (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_eh_dispatch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_resx (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_build_cfg (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_early_tree_profile (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_cleanup_eh (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sra (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sra_early (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tail_recursion (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tail_calls (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_fix_loops (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tree_loop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tree_no_loop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tree_loop_init (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_loop_versioning (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lim (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_linterchange (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tree_unswitch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_loop_split (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_loop_jam (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_predcom (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_iv_canon (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_scev_cprop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_empty_loop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_graphite (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_graphite_transforms (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_if_conversion (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_if_to_switch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_loop_distribution (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_vectorize (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_simduid_cleanup (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_slp_vectorize (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_complete_unroll (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_complete_unrolli (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_pre_slp_scalar_cleanup (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_parallelize_loops (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_loop_prefetch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_iv_optimize (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tree_loop_done (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ch_vect (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ccp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_split_paths (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_build_ssa (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_build_alias (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_build_ealias (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_dominator (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_dce (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_cd_dce (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_call_cdce (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_merge_phi (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_thread_jumps (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_thread_jumps_full (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_early_thread_jumps (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_split_crit_edges (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_laddress (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_pre (gcc::context *ctxt);
+extern unsigned int tail_merge_optimize (bool);
+extern gimple_opt_pass *make_pass_profile (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_strip_predict_hints (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_complex_O0 (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_complex (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_switch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_switch_O0 (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_vector (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_vector_ssa (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_omp_oacc_kernels_decompose (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_omp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_diagnose_omp_blocks (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_expand_omp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_expand_omp_ssa (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_omp_target_link (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_oacc_loop_designation (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_omp_oacc_neuter_broadcast (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_oacc_device_lower (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_omp_device_lower (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_early_object_sizes (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_access (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_printf (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_recursion (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_fold_builtins (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_post_ipa_warn (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_stdarg (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_early_warn_uninitialized (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_late_warn_uninitialized (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_cse_reciprocals (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_cse_sincos (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_optimize_bswap (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_store_merging (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_optimize_widening_mul (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_function_return (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_function_noreturn (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_cselim (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_phiopt (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_forwprop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_phiprop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tree_ifcombine (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_dse (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_nrv (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_rename_ssa_copies (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sink_code (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_fre (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_check_data_deps (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_copy_prop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_isolate_erroneous_paths (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_early_vrp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_vrp (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_uncprop (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_return_slot (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_reassoc (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_rebuild_cgraph_edges (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_remove_cgraph_callee_edges (gcc::context
+ *ctxt);
+extern gimple_opt_pass *make_pass_build_cgraph_edges (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_local_pure_const (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_nothrow (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tracer (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_restrict (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_unused_result (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_diagnose_tm_blocks (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_tm (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tm_init (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tm_mark (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tm_memopt (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_tm_edges (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_split_functions (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_feedback_split_functions (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_strength_reduction (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_vtable_verify (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ubsan (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sanopt (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_oacc_kernels (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_oacc (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_oacc_kernels (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_warn_nonnull_compare (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_sprintf_length (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_walloca (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_modref (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_coroutine_lower_builtins (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_coroutine_early_expand_ifns (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_adjust_alignment (gcc::context *ctxt);
+
+/* IPA Passes */
+extern simple_ipa_opt_pass *make_pass_ipa_lower_emutls (gcc::context *ctxt);
+extern simple_ipa_opt_pass
+ *make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_tree_profile (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_auto_profile (gcc::context *ctxt);
+
+extern simple_ipa_opt_pass *make_pass_build_ssa_passes (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_local_optimization_passes (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_remove_symbols (gcc::context *ctxt);
+
+extern ipa_opt_pass_d *make_pass_analyzer (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_whole_program_visibility (gcc::context
+ *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_increase_alignment (gcc::context
+ *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_fn_summary (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_inline (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_free_lang_data (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_free_fn_summary (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_cp (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_sra (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_icf (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_odr (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_target_clone (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_dispatcher_calls (gcc::context *ctxt);
+extern simple_ipa_opt_pass *make_pass_omp_simd_clone (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_profile (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_cdtor_merge (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_single_use (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_comdats (gcc::context *ctxt);
+extern ipa_opt_pass_d *make_pass_ipa_modref (gcc::context *ctxt);
+
+extern gimple_opt_pass *make_pass_cleanup_cfg_post_optimizing (gcc::context
+ *ctxt);
+extern gimple_opt_pass *make_pass_fixup_cfg (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_backprop (gcc::context *ctxt);
+
+extern rtl_opt_pass *make_pass_expand (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_instantiate_virtual_regs (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_fwprop (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_fwprop_addr (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_jump (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_jump2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_lower_subreg (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_cse (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_fast_rtl_dce (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_ud_rtl_dce (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_dce (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_dse1 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_dse2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_dse3 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_cprop (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_pre (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_hoist (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_store_motion (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_cse_after_global_opts (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_ifcvt (gcc::context *ctxt);
+
+extern rtl_opt_pass *make_pass_into_cfg_layout_mode (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_outof_cfg_layout_mode (gcc::context *ctxt);
+
+extern rtl_opt_pass *make_pass_loop2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_loop_init (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_move_loop_invariants (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_unroll_loops (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_doloop (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_loop_done (gcc::context *ctxt);
+
+extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_web (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_cse2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_df_initialize_opt (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_df_initialize_no_opt (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_reginfo_init (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_inc_dec (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_stack_ptr_mod (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_initialize_regs (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_combine (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_if_after_combine (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_jump_after_combine (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_ree (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_partition_blocks (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_match_asm_constraints (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_split_all_insns (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_fast_rtl_byte_dce (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_lower_subreg3 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_mode_switching (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_sms (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_sched (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_live_range_shrinkage (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_early_remat (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_ira (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_reload (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_clean_state (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_branch_prob (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_value_profile_transformations (gcc::context
+ *ctxt);
+extern rtl_opt_pass *make_pass_postreload_cse (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_gcse2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_split_after_reload (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_thread_prologue_and_epilogue (gcc::context
+ *ctxt);
+extern rtl_opt_pass *make_pass_zero_call_used_regs (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_stack_adjustments (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_sched_fusion (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_peephole2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_if_after_reload (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_regrename (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_cprop_hardreg (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_reorder_blocks (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_leaf_regs (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_split_before_sched2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_compare_elim_after_reload (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_sched2 (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_stack_regs (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_stack_regs_run (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_df_finish (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_compute_alignments (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_duplicate_computed_gotos (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_variable_tracking (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_free_cfg (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_machine_reorg (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_cleanup_barriers (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_delay_slots (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_split_for_shorten_branches (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_split_before_regstack (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_convert_to_eh_region_ranges (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_shorten_branches (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_set_nothrow_function_flags (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_dwarf2_frame (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_final (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_rtl_seqabstr (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_release_ssa_names (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_early_inline (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_local_fn_summary (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_update_address_taken (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_convert_switch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_lower_vaarg (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_gimple_isel (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_harden_compares (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_harden_conditional_branches (gcc::context
+ *ctxt);
+
+/* Current optimization pass. */
+extern opt_pass *current_pass;
+
+extern bool execute_one_pass (opt_pass *);
+extern void execute_pass_list (function *, opt_pass *);
+extern void execute_ipa_pass_list (opt_pass *);
+extern void execute_ipa_summary_passes (ipa_opt_pass_d *);
+extern void execute_all_ipa_transforms (bool);
+extern void execute_all_ipa_stmt_fixups (struct cgraph_node *, gimple **);
+extern bool pass_init_dump_file (opt_pass *);
+extern void pass_fini_dump_file (opt_pass *);
+extern void emergency_dump_function (void);
+
+extern void print_current_pass (FILE *);
+extern void debug_pass (void);
+extern void ipa_write_summaries (void);
+extern void ipa_write_optimization_summaries (struct lto_symtab_encoder_d *);
+extern void ipa_read_summaries (void);
+extern void ipa_read_optimization_summaries (void);
+extern void register_one_dump_file (opt_pass *);
+extern bool function_called_by_processed_nodes_p (void);
+
+/* Declare for plugins. */
+extern void do_per_function_toporder (void (*) (function *, void *), void *);
+
+extern void disable_pass (const char *);
+extern void enable_pass (const char *);
+extern void dump_passes (void);
+
+#endif /* GCC_TREE_PASS_H */
diff --git a/support/cpp/gcc/tree-pretty-print.h b/support/cpp/gcc/tree-pretty-print.h
new file mode 100644
index 000000000..89d2641a3
--- /dev/null
+++ b/support/cpp/gcc/tree-pretty-print.h
@@ -0,0 +1,60 @@
+/* Various declarations for language-independent pretty-print
+ subroutines that are only for use in the compilers proper and not
+ the driver or other programs.
+ Copyright (C) 2002-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_TREE_PRETTY_PRINT_H
+#define GCC_TREE_PRETTY_PRINT_H
+
+#include "pretty-print.h"
+
+#define pp_unsupported_tree(PP, T) \
+ pp_verbatim (PP, "%qs not supported by %s", \
+ get_tree_code_name (TREE_CODE (T)), __FUNCTION__)
+
+#define pp_ti_abstract_origin(TI) ((tree *) (TI)->x_data)
+
+
+extern void debug_generic_expr (tree);
+extern void debug_generic_stmt (tree);
+extern void debug_tree_chain (tree);
+extern void print_generic_decl (FILE *, tree, dump_flags_t);
+extern void print_generic_stmt (FILE *, tree, dump_flags_t = TDF_NONE);
+extern void print_generic_stmt_indented (FILE *, tree, dump_flags_t, int);
+extern void print_generic_expr (FILE *, tree, dump_flags_t = TDF_NONE);
+extern char *print_generic_expr_to_str (tree);
+extern void dump_omp_clauses (pretty_printer *, tree, int, dump_flags_t,
+ bool = true);
+// sdcpp extern void dump_omp_atomic_memory_order (pretty_printer *,
+// sdcpp enum omp_memory_order);
+extern void dump_omp_loop_non_rect_expr (pretty_printer *, tree, int,
+ dump_flags_t);
+extern int dump_generic_node (pretty_printer *, tree, int, dump_flags_t, bool);
+extern void print_declaration (pretty_printer *, tree, int, dump_flags_t);
+// sdcpp extern int op_code_prio (enum tree_code);
+extern int op_prio (const_tree);
+// sdcpp extern const char *op_symbol_code (enum tree_code);
+extern void pretty_print_string (pretty_printer *, const char *, size_t);
+extern void print_call_name (pretty_printer *, tree, dump_flags_t);
+extern void pp_tree_identifier (pretty_printer *, tree);
+extern void dump_function_header (FILE *, tree, dump_flags_t);
+extern void pp_double_int (pretty_printer *pp, double_int d, bool uns);
+extern void dump_location (pretty_printer *buffer, location_t loc);
+
+#endif /* ! GCC_TREE_PRETTY_PRINT_H */
diff --git a/support/cpp/gcc/tree-ssa-alias.h b/support/cpp/gcc/tree-ssa-alias.h
new file mode 100644
index 000000000..a1933ff48
--- /dev/null
+++ b/support/cpp/gcc/tree-ssa-alias.h
@@ -0,0 +1,211 @@
+/* Tree based alias analysis and alias oracle.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
+ Contributed by Richard Guenther <rguenther@suse.de>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, 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/>. */
+
+#if 0 // sdcpp ndef TREE_SSA_ALIAS_H
+#define TREE_SSA_ALIAS_H
+
+/* The points-to solution.
+
+ The points-to solution is a union of pt_vars and the abstract
+ sets specified by the flags. */
+struct GTY(()) pt_solution
+{
+ /* Nonzero if points-to analysis couldn't determine where this pointer
+ is pointing to. */
+ unsigned int anything : 1;
+
+ /* Nonzero if the points-to set includes any global memory. Note that
+ even if this is zero pt_vars can still include global variables. */
+ unsigned int nonlocal : 1;
+
+ /* Nonzero if the points-to set includes the local escaped solution by
+ reference. */
+ unsigned int escaped : 1;
+
+ /* Nonzero if the points-to set includes the IPA escaped solution by
+ reference. */
+ unsigned int ipa_escaped : 1;
+
+ /* Nonzero if the points-to set includes 'nothing', the points-to set
+ includes memory at address NULL. */
+ unsigned int null : 1;
+
+ /* Nonzero if the vars bitmap includes a variable included in 'nonlocal'. */
+ unsigned int vars_contains_nonlocal : 1;
+ /* Nonzero if the vars bitmap includes a variable included in 'escaped'. */
+ unsigned int vars_contains_escaped : 1;
+ /* Nonzero if the vars bitmap includes a anonymous heap variable that
+ escaped the function and thus became global. */
+ unsigned int vars_contains_escaped_heap : 1;
+ /* Nonzero if the vars bitmap includes a anonymous variable used to
+ represent storage pointed to by a restrict qualified pointer. */
+ unsigned int vars_contains_restrict : 1;
+ /* Nonzero if the vars bitmap includes an interposable variable. */
+ unsigned int vars_contains_interposable : 1;
+
+ /* Set of variables that this pointer may point to. */
+ bitmap vars;
+};
+
+
+/* Simplified and cached information about a memory reference tree.
+ Used by the alias-oracle internally and externally in alternate
+ interfaces. */
+class ao_ref
+{
+public:
+ /* The original full memory reference tree or NULL_TREE if that is
+ not available. */
+ tree ref;
+
+ /* The following fields are the decomposed reference as returned
+ by get_ref_base_and_extent. */
+ /* The base object of the memory reference or NULL_TREE if all of
+ the following fields are not yet computed. */
+ tree base;
+ /* The offset relative to the base. */
+ poly_int64 offset;
+ /* The size of the access. */
+ poly_int64 size;
+ /* The maximum possible extent of the access or -1 if unconstrained. */
+ poly_int64 max_size;
+
+ /* The alias set of the access or -1 if not yet computed. */
+ alias_set_type ref_alias_set;
+
+ /* The alias set of the base object or -1 if not yet computed. */
+ alias_set_type base_alias_set;
+
+ /* Whether the memory is considered a volatile access. */
+ bool volatile_p;
+
+ bool max_size_known_p () const;
+};
+
+/* Return true if the maximum size is known, rather than the special -1
+ marker. */
+
+inline bool
+ao_ref::max_size_known_p () const
+{
+ return known_size_p (max_size);
+}
+
+/* In tree-ssa-alias.cc */
+extern void ao_ref_init (ao_ref *, tree);
+extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
+extern void ao_ref_init_from_ptr_and_range (ao_ref *, tree, bool,
+ poly_int64, poly_int64,
+ poly_int64);
+extern tree ao_ref_base (ao_ref *);
+extern alias_set_type ao_ref_alias_set (ao_ref *);
+extern alias_set_type ao_ref_base_alias_set (ao_ref *);
+extern tree ao_ref_alias_ptr_type (ao_ref *);
+extern tree ao_ref_base_alias_ptr_type (ao_ref *);
+extern bool ao_ref_alignment (ao_ref *, unsigned int *,
+ unsigned HOST_WIDE_INT *);
+extern bool ptr_deref_may_alias_global_p (tree, bool);
+extern bool ptr_derefs_may_alias_p (tree, tree);
+extern bool ptrs_compare_unequal (tree, tree);
+extern bool ref_may_alias_global_p (tree, bool);
+extern bool ref_may_alias_global_p (ao_ref *, bool);
+extern bool refs_may_alias_p (tree, tree, bool = true);
+extern bool refs_may_alias_p_1 (ao_ref *, ao_ref *, bool);
+extern bool refs_anti_dependent_p (tree, tree);
+extern bool refs_output_dependent_p (tree, tree);
+extern bool ref_maybe_used_by_stmt_p (gimple *, tree, bool = true);
+extern bool ref_maybe_used_by_stmt_p (gimple *, ao_ref *, bool = true);
+extern bool stmt_may_clobber_global_p (gimple *, bool);
+extern bool stmt_may_clobber_ref_p (gimple *, tree, bool = true);
+extern bool stmt_may_clobber_ref_p_1 (gimple *, ao_ref *, bool = true);
+extern bool call_may_clobber_ref_p (gcall *, tree, bool = true);
+extern bool call_may_clobber_ref_p_1 (gcall *, ao_ref *, bool = true);
+extern bool stmt_kills_ref_p (gimple *, tree);
+extern bool stmt_kills_ref_p (gimple *, ao_ref *);
+enum translate_flags
+ { TR_TRANSLATE, TR_VALUEIZE_AND_DISAMBIGUATE, TR_DISAMBIGUATE };
+extern tree get_continuation_for_phi (gimple *, ao_ref *, bool,
+ unsigned int &, bitmap *, bool,
+ void *(*)(ao_ref *, tree, void *,
+ translate_flags *),
+ void *, translate_flags
+ = TR_VALUEIZE_AND_DISAMBIGUATE);
+extern void *walk_non_aliased_vuses (ao_ref *, tree, bool,
+ void *(*)(ao_ref *, tree, void *),
+ void *(*)(ao_ref *, tree, void *,
+ translate_flags *),
+ tree (*)(tree), unsigned &, void *);
+extern int walk_aliased_vdefs (ao_ref *, tree,
+ bool (*)(ao_ref *, tree, void *),
+ void *, bitmap *,
+ bool *function_entry_reached = NULL,
+ unsigned int limit = 0);
+extern void dump_alias_info (FILE *);
+extern void debug_alias_info (void);
+extern void dump_points_to_solution (FILE *, struct pt_solution *);
+extern void debug (pt_solution &ref);
+extern void debug (pt_solution *ptr);
+extern void dump_points_to_info_for (FILE *, tree);
+extern void debug_points_to_info_for (tree);
+extern void dump_alias_stats (FILE *);
+
+
+/* In tree-ssa-structalias.cc */
+extern unsigned int compute_may_aliases (void);
+extern bool pt_solution_empty_p (const pt_solution *);
+extern bool pt_solution_singleton_or_null_p (struct pt_solution *, unsigned *);
+extern bool pt_solution_includes_global (struct pt_solution *, bool);
+extern bool pt_solution_includes (struct pt_solution *, const_tree);
+extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
+extern void pt_solution_reset (struct pt_solution *);
+extern void pt_solution_set (struct pt_solution *, bitmap, bool);
+extern void pt_solution_set_var (struct pt_solution *, tree);
+
+extern void dump_pta_stats (FILE *);
+
+extern GTY(()) struct pt_solution ipa_escaped_pt;
+
+/* Return true, if the two ranges [POS1, SIZE1] and [POS2, SIZE2]
+ overlap. SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the
+ range is open-ended. Otherwise return false. */
+
+static inline bool
+ranges_overlap_p (HOST_WIDE_INT pos1,
+ unsigned HOST_WIDE_INT size1,
+ HOST_WIDE_INT pos2,
+ unsigned HOST_WIDE_INT size2)
+{
+ if (size1 == 0 || size2 == 0)
+ return false;
+ if (pos1 >= pos2
+ && (size2 == (unsigned HOST_WIDE_INT)-1
+ || pos1 < (pos2 + (HOST_WIDE_INT) size2)))
+ return true;
+ if (pos2 >= pos1
+ && (size1 == (unsigned HOST_WIDE_INT)-1
+ || pos2 < (pos1 + (HOST_WIDE_INT) size1)))
+ return true;
+
+ return false;
+}
+
+
+
+#endif /* TREE_SSA_ALIAS_H */
diff --git a/support/cpp/gcc/tree-vrp.h b/support/cpp/gcc/tree-vrp.h
new file mode 100644
index 000000000..16f3c3ad1
--- /dev/null
+++ b/support/cpp/gcc/tree-vrp.h
@@ -0,0 +1,70 @@
+/* Support routines for Value Range Propagation (VRP).
+ Copyright (C) 2016-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/>. */
+
+#if 0 // sdcpp ndef GCC_TREE_VRP_H
+#define GCC_TREE_VRP_H
+
+#include "value-range.h"
+
+struct assert_info
+{
+ /* Predicate code for the ASSERT_EXPR. Must be COMPARISON_CLASS_P. */
+ enum tree_code comp_code;
+
+ /* Name to register the assert for. */
+ tree name;
+
+ /* Value being compared against. */
+ tree val;
+
+ /* Expression to compare. */
+ tree expr;
+};
+
+extern void register_edge_assert_for (tree, edge, enum tree_code,
+ tree, tree, vec<assert_info> &);
+extern bool stmt_interesting_for_vrp (gimple *);
+extern bool infer_value_range (gimple *, tree, tree_code *, tree *);
+
+extern bool range_int_cst_p (const value_range *);
+
+extern int compare_values (tree, tree);
+extern int compare_values_warnv (tree, tree, bool *);
+extern int operand_less_p (tree, tree);
+
+void range_fold_unary_expr (value_range *, enum tree_code, tree type,
+ const value_range *, tree op0_type);
+void range_fold_binary_expr (value_range *, enum tree_code, tree type,
+ const value_range *, const value_range *);
+
+extern enum value_range_kind intersect_range_with_nonzero_bits
+ (enum value_range_kind, wide_int *, wide_int *, const wide_int &, signop);
+
+extern bool find_case_label_range (gswitch *, tree, tree, size_t *, size_t *);
+extern tree find_case_label_range (gswitch *, const irange *vr);
+extern bool find_case_label_index (gswitch *, size_t, tree, size_t *);
+extern bool overflow_comparison_p (tree_code, tree, tree, bool, tree *);
+extern tree get_single_symbol (tree, bool *, tree *);
+extern void maybe_set_nonzero_bits (edge, tree);
+extern wide_int masked_increment (const wide_int &val_in, const wide_int &mask,
+ const wide_int &sgnbit, unsigned int prec);
+
+extern unsigned int execute_ranger_vrp (struct function *fun,
+ bool warn_array_bounds_p = false);
+#endif /* GCC_TREE_VRP_H */
diff --git a/support/cpp/gcc/tree.def b/support/cpp/gcc/tree.def
new file mode 100644
index 000000000..62650b693
--- /dev/null
+++ b/support/cpp/gcc/tree.def
@@ -0,0 +1,1480 @@
+/* This file contains the definitions and documentation for the
+ tree codes used in GCC.
+ 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/>. */
+
+
+/* For tcc_references, tcc_expression, tcc_comparison, tcc_unary,
+ tcc_binary, and tcc_statement nodes, which use struct tree_exp, the
+ 4th element is the number of argument slots to allocate. This
+ determines the size of the tree node object. Other nodes use
+ different structures, and the size is determined by the tree_union
+ member structure; the 4th element should be zero. Languages that
+ define language-specific tcc_exceptional or tcc_constant codes must
+ define the tree_size langhook to say how big they are.
+
+ These tree codes have been sorted so that the macros in tree.h that
+ check for various tree codes are optimized into range checks. This
+ gives a measurable performance improvement. When adding a new
+ code, consider its placement in relation to the other codes. */
+
+/* Any erroneous construct is parsed into a node of this type.
+ This type of node is accepted without complaint in all contexts
+ by later parsing activities, to avoid multiple error messages
+ for one error.
+ No fields in these nodes are used except the TREE_CODE. */
+DEFTREECODE (ERROR_MARK, "error_mark", tcc_exceptional, 0)
+
+/* Used to represent a name (such as, in the DECL_NAME of a decl node).
+ Internally it looks like a STRING_CST node.
+ There is only one IDENTIFIER_NODE ever made for any particular name.
+ Use `get_identifier' to get it (or create it, the first time). */
+DEFTREECODE (IDENTIFIER_NODE, "identifier_node", tcc_exceptional, 0)
+
+/* Has the TREE_VALUE and TREE_PURPOSE fields. */
+/* These nodes are made into lists by chaining through the
+ TREE_CHAIN field. The elements of the list live in the
+ TREE_VALUE fields, while TREE_PURPOSE fields are occasionally
+ used as well to get the effect of Lisp association lists. */
+DEFTREECODE (TREE_LIST, "tree_list", tcc_exceptional, 0)
+
+/* These nodes contain an array of tree nodes. */
+DEFTREECODE (TREE_VEC, "tree_vec", tcc_exceptional, 0)
+
+/* A symbol binding block. These are arranged in a tree,
+ where the BLOCK_SUBBLOCKS field contains a chain of subblocks
+ chained through the BLOCK_CHAIN field.
+ BLOCK_SUPERCONTEXT points to the parent block.
+ For a block which represents the outermost scope of a function, it
+ points to the FUNCTION_DECL node.
+ BLOCK_VARS points to a chain of decl nodes.
+ BLOCK_CHAIN points to the next BLOCK at the same level.
+ BLOCK_ABSTRACT_ORIGIN points to the original (abstract) tree node which
+ this block is an instance of, or else is NULL to indicate that this
+ block is not an instance of anything else. When non-NULL, the value
+ could either point to another BLOCK node or it could point to a
+ FUNCTION_DECL node (e.g. in the case of a block representing the
+ outermost scope of a particular inlining of a function).
+ TREE_ASM_WRITTEN is nonzero if the block was actually referenced
+ in the generated assembly. */
+DEFTREECODE (BLOCK, "block", tcc_exceptional, 0)
+
+/* Each data type is represented by a tree node whose code is one of
+ the following: */
+/* Each node that represents a data type has a component TYPE_SIZE
+ that evaluates either to a tree that is a (potentially non-constant)
+ expression representing the type size in bits, or to a null pointer
+ when the size of the type is unknown (for example, for incomplete
+ types such as arrays of unspecified bound).
+ The TYPE_MODE contains the machine mode for values of this type.
+ The TYPE_POINTER_TO field contains a type for a pointer to this type,
+ or zero if no such has been created yet.
+ The TYPE_NEXT_VARIANT field is used to chain together types
+ that are variants made by type modifiers such as "const" and "volatile".
+ The TYPE_MAIN_VARIANT field, in any member of such a chain,
+ points to the start of the chain.
+ The TYPE_NAME field contains info on the name used in the program
+ for this type (for GDB symbol table output). It is either a
+ TYPE_DECL node, for types that are typedefs, or an IDENTIFIER_NODE
+ in the case of structs, unions or enums that are known with a tag,
+ or zero for types that have no special name.
+ The TYPE_CONTEXT for any sort of type which could have a name or
+ which could have named members (e.g. tagged types in C/C++) will
+ point to the node which represents the scope of the given type, or
+ will be NULL_TREE if the type has "file scope". For most types, this
+ will point to a BLOCK node or a FUNCTION_DECL node, but it could also
+ point to a FUNCTION_TYPE node (for types whose scope is limited to the
+ formal parameter list of some function type specification) or it
+ could point to a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE node
+ (for C++ "member" types).
+ For non-tagged-types, TYPE_CONTEXT need not be set to anything in
+ particular, since any type which is of some type category (e.g.
+ an array type or a function type) which cannot either have a name
+ itself or have named members doesn't really have a "scope" per se.
+ The TYPE_STUB_DECL field is used as a forward-references to names for
+ ENUMERAL_TYPE, RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE nodes;
+ see below. */
+
+/* The ordering of the following codes is optimized for the checking
+ macros in tree.h. Changing the order will degrade the speed of the
+ compiler. OFFSET_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, INTEGER_TYPE,
+ REAL_TYPE, POINTER_TYPE. */
+
+/* An offset is a pointer relative to an object.
+ The TREE_TYPE field is the type of the object at the offset.
+ The TYPE_OFFSET_BASETYPE points to the node for the type of object
+ that the offset is relative to. */
+DEFTREECODE (OFFSET_TYPE, "offset_type", tcc_type, 0)
+
+/* C enums. The type node looks just like an INTEGER_TYPE node.
+ The symbols for the values of the enum type are defined by
+ CONST_DECL nodes, but the type does not point to them;
+ however, the TYPE_VALUES is a list in which each element's TREE_PURPOSE
+ is a name and the TREE_VALUE is the value (an INTEGER_CST node). */
+/* A forward reference `enum foo' when no enum named foo is defined yet
+ has zero (a null pointer) in its TYPE_SIZE. The tag name is in
+ the TYPE_NAME field. If the type is later defined, the normal
+ fields are filled in.
+ RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE forward refs are
+ treated similarly. */
+DEFTREECODE (ENUMERAL_TYPE, "enumeral_type", tcc_type, 0)
+
+/* Boolean type (true or false are the only values). Looks like an
+ INTEGRAL_TYPE. */
+DEFTREECODE (BOOLEAN_TYPE, "boolean_type", tcc_type, 0)
+
+/* Integer types in all languages, including char in C.
+ Also used for sub-ranges of other discrete types.
+ Has components TYPE_MIN_VALUE, TYPE_MAX_VALUE (expressions, inclusive)
+ and TYPE_PRECISION (number of bits used by this type). */
+DEFTREECODE (INTEGER_TYPE, "integer_type", tcc_type, 0)
+
+/* C's float and double. Different floating types are distinguished
+ by machine mode and by the TYPE_SIZE and the TYPE_PRECISION. */
+DEFTREECODE (REAL_TYPE, "real_type", tcc_type, 0)
+
+/* The ordering of the following codes is optimized for the checking
+ macros in tree.h. Changing the order will degrade the speed of the
+ compiler. POINTER_TYPE, REFERENCE_TYPE. Note that this range
+ overlaps the previous range of ordered types. */
+
+/* All pointer-to-x types have code POINTER_TYPE.
+ The TREE_TYPE points to the node for the type pointed to. */
+DEFTREECODE (POINTER_TYPE, "pointer_type", tcc_type, 0)
+
+/* A reference is like a pointer except that it is coerced
+ automatically to the value it points to. Used in C++. */
+DEFTREECODE (REFERENCE_TYPE, "reference_type", tcc_type, 0)
+
+/* The C++ decltype(nullptr) type. */
+DEFTREECODE (NULLPTR_TYPE, "nullptr_type", tcc_type, 0)
+
+/* _Fract and _Accum types in Embedded-C. Different fixed-point types
+ are distinguished by machine mode and by the TYPE_SIZE and the
+ TYPE_PRECISION. */
+DEFTREECODE (FIXED_POINT_TYPE, "fixed_point_type", tcc_type, 0)
+
+/* The ordering of the following codes is optimized for the checking
+ macros in tree.h. Changing the order will degrade the speed of the
+ compiler. COMPLEX_TYPE, VECTOR_TYPE, ARRAY_TYPE. */
+
+/* Complex number types. The TREE_TYPE field is the data type
+ of the real and imaginary parts. It must be of scalar
+ arithmetic type, not including pointer type. */
+DEFTREECODE (COMPLEX_TYPE, "complex_type", tcc_type, 0)
+
+/* Vector types. The TREE_TYPE field is the data type of the vector
+ elements. The TYPE_PRECISION field is the number of subparts of
+ the vector. */
+DEFTREECODE (VECTOR_TYPE, "vector_type", tcc_type, 0)
+
+/* The ordering of the following codes is optimized for the checking
+ macros in tree.h. Changing the order will degrade the speed of the
+ compiler. ARRAY_TYPE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE.
+ Note that this range overlaps the previous range. */
+
+/* Types of arrays. Special fields:
+ TREE_TYPE Type of an array element.
+ TYPE_DOMAIN Type to index by.
+ Its range of values specifies the array length.
+ The field TYPE_POINTER_TO (TREE_TYPE (array_type)) is always nonzero
+ and holds the type to coerce a value of that array type to in C.
+ TYPE_STRING_FLAG indicates a string (in contrast to an array of chars)
+ in languages (such as Chill) that make a distinction. */
+/* Array types in C */
+DEFTREECODE (ARRAY_TYPE, "array_type", tcc_type, 0)
+
+/* Struct in C. */
+/* Special fields:
+ TYPE_FIELDS chain of FIELD_DECLs for the fields of the struct,
+ VAR_DECLs, TYPE_DECLs and CONST_DECLs for record-scope variables,
+ types and enumerators and FUNCTION_DECLs for methods associated
+ with the type. */
+/* See the comment above, before ENUMERAL_TYPE, for how
+ forward references to struct tags are handled in C. */
+DEFTREECODE (RECORD_TYPE, "record_type", tcc_type, 0)
+
+/* Union in C. Like a struct, except that the offsets of the fields
+ will all be zero. */
+/* See the comment above, before ENUMERAL_TYPE, for how
+ forward references to union tags are handled in C. */
+DEFTREECODE (UNION_TYPE, "union_type", tcc_type, 0) /* C union type */
+
+/* Similar to UNION_TYPE, except that the expressions in DECL_QUALIFIER
+ in each FIELD_DECL determine what the union contains. The first
+ field whose DECL_QUALIFIER expression is true is deemed to occupy
+ the union. */
+DEFTREECODE (QUAL_UNION_TYPE, "qual_union_type", tcc_type, 0)
+
+/* The ordering of the following codes is optimized for the checking
+ macros in tree.h. Changing the order will degrade the speed of the
+ compiler. VOID_TYPE, FUNCTION_TYPE, METHOD_TYPE. */
+
+/* The void type in C */
+DEFTREECODE (VOID_TYPE, "void_type", tcc_type, 0)
+
+/* Type of functions. Special fields:
+ TREE_TYPE type of value returned.
+ TYPE_ARG_TYPES list of types of arguments expected.
+ this list is made of TREE_LIST nodes.
+ In this list TREE_PURPOSE can be used to indicate the default
+ value of parameter (used by C++ frontend).
+ Types of "Procedures" in languages where they are different from functions
+ have code FUNCTION_TYPE also, but then TREE_TYPE is zero or void type. */
+DEFTREECODE (FUNCTION_TYPE, "function_type", tcc_type, 0)
+
+/* METHOD_TYPE is the type of a function which takes an extra first
+ argument for "self", which is not present in the declared argument list.
+ The TREE_TYPE is the return type of the method. The TYPE_METHOD_BASETYPE
+ is the type of "self". TYPE_ARG_TYPES is the real argument list, which
+ includes the hidden argument for "self". */
+DEFTREECODE (METHOD_TYPE, "method_type", tcc_type, 0)
+
+/* This is a language-specific kind of type.
+ Its meaning is defined by the language front end.
+ layout_type does not know how to lay this out,
+ so the front-end must do so manually. */
+DEFTREECODE (LANG_TYPE, "lang_type", tcc_type, 0)
+
+/* This is for types that will use MODE_OPAQUE in the back end. They are meant
+ to be able to go in a register of some sort but are explicitly not to be
+ converted or operated on like INTEGER_TYPE. They will have size and
+ alignment information only. */
+DEFTREECODE (OPAQUE_TYPE, "opaque_type", tcc_type, 0)
+
+/* Expressions */
+
+/* First, the constants. */
+
+DEFTREECODE (VOID_CST, "void_cst", tcc_constant, 0)
+
+/* Contents are in an array of HOST_WIDE_INTs.
+
+ We often access these constants both in their native precision and
+ in wider precisions (with the constant being implicitly extended
+ according to TYPE_SIGN). In each case, the useful part of the array
+ may be as wide as the precision requires but may be shorter when all
+ of the upper bits are sign bits. The length of the array when accessed
+ in the constant's native precision is given by TREE_INT_CST_NUNITS.
+ The length of the array when accessed in wider precisions is given
+ by TREE_INT_CST_EXT_NUNITS. Each element can be obtained using
+ TREE_INT_CST_ELT.
+
+ INTEGER_CST nodes can be shared, and therefore should be considered
+ read only. They should be copied before setting a flag such as
+ TREE_OVERFLOW. If an INTEGER_CST has TREE_OVERFLOW already set,
+ it is known to be unique. INTEGER_CST nodes are created for the
+ integral types, for pointer types and for vector and float types in
+ some circumstances. */
+DEFTREECODE (INTEGER_CST, "integer_cst", tcc_constant, 0)
+
+/* Contents are given by POLY_INT_CST_COEFF. */
+DEFTREECODE (POLY_INT_CST, "poly_int_cst", tcc_constant, 0)
+
+/* Contents are in TREE_REAL_CST field. */
+DEFTREECODE (REAL_CST, "real_cst", tcc_constant, 0)
+
+/* Contents are in TREE_FIXED_CST field. */
+DEFTREECODE (FIXED_CST, "fixed_cst", tcc_constant, 0)
+
+/* Contents are in TREE_REALPART and TREE_IMAGPART fields,
+ whose contents are other constant nodes. */
+DEFTREECODE (COMPLEX_CST, "complex_cst", tcc_constant, 0)
+
+/* See generic.texi for details. */
+DEFTREECODE (VECTOR_CST, "vector_cst", tcc_constant, 0)
+
+/* Contents are TREE_STRING_LENGTH and the actual contents of the string. */
+DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0)
+
+/* Declarations. All references to names are represented as ..._DECL
+ nodes. The decls in one binding context are chained through the
+ TREE_CHAIN field. Each DECL has a DECL_NAME field which contains
+ an IDENTIFIER_NODE. (Some decls, most often labels, may have zero
+ as the DECL_NAME). DECL_CONTEXT points to the node representing
+ the context in which this declaration has its scope. For
+ FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
+ QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
+ PARM_DECL, FUNCTION_DECL, LABEL_DECL, and CONST_DECL nodes, this
+ points to either the FUNCTION_DECL for the containing function, the
+ RECORD_TYPE or UNION_TYPE for the containing type, or NULL_TREE or
+ a TRANSLATION_UNIT_DECL if the given decl has "file scope".
+ DECL_ABSTRACT_ORIGIN, if non-NULL, points to the original (abstract)
+ ..._DECL node of which this decl is an (inlined or template expanded)
+ instance.
+ The TREE_TYPE field holds the data type of the object, when relevant.
+ LABEL_DECLs have no data type. For TYPE_DECL, the TREE_TYPE field
+ contents are the type whose name is being declared.
+ The DECL_ALIGN, DECL_SIZE,
+ and DECL_MODE fields exist in decl nodes just as in type nodes.
+ They are unused in LABEL_DECL, TYPE_DECL and CONST_DECL nodes.
+
+ DECL_FIELD_BIT_OFFSET holds an integer number of bits offset for
+ the location. DECL_VOFFSET holds an expression for a variable
+ offset; it is to be multiplied by DECL_VOFFSET_UNIT (an integer).
+ These fields are relevant only in FIELD_DECLs and PARM_DECLs.
+
+ DECL_INITIAL holds the value to initialize a variable to,
+ or the value of a constant. For a function, it holds the body
+ (a node of type BLOCK representing the function's binding contour
+ and whose body contains the function's statements.) For a LABEL_DECL
+ in C, it is a flag, nonzero if the label's definition has been seen.
+
+ PARM_DECLs use a special field:
+ DECL_ARG_TYPE is the type in which the argument is actually
+ passed, which may be different from its type within the function.
+
+ FUNCTION_DECLs use four special fields:
+ DECL_ARGUMENTS holds a chain of PARM_DECL nodes for the arguments.
+ DECL_RESULT holds a RESULT_DECL node for the value of a function.
+ The DECL_RTL field is 0 for a function that returns no value.
+ (C functions returning void have zero here.)
+ The TREE_TYPE field is the type in which the result is actually
+ returned. This is usually the same as the return type of the
+ FUNCTION_DECL, but it may be a wider integer type because of
+ promotion.
+ DECL_FUNCTION_CODE is a code number that is nonzero for
+ built-in functions. Its value is an enum built_in_function
+ that says which built-in function it is.
+
+ DECL_SOURCE_FILE holds a filename string and DECL_SOURCE_LINE
+ holds a line number. In some cases these can be the location of
+ a reference, if no definition has been seen.
+
+ DECL_ABSTRACT is nonzero if the decl represents an abstract instance
+ of a decl (i.e. one which is nested within an abstract instance of a
+ inline function. */
+
+DEFTREECODE (FUNCTION_DECL, "function_decl", tcc_declaration, 0)
+DEFTREECODE (LABEL_DECL, "label_decl", tcc_declaration, 0)
+/* The ordering of the following codes is optimized for the checking
+ macros in tree.h. Changing the order will degrade the speed of the
+ compiler. FIELD_DECL, VAR_DECL, CONST_DECL, PARM_DECL,
+ TYPE_DECL. */
+DEFTREECODE (FIELD_DECL, "field_decl", tcc_declaration, 0)
+DEFTREECODE (VAR_DECL, "var_decl", tcc_declaration, 0)
+DEFTREECODE (CONST_DECL, "const_decl", tcc_declaration, 0)
+DEFTREECODE (PARM_DECL, "parm_decl", tcc_declaration, 0)
+DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
+DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
+
+/* A "declaration" of a debug temporary. It should only appear in
+ DEBUG stmts. */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
+/* A stmt that marks the beginning of a source statement. */
+DEFTREECODE (DEBUG_BEGIN_STMT, "debug_begin_stmt", tcc_statement, 0)
+
+/* A namespace declaration. Namespaces appear in DECL_CONTEXT of other
+ _DECLs, providing a hierarchy of names. */
+DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
+
+/* A declaration import.
+ The C++ FE uses this to represent a using-directive; eg:
+ "using namespace foo".
+ But it could be used to represent any declaration import construct.
+ Whenever a declaration import appears in a lexical block, the BLOCK node
+ representing that lexical block in GIMPLE will contain an IMPORTED_DECL
+ node, linked via BLOCK_VARS accessor of the said BLOCK.
+ For a given NODE which code is IMPORTED_DECL,
+ IMPORTED_DECL_ASSOCIATED_DECL (NODE) accesses the imported declaration. */
+DEFTREECODE (IMPORTED_DECL, "imported_decl", tcc_declaration, 0)
+
+/* A namelist declaration.
+ The Fortran FE uses this to represent a namelist statement, e.g.:
+ NAMELIST /namelist-group-name/ namelist-group-object-list.
+ Whenever a declaration import appears in a lexical block, the BLOCK node
+ representing that lexical block in GIMPLE will contain an NAMELIST_DECL
+ node, linked via BLOCK_VARS accessor of the said BLOCK.
+ For a given NODE which code is NAMELIST_DECL,
+ NAMELIST_DECL_ASSOCIATED_DECL (NODE) accesses the imported declaration. */
+DEFTREECODE (NAMELIST_DECL, "namelist_decl", tcc_declaration, 0)
+
+/* A translation unit. This is not technically a declaration, since it
+ can't be looked up, but it's close enough. */
+DEFTREECODE (TRANSLATION_UNIT_DECL, "translation_unit_decl",\
+ tcc_declaration, 0)
+
+/* References to storage. */
+
+/* The ordering of the following codes is optimized for the classification
+ in handled_component_p. Keep them in a consecutive group. */
+
+/* Value is structure or union component.
+ Operand 0 is the structure or union (an expression).
+ Operand 1 is the field (a node of type FIELD_DECL).
+ Operand 2, if present, is the value of DECL_FIELD_OFFSET, measured
+ in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. */
+DEFTREECODE (COMPONENT_REF, "component_ref", tcc_reference, 3)
+
+/* Reference to a group of bits within an object. Similar to COMPONENT_REF
+ except the position is given explicitly rather than via a FIELD_DECL.
+ Operand 0 is the structure or union expression;
+ operand 1 is a tree giving the constant number of bits being referenced;
+ operand 2 is a tree giving the constant position of the first referenced bit.
+ The result type width has to match the number of bits referenced.
+ If the result type is integral, its signedness specifies how it is extended
+ to its mode width. */
+DEFTREECODE (BIT_FIELD_REF, "bit_field_ref", tcc_reference, 3)
+
+/* Array indexing.
+ Operand 0 is the array; operand 1 is a (single) array index.
+ Operand 2, if present, is a copy of TYPE_MIN_VALUE of the index.
+ Operand 3, if present, is the element size, measured in units of
+ the alignment of the element type. */
+DEFTREECODE (ARRAY_REF, "array_ref", tcc_reference, 4)
+
+/* Likewise, except that the result is a range ("slice") of the array. The
+ starting index of the resulting array is taken from operand 1 and the size
+ of the range is taken from the type of the expression. */
+DEFTREECODE (ARRAY_RANGE_REF, "array_range_ref", tcc_reference, 4)
+
+/* Used only on an operand of complex type, these return
+ a value of the corresponding component type. */
+DEFTREECODE (REALPART_EXPR, "realpart_expr", tcc_reference, 1)
+DEFTREECODE (IMAGPART_EXPR, "imagpart_expr", tcc_reference, 1)
+
+/* Represents viewing something of one type as being of a second type.
+ This corresponds to an "Unchecked Conversion" in Ada and roughly to
+ the idiom *(type2 *)&X in C. The only operand is the value to be
+ viewed as being of another type. It is undefined if the type of the
+ input and of the expression have different sizes.
+
+ This code may also be used within the LHS of a MODIFY_EXPR, in which
+ case no actual data motion may occur. TREE_ADDRESSABLE will be set in
+ this case and GCC must abort if it could not do the operation without
+ generating insns. */
+DEFTREECODE (VIEW_CONVERT_EXPR, "view_convert_expr", tcc_reference, 1)
+
+/* C unary `*'. One operand, an expression for a pointer. */
+DEFTREECODE (INDIRECT_REF, "indirect_ref", tcc_reference, 1)
+
+/* Used to represent lookup in a virtual method table which is dependent on
+ the runtime type of an object. Operands are:
+ OBJ_TYPE_REF_EXPR: An expression that evaluates the value to use.
+ OBJ_TYPE_REF_OBJECT: Is the object on whose behalf the lookup is
+ being performed. Through this the optimizers may be able to statically
+ determine the dynamic type of the object.
+ OBJ_TYPE_REF_TOKEN: An integer index to the virtual method table.
+ The integer index should have as type the original type of
+ OBJ_TYPE_REF_OBJECT; as pointer type conversions are useless in GIMPLE,
+ the type of OBJ_TYPE_REF_OBJECT can change to an unrelated pointer
+ type during optimizations. */
+DEFTREECODE (OBJ_TYPE_REF, "obj_type_ref", tcc_expression, 3)
+
+/* Used to represent the brace-enclosed initializers for a structure or an
+ array. It contains a sequence of component values made out of a VEC of
+ constructor_elt.
+
+ For RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE:
+ The field INDEX of each constructor_elt is a FIELD_DECL.
+
+ For ARRAY_TYPE:
+ The field INDEX of each constructor_elt is the corresponding index.
+ If the index is a RANGE_EXPR, it is a short-hand for many nodes,
+ one for each index in the range. (If the corresponding field VALUE
+ has side-effects, they are evaluated once for each element. Wrap the
+ value in a SAVE_EXPR if you want to evaluate side effects only once.)
+
+ Components that aren't present are cleared as per the C semantics,
+ unless the CONSTRUCTOR_NO_CLEARING flag is set, in which case their
+ value becomes undefined. */
+DEFTREECODE (CONSTRUCTOR, "constructor", tcc_exceptional, 0)
+
+/* The expression types are mostly straightforward, with the fourth argument
+ of DEFTREECODE saying how many operands there are.
+ Unless otherwise specified, the operands are expressions and the
+ types of all the operands and the expression must all be the same. */
+
+/* Contains two expressions to compute, one followed by the other.
+ the first value is ignored. The second one's value is used. The
+ type of the first expression need not agree with the other types. */
+DEFTREECODE (COMPOUND_EXPR, "compound_expr", tcc_expression, 2)
+
+/* Assignment expression. Operand 0 is the what to set; 1, the new value. */
+DEFTREECODE (MODIFY_EXPR, "modify_expr", tcc_expression, 2)
+
+/* Initialization expression. Operand 0 is the variable to initialize;
+ Operand 1 is the initializer. This differs from MODIFY_EXPR in that any
+ reference to the referent of operand 0 within operand 1 is undefined. */
+DEFTREECODE (INIT_EXPR, "init_expr", tcc_expression, 2)
+
+/* For TARGET_EXPR, operand 0 is the target of an initialization,
+ operand 1 is the initializer for the target, which may be void
+ if simply expanding it initializes the target.
+ operand 2 is the cleanup for this node, if any.
+ operand 3 is the saved initializer after this node has been
+ expanded once; this is so we can re-expand the tree later. */
+DEFTREECODE (TARGET_EXPR, "target_expr", tcc_expression, 4)
+
+/* Conditional expression ( ... ? ... : ... in C).
+ Operand 0 is the condition.
+ Operand 1 is the then-value.
+ Operand 2 is the else-value.
+ Operand 0 may be of any type.
+ Operand 1 must have the same type as the entire expression, unless
+ it unconditionally throws an exception, in which case it should
+ have VOID_TYPE. The same constraints apply to operand 2. The
+ condition in operand 0 must be of integral type.
+
+ In cfg gimple, if you do not have a selection expression, operands
+ 1 and 2 are NULL. The operands are then taken from the cfg edges. */
+DEFTREECODE (COND_EXPR, "cond_expr", tcc_expression, 3)
+
+/* Represents a vector in which every element is equal to operand 0. */
+DEFTREECODE (VEC_DUPLICATE_EXPR, "vec_duplicate_expr", tcc_unary, 1)
+
+/* Vector series created from a start (base) value and a step.
+
+ A = VEC_SERIES_EXPR (B, C)
+
+ means
+
+ for (i = 0; i < N; i++)
+ A[i] = B + C * i; */
+DEFTREECODE (VEC_SERIES_EXPR, "vec_series_expr", tcc_binary, 2)
+
+/* Vector conditional expression. It is like COND_EXPR, but with
+ vector operands.
+
+ A = VEC_COND_EXPR ( X < Y, B, C)
+
+ means
+
+ for (i=0; i<N; i++)
+ A[i] = X[i] < Y[i] ? B[i] : C[i];
+*/
+DEFTREECODE (VEC_COND_EXPR, "vec_cond_expr", tcc_expression, 3)
+
+/* Vector permutation expression. A = VEC_PERM_EXPR<v0, v1, mask> means
+
+ N = length(mask)
+ foreach i in N:
+ M = mask[i] % (2*N)
+ A = M < N ? v0[M] : v1[M-N]
+
+ V0 and V1 are vectors of the same type. MASK is an integer-typed
+ vector. The number of MASK elements must be the same with the
+ number of elements in V0 and V1. The size of the inner type
+ of the MASK and of the V0 and V1 must be the same.
+*/
+DEFTREECODE (VEC_PERM_EXPR, "vec_perm_expr", tcc_expression, 3)
+
+/* Declare local variables, including making RTL and allocating space.
+ BIND_EXPR_VARS is a chain of VAR_DECL nodes for the variables.
+ BIND_EXPR_BODY is the body, the expression to be computed using
+ the variables. The value of operand 1 becomes that of the BIND_EXPR.
+ BIND_EXPR_BLOCK is the BLOCK that corresponds to these bindings
+ for debugging purposes. If this BIND_EXPR is actually expanded,
+ that sets the TREE_USED flag in the BLOCK.
+
+ The BIND_EXPR is not responsible for informing parsers
+ about these variables. If the body is coming from the input file,
+ then the code that creates the BIND_EXPR is also responsible for
+ informing the parser of the variables.
+
+ If the BIND_EXPR is ever expanded, its TREE_USED flag is set.
+ This tells the code for debugging symbol tables not to ignore the BIND_EXPR.
+ If the BIND_EXPR should be output for debugging but will not be expanded,
+ set the TREE_USED flag by hand.
+
+ In order for the BIND_EXPR to be known at all, the code that creates it
+ must also install it as a subblock in the tree of BLOCK
+ nodes for the function. */
+DEFTREECODE (BIND_EXPR, "bind_expr", tcc_expression, 3)
+
+/* Function call. CALL_EXPRs are represented by variably-sized expression
+ nodes. There are at least three fixed operands. Operand 0 is an
+ INTEGER_CST node containing the total operand count, the number of
+ arguments plus 3. Operand 1 is the function or NULL, while operand 2 is
+ is static chain argument, or NULL. The remaining operands are the
+ arguments to the call. */
+DEFTREECODE (CALL_EXPR, "call_expr", tcc_vl_exp, 3)
+
+/* Specify a value to compute along with its corresponding cleanup.
+ Operand 0 is the cleanup expression.
+ The cleanup is executed by the first enclosing CLEANUP_POINT_EXPR,
+ which must exist. This differs from TRY_CATCH_EXPR in that operand 1
+ is always evaluated when cleanups are run. */
+DEFTREECODE (WITH_CLEANUP_EXPR, "with_cleanup_expr", tcc_expression, 1)
+
+/* Specify a cleanup point.
+ Operand 0 is an expression that may have cleanups. If it does, those
+ cleanups are executed after the expression is expanded.
+
+ Note that if the expression is a reference to storage, it is forced out
+ of memory before the cleanups are run. This is necessary to handle
+ cases where the cleanups modify the storage referenced; in the
+ expression 't.i', if 't' is a struct with an integer member 'i' and a
+ cleanup which modifies 'i', the value of the expression depends on
+ whether the cleanup is run before or after 't.i' is evaluated. When
+ expand_expr is run on 't.i', it returns a MEM. This is not good enough;
+ the value of 't.i' must be forced out of memory.
+
+ As a consequence, the operand of a CLEANUP_POINT_EXPR must not have
+ BLKmode, because it will not be forced out of memory. */
+DEFTREECODE (CLEANUP_POINT_EXPR, "cleanup_point_expr", tcc_expression, 1)
+
+/* The following code is used in languages that have types where some
+ field in an object of the type contains a value that is used in the
+ computation of another field's offset or size and/or the size of the
+ type. The positions and/or sizes of fields can vary from object to
+ object of the same type or even for one and the same object within
+ its scope.
+
+ Record types with discriminants in Ada are
+ examples of such types. This mechanism is also used to create "fat
+ pointers" for unconstrained array types in Ada; the fat pointer is a
+ structure one of whose fields is a pointer to the actual array type
+ and the other field is a pointer to a template, which is a structure
+ containing the bounds of the array. The bounds in the type pointed
+ to by the first field in the fat pointer refer to the values in the
+ template.
+
+ When you wish to construct such a type you need "self-references"
+ that allow you to reference the object having this type from the
+ TYPE node, i.e. without having a variable instantiating this type.
+
+ Such a "self-references" is done using a PLACEHOLDER_EXPR. This is
+ a node that will later be replaced with the object being referenced.
+ Its type is that of the object and selects which object to use from
+ a chain of references (see below). No other slots are used in the
+ PLACEHOLDER_EXPR.
+
+ For example, if your type FOO is a RECORD_TYPE with a field BAR,
+ and you need the value of <variable>.BAR to calculate TYPE_SIZE
+ (FOO), just substitute <variable> above with a PLACEHOLDER_EXPR
+ whose TREE_TYPE is FOO. Then construct your COMPONENT_REF with
+ the PLACEHOLDER_EXPR as the first operand (which has the correct
+ type). Later, when the size is needed in the program, the back-end
+ will find this PLACEHOLDER_EXPR and generate code to calculate the
+ actual size at run-time. In the following, we describe how this
+ calculation is done.
+
+ When we wish to evaluate a size or offset, we check whether it contains a
+ PLACEHOLDER_EXPR. If it does, we call substitute_placeholder_in_expr
+ passing both that tree and an expression within which the object may be
+ found. The latter expression is the object itself in the simple case of
+ an Ada record with discriminant, but it can be the array in the case of an
+ unconstrained array.
+
+ In the latter case, we need the fat pointer, because the bounds of
+ the array can only be accessed from it. However, we rely here on the
+ fact that the expression for the array contains the dereference of
+ the fat pointer that obtained the array pointer. */
+
+/* Denotes a record to later be substituted before evaluating this expression.
+ The type of this expression is used to find the record to replace it. */
+DEFTREECODE (PLACEHOLDER_EXPR, "placeholder_expr", tcc_exceptional, 0)
+
+/* Simple arithmetic. */
+DEFTREECODE (PLUS_EXPR, "plus_expr", tcc_binary, 2)
+DEFTREECODE (MINUS_EXPR, "minus_expr", tcc_binary, 2)
+DEFTREECODE (MULT_EXPR, "mult_expr", tcc_binary, 2)
+
+/* Pointer addition. The first operand is always a pointer and the
+ second operand is an integer of type sizetype. */
+DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2)
+
+/* Pointer subtraction. The two arguments are pointers, and the result
+ is a signed integer of the same precision. Pointers are interpreted
+ as unsigned, the difference is computed as if in infinite signed
+ precision. Behavior is undefined if the difference does not fit in
+ the result type. The result does not depend on the pointer type,
+ it is not divided by the size of the pointed-to type. */
+DEFTREECODE (POINTER_DIFF_EXPR, "pointer_diff_expr", tcc_binary, 2)
+
+/* Highpart multiplication. For an integral type with precision B,
+ returns bits [2B-1, B] of the full 2*B product. Both operands
+ and the result should have integer types of the same precision
+ and signedness. */
+DEFTREECODE (MULT_HIGHPART_EXPR, "mult_highpart_expr", tcc_binary, 2)
+
+/* Division for integer result that rounds the quotient toward zero. */
+DEFTREECODE (TRUNC_DIV_EXPR, "trunc_div_expr", tcc_binary, 2)
+
+/* Division for integer result that rounds it toward plus infinity. */
+DEFTREECODE (CEIL_DIV_EXPR, "ceil_div_expr", tcc_binary, 2)
+
+/* Division for integer result that rounds it toward minus infinity. */
+DEFTREECODE (FLOOR_DIV_EXPR, "floor_div_expr", tcc_binary, 2)
+
+/* Division for integer result that rounds it toward nearest integer. */
+DEFTREECODE (ROUND_DIV_EXPR, "round_div_expr", tcc_binary, 2)
+
+/* Four kinds of remainder that go with the four kinds of division: */
+
+/* The sign of the remainder is that of the dividend. */
+DEFTREECODE (TRUNC_MOD_EXPR, "trunc_mod_expr", tcc_binary, 2)
+
+/* The sign of the remainder is the opposite of that of the divisor. */
+DEFTREECODE (CEIL_MOD_EXPR, "ceil_mod_expr", tcc_binary, 2)
+
+/* The sign of the remainder is that of the divisor. */
+DEFTREECODE (FLOOR_MOD_EXPR, "floor_mod_expr", tcc_binary, 2)
+
+/* The sign of the remainder is not predictable. */
+DEFTREECODE (ROUND_MOD_EXPR, "round_mod_expr", tcc_binary, 2)
+
+/* Division for real result. */
+DEFTREECODE (RDIV_EXPR, "rdiv_expr", tcc_binary, 2)
+
+/* Division which is not supposed to need rounding.
+ Used for pointer subtraction in C. */
+DEFTREECODE (EXACT_DIV_EXPR, "exact_div_expr", tcc_binary, 2)
+
+/* Conversion of real to fixed point by truncation. */
+DEFTREECODE (FIX_TRUNC_EXPR, "fix_trunc_expr", tcc_unary, 1)
+
+/* Conversion of an integer to a real. */
+DEFTREECODE (FLOAT_EXPR, "float_expr", tcc_unary, 1)
+
+/* Unary negation. */
+DEFTREECODE (NEGATE_EXPR, "negate_expr", tcc_unary, 1)
+
+/* Minimum and maximum values. When used with floating point, if both
+ operands are zeros, or if either operand is NaN, then it is unspecified
+ which of the two operands is returned as the result. */
+DEFTREECODE (MIN_EXPR, "min_expr", tcc_binary, 2)
+DEFTREECODE (MAX_EXPR, "max_expr", tcc_binary, 2)
+
+/* Represents the absolute value of the operand.
+
+ An ABS_EXPR must have either an INTEGER_TYPE or a REAL_TYPE. The
+ operand of the ABS_EXPR must have the same type. */
+DEFTREECODE (ABS_EXPR, "abs_expr", tcc_unary, 1)
+
+/* Represents the unsigned absolute value of the operand.
+ An ABSU_EXPR must have unsigned INTEGER_TYPE. The operand of the ABSU_EXPR
+ must have the corresponding signed type. */
+DEFTREECODE (ABSU_EXPR, "absu_expr", tcc_unary, 1)
+
+/* Shift operations for shift and rotate.
+ Shift means logical shift if done on an
+ unsigned type, arithmetic shift if done on a signed type.
+ The second operand is the number of bits to
+ shift by; it need not be the same type as the first operand and result.
+ Note that the result is undefined if the second operand is larger
+ than or equal to the first operand's type size.
+
+ The first operand of a shift can have either an integer or a
+ (non-integer) fixed-point type. We follow the ISO/IEC TR 18037:2004
+ semantics for the latter.
+
+ Rotates are defined for integer types only. */
+DEFTREECODE (LSHIFT_EXPR, "lshift_expr", tcc_binary, 2)
+DEFTREECODE (RSHIFT_EXPR, "rshift_expr", tcc_binary, 2)
+DEFTREECODE (LROTATE_EXPR, "lrotate_expr", tcc_binary, 2)
+DEFTREECODE (RROTATE_EXPR, "rrotate_expr", tcc_binary, 2)
+
+/* Bitwise operations. Operands have same mode as result. */
+DEFTREECODE (BIT_IOR_EXPR, "bit_ior_expr", tcc_binary, 2)
+DEFTREECODE (BIT_XOR_EXPR, "bit_xor_expr", tcc_binary, 2)
+DEFTREECODE (BIT_AND_EXPR, "bit_and_expr", tcc_binary, 2)
+DEFTREECODE (BIT_NOT_EXPR, "bit_not_expr", tcc_unary, 1)
+
+/* ANDIF and ORIF allow the second operand not to be computed if the
+ value of the expression is determined from the first operand. AND,
+ OR, and XOR always compute the second operand whether its value is
+ needed or not (for side effects). The operand may have
+ BOOLEAN_TYPE or INTEGER_TYPE. In either case, the argument will be
+ either zero or one. For example, a TRUTH_NOT_EXPR will never have
+ an INTEGER_TYPE VAR_DECL as its argument; instead, a NE_EXPR will be
+ used to compare the VAR_DECL to zero, thereby obtaining a node with
+ value zero or one. */
+DEFTREECODE (TRUTH_ANDIF_EXPR, "truth_andif_expr", tcc_expression, 2)
+DEFTREECODE (TRUTH_ORIF_EXPR, "truth_orif_expr", tcc_expression, 2)
+DEFTREECODE (TRUTH_AND_EXPR, "truth_and_expr", tcc_expression, 2)
+DEFTREECODE (TRUTH_OR_EXPR, "truth_or_expr", tcc_expression, 2)
+DEFTREECODE (TRUTH_XOR_EXPR, "truth_xor_expr", tcc_expression, 2)
+DEFTREECODE (TRUTH_NOT_EXPR, "truth_not_expr", tcc_expression, 1)
+
+/* Relational operators.
+ EQ_EXPR and NE_EXPR are allowed for any types. The others, except for
+ LTGT_EXPR, are allowed only for integral, floating-point and vector types.
+ LTGT_EXPR is allowed only for floating-point types.
+ For floating-point operators, if either operand is a NaN, then NE_EXPR
+ returns true and the remaining operators return false. The operators
+ other than EQ_EXPR and NE_EXPR may generate an exception on quiet NaNs.
+ In all cases the operands will have the same type,
+ and the value is either the type used by the language for booleans
+ or an integer vector type of the same size and with the same number
+ of elements as the comparison operands. True for a vector of
+ comparison results has all bits set while false is equal to zero. */
+DEFTREECODE (LT_EXPR, "lt_expr", tcc_comparison, 2)
+DEFTREECODE (LE_EXPR, "le_expr", tcc_comparison, 2)
+DEFTREECODE (GT_EXPR, "gt_expr", tcc_comparison, 2)
+DEFTREECODE (GE_EXPR, "ge_expr", tcc_comparison, 2)
+DEFTREECODE (LTGT_EXPR, "ltgt_expr", tcc_comparison, 2)
+DEFTREECODE (EQ_EXPR, "eq_expr", tcc_comparison, 2)
+DEFTREECODE (NE_EXPR, "ne_expr", tcc_comparison, 2)
+
+/* Additional relational operators for floating-point unordered. */
+DEFTREECODE (UNORDERED_EXPR, "unordered_expr", tcc_comparison, 2)
+DEFTREECODE (ORDERED_EXPR, "ordered_expr", tcc_comparison, 2)
+
+/* These are equivalent to unordered or ... */
+DEFTREECODE (UNLT_EXPR, "unlt_expr", tcc_comparison, 2)
+DEFTREECODE (UNLE_EXPR, "unle_expr", tcc_comparison, 2)
+DEFTREECODE (UNGT_EXPR, "ungt_expr", tcc_comparison, 2)
+DEFTREECODE (UNGE_EXPR, "unge_expr", tcc_comparison, 2)
+DEFTREECODE (UNEQ_EXPR, "uneq_expr", tcc_comparison, 2)
+
+DEFTREECODE (RANGE_EXPR, "range_expr", tcc_binary, 2)
+
+/* Represents a re-association barrier for floating point expressions
+ like explicit parenthesis in fortran. */
+DEFTREECODE (PAREN_EXPR, "paren_expr", tcc_unary, 1)
+
+/* Represents a conversion of type of a value.
+ All conversions, including implicit ones, must be
+ represented by CONVERT_EXPR or NOP_EXPR nodes. */
+DEFTREECODE (CONVERT_EXPR, "convert_expr", tcc_unary, 1)
+
+/* Conversion of a pointer value to a pointer to a different
+ address space. */
+DEFTREECODE (ADDR_SPACE_CONVERT_EXPR, "addr_space_convert_expr", tcc_unary, 1)
+
+/* Conversion of a fixed-point value to an integer, a real, or a fixed-point
+ value. Or conversion of a fixed-point value from an integer, a real, or
+ a fixed-point value. */
+DEFTREECODE (FIXED_CONVERT_EXPR, "fixed_convert_expr", tcc_unary, 1)
+
+/* Represents a conversion expected to require no code to be generated. */
+DEFTREECODE (NOP_EXPR, "nop_expr", tcc_unary, 1)
+
+/* Value is same as argument, but guaranteed not an lvalue. */
+DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", tcc_unary, 1)
+
+/* A COMPOUND_LITERAL_EXPR represents a literal that is placed in a DECL. The
+ COMPOUND_LITERAL_EXPR_DECL_EXPR is the a DECL_EXPR containing the decl
+ for the anonymous object represented by the COMPOUND_LITERAL;
+ the DECL_INITIAL of that decl is the CONSTRUCTOR that initializes
+ the compound literal. */
+DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", tcc_expression, 1)
+
+/* Represents something we computed once and will use multiple times.
+ First operand is that expression. After it is evaluated once, it
+ will be replaced by the temporary variable that holds the value. */
+DEFTREECODE (SAVE_EXPR, "save_expr", tcc_expression, 1)
+
+/* & in C. Value is the address at which the operand's value resides.
+ Operand may have any mode. Result mode is Pmode. */
+DEFTREECODE (ADDR_EXPR, "addr_expr", tcc_expression, 1)
+
+/* Operand0 is a function constant; result is part N of a function
+ descriptor of type ptr_mode. */
+DEFTREECODE (FDESC_EXPR, "fdesc_expr", tcc_expression, 2)
+
+/* Given a container value, a replacement value and a bit position within
+ the container, produce the value that results from replacing the part of
+ the container starting at the bit position with the replacement value.
+ Operand 0 is a tree for the container value of integral or vector type;
+ Operand 1 is a tree for the replacement value of another integral or
+ the vector element type;
+ Operand 2 is a tree giving the constant bit position;
+ The number of bits replaced is given by the precision of the type of the
+ replacement value if it is integral or by its size if it is non-integral.
+ ??? The reason to make the size of the replacement implicit is to avoid
+ introducing a quaternary operation.
+ The replaced bits shall be fully inside the container. If the container
+ is of vector type, then these bits shall be aligned with its elements. */
+DEFTREECODE (BIT_INSERT_EXPR, "bit_insert_expr", tcc_expression, 3)
+
+/* Given two real or integer operands of the same type,
+ returns a complex value of the corresponding complex type. */
+DEFTREECODE (COMPLEX_EXPR, "complex_expr", tcc_binary, 2)
+
+/* Complex conjugate of operand. Used only on complex types. */
+DEFTREECODE (CONJ_EXPR, "conj_expr", tcc_unary, 1)
+
+/* Nodes for ++ and -- in C.
+ The second arg is how much to increment or decrement by.
+ For a pointer, it would be the size of the object pointed to. */
+DEFTREECODE (PREDECREMENT_EXPR, "predecrement_expr", tcc_expression, 2)
+DEFTREECODE (PREINCREMENT_EXPR, "preincrement_expr", tcc_expression, 2)
+DEFTREECODE (POSTDECREMENT_EXPR, "postdecrement_expr", tcc_expression, 2)
+DEFTREECODE (POSTINCREMENT_EXPR, "postincrement_expr", tcc_expression, 2)
+
+/* Used to implement `va_arg'. */
+DEFTREECODE (VA_ARG_EXPR, "va_arg_expr", tcc_expression, 1)
+
+/* Evaluate operand 0. If and only if an exception is thrown during
+ the evaluation of operand 0, evaluate operand 1.
+
+ This differs from TRY_FINALLY_EXPR in that operand 1 is not evaluated
+ on a normal or jump exit, only on an exception. */
+DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", tcc_statement, 2)
+
+/* Evaluate the first operand.
+ The second operand is a cleanup expression which is evaluated
+ on any exit (normal, exception, or jump out) from this expression. */
+DEFTREECODE (TRY_FINALLY_EXPR, "try_finally_expr", tcc_statement, 2)
+
+/* Evaluate either the normal or the exceptional cleanup. This must
+ only be present as the cleanup expression in a TRY_FINALLY_EXPR.
+ If the TRY_FINALLY_EXPR completes normally, the first operand of
+ EH_ELSE_EXPR is used as a cleanup, otherwise the second operand is
+ used. */
+DEFTREECODE (EH_ELSE_EXPR, "eh_else_expr", tcc_statement, 2)
+
+/* These types of expressions have no useful value,
+ and always have side effects. */
+
+/* Used to represent a local declaration. The operand is DECL_EXPR_DECL. */
+DEFTREECODE (DECL_EXPR, "decl_expr", tcc_statement, 1)
+
+/* A label definition, encapsulated as a statement.
+ Operand 0 is the LABEL_DECL node for the label that appears here.
+ The type should be void and the value should be ignored. */
+DEFTREECODE (LABEL_EXPR, "label_expr", tcc_statement, 1)
+
+/* GOTO. Operand 0 is a LABEL_DECL node or an expression.
+ The type should be void and the value should be ignored. */
+DEFTREECODE (GOTO_EXPR, "goto_expr", tcc_statement, 1)
+
+/* RETURN. Evaluates operand 0, then returns from the current function.
+ Presumably that operand is an assignment that stores into the
+ RESULT_DECL that hold the value to be returned.
+ The operand may be null.
+ The type should be void and the value should be ignored. */
+DEFTREECODE (RETURN_EXPR, "return_expr", tcc_statement, 1)
+
+/* Exit the inner most loop conditionally. Operand 0 is the condition.
+ The type should be void and the value should be ignored. */
+DEFTREECODE (EXIT_EXPR, "exit_expr", tcc_statement, 1)
+
+/* A loop. Operand 0 is the body of the loop.
+ It must contain an EXIT_EXPR or is an infinite loop.
+ The type should be void and the value should be ignored. */
+DEFTREECODE (LOOP_EXPR, "loop_expr", tcc_statement, 1)
+
+/* Switch expression.
+
+ TREE_TYPE is the original type of the condition, before any
+ language required type conversions. It may be NULL, in which case
+ the original type and final types are assumed to be the same.
+
+ Operand 0 is the expression used to perform the branch,
+ Operand 1 is the body of the switch, which probably contains
+ CASE_LABEL_EXPRs. It may also be NULL, in which case operand 2
+ must not be NULL. */
+DEFTREECODE (SWITCH_EXPR, "switch_expr", tcc_statement, 2)
+
+/* Used to represent a case label.
+
+ Operand 0 is CASE_LOW. It may be NULL_TREE, in which case the label
+ is a 'default' label.
+ Operand 1 is CASE_HIGH. If it is NULL_TREE, the label is a simple
+ (one-value) case label. If it is non-NULL_TREE, the case is a range.
+ Operand 2 is CASE_LABEL, which has the corresponding LABEL_DECL.
+ Operand 3 is CASE_CHAIN. This operand is only used in tree-cfg.cc to
+ speed up the lookup of case labels which use a particular edge in
+ the control flow graph. */
+DEFTREECODE (CASE_LABEL_EXPR, "case_label_expr", tcc_statement, 4)
+
+/* Used to represent an inline assembly statement. ASM_STRING returns a
+ STRING_CST for the instruction (e.g., "mov x, y"). ASM_OUTPUTS,
+ ASM_INPUTS, and ASM_CLOBBERS represent the outputs, inputs, and clobbers
+ for the statement. ASM_LABELS, if present, indicates various destinations
+ for the asm; labels cannot be combined with outputs. */
+DEFTREECODE (ASM_EXPR, "asm_expr", tcc_statement, 5)
+
+/* Variable references for SSA analysis. New SSA names are created every
+ time a variable is assigned a new value. The SSA builder uses SSA_NAME
+ nodes to implement SSA versioning. */
+DEFTREECODE (SSA_NAME, "ssa_name", tcc_exceptional, 0)
+
+/* Used to represent a typed exception handler. CATCH_TYPES is the type (or
+ list of types) handled, and CATCH_BODY is the code for the handler. */
+DEFTREECODE (CATCH_EXPR, "catch_expr", tcc_statement, 2)
+
+/* Used to represent an exception specification. EH_FILTER_TYPES is a list
+ of allowed types, and EH_FILTER_FAILURE is an expression to evaluate on
+ failure. */
+DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", tcc_statement, 2)
+
+/* Node used for describing a property that is known at compile
+ time. */
+DEFTREECODE (SCEV_KNOWN, "scev_known", tcc_expression, 0)
+
+/* Node used for describing a property that is not known at compile
+ time. */
+DEFTREECODE (SCEV_NOT_KNOWN, "scev_not_known", tcc_expression, 0)
+
+/* Polynomial chains of recurrences.
+ cr = {CHREC_LEFT (cr), +, CHREC_RIGHT (cr)}_CHREC_VARIABLE (cr). */
+DEFTREECODE (POLYNOMIAL_CHREC, "polynomial_chrec", tcc_expression, 2)
+
+/* Used to chain children of container statements together.
+ Use the interface in tree-iterator.h to access this node. */
+DEFTREECODE (STATEMENT_LIST, "statement_list", tcc_exceptional, 0)
+
+/* Predicate assertion. Artificial expression generated by the optimizers
+ to keep track of predicate values. This expression may only appear on
+ the RHS of assignments.
+
+ Given X = ASSERT_EXPR <Y, EXPR>, the optimizers can infer
+ two things:
+
+ 1- X is a copy of Y.
+ 2- EXPR is a conditional expression and is known to be true.
+
+ Valid and to be expected forms of conditional expressions are
+ valid GIMPLE conditional expressions (as defined by is_gimple_condexpr)
+ and conditional expressions with the first operand being a
+ PLUS_EXPR with a variable possibly wrapped in a NOP_EXPR first
+ operand and an integer constant second operand.
+
+ The type of the expression is the same as Y. */
+DEFTREECODE (ASSERT_EXPR, "assert_expr", tcc_expression, 2)
+
+/* Base class information. Holds information about a class as a
+ baseclass of itself or another class. */
+DEFTREECODE (TREE_BINFO, "tree_binfo", tcc_exceptional, 0)
+
+/* Records the size for an expression of variable size type. This is
+ for use in contexts in which we are accessing the entire object,
+ such as for a function call, or block copy.
+ Operand 0 is the real expression.
+ Operand 1 is the size of the type in the expression. */
+DEFTREECODE (WITH_SIZE_EXPR, "with_size_expr", tcc_expression, 2)
+
+/* Extract elements from two input vectors Operand 0 and Operand 1
+ size VS, according to the offset OFF defined by Operand 2 as
+ follows:
+ If OFF > 0, the last VS - OFF elements of vector OP0 are concatenated to
+ the first OFF elements of the vector OP1.
+ If OFF == 0, then the returned vector is OP1.
+ On different targets OFF may take different forms; It can be an address, in
+ which case its low log2(VS)-1 bits define the offset, or it can be a mask
+ generated by the builtin targetm.vectorize.mask_for_load_builtin_decl. */
+DEFTREECODE (REALIGN_LOAD_EXPR, "realign_load", tcc_expression, 3)
+
+/* Low-level memory addressing. Operands are BASE (address of static or
+ global variable or register), OFFSET (integer constant),
+ INDEX (register), STEP (integer constant), INDEX2 (register),
+ The corresponding address is BASE + STEP * INDEX + INDEX2 + OFFSET.
+ Only variations and values valid on the target are allowed.
+
+ The type of STEP, INDEX and INDEX2 is sizetype.
+
+ The type of BASE is a pointer type. If BASE is not an address of
+ a static or global variable INDEX2 will be NULL.
+
+ The type of OFFSET is a pointer type and determines TBAA the same as
+ the constant offset operand in MEM_REF. */
+
+DEFTREECODE (TARGET_MEM_REF, "target_mem_ref", tcc_reference, 5)
+
+/* Memory addressing. Operands are a pointer and a tree constant integer
+ byte offset of the pointer type that when dereferenced yields the
+ type of the base object the pointer points into and which is used for
+ TBAA purposes.
+ The type of the MEM_REF is the type the bytes at the memory location
+ are interpreted as.
+ MEM_REF <p, c> is equivalent to ((typeof(c))p)->x... where x... is a
+ chain of component references offsetting p by c. */
+DEFTREECODE (MEM_REF, "mem_ref", tcc_reference, 2)
+
+/* OpenACC and OpenMP. As it is exposed in TREE_RANGE_CHECK invocations, do
+ not change the ordering of these codes. */
+
+/* OpenACC - #pragma acc parallel [clause1 ... clauseN]
+ Operand 0: OMP_BODY: Code to be executed in parallel.
+ Operand 1: OMP_CLAUSES: List of clauses. */
+
+DEFTREECODE (OACC_PARALLEL, "oacc_parallel", tcc_statement, 2)
+
+/* OpenACC - #pragma acc kernels [clause1 ... clauseN]
+ Operand 0: OMP_BODY: Sequence of kernels.
+ Operand 1: OMP_CLAUSES: List of clauses. */
+
+DEFTREECODE (OACC_KERNELS, "oacc_kernels", tcc_statement, 2)
+
+/* OpenACC - #pragma acc serial [clause1 ... clauseN]
+ Operand 0: OMP_BODY: Code to be executed sequentially.
+ Operand 1: OMP_CLAUSES: List of clauses. */
+
+DEFTREECODE (OACC_SERIAL, "oacc_serial", tcc_statement, 2)
+
+/* OpenACC - #pragma acc data [clause1 ... clauseN]
+ Operand 0: OACC_DATA_BODY: Data construct body.
+ Operand 1: OACC_DATA_CLAUSES: List of clauses. */
+
+DEFTREECODE (OACC_DATA, "oacc_data", tcc_statement, 2)
+
+/* OpenACC - #pragma acc host_data [clause1 ... clauseN]
+ Operand 0: OACC_HOST_DATA_BODY: Host_data construct body.
+ Operand 1: OACC_HOST_DATA_CLAUSES: List of clauses. */
+
+DEFTREECODE (OACC_HOST_DATA, "oacc_host_data", tcc_statement, 2)
+
+/* OpenMP - #pragma omp parallel [clause1 ... clauseN]
+ Operand 0: OMP_PARALLEL_BODY: Code to be executed by all threads.
+ Operand 1: OMP_PARALLEL_CLAUSES: List of clauses. */
+
+DEFTREECODE (OMP_PARALLEL, "omp_parallel", tcc_statement, 2)
+
+/* OpenMP - #pragma omp task [clause1 ... clauseN]
+ Operand 0: OMP_TASK_BODY: Code to be executed by all threads.
+ Operand 1: OMP_TASK_CLAUSES: List of clauses. */
+
+DEFTREECODE (OMP_TASK, "omp_task", tcc_statement, 2)
+
+/* OpenMP - #pragma omp for [clause1 ... clauseN]
+ Operand 0: OMP_FOR_BODY: Loop body.
+ Operand 1: OMP_FOR_CLAUSES: List of clauses.
+ Operand 2: OMP_FOR_INIT: Initialization code of the form
+ VAR = N1.
+ Operand 3: OMP_FOR_COND: Loop conditional expression of the form
+ VAR { <, >, <=, >= } N2.
+ Operand 4: OMP_FOR_INCR: Loop index increment of the form
+ VAR { +=, -= } INCR.
+ Operand 5: OMP_FOR_PRE_BODY: Filled by the gimplifier with things
+ from INIT, COND, and INCR that are technically part of the
+ OMP_FOR structured block, but are evaluated before the loop
+ body begins.
+ Operand 6: OMP_FOR_ORIG_DECLS: If non-NULL, list of DECLs initialized
+ in OMP_FOR_INIT. In some cases, like C++ iterators, the original
+ DECL init has been lost in gimplification and now contains a
+ temporary (D.nnnn). This list contains the original DECLs in
+ the source.
+
+ VAR must be an integer or pointer variable, which is implicitly thread
+ private. N1, N2 and INCR are required to be loop invariant integer
+ expressions that are evaluated without any synchronization.
+ The evaluation order, frequency of evaluation and side-effects are
+ unspecified by the standards. */
+DEFTREECODE (OMP_FOR, "omp_for", tcc_statement, 7)
+
+/* OpenMP - #pragma omp simd [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_SIMD, "omp_simd", tcc_statement, 7)
+
+/* OpenMP - #pragma omp distribute [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_DISTRIBUTE, "omp_distribute", tcc_statement, 7)
+
+/* OpenMP - #pragma omp taskloop [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_TASKLOOP, "omp_taskloop", tcc_statement, 7)
+
+/* OpenMP - #pragma omp loop [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OMP_LOOP, "omp_loop", tcc_statement, 7)
+
+/* OpenMP - #pragma acc loop [clause1 ... clauseN]
+ Operands like for OMP_FOR. */
+DEFTREECODE (OACC_LOOP, "oacc_loop", tcc_statement, 7)
+
+/* OpenMP - #pragma omp teams [clause1 ... clauseN]
+ Operand 0: OMP_TEAMS_BODY: Teams body.
+ Operand 1: OMP_TEAMS_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TEAMS, "omp_teams", tcc_statement, 2)
+
+/* OpenMP - #pragma omp target data [clause1 ... clauseN]
+ Operand 0: OMP_TARGET_DATA_BODY: Target data construct body.
+ Operand 1: OMP_TARGET_DATA_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TARGET_DATA, "omp_target_data", tcc_statement, 2)
+
+/* OpenMP - #pragma omp target [clause1 ... clauseN]
+ Operand 0: OMP_TARGET_BODY: Target construct body.
+ Operand 1: OMP_TARGET_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TARGET, "omp_target", tcc_statement, 2)
+
+/* OpenMP - #pragma omp sections [clause1 ... clauseN]
+ Operand 0: OMP_SECTIONS_BODY: Sections body.
+ Operand 1: OMP_SECTIONS_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_SECTIONS, "omp_sections", tcc_statement, 2)
+
+/* OpenMP - #pragma omp ordered
+ Operand 0: OMP_ORDERED_BODY: Master section body.
+ Operand 1: OMP_ORDERED_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_ORDERED, "omp_ordered", tcc_statement, 2)
+
+/* OpenMP - #pragma omp critical [name]
+ Operand 0: OMP_CRITICAL_BODY: Critical section body.
+ Operand 1: OMP_CRITICAL_CLAUSES: List of clauses.
+ Operand 2: OMP_CRITICAL_NAME: Identifier for critical section. */
+DEFTREECODE (OMP_CRITICAL, "omp_critical", tcc_statement, 3)
+
+/* OpenMP - #pragma omp single
+ Operand 0: OMP_SINGLE_BODY: Single section body.
+ Operand 1: OMP_SINGLE_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_SINGLE, "omp_single", tcc_statement, 2)
+
+/* OpenMP - #pragma omp scope
+ Operand 0: OMP_SCOPE_BODY: Masked section body.
+ Operand 1: OMP_SCOPE_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_SCOPE, "omp_scope", tcc_statement, 2)
+
+/* OpenMP - #pragma omp taskgroup
+ Operand 0: OMP_TASKGROUP_BODY: Taskgroup body.
+ Operand 1: OMP_SINGLE_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 2)
+
+/* OpenMP - #pragma omp masked
+ Operand 0: OMP_MASKED_BODY: Masked section body.
+ Operand 1: OMP_MASKED_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_MASKED, "omp_masked", tcc_statement, 2)
+
+/* OpenMP - #pragma omp scan
+ Operand 0: OMP_SCAN_BODY: Scan body.
+ Operand 1: OMP_SCAN_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_SCAN, "omp_scan", tcc_statement, 2)
+
+/* OpenMP - #pragma omp section
+ Operand 0: OMP_SECTION_BODY: Section body. */
+DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
+
+/* OpenMP - #pragma omp master
+ Operand 0: OMP_MASTER_BODY: Master section body. */
+DEFTREECODE (OMP_MASTER, "omp_master", tcc_statement, 1)
+
+/* OpenACC - #pragma acc cache (variable1 ... variableN)
+ Operand 0: OACC_CACHE_CLAUSES: List of variables (transformed into
+ OMP_CLAUSE__CACHE_ clauses). */
+DEFTREECODE (OACC_CACHE, "oacc_cache", tcc_statement, 1)
+
+/* OpenACC - #pragma acc declare [clause1 ... clauseN]
+ Operand 0: OACC_DECLARE_CLAUSES: List of clauses. */
+DEFTREECODE (OACC_DECLARE, "oacc_declare", tcc_statement, 1)
+
+/* OpenACC - #pragma acc enter data [clause1 ... clauseN]
+ Operand 0: OACC_ENTER_DATA_CLAUSES: List of clauses. */
+DEFTREECODE (OACC_ENTER_DATA, "oacc_enter_data", tcc_statement, 1)
+
+/* OpenACC - #pragma acc exit data [clause1 ... clauseN]
+ Operand 0: OACC_EXIT_DATA_CLAUSES: List of clauses. */
+DEFTREECODE (OACC_EXIT_DATA, "oacc_exit_data", tcc_statement, 1)
+
+/* OpenACC - #pragma acc update [clause1 ... clauseN]
+ Operand 0: OACC_UPDATE_CLAUSES: List of clauses. */
+DEFTREECODE (OACC_UPDATE, "oacc_update", tcc_statement, 1)
+
+/* OpenMP - #pragma omp target update [clause1 ... clauseN]
+ Operand 0: OMP_TARGET_UPDATE_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TARGET_UPDATE, "omp_target_update", tcc_statement, 1)
+
+/* OpenMP - #pragma omp target enter data [clause1 ... clauseN]
+ Operand 0: OMP_TARGET_ENTER_DATA_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TARGET_ENTER_DATA, "omp_target_enter_data", tcc_statement, 1)
+
+/* OpenMP - #pragma omp target exit data [clause1 ... clauseN]
+ Operand 0: OMP_TARGET_EXIT_DATA_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_TARGET_EXIT_DATA, "omp_target_exit_data", tcc_statement, 1)
+
+/* OMP_ATOMIC through OMP_ATOMIC_CAPTURE_NEW must be consecutive,
+ or OMP_ATOMIC_SEQ_CST needs adjusting. */
+
+/* OpenMP - #pragma omp atomic
+ Operand 0: The address at which the atomic operation is to be performed.
+ This address should be stabilized with save_expr.
+ Operand 1: The expression to evaluate. When the old value of the object
+ at the address is used in the expression, it should appear as if
+ build_fold_indirect_ref of the address. */
+DEFTREECODE (OMP_ATOMIC, "omp_atomic", tcc_statement, 2)
+
+/* OpenMP - #pragma omp atomic read
+ Operand 0: The address at which the atomic operation is to be performed.
+ This address should be stabilized with save_expr. */
+DEFTREECODE (OMP_ATOMIC_READ, "omp_atomic_read", tcc_statement, 1)
+
+/* OpenMP - #pragma omp atomic capture
+ Operand 0: The address at which the atomic operation is to be performed.
+ This address should be stabilized with save_expr.
+ Operand 1: The expression to evaluate. When the old value of the object
+ at the address is used in the expression, it should appear as if
+ build_fold_indirect_ref of the address.
+ OMP_ATOMIC_CAPTURE_OLD returns the old memory content,
+ OMP_ATOMIC_CAPTURE_NEW the new value. */
+DEFTREECODE (OMP_ATOMIC_CAPTURE_OLD, "omp_atomic_capture_old", tcc_statement, 2)
+DEFTREECODE (OMP_ATOMIC_CAPTURE_NEW, "omp_atomic_capture_new", tcc_statement, 2)
+
+/* OpenMP clauses. */
+DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0)
+
+/* TRANSACTION_EXPR tree code.
+ Operand 0: BODY: contains body of the transaction. */
+DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_expression, 1)
+
+/* Widening dot-product.
+ The first two arguments are of type t1.
+ The third argument and the result are of type t2, such that t2 is at least
+ twice the size of t1. DOT_PROD_EXPR(arg1,arg2,arg3) is equivalent to:
+ tmp = WIDEN_MULT_EXPR(arg1, arg2);
+ arg3 = PLUS_EXPR (tmp, arg3);
+ or:
+ tmp = WIDEN_MULT_EXPR(arg1, arg2);
+ arg3 = WIDEN_SUM_EXPR (tmp, arg3); */
+DEFTREECODE (DOT_PROD_EXPR, "dot_prod_expr", tcc_expression, 3)
+
+/* Widening summation.
+ The first argument is of type t1.
+ The second argument is of type t2, such that t2 is at least twice
+ the size of t1. The type of the entire expression is also t2.
+ WIDEN_SUM_EXPR is equivalent to first widening (promoting)
+ the first argument from type t1 to type t2, and then summing it
+ with the second argument. */
+DEFTREECODE (WIDEN_SUM_EXPR, "widen_sum_expr", tcc_binary, 2)
+
+/* Widening sad (sum of absolute differences).
+ The first two arguments are of type t1 which should be integer.
+ The third argument and the result are of type t2, such that t2 is at least
+ twice the size of t1. Like DOT_PROD_EXPR, SAD_EXPR (arg1,arg2,arg3) is
+ equivalent to (note we don't have WIDEN_MINUS_EXPR now, but we assume its
+ behavior is similar to WIDEN_SUM_EXPR):
+ tmp = WIDEN_MINUS_EXPR (arg1, arg2)
+ tmp2 = ABS_EXPR (tmp)
+ arg3 = PLUS_EXPR (tmp2, arg3)
+ or:
+ tmp = WIDEN_MINUS_EXPR (arg1, arg2)
+ tmp2 = ABS_EXPR (tmp)
+ arg3 = WIDEN_SUM_EXPR (tmp2, arg3)
+ */
+DEFTREECODE (SAD_EXPR, "sad_expr", tcc_expression, 3)
+
+/* Widening multiplication.
+ The two arguments are of type t1 and t2, both integral types that
+ have the same precision, but possibly different signedness.
+ The result is of integral type t3, such that t3 is at least twice
+ the size of t1/t2. WIDEN_MULT_EXPR is equivalent to first widening
+ (promoting) the arguments from type t1 to type t3, and from t2 to
+ type t3 and then multiplying them. */
+DEFTREECODE (WIDEN_MULT_EXPR, "widen_mult_expr", tcc_binary, 2)
+
+/* Widening multiply-accumulate.
+ The first two arguments are of type t1.
+ The third argument and the result are of type t2, such as t2 is at least
+ twice the size of t1. t1 and t2 must be integral or fixed-point types.
+ The expression is equivalent to a WIDEN_MULT_EXPR operation
+ of the first two operands followed by an add or subtract of the third
+ operand. */
+DEFTREECODE (WIDEN_MULT_PLUS_EXPR, "widen_mult_plus_expr", tcc_expression, 3)
+/* This is like the above, except in the final expression the multiply result
+ is subtracted from t3. */
+DEFTREECODE (WIDEN_MULT_MINUS_EXPR, "widen_mult_minus_expr", tcc_expression, 3)
+
+/* Widening shift left.
+ The first operand is of type t1.
+ The second operand is the number of bits to shift by; it need not be the
+ same type as the first operand and result.
+ Note that the result is undefined if the second operand is larger
+ than or equal to the first operand's type size.
+ The type of the entire expression is t2, such that t2 is at least twice
+ the size of t1.
+ WIDEN_LSHIFT_EXPR is equivalent to first widening (promoting)
+ the first argument from type t1 to type t2, and then shifting it
+ by the second argument. */
+DEFTREECODE (WIDEN_LSHIFT_EXPR, "widen_lshift_expr", tcc_binary, 2)
+DEFTREECODE (WIDEN_PLUS_EXPR, "widen_plus_expr", tcc_binary, 2)
+DEFTREECODE (WIDEN_MINUS_EXPR, "widen_minus_expr", tcc_binary, 2)
+
+/* Widening vector multiplication.
+ The two operands are vectors with N elements of size S. Multiplying the
+ elements of the two vectors will result in N products of size 2*S.
+ VEC_WIDEN_MULT_HI_EXPR computes the N/2 high products.
+ VEC_WIDEN_MULT_LO_EXPR computes the N/2 low products. */
+DEFTREECODE (VEC_WIDEN_MULT_HI_EXPR, "widen_mult_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_MULT_LO_EXPR, "widen_mult_lo_expr", tcc_binary, 2)
+
+/* Similarly, but return the even or odd N/2 products. */
+DEFTREECODE (VEC_WIDEN_MULT_EVEN_EXPR, "widen_mult_even_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_MULT_ODD_EXPR, "widen_mult_odd_expr", tcc_binary, 2)
+
+/* Unpack (extract and promote/widen) the high/low elements of the input
+ vector into the output vector. The input vector has twice as many
+ elements as the output vector, that are half the size of the elements
+ of the output vector. This is used to support type promotion. */
+DEFTREECODE (VEC_UNPACK_HI_EXPR, "vec_unpack_hi_expr", tcc_unary, 1)
+DEFTREECODE (VEC_UNPACK_LO_EXPR, "vec_unpack_lo_expr", tcc_unary, 1)
+
+/* Unpack (extract) the high/low elements of the input vector, convert
+ fixed point values to floating point and widen elements into the
+ output vector. The input vector has twice as many elements as the output
+ vector, that are half the size of the elements of the output vector. */
+DEFTREECODE (VEC_UNPACK_FLOAT_HI_EXPR, "vec_unpack_float_hi_expr", tcc_unary, 1)
+DEFTREECODE (VEC_UNPACK_FLOAT_LO_EXPR, "vec_unpack_float_lo_expr", tcc_unary, 1)
+
+/* Unpack (extract) the high/low elements of the input vector, convert
+ floating point values to integer and widen elements into the output
+ vector. The input vector has twice as many elements as the output
+ vector, that are half the size of the elements of the output vector. */
+DEFTREECODE (VEC_UNPACK_FIX_TRUNC_HI_EXPR, "vec_unpack_fix_trunc_hi_expr",
+ tcc_unary, 1)
+DEFTREECODE (VEC_UNPACK_FIX_TRUNC_LO_EXPR, "vec_unpack_fix_trunc_lo_expr",
+ tcc_unary, 1)
+
+/* Pack (demote/narrow and merge) the elements of the two input vectors
+ into the output vector using truncation/saturation.
+ The elements of the input vectors are twice the size of the elements of the
+ output vector. This is used to support type demotion. */
+DEFTREECODE (VEC_PACK_TRUNC_EXPR, "vec_pack_trunc_expr", tcc_binary, 2)
+DEFTREECODE (VEC_PACK_SAT_EXPR, "vec_pack_sat_expr", tcc_binary, 2)
+
+/* Convert floating point values of the two input vectors to integer
+ and pack (narrow and merge) the elements into the output vector. The
+ elements of the input vector are twice the size of the elements of
+ the output vector. */
+DEFTREECODE (VEC_PACK_FIX_TRUNC_EXPR, "vec_pack_fix_trunc_expr", tcc_binary, 2)
+
+/* Convert fixed point values of the two input vectors to floating point
+ and pack (narrow and merge) the elements into the output vector. The
+ elements of the input vector are twice the size of the elements of
+ the output vector. */
+DEFTREECODE (VEC_PACK_FLOAT_EXPR, "vec_pack_float_expr", tcc_binary, 2)
+
+/* Widening vector shift left in bits.
+ Operand 0 is a vector to be shifted with N elements of size S.
+ Operand 1 is an integer shift amount in bits.
+ The result of the operation is N elements of size 2*S.
+ VEC_WIDEN_LSHIFT_HI_EXPR computes the N/2 high results.
+ VEC_WIDEN_LSHIFT_LO_EXPR computes the N/2 low results.
+ */
+DEFTREECODE (VEC_WIDEN_LSHIFT_HI_EXPR, "widen_lshift_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_LSHIFT_LO_EXPR, "widen_lshift_lo_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_PLUS_HI_EXPR, "widen_plus_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_PLUS_LO_EXPR, "widen_plus_lo_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_MINUS_HI_EXPR, "widen_minus_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_MINUS_LO_EXPR, "widen_minus_lo_expr", tcc_binary, 2)
+
+/* PREDICT_EXPR. Specify hint for branch prediction. The
+ PREDICT_EXPR_PREDICTOR specify predictor and PREDICT_EXPR_OUTCOME the
+ outcome (0 for not taken and 1 for taken). Once the profile is guessed
+ all conditional branches leading to execution paths executing the
+ PREDICT_EXPR will get predicted by the specified predictor. */
+DEFTREECODE (PREDICT_EXPR, "predict_expr", tcc_expression, 1)
+
+/* OPTIMIZATION_NODE. Node to store the optimization options. */
+DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
+
+/* TARGET_OPTION_NODE. Node to store the target specific options. */
+DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0)
+
+/* ANNOTATE_EXPR.
+ Operand 0 is the expression to be annotated.
+ Operand 1 is the annotation kind.
+ Operand 2 is additional data. */
+DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 3)
+
+/*
+Local variables:
+mode:c
+End:
+*/
diff --git a/support/cpp/gcc/tree.h b/support/cpp/gcc/tree.h
new file mode 100644
index 000000000..19bfb7d41
--- /dev/null
+++ b/support/cpp/gcc/tree.h
@@ -0,0 +1,6643 @@
+/* Definitions for the ubiquitous 'tree' type for GNU compilers.
+ Copyright (C) 1989-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_TREE_H
+#define GCC_TREE_H
+
+#include "tree-core.h"
+#include "options.h"
+#if 0 // sdcpp
+
+/* Convert a target-independent built-in function code to a combined_fn. */
+
+inline combined_fn
+as_combined_fn (built_in_function fn)
+{
+ return combined_fn (int (fn));
+}
+
+/* Convert an internal function code to a combined_fn. */
+
+inline combined_fn
+as_combined_fn (internal_fn fn)
+{
+ return combined_fn (int (fn) + int (END_BUILTINS));
+}
+
+/* Return true if CODE is a target-independent built-in function. */
+
+inline bool
+builtin_fn_p (combined_fn code)
+{
+ return int (code) < int (END_BUILTINS);
+}
+
+/* Return the target-independent built-in function represented by CODE.
+ Only valid if builtin_fn_p (CODE). */
+
+inline built_in_function
+as_builtin_fn (combined_fn code)
+{
+ gcc_checking_assert (builtin_fn_p (code));
+ return built_in_function (int (code));
+}
+
+/* Return true if CODE is an internal function. */
+
+inline bool
+internal_fn_p (combined_fn code)
+{
+ return int (code) >= int (END_BUILTINS);
+}
+
+/* Return the internal function represented by CODE. Only valid if
+ internal_fn_p (CODE). */
+
+inline internal_fn
+as_internal_fn (combined_fn code)
+{
+ gcc_checking_assert (internal_fn_p (code));
+ return internal_fn (int (code) - int (END_BUILTINS));
+}
+
+/* Macros for initializing `tree_contains_struct'. */
+#define MARK_TS_BASE(C) \
+ (tree_contains_struct[C][TS_BASE] = true)
+
+#define MARK_TS_TYPED(C) \
+ (MARK_TS_BASE (C), \
+ tree_contains_struct[C][TS_TYPED] = true)
+
+#define MARK_TS_COMMON(C) \
+ (MARK_TS_TYPED (C), \
+ tree_contains_struct[C][TS_COMMON] = true)
+
+#define MARK_TS_TYPE_COMMON(C) \
+ (MARK_TS_COMMON (C), \
+ tree_contains_struct[C][TS_TYPE_COMMON] = true)
+
+#define MARK_TS_TYPE_WITH_LANG_SPECIFIC(C) \
+ (MARK_TS_TYPE_COMMON (C), \
+ tree_contains_struct[C][TS_TYPE_WITH_LANG_SPECIFIC] = true)
+
+#define MARK_TS_TYPE_NON_COMMON(C) \
+ (MARK_TS_TYPE_WITH_LANG_SPECIFIC (C), \
+ tree_contains_struct[C][TS_TYPE_NON_COMMON] = true) \
+
+#define MARK_TS_DECL_MINIMAL(C) \
+ (MARK_TS_COMMON (C), \
+ tree_contains_struct[C][TS_DECL_MINIMAL] = true)
+
+#define MARK_TS_DECL_COMMON(C) \
+ (MARK_TS_DECL_MINIMAL (C), \
+ tree_contains_struct[C][TS_DECL_COMMON] = true)
+
+#define MARK_TS_DECL_WRTL(C) \
+ (MARK_TS_DECL_COMMON (C), \
+ tree_contains_struct[C][TS_DECL_WRTL] = true)
+
+#define MARK_TS_DECL_WITH_VIS(C) \
+ (MARK_TS_DECL_WRTL (C), \
+ tree_contains_struct[C][TS_DECL_WITH_VIS] = true)
+
+#define MARK_TS_DECL_NON_COMMON(C) \
+ (MARK_TS_DECL_WITH_VIS (C), \
+ tree_contains_struct[C][TS_DECL_NON_COMMON] = true)
+
+#define MARK_TS_EXP(C) \
+ (MARK_TS_TYPED (C), \
+ tree_contains_struct[C][TS_EXP] = true)
+
+/* Returns the string representing CLASS. */
+
+#define TREE_CODE_CLASS_STRING(CLASS)\
+ tree_code_class_strings[(int) (CLASS)]
+
+#define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)]
+
+/* Nonzero if NODE represents an exceptional code. */
+
+#define EXCEPTIONAL_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_exceptional)
+
+/* Nonzero if NODE represents a constant. */
+
+#define CONSTANT_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_constant)
+
+/* Nonzero if NODE represents a constant, or is a location wrapper
+ around such a node. */
+
+#define CONSTANT_CLASS_OR_WRAPPER_P(NODE)\
+ (CONSTANT_CLASS_P (tree_strip_any_location_wrapper (NODE)))
+
+/* Nonzero if NODE represents a type. */
+
+#define TYPE_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_type)
+
+/* Nonzero if NODE represents a declaration. */
+
+#define DECL_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_declaration)
+
+/* True if NODE designates a variable declaration. */
+#define VAR_P(NODE) \
+ (TREE_CODE (NODE) == VAR_DECL)
+
+/* Nonzero if DECL represents a VAR_DECL or FUNCTION_DECL. */
+
+#define VAR_OR_FUNCTION_DECL_P(DECL)\
+ (TREE_CODE (DECL) == VAR_DECL || TREE_CODE (DECL) == FUNCTION_DECL)
+
+/* Nonzero if NODE represents a INDIRECT_REF. Keep these checks in
+ ascending code order. */
+
+#define INDIRECT_REF_P(NODE)\
+ (TREE_CODE (NODE) == INDIRECT_REF)
+
+/* Nonzero if NODE represents a reference. */
+
+#define REFERENCE_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_reference)
+
+/* Nonzero if NODE represents a comparison. */
+
+#define COMPARISON_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_comparison)
+
+/* Nonzero if NODE represents a unary arithmetic expression. */
+
+#define UNARY_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_unary)
+
+/* Nonzero if NODE represents a binary arithmetic expression. */
+
+#define BINARY_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_binary)
+
+/* Nonzero if NODE represents a statement expression. */
+
+#define STATEMENT_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_statement)
+
+/* Nonzero if NODE represents a function call-like expression with a
+ variable-length operand vector. */
+
+#define VL_EXP_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_vl_exp)
+
+/* Nonzero if NODE represents any other expression. */
+
+#define EXPRESSION_CLASS_P(NODE)\
+ (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_expression)
+
+/* Returns nonzero iff NODE represents a type or declaration. */
+
+#define IS_TYPE_OR_DECL_P(NODE)\
+ (TYPE_P (NODE) || DECL_P (NODE))
+
+/* Returns nonzero iff CLASS is the tree-code class of an
+ expression. */
+
+#define IS_EXPR_CODE_CLASS(CLASS)\
+ ((CLASS) >= tcc_reference && (CLASS) <= tcc_expression)
+
+/* Returns nonzero iff NODE is an expression of some kind. */
+
+#define EXPR_P(NODE) IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (NODE)))
+
+#define TREE_CODE_LENGTH(CODE) tree_code_length[(int) (CODE)]
+
+
+/* Helper macros for math builtins. */
+
+#define CASE_FLT_FN(FN) case FN: case FN##F: case FN##L
+#define CASE_FLT_FN_FLOATN_NX(FN) \
+ case FN##F16: case FN##F32: case FN##F64: case FN##F128: \
+ case FN##F32X: case FN##F64X: case FN##F128X
+#define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
+#define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL: case FN##IMAX
+
+#endif // sdcpp
+#define NULL_TREE (tree) NULL
+
+/* Define accessors for the fields that all tree nodes have
+ (though some fields are not used for all kinds of nodes). */
+
+/* The tree-code says what kind of node it is.
+ Codes are defined in tree.def. */
+#define TREE_CODE(NODE) ((enum tree_code) (NODE)->base.code)
+#define TREE_SET_CODE(NODE, VALUE) ((NODE)->base.code = (VALUE))
+#if 0 // sdcpp
+
+/* When checking is enabled, errors will be generated if a tree node
+ is accessed incorrectly. The macros die with a fatal error. */
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+#define TREE_CHECK(T, CODE) \
+(tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
+
+#define TREE_NOT_CHECK(T, CODE) \
+(tree_not_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
+
+#define TREE_CHECK2(T, CODE1, CODE2) \
+(tree_check2 ((T), __FILE__, __LINE__, __FUNCTION__, (CODE1), (CODE2)))
+
+#define TREE_NOT_CHECK2(T, CODE1, CODE2) \
+(tree_not_check2 ((T), __FILE__, __LINE__, __FUNCTION__, (CODE1), (CODE2)))
+
+#define TREE_CHECK3(T, CODE1, CODE2, CODE3) \
+(tree_check3 ((T), __FILE__, __LINE__, __FUNCTION__, (CODE1), (CODE2), (CODE3)))
+
+#define TREE_NOT_CHECK3(T, CODE1, CODE2, CODE3) \
+(tree_not_check3 ((T), __FILE__, __LINE__, __FUNCTION__, \
+ (CODE1), (CODE2), (CODE3)))
+
+#define TREE_CHECK4(T, CODE1, CODE2, CODE3, CODE4) \
+(tree_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \
+ (CODE1), (CODE2), (CODE3), (CODE4)))
+
+#define TREE_NOT_CHECK4(T, CODE1, CODE2, CODE3, CODE4) \
+(tree_not_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \
+ (CODE1), (CODE2), (CODE3), (CODE4)))
+
+#define TREE_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) \
+(tree_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \
+ (CODE1), (CODE2), (CODE3), (CODE4), (CODE5)))
+
+#define TREE_NOT_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) \
+(tree_not_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \
+ (CODE1), (CODE2), (CODE3), (CODE4), (CODE5)))
+
+#define CONTAINS_STRUCT_CHECK(T, STRUCT) \
+(contains_struct_check ((T), (STRUCT), __FILE__, __LINE__, __FUNCTION__))
+
+#define TREE_CLASS_CHECK(T, CLASS) \
+(tree_class_check ((T), (CLASS), __FILE__, __LINE__, __FUNCTION__))
+
+#define TREE_RANGE_CHECK(T, CODE1, CODE2) \
+(tree_range_check ((T), (CODE1), (CODE2), __FILE__, __LINE__, __FUNCTION__))
+
+#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) \
+(omp_clause_subcode_check ((T), (CODE), __FILE__, __LINE__, __FUNCTION__))
+
+#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) \
+(omp_clause_range_check ((T), (CODE1), (CODE2), \
+ __FILE__, __LINE__, __FUNCTION__))
+
+/* These checks have to be special cased. */
+#define EXPR_CHECK(T) \
+(expr_check ((T), __FILE__, __LINE__, __FUNCTION__))
+
+/* These checks have to be special cased. */
+#define NON_TYPE_CHECK(T) \
+(non_type_check ((T), __FILE__, __LINE__, __FUNCTION__))
+
+/* These checks have to be special cased. */
+#define ANY_INTEGRAL_TYPE_CHECK(T) \
+(any_integral_type_check ((T), __FILE__, __LINE__, __FUNCTION__))
+
+#define TREE_INT_CST_ELT_CHECK(T, I) \
+(*tree_int_cst_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))
+
+#define TREE_VEC_ELT_CHECK(T, I) \
+(*(CONST_CAST2 (tree *, typeof (T)*, \
+ tree_vec_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))))
+
+#define OMP_CLAUSE_ELT_CHECK(T, I) \
+(*(omp_clause_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__)))
+
+/* Special checks for TREE_OPERANDs. */
+#define TREE_OPERAND_CHECK(T, I) \
+(*(CONST_CAST2 (tree*, typeof (T)*, \
+ tree_operand_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))))
+
+#define TREE_OPERAND_CHECK_CODE(T, CODE, I) \
+(*(tree_operand_check_code ((T), (CODE), (I), \
+ __FILE__, __LINE__, __FUNCTION__)))
+
+/* Nodes are chained together for many purposes.
+ Types are chained together to record them for being output to the debugger
+ (see the function `chain_type').
+ Decls in the same scope are chained together to record the contents
+ of the scope.
+ Statement nodes for successive statements used to be chained together.
+ Often lists of things are represented by TREE_LIST nodes that
+ are chained together. */
+
+#define TREE_CHAIN(NODE) \
+(CONTAINS_STRUCT_CHECK (NODE, TS_COMMON)->common.chain)
+
+/* In all nodes that are expressions, this is the data type of the expression.
+ In POINTER_TYPE nodes, this is the type that the pointer points to.
+ In ARRAY_TYPE nodes, this is the type of the elements.
+ In VECTOR_TYPE nodes, this is the type of the elements. */
+#define TREE_TYPE(NODE) \
+(CONTAINS_STRUCT_CHECK (NODE, TS_TYPED)->typed.type)
+
+extern void tree_contains_struct_check_failed (const_tree,
+ const enum tree_node_structure_enum,
+ const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+
+extern void tree_check_failed (const_tree, const char *, int, const char *,
+ ...) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_not_check_failed (const_tree, const char *, int, const char *,
+ ...) ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_class_check_failed (const_tree, const enum tree_code_class,
+ const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_range_check_failed (const_tree, const char *, int,
+ const char *, enum tree_code,
+ enum tree_code)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_not_class_check_failed (const_tree,
+ const enum tree_code_class,
+ const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_int_cst_elt_check_failed (int, int, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_vec_elt_check_failed (int, int, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void phi_node_elt_check_failed (int, int, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void tree_operand_check_failed (int, const_tree,
+ const char *, int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void omp_clause_check_failed (const_tree, const char *, int,
+ const char *, enum omp_clause_code)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void omp_clause_operand_check_failed (int, const_tree, const char *,
+ int, const char *)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+extern void omp_clause_range_check_failed (const_tree, const char *, int,
+ const char *, enum omp_clause_code,
+ enum omp_clause_code)
+ ATTRIBUTE_NORETURN ATTRIBUTE_COLD;
+
+#else /* not ENABLE_TREE_CHECKING, or not gcc */
+
+#define CONTAINS_STRUCT_CHECK(T, ENUM) (T)
+#define TREE_CHECK(T, CODE) (T)
+#define TREE_NOT_CHECK(T, CODE) (T)
+#define TREE_CHECK2(T, CODE1, CODE2) (T)
+#define TREE_NOT_CHECK2(T, CODE1, CODE2) (T)
+#define TREE_CHECK3(T, CODE1, CODE2, CODE3) (T)
+#define TREE_NOT_CHECK3(T, CODE1, CODE2, CODE3) (T)
+#define TREE_CHECK4(T, CODE1, CODE2, CODE3, CODE4) (T)
+#define TREE_NOT_CHECK4(T, CODE1, CODE2, CODE3, CODE4) (T)
+#define TREE_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) (T)
+#define TREE_NOT_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) (T)
+#define TREE_CLASS_CHECK(T, CODE) (T)
+#define TREE_RANGE_CHECK(T, CODE1, CODE2) (T)
+#define EXPR_CHECK(T) (T)
+#define NON_TYPE_CHECK(T) (T)
+#define TREE_INT_CST_ELT_CHECK(T, I) ((T)->int_cst.val[I])
+#define TREE_VEC_ELT_CHECK(T, I) ((T)->vec.a[I])
+#define TREE_OPERAND_CHECK(T, I) ((T)->exp.operands[I])
+#define TREE_OPERAND_CHECK_CODE(T, CODE, I) ((T)->exp.operands[I])
+#define OMP_CLAUSE_ELT_CHECK(T, i) ((T)->omp_clause.ops[i])
+#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) (T)
+#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) (T)
+#define ANY_INTEGRAL_TYPE_CHECK(T) (T)
+
+#define TREE_CHAIN(NODE) ((NODE)->common.chain)
+#define TREE_TYPE(NODE) ((NODE)->typed.type)
+
+#endif
+
+#define TREE_BLOCK(NODE) (tree_block (NODE))
+#define TREE_SET_BLOCK(T, B) (tree_set_block ((T), (B)))
+
+#include "tree-check.h"
+#endif // sdcpp
+
+#if 0 // sdcpp
+#define TYPE_CHECK(T) TREE_CLASS_CHECK (T, tcc_type)
+#define DECL_MINIMAL_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_MINIMAL)
+#define DECL_COMMON_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_COMMON)
+#define DECL_WRTL_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_WRTL)
+#define DECL_WITH_VIS_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_WITH_VIS)
+#define DECL_NON_COMMON_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_NON_COMMON)
+#define CST_CHECK(T) TREE_CLASS_CHECK (T, tcc_constant)
+#define STMT_CHECK(T) TREE_CLASS_CHECK (T, tcc_statement)
+#define VL_EXP_CHECK(T) TREE_CLASS_CHECK (T, tcc_vl_exp)
+#define FUNC_OR_METHOD_CHECK(T) TREE_CHECK2 (T, FUNCTION_TYPE, METHOD_TYPE)
+#define PTR_OR_REF_CHECK(T) TREE_CHECK2 (T, POINTER_TYPE, REFERENCE_TYPE)
+
+#define RECORD_OR_UNION_CHECK(T) \
+ TREE_CHECK3 (T, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE)
+#define NOT_RECORD_OR_UNION_CHECK(T) \
+ TREE_NOT_CHECK3 (T, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE)
+#define ARRAY_OR_INTEGER_TYPE_CHECK(T) \
+ TREE_CHECK2 (T, ARRAY_TYPE, INTEGER_TYPE)
+
+#define NUMERICAL_TYPE_CHECK(T) \
+ TREE_CHECK5 (T, INTEGER_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, REAL_TYPE, \
+ FIXED_POINT_TYPE)
+
+/* Here is how primitive or already-canonicalized types' hash codes
+ are made. */
+#define TYPE_HASH(TYPE) (TYPE_UID (TYPE))
+
+/* A simple hash function for an arbitrary tree node. This must not be
+ used in hash tables which are saved to a PCH. */
+#define TREE_HASH(NODE) ((size_t) (NODE) & 0777777)
+
+/* Tests if CODE is a conversion expr (NOP_EXPR or CONVERT_EXPR). */
+#define CONVERT_EXPR_CODE_P(CODE) \
+ ((CODE) == NOP_EXPR || (CODE) == CONVERT_EXPR)
+
+/* Similarly, but accept an expression instead of a tree code. */
+#define CONVERT_EXPR_P(EXP) CONVERT_EXPR_CODE_P (TREE_CODE (EXP))
+
+/* Generate case for NOP_EXPR, CONVERT_EXPR. */
+
+#define CASE_CONVERT \
+ case NOP_EXPR: \
+ case CONVERT_EXPR
+
+/* Given an expression as a tree, strip any conversion that generates
+ no instruction. Accepts both tree and const_tree arguments since
+ we are not modifying the tree itself. */
+
+#define STRIP_NOPS(EXP) \
+ (EXP) = tree_strip_nop_conversions (CONST_CAST_TREE (EXP))
+
+/* Like STRIP_NOPS, but don't let the signedness change either. */
+
+#define STRIP_SIGN_NOPS(EXP) \
+ (EXP) = tree_strip_sign_nop_conversions (CONST_CAST_TREE (EXP))
+
+/* Like STRIP_NOPS, but don't alter the TREE_TYPE either. */
+
+#define STRIP_TYPE_NOPS(EXP) \
+ while ((CONVERT_EXPR_P (EXP) \
+ || TREE_CODE (EXP) == NON_LVALUE_EXPR) \
+ && TREE_OPERAND (EXP, 0) != error_mark_node \
+ && (TREE_TYPE (EXP) \
+ == TREE_TYPE (TREE_OPERAND (EXP, 0)))) \
+ (EXP) = TREE_OPERAND (EXP, 0)
+
+/* Remove unnecessary type conversions according to
+ tree_ssa_useless_type_conversion. */
+
+#define STRIP_USELESS_TYPE_CONVERSION(EXP) \
+ (EXP) = tree_ssa_strip_useless_type_conversions (EXP)
+
+/* Remove any VIEW_CONVERT_EXPR or NON_LVALUE_EXPR that's purely
+ in use to provide a location_t. */
+
+#define STRIP_ANY_LOCATION_WRAPPER(EXP) \
+ (EXP) = tree_strip_any_location_wrapper (CONST_CAST_TREE (EXP))
+
+/* Nonzero if TYPE represents a vector type. */
+
+#define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
+
+/* Nonzero if TYPE represents a vector of booleans. */
+
+#define VECTOR_BOOLEAN_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == VECTOR_TYPE \
+ && TREE_CODE (TREE_TYPE (TYPE)) == BOOLEAN_TYPE)
+
+/* Nonzero if TYPE represents an integral type. Note that we do not
+ include COMPLEX types here. Keep these checks in ascending code
+ order. */
+
+#define INTEGRAL_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == ENUMERAL_TYPE \
+ || TREE_CODE (TYPE) == BOOLEAN_TYPE \
+ || TREE_CODE (TYPE) == INTEGER_TYPE)
+
+/* Nonzero if TYPE represents an integral type, including complex
+ and vector integer types. */
+
+#define ANY_INTEGRAL_TYPE_P(TYPE) \
+ (INTEGRAL_TYPE_P (TYPE) \
+ || ((TREE_CODE (TYPE) == COMPLEX_TYPE \
+ || VECTOR_TYPE_P (TYPE)) \
+ && INTEGRAL_TYPE_P (TREE_TYPE (TYPE))))
+
+/* Nonzero if TYPE represents a non-saturating fixed-point type. */
+
+#define NON_SAT_FIXED_POINT_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == FIXED_POINT_TYPE && !TYPE_SATURATING (TYPE))
+
+/* Nonzero if TYPE represents a saturating fixed-point type. */
+
+#define SAT_FIXED_POINT_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == FIXED_POINT_TYPE && TYPE_SATURATING (TYPE))
+
+/* Nonzero if TYPE represents a fixed-point type. */
+
+#define FIXED_POINT_TYPE_P(TYPE) (TREE_CODE (TYPE) == FIXED_POINT_TYPE)
+
+/* Nonzero if TYPE represents a scalar floating-point type. */
+
+#define SCALAR_FLOAT_TYPE_P(TYPE) (TREE_CODE (TYPE) == REAL_TYPE)
+
+/* Nonzero if TYPE represents a complex floating-point type. */
+
+#define COMPLEX_FLOAT_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == COMPLEX_TYPE \
+ && TREE_CODE (TREE_TYPE (TYPE)) == REAL_TYPE)
+
+/* Nonzero if TYPE represents a vector integer type. */
+
+#define VECTOR_INTEGER_TYPE_P(TYPE) \
+ (VECTOR_TYPE_P (TYPE) \
+ && TREE_CODE (TREE_TYPE (TYPE)) == INTEGER_TYPE)
+
+
+/* Nonzero if TYPE represents a vector floating-point type. */
+
+#define VECTOR_FLOAT_TYPE_P(TYPE) \
+ (VECTOR_TYPE_P (TYPE) \
+ && TREE_CODE (TREE_TYPE (TYPE)) == REAL_TYPE)
+
+/* Nonzero if TYPE represents a floating-point type, including complex
+ and vector floating-point types. The vector and complex check does
+ not use the previous two macros to enable early folding. */
+
+#define FLOAT_TYPE_P(TYPE) \
+ (SCALAR_FLOAT_TYPE_P (TYPE) \
+ || ((TREE_CODE (TYPE) == COMPLEX_TYPE \
+ || VECTOR_TYPE_P (TYPE)) \
+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TYPE))))
+
+/* Nonzero if TYPE represents a decimal floating-point type. */
+#define DECIMAL_FLOAT_TYPE_P(TYPE) \
+ (SCALAR_FLOAT_TYPE_P (TYPE) \
+ && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TYPE)))
+
+/* Nonzero if TYPE is a record or union type. */
+#define RECORD_OR_UNION_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == RECORD_TYPE \
+ || TREE_CODE (TYPE) == UNION_TYPE \
+ || TREE_CODE (TYPE) == QUAL_UNION_TYPE)
+
+/* Nonzero if TYPE represents an aggregate (multi-component) type.
+ Keep these checks in ascending code order. */
+
+#define AGGREGATE_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == ARRAY_TYPE || RECORD_OR_UNION_TYPE_P (TYPE))
+
+/* Nonzero if TYPE represents a pointer or reference type.
+ (It should be renamed to INDIRECT_TYPE_P.) Keep these checks in
+ ascending code order. */
+
+#define POINTER_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == POINTER_TYPE || TREE_CODE (TYPE) == REFERENCE_TYPE)
+
+/* Nonzero if TYPE represents a pointer to function. */
+#define FUNCTION_POINTER_TYPE_P(TYPE) \
+ (POINTER_TYPE_P (TYPE) && TREE_CODE (TREE_TYPE (TYPE)) == FUNCTION_TYPE)
+
+/* Nonzero if this type is a complete type. */
+#define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE)
+
+/* Nonzero if this type is the (possibly qualified) void type. */
+#define VOID_TYPE_P(NODE) (TREE_CODE (NODE) == VOID_TYPE)
+
+/* Nonzero if this type is complete or is cv void. */
+#define COMPLETE_OR_VOID_TYPE_P(NODE) \
+ (COMPLETE_TYPE_P (NODE) || VOID_TYPE_P (NODE))
+
+/* Nonzero if this type is complete or is an array with unspecified bound. */
+#define COMPLETE_OR_UNBOUND_ARRAY_TYPE_P(NODE) \
+ (COMPLETE_TYPE_P (TREE_CODE (NODE) == ARRAY_TYPE ? TREE_TYPE (NODE) : (NODE)))
+
+#define FUNC_OR_METHOD_TYPE_P(NODE) \
+ (TREE_CODE (NODE) == FUNCTION_TYPE || TREE_CODE (NODE) == METHOD_TYPE)
+
+#define OPAQUE_TYPE_P(NODE) \
+ (TREE_CODE (NODE) == OPAQUE_TYPE)
+
+/* Define many boolean fields that all tree nodes have. */
+
+/* In VAR_DECL, PARM_DECL and RESULT_DECL nodes, nonzero means address
+ of this is needed. So it cannot be in a register.
+ In a FUNCTION_DECL it has no meaning.
+ In LABEL_DECL nodes, it means a goto for this label has been seen
+ from a place outside all binding contours that restore stack levels.
+ In an artificial SSA_NAME that points to a stack partition with at least
+ two variables, it means that at least one variable has TREE_ADDRESSABLE.
+ In ..._TYPE nodes, it means that objects of this type must be fully
+ addressable. This means that pieces of this object cannot go into
+ register parameters, for example. If this a function type, this
+ means that the value must be returned in memory.
+ In CONSTRUCTOR nodes, it means object constructed must be in memory.
+ In IDENTIFIER_NODEs, this means that some extern decl for this name
+ had its address taken. That matters for inline functions.
+ In a STMT_EXPR, it means we want the result of the enclosed expression. */
+#define TREE_ADDRESSABLE(NODE) ((NODE)->base.addressable_flag)
+
+/* Set on a CALL_EXPR if the call is in a tail position, ie. just before the
+ exit of a function. Calls for which this is true are candidates for tail
+ call optimizations. */
+#define CALL_EXPR_TAILCALL(NODE) \
+ (CALL_EXPR_CHECK (NODE)->base.addressable_flag)
+
+/* Set on a CALL_EXPR if the call has been marked as requiring tail call
+ optimization for correctness. */
+#define CALL_EXPR_MUST_TAIL_CALL(NODE) \
+ (CALL_EXPR_CHECK (NODE)->base.static_flag)
+
+/* Used as a temporary field on a CASE_LABEL_EXPR to indicate that the
+ CASE_LOW operand has been processed. */
+#define CASE_LOW_SEEN(NODE) \
+ (CASE_LABEL_EXPR_CHECK (NODE)->base.addressable_flag)
+
+#define PREDICT_EXPR_OUTCOME(NODE) \
+ ((enum prediction) (PREDICT_EXPR_CHECK (NODE)->base.addressable_flag))
+#define SET_PREDICT_EXPR_OUTCOME(NODE, OUTCOME) \
+ (PREDICT_EXPR_CHECK (NODE)->base.addressable_flag = (int) OUTCOME)
+#define PREDICT_EXPR_PREDICTOR(NODE) \
+ ((enum br_predictor)tree_to_shwi (TREE_OPERAND (PREDICT_EXPR_CHECK (NODE), 0)))
+
+/* In a VAR_DECL, nonzero means allocate static storage.
+ In a FUNCTION_DECL, nonzero if function has been defined.
+ In a CONSTRUCTOR, nonzero means allocate static storage. */
+#define TREE_STATIC(NODE) ((NODE)->base.static_flag)
+
+/* In an ADDR_EXPR, nonzero means do not use a trampoline. */
+#define TREE_NO_TRAMPOLINE(NODE) (ADDR_EXPR_CHECK (NODE)->base.static_flag)
+
+/* In a TARGET_EXPR or WITH_CLEANUP_EXPR, means that the pertinent cleanup
+ should only be executed if an exception is thrown, not on normal exit
+ of its scope. */
+#define CLEANUP_EH_ONLY(NODE) ((NODE)->base.static_flag)
+
+/* In a TRY_CATCH_EXPR, means that the handler should be considered a
+ separate cleanup in honor_protect_cleanup_actions. */
+#define TRY_CATCH_IS_CLEANUP(NODE) \
+ (TRY_CATCH_EXPR_CHECK (NODE)->base.static_flag)
+
+/* Used as a temporary field on a CASE_LABEL_EXPR to indicate that the
+ CASE_HIGH operand has been processed. */
+#define CASE_HIGH_SEEN(NODE) \
+ (CASE_LABEL_EXPR_CHECK (NODE)->base.static_flag)
+
+/* Used to mark scoped enums. */
+#define ENUM_IS_SCOPED(NODE) (ENUMERAL_TYPE_CHECK (NODE)->base.static_flag)
+
+/* Determines whether an ENUMERAL_TYPE has defined the list of constants. */
+#define ENUM_IS_OPAQUE(NODE) (ENUMERAL_TYPE_CHECK (NODE)->base.private_flag)
+
+/* In an expr node (usually a conversion) this means the node was made
+ implicitly and should not lead to any sort of warning. In a decl node,
+ warnings concerning the decl should be suppressed. This is used at
+ least for used-before-set warnings, and it set after one warning is
+ emitted. */
+#define TREE_NO_WARNING(NODE) ((NODE)->base.nowarning_flag)
+
+/* Nonzero if we should warn about the change in empty class parameter
+ passing ABI in this TU. */
+#define TRANSLATION_UNIT_WARN_EMPTY_P(NODE) \
+ (TRANSLATION_UNIT_DECL_CHECK (NODE)->decl_common.decl_flag_0)
+
+/* Nonzero if this type is "empty" according to the particular psABI. */
+#define TYPE_EMPTY_P(NODE) (TYPE_CHECK (NODE)->type_common.empty_flag)
+
+/* Used to indicate that this TYPE represents a compiler-generated entity. */
+#define TYPE_ARTIFICIAL(NODE) (TYPE_CHECK (NODE)->base.nowarning_flag)
+
+/* True if the type is indivisible at the source level, i.e. if its
+ component parts cannot be accessed directly. This is used to suppress
+ normal GNU extensions for target-specific vector types. */
+#define TYPE_INDIVISIBLE_P(NODE) (TYPE_CHECK (NODE)->type_common.indivisible_p)
+
+/* In an IDENTIFIER_NODE, this means that assemble_name was called with
+ this string as an argument. */
+#define TREE_SYMBOL_REFERENCED(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->base.static_flag)
+
+/* Nonzero in a pointer or reference type means the data pointed to
+ by this type can alias anything. */
+#define TYPE_REF_CAN_ALIAS_ALL(NODE) \
+ (PTR_OR_REF_CHECK (NODE)->base.static_flag)
+
+/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, or VECTOR_CST, this means
+ there was an overflow in folding. */
+
+#define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag)
+
+/* TREE_OVERFLOW can only be true for EXPR of CONSTANT_CLASS_P. */
+
+#define TREE_OVERFLOW_P(EXPR) \
+ (CONSTANT_CLASS_P (EXPR) && TREE_OVERFLOW (EXPR))
+
+/* In a VAR_DECL, FUNCTION_DECL, NAMESPACE_DECL or TYPE_DECL,
+ nonzero means name is to be accessible from outside this translation unit.
+ In an IDENTIFIER_NODE, nonzero means an external declaration
+ accessible from outside this translation unit was previously seen
+ for this name in an inner scope. */
+#define TREE_PUBLIC(NODE) ((NODE)->base.public_flag)
+
+/* In a _TYPE, indicates whether TYPE_CACHED_VALUES contains a vector
+ of cached values, or is something else. */
+#define TYPE_CACHED_VALUES_P(NODE) (TYPE_CHECK (NODE)->base.public_flag)
+
+/* In a SAVE_EXPR, indicates that the original expression has already
+ been substituted with a VAR_DECL that contains the value. */
+#define SAVE_EXPR_RESOLVED_P(NODE) \
+ (SAVE_EXPR_CHECK (NODE)->base.public_flag)
+
+/* Set on a CALL_EXPR if this stdarg call should be passed the argument
+ pack. */
+#define CALL_EXPR_VA_ARG_PACK(NODE) \
+ (CALL_EXPR_CHECK (NODE)->base.public_flag)
+
+/* In any expression, decl, or constant, nonzero means it has side effects or
+ reevaluation of the whole expression could produce a different value.
+ This is set if any subexpression is a function call, a side effect or a
+ reference to a volatile variable. In a ..._DECL, this is set only if the
+ declaration said `volatile'. This will never be set for a constant. */
+#define TREE_SIDE_EFFECTS(NODE) \
+ (NON_TYPE_CHECK (NODE)->base.side_effects_flag)
+
+/* In a LABEL_DECL, nonzero means this label had its address taken
+ and therefore can never be deleted and is a jump target for
+ computed gotos. */
+#define FORCED_LABEL(NODE) (LABEL_DECL_CHECK (NODE)->base.side_effects_flag)
+
+/* Whether a case or a user-defined label is allowed to fall through to.
+ This is used to implement -Wimplicit-fallthrough. */
+#define FALLTHROUGH_LABEL_P(NODE) \
+ (LABEL_DECL_CHECK (NODE)->base.private_flag)
+
+/* Set on the artificial label created for break; stmt from a switch.
+ This is used to implement -Wimplicit-fallthrough. */
+#define SWITCH_BREAK_LABEL_P(NODE) \
+ (LABEL_DECL_CHECK (NODE)->base.protected_flag)
+
+/* Set on label that is known not to be jumped to, it can be only
+ reached by falling through from previous statements.
+ This is used to implement -Wimplicit-fallthrough. */
+#define UNUSED_LABEL_P(NODE) \
+ (LABEL_DECL_CHECK (NODE)->base.default_def_flag)
+
+/* Nonzero means this expression is volatile in the C sense:
+ its address should be of type `volatile WHATEVER *'.
+ In other words, the declared item is volatile qualified.
+ This is used in _DECL nodes and _REF nodes.
+ On a FUNCTION_DECL node, this means the function does not
+ return normally. This is the same effect as setting
+ the attribute noreturn on the function in C.
+
+ In a ..._TYPE node, means this type is volatile-qualified.
+ But use TYPE_VOLATILE instead of this macro when the node is a type,
+ because eventually we may make that a different bit.
+
+ If this bit is set in an expression, so is TREE_SIDE_EFFECTS. */
+#define TREE_THIS_VOLATILE(NODE) ((NODE)->base.volatile_flag)
+
+/* Nonzero means this node will not trap. In an INDIRECT_REF, means
+ accessing the memory pointed to won't generate a trap. However,
+ this only applies to an object when used appropriately: it doesn't
+ mean that writing a READONLY mem won't trap.
+
+ In ARRAY_REF and ARRAY_RANGE_REF means that we know that the index
+ (or slice of the array) always belongs to the range of the array.
+ I.e. that the access will not trap, provided that the access to
+ the base to the array will not trap. */
+#define TREE_THIS_NOTRAP(NODE) \
+ (TREE_CHECK5 (NODE, INDIRECT_REF, MEM_REF, TARGET_MEM_REF, ARRAY_REF, \
+ ARRAY_RANGE_REF)->base.nothrow_flag)
+
+/* In a VAR_DECL, PARM_DECL or FIELD_DECL, or any kind of ..._REF node,
+ nonzero means it may not be the lhs of an assignment.
+ Nonzero in a FUNCTION_DECL means this function should be treated
+ as "const" function (can only read its arguments). */
+#define TREE_READONLY(NODE) (NON_TYPE_CHECK (NODE)->base.readonly_flag)
+
+/* Value of expression is constant. Always on in all ..._CST nodes. May
+ also appear in an expression or decl where the value is constant. */
+#define TREE_CONSTANT(NODE) (NON_TYPE_CHECK (NODE)->base.constant_flag)
+
+/* Nonzero if NODE, a type, has had its sizes gimplified. */
+#define TYPE_SIZES_GIMPLIFIED(NODE) \
+ (TYPE_CHECK (NODE)->base.constant_flag)
+
+/* In a decl (most significantly a FIELD_DECL), means an unsigned field. */
+#define DECL_UNSIGNED(NODE) \
+ (DECL_COMMON_CHECK (NODE)->base.u.bits.unsigned_flag)
+
+/* In integral and pointer types, means an unsigned type. */
+#define TYPE_UNSIGNED(NODE) (TYPE_CHECK (NODE)->base.u.bits.unsigned_flag)
+
+/* Same as TYPE_UNSIGNED but converted to SIGNOP. */
+#define TYPE_SIGN(NODE) ((signop) TYPE_UNSIGNED (NODE))
+
+/* True if overflow wraps around for the given integral or pointer type. That
+ is, TYPE_MAX + 1 == TYPE_MIN. */
+#define TYPE_OVERFLOW_WRAPS(TYPE) \
+ (POINTER_TYPE_P (TYPE) \
+ ? flag_wrapv_pointer \
+ : (ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \
+ || flag_wrapv))
+
+/* True if overflow is undefined for the given integral or pointer type.
+ We may optimize on the assumption that values in the type never overflow.
+
+ IMPORTANT NOTE: Any optimization based on TYPE_OVERFLOW_UNDEFINED
+ must issue a warning based on warn_strict_overflow. In some cases
+ it will be appropriate to issue the warning immediately, and in
+ other cases it will be appropriate to simply set a flag and let the
+ caller decide whether a warning is appropriate or not. */
+#define TYPE_OVERFLOW_UNDEFINED(TYPE) \
+ (POINTER_TYPE_P (TYPE) \
+ ? !flag_wrapv_pointer \
+ : (!ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag \
+ && !flag_wrapv && !flag_trapv))
+
+/* True if overflow for the given integral type should issue a
+ trap. */
+#define TYPE_OVERFLOW_TRAPS(TYPE) \
+ (!ANY_INTEGRAL_TYPE_CHECK(TYPE)->base.u.bits.unsigned_flag && flag_trapv)
+
+/* True if an overflow is to be preserved for sanitization. */
+#define TYPE_OVERFLOW_SANITIZED(TYPE) \
+ (INTEGRAL_TYPE_P (TYPE) \
+ && !TYPE_OVERFLOW_WRAPS (TYPE) \
+ && (flag_sanitize & SANITIZE_SI_OVERFLOW))
+
+/* Nonzero in a VAR_DECL or STRING_CST means assembler code has been written.
+ Nonzero in a FUNCTION_DECL means that the function has been compiled.
+ This is interesting in an inline function, since it might not need
+ to be compiled separately.
+ Nonzero in a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ENUMERAL_TYPE
+ or TYPE_DECL if the debugging info for the type has been written.
+ In a BLOCK node, nonzero if reorder_blocks has already seen this block.
+ In an SSA_NAME node, nonzero if the SSA_NAME occurs in an abnormal
+ PHI node. */
+#define TREE_ASM_WRITTEN(NODE) ((NODE)->base.asm_written_flag)
+
+/* Nonzero in a _DECL if the name is used in its scope.
+ Nonzero in an expr node means inhibit warning if value is unused.
+ In IDENTIFIER_NODEs, this means that some extern decl for this name
+ was used.
+ In a BLOCK, this means that the block contains variables that are used. */
+#define TREE_USED(NODE) ((NODE)->base.used_flag)
+
+/* In a FUNCTION_DECL, nonzero means a call to the function cannot
+ throw an exception. In a CALL_EXPR, nonzero means the call cannot
+ throw. We can't easily check the node type here as the C++
+ frontend also uses this flag (for AGGR_INIT_EXPR). */
+#define TREE_NOTHROW(NODE) ((NODE)->base.nothrow_flag)
+
+/* In a CALL_EXPR, means that it's safe to use the target of the call
+ expansion as the return slot for a call that returns in memory. */
+#define CALL_EXPR_RETURN_SLOT_OPT(NODE) \
+ (CALL_EXPR_CHECK (NODE)->base.private_flag)
+
+/* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is
+ passed by invisible reference (and the TREE_TYPE is a pointer to the true
+ type). */
+#define DECL_BY_REFERENCE(NODE) \
+ (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, \
+ RESULT_DECL)->decl_common.decl_by_reference_flag)
+
+/* In VAR_DECL and PARM_DECL, set when the decl has been used except for
+ being set. */
+#define DECL_READ_P(NODE) \
+ (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_read_flag)
+
+/* In VAR_DECL or RESULT_DECL, set when significant code movement precludes
+ attempting to share the stack slot with some other variable. */
+#define DECL_NONSHAREABLE(NODE) \
+ (TREE_CHECK2 (NODE, VAR_DECL, \
+ RESULT_DECL)->decl_common.decl_nonshareable_flag)
+
+/* In a PARM_DECL, set for Fortran hidden string length arguments that some
+ buggy callers don't pass to the callee. */
+#define DECL_HIDDEN_STRING_LENGTH(NODE) \
+ (TREE_CHECK (NODE, PARM_DECL)->decl_common.decl_nonshareable_flag)
+
+/* In a CALL_EXPR, means that the call is the jump from a thunk to the
+ thunked-to function. Be careful to avoid using this macro when one of the
+ next two applies instead. */
+#define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag)
+
+/* In a CALL_EXPR, if the function being called is BUILT_IN_ALLOCA, means that
+ it has been built for the declaration of a variable-sized object and, if the
+ function being called is BUILT_IN_MEMCPY, means that it has been built for
+ the assignment of a variable-sized object. */
+#define CALL_ALLOCA_FOR_VAR_P(NODE) \
+ (CALL_EXPR_CHECK (NODE)->base.protected_flag)
+
+/* In a CALL_EXPR, if the function being called is DECL_IS_OPERATOR_NEW_P or
+ DECL_IS_OPERATOR_DELETE_P, true for allocator calls from C++ new or delete
+ expressions. Not set for C++20 destroying delete operators. */
+#define CALL_FROM_NEW_OR_DELETE_P(NODE) \
+ (CALL_EXPR_CHECK (NODE)->base.protected_flag)
+
+/* Used in classes in C++. */
+#define TREE_PRIVATE(NODE) ((NODE)->base.private_flag)
+/* Used in classes in C++. */
+#define TREE_PROTECTED(NODE) ((NODE)->base.protected_flag)
+
+/* True if reference type NODE is a C++ rvalue reference. */
+#define TYPE_REF_IS_RVALUE(NODE) \
+ (REFERENCE_TYPE_CHECK (NODE)->base.private_flag)
+
+/* Nonzero in a _DECL if the use of the name is defined as a
+ deprecated feature by __attribute__((deprecated)). */
+#define TREE_DEPRECATED(NODE) \
+ ((NODE)->base.deprecated_flag)
+
+/* Nonzero in a _DECL if the use of the name is defined as an
+ unavailable feature by __attribute__((unavailable)). */
+#define TREE_UNAVAILABLE(NODE) \
+ ((NODE)->base.u.bits.unavailable_flag)
+
+/* Nonzero indicates an IDENTIFIER_NODE that names an anonymous
+ aggregate, (as created by anon_aggr_name_format). */
+#define IDENTIFIER_ANON_P(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->base.private_flag)
+
+/* Nonzero in an IDENTIFIER_NODE if the name is a local alias, whose
+ uses are to be substituted for uses of the TREE_CHAINed identifier. */
+#define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->base.deprecated_flag)
+
+/* In an aggregate type, indicates that the scalar fields of the type are
+ stored in reverse order from the target order. This effectively
+ toggles BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN within the type. */
+#define TYPE_REVERSE_STORAGE_ORDER(NODE) \
+ (TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE)->base.u.bits.saturating_flag)
+
+/* In a non-aggregate type, indicates a saturating type. */
+#define TYPE_SATURATING(NODE) \
+ (TREE_NOT_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, ARRAY_TYPE)->base.u.bits.saturating_flag)
+
+/* In a BIT_FIELD_REF and MEM_REF, indicates that the reference is to a group
+ of bits stored in reverse order from the target order. This effectively
+ toggles both BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN for the reference.
+
+ The overall strategy is to preserve the invariant that every scalar in
+ memory is associated with a single storage order, i.e. all accesses to
+ this scalar are done with the same storage order. This invariant makes
+ it possible to factor out the storage order in most transformations, as
+ only the address and/or the value (in target order) matter for them.
+ But, of course, the storage order must be preserved when the accesses
+ themselves are rewritten or transformed. */
+#define REF_REVERSE_STORAGE_ORDER(NODE) \
+ (TREE_CHECK2 (NODE, BIT_FIELD_REF, MEM_REF)->base.default_def_flag)
+
+ /* In an ADDR_EXPR, indicates that this is a pointer to nested function
+ represented by a descriptor instead of a trampoline. */
+#define FUNC_ADDR_BY_DESCRIPTOR(NODE) \
+ (TREE_CHECK (NODE, ADDR_EXPR)->base.default_def_flag)
+
+/* In a CALL_EXPR, indicates that this is an indirect call for which
+ pointers to nested function are descriptors instead of trampolines. */
+#define CALL_EXPR_BY_DESCRIPTOR(NODE) \
+ (TREE_CHECK (NODE, CALL_EXPR)->base.default_def_flag)
+
+/* These flags are available for each language front end to use internally. */
+#define TREE_LANG_FLAG_0(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_0)
+#define TREE_LANG_FLAG_1(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_1)
+#define TREE_LANG_FLAG_2(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_2)
+#define TREE_LANG_FLAG_3(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_3)
+#define TREE_LANG_FLAG_4(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_4)
+#define TREE_LANG_FLAG_5(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_5)
+#define TREE_LANG_FLAG_6(NODE) \
+ (TREE_NOT_CHECK2 (NODE, TREE_VEC, SSA_NAME)->base.u.bits.lang_flag_6)
+
+/* Define additional fields and accessors for nodes representing constants. */
+
+#define TREE_INT_CST_NUNITS(NODE) \
+ (INTEGER_CST_CHECK (NODE)->base.u.int_length.unextended)
+#define TREE_INT_CST_EXT_NUNITS(NODE) \
+ (INTEGER_CST_CHECK (NODE)->base.u.int_length.extended)
+#define TREE_INT_CST_OFFSET_NUNITS(NODE) \
+ (INTEGER_CST_CHECK (NODE)->base.u.int_length.offset)
+#define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I)
+#define TREE_INT_CST_LOW(NODE) \
+ ((unsigned HOST_WIDE_INT) TREE_INT_CST_ELT (NODE, 0))
+
+/* Return true if NODE is a POLY_INT_CST. This is only ever true on
+ targets with variable-sized modes. */
+#if 0 // sdcpp
+#define POLY_INT_CST_P(NODE) \
+ (NUM_POLY_INT_COEFFS > 1 && TREE_CODE (NODE) == POLY_INT_CST)
+
+/* In a POLY_INT_CST node. */
+#define POLY_INT_CST_COEFF(NODE, I) \
+ (POLY_INT_CST_CHECK (NODE)->poly_int_cst.coeffs[I])
+#endif // sdcpp
+
+#define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
+#define TREE_REAL_CST(NODE) (*TREE_REAL_CST_PTR (NODE))
+
+#define TREE_FIXED_CST_PTR(NODE) \
+ (FIXED_CST_CHECK (NODE)->fixed_cst.fixed_cst_ptr)
+#define TREE_FIXED_CST(NODE) (*TREE_FIXED_CST_PTR (NODE))
+
+/* In a STRING_CST */
+/* In C terms, this is sizeof, not strlen. */
+#define TREE_STRING_LENGTH(NODE) (STRING_CST_CHECK (NODE)->string.length)
+#define TREE_STRING_POINTER(NODE) \
+ ((const char *)(STRING_CST_CHECK (NODE)->string.str))
+
+/* In a COMPLEX_CST node. */
+#define TREE_REALPART(NODE) (COMPLEX_CST_CHECK (NODE)->complex.real)
+#define TREE_IMAGPART(NODE) (COMPLEX_CST_CHECK (NODE)->complex.imag)
+
+/* In a VECTOR_CST node. See generic.texi for details. */
+#define VECTOR_CST_NELTS(NODE) (TYPE_VECTOR_SUBPARTS (TREE_TYPE (NODE)))
+#define VECTOR_CST_ELT(NODE,IDX) vector_cst_elt (NODE, IDX)
+
+#define VECTOR_CST_LOG2_NPATTERNS(NODE) \
+ (VECTOR_CST_CHECK (NODE)->base.u.vector_cst.log2_npatterns)
+#define VECTOR_CST_NPATTERNS(NODE) \
+ (1U << VECTOR_CST_LOG2_NPATTERNS (NODE))
+#define VECTOR_CST_NELTS_PER_PATTERN(NODE) \
+ (VECTOR_CST_CHECK (NODE)->base.u.vector_cst.nelts_per_pattern)
+#define VECTOR_CST_DUPLICATE_P(NODE) \
+ (VECTOR_CST_NELTS_PER_PATTERN (NODE) == 1)
+#define VECTOR_CST_STEPPED_P(NODE) \
+ (VECTOR_CST_NELTS_PER_PATTERN (NODE) == 3)
+#define VECTOR_CST_ENCODED_ELTS(NODE) \
+ (VECTOR_CST_CHECK (NODE)->vector.elts)
+#define VECTOR_CST_ENCODED_ELT(NODE, ELT) \
+ (VECTOR_CST_CHECK (NODE)->vector.elts[ELT])
+
+/* Define fields and accessors for some special-purpose tree nodes. */
+
+/* As with STRING_CST, in C terms this is sizeof, not strlen. */
+#define IDENTIFIER_LENGTH(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.len)
+#define IDENTIFIER_POINTER(NODE) \
+ ((const char *) IDENTIFIER_NODE_CHECK (NODE)->identifier.id.str)
+#define IDENTIFIER_HASH_VALUE(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.hash_value)
+
+/* Translate a hash table identifier pointer to a tree_identifier
+ pointer, and vice versa. */
+
+#define HT_IDENT_TO_GCC_IDENT(NODE) \
+ ((tree) ((char *) (NODE) - sizeof (struct tree_common)))
+#define GCC_IDENT_TO_HT_IDENT(NODE) (&((struct tree_identifier *) (NODE))->id)
+
+/* In a TREE_LIST node. */
+#define TREE_PURPOSE(NODE) (TREE_LIST_CHECK (NODE)->list.purpose)
+#define TREE_VALUE(NODE) (TREE_LIST_CHECK (NODE)->list.value)
+
+/* In a TREE_VEC node. */
+#define TREE_VEC_LENGTH(NODE) (TREE_VEC_CHECK (NODE)->base.u.length)
+#define TREE_VEC_END(NODE) \
+ ((void) TREE_VEC_CHECK (NODE), &((NODE)->vec.a[(NODE)->vec.base.u.length]))
+
+#define TREE_VEC_ELT(NODE,I) TREE_VEC_ELT_CHECK (NODE, I)
+
+/* In a CONSTRUCTOR node. */
+#define CONSTRUCTOR_ELTS(NODE) (CONSTRUCTOR_CHECK (NODE)->constructor.elts)
+#define CONSTRUCTOR_ELT(NODE,IDX) \
+ (&(*CONSTRUCTOR_ELTS (NODE))[IDX])
+#define CONSTRUCTOR_NELTS(NODE) \
+ (vec_safe_length (CONSTRUCTOR_ELTS (NODE)))
+#define CONSTRUCTOR_NO_CLEARING(NODE) \
+ (CONSTRUCTOR_CHECK (NODE)->base.public_flag)
+
+/* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding the
+ value of each element (stored within VAL). IX must be a scratch variable
+ of unsigned integer type. */
+#define FOR_EACH_CONSTRUCTOR_VALUE(V, IX, VAL) \
+ for (IX = 0; (IX >= vec_safe_length (V)) \
+ ? false \
+ : ((VAL = (*(V))[IX].value), \
+ true); \
+ (IX)++)
+
+/* Iterate through the vector V of CONSTRUCTOR_ELT elements, yielding both
+ the value of each element (stored within VAL) and its index (stored
+ within INDEX). IX must be a scratch variable of unsigned integer type. */
+#define FOR_EACH_CONSTRUCTOR_ELT(V, IX, INDEX, VAL) \
+ for (IX = 0; (IX >= vec_safe_length (V)) \
+ ? false \
+ : (((void) (VAL = (*V)[IX].value)), \
+ (INDEX = (*V)[IX].index), \
+ true); \
+ (IX)++)
+
+/* Append a new constructor element to V, with the specified INDEX and VAL. */
+#define CONSTRUCTOR_APPEND_ELT(V, INDEX, VALUE) \
+ do { \
+ constructor_elt _ce___ = {INDEX, VALUE}; \
+ vec_safe_push ((V), _ce___); \
+ } while (0)
+
+/* True if NODE, a FIELD_DECL, is to be processed as a bitfield for
+ constructor output purposes. */
+#define CONSTRUCTOR_BITFIELD_P(NODE) \
+ (DECL_BIT_FIELD (FIELD_DECL_CHECK (NODE)) && DECL_MODE (NODE) != BLKmode)
+
+/* True if NODE is a clobber right hand side, an expression of indeterminate
+ value that clobbers the LHS in a copy instruction. We use a volatile
+ empty CONSTRUCTOR for this, as it matches most of the necessary semantic.
+ In particular the volatile flag causes us to not prematurely remove
+ such clobber instructions. */
+#define TREE_CLOBBER_P(NODE) \
+ (TREE_CODE (NODE) == CONSTRUCTOR && TREE_THIS_VOLATILE (NODE))
+
+/* Return the clobber_kind of a CLOBBER CONSTRUCTOR. */
+#define CLOBBER_KIND(NODE) \
+ (CONSTRUCTOR_CHECK (NODE)->base.u.bits.address_space)
+
+/* Define fields and accessors for some nodes that represent expressions. */
+
+/* Nonzero if NODE is an empty statement (NOP_EXPR <0>). */
+#define IS_EMPTY_STMT(NODE) (TREE_CODE (NODE) == NOP_EXPR \
+ && VOID_TYPE_P (TREE_TYPE (NODE)) \
+ && integer_zerop (TREE_OPERAND (NODE, 0)))
+
+/* In ordinary expression nodes. */
+#define TREE_OPERAND_LENGTH(NODE) tree_operand_length (NODE)
+#define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
+
+/* In a tcc_vl_exp node, operand 0 is an INT_CST node holding the operand
+ length. Its value includes the length operand itself; that is,
+ the minimum valid length is 1.
+ Note that we have to bypass the use of TREE_OPERAND to access
+ that field to avoid infinite recursion in expanding the macros. */
+#define VL_EXP_OPERAND_LENGTH(NODE) \
+ ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0]))
+
+/* Nonzero if gimple_debug_nonbind_marker_p() may possibly hold. */
+#define MAY_HAVE_DEBUG_MARKER_STMTS debug_nonbind_markers_p
+/* Nonzero if gimple_debug_bind_p() (and thus
+ gimple_debug_source_bind_p()) may possibly hold. */
+#define MAY_HAVE_DEBUG_BIND_STMTS flag_var_tracking_assignments
+/* Nonzero if is_gimple_debug() may possibly hold. */
+#define MAY_HAVE_DEBUG_STMTS \
+ (MAY_HAVE_DEBUG_MARKER_STMTS || MAY_HAVE_DEBUG_BIND_STMTS)
+
+/* In a LOOP_EXPR node. */
+#define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
+
+/* The source location of this expression. Non-tree_exp nodes such as
+ decls and constants can be shared among multiple locations, so
+ return nothing. */
+#define EXPR_LOCATION(NODE) \
+ (CAN_HAVE_LOCATION_P ((NODE)) ? (NODE)->exp.locus : UNKNOWN_LOCATION)
+#define SET_EXPR_LOCATION(NODE, LOCUS) EXPR_CHECK ((NODE))->exp.locus = (LOCUS)
+#define EXPR_HAS_LOCATION(NODE) (LOCATION_LOCUS (EXPR_LOCATION (NODE)) \
+ != UNKNOWN_LOCATION)
+/* The location to be used in a diagnostic about this expression. Do not
+ use this macro if the location will be assigned to other expressions. */
+#define EXPR_LOC_OR_LOC(NODE, LOCUS) (EXPR_HAS_LOCATION (NODE) \
+ ? (NODE)->exp.locus : (LOCUS))
+#define EXPR_FILENAME(NODE) LOCATION_FILE (EXPR_CHECK ((NODE))->exp.locus)
+#define EXPR_LINENO(NODE) LOCATION_LINE (EXPR_CHECK (NODE)->exp.locus)
+
+#define CAN_HAVE_RANGE_P(NODE) (CAN_HAVE_LOCATION_P (NODE))
+#define EXPR_LOCATION_RANGE(NODE) (get_expr_source_range (EXPR_CHECK ((NODE))))
+
+#define EXPR_HAS_RANGE(NODE) \
+ (CAN_HAVE_RANGE_P (NODE) \
+ ? EXPR_LOCATION_RANGE (NODE).m_start != UNKNOWN_LOCATION \
+ : false)
+
+/* True if a tree is an expression or statement that can have a
+ location. */
+#define CAN_HAVE_LOCATION_P(NODE) ((NODE) && EXPR_P (NODE))
+
+static inline source_range
+get_expr_source_range (tree expr)
+{
+ location_t loc = EXPR_LOCATION (expr);
+ return get_range_from_loc (line_table, loc);
+}
+
+extern void protected_set_expr_location (tree, location_t);
+extern void protected_set_expr_location_if_unset (tree, location_t);
+
+WARN_UNUSED_RESULT extern tree maybe_wrap_with_location (tree, location_t);
+
+extern int suppress_location_wrappers;
+
+/* A class for suppressing the creation of location wrappers.
+ Location wrappers will not be created during the lifetime
+ of an instance of this class. */
+
+class auto_suppress_location_wrappers
+{
+ public:
+ auto_suppress_location_wrappers () { ++suppress_location_wrappers; }
+ ~auto_suppress_location_wrappers () { --suppress_location_wrappers; }
+};
+
+/* In a TARGET_EXPR node. */
+#define TARGET_EXPR_SLOT(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 0)
+#define TARGET_EXPR_INITIAL(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 1)
+#define TARGET_EXPR_CLEANUP(NODE) TREE_OPERAND_CHECK_CODE (NODE, TARGET_EXPR, 2)
+/* Don't elide the initialization of TARGET_EXPR_SLOT for this TARGET_EXPR
+ on rhs of MODIFY_EXPR. */
+#define TARGET_EXPR_NO_ELIDE(NODE) (TARGET_EXPR_CHECK (NODE)->base.private_flag)
+
+/* DECL_EXPR accessor. This gives access to the DECL associated with
+ the given declaration statement. */
+#define DECL_EXPR_DECL(NODE) TREE_OPERAND (DECL_EXPR_CHECK (NODE), 0)
+
+#define EXIT_EXPR_COND(NODE) TREE_OPERAND (EXIT_EXPR_CHECK (NODE), 0)
+
+/* COMPOUND_LITERAL_EXPR accessors. */
+#define COMPOUND_LITERAL_EXPR_DECL_EXPR(NODE) \
+ TREE_OPERAND (COMPOUND_LITERAL_EXPR_CHECK (NODE), 0)
+#define COMPOUND_LITERAL_EXPR_DECL(NODE) \
+ DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_EXPR (NODE))
+
+/* SWITCH_EXPR accessors. These give access to the condition and body. */
+#define SWITCH_COND(NODE) TREE_OPERAND (SWITCH_EXPR_CHECK (NODE), 0)
+#define SWITCH_BODY(NODE) TREE_OPERAND (SWITCH_EXPR_CHECK (NODE), 1)
+/* True if there are case labels for all possible values of SWITCH_COND, either
+ because there is a default: case label or because the case label ranges cover
+ all values. */
+#define SWITCH_ALL_CASES_P(NODE) (SWITCH_EXPR_CHECK (NODE)->base.private_flag)
+
+/* CASE_LABEL_EXPR accessors. These give access to the high and low values
+ of a case label, respectively. */
+#define CASE_LOW(NODE) TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 0)
+#define CASE_HIGH(NODE) TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 1)
+#define CASE_LABEL(NODE) TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 2)
+#define CASE_CHAIN(NODE) TREE_OPERAND (CASE_LABEL_EXPR_CHECK (NODE), 3)
+
+/* The operands of a TARGET_MEM_REF. Operands 0 and 1 have to match
+ corresponding MEM_REF operands. */
+#define TMR_BASE(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 0))
+#define TMR_OFFSET(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 1))
+#define TMR_INDEX(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 2))
+#define TMR_STEP(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 3))
+#define TMR_INDEX2(NODE) (TREE_OPERAND (TARGET_MEM_REF_CHECK (NODE), 4))
+
+#define MR_DEPENDENCE_CLIQUE(NODE) \
+ (TREE_CHECK2 (NODE, MEM_REF, TARGET_MEM_REF)->base.u.dependence_info.clique)
+#define MR_DEPENDENCE_BASE(NODE) \
+ (TREE_CHECK2 (NODE, MEM_REF, TARGET_MEM_REF)->base.u.dependence_info.base)
+
+/* The operands of a BIND_EXPR. */
+#define BIND_EXPR_VARS(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 0))
+#define BIND_EXPR_BODY(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 1))
+#define BIND_EXPR_BLOCK(NODE) (TREE_OPERAND (BIND_EXPR_CHECK (NODE), 2))
+
+/* GOTO_EXPR accessor. This gives access to the label associated with
+ a goto statement. */
+#define GOTO_DESTINATION(NODE) TREE_OPERAND (GOTO_EXPR_CHECK (NODE), 0)
+
+/* ASM_EXPR accessors. ASM_STRING returns a STRING_CST for the
+ instruction (e.g., "mov x, y"). ASM_OUTPUTS, ASM_INPUTS, and
+ ASM_CLOBBERS represent the outputs, inputs, and clobbers for the
+ statement. */
+#define ASM_STRING(NODE) TREE_OPERAND (ASM_EXPR_CHECK (NODE), 0)
+#define ASM_OUTPUTS(NODE) TREE_OPERAND (ASM_EXPR_CHECK (NODE), 1)
+#define ASM_INPUTS(NODE) TREE_OPERAND (ASM_EXPR_CHECK (NODE), 2)
+#define ASM_CLOBBERS(NODE) TREE_OPERAND (ASM_EXPR_CHECK (NODE), 3)
+#define ASM_LABELS(NODE) TREE_OPERAND (ASM_EXPR_CHECK (NODE), 4)
+/* Nonzero if we want to create an ASM_INPUT instead of an
+ ASM_OPERAND with no operands. */
+#define ASM_INPUT_P(NODE) (ASM_EXPR_CHECK (NODE)->base.static_flag)
+#define ASM_VOLATILE_P(NODE) (ASM_EXPR_CHECK (NODE)->base.public_flag)
+/* Nonzero if we want to consider this asm as minimum length and cost
+ for inlining decisions. */
+#define ASM_INLINE_P(NODE) (ASM_EXPR_CHECK (NODE)->base.protected_flag)
+
+/* COND_EXPR accessors. */
+#define COND_EXPR_COND(NODE) (TREE_OPERAND (COND_EXPR_CHECK (NODE), 0))
+#define COND_EXPR_THEN(NODE) (TREE_OPERAND (COND_EXPR_CHECK (NODE), 1))
+#define COND_EXPR_ELSE(NODE) (TREE_OPERAND (COND_EXPR_CHECK (NODE), 2))
+
+/* Accessors for the chains of recurrences. */
+#define CHREC_LEFT(NODE) TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 0)
+#define CHREC_RIGHT(NODE) TREE_OPERAND (POLYNOMIAL_CHREC_CHECK (NODE), 1)
+#define CHREC_VARIABLE(NODE) POLYNOMIAL_CHREC_CHECK (NODE)->base.u.chrec_var
+
+/* LABEL_EXPR accessor. This gives access to the label associated with
+ the given label expression. */
+#define LABEL_EXPR_LABEL(NODE) TREE_OPERAND (LABEL_EXPR_CHECK (NODE), 0)
+
+/* CATCH_EXPR accessors. */
+#define CATCH_TYPES(NODE) TREE_OPERAND (CATCH_EXPR_CHECK (NODE), 0)
+#define CATCH_BODY(NODE) TREE_OPERAND (CATCH_EXPR_CHECK (NODE), 1)
+
+/* EH_FILTER_EXPR accessors. */
+#define EH_FILTER_TYPES(NODE) TREE_OPERAND (EH_FILTER_EXPR_CHECK (NODE), 0)
+#define EH_FILTER_FAILURE(NODE) TREE_OPERAND (EH_FILTER_EXPR_CHECK (NODE), 1)
+
+/* OBJ_TYPE_REF accessors. */
+#define OBJ_TYPE_REF_EXPR(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 0)
+#define OBJ_TYPE_REF_OBJECT(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 1)
+#define OBJ_TYPE_REF_TOKEN(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 2)
+
+/* ASSERT_EXPR accessors. */
+#define ASSERT_EXPR_VAR(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 0)
+#define ASSERT_EXPR_COND(NODE) TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 1)
+
+/* CALL_EXPR accessors. */
+#define CALL_EXPR_FN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 1)
+#define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 2)
+#define CALL_EXPR_ARG(NODE, I) TREE_OPERAND (CALL_EXPR_CHECK (NODE), (I) + 3)
+#define call_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH (NODE) - 3)
+#define CALL_EXPR_IFN(NODE) (CALL_EXPR_CHECK (NODE)->base.u.ifn)
+
+/* CALL_EXPR_ARGP returns a pointer to the argument vector for NODE.
+ We can't use &CALL_EXPR_ARG (NODE, 0) because that will complain if
+ the argument count is zero when checking is enabled. Instead, do
+ the pointer arithmetic to advance past the 3 fixed operands in a
+ CALL_EXPR. That produces a valid pointer to just past the end of the
+ operand array, even if it's not valid to dereference it. */
+#define CALL_EXPR_ARGP(NODE) \
+ (&(TREE_OPERAND (CALL_EXPR_CHECK (NODE), 0)) + 3)
+
+/* TM directives and accessors. */
+#define TRANSACTION_EXPR_BODY(NODE) \
+ TREE_OPERAND (TRANSACTION_EXPR_CHECK (NODE), 0)
+#define TRANSACTION_EXPR_OUTER(NODE) \
+ (TRANSACTION_EXPR_CHECK (NODE)->base.static_flag)
+#define TRANSACTION_EXPR_RELAXED(NODE) \
+ (TRANSACTION_EXPR_CHECK (NODE)->base.public_flag)
+
+/* OpenMP and OpenACC directive and clause accessors. */
+
+#if 0 // sdcpp
+/* Generic accessors for OMP nodes that keep the body as operand 0, and clauses
+ as operand 1. */
+#define OMP_BODY(NODE) \
+ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_MASTER), 0)
+#define OMP_CLAUSES(NODE) \
+ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SCAN), 1)
+
+/* Generic accessors for OMP nodes that keep clauses as operand 0. */
+#define OMP_STANDALONE_CLAUSES(NODE) \
+ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_CACHE, OMP_TARGET_EXIT_DATA), 0)
+
+#define OACC_DATA_BODY(NODE) \
+ TREE_OPERAND (OACC_DATA_CHECK (NODE), 0)
+#define OACC_DATA_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_DATA_CHECK (NODE), 1)
+
+#define OACC_HOST_DATA_BODY(NODE) \
+ TREE_OPERAND (OACC_HOST_DATA_CHECK (NODE), 0)
+#define OACC_HOST_DATA_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_HOST_DATA_CHECK (NODE), 1)
+
+#define OACC_CACHE_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_CACHE_CHECK (NODE), 0)
+
+#define OACC_DECLARE_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_DECLARE_CHECK (NODE), 0)
+
+#define OACC_ENTER_DATA_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_ENTER_DATA_CHECK (NODE), 0)
+
+#define OACC_EXIT_DATA_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_EXIT_DATA_CHECK (NODE), 0)
+
+#define OACC_UPDATE_CLAUSES(NODE) \
+ TREE_OPERAND (OACC_UPDATE_CHECK (NODE), 0)
+
+#define OMP_PARALLEL_BODY(NODE) TREE_OPERAND (OMP_PARALLEL_CHECK (NODE), 0)
+#define OMP_PARALLEL_CLAUSES(NODE) TREE_OPERAND (OMP_PARALLEL_CHECK (NODE), 1)
+
+#define OMP_TASK_BODY(NODE) TREE_OPERAND (OMP_TASK_CHECK (NODE), 0)
+#define OMP_TASK_CLAUSES(NODE) TREE_OPERAND (OMP_TASK_CHECK (NODE), 1)
+
+#define OMP_TASKREG_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_PARALLEL, OMP_TASK)
+#define OMP_TASKREG_BODY(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 0)
+#define OMP_TASKREG_CLAUSES(NODE) TREE_OPERAND (OMP_TASKREG_CHECK (NODE), 1)
+
+#define OMP_LOOPING_CHECK(NODE) TREE_RANGE_CHECK (NODE, OMP_FOR, OACC_LOOP)
+#define OMP_FOR_BODY(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 0)
+#define OMP_FOR_CLAUSES(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 1)
+#define OMP_FOR_INIT(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 2)
+#define OMP_FOR_COND(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 3)
+#define OMP_FOR_INCR(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 4)
+#define OMP_FOR_PRE_BODY(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 5)
+#define OMP_FOR_ORIG_DECLS(NODE) TREE_OPERAND (OMP_LOOPING_CHECK (NODE), 6)
+
+#define OMP_SECTIONS_BODY(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 0)
+#define OMP_SECTIONS_CLAUSES(NODE) TREE_OPERAND (OMP_SECTIONS_CHECK (NODE), 1)
+
+#define OMP_SECTION_BODY(NODE) TREE_OPERAND (OMP_SECTION_CHECK (NODE), 0)
+
+#define OMP_SINGLE_BODY(NODE) TREE_OPERAND (OMP_SINGLE_CHECK (NODE), 0)
+#define OMP_SINGLE_CLAUSES(NODE) TREE_OPERAND (OMP_SINGLE_CHECK (NODE), 1)
+
+#define OMP_SCOPE_BODY(NODE) TREE_OPERAND (OMP_SCOPE_CHECK (NODE), 0)
+#define OMP_SCOPE_CLAUSES(NODE) TREE_OPERAND (OMP_SCOPE_CHECK (NODE), 1)
+
+#define OMP_MASTER_BODY(NODE) TREE_OPERAND (OMP_MASTER_CHECK (NODE), 0)
+
+#define OMP_MASKED_BODY(NODE) TREE_OPERAND (OMP_MASKED_CHECK (NODE), 0)
+#define OMP_MASKED_CLAUSES(NODE) TREE_OPERAND (OMP_MASKED_CHECK (NODE), 1)
+
+#define OMP_TASKGROUP_BODY(NODE) TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 0)
+#define OMP_TASKGROUP_CLAUSES(NODE) \
+ TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 1)
+
+#define OMP_ORDERED_BODY(NODE) TREE_OPERAND (OMP_ORDERED_CHECK (NODE), 0)
+#define OMP_ORDERED_CLAUSES(NODE) TREE_OPERAND (OMP_ORDERED_CHECK (NODE), 1)
+
+#define OMP_CRITICAL_BODY(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 0)
+#define OMP_CRITICAL_CLAUSES(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 1)
+#define OMP_CRITICAL_NAME(NODE) TREE_OPERAND (OMP_CRITICAL_CHECK (NODE), 2)
+
+#define OMP_TEAMS_BODY(NODE) TREE_OPERAND (OMP_TEAMS_CHECK (NODE), 0)
+#define OMP_TEAMS_CLAUSES(NODE) TREE_OPERAND (OMP_TEAMS_CHECK (NODE), 1)
+
+#define OMP_TARGET_DATA_BODY(NODE) \
+ TREE_OPERAND (OMP_TARGET_DATA_CHECK (NODE), 0)
+#define OMP_TARGET_DATA_CLAUSES(NODE)\
+ TREE_OPERAND (OMP_TARGET_DATA_CHECK (NODE), 1)
+
+#define OMP_TARGET_BODY(NODE) TREE_OPERAND (OMP_TARGET_CHECK (NODE), 0)
+#define OMP_TARGET_CLAUSES(NODE) TREE_OPERAND (OMP_TARGET_CHECK (NODE), 1)
+
+#define OMP_TARGET_UPDATE_CLAUSES(NODE)\
+ TREE_OPERAND (OMP_TARGET_UPDATE_CHECK (NODE), 0)
+
+#define OMP_TARGET_ENTER_DATA_CLAUSES(NODE)\
+ TREE_OPERAND (OMP_TARGET_ENTER_DATA_CHECK (NODE), 0)
+
+#define OMP_TARGET_EXIT_DATA_CLAUSES(NODE)\
+ TREE_OPERAND (OMP_TARGET_EXIT_DATA_CHECK (NODE), 0)
+
+#define OMP_SCAN_BODY(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 0)
+#define OMP_SCAN_CLAUSES(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 1)
+
+#define OMP_CLAUSE_SIZE(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
+ OMP_CLAUSE_FROM, \
+ OMP_CLAUSE__CACHE_), 1)
+
+#define OMP_CLAUSE_CHAIN(NODE) TREE_CHAIN (OMP_CLAUSE_CHECK (NODE))
+#define OMP_CLAUSE_DECL(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
+ OMP_CLAUSE_PRIVATE, \
+ OMP_CLAUSE__SCANTEMP_), 0)
+#define OMP_CLAUSE_HAS_LOCATION(NODE) \
+ (LOCATION_LOCUS ((OMP_CLAUSE_CHECK (NODE))->omp_clause.locus) \
+ != UNKNOWN_LOCATION)
+#define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
+
+/* True on OMP_FOR and other OpenMP/OpenACC looping constructs if the loop nest
+ is non-rectangular. */
+#define OMP_FOR_NON_RECTANGULAR(NODE) \
+ (OMP_LOOPING_CHECK (NODE)->base.private_flag)
+
+/* True on an OMP_SECTION statement that was the last lexical member.
+ This status is meaningful in the implementation of lastprivate. */
+#define OMP_SECTION_LAST(NODE) \
+ (OMP_SECTION_CHECK (NODE)->base.private_flag)
+
+/* True on an OMP_PARALLEL statement if it represents an explicit
+ combined parallel work-sharing constructs. */
+#define OMP_PARALLEL_COMBINED(NODE) \
+ (OMP_PARALLEL_CHECK (NODE)->base.private_flag)
+
+/* True on an OMP_TEAMS statement if it represents an explicit
+ combined teams distribute constructs. */
+#define OMP_TEAMS_COMBINED(NODE) \
+ (OMP_TEAMS_CHECK (NODE)->base.private_flag)
+
+/* True on an OMP_TARGET statement if it represents explicit
+ combined target teams, target parallel or target simd constructs. */
+#define OMP_TARGET_COMBINED(NODE) \
+ (OMP_TARGET_CHECK (NODE)->base.private_flag)
+
+/* True on an OMP_MASTER statement if it represents an explicit
+ combined master constructs. */
+#define OMP_MASTER_COMBINED(NODE) \
+ (OMP_MASTER_CHECK (NODE)->base.private_flag)
+
+/* True on an OMP_MASKED statement if it represents an explicit
+ combined masked constructs. */
+#define OMP_MASKED_COMBINED(NODE) \
+ (OMP_MASKED_CHECK (NODE)->base.private_flag)
+
+/* Memory order for OMP_ATOMIC*. */
+#define OMP_ATOMIC_MEMORY_ORDER(NODE) \
+ (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
+ OMP_ATOMIC_CAPTURE_NEW)->base.u.omp_atomic_memory_order)
+
+/* Weak clause on OMP_ATOMIC*. */
+#define OMP_ATOMIC_WEAK(NODE) \
+ (TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
+ OMP_ATOMIC_CAPTURE_NEW)->base.public_flag)
+
+/* True on a PRIVATE clause if its decl is kept around for debugging
+ information only and its DECL_VALUE_EXPR is supposed to point
+ to what it has been remapped to. */
+#define OMP_CLAUSE_PRIVATE_DEBUG(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE)->base.public_flag)
+
+/* True on a PRIVATE clause if ctor needs access to outer region's
+ variable. */
+#define OMP_CLAUSE_PRIVATE_OUTER_REF(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE))
+
+/* True if a PRIVATE clause is for a C++ class IV on taskloop construct
+ (thus should be private on the outer taskloop and firstprivate on
+ task). */
+#define OMP_CLAUSE_PRIVATE_TASKLOOP_IV(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIVATE))
+
+/* True on a FIRSTPRIVATE clause if it has been added implicitly. */
+#define OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FIRSTPRIVATE)->base.public_flag)
+
+/* True on a FIRSTPRIVATE clause if only the reference and not what it refers
+ to should be firstprivatized. */
+#define OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FIRSTPRIVATE))
+
+/* True on a FIRSTPRIVATE clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT also
+ set if target construct is the only one that accepts the clause. */
+#define OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FIRSTPRIVATE))
+
+/* True on a LASTPRIVATE clause if a FIRSTPRIVATE clause for the same
+ decl is present in the chain. */
+#define OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE)->base.public_flag)
+#define OMP_CLAUSE_LASTPRIVATE_STMT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE_LASTPRIVATE),\
+ 1)
+#define OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ(NODE) \
+ (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
+
+/* True if a LASTPRIVATE clause is for a C++ class IV on taskloop or
+ loop construct (thus should be lastprivate on the outer taskloop and
+ firstprivate on task for the taskloop construct and carefully handled
+ for loop construct). */
+#define OMP_CLAUSE_LASTPRIVATE_LOOP_IV(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE))
+
+/* True if a LASTPRIVATE clause has CONDITIONAL: modifier. */
+#define OMP_CLAUSE_LASTPRIVATE_CONDITIONAL(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LASTPRIVATE))
+
+/* True on a SHARED clause if a FIRSTPRIVATE clause for the same
+ decl is present in the chain (this can happen only for taskloop
+ with FIRSTPRIVATE/LASTPRIVATE on it originally. */
+#define OMP_CLAUSE_SHARED_FIRSTPRIVATE(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SHARED)->base.public_flag)
+
+/* True on a SHARED clause if a scalar is not modified in the body and
+ thus could be optimized as firstprivate. */
+#define OMP_CLAUSE_SHARED_READONLY(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SHARED))
+
+#define OMP_CLAUSE_IF_MODIFIER(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_IF)->omp_clause.subcode.if_modifier)
+
+#define OMP_CLAUSE_FINAL_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FINAL), 0)
+#define OMP_CLAUSE_IF_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_IF), 0)
+#define OMP_CLAUSE_NUM_THREADS_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_THREADS),0)
+#define OMP_CLAUSE_SCHEDULE_CHUNK_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SCHEDULE), 0)
+#define OMP_CLAUSE_NUM_TASKS_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TASKS), 0)
+#define OMP_CLAUSE_HINT_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_HINT), 0)
+#define OMP_CLAUSE_FILTER_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FILTER), 0)
+
+#define OMP_CLAUSE_GRAINSIZE_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GRAINSIZE),0)
+
+#define OMP_CLAUSE_PRIORITY_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PRIORITY),0)
+
+#define OMP_CLAUSE_GRAINSIZE_STRICT(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GRAINSIZE))
+#define OMP_CLAUSE_NUM_TASKS_STRICT(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TASKS))
+
+/* OpenACC clause expressions */
+#define OMP_CLAUSE_EXPR(NODE, CLAUSE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, CLAUSE), 0)
+#define OMP_CLAUSE_GANG_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GANG), 0)
+#define OMP_CLAUSE_GANG_STATIC_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GANG), 1)
+#define OMP_CLAUSE_ASYNC_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ASYNC), 0)
+#define OMP_CLAUSE_WAIT_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_WAIT), 0)
+#define OMP_CLAUSE_VECTOR_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_VECTOR), 0)
+#define OMP_CLAUSE_WORKER_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_WORKER), 0)
+#define OMP_CLAUSE_NUM_GANGS_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_GANGS), 0)
+#define OMP_CLAUSE_NUM_WORKERS_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_WORKERS), 0)
+#define OMP_CLAUSE_VECTOR_LENGTH_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND ( \
+ OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_VECTOR_LENGTH), 0)
+
+#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) \
+ TREE_PUBLIC (TREE_LIST_CHECK (NODE))
+
+#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) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->omp_clause.subcode.map_kind \
+ = (unsigned int) (MAP_KIND))
+
+/* Nonzero if this map clause is for array (rather than pointer) based array
+ section with zero bias. Both the non-decl OMP_CLAUSE_MAP and corresponding
+ OMP_CLAUSE_MAP with GOMP_MAP_POINTER are marked with this flag. */
+#define OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->base.public_flag)
+/* Nonzero if this is a mapped array section, that might need special
+ treatment if OMP_CLAUSE_SIZE is zero. */
+#define OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP))
+/* Nonzero if this map clause is for an OpenACC compute construct's reduction
+ variable or OpenMP map clause mentioned also in in_reduction clause on the
+ same construct. */
+#define OMP_CLAUSE_MAP_IN_REDUCTION(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP))
+/* Nonzero on map clauses added implicitly for reduction clauses on combined
+ or composite constructs. They shall be removed if there is an explicit
+ map clause. */
+#define OMP_CLAUSE_MAP_IMPLICIT(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->base.default_def_flag)
+/* Nonzero if this map clause is to be indicated to the runtime as 'implicit',
+ due to being created through implicit data-mapping rules in the middle-end.
+ NOTE: this is different than OMP_CLAUSE_MAP_IMPLICIT. */
+#define OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->base.deprecated_flag)
+
+/* Flag that 'OMP_CLAUSE_DECL (NODE)' is to be made addressable during OMP
+ lowering. */
+#define OMP_CLAUSE_MAP_DECL_MAKE_ADDRESSABLE(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_MAP)->base.addressable_flag)
+
+/* True on an OMP_CLAUSE_USE_DEVICE_PTR with an OpenACC 'if_present'
+ clause. */
+#define OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_USE_DEVICE_PTR)->base.public_flag)
+
+#define OMP_CLAUSE_PROC_BIND_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_PROC_BIND)->omp_clause.subcode.proc_bind_kind)
+
+#define OMP_CLAUSE_DEVICE_TYPE_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEVICE_TYPE)->omp_clause.subcode.device_type_kind)
+
+/* True if there is a device clause with a device-modifier 'ancestor'. */
+#define OMP_CLAUSE_DEVICE_ANCESTOR(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEVICE)->base.public_flag)
+
+#define OMP_CLAUSE_COLLAPSE_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_COLLAPSE), 0)
+#define OMP_CLAUSE_COLLAPSE_ITERVAR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_COLLAPSE), 1)
+#define OMP_CLAUSE_COLLAPSE_COUNT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_COLLAPSE), 2)
+
+#define OMP_CLAUSE_ORDERED_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDERED), 0)
+
+/* 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)
+/* True for reproducible modifier on order(concurrent) clause. */
+#define OMP_CLAUSE_ORDER_REPRODUCIBLE(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ORDER))
+
+#define OMP_CLAUSE_REDUCTION_CODE(NODE) \
+ (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+ OMP_CLAUSE_IN_REDUCTION)->omp_clause.subcode.reduction_code)
+#define OMP_CLAUSE_REDUCTION_INIT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+ OMP_CLAUSE_IN_REDUCTION), 1)
+#define OMP_CLAUSE_REDUCTION_MERGE(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+ OMP_CLAUSE_IN_REDUCTION), 2)
+#define OMP_CLAUSE_REDUCTION_GIMPLE_INIT(NODE) \
+ (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
+#define OMP_CLAUSE_REDUCTION_GIMPLE_MERGE(NODE) \
+ (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_merge
+#define OMP_CLAUSE_REDUCTION_PLACEHOLDER(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+ OMP_CLAUSE_IN_REDUCTION), 3)
+#define OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+ OMP_CLAUSE_IN_REDUCTION), 4)
+
+/* True if a REDUCTION clause may reference the original list item (omp_orig)
+ in its OMP_CLAUSE_REDUCTION_{,GIMPLE_}INIT. */
+#define OMP_CLAUSE_REDUCTION_OMP_ORIG_REF(NODE) \
+ (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \
+ OMP_CLAUSE_IN_REDUCTION)->base.public_flag)
+
+/* True if a REDUCTION clause has task reduction-modifier. */
+#define OMP_CLAUSE_REDUCTION_TASK(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION))
+
+/* True if a REDUCTION clause has inscan reduction-modifier. */
+#define OMP_CLAUSE_REDUCTION_INSCAN(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION))
+
+/* True if a LINEAR clause doesn't need copy in. True for iterator vars which
+ are always initialized inside of the loop construct, false otherwise. */
+#define OMP_CLAUSE_LINEAR_NO_COPYIN(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)->base.public_flag)
+
+/* True if a LINEAR clause doesn't need copy out. True for iterator vars which
+ are declared inside of the simd construct. */
+#define OMP_CLAUSE_LINEAR_NO_COPYOUT(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR))
+
+/* True if a LINEAR clause has a stride that is variable. */
+#define OMP_CLAUSE_LINEAR_VARIABLE_STRIDE(NODE) \
+ TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR))
+
+/* True if a LINEAR clause is for an array or allocatable variable that
+ needs special handling by the frontend. */
+#define OMP_CLAUSE_LINEAR_ARRAY(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)->base.deprecated_flag)
+
+#define OMP_CLAUSE_LINEAR_STEP(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1)
+
+#define OMP_CLAUSE_LINEAR_STMT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 2)
+
+#define OMP_CLAUSE_LINEAR_GIMPLE_SEQ(NODE) \
+ (OMP_CLAUSE_CHECK (NODE))->omp_clause.gimple_reduction_init
+
+#define OMP_CLAUSE_LINEAR_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)->omp_clause.subcode.linear_kind)
+
+#define OMP_CLAUSE_ALIGNED_ALIGNMENT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALIGNED), 1)
+
+#define OMP_CLAUSE_ALLOCATE_ALLOCATOR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 1)
+
+#define OMP_CLAUSE_ALLOCATE_ALIGN(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE), 2)
+
+/* True if an ALLOCATE clause was present on a combined or composite
+ construct and the code for splitting the clauses has already performed
+ checking if the listed variable has explicit privatization on the
+ construct. */
+#define OMP_CLAUSE_ALLOCATE_COMBINED(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ALLOCATE)->base.public_flag)
+
+#define OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TEAMS), 0)
+
+#define OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TEAMS), 1)
+
+#define OMP_CLAUSE_THREAD_LIMIT_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE_THREAD_LIMIT), 0)
+
+#define OMP_CLAUSE_DEVICE_ID(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEVICE), 0)
+
+#define OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, \
+ OMP_CLAUSE_DIST_SCHEDULE), 0)
+
+#define OMP_CLAUSE_SAFELEN_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SAFELEN), 0)
+
+#define OMP_CLAUSE_SIMDLEN_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SIMDLEN), 0)
+
+#define OMP_CLAUSE__SIMDUID__DECL(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SIMDUID_), 0)
+
+#define OMP_CLAUSE_SCHEDULE_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SCHEDULE)->omp_clause.subcode.schedule_kind)
+
+/* True if a SCHEDULE clause has the simd modifier on it. */
+#define OMP_CLAUSE_SCHEDULE_SIMD(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_SCHEDULE)->base.public_flag)
+
+#define OMP_CLAUSE_DEFAULT_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEFAULT)->omp_clause.subcode.default_kind)
+
+#define OMP_CLAUSE_DEFAULTMAP_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DEFAULTMAP)->omp_clause.subcode.defaultmap_kind)
+#define OMP_CLAUSE_DEFAULTMAP_CATEGORY(NODE) \
+ ((enum omp_clause_defaultmap_kind) \
+ (OMP_CLAUSE_DEFAULTMAP_KIND (NODE) & OMP_CLAUSE_DEFAULTMAP_CATEGORY_MASK))
+#define OMP_CLAUSE_DEFAULTMAP_BEHAVIOR(NODE) \
+ ((enum omp_clause_defaultmap_kind) \
+ (OMP_CLAUSE_DEFAULTMAP_KIND (NODE) & OMP_CLAUSE_DEFAULTMAP_MASK))
+#define OMP_CLAUSE_DEFAULTMAP_SET_KIND(NODE, BEHAVIOR, CATEGORY) \
+ (OMP_CLAUSE_DEFAULTMAP_KIND (NODE) \
+ = (enum omp_clause_defaultmap_kind) (CATEGORY | BEHAVIOR))
+
+#define OMP_CLAUSE_BIND_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_BIND)->omp_clause.subcode.bind_kind)
+
+#define OMP_CLAUSE_TILE_LIST(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_TILE), 0)
+#define OMP_CLAUSE_TILE_ITERVAR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_TILE), 1)
+#define OMP_CLAUSE_TILE_COUNT(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_TILE), 2)
+
+/* _CONDTEMP_ holding temporary with iteration count. */
+#define OMP_CLAUSE__CONDTEMP__ITER(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__CONDTEMP_)->base.public_flag)
+
+/* _SCANTEMP_ holding temporary with pointer to thread's local array;
+ allocation. */
+#define OMP_CLAUSE__SCANTEMP__ALLOC(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SCANTEMP_)->base.public_flag)
+
+/* _SCANTEMP_ holding temporary with a control variable for deallocation;
+ one boolean_type_node for test whether alloca was used, another one
+ to pass to __builtin_stack_restore or free. */
+#define OMP_CLAUSE__SCANTEMP__CONTROL(NODE) \
+ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE__SCANTEMP_))
+
+#endif
+
+/* SSA_NAME accessors. */
+
+/* Whether SSA_NAME NODE is a virtual operand. This simply caches the
+ information in the underlying SSA_NAME_VAR for efficiency. */
+#define SSA_NAME_IS_VIRTUAL_OPERAND(NODE) \
+ SSA_NAME_CHECK (NODE)->base.public_flag
+
+/* Returns the IDENTIFIER_NODE giving the SSA name a name or NULL_TREE
+ if there is no name associated with it. */
+#define SSA_NAME_IDENTIFIER(NODE) \
+ (SSA_NAME_CHECK (NODE)->ssa_name.var != NULL_TREE \
+ ? (TREE_CODE ((NODE)->ssa_name.var) == IDENTIFIER_NODE \
+ ? (NODE)->ssa_name.var \
+ : DECL_NAME ((NODE)->ssa_name.var)) \
+ : NULL_TREE)
+
+/* Returns the variable being referenced. This can be NULL_TREE for
+ temporaries not associated with any user variable.
+ Once released, this is the only field that can be relied upon. */
+#define SSA_NAME_VAR(NODE) \
+ (SSA_NAME_CHECK (NODE)->ssa_name.var == NULL_TREE \
+ || TREE_CODE ((NODE)->ssa_name.var) == IDENTIFIER_NODE \
+ ? NULL_TREE : (NODE)->ssa_name.var)
+
+#define SET_SSA_NAME_VAR_OR_IDENTIFIER(NODE,VAR) \
+ do \
+ { \
+ tree var_ = (VAR); \
+ SSA_NAME_CHECK (NODE)->ssa_name.var = var_; \
+ SSA_NAME_IS_VIRTUAL_OPERAND (NODE) \
+ = (var_ \
+ && TREE_CODE (var_) == VAR_DECL \
+ && VAR_DECL_IS_VIRTUAL_OPERAND (var_)); \
+ } \
+ while (0)
+
+/* Returns the statement which defines this SSA name. */
+#define SSA_NAME_DEF_STMT(NODE) SSA_NAME_CHECK (NODE)->ssa_name.def_stmt
+
+/* Returns the SSA version number of this SSA name. Note that in
+ tree SSA, version numbers are not per variable and may be recycled. */
+#define SSA_NAME_VERSION(NODE) SSA_NAME_CHECK (NODE)->base.u.version
+
+/* Nonzero if this SSA name occurs in an abnormal PHI. SSA_NAMES are
+ never output, so we can safely use the ASM_WRITTEN_FLAG for this
+ status bit. */
+#define SSA_NAME_OCCURS_IN_ABNORMAL_PHI(NODE) \
+ SSA_NAME_CHECK (NODE)->base.asm_written_flag
+
+/* Nonzero if this SSA_NAME expression is currently on the free list of
+ SSA_NAMES. Using NOTHROW_FLAG seems reasonably safe since throwing
+ has no meaning for an SSA_NAME. */
+#define SSA_NAME_IN_FREE_LIST(NODE) \
+ SSA_NAME_CHECK (NODE)->base.nothrow_flag
+
+/* Nonzero if this SSA_NAME is the default definition for the
+ underlying symbol. A default SSA name is created for symbol S if
+ the very first reference to S in the function is a read operation.
+ Default definitions are always created by an empty statement and
+ belong to no basic block. */
+#define SSA_NAME_IS_DEFAULT_DEF(NODE) \
+ SSA_NAME_CHECK (NODE)->base.default_def_flag
+
+/* Nonzero if this SSA_NAME is known to point to memory that may not
+ be written to. This is set for default defs of function parameters
+ that have a corresponding r or R specification in the functions
+ fn spec attribute. This is used by alias analysis. */
+#define SSA_NAME_POINTS_TO_READONLY_MEMORY(NODE) \
+ SSA_NAME_CHECK (NODE)->base.deprecated_flag
+
+/* Attributes for SSA_NAMEs for pointer-type variables. */
+#define SSA_NAME_PTR_INFO(N) \
+ SSA_NAME_CHECK (N)->ssa_name.info.ptr_info
+
+/* True if SSA_NAME_RANGE_INFO describes an anti-range. */
+#define SSA_NAME_ANTI_RANGE_P(N) \
+ SSA_NAME_CHECK (N)->base.static_flag
+
+/* The type of range described by SSA_NAME_RANGE_INFO. */
+#define SSA_NAME_RANGE_TYPE(N) \
+ (SSA_NAME_ANTI_RANGE_P (N) ? VR_ANTI_RANGE : VR_RANGE)
+
+/* Value range info attributes for SSA_NAMEs of non pointer-type variables. */
+#define SSA_NAME_RANGE_INFO(N) \
+ SSA_NAME_CHECK (N)->ssa_name.info.range_info
+
+/* Return the immediate_use information for an SSA_NAME. */
+#define SSA_NAME_IMM_USE_NODE(NODE) SSA_NAME_CHECK (NODE)->ssa_name.imm_uses
+
+#define OMP_CLAUSE_CODE(NODE) \
+ (OMP_CLAUSE_CHECK (NODE))->omp_clause.code
+
+#define OMP_CLAUSE_SET_CODE(NODE, CODE) \
+ ((OMP_CLAUSE_CHECK (NODE))->omp_clause.code = (CODE))
+
+#define OMP_CLAUSE_OPERAND(NODE, I) \
+ OMP_CLAUSE_ELT_CHECK (NODE, I)
+
+/* In a BLOCK (scope) node:
+ Variables declared in the scope NODE. */
+#define BLOCK_VARS(NODE) (BLOCK_CHECK (NODE)->block.vars)
+#define BLOCK_NONLOCALIZED_VARS(NODE) \
+ (BLOCK_CHECK (NODE)->block.nonlocalized_vars)
+#define BLOCK_NUM_NONLOCALIZED_VARS(NODE) \
+ vec_safe_length (BLOCK_NONLOCALIZED_VARS (NODE))
+#define BLOCK_NONLOCALIZED_VAR(NODE,N) (*BLOCK_NONLOCALIZED_VARS (NODE))[N]
+/* A chain of BLOCKs (scopes) nested within the scope NODE. */
+#define BLOCK_SUBBLOCKS(NODE) (BLOCK_CHECK (NODE)->block.subblocks)
+/* The scope enclosing the scope NODE, or FUNCTION_DECL for the "outermost"
+ function scope. Inlined functions are chained by this so that given
+ expression E and its TREE_BLOCK(E) B, BLOCK_SUPERCONTEXT(B) is the scope
+ in which E has been made or into which E has been inlined. */
+#define BLOCK_SUPERCONTEXT(NODE) (BLOCK_CHECK (NODE)->block.supercontext)
+/* Points to the next scope at the same level of nesting as scope NODE. */
+#define BLOCK_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.chain)
+/* A BLOCK, or FUNCTION_DECL of the function from which a block has been
+ inlined. In a scope immediately enclosing an inlined leaf expression,
+ points to the outermost scope into which it has been inlined (thus
+ bypassing all intermediate BLOCK_SUPERCONTEXTs). */
+#define BLOCK_ABSTRACT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.abstract_origin)
+#define BLOCK_ORIGIN(NODE) \
+ (BLOCK_ABSTRACT_ORIGIN(NODE) ? BLOCK_ABSTRACT_ORIGIN(NODE) : (NODE))
+#define BLOCK_DIE(NODE) (BLOCK_CHECK (NODE)->block.die)
+
+/* True if BLOCK has the same ranges as its BLOCK_SUPERCONTEXT. */
+#define BLOCK_SAME_RANGE(NODE) (BLOCK_CHECK (NODE)->base.u.bits.nameless_flag)
+
+/* True if BLOCK appears in cold section. */
+#define BLOCK_IN_COLD_SECTION_P(NODE) \
+ (BLOCK_CHECK (NODE)->base.u.bits.atomic_flag)
+
+/* An index number for this block. These values are not guaranteed to
+ be unique across functions -- whether or not they are depends on
+ the debugging output format in use. */
+#define BLOCK_NUMBER(NODE) (BLOCK_CHECK (NODE)->block.block_num)
+
+/* If block reordering splits a lexical block into discontiguous
+ address ranges, we'll make a copy of the original block.
+
+ Note that this is logically distinct from BLOCK_ABSTRACT_ORIGIN.
+ In that case, we have one source block that has been replicated
+ (through inlining or unrolling) into many logical blocks, and that
+ these logical blocks have different physical variables in them.
+
+ In this case, we have one logical block split into several
+ non-contiguous address ranges. Most debug formats can't actually
+ represent this idea directly, so we fake it by creating multiple
+ logical blocks with the same variables in them. However, for those
+ that do support non-contiguous regions, these allow the original
+ logical block to be reconstructed, along with the set of address
+ ranges.
+
+ One of the logical block fragments is arbitrarily chosen to be
+ the ORIGIN. The other fragments will point to the origin via
+ BLOCK_FRAGMENT_ORIGIN; the origin itself will have this pointer
+ be null. The list of fragments will be chained through
+ BLOCK_FRAGMENT_CHAIN from the origin. */
+
+#define BLOCK_FRAGMENT_ORIGIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_origin)
+#define BLOCK_FRAGMENT_CHAIN(NODE) (BLOCK_CHECK (NODE)->block.fragment_chain)
+
+/* For an inlined function, this gives the location where it was called
+ from. This is only set in the top level block, which corresponds to the
+ inlined function scope. This is used in the debug output routines. */
+
+#define BLOCK_SOURCE_LOCATION(NODE) (BLOCK_CHECK (NODE)->block.locus)
+
+/* This gives the location of the end of the block, useful to attach
+ code implicitly generated for outgoing paths. */
+
+#define BLOCK_SOURCE_END_LOCATION(NODE) (BLOCK_CHECK (NODE)->block.end_locus)
+
+/* Define fields and accessors for nodes representing data types. */
+
+/* See tree.def for documentation of the use of these fields.
+ Look at the documentation of the various ..._TYPE tree codes.
+
+ Note that the type.values, type.minval, and type.maxval fields are
+ overloaded and used for different macros in different kinds of types.
+ Each macro must check to ensure the tree node is of the proper kind of
+ type. Note also that some of the front-ends also overload these fields,
+ so they must be checked as well. */
+
+#define TYPE_UID(NODE) (TYPE_CHECK (NODE)->type_common.uid)
+/* Type size in bits as a tree expression. Need not be constant and may
+ be greater than TYPE_SIZE for a C++ FIELD_DECL representing a base
+ class subobject with its own virtual base classes (which are laid out
+ separately). */
+#define TYPE_SIZE(NODE) (TYPE_CHECK (NODE)->type_common.size)
+/* Likewise, type size in bytes. */
+#endif // sdcpp
+#define TYPE_SIZE_UNIT(NODE) (TYPE_CHECK (NODE)->type_common.size_unit)
+#define TYPE_POINTER_TO(NODE) (TYPE_CHECK (NODE)->type_common.pointer_to)
+#define TYPE_REFERENCE_TO(NODE) (TYPE_CHECK (NODE)->type_common.reference_to)
+#define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type_common.precision)
+#define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type_common.name)
+#define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.next_variant)
+#define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.main_variant)
+#define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type_common.context)
+#if 0 // sdcpp
+
+#define TYPE_MODE_RAW(NODE) (TYPE_CHECK (NODE)->type_common.mode)
+#define TYPE_MODE(NODE) \
+ (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
+ ? vector_type_mode (NODE) : (NODE)->type_common.mode)
+#define SCALAR_TYPE_MODE(NODE) \
+ (as_a <scalar_mode> (TYPE_CHECK (NODE)->type_common.mode))
+#define SCALAR_INT_TYPE_MODE(NODE) \
+ (as_a <scalar_int_mode> (TYPE_CHECK (NODE)->type_common.mode))
+#define SCALAR_FLOAT_TYPE_MODE(NODE) \
+ (as_a <scalar_float_mode> (TYPE_CHECK (NODE)->type_common.mode))
+#define SET_TYPE_MODE(NODE, MODE) \
+ (TYPE_CHECK (NODE)->type_common.mode = (MODE))
+
+extern machine_mode element_mode (const_tree);
+extern machine_mode vector_type_mode (const_tree);
+extern unsigned int vector_element_bits (const_tree);
+extern tree vector_element_bits_tree (const_tree);
+
+/* The "canonical" type for this type node, which is used by frontends to
+ compare the type for equality with another type. If two types are
+ equal (based on the semantics of the language), then they will have
+ equivalent TYPE_CANONICAL entries.
+
+ As a special case, if TYPE_CANONICAL is NULL_TREE, and thus
+ TYPE_STRUCTURAL_EQUALITY_P is true, then it cannot
+ be used for comparison against other types. Instead, the type is
+ said to require structural equality checks, described in
+ TYPE_STRUCTURAL_EQUALITY_P.
+
+ For unqualified aggregate and function types the middle-end relies on
+ TYPE_CANONICAL to tell whether two variables can be assigned
+ to each other without a conversion. The middle-end also makes sure
+ to assign the same alias-sets to the type partition with equal
+ TYPE_CANONICAL of their unqualified variants. */
+#define TYPE_CANONICAL(NODE) (TYPE_CHECK (NODE)->type_common.canonical)
+/* Indicates that the type node requires structural equality
+ checks. The compiler will need to look at the composition of the
+ type to determine whether it is equal to another type, rather than
+ just comparing canonical type pointers. For instance, we would need
+ to look at the return and parameter types of a FUNCTION_TYPE
+ node. */
+#define TYPE_STRUCTURAL_EQUALITY_P(NODE) (TYPE_CANONICAL (NODE) == NULL_TREE)
+/* Sets the TYPE_CANONICAL field to NULL_TREE, indicating that the
+ type node requires structural equality. */
+#define SET_TYPE_STRUCTURAL_EQUALITY(NODE) (TYPE_CANONICAL (NODE) = NULL_TREE)
+
+#define TYPE_IBIT(NODE) (GET_MODE_IBIT (TYPE_MODE (NODE)))
+#define TYPE_FBIT(NODE) (GET_MODE_FBIT (TYPE_MODE (NODE)))
+
+/* The (language-specific) typed-based alias set for this type.
+ Objects whose TYPE_ALIAS_SETs are different cannot alias each
+ other. If the TYPE_ALIAS_SET is -1, no alias set has yet been
+ assigned to this type. If the TYPE_ALIAS_SET is 0, objects of this
+ type can alias objects of any type. */
+#define TYPE_ALIAS_SET(NODE) (TYPE_CHECK (NODE)->type_common.alias_set)
+
+/* Nonzero iff the typed-based alias set for this type has been
+ calculated. */
+#define TYPE_ALIAS_SET_KNOWN_P(NODE) \
+ (TYPE_CHECK (NODE)->type_common.alias_set != -1)
+
+/* A TREE_LIST of IDENTIFIER nodes of the attributes that apply
+ to this type. */
+#define TYPE_ATTRIBUTES(NODE) (TYPE_CHECK (NODE)->type_common.attributes)
+
+/* Raw access to the alignment field. */
+#define TYPE_ALIGN_RAW(NODE) \
+ (TYPE_CHECK (NODE)->type_common.align)
+
+/* The alignment necessary for objects of this type.
+ The value is an int, measured in bits and must be a power of two.
+ We support also an "alignment" of zero. */
+#define TYPE_ALIGN(NODE) \
+ (TYPE_ALIGN_RAW (NODE) \
+ ? ((unsigned)1) << (TYPE_ALIGN_RAW(NODE) - 1) : 0)
+
+/* Specify that TYPE_ALIGN(NODE) is X. */
+#define SET_TYPE_ALIGN(NODE, X) \
+ (TYPE_CHECK (NODE)->type_common.align = ffs_hwi (X))
+
+/* 1 if the alignment for this type was requested by "aligned" attribute,
+ 0 if it is the default for this type. */
+#define TYPE_USER_ALIGN(NODE) (TYPE_CHECK (NODE)->base.u.bits.user_align)
+
+/* The alignment for NODE, in bytes. */
+#define TYPE_ALIGN_UNIT(NODE) (TYPE_ALIGN (NODE) / BITS_PER_UNIT)
+
+/* The minimum alignment necessary for objects of this type without
+ warning. The value is an int, measured in bits. */
+#define TYPE_WARN_IF_NOT_ALIGN(NODE) \
+ (TYPE_CHECK (NODE)->type_common.warn_if_not_align \
+ ? ((unsigned)1) << ((NODE)->type_common.warn_if_not_align - 1) : 0)
+
+/* Specify that TYPE_WARN_IF_NOT_ALIGN(NODE) is X. */
+#define SET_TYPE_WARN_IF_NOT_ALIGN(NODE, X) \
+ (TYPE_CHECK (NODE)->type_common.warn_if_not_align = ffs_hwi (X))
+
+/* If your language allows you to declare types, and you want debug info
+ for them, then you need to generate corresponding TYPE_DECL nodes.
+ These "stub" TYPE_DECL nodes have no name, and simply point at the
+ type node. You then set the TYPE_STUB_DECL field of the type node
+ to point back at the TYPE_DECL node. This allows the debug routines
+ to know that the two nodes represent the same type, so that we only
+ get one debug info record for them. */
+#define TYPE_STUB_DECL(NODE) (TREE_CHAIN (TYPE_CHECK (NODE)))
+
+/* In a RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ARRAY_TYPE, it means
+ the type has BLKmode only because it lacks the alignment required for
+ its size. */
+#define TYPE_NO_FORCE_BLK(NODE) \
+ (TYPE_CHECK (NODE)->type_common.no_force_blk_flag)
+
+/* Nonzero in a type considered volatile as a whole. */
+#define TYPE_VOLATILE(NODE) (TYPE_CHECK (NODE)->base.volatile_flag)
+
+/* Nonzero in a type considered atomic as a whole. */
+#define TYPE_ATOMIC(NODE) (TYPE_CHECK (NODE)->base.u.bits.atomic_flag)
+
+/* Means this type is const-qualified. */
+#define TYPE_READONLY(NODE) (TYPE_CHECK (NODE)->base.readonly_flag)
+
+/* If nonzero, this type is `restrict'-qualified, in the C sense of
+ the term. */
+#define TYPE_RESTRICT(NODE) (TYPE_CHECK (NODE)->type_common.restrict_flag)
+
+/* If nonzero, type's name shouldn't be emitted into debug info. */
+#define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.u.bits.nameless_flag)
+
+/* The address space the type is in. */
+#define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->base.u.bits.address_space)
+
+/* Encode/decode the named memory support as part of the qualifier. If more
+ than 8 qualifiers are added, these macros need to be adjusted. */
+#define ENCODE_QUAL_ADDR_SPACE(NUM) ((NUM & 0xFF) << 8)
+#define DECODE_QUAL_ADDR_SPACE(X) (((X) >> 8) & 0xFF)
+
+/* Return all qualifiers except for the address space qualifiers. */
+#define CLEAR_QUAL_ADDR_SPACE(X) ((X) & ~0xFF00)
+
+/* Only keep the address space out of the qualifiers and discard the other
+ qualifiers. */
+#define KEEP_QUAL_ADDR_SPACE(X) ((X) & 0xFF00)
+
+/* The set of type qualifiers for this type. */
+#define TYPE_QUALS(NODE) \
+ ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
+ | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
+ | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
+ | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT) \
+ | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
+
+/* The same as TYPE_QUALS without the address space qualifications. */
+#define TYPE_QUALS_NO_ADDR_SPACE(NODE) \
+ ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
+ | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
+ | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
+ | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
+
+/* The same as TYPE_QUALS without the address space and atomic
+ qualifications. */
+#define TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC(NODE) \
+ ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
+ | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
+ | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
+
+/* These flags are available for each language front end to use internally. */
+#define TYPE_LANG_FLAG_0(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_0)
+#define TYPE_LANG_FLAG_1(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_1)
+#define TYPE_LANG_FLAG_2(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_2)
+#define TYPE_LANG_FLAG_3(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_3)
+#define TYPE_LANG_FLAG_4(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_4)
+#define TYPE_LANG_FLAG_5(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_5)
+#define TYPE_LANG_FLAG_6(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_6)
+#define TYPE_LANG_FLAG_7(NODE) (TYPE_CHECK (NODE)->type_common.lang_flag_7)
+
+/* Used to keep track of visited nodes in tree traversals. This is set to
+ 0 by copy_node and make_node. */
+#define TREE_VISITED(NODE) ((NODE)->base.visited)
+
+/* If set in an ARRAY_TYPE, indicates a string type (for languages
+ that distinguish string from array of char).
+ If set in a INTEGER_TYPE, indicates a character type. */
+#define TYPE_STRING_FLAG(NODE) \
+ (ARRAY_OR_INTEGER_TYPE_CHECK (NODE)->type_common.string_flag)
+
+/* If set for RECORD_TYPE or UNION_TYPE it indicates that the type conforms
+ to the C++ one definition rule. This is used for LTO canonical type
+ computation. */
+#define TYPE_CXX_ODR_P(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->type_common.string_flag)
+
+/* Nonzero in a VECTOR_TYPE if the frontends should not emit warnings
+ about missing conversions to other vector types of the same size. */
+#define TYPE_VECTOR_OPAQUE(NODE) \
+ (VECTOR_TYPE_CHECK (NODE)->base.default_def_flag)
+
+/* Indicates that objects of this type must be initialized by calling a
+ function when they are created. */
+#define TYPE_NEEDS_CONSTRUCTING(NODE) \
+ (TYPE_CHECK (NODE)->type_common.needs_constructing_flag)
+
+/* Indicates that a UNION_TYPE object should be passed the same way that
+ the first union alternative would be passed, or that a RECORD_TYPE
+ object should be passed the same way that the first (and only) member
+ would be passed. */
+#define TYPE_TRANSPARENT_AGGR(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->type_common.transparent_aggr_flag)
+
+/* For an ARRAY_TYPE, indicates that it is not permitted to take the
+ address of a component of the type. This is the counterpart of
+ DECL_NONADDRESSABLE_P for arrays, see the definition of this flag. */
+#define TYPE_NONALIASED_COMPONENT(NODE) \
+ (ARRAY_TYPE_CHECK (NODE)->type_common.transparent_aggr_flag)
+
+/* For an ARRAY_TYPE, a RECORD_TYPE, a UNION_TYPE or a QUAL_UNION_TYPE
+ whether the array is typeless storage or the type contains a member
+ with this flag set. Such types are exempt from type-based alias
+ analysis. For ARRAY_TYPEs with AGGREGATE_TYPE_P element types
+ the flag should be inherited from the element type, can change
+ when type is finalized and because of that should not be used in
+ type hashing. For ARRAY_TYPEs with non-AGGREGATE_TYPE_P element types
+ the flag should not be changed after the array is created and should
+ be used in type hashing. */
+#define TYPE_TYPELESS_STORAGE(NODE) \
+ (TREE_CHECK4 (NODE, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE, \
+ ARRAY_TYPE)->type_common.typeless_storage)
+
+/* Indicated that objects of this type should be laid out in as
+ compact a way as possible. */
+#define TYPE_PACKED(NODE) (TYPE_CHECK (NODE)->base.u.bits.packed_flag)
+
+/* Used by type_contains_placeholder_p to avoid recomputation.
+ Values are: 0 (unknown), 1 (false), 2 (true). Never access
+ this field directly. */
+#define TYPE_CONTAINS_PLACEHOLDER_INTERNAL(NODE) \
+ (TYPE_CHECK (NODE)->type_common.contains_placeholder_bits)
+
+/* Nonzero if RECORD_TYPE represents a final derivation of class. */
+#define TYPE_FINAL_P(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->base.default_def_flag)
+
+/* The debug output functions use the symtab union field to store
+ information specific to the debugging format. The different debug
+ output hooks store different types in the union field. These three
+ macros are used to access different fields in the union. The debug
+ hooks are responsible for consistently using only a specific
+ macro. */
+
+/* Symtab field as an integer. Used by stabs generator in dbxout.cc to
+ hold the type's number in the generated stabs. */
+#define TYPE_SYMTAB_ADDRESS(NODE) \
+ (TYPE_CHECK (NODE)->type_common.symtab.address)
+
+/* Symtab field as a pointer to a DWARF DIE. Used by DWARF generator
+ in dwarf2out.cc to point to the DIE generated for the type. */
+#define TYPE_SYMTAB_DIE(NODE) \
+ (TYPE_CHECK (NODE)->type_common.symtab.die)
+
+/* The garbage collector needs to know the interpretation of the
+ symtab field. These constants represent the different types in the
+ union. */
+
+#endif // sdcpp
+#define TYPE_SYMTAB_IS_ADDRESS (0)
+#define TYPE_SYMTAB_IS_DIE (1)
+#if 0 // sdcpp
+
+#define TYPE_LANG_SPECIFIC(NODE) \
+ (TYPE_CHECK (NODE)->type_with_lang_specific.lang_specific)
+
+#define TYPE_VALUES(NODE) (ENUMERAL_TYPE_CHECK (NODE)->type_non_common.values)
+#define TYPE_DOMAIN(NODE) (ARRAY_TYPE_CHECK (NODE)->type_non_common.values)
+#define TYPE_FIELDS(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->type_non_common.values)
+#define TYPE_CACHED_VALUES(NODE) (TYPE_CHECK (NODE)->type_non_common.values)
+#define TYPE_ARG_TYPES(NODE) \
+ (FUNC_OR_METHOD_CHECK (NODE)->type_non_common.values)
+#define TYPE_VALUES_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.values)
+
+#define TYPE_MIN_VALUE(NODE) \
+ (NUMERICAL_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_NEXT_PTR_TO(NODE) \
+ (POINTER_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_NEXT_REF_TO(NODE) \
+ (REFERENCE_TYPE_CHECK (NODE)->type_non_common.minval)
+#define TYPE_VFIELD(NODE) \
+ (RECORD_OR_UNION_CHECK (NODE)->type_non_common.minval)
+#define TYPE_MIN_VALUE_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.minval)
+
+#define TYPE_MAX_VALUE(NODE) \
+ (NUMERICAL_TYPE_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_METHOD_BASETYPE(NODE) \
+ (FUNC_OR_METHOD_CHECK (NODE)->type_non_common.maxval)
+#define TYPE_OFFSET_BASETYPE(NODE) \
+ (OFFSET_TYPE_CHECK (NODE)->type_non_common.maxval)
+/* If non-NULL, this is an upper bound of the size (in bytes) of an
+ object of the given ARRAY_TYPE_NON_COMMON. This allows temporaries to be
+ allocated. */
+#define TYPE_ARRAY_MAX_SIZE(ARRAY_TYPE) \
+ (ARRAY_TYPE_CHECK (ARRAY_TYPE)->type_non_common.maxval)
+#define TYPE_MAX_VALUE_RAW(NODE) (TYPE_CHECK (NODE)->type_non_common.maxval)
+/* For record and union types, information about this type, as a base type
+ for itself. */
+#define TYPE_BINFO(NODE) (RECORD_OR_UNION_CHECK (NODE)->type_non_common.maxval)
+
+/* For types, used in a language-dependent way. */
+#define TYPE_LANG_SLOT_1(NODE) \
+ (TYPE_CHECK (NODE)->type_non_common.lang_1)
+
+/* Define accessor macros for information about type inheritance
+ and basetypes.
+
+ A "basetype" means a particular usage of a data type for inheritance
+ in another type. Each such basetype usage has its own "binfo"
+ object to describe it. The binfo object is a TREE_VEC node.
+
+ Inheritance is represented by the binfo nodes allocated for a
+ given type. For example, given types C and D, such that D is
+ inherited by C, 3 binfo nodes will be allocated: one for describing
+ the binfo properties of C, similarly one for D, and one for
+ describing the binfo properties of D as a base type for C.
+ Thus, given a pointer to class C, one can get a pointer to the binfo
+ of D acting as a basetype for C by looking at C's binfo's basetypes. */
+
+/* BINFO specific flags. */
+
+/* Nonzero means that the derivation chain is via a `virtual' declaration. */
+#define BINFO_VIRTUAL_P(NODE) (TREE_BINFO_CHECK (NODE)->base.static_flag)
+
+/* Flags for language dependent use. */
+#define BINFO_FLAG_0(NODE) TREE_LANG_FLAG_0 (TREE_BINFO_CHECK (NODE))
+#define BINFO_FLAG_1(NODE) TREE_LANG_FLAG_1 (TREE_BINFO_CHECK (NODE))
+#define BINFO_FLAG_2(NODE) TREE_LANG_FLAG_2 (TREE_BINFO_CHECK (NODE))
+#define BINFO_FLAG_3(NODE) TREE_LANG_FLAG_3 (TREE_BINFO_CHECK (NODE))
+#define BINFO_FLAG_4(NODE) TREE_LANG_FLAG_4 (TREE_BINFO_CHECK (NODE))
+#define BINFO_FLAG_5(NODE) TREE_LANG_FLAG_5 (TREE_BINFO_CHECK (NODE))
+#define BINFO_FLAG_6(NODE) TREE_LANG_FLAG_6 (TREE_BINFO_CHECK (NODE))
+
+/* The actual data type node being inherited in this basetype. */
+#define BINFO_TYPE(NODE) TREE_TYPE (TREE_BINFO_CHECK (NODE))
+
+/* The offset where this basetype appears in its containing type.
+ BINFO_OFFSET slot holds the offset (in bytes)
+ from the base of the complete object to the base of the part of the
+ object that is allocated on behalf of this `type'.
+ This is always 0 except when there is multiple inheritance. */
+
+#define BINFO_OFFSET(NODE) (TREE_BINFO_CHECK (NODE)->binfo.offset)
+#define BINFO_OFFSET_ZEROP(NODE) (integer_zerop (BINFO_OFFSET (NODE)))
+
+/* The virtual function table belonging to this basetype. Virtual
+ function tables provide a mechanism for run-time method dispatching.
+ The entries of a virtual function table are language-dependent. */
+
+#define BINFO_VTABLE(NODE) (TREE_BINFO_CHECK (NODE)->binfo.vtable)
+
+/* The virtual functions in the virtual function table. This is
+ a TREE_LIST that is used as an initial approximation for building
+ a virtual function table for this basetype. */
+#define BINFO_VIRTUALS(NODE) (TREE_BINFO_CHECK (NODE)->binfo.virtuals)
+
+/* A vector of binfos for the direct basetypes inherited by this
+ basetype.
+
+ If this basetype describes type D as inherited in C, and if the
+ basetypes of D are E and F, then this vector contains binfos for
+ inheritance of E and F by C. */
+#define BINFO_BASE_BINFOS(NODE) (&TREE_BINFO_CHECK (NODE)->binfo.base_binfos)
+
+/* The number of basetypes for NODE. */
+#define BINFO_N_BASE_BINFOS(NODE) (BINFO_BASE_BINFOS (NODE)->length ())
+
+/* Accessor macro to get to the Nth base binfo of this binfo. */
+#define BINFO_BASE_BINFO(NODE,N) \
+ ((*BINFO_BASE_BINFOS (NODE))[(N)])
+#define BINFO_BASE_ITERATE(NODE,N,B) \
+ (BINFO_BASE_BINFOS (NODE)->iterate ((N), &(B)))
+#define BINFO_BASE_APPEND(NODE,T) \
+ (BINFO_BASE_BINFOS (NODE)->quick_push ((T)))
+
+/* For a BINFO record describing a virtual base class, i.e., one where
+ TREE_VIA_VIRTUAL is set, this field assists in locating the virtual
+ base. The actual contents are language-dependent. In the C++
+ front-end this field is an INTEGER_CST giving an offset into the
+ vtable where the offset to the virtual base can be found. */
+#define BINFO_VPTR_FIELD(NODE) (TREE_BINFO_CHECK (NODE)->binfo.vptr_field)
+
+/* Indicates the accesses this binfo has to its bases. The values are
+ access_public_node, access_protected_node or access_private_node.
+ If this array is not present, public access is implied. */
+#define BINFO_BASE_ACCESSES(NODE) \
+ (TREE_BINFO_CHECK (NODE)->binfo.base_accesses)
+
+#define BINFO_BASE_ACCESS(NODE,N) \
+ (*BINFO_BASE_ACCESSES (NODE))[(N)]
+#define BINFO_BASE_ACCESS_APPEND(NODE,T) \
+ BINFO_BASE_ACCESSES (NODE)->quick_push ((T))
+
+/* The index in the VTT where this subobject's sub-VTT can be found.
+ NULL_TREE if there is no sub-VTT. */
+#define BINFO_SUBVTT_INDEX(NODE) (TREE_BINFO_CHECK (NODE)->binfo.vtt_subvtt)
+
+/* The index in the VTT where the vptr for this subobject can be
+ found. NULL_TREE if there is no secondary vptr in the VTT. */
+#define BINFO_VPTR_INDEX(NODE) (TREE_BINFO_CHECK (NODE)->binfo.vtt_vptr)
+
+/* The BINFO_INHERITANCE_CHAIN points at the binfo for the base
+ inheriting this base for non-virtual bases. For virtual bases it
+ points either to the binfo for which this is a primary binfo, or to
+ the binfo of the most derived type. */
+#define BINFO_INHERITANCE_CHAIN(NODE) \
+ (TREE_BINFO_CHECK (NODE)->binfo.inheritance)
+
+
+/* Define fields and accessors for nodes representing declared names. */
+
+/* Nonzero if DECL represents an SSA name or a variable that can possibly
+ have an associated SSA name. */
+#define SSA_VAR_P(DECL) \
+ (TREE_CODE (DECL) == VAR_DECL \
+ || TREE_CODE (DECL) == PARM_DECL \
+ || TREE_CODE (DECL) == RESULT_DECL \
+ || TREE_CODE (DECL) == SSA_NAME)
+
+
+#define DECL_CHAIN(NODE) (TREE_CHAIN (DECL_MINIMAL_CHECK (NODE)))
+
+/* This is the name of the object as written by the user.
+ It is an IDENTIFIER_NODE. */
+#define DECL_NAME(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.name)
+
+/* The IDENTIFIER_NODE associated with the TYPE_NAME field. */
+#define TYPE_IDENTIFIER(NODE) \
+ (TYPE_NAME (NODE) && DECL_P (TYPE_NAME (NODE)) \
+ ? DECL_NAME (TYPE_NAME (NODE)) : TYPE_NAME (NODE))
+
+/* Every ..._DECL node gets a unique number. */
+#define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
+
+/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
+ uses. */
+#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
+
+/* Every ..._DECL node gets a unique number that stays the same even
+ when the decl is copied by the inliner once it is set. */
+#define DECL_PT_UID(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.pt_uid == -1u \
+ ? (NODE)->decl_minimal.uid : (NODE)->decl_common.pt_uid)
+/* Initialize the ..._DECL node pt-uid to the decls uid. */
+#define SET_DECL_PT_UID(NODE, UID) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.pt_uid = (UID))
+/* Whether the ..._DECL node pt-uid has been initialized and thus needs to
+ be preserved when copyin the decl. */
+#define DECL_PT_UID_SET_P(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.pt_uid != -1u)
+
+/* These two fields describe where in the source code the declaration
+ was. If the declaration appears in several places (as for a C
+ function that is declared first and then defined later), this
+ information should refer to the definition. */
+#define DECL_SOURCE_LOCATION(NODE) \
+ (DECL_MINIMAL_CHECK (NODE)->decl_minimal.locus)
+#define DECL_SOURCE_FILE(NODE) LOCATION_FILE (DECL_SOURCE_LOCATION (NODE))
+#define DECL_SOURCE_LINE(NODE) LOCATION_LINE (DECL_SOURCE_LOCATION (NODE))
+#define DECL_SOURCE_COLUMN(NODE) LOCATION_COLUMN (DECL_SOURCE_LOCATION (NODE))
+/* This decl was created by a front-end or back-end rather than by
+ user code, and has not been explicitly declared by the user -- when
+ that happens the source location is updated to the user's
+ source. This includes decls with no location (!). */
+#define DECL_IS_UNDECLARED_BUILTIN(DECL) \
+ (DECL_SOURCE_LOCATION (DECL) <= BUILTINS_LOCATION)
+
+/* For FIELD_DECLs, this is the RECORD_TYPE, UNION_TYPE, or
+ QUAL_UNION_TYPE node that the field is a member of. For VAR_DECL,
+ PARM_DECL, FUNCTION_DECL, LABEL_DECL, RESULT_DECL, and CONST_DECL
+ nodes, this points to either the FUNCTION_DECL for the containing
+ function, the RECORD_TYPE or UNION_TYPE for the containing type, or
+ NULL_TREE or a TRANSLATION_UNIT_DECL if the given decl has "file
+ scope". In particular, for VAR_DECLs which are virtual table pointers
+ (they have DECL_VIRTUAL set), we use DECL_CONTEXT to determine the type
+ they belong to. */
+#define DECL_CONTEXT(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.context)
+#define DECL_FIELD_CONTEXT(NODE) \
+ (FIELD_DECL_CHECK (NODE)->decl_minimal.context)
+
+/* If nonzero, decl's name shouldn't be emitted into debug info. */
+#define DECL_NAMELESS(NODE) (DECL_MINIMAL_CHECK (NODE)->base.u.bits.nameless_flag)
+
+/* For any sort of a ..._DECL node, this points to the original (abstract)
+ decl node which this decl is an inlined/cloned instance of, or else it
+ is NULL indicating that this decl is not an instance of some other decl.
+
+ The C front-end also uses this in a nested declaration of an inline
+ function, to point back to the definition. */
+#define DECL_ABSTRACT_ORIGIN(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.abstract_origin)
+
+/* Like DECL_ABSTRACT_ORIGIN, but returns NODE if there's no abstract
+ origin. This is useful when setting the DECL_ABSTRACT_ORIGIN. */
+#define DECL_ORIGIN(NODE) \
+ (DECL_ABSTRACT_ORIGIN (NODE) ? DECL_ABSTRACT_ORIGIN (NODE) : (NODE))
+
+/* Nonzero for any sort of ..._DECL node means this decl node represents an
+ inline instance of some original (abstract) decl from an inline function;
+ suppress any warnings about shadowing some other variable. FUNCTION_DECL
+ nodes can also have their abstract origin set to themselves. */
+#define DECL_FROM_INLINE(NODE) \
+ (DECL_ABSTRACT_ORIGIN (NODE) != NULL_TREE \
+ && DECL_ABSTRACT_ORIGIN (NODE) != (NODE))
+
+/* In a DECL this is the field where attributes are stored. */
+#define DECL_ATTRIBUTES(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.attributes)
+
+/* For a FUNCTION_DECL, holds the tree of BINDINGs.
+ For a TRANSLATION_UNIT_DECL, holds the namespace's BLOCK.
+ For a VAR_DECL, holds the initial value.
+ For a PARM_DECL, used for DECL_ARG_TYPE--default
+ values for parameters are encoded in the type of the function,
+ not in the PARM_DECL slot.
+ For a FIELD_DECL, this is used for enumeration values and the C
+ frontend uses it for temporarily storing bitwidth of bitfields.
+
+ ??? Need to figure out some way to check this isn't a PARM_DECL. */
+#define DECL_INITIAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.initial)
+
+/* Holds the size of the datum, in bits, as a tree expression.
+ Need not be constant and may be null. May be less than TYPE_SIZE
+ for a C++ FIELD_DECL representing a base class subobject with its
+ own virtual base classes (which are laid out separately). */
+#define DECL_SIZE(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.size)
+/* Likewise for the size in bytes. */
+#define DECL_SIZE_UNIT(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.size_unit)
+#define DECL_ALIGN_RAW(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.align)
+/* Returns the alignment required for the datum, in bits. It must
+ be a power of two, but an "alignment" of zero is supported
+ (e.g. as "uninitialized" sentinel). */
+#define DECL_ALIGN(NODE) \
+ (DECL_ALIGN_RAW (NODE) \
+ ? ((unsigned)1) << (DECL_ALIGN_RAW (NODE) - 1) : 0)
+/* Specify that DECL_ALIGN(NODE) is X. */
+#define SET_DECL_ALIGN(NODE, X) \
+ (DECL_ALIGN_RAW (NODE) = ffs_hwi (X))
+
+/* The minimum alignment necessary for the datum, in bits, without
+ warning. */
+#define DECL_WARN_IF_NOT_ALIGN_RAW(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.warn_if_not_align)
+#define DECL_WARN_IF_NOT_ALIGN(NODE) \
+ (DECL_WARN_IF_NOT_ALIGN_RAW (NODE) \
+ ? ((unsigned)1) << (DECL_WARN_IF_NOT_ALIGN_RAW (NODE) - 1) : 0)
+
+/* Specify that DECL_WARN_IF_NOT_ALIGN(NODE) is X. */
+#define SET_DECL_WARN_IF_NOT_ALIGN(NODE, X) \
+ (DECL_WARN_IF_NOT_ALIGN_RAW (NODE) = ffs_hwi (X))
+
+/* The alignment of NODE, in bytes. */
+#define DECL_ALIGN_UNIT(NODE) (DECL_ALIGN (NODE) / BITS_PER_UNIT)
+/* Set if the alignment of this DECL has been set by the user, for
+ example with an 'aligned' attribute. */
+#define DECL_USER_ALIGN(NODE) \
+ (DECL_COMMON_CHECK (NODE)->base.u.bits.user_align)
+/* Holds the machine mode corresponding to the declaration of a variable or
+ field. Always equal to TYPE_MODE (TREE_TYPE (decl)) except for a
+ FIELD_DECL. */
+#define DECL_MODE(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.mode)
+#define SET_DECL_MODE(NODE, MODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.mode = (MODE))
+
+/* For FUNCTION_DECL, if it is built-in, this identifies which built-in
+ operation it is. This is only intended for low-level accesses;
+ normally DECL_FUNCTION_CODE, DECL_FE_FUNCTION_CODE or DECL_MD_FUNCTION
+ should be used instead. */
+#define DECL_UNCHECKED_FUNCTION_CODE(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.function_code)
+
+/* Test if FCODE is a function code for an alloca operation. */
+#define ALLOCA_FUNCTION_CODE_P(FCODE) \
+ ((FCODE) == BUILT_IN_ALLOCA \
+ || (FCODE) == BUILT_IN_ALLOCA_WITH_ALIGN \
+ || (FCODE) == BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX)
+
+/* Generate case for an alloca operation. */
+#define CASE_BUILT_IN_ALLOCA \
+ case BUILT_IN_ALLOCA: \
+ case BUILT_IN_ALLOCA_WITH_ALIGN: \
+ case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX
+
+#define DECL_FUNCTION_PERSONALITY(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.personality)
+
+/* Nonzero for a given ..._DECL node means that the name of this node should
+ be ignored for symbolic debug purposes. For a TYPE_DECL, this means that
+ the associated type should be ignored. For a FUNCTION_DECL, the body of
+ the function should also be ignored. */
+#define DECL_IGNORED_P(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.ignored_flag)
+
+/* Nonzero for a given ..._DECL node means that this node represents an
+ "abstract instance" of the given declaration (e.g. in the original
+ declaration of an inline function). When generating symbolic debugging
+ information, we mustn't try to generate any address information for nodes
+ marked as "abstract instances" because we don't actually generate
+ any code or allocate any data space for such instances. */
+#define DECL_ABSTRACT_P(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.abstract_flag)
+
+/* Language-specific decl information. */
+#define DECL_LANG_SPECIFIC(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_specific)
+
+/* In a VAR_DECL or FUNCTION_DECL, nonzero means external reference:
+ do not allocate storage, and refer to a definition elsewhere. Note that
+ this does not necessarily imply the entity represented by NODE
+ has no program source-level definition in this translation unit. For
+ example, for a FUNCTION_DECL, DECL_SAVED_TREE may be non-NULL and
+ DECL_EXTERNAL may be true simultaneously; that can be the case for
+ a C99 "extern inline" function. */
+#define DECL_EXTERNAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.decl_flag_1)
+
+/* Nonzero in a ..._DECL means this variable is ref'd from a nested function.
+ For VAR_DECL nodes, PARM_DECL nodes, and FUNCTION_DECL nodes.
+
+ For LABEL_DECL nodes, nonzero if nonlocal gotos to the label are permitted.
+
+ Also set in some languages for variables, etc., outside the normal
+ lexical scope, such as class instance variables. */
+#define DECL_NONLOCAL(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.nonlocal_flag)
+
+/* Used in VAR_DECLs to indicate that the variable is a vtable.
+ Used in FIELD_DECLs for vtable pointers.
+ Used in FUNCTION_DECLs to indicate that the function is virtual. */
+#define DECL_VIRTUAL_P(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.virtual_flag)
+
+/* Used to indicate that this DECL represents a compiler-generated entity. */
+#define DECL_ARTIFICIAL(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.artificial_flag)
+
+/* Additional flags for language-specific uses. */
+#define DECL_LANG_FLAG_0(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_0)
+#define DECL_LANG_FLAG_1(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_1)
+#define DECL_LANG_FLAG_2(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_2)
+#define DECL_LANG_FLAG_3(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_3)
+#define DECL_LANG_FLAG_4(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_4)
+#define DECL_LANG_FLAG_5(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_5)
+#define DECL_LANG_FLAG_6(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_6)
+#define DECL_LANG_FLAG_7(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_7)
+#define DECL_LANG_FLAG_8(NODE) \
+ (DECL_COMMON_CHECK (NODE)->decl_common.lang_flag_8)
+
+/* Nonzero for a scope which is equal to file scope. */
+#define SCOPE_FILE_SCOPE_P(EXP) \
+ (! (EXP) || TREE_CODE (EXP) == TRANSLATION_UNIT_DECL)
+/* Nonzero for a decl which is at file scope. */
+#define DECL_FILE_SCOPE_P(EXP) SCOPE_FILE_SCOPE_P (DECL_CONTEXT (EXP))
+/* Nonzero for a type which is at file scope. */
+#define TYPE_FILE_SCOPE_P(EXP) SCOPE_FILE_SCOPE_P (TYPE_CONTEXT (EXP))
+
+/* Nonzero for a decl that is decorated using attribute used.
+ This indicates to compiler tools that this decl needs to be preserved. */
+#define DECL_PRESERVE_P(DECL) \
+ DECL_COMMON_CHECK (DECL)->decl_common.preserve_flag
+
+/* Nonzero for a decl that is decorated with the "noinit" attribute.
+ decls with this attribute are placed into the ".noinit" section, so they are
+ not initialized by the target's startup code. */
+#define DECL_NOINIT_P(DECL) \
+ (DECL_P (DECL) \
+ && (lookup_attribute ("noinit", DECL_ATTRIBUTES (DECL)) != NULL_TREE))
+
+/* Nonzero for a decl that is decorated with the "persistent" attribute.
+ decls with this attribute are placed into the ".persistent" section, so they
+ are not initialized by the target's startup code. */
+#define DECL_PERSISTENT_P(DECL) \
+ (DECL_P (DECL) \
+ && (lookup_attribute ("persistent", DECL_ATTRIBUTES (DECL)) != NULL_TREE))
+
+/* For function local variables of COMPLEX and VECTOR types,
+ indicates that the variable is not aliased, and that all
+ modifications to the variable have been adjusted so that
+ they are killing assignments. Thus the variable may now
+ be treated as a GIMPLE register, and use real instead of
+ virtual ops in SSA form. */
+#define DECL_NOT_GIMPLE_REG_P(DECL) \
+ DECL_COMMON_CHECK (DECL)->decl_common.not_gimple_reg_flag
+
+extern tree decl_value_expr_lookup (tree);
+extern void decl_value_expr_insert (tree, tree);
+
+/* In a VAR_DECL or PARM_DECL, the location at which the value may be found,
+ if transformations have made this more complicated than evaluating the
+ decl itself. */
+#define DECL_HAS_VALUE_EXPR_P(NODE) \
+ (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, RESULT_DECL) \
+ ->decl_common.decl_flag_2)
+#define DECL_VALUE_EXPR(NODE) \
+ (decl_value_expr_lookup (DECL_WRTL_CHECK (NODE)))
+#define SET_DECL_VALUE_EXPR(NODE, VAL) \
+ (decl_value_expr_insert (DECL_WRTL_CHECK (NODE), VAL))
+
+/* Holds the RTL expression for the value of a variable or function.
+ This value can be evaluated lazily for functions, variables with
+ static storage duration, and labels. */
+#define DECL_RTL(NODE) \
+ (DECL_WRTL_CHECK (NODE)->decl_with_rtl.rtl \
+ ? (NODE)->decl_with_rtl.rtl \
+ : (make_decl_rtl (NODE), (NODE)->decl_with_rtl.rtl))
+
+/* Set the DECL_RTL for NODE to RTL. */
+#define SET_DECL_RTL(NODE, RTL) set_decl_rtl (NODE, RTL)
+
+/* Returns nonzero if NODE is a tree node that can contain RTL. */
+#define HAS_RTL_P(NODE) (CODE_CONTAINS_STRUCT (TREE_CODE (NODE), TS_DECL_WRTL))
+
+/* Returns nonzero if the DECL_RTL for NODE has already been set. */
+#define DECL_RTL_SET_P(NODE) \
+ (HAS_RTL_P (NODE) && DECL_WRTL_CHECK (NODE)->decl_with_rtl.rtl != NULL)
+
+/* Copy the RTL from SRC_DECL to DST_DECL. If the RTL was not set for
+ SRC_DECL, it will not be set for DST_DECL; this is a lazy copy. */
+#define COPY_DECL_RTL(SRC_DECL, DST_DECL) \
+ (DECL_WRTL_CHECK (DST_DECL)->decl_with_rtl.rtl \
+ = DECL_WRTL_CHECK (SRC_DECL)->decl_with_rtl.rtl)
+
+/* The DECL_RTL for NODE, if it is set, or NULL, if it is not set. */
+#define DECL_RTL_IF_SET(NODE) (DECL_RTL_SET_P (NODE) ? DECL_RTL (NODE) : NULL)
+
+#if (GCC_VERSION >= 2007)
+#define DECL_RTL_KNOWN_SET(decl) __extension__ \
+({ tree const __d = (decl); \
+ gcc_checking_assert (DECL_RTL_SET_P (__d)); \
+ /* Dereference it so the compiler knows it can't be NULL even \
+ without assertion checking. */ \
+ &*DECL_RTL_IF_SET (__d); })
+#else
+#define DECL_RTL_KNOWN_SET(decl) (&*DECL_RTL_IF_SET (decl))
+#endif
+
+/* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'. */
+#define DECL_REGISTER(NODE) (DECL_WRTL_CHECK (NODE)->decl_common.decl_flag_0)
+
+/* In a FIELD_DECL, this is the field position, counting in bytes, of the
+ DECL_OFFSET_ALIGN-bit-sized word containing the bit closest to the beginning
+ of the structure. */
+#define DECL_FIELD_OFFSET(NODE) (FIELD_DECL_CHECK (NODE)->field_decl.offset)
+
+/* In a FIELD_DECL, this is the offset, in bits, of the first bit of the
+ field from DECL_FIELD_OFFSET. This field may be nonzero even for fields
+ that are not bit fields (since DECL_OFFSET_ALIGN may be larger than the
+ natural alignment of the field's type). */
+#define DECL_FIELD_BIT_OFFSET(NODE) \
+ (FIELD_DECL_CHECK (NODE)->field_decl.bit_offset)
+
+/* In a FIELD_DECL, this indicates whether the field was a bit-field and
+ if so, the type that was originally specified for it.
+ TREE_TYPE may have been modified (in finish_struct). */
+#define DECL_BIT_FIELD_TYPE(NODE) \
+ (FIELD_DECL_CHECK (NODE)->field_decl.bit_field_type)
+
+/* In a FIELD_DECL of a RECORD_TYPE, this is a pointer to the storage
+ representative FIELD_DECL. */
+#define DECL_BIT_FIELD_REPRESENTATIVE(NODE) \
+ (FIELD_DECL_CHECK (NODE)->field_decl.qualifier)
+
+/* For a FIELD_DECL in a QUAL_UNION_TYPE, records the expression, which
+ if nonzero, indicates that the field occupies the type. */
+#define DECL_QUALIFIER(NODE) (FIELD_DECL_CHECK (NODE)->field_decl.qualifier)
+
+/* For FIELD_DECLs, off_align holds the number of low-order bits of
+ DECL_FIELD_OFFSET which are known to be always zero.
+ DECL_OFFSET_ALIGN thus returns the alignment that DECL_FIELD_OFFSET
+ has. */
+#define DECL_OFFSET_ALIGN(NODE) \
+ (((unsigned HOST_WIDE_INT)1) << FIELD_DECL_CHECK (NODE)->decl_common.off_align)
+
+/* Specify that DECL_OFFSET_ALIGN(NODE) is X. */
+#define SET_DECL_OFFSET_ALIGN(NODE, X) \
+ (FIELD_DECL_CHECK (NODE)->decl_common.off_align = ffs_hwi (X) - 1)
+
+/* For FIELD_DECLS, DECL_FCONTEXT is the *first* baseclass in
+ which this FIELD_DECL is defined. This information is needed when
+ writing debugging information about vfield and vbase decls for C++. */
+#define DECL_FCONTEXT(NODE) (FIELD_DECL_CHECK (NODE)->field_decl.fcontext)
+
+/* In a FIELD_DECL, indicates this field should be bit-packed. */
+#define DECL_PACKED(NODE) (FIELD_DECL_CHECK (NODE)->base.u.bits.packed_flag)
+
+/* Nonzero in a FIELD_DECL means it is a bit field, and must be accessed
+ specially. */
+#define DECL_BIT_FIELD(NODE) (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_1)
+
+/* In a FIELD_DECL, indicates this field should be ignored for ABI decisions
+ like passing/returning containing struct by value.
+ Set for C++17 empty base artificial FIELD_DECLs as well as
+ empty [[no_unique_address]] non-static data members. */
+#define DECL_FIELD_ABI_IGNORED(NODE) \
+ (!DECL_BIT_FIELD (NODE) && (NODE)->decl_common.decl_flag_0)
+#define SET_DECL_FIELD_ABI_IGNORED(NODE, VAL) \
+ do { \
+ gcc_checking_assert (!DECL_BIT_FIELD (NODE)); \
+ FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0 = (VAL); \
+ } while (0)
+
+/* In a FIELD_DECL, indicates C++ zero-width bitfield that used to be
+ removed from the IL since PR42217 until PR101539 and by that changed
+ the ABI on several targets. This flag is provided so that the backends
+ can decide on the ABI with zero-width bitfields and emit -Wpsabi
+ warnings. */
+#define DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD(NODE) \
+ (DECL_BIT_FIELD (NODE) && (NODE)->decl_common.decl_flag_0)
+#define SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD(NODE, VAL) \
+ do { \
+ gcc_checking_assert (DECL_BIT_FIELD (NODE)); \
+ FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_0 = (VAL); \
+ } while (0)
+
+/* Used in a FIELD_DECL to indicate that we cannot form the address of
+ this component. This makes it possible for Type-Based Alias Analysis
+ to disambiguate accesses to this field with indirect accesses using
+ the field's type:
+
+ struct S { int i; } s;
+ int *p;
+
+ If the flag is set on 'i', TBAA computes that s.i and *p never conflict.
+
+ From the implementation's viewpoint, the alias set of the type of the
+ field 'i' (int) will not be recorded as a subset of that of the type of
+ 's' (struct S) in record_component_aliases. The counterpart is that
+ accesses to s.i must not be given the alias set of the type of 'i'
+ (int) but instead directly that of the type of 's' (struct S). */
+#define DECL_NONADDRESSABLE_P(NODE) \
+ (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_2)
+
+/* Used in a FIELD_DECL to indicate that this field is padding. */
+#define DECL_PADDING_P(NODE) \
+ (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_3)
+
+/* A numeric unique identifier for a LABEL_DECL. The UID allocation is
+ dense, unique within any one function, and may be used to index arrays.
+ If the value is -1, then no UID has been assigned. */
+#define LABEL_DECL_UID(NODE) \
+ (LABEL_DECL_CHECK (NODE)->label_decl.label_decl_uid)
+
+/* In a LABEL_DECL, the EH region number for which the label is the
+ post_landing_pad. */
+#define EH_LANDING_PAD_NR(NODE) \
+ (LABEL_DECL_CHECK (NODE)->label_decl.eh_landing_pad_nr)
+
+/* For a PARM_DECL, records the data type used to pass the argument,
+ which may be different from the type seen in the program. */
+#define DECL_ARG_TYPE(NODE) (PARM_DECL_CHECK (NODE)->decl_common.initial)
+
+/* For PARM_DECL, holds an RTL for the stack slot or register
+ where the data was actually passed. */
+#define DECL_INCOMING_RTL(NODE) \
+ (PARM_DECL_CHECK (NODE)->parm_decl.incoming_rtl)
+
+/* Nonzero for a given ..._DECL node means that no warnings should be
+ generated just because this node is unused. */
+#define DECL_IN_SYSTEM_HEADER(NODE) \
+ (in_system_header_at (DECL_SOURCE_LOCATION (NODE)))
+
+/* Used to indicate that the linkage status of this DECL is not yet known,
+ so it should not be output now. */
+#define DECL_DEFER_OUTPUT(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.defer_output)
+
+/* In a VAR_DECL that's static,
+ nonzero if the space is in the text section. */
+#define DECL_IN_TEXT_SECTION(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_with_vis.in_text_section)
+
+/* In a VAR_DECL that's static,
+ nonzero if it belongs to the global constant pool. */
+#define DECL_IN_CONSTANT_POOL(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_with_vis.in_constant_pool)
+
+/* Nonzero for a given ..._DECL node means that this node should be
+ put in .common, if possible. If a DECL_INITIAL is given, and it
+ is not error_mark_node, then the decl cannot be put in .common. */
+#define DECL_COMMON(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.common_flag)
+
+/* In a VAR_DECL, nonzero if the decl is a register variable with
+ an explicit asm specification. */
+#define DECL_HARD_REGISTER(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_with_vis.hard_register)
+
+ /* Used to indicate that this DECL has weak linkage. */
+#define DECL_WEAK(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.weak_flag)
+
+/* Used to indicate that the DECL is a dllimport. */
+#define DECL_DLLIMPORT_P(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
+
+/* Used in a DECL to indicate that, even if it TREE_PUBLIC, it need
+ not be put out unless it is needed in this translation unit.
+ Entities like this are shared across translation units (like weak
+ entities), but are guaranteed to be generated by any translation
+ unit that needs them, and therefore need not be put out anywhere
+ where they are not needed. DECL_COMDAT is just a hint to the
+ back-end; it is up to front-ends which set this flag to ensure
+ that there will never be any harm, other than bloat, in putting out
+ something which is DECL_COMDAT. */
+#define DECL_COMDAT(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_flag)
+
+#define DECL_COMDAT_GROUP(NODE) \
+ decl_comdat_group (NODE)
+
+/* Used in TREE_PUBLIC decls to indicate that copies of this DECL in
+ multiple translation units should be merged. */
+#define DECL_ONE_ONLY(NODE) (DECL_COMDAT_GROUP (NODE) != NULL_TREE \
+ && (TREE_PUBLIC (NODE) || DECL_EXTERNAL (NODE)))
+
+/* The name of the object as the assembler will see it (but before any
+ translations made by ASM_OUTPUT_LABELREF). Often this is the same
+ as DECL_NAME. It is an IDENTIFIER_NODE.
+
+ ASSEMBLER_NAME of TYPE_DECLS may store global name of type used for
+ One Definition Rule based type merging at LTO. It is computed only for
+ LTO compilation and C++. */
+#define DECL_ASSEMBLER_NAME(NODE) decl_assembler_name (NODE)
+
+/* Raw accessor for DECL_ASSEMBLE_NAME. */
+#define DECL_ASSEMBLER_NAME_RAW(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.assembler_name)
+
+/* Return true if NODE is a NODE that can contain a DECL_ASSEMBLER_NAME.
+ This is true of all DECL nodes except FIELD_DECL. */
+#define HAS_DECL_ASSEMBLER_NAME_P(NODE) \
+ (CODE_CONTAINS_STRUCT (TREE_CODE (NODE), TS_DECL_WITH_VIS))
+
+/* Returns nonzero if the DECL_ASSEMBLER_NAME for NODE has been set. If zero,
+ the NODE might still have a DECL_ASSEMBLER_NAME -- it just hasn't been set
+ yet. */
+#define DECL_ASSEMBLER_NAME_SET_P(NODE) \
+ (DECL_ASSEMBLER_NAME_RAW (NODE) != NULL_TREE)
+
+/* Set the DECL_ASSEMBLER_NAME for NODE to NAME. */
+#define SET_DECL_ASSEMBLER_NAME(NODE, NAME) \
+ overwrite_decl_assembler_name (NODE, NAME)
+
+/* Copy the DECL_ASSEMBLER_NAME from SRC_DECL to DST_DECL. Note that
+ if SRC_DECL's DECL_ASSEMBLER_NAME has not yet been set, using this
+ macro will not cause the DECL_ASSEMBLER_NAME to be set, but will
+ clear DECL_ASSEMBLER_NAME of DST_DECL, if it was already set. In
+ other words, the semantics of using this macro, are different than
+ saying:
+
+ SET_DECL_ASSEMBLER_NAME(DST_DECL, DECL_ASSEMBLER_NAME (SRC_DECL))
+
+ which will try to set the DECL_ASSEMBLER_NAME for SRC_DECL. */
+
+#define COPY_DECL_ASSEMBLER_NAME(SRC_DECL, DST_DECL) \
+ SET_DECL_ASSEMBLER_NAME (DST_DECL, DECL_ASSEMBLER_NAME_RAW (SRC_DECL))
+
+/* Records the section name in a section attribute. Used to pass
+ the name from decl_attributes to make_function_rtl and make_decl_rtl. */
+#define DECL_SECTION_NAME(NODE) decl_section_name (NODE)
+
+/* Nonzero in a decl means that the gimplifier has seen (or placed)
+ this variable in a BIND_EXPR. */
+#define DECL_SEEN_IN_BIND_EXPR_P(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.seen_in_bind_expr)
+
+/* Value of the decls's visibility attribute */
+#define DECL_VISIBILITY(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.visibility)
+
+/* Nonzero means that the decl (or an enclosing scope) had its
+ visibility specified rather than being inferred. */
+#define DECL_VISIBILITY_SPECIFIED(NODE) \
+ (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.visibility_specified)
+
+/* In a VAR_DECL, the model to use if the data should be allocated from
+ thread-local storage. */
+#define DECL_TLS_MODEL(NODE) decl_tls_model (NODE)
+
+/* In a VAR_DECL, nonzero if the data should be allocated from
+ thread-local storage. */
+#define DECL_THREAD_LOCAL_P(NODE) \
+ ((TREE_STATIC (NODE) || DECL_EXTERNAL (NODE)) && decl_tls_model (NODE) >= TLS_MODEL_REAL)
+
+/* In a non-local VAR_DECL with static storage duration, true if the
+ variable has an initialization priority. If false, the variable
+ will be initialized at the DEFAULT_INIT_PRIORITY. */
+#define DECL_HAS_INIT_PRIORITY_P(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p)
+
+extern tree decl_debug_expr_lookup (tree);
+extern void decl_debug_expr_insert (tree, tree);
+
+/* For VAR_DECL, this is set to an expression that it was split from. */
+#define DECL_HAS_DEBUG_EXPR_P(NODE) \
+ (VAR_DECL_CHECK (NODE)->decl_common.debug_expr_is_from)
+#define DECL_DEBUG_EXPR(NODE) \
+ (decl_debug_expr_lookup (VAR_DECL_CHECK (NODE)))
+
+#define SET_DECL_DEBUG_EXPR(NODE, VAL) \
+ (decl_debug_expr_insert (VAR_DECL_CHECK (NODE), VAL))
+
+extern priority_type decl_init_priority_lookup (tree);
+extern priority_type decl_fini_priority_lookup (tree);
+extern void decl_init_priority_insert (tree, priority_type);
+extern void decl_fini_priority_insert (tree, priority_type);
+
+/* For a VAR_DECL or FUNCTION_DECL the initialization priority of
+ NODE. */
+#define DECL_INIT_PRIORITY(NODE) \
+ (decl_init_priority_lookup (NODE))
+/* Set the initialization priority for NODE to VAL. */
+#define SET_DECL_INIT_PRIORITY(NODE, VAL) \
+ (decl_init_priority_insert (NODE, VAL))
+
+/* For a FUNCTION_DECL the finalization priority of NODE. */
+#define DECL_FINI_PRIORITY(NODE) \
+ (decl_fini_priority_lookup (NODE))
+/* Set the finalization priority for NODE to VAL. */
+#define SET_DECL_FINI_PRIORITY(NODE, VAL) \
+ (decl_fini_priority_insert (NODE, VAL))
+
+/* The initialization priority for entities for which no explicit
+ initialization priority has been specified. */
+#define DEFAULT_INIT_PRIORITY 65535
+
+/* The maximum allowed initialization priority. */
+#define MAX_INIT_PRIORITY 65535
+
+/* The largest priority value reserved for use by system runtime
+ libraries. */
+#define MAX_RESERVED_INIT_PRIORITY 100
+
+/* In a VAR_DECL, nonzero if this is a global variable for VOPs. */
+#define VAR_DECL_IS_VIRTUAL_OPERAND(NODE) \
+ (VAR_DECL_CHECK (NODE)->base.u.bits.saturating_flag)
+
+/* In a VAR_DECL, nonzero if this is a non-local frame structure. */
+#define DECL_NONLOCAL_FRAME(NODE) \
+ (VAR_DECL_CHECK (NODE)->base.default_def_flag)
+
+/* In a VAR_DECL, nonzero if this variable is not aliased by any pointer. */
+#define DECL_NONALIASED(NODE) \
+ (VAR_DECL_CHECK (NODE)->base.nothrow_flag)
+
+/* This field is used to reference anything in decl.result and is meant only
+ for use by the garbage collector. */
+#define DECL_RESULT_FLD(NODE) \
+ (DECL_NON_COMMON_CHECK (NODE)->decl_non_common.result)
+
+/* The DECL_VINDEX is used for FUNCTION_DECLS in two different ways.
+ Before the struct containing the FUNCTION_DECL is laid out,
+ DECL_VINDEX may point to a FUNCTION_DECL in a base class which
+ is the FUNCTION_DECL which this FUNCTION_DECL will replace as a virtual
+ function. When the class is laid out, this pointer is changed
+ to an INTEGER_CST node which is suitable for use as an index
+ into the virtual function table. */
+#define DECL_VINDEX(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.vindex)
+
+/* In FUNCTION_DECL, holds the decl for the return value. */
+#define DECL_RESULT(NODE) (FUNCTION_DECL_CHECK (NODE)->decl_non_common.result)
+
+/* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
+#define DECL_UNINLINABLE(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.uninlinable)
+
+/* In a FUNCTION_DECL, the saved representation of the body of the
+ entire function. */
+#define DECL_SAVED_TREE(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.saved_tree)
+
+/* Nonzero in a FUNCTION_DECL means this function should be treated
+ as if it were a malloc, meaning it returns a pointer that is
+ not an alias. */
+#define DECL_IS_MALLOC(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.malloc_flag)
+
+/* Macro for direct set and get of function_decl.decl_type. */
+#define FUNCTION_DECL_DECL_TYPE(NODE) \
+ (NODE->function_decl.decl_type)
+
+/* Set decl_type of a DECL. Set it to T when SET is true, or reset
+ it to NONE. */
+
+static inline void
+set_function_decl_type (tree decl, function_decl_type t, bool set)
+{
+ if (set)
+ {
+ gcc_assert (FUNCTION_DECL_DECL_TYPE (decl) == NONE
+ || FUNCTION_DECL_DECL_TYPE (decl) == t);
+ FUNCTION_DECL_DECL_TYPE (decl) = t;
+ }
+ else if (FUNCTION_DECL_DECL_TYPE (decl) == t)
+ FUNCTION_DECL_DECL_TYPE (decl) = NONE;
+}
+
+/* Nonzero in a FUNCTION_DECL means this function is a replaceable
+ function (like replaceable operators new or delete). */
+#define DECL_IS_REPLACEABLE_OPERATOR(NODE)\
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.replaceable_operator)
+
+/* Nonzero in a FUNCTION_DECL means this function should be treated as
+ C++ operator new, meaning that it returns a pointer for which we
+ should not use type based aliasing. */
+#define DECL_IS_OPERATOR_NEW_P(NODE) \
+ (FUNCTION_DECL_DECL_TYPE (FUNCTION_DECL_CHECK (NODE)) == OPERATOR_NEW)
+
+#define DECL_IS_REPLACEABLE_OPERATOR_NEW_P(NODE) \
+ (DECL_IS_OPERATOR_NEW_P (NODE) && DECL_IS_REPLACEABLE_OPERATOR (NODE))
+
+#define DECL_SET_IS_OPERATOR_NEW(NODE, VAL) \
+ set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_NEW, VAL)
+
+/* Nonzero in a FUNCTION_DECL means this function should be treated as
+ C++ operator delete. */
+#define DECL_IS_OPERATOR_DELETE_P(NODE) \
+ (FUNCTION_DECL_DECL_TYPE (FUNCTION_DECL_CHECK (NODE)) == OPERATOR_DELETE)
+
+#define DECL_SET_IS_OPERATOR_DELETE(NODE, VAL) \
+ set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_DELETE, VAL)
+
+/* Nonzero in a FUNCTION_DECL means this function may return more
+ than once. */
+#define DECL_IS_RETURNS_TWICE(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.returns_twice_flag)
+
+/* Nonzero in a FUNCTION_DECL means this function should be treated
+ as "pure" function (like const function, but may read global memory).
+ Note that being pure or const for a function is orthogonal to being
+ nothrow, i.e. it is valid to have DECL_PURE_P set and TREE_NOTHROW
+ cleared. */
+#define DECL_PURE_P(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.pure_flag)
+
+/* Nonzero only if one of TREE_READONLY or DECL_PURE_P is nonzero AND
+ the const or pure function may not terminate. When this is nonzero
+ for a const or pure function, it can be dealt with by cse passes
+ but cannot be removed by dce passes since you are not allowed to
+ change an infinite looping program into one that terminates without
+ error. */
+#define DECL_LOOPING_CONST_OR_PURE_P(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.looping_const_or_pure_flag)
+
+/* Nonzero in a FUNCTION_DECL means this function should be treated
+ as "novops" function (function that does not read global memory,
+ but may have arbitrary side effects). */
+#define DECL_IS_NOVOPS(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.novops_flag)
+
+/* Used in FUNCTION_DECLs to indicate that they should be run automatically
+ at the beginning or end of execution. */
+#define DECL_STATIC_CONSTRUCTOR(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.static_ctor_flag)
+
+#define DECL_STATIC_DESTRUCTOR(NODE) \
+(FUNCTION_DECL_CHECK (NODE)->function_decl.static_dtor_flag)
+
+/* Used in FUNCTION_DECLs to indicate that function entry and exit should
+ be instrumented with calls to support routines. */
+#define DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.no_instrument_function_entry_exit)
+
+/* Used in FUNCTION_DECLs to indicate that limit-stack-* should be
+ disabled in this function. */
+#define DECL_NO_LIMIT_STACK(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.no_limit_stack)
+
+/* In a FUNCTION_DECL indicates that a static chain is needed. */
+#define DECL_STATIC_CHAIN(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.regdecl_flag)
+
+/* Nonzero for a decl that cgraph has decided should be inlined into
+ at least one call site. It is not meaningful to look at this
+ directly; always use cgraph_function_possibly_inlined_p. */
+#define DECL_POSSIBLY_INLINED(DECL) \
+ FUNCTION_DECL_CHECK (DECL)->function_decl.possibly_inlined
+
+/* Nonzero in a FUNCTION_DECL means that this function was declared inline,
+ such as via the `inline' keyword in C/C++. This flag controls the linkage
+ semantics of 'inline' */
+#define DECL_DECLARED_INLINE_P(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.declared_inline_flag)
+
+/* Nonzero in a FUNCTION_DECL means this function should not get
+ -Winline warnings. */
+#define DECL_NO_INLINE_WARNING_P(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.no_inline_warning_flag)
+
+/* Nonzero if a FUNCTION_CODE is a TM load/store. */
+#define BUILTIN_TM_LOAD_STORE_P(FN) \
+ ((FN) >= BUILT_IN_TM_STORE_1 && (FN) <= BUILT_IN_TM_LOAD_RFW_LDOUBLE)
+
+/* Nonzero if a FUNCTION_CODE is a TM load. */
+#define BUILTIN_TM_LOAD_P(FN) \
+ ((FN) >= BUILT_IN_TM_LOAD_1 && (FN) <= BUILT_IN_TM_LOAD_RFW_LDOUBLE)
+
+/* Nonzero if a FUNCTION_CODE is a TM store. */
+#define BUILTIN_TM_STORE_P(FN) \
+ ((FN) >= BUILT_IN_TM_STORE_1 && (FN) <= BUILT_IN_TM_STORE_WAW_LDOUBLE)
+
+#define CASE_BUILT_IN_TM_LOAD(FN) \
+ case BUILT_IN_TM_LOAD_##FN: \
+ case BUILT_IN_TM_LOAD_RAR_##FN: \
+ case BUILT_IN_TM_LOAD_RAW_##FN: \
+ case BUILT_IN_TM_LOAD_RFW_##FN
+
+#define CASE_BUILT_IN_TM_STORE(FN) \
+ case BUILT_IN_TM_STORE_##FN: \
+ case BUILT_IN_TM_STORE_WAR_##FN: \
+ case BUILT_IN_TM_STORE_WAW_##FN
+
+/* Nonzero in a FUNCTION_DECL that should be always inlined by the inliner
+ disregarding size and cost heuristics. This is equivalent to using
+ the always_inline attribute without the required diagnostics if the
+ function cannot be inlined. */
+#define DECL_DISREGARD_INLINE_LIMITS(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.disregard_inline_limits)
+
+extern vec<tree, va_gc> **decl_debug_args_lookup (tree);
+extern vec<tree, va_gc> **decl_debug_args_insert (tree);
+
+/* Nonzero if a FUNCTION_DECL has DEBUG arguments attached to it. */
+#define DECL_HAS_DEBUG_ARGS_P(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.has_debug_args_flag)
+
+/* For FUNCTION_DECL, this holds a pointer to a structure ("struct function")
+ that describes the status of this function. */
+#define DECL_STRUCT_FUNCTION(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.f)
+
+/* For a builtin function, identify which part of the compiler defined it. */
+#define DECL_BUILT_IN_CLASS(NODE) \
+ ((built_in_class) FUNCTION_DECL_CHECK (NODE)->function_decl.built_in_class)
+
+/* In FUNCTION_DECL, a chain of ..._DECL nodes. */
+#define DECL_ARGUMENTS(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.arguments)
+
+/* In FUNCTION_DECL, the function specific target options to use when compiling
+ this function. */
+#define DECL_FUNCTION_SPECIFIC_TARGET(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_target)
+
+/* In FUNCTION_DECL, the function specific optimization options to use when
+ compiling this function. */
+#define DECL_FUNCTION_SPECIFIC_OPTIMIZATION(NODE) \
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_optimization)
+
+/* In FUNCTION_DECL, this is set if this function has other versions generated
+ using "target" attributes. The default version is the one which does not
+ have any "target" attribute set. */
+#define DECL_FUNCTION_VERSIONED(NODE)\
+ (FUNCTION_DECL_CHECK (NODE)->function_decl.versioned_function)
+
+/* In FUNCTION_DECL, this is set if this function is a C++ constructor.
+ Devirtualization machinery uses this knowledge for determing type of the
+ object constructed. Also we assume that constructor address is not
+ important. */
+#define DECL_CXX_CONSTRUCTOR_P(NODE)\
+ (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.cxx_constructor)
+
+/* In FUNCTION_DECL, this is set if this function is a C++ destructor.
+ Devirtualization machinery uses this to track types in destruction. */
+#define DECL_CXX_DESTRUCTOR_P(NODE)\
+ (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.cxx_destructor)
+
+/* In FUNCTION_DECL, this is set if this function is a lambda function. */
+#define DECL_LAMBDA_FUNCTION_P(NODE) \
+ (FUNCTION_DECL_DECL_TYPE (FUNCTION_DECL_CHECK (NODE)) == LAMBDA_FUNCTION)
+
+#define DECL_SET_LAMBDA_FUNCTION(NODE, VAL) \
+ set_function_decl_type (FUNCTION_DECL_CHECK (NODE), LAMBDA_FUNCTION, VAL)
+
+/* In FUNCTION_DECL that represent an virtual method this is set when
+ the method is final. */
+#define DECL_FINAL_P(NODE)\
+ (FUNCTION_DECL_CHECK (NODE)->decl_with_vis.final)
+
+/* The source language of the translation-unit. */
+#define TRANSLATION_UNIT_LANGUAGE(NODE) \
+ (TRANSLATION_UNIT_DECL_CHECK (NODE)->translation_unit_decl.language)
+
+/* TRANSLATION_UNIT_DECL inherits from DECL_MINIMAL. */
+
+/* For a TYPE_DECL, holds the "original" type. (TREE_TYPE has the copy.) */
+#define DECL_ORIGINAL_TYPE(NODE) \
+ (TYPE_DECL_CHECK (NODE)->decl_non_common.result)
+
+/* In a TYPE_DECL nonzero means the detail info about this type is not dumped
+ into stabs. Instead it will generate cross reference ('x') of names.
+ This uses the same flag as DECL_EXTERNAL. */
+#define TYPE_DECL_SUPPRESS_DEBUG(NODE) \
+ (TYPE_DECL_CHECK (NODE)->decl_common.decl_flag_1)
+
+/* Getter of the imported declaration associated to the
+ IMPORTED_DECL node. */
+#define IMPORTED_DECL_ASSOCIATED_DECL(NODE) \
+(DECL_INITIAL (IMPORTED_DECL_CHECK (NODE)))
+
+/* Getter of the symbol declaration associated with the
+ NAMELIST_DECL node. */
+#define NAMELIST_DECL_ASSOCIATED_DECL(NODE) \
+ (DECL_INITIAL (NODE))
+
+/* A STATEMENT_LIST chains statements together in GENERIC and GIMPLE.
+ To reduce overhead, the nodes containing the statements are not trees.
+ This avoids the overhead of tree_common on all linked list elements.
+
+ Use the interface in tree-iterator.h to access this node. */
+
+#define STATEMENT_LIST_HEAD(NODE) \
+ (STATEMENT_LIST_CHECK (NODE)->stmt_list.head)
+#define STATEMENT_LIST_TAIL(NODE) \
+ (STATEMENT_LIST_CHECK (NODE)->stmt_list.tail)
+
+#define TREE_OPTIMIZATION(NODE) \
+ (OPTIMIZATION_NODE_CHECK (NODE)->optimization.opts)
+
+#define TREE_OPTIMIZATION_OPTABS(NODE) \
+ (OPTIMIZATION_NODE_CHECK (NODE)->optimization.optabs)
+
+#define TREE_OPTIMIZATION_BASE_OPTABS(NODE) \
+ (OPTIMIZATION_NODE_CHECK (NODE)->optimization.base_optabs)
+
+/* Return a tree node that encapsulates the optimization options in OPTS
+ and OPTS_SET. */
+extern tree build_optimization_node (struct gcc_options *opts,
+ struct gcc_options *opts_set);
+
+#define TREE_TARGET_OPTION(NODE) \
+ (TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts)
+
+#define TREE_TARGET_GLOBALS(NODE) \
+ (TARGET_OPTION_NODE_CHECK (NODE)->target_option.globals)
+
+/* Return a tree node that encapsulates the target options in OPTS and
+ OPTS_SET. */
+extern tree build_target_option_node (struct gcc_options *opts,
+ struct gcc_options *opts_set);
+
+extern void prepare_target_option_nodes_for_pch (void);
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+inline tree
+tree_check (tree __t, const char *__f, int __l, const char *__g, tree_code __c)
+{
+ if (TREE_CODE (__t) != __c)
+ tree_check_failed (__t, __f, __l, __g, __c, 0);
+ return __t;
+}
+
+inline tree
+tree_not_check (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c)
+{
+ if (TREE_CODE (__t) == __c)
+ tree_not_check_failed (__t, __f, __l, __g, __c, 0);
+ return __t;
+}
+
+inline tree
+tree_check2 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, 0);
+ return __t;
+}
+
+inline tree
+tree_not_check2 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, 0);
+ return __t;
+}
+
+inline tree
+tree_check3 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2
+ && TREE_CODE (__t) != __c3)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0);
+ return __t;
+}
+
+inline tree
+tree_not_check3 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2
+ || TREE_CODE (__t) == __c3)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0);
+ return __t;
+}
+
+inline tree
+tree_check4 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2
+ && TREE_CODE (__t) != __c3
+ && TREE_CODE (__t) != __c4)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0);
+ return __t;
+}
+
+inline tree
+tree_not_check4 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2
+ || TREE_CODE (__t) == __c3
+ || TREE_CODE (__t) == __c4)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0);
+ return __t;
+}
+
+inline tree
+tree_check5 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4, enum tree_code __c5)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2
+ && TREE_CODE (__t) != __c3
+ && TREE_CODE (__t) != __c4
+ && TREE_CODE (__t) != __c5)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0);
+ return __t;
+}
+
+inline tree
+tree_not_check5 (tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4, enum tree_code __c5)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2
+ || TREE_CODE (__t) == __c3
+ || TREE_CODE (__t) == __c4
+ || TREE_CODE (__t) == __c5)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0);
+ return __t;
+}
+
+inline tree
+contains_struct_check (tree __t, const enum tree_node_structure_enum __s,
+ const char *__f, int __l, const char *__g)
+{
+ if (tree_contains_struct[TREE_CODE (__t)][__s] != 1)
+ tree_contains_struct_check_failed (__t, __s, __f, __l, __g);
+ return __t;
+}
+
+inline tree
+tree_class_check (tree __t, const enum tree_code_class __class,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE_CLASS (TREE_CODE (__t)) != __class)
+ tree_class_check_failed (__t, __class, __f, __l, __g);
+ return __t;
+}
+
+inline tree
+tree_range_check (tree __t,
+ enum tree_code __code1, enum tree_code __code2,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) < __code1 || TREE_CODE (__t) > __code2)
+ tree_range_check_failed (__t, __f, __l, __g, __code1, __code2);
+ return __t;
+}
+
+inline tree
+omp_clause_subcode_check (tree __t, enum omp_clause_code __code,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != OMP_CLAUSE)
+ tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+ if (__t->omp_clause.code != __code)
+ omp_clause_check_failed (__t, __f, __l, __g, __code);
+ return __t;
+}
+
+inline tree
+omp_clause_range_check (tree __t,
+ enum omp_clause_code __code1,
+ enum omp_clause_code __code2,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != OMP_CLAUSE)
+ tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+ if ((int) __t->omp_clause.code < (int) __code1
+ || (int) __t->omp_clause.code > (int) __code2)
+ omp_clause_range_check_failed (__t, __f, __l, __g, __code1, __code2);
+ return __t;
+}
+
+/* These checks have to be special cased. */
+
+inline tree
+expr_check (tree __t, const char *__f, int __l, const char *__g)
+{
+ char const __c = TREE_CODE_CLASS (TREE_CODE (__t));
+ if (!IS_EXPR_CODE_CLASS (__c))
+ tree_class_check_failed (__t, tcc_expression, __f, __l, __g);
+ return __t;
+}
+
+/* These checks have to be special cased. */
+
+inline tree
+non_type_check (tree __t, const char *__f, int __l, const char *__g)
+{
+ if (TYPE_P (__t))
+ tree_not_class_check_failed (__t, tcc_type, __f, __l, __g);
+ return __t;
+}
+
+inline const HOST_WIDE_INT *
+tree_int_cst_elt_check (const_tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != INTEGER_CST)
+ tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
+ if (__i < 0 || __i >= __t->base.u.int_length.extended)
+ tree_int_cst_elt_check_failed (__i, __t->base.u.int_length.extended,
+ __f, __l, __g);
+ return &CONST_CAST_TREE (__t)->int_cst.val[__i];
+}
+
+inline HOST_WIDE_INT *
+tree_int_cst_elt_check (tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != INTEGER_CST)
+ tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
+ if (__i < 0 || __i >= __t->base.u.int_length.extended)
+ tree_int_cst_elt_check_failed (__i, __t->base.u.int_length.extended,
+ __f, __l, __g);
+ return &CONST_CAST_TREE (__t)->int_cst.val[__i];
+}
+
+/* Workaround -Wstrict-overflow false positive during profiledbootstrap. */
+
+# if GCC_VERSION >= 4006
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#endif
+
+inline tree *
+tree_vec_elt_check (tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != TREE_VEC)
+ tree_check_failed (__t, __f, __l, __g, TREE_VEC, 0);
+ if (__i < 0 || __i >= __t->base.u.length)
+ tree_vec_elt_check_failed (__i, __t->base.u.length, __f, __l, __g);
+ return &CONST_CAST_TREE (__t)->vec.a[__i];
+}
+
+# if GCC_VERSION >= 4006
+#pragma GCC diagnostic pop
+#endif
+
+inline tree *
+omp_clause_elt_check (tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != OMP_CLAUSE)
+ tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+ if (__i < 0 || __i >= omp_clause_num_ops [__t->omp_clause.code])
+ omp_clause_operand_check_failed (__i, __t, __f, __l, __g);
+ return &__t->omp_clause.ops[__i];
+}
+
+/* These checks have to be special cased. */
+
+inline tree
+any_integral_type_check (tree __t, const char *__f, int __l, const char *__g)
+{
+ if (!ANY_INTEGRAL_TYPE_P (__t))
+ tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE,
+ INTEGER_TYPE, 0);
+ return __t;
+}
+
+inline const_tree
+tree_check (const_tree __t, const char *__f, int __l, const char *__g,
+ tree_code __c)
+{
+ if (TREE_CODE (__t) != __c)
+ tree_check_failed (__t, __f, __l, __g, __c, 0);
+ return __t;
+}
+
+inline const_tree
+tree_not_check (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c)
+{
+ if (TREE_CODE (__t) == __c)
+ tree_not_check_failed (__t, __f, __l, __g, __c, 0);
+ return __t;
+}
+
+inline const_tree
+tree_check2 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, 0);
+ return __t;
+}
+
+inline const_tree
+tree_not_check2 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, 0);
+ return __t;
+}
+
+inline const_tree
+tree_check3 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2
+ && TREE_CODE (__t) != __c3)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0);
+ return __t;
+}
+
+inline const_tree
+tree_not_check3 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2
+ || TREE_CODE (__t) == __c3)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0);
+ return __t;
+}
+
+inline const_tree
+tree_check4 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2
+ && TREE_CODE (__t) != __c3
+ && TREE_CODE (__t) != __c4)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0);
+ return __t;
+}
+
+inline const_tree
+tree_not_check4 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2
+ || TREE_CODE (__t) == __c3
+ || TREE_CODE (__t) == __c4)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0);
+ return __t;
+}
+
+inline const_tree
+tree_check5 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4, enum tree_code __c5)
+{
+ if (TREE_CODE (__t) != __c1
+ && TREE_CODE (__t) != __c2
+ && TREE_CODE (__t) != __c3
+ && TREE_CODE (__t) != __c4
+ && TREE_CODE (__t) != __c5)
+ tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0);
+ return __t;
+}
+
+inline const_tree
+tree_not_check5 (const_tree __t, const char *__f, int __l, const char *__g,
+ enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+ enum tree_code __c4, enum tree_code __c5)
+{
+ if (TREE_CODE (__t) == __c1
+ || TREE_CODE (__t) == __c2
+ || TREE_CODE (__t) == __c3
+ || TREE_CODE (__t) == __c4
+ || TREE_CODE (__t) == __c5)
+ tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0);
+ return __t;
+}
+
+inline const_tree
+contains_struct_check (const_tree __t, const enum tree_node_structure_enum __s,
+ const char *__f, int __l, const char *__g)
+{
+ if (tree_contains_struct[TREE_CODE (__t)][__s] != 1)
+ tree_contains_struct_check_failed (__t, __s, __f, __l, __g);
+ return __t;
+}
+
+inline const_tree
+tree_class_check (const_tree __t, const enum tree_code_class __class,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE_CLASS (TREE_CODE (__t)) != __class)
+ tree_class_check_failed (__t, __class, __f, __l, __g);
+ return __t;
+}
+
+inline const_tree
+tree_range_check (const_tree __t,
+ enum tree_code __code1, enum tree_code __code2,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) < __code1 || TREE_CODE (__t) > __code2)
+ tree_range_check_failed (__t, __f, __l, __g, __code1, __code2);
+ return __t;
+}
+
+inline const_tree
+omp_clause_subcode_check (const_tree __t, enum omp_clause_code __code,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != OMP_CLAUSE)
+ tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+ if (__t->omp_clause.code != __code)
+ omp_clause_check_failed (__t, __f, __l, __g, __code);
+ return __t;
+}
+
+inline const_tree
+omp_clause_range_check (const_tree __t,
+ enum omp_clause_code __code1,
+ enum omp_clause_code __code2,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != OMP_CLAUSE)
+ tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+ if ((int) __t->omp_clause.code < (int) __code1
+ || (int) __t->omp_clause.code > (int) __code2)
+ omp_clause_range_check_failed (__t, __f, __l, __g, __code1, __code2);
+ return __t;
+}
+
+inline const_tree
+expr_check (const_tree __t, const char *__f, int __l, const char *__g)
+{
+ char const __c = TREE_CODE_CLASS (TREE_CODE (__t));
+ if (!IS_EXPR_CODE_CLASS (__c))
+ tree_class_check_failed (__t, tcc_expression, __f, __l, __g);
+ return __t;
+}
+
+inline const_tree
+non_type_check (const_tree __t, const char *__f, int __l, const char *__g)
+{
+ if (TYPE_P (__t))
+ tree_not_class_check_failed (__t, tcc_type, __f, __l, __g);
+ return __t;
+}
+
+# if GCC_VERSION >= 4006
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-overflow"
+#endif
+
+inline const_tree *
+tree_vec_elt_check (const_tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != TREE_VEC)
+ tree_check_failed (__t, __f, __l, __g, TREE_VEC, 0);
+ if (__i < 0 || __i >= __t->base.u.length)
+ tree_vec_elt_check_failed (__i, __t->base.u.length, __f, __l, __g);
+ return CONST_CAST (const_tree *, &__t->vec.a[__i]);
+ //return &__t->vec.a[__i];
+}
+
+# if GCC_VERSION >= 4006
+#pragma GCC diagnostic pop
+#endif
+
+inline const_tree *
+omp_clause_elt_check (const_tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != OMP_CLAUSE)
+ tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+ if (__i < 0 || __i >= omp_clause_num_ops [__t->omp_clause.code])
+ omp_clause_operand_check_failed (__i, __t, __f, __l, __g);
+ return CONST_CAST (const_tree *, &__t->omp_clause.ops[__i]);
+}
+
+inline const_tree
+any_integral_type_check (const_tree __t, const char *__f, int __l,
+ const char *__g)
+{
+ if (!ANY_INTEGRAL_TYPE_P (__t))
+ tree_check_failed (__t, __f, __l, __g, BOOLEAN_TYPE, ENUMERAL_TYPE,
+ INTEGER_TYPE, 0);
+ return __t;
+}
+
+#endif
+
+/* Compute the number of operands in an expression node NODE. For
+ tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
+ otherwise it is looked up from the node's code. */
+static inline int
+tree_operand_length (const_tree node)
+{
+ if (VL_EXP_CLASS_P (node))
+ return VL_EXP_OPERAND_LENGTH (node);
+ else
+ return TREE_CODE_LENGTH (TREE_CODE (node));
+}
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Special checks for TREE_OPERANDs. */
+inline tree *
+tree_operand_check (tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ const_tree __u = EXPR_CHECK (__t);
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__u))
+ tree_operand_check_failed (__i, __u, __f, __l, __g);
+ return &CONST_CAST_TREE (__u)->exp.operands[__i];
+}
+
+inline tree *
+tree_operand_check_code (tree __t, enum tree_code __code, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != __code)
+ tree_check_failed (__t, __f, __l, __g, __code, 0);
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))
+ tree_operand_check_failed (__i, __t, __f, __l, __g);
+ return &__t->exp.operands[__i];
+}
+
+inline const_tree *
+tree_operand_check (const_tree __t, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ const_tree __u = EXPR_CHECK (__t);
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__u))
+ tree_operand_check_failed (__i, __u, __f, __l, __g);
+ return CONST_CAST (const_tree *, &__u->exp.operands[__i]);
+}
+
+inline const_tree *
+tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
+ const char *__f, int __l, const char *__g)
+{
+ if (TREE_CODE (__t) != __code)
+ tree_check_failed (__t, __f, __l, __g, __code, 0);
+ if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))
+ tree_operand_check_failed (__i, __t, __f, __l, __g);
+ return CONST_CAST (const_tree *, &__t->exp.operands[__i]);
+}
+
+#endif
+
+/* True iff an identifier matches a C string. */
+
+inline bool
+id_equal (const_tree id, const char *str)
+{
+ return !strcmp (IDENTIFIER_POINTER (id), str);
+}
+
+inline bool
+id_equal (const char *str, const_tree id)
+{
+ return id_equal (id, str);
+}
+
+/* Return the number of elements in the VECTOR_TYPE given by NODE. */
+
+#if 0 // sdcpp
+inline poly_uint64
+TYPE_VECTOR_SUBPARTS (const_tree node)
+{
+ STATIC_ASSERT (NUM_POLY_INT_COEFFS <= 2);
+ unsigned int precision = VECTOR_TYPE_CHECK (node)->type_common.precision;
+ if (NUM_POLY_INT_COEFFS == 2)
+ {
+ /* See the corresponding code in SET_TYPE_VECTOR_SUBPARTS for a
+ description of the encoding. */
+ poly_uint64 res = 0;
+ res.coeffs[0] = HOST_WIDE_INT_1U << (precision & 0xff);
+ if (precision & 0x100)
+ res.coeffs[1] = HOST_WIDE_INT_1U << (precision & 0xff);
+ return res;
+ }
+ else
+ return HOST_WIDE_INT_1U << precision;
+}
+#endif // sdcpp
+
+/* Set the number of elements in VECTOR_TYPE NODE to SUBPARTS, which must
+ satisfy valid_vector_subparts_p. */
+
+#if 0 // sdcpp
+inline void
+SET_TYPE_VECTOR_SUBPARTS (tree node, poly_uint64 subparts)
+{
+ STATIC_ASSERT (NUM_POLY_INT_COEFFS <= 2);
+ unsigned HOST_WIDE_INT coeff0 = subparts.coeffs[0];
+ int index = exact_log2 (coeff0);
+ gcc_assert (index >= 0);
+ if (NUM_POLY_INT_COEFFS == 2)
+ {
+ /* We have two coefficients that are each in the range 1 << [0, 63],
+ so supporting all combinations would require 6 bits per coefficient
+ and 12 bits in total. Since the precision field is only 10 bits
+ in size, we need to be more restrictive than that.
+
+ At present, coeff[1] is always either 0 (meaning that the number
+ of units is constant) or equal to coeff[0] (meaning that the number
+ of units is N + X * N for some target-dependent zero-based runtime
+ parameter X). We can therefore encode coeff[1] in a single bit.
+
+ The most compact encoding would be to use mask 0x3f for coeff[0]
+ and 0x40 for coeff[1], leaving 0x380 unused. It's possible to
+ get slightly more efficient code on some hosts if we instead
+ treat the shift amount as an independent byte, so here we use
+ 0xff for coeff[0] and 0x100 for coeff[1]. */
+ unsigned HOST_WIDE_INT coeff1 = subparts.coeffs[1];
+ gcc_assert (coeff1 == 0 || coeff1 == coeff0);
+ VECTOR_TYPE_CHECK (node)->type_common.precision
+ = index + (coeff1 != 0 ? 0x100 : 0);
+ }
+ else
+ VECTOR_TYPE_CHECK (node)->type_common.precision = index;
+}
+
+/* Return true if we can construct vector types with the given number
+ of subparts. */
+
+static inline bool
+valid_vector_subparts_p (poly_uint64 subparts)
+{
+ unsigned HOST_WIDE_INT coeff0 = subparts.coeffs[0];
+ if (!pow2p_hwi (coeff0))
+ return false;
+ if (NUM_POLY_INT_COEFFS == 2)
+ {
+ unsigned HOST_WIDE_INT coeff1 = subparts.coeffs[1];
+ if (coeff1 != 0 && coeff1 != coeff0)
+ return false;
+ }
+ return true;
+}
+#endif // sdcpp
+
+/* Return the built-in function that DECL represents, given that it is known
+ to be a FUNCTION_DECL with built-in class BUILT_IN_NORMAL. */
+inline built_in_function
+DECL_FUNCTION_CODE (const_tree decl)
+{
+ const tree_function_decl &fndecl = FUNCTION_DECL_CHECK (decl)->function_decl;
+ gcc_checking_assert (fndecl.built_in_class == BUILT_IN_NORMAL);
+ return (built_in_function) fndecl.function_code;
+}
+
+/* Return the target-specific built-in function that DECL represents,
+ given that it is known to be a FUNCTION_DECL with built-in class
+ BUILT_IN_MD. */
+inline int
+DECL_MD_FUNCTION_CODE (const_tree decl)
+{
+ const tree_function_decl &fndecl = FUNCTION_DECL_CHECK (decl)->function_decl;
+ gcc_checking_assert (fndecl.built_in_class == BUILT_IN_MD);
+ return fndecl.function_code;
+}
+
+/* Return the frontend-specific built-in function that DECL represents,
+ given that it is known to be a FUNCTION_DECL with built-in class
+ BUILT_IN_FRONTEND. */
+inline int
+DECL_FE_FUNCTION_CODE (const_tree decl)
+{
+ const tree_function_decl &fndecl = FUNCTION_DECL_CHECK (decl)->function_decl;
+ gcc_checking_assert (fndecl.built_in_class == BUILT_IN_FRONTEND);
+ return fndecl.function_code;
+}
+
+/* Record that FUNCTION_DECL DECL represents built-in function FCODE of
+ class FCLASS. */
+inline void
+set_decl_built_in_function (tree decl, built_in_class fclass,
+ unsigned int fcode)
+{
+ tree_function_decl &fndecl = FUNCTION_DECL_CHECK (decl)->function_decl;
+ fndecl.built_in_class = fclass;
+ fndecl.function_code = fcode;
+}
+
+/* Record that FUNCTION_DECL NEWDECL represents the same built-in function
+ as OLDDECL (or none, if OLDDECL doesn't represent a built-in function). */
+inline void
+copy_decl_built_in_function (tree newdecl, const_tree olddecl)
+{
+ tree_function_decl &newfndecl = FUNCTION_DECL_CHECK (newdecl)->function_decl;
+ const tree_function_decl &oldfndecl
+ = FUNCTION_DECL_CHECK (olddecl)->function_decl;
+ newfndecl.built_in_class = oldfndecl.built_in_class;
+ newfndecl.function_code = oldfndecl.function_code;
+}
+
+/* In NON_LVALUE_EXPR and VIEW_CONVERT_EXPR, set when this node is merely a
+ wrapper added to express a location_t on behalf of the node's child
+ (e.g. by maybe_wrap_with_location). */
+
+#define EXPR_LOCATION_WRAPPER_P(NODE) \
+ (TREE_CHECK2(NODE, NON_LVALUE_EXPR, VIEW_CONVERT_EXPR)->base.public_flag)
+
+/* Test if EXP is merely a wrapper node, added to express a location_t
+ on behalf of the node's child (e.g. by maybe_wrap_with_location). */
+
+inline bool
+location_wrapper_p (const_tree exp)
+{
+ /* A wrapper node has code NON_LVALUE_EXPR or VIEW_CONVERT_EXPR, and
+ the flag EXPR_LOCATION_WRAPPER_P is set.
+ It normally has the same type as its operand, but it can have a
+ different one if the type of the operand has changed (e.g. when
+ merging duplicate decls).
+
+ NON_LVALUE_EXPR is used for wrapping constants, apart from STRING_CST.
+ VIEW_CONVERT_EXPR is used for wrapping non-constants and STRING_CST. */
+ if ((TREE_CODE (exp) == NON_LVALUE_EXPR
+ || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
+ && EXPR_LOCATION_WRAPPER_P (exp))
+ return true;
+ return false;
+}
+
+/* Implementation of STRIP_ANY_LOCATION_WRAPPER. */
+
+inline tree
+tree_strip_any_location_wrapper (tree exp)
+{
+ if (location_wrapper_p (exp))
+ return TREE_OPERAND (exp, 0);
+ else
+ return exp;
+}
+
+#define error_mark_node global_trees[TI_ERROR_MARK]
+
+#define intQI_type_node global_trees[TI_INTQI_TYPE]
+#define intHI_type_node global_trees[TI_INTHI_TYPE]
+#define intSI_type_node global_trees[TI_INTSI_TYPE]
+#define intDI_type_node global_trees[TI_INTDI_TYPE]
+#define intTI_type_node global_trees[TI_INTTI_TYPE]
+
+#define unsigned_intQI_type_node global_trees[TI_UINTQI_TYPE]
+#define unsigned_intHI_type_node global_trees[TI_UINTHI_TYPE]
+#define unsigned_intSI_type_node global_trees[TI_UINTSI_TYPE]
+#define unsigned_intDI_type_node global_trees[TI_UINTDI_TYPE]
+#define unsigned_intTI_type_node global_trees[TI_UINTTI_TYPE]
+
+#define atomicQI_type_node global_trees[TI_ATOMICQI_TYPE]
+#define atomicHI_type_node global_trees[TI_ATOMICHI_TYPE]
+#define atomicSI_type_node global_trees[TI_ATOMICSI_TYPE]
+#define atomicDI_type_node global_trees[TI_ATOMICDI_TYPE]
+#define atomicTI_type_node global_trees[TI_ATOMICTI_TYPE]
+
+#define uint16_type_node global_trees[TI_UINT16_TYPE]
+#define uint32_type_node global_trees[TI_UINT32_TYPE]
+#define uint64_type_node global_trees[TI_UINT64_TYPE]
+#define uint128_type_node global_trees[TI_UINT128_TYPE]
+
+#define void_node global_trees[TI_VOID]
+
+#define integer_zero_node global_trees[TI_INTEGER_ZERO]
+#define integer_one_node global_trees[TI_INTEGER_ONE]
+#define integer_three_node global_trees[TI_INTEGER_THREE]
+#define integer_minus_one_node global_trees[TI_INTEGER_MINUS_ONE]
+#define size_zero_node global_trees[TI_SIZE_ZERO]
+#define size_one_node global_trees[TI_SIZE_ONE]
+#define bitsize_zero_node global_trees[TI_BITSIZE_ZERO]
+#define bitsize_one_node global_trees[TI_BITSIZE_ONE]
+#define bitsize_unit_node global_trees[TI_BITSIZE_UNIT]
+
+/* Base access nodes. */
+#define access_public_node global_trees[TI_PUBLIC]
+#define access_protected_node global_trees[TI_PROTECTED]
+#define access_private_node global_trees[TI_PRIVATE]
+
+#define null_pointer_node global_trees[TI_NULL_POINTER]
+
+#define float_type_node global_trees[TI_FLOAT_TYPE]
+#define double_type_node global_trees[TI_DOUBLE_TYPE]
+#define long_double_type_node global_trees[TI_LONG_DOUBLE_TYPE]
+
+/* Nodes for particular _FloatN and _FloatNx types in sequence. */
+#define FLOATN_TYPE_NODE(IDX) global_trees[TI_FLOATN_TYPE_FIRST + (IDX)]
+#define FLOATN_NX_TYPE_NODE(IDX) global_trees[TI_FLOATN_NX_TYPE_FIRST + (IDX)]
+#define FLOATNX_TYPE_NODE(IDX) global_trees[TI_FLOATNX_TYPE_FIRST + (IDX)]
+
+/* Names for individual types (code should normally iterate over all
+ such types; these are only for back-end use, or in contexts such as
+ *.def where iteration is not possible). */
+#define float16_type_node global_trees[TI_FLOAT16_TYPE]
+#define float32_type_node global_trees[TI_FLOAT32_TYPE]
+#define float64_type_node global_trees[TI_FLOAT64_TYPE]
+#define float128_type_node global_trees[TI_FLOAT128_TYPE]
+#define float32x_type_node global_trees[TI_FLOAT32X_TYPE]
+#define float64x_type_node global_trees[TI_FLOAT64X_TYPE]
+#define float128x_type_node global_trees[TI_FLOAT128X_TYPE]
+
+#define float_ptr_type_node global_trees[TI_FLOAT_PTR_TYPE]
+#define double_ptr_type_node global_trees[TI_DOUBLE_PTR_TYPE]
+#define long_double_ptr_type_node global_trees[TI_LONG_DOUBLE_PTR_TYPE]
+#define integer_ptr_type_node global_trees[TI_INTEGER_PTR_TYPE]
+
+#define complex_integer_type_node global_trees[TI_COMPLEX_INTEGER_TYPE]
+#define complex_float_type_node global_trees[TI_COMPLEX_FLOAT_TYPE]
+#define complex_double_type_node global_trees[TI_COMPLEX_DOUBLE_TYPE]
+#define complex_long_double_type_node global_trees[TI_COMPLEX_LONG_DOUBLE_TYPE]
+
+#define COMPLEX_FLOATN_NX_TYPE_NODE(IDX) global_trees[TI_COMPLEX_FLOATN_NX_TYPE_FIRST + (IDX)]
+
+#define void_type_node global_trees[TI_VOID_TYPE]
+/* The C type `void *'. */
+#define ptr_type_node global_trees[TI_PTR_TYPE]
+/* The C type `const void *'. */
+#define const_ptr_type_node global_trees[TI_CONST_PTR_TYPE]
+/* The C type `size_t'. */
+#define size_type_node global_trees[TI_SIZE_TYPE]
+#define pid_type_node global_trees[TI_PID_TYPE]
+#define ptrdiff_type_node global_trees[TI_PTRDIFF_TYPE]
+#define va_list_type_node global_trees[TI_VA_LIST_TYPE]
+#define va_list_gpr_counter_field global_trees[TI_VA_LIST_GPR_COUNTER_FIELD]
+#define va_list_fpr_counter_field global_trees[TI_VA_LIST_FPR_COUNTER_FIELD]
+/* The C type `FILE *'. */
+#define fileptr_type_node global_trees[TI_FILEPTR_TYPE]
+/* The C type `const struct tm *'. */
+#define const_tm_ptr_type_node global_trees[TI_CONST_TM_PTR_TYPE]
+/* The C type `fenv_t *'. */
+#define fenv_t_ptr_type_node global_trees[TI_FENV_T_PTR_TYPE]
+#define const_fenv_t_ptr_type_node global_trees[TI_CONST_FENV_T_PTR_TYPE]
+/* The C type `fexcept_t *'. */
+#define fexcept_t_ptr_type_node global_trees[TI_FEXCEPT_T_PTR_TYPE]
+#define const_fexcept_t_ptr_type_node global_trees[TI_CONST_FEXCEPT_T_PTR_TYPE]
+#define pointer_sized_int_node global_trees[TI_POINTER_SIZED_TYPE]
+
+#define boolean_type_node global_trees[TI_BOOLEAN_TYPE]
+#define boolean_false_node global_trees[TI_BOOLEAN_FALSE]
+#define boolean_true_node global_trees[TI_BOOLEAN_TRUE]
+
+/* The decimal floating point types. */
+#define dfloat32_type_node global_trees[TI_DFLOAT32_TYPE]
+#define dfloat64_type_node global_trees[TI_DFLOAT64_TYPE]
+#define dfloat128_type_node global_trees[TI_DFLOAT128_TYPE]
+
+/* The fixed-point types. */
+#define sat_short_fract_type_node global_trees[TI_SAT_SFRACT_TYPE]
+#define sat_fract_type_node global_trees[TI_SAT_FRACT_TYPE]
+#define sat_long_fract_type_node global_trees[TI_SAT_LFRACT_TYPE]
+#define sat_long_long_fract_type_node global_trees[TI_SAT_LLFRACT_TYPE]
+#define sat_unsigned_short_fract_type_node \
+ global_trees[TI_SAT_USFRACT_TYPE]
+#define sat_unsigned_fract_type_node global_trees[TI_SAT_UFRACT_TYPE]
+#define sat_unsigned_long_fract_type_node \
+ global_trees[TI_SAT_ULFRACT_TYPE]
+#define sat_unsigned_long_long_fract_type_node \
+ global_trees[TI_SAT_ULLFRACT_TYPE]
+#define short_fract_type_node global_trees[TI_SFRACT_TYPE]
+#define fract_type_node global_trees[TI_FRACT_TYPE]
+#define long_fract_type_node global_trees[TI_LFRACT_TYPE]
+#define long_long_fract_type_node global_trees[TI_LLFRACT_TYPE]
+#define unsigned_short_fract_type_node global_trees[TI_USFRACT_TYPE]
+#define unsigned_fract_type_node global_trees[TI_UFRACT_TYPE]
+#define unsigned_long_fract_type_node global_trees[TI_ULFRACT_TYPE]
+#define unsigned_long_long_fract_type_node \
+ global_trees[TI_ULLFRACT_TYPE]
+#define sat_short_accum_type_node global_trees[TI_SAT_SACCUM_TYPE]
+#define sat_accum_type_node global_trees[TI_SAT_ACCUM_TYPE]
+#define sat_long_accum_type_node global_trees[TI_SAT_LACCUM_TYPE]
+#define sat_long_long_accum_type_node global_trees[TI_SAT_LLACCUM_TYPE]
+#define sat_unsigned_short_accum_type_node \
+ global_trees[TI_SAT_USACCUM_TYPE]
+#define sat_unsigned_accum_type_node global_trees[TI_SAT_UACCUM_TYPE]
+#define sat_unsigned_long_accum_type_node \
+ global_trees[TI_SAT_ULACCUM_TYPE]
+#define sat_unsigned_long_long_accum_type_node \
+ global_trees[TI_SAT_ULLACCUM_TYPE]
+#define short_accum_type_node global_trees[TI_SACCUM_TYPE]
+#define accum_type_node global_trees[TI_ACCUM_TYPE]
+#define long_accum_type_node global_trees[TI_LACCUM_TYPE]
+#define long_long_accum_type_node global_trees[TI_LLACCUM_TYPE]
+#define unsigned_short_accum_type_node global_trees[TI_USACCUM_TYPE]
+#define unsigned_accum_type_node global_trees[TI_UACCUM_TYPE]
+#define unsigned_long_accum_type_node global_trees[TI_ULACCUM_TYPE]
+#define unsigned_long_long_accum_type_node \
+ global_trees[TI_ULLACCUM_TYPE]
+#define qq_type_node global_trees[TI_QQ_TYPE]
+#define hq_type_node global_trees[TI_HQ_TYPE]
+#define sq_type_node global_trees[TI_SQ_TYPE]
+#define dq_type_node global_trees[TI_DQ_TYPE]
+#define tq_type_node global_trees[TI_TQ_TYPE]
+#define uqq_type_node global_trees[TI_UQQ_TYPE]
+#define uhq_type_node global_trees[TI_UHQ_TYPE]
+#define usq_type_node global_trees[TI_USQ_TYPE]
+#define udq_type_node global_trees[TI_UDQ_TYPE]
+#define utq_type_node global_trees[TI_UTQ_TYPE]
+#define sat_qq_type_node global_trees[TI_SAT_QQ_TYPE]
+#define sat_hq_type_node global_trees[TI_SAT_HQ_TYPE]
+#define sat_sq_type_node global_trees[TI_SAT_SQ_TYPE]
+#define sat_dq_type_node global_trees[TI_SAT_DQ_TYPE]
+#define sat_tq_type_node global_trees[TI_SAT_TQ_TYPE]
+#define sat_uqq_type_node global_trees[TI_SAT_UQQ_TYPE]
+#define sat_uhq_type_node global_trees[TI_SAT_UHQ_TYPE]
+#define sat_usq_type_node global_trees[TI_SAT_USQ_TYPE]
+#define sat_udq_type_node global_trees[TI_SAT_UDQ_TYPE]
+#define sat_utq_type_node global_trees[TI_SAT_UTQ_TYPE]
+#define ha_type_node global_trees[TI_HA_TYPE]
+#define sa_type_node global_trees[TI_SA_TYPE]
+#define da_type_node global_trees[TI_DA_TYPE]
+#define ta_type_node global_trees[TI_TA_TYPE]
+#define uha_type_node global_trees[TI_UHA_TYPE]
+#define usa_type_node global_trees[TI_USA_TYPE]
+#define uda_type_node global_trees[TI_UDA_TYPE]
+#define uta_type_node global_trees[TI_UTA_TYPE]
+#define sat_ha_type_node global_trees[TI_SAT_HA_TYPE]
+#define sat_sa_type_node global_trees[TI_SAT_SA_TYPE]
+#define sat_da_type_node global_trees[TI_SAT_DA_TYPE]
+#define sat_ta_type_node global_trees[TI_SAT_TA_TYPE]
+#define sat_uha_type_node global_trees[TI_SAT_UHA_TYPE]
+#define sat_usa_type_node global_trees[TI_SAT_USA_TYPE]
+#define sat_uda_type_node global_trees[TI_SAT_UDA_TYPE]
+#define sat_uta_type_node global_trees[TI_SAT_UTA_TYPE]
+
+/* The node that should be placed at the end of a parameter list to
+ indicate that the function does not take a variable number of
+ arguments. The TREE_VALUE will be void_type_node and there will be
+ no TREE_CHAIN. Language-independent code should not assume
+ anything else about this node. */
+#define void_list_node global_trees[TI_VOID_LIST_NODE]
+
+#define main_identifier_node global_trees[TI_MAIN_IDENTIFIER]
+#define MAIN_NAME_P(NODE) \
+ (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node)
+
+/* Optimization options (OPTIMIZATION_NODE) to use for default and current
+ functions. */
+#define optimization_default_node global_trees[TI_OPTIMIZATION_DEFAULT]
+#define optimization_current_node global_trees[TI_OPTIMIZATION_CURRENT]
+
+/* Default/current target options (TARGET_OPTION_NODE). */
+#define target_option_default_node global_trees[TI_TARGET_OPTION_DEFAULT]
+#define target_option_current_node global_trees[TI_TARGET_OPTION_CURRENT]
+
+/* Default tree list option(), optimize() pragmas to be linked into the
+ attribute list. */
+#define current_target_pragma global_trees[TI_CURRENT_TARGET_PRAGMA]
+#define current_optimize_pragma global_trees[TI_CURRENT_OPTIMIZE_PRAGMA]
+
+/* SCEV analyzer global shared trees. */
+#define chrec_not_analyzed_yet NULL_TREE
+#define chrec_dont_know global_trees[TI_CHREC_DONT_KNOW]
+#define chrec_known global_trees[TI_CHREC_KNOWN]
+
+#define char_type_node integer_types[itk_char]
+#define signed_char_type_node integer_types[itk_signed_char]
+#define unsigned_char_type_node integer_types[itk_unsigned_char]
+#define short_integer_type_node integer_types[itk_short]
+#define short_unsigned_type_node integer_types[itk_unsigned_short]
+#define integer_type_node integer_types[itk_int]
+#define unsigned_type_node integer_types[itk_unsigned_int]
+#define long_integer_type_node integer_types[itk_long]
+#define long_unsigned_type_node integer_types[itk_unsigned_long]
+#define long_long_integer_type_node integer_types[itk_long_long]
+#define long_long_unsigned_type_node integer_types[itk_unsigned_long_long]
+
+/* True if T is an erroneous expression. */
+
+inline bool
+error_operand_p (const_tree t)
+{
+ fprintf(stderr, "incomplete %s %d\n", __func__, __LINE__);
+ return false;
+
+// sdcpp return (t == error_mark_node
+// sdcpp || (t && TREE_TYPE (t) == error_mark_node));
+}
+
+/* Return the number of elements encoded directly in a VECTOR_CST. */
+
+inline unsigned int
+vector_cst_encoded_nelts (const_tree t)
+{
+ return VECTOR_CST_NPATTERNS (t) * VECTOR_CST_NELTS_PER_PATTERN (t);
+}
+
+extern tree decl_assembler_name (tree);
+extern void overwrite_decl_assembler_name (tree decl, tree name);
+extern tree decl_comdat_group (const_tree);
+extern tree decl_comdat_group_id (const_tree);
+extern const char *decl_section_name (const_tree);
+extern void set_decl_section_name (tree, const char *);
+extern void set_decl_section_name (tree, const_tree);
+extern enum tls_model decl_tls_model (const_tree);
+extern void set_decl_tls_model (tree, enum tls_model);
+
+/* Compute the number of bytes occupied by 'node'. This routine only
+ looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH. */
+
+extern size_t tree_size (const_tree);
+
+/* Compute the number of bytes occupied by a tree with code CODE.
+ This function cannot be used for TREE_VEC or INTEGER_CST nodes,
+ which are of variable length. */
+extern size_t tree_code_size (enum tree_code);
+
+/* Allocate and return a new UID from the DECL_UID namespace. */
+extern int allocate_decl_uid (void);
+
+/* Lowest level primitive for allocating a node.
+ The TREE_CODE is the only argument. Contents are initialized
+ to zero except for a few of the common fields. */
+
+extern tree make_node (enum tree_code CXX_MEM_STAT_INFO);
+
+/* Free tree node. */
+
+extern void free_node (tree);
+
+/* Make a copy of a node, with all the same contents. */
+
+extern tree copy_node (tree CXX_MEM_STAT_INFO);
+
+/* Make a copy of a chain of TREE_LIST nodes. */
+
+extern tree copy_list (tree);
+
+/* Make a CASE_LABEL_EXPR. */
+
+extern tree build_case_label (tree, tree, tree);
+
+/* Make a BINFO. */
+extern tree make_tree_binfo (unsigned CXX_MEM_STAT_INFO);
+
+/* Make an INTEGER_CST. */
+
+extern tree make_int_cst (int, int CXX_MEM_STAT_INFO);
+
+/* Make a TREE_VEC. */
+
+extern tree make_tree_vec (int CXX_MEM_STAT_INFO);
+
+/* Grow a TREE_VEC. */
+
+extern tree grow_tree_vec (tree v, int CXX_MEM_STAT_INFO);
+
+/* Construct various types of nodes. */
+
+extern tree build_nt (enum tree_code, ...);
+extern tree build_nt_call_vec (tree, vec<tree, va_gc> *);
+
+extern tree build0 (enum tree_code, tree CXX_MEM_STAT_INFO);
+extern tree build1 (enum tree_code, tree, tree CXX_MEM_STAT_INFO);
+extern tree build2 (enum tree_code, tree, tree, tree CXX_MEM_STAT_INFO);
+extern tree build3 (enum tree_code, tree, tree, tree, tree CXX_MEM_STAT_INFO);
+extern tree build4 (enum tree_code, tree, tree, tree, tree,
+ tree CXX_MEM_STAT_INFO);
+extern tree build5 (enum tree_code, tree, tree, tree, tree, tree,
+ tree CXX_MEM_STAT_INFO);
+
+/* _loc versions of build[1-5]. */
+
+static inline tree
+build1_loc (location_t loc, enum tree_code code, tree type,
+ tree arg1 CXX_MEM_STAT_INFO)
+{
+ tree t = build1 (code, type, arg1 PASS_MEM_STAT);
+ if (CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
+ return t;
+}
+
+static inline tree
+build2_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1 CXX_MEM_STAT_INFO)
+{
+ tree t = build2 (code, type, arg0, arg1 PASS_MEM_STAT);
+ if (CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
+ return t;
+}
+
+static inline tree
+build3_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1, tree arg2 CXX_MEM_STAT_INFO)
+{
+ tree t = build3 (code, type, arg0, arg1, arg2 PASS_MEM_STAT);
+ if (CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
+ return t;
+}
+
+static inline tree
+build4_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1, tree arg2, tree arg3 CXX_MEM_STAT_INFO)
+{
+ tree t = build4 (code, type, arg0, arg1, arg2, arg3 PASS_MEM_STAT);
+ if (CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
+ return t;
+}
+
+static inline tree
+build5_loc (location_t loc, enum tree_code code, tree type, tree arg0,
+ tree arg1, tree arg2, tree arg3, tree arg4 CXX_MEM_STAT_INFO)
+{
+ tree t = build5 (code, type, arg0, arg1, arg2, arg3,
+ arg4 PASS_MEM_STAT);
+ if (CAN_HAVE_LOCATION_P (t))
+ SET_EXPR_LOCATION (t, loc);
+ return t;
+}
+
+/* Constructs double_int from tree CST. */
+
+extern tree double_int_to_tree (tree, double_int);
+
+#if 0 // sdcpp
+extern tree wide_int_to_tree (tree type, const poly_wide_int_ref &cst);
+extern tree force_fit_type (tree, const poly_wide_int_ref &, int, bool);
+
+/* Create an INT_CST node with a CST value zero extended. */
+
+/* static inline */
+extern tree build_int_cst (tree, poly_int64);
+extern tree build_int_cstu (tree type, poly_uint64);
+extern tree build_int_cst_type (tree, poly_int64);
+#endif // sdcpp
+extern tree make_vector (unsigned, unsigned CXX_MEM_STAT_INFO);
+extern tree build_vector_from_ctor (tree, const vec<constructor_elt, va_gc> *);
+extern tree build_vector_from_val (tree, tree);
+extern tree build_uniform_cst (tree, tree);
+extern tree build_vec_series (tree, tree, tree);
+// sdcpp extern tree build_index_vector (tree, poly_uint64, poly_uint64);
+extern tree build_vector_a_then_b (tree, unsigned int, tree, tree);
+extern void recompute_constructor_flags (tree);
+extern void verify_constructor_flags (tree);
+extern tree build_constructor (tree, vec<constructor_elt, va_gc> * CXX_MEM_STAT_INFO);
+extern tree build_constructor_single (tree, tree, tree);
+extern tree build_constructor_from_list (tree, tree);
+extern tree build_constructor_from_vec (tree, const vec<tree, va_gc> *);
+extern tree build_constructor_va (tree, int, ...);
+extern tree build_clobber (tree, enum clobber_kind = CLOBBER_UNDEF);
+extern tree build_real_from_int_cst (tree, const_tree);
+extern tree build_real_from_wide (tree, const wide_int_ref &, signop);
+extern tree build_complex (tree, tree, tree);
+extern tree build_complex_inf (tree, bool);
+extern tree build_each_one_cst (tree);
+extern tree build_one_cst (tree);
+extern tree build_minus_one_cst (tree);
+extern tree build_all_ones_cst (tree);
+extern tree build_zero_cst (tree);
+extern tree build_string (unsigned, const char * = NULL);
+// sdcpp extern tree build_poly_int_cst (tree, const poly_wide_int_ref &);
+#endif // sdcpp
+extern tree build_tree_list (tree, tree CXX_MEM_STAT_INFO);
+#if 0 // sdcpp
+extern tree build_tree_list_vec (const vec<tree, va_gc> * CXX_MEM_STAT_INFO);
+extern tree build_decl (location_t, enum tree_code,
+ tree, tree CXX_MEM_STAT_INFO);
+extern tree build_debug_expr_decl (tree type);
+extern tree build_fn_decl (const char *, tree);
+extern tree build_translation_unit_decl (tree);
+extern tree build_block (tree, tree, tree, tree);
+extern tree build_empty_stmt (location_t);
+extern tree build_omp_clause (location_t, enum omp_clause_code);
+
+extern tree build_vl_exp (enum tree_code, int CXX_MEM_STAT_INFO);
+
+extern tree build_call_nary (tree, tree, int, ...);
+extern tree build_call_valist (tree, tree, int, va_list);
+#define build_call_array(T1,T2,N,T3)\
+ build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T3)
+extern tree build_call_array_loc (location_t, tree, tree, int, const tree *);
+extern tree build_call_vec (tree, tree, const vec<tree, va_gc> *);
+extern tree build_call_expr_loc_array (location_t, tree, int, tree *);
+extern tree build_call_expr_loc_vec (location_t, tree, vec<tree, va_gc> *);
+extern tree build_call_expr_loc (location_t, tree, int, ...);
+extern tree build_call_expr (tree, int, ...);
+extern tree build_call_expr_internal_loc (location_t, enum internal_fn,
+ tree, int, ...);
+extern tree build_call_expr_internal_loc_array (location_t, enum internal_fn,
+ tree, int, const tree *);
+extern tree maybe_build_call_expr_loc (location_t, combined_fn, tree,
+ int, ...);
+extern tree build_alloca_call_expr (tree, unsigned int, HOST_WIDE_INT);
+extern tree build_string_literal (unsigned, const char * = NULL,
+ tree = char_type_node,
+ unsigned HOST_WIDE_INT = HOST_WIDE_INT_M1U);
+
+/* Construct various nodes representing data types. */
+
+extern tree signed_or_unsigned_type_for (int, tree);
+extern tree signed_type_for (tree);
+extern tree unsigned_type_for (tree);
+extern bool is_truth_type_for (tree, tree);
+extern tree truth_type_for (tree);
+extern tree build_pointer_type_for_mode (tree, machine_mode, bool);
+extern tree build_pointer_type (tree);
+extern tree build_reference_type_for_mode (tree, machine_mode, bool);
+extern tree build_reference_type (tree);
+extern tree build_vector_type_for_mode (tree, machine_mode);
+// sdcpp extern tree build_vector_type (tree, poly_int64);
+// sdcpp extern tree build_truth_vector_type_for_mode (poly_uint64, machine_mode);
+// sdcpp extern tree build_opaque_vector_type (tree, poly_int64);
+extern tree build_index_type (tree);
+extern tree build_array_type_1 (tree, tree, bool, bool, bool);
+extern tree build_array_type (tree, tree, bool = false);
+extern tree build_nonshared_array_type (tree, tree);
+// sdcpp extern tree build_array_type_nelts (tree, poly_uint64);
+extern tree build_function_type (tree, tree);
+extern tree build_function_type_list (tree, ...);
+extern tree build_varargs_function_type_list (tree, ...);
+extern tree build_function_type_array (tree, int, tree *);
+extern tree build_varargs_function_type_array (tree, int, tree *);
+#define build_function_type_vec(RET, V) \
+ build_function_type_array (RET, vec_safe_length (V), vec_safe_address (V))
+#define build_varargs_function_type_vec(RET, V) \
+ build_varargs_function_type_array (RET, vec_safe_length (V), \
+ vec_safe_address (V))
+extern tree build_method_type_directly (tree, tree, tree);
+extern tree build_method_type (tree, tree);
+extern tree build_offset_type (tree, tree);
+extern tree build_complex_type (tree, bool named = false);
+extern tree array_type_nelts (const_tree);
+
+extern tree value_member (tree, tree);
+extern tree purpose_member (const_tree, tree);
+extern bool vec_member (const_tree, vec<tree, va_gc> *);
+extern tree chain_index (int, tree);
+
+/* Arguments may be null. */
+extern int tree_int_cst_equal (const_tree, const_tree);
+
+/* The following predicates are safe to call with a null argument. */
+extern bool tree_fits_shwi_p (const_tree) ATTRIBUTE_PURE;
+extern bool tree_fits_poly_int64_p (const_tree) ATTRIBUTE_PURE;
+extern bool tree_fits_uhwi_p (const_tree) ATTRIBUTE_PURE;
+extern bool tree_fits_poly_uint64_p (const_tree) ATTRIBUTE_PURE;
+
+extern HOST_WIDE_INT tree_to_shwi (const_tree)
+ ATTRIBUTE_NONNULL (1) ATTRIBUTE_PURE;
+// sdcpp extern poly_int64 tree_to_poly_int64 (const_tree)
+// sdcpp ATTRIBUTE_NONNULL (1) ATTRIBUTE_PURE;
+extern unsigned HOST_WIDE_INT tree_to_uhwi (const_tree)
+ ATTRIBUTE_NONNULL (1) ATTRIBUTE_PURE;
+// sdcpp extern poly_uint64 tree_to_poly_uint64 (const_tree)
+// sdcpp ATTRIBUTE_NONNULL (1) ATTRIBUTE_PURE;
+#if !defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 4003)
+extern inline __attribute__ ((__gnu_inline__)) HOST_WIDE_INT
+tree_to_shwi (const_tree t)
+{
+ gcc_assert (tree_fits_shwi_p (t));
+ return TREE_INT_CST_LOW (t);
+}
+
+extern inline __attribute__ ((__gnu_inline__)) unsigned HOST_WIDE_INT
+tree_to_uhwi (const_tree t)
+{
+ gcc_assert (tree_fits_uhwi_p (t));
+ return TREE_INT_CST_LOW (t);
+}
+#if NUM_POLY_INT_COEFFS == 1
+extern inline __attribute__ ((__gnu_inline__)) poly_int64
+tree_to_poly_int64 (const_tree t)
+{
+ gcc_assert (tree_fits_poly_int64_p (t));
+ return TREE_INT_CST_LOW (t);
+}
+
+extern inline __attribute__ ((__gnu_inline__)) poly_uint64
+tree_to_poly_uint64 (const_tree t)
+{
+ gcc_assert (tree_fits_poly_uint64_p (t));
+ return TREE_INT_CST_LOW (t);
+}
+#endif
+#endif
+extern int tree_int_cst_sgn (const_tree);
+extern int tree_int_cst_sign_bit (const_tree);
+extern unsigned int tree_int_cst_min_precision (tree, signop);
+extern tree strip_array_types (tree);
+extern tree excess_precision_type (tree);
+
+/* Desription of the reason why the argument of valid_constant_size_p
+ is not a valid size. */
+enum cst_size_error {
+ cst_size_ok,
+ cst_size_not_constant,
+ cst_size_negative,
+ cst_size_too_big,
+ cst_size_overflow
+};
+
+extern bool valid_constant_size_p (const_tree, cst_size_error * = NULL);
+extern tree max_object_size ();
+
+/* Return true if T holds a value that can be represented as a poly_int64
+ without loss of precision. Store the value in *VALUE if so. */
+
+#if 0 // sdcpp
+inline bool
+poly_int_tree_p (const_tree t, poly_int64_pod *value)
+{
+ if (tree_fits_poly_int64_p (t))
+ {
+ *value = tree_to_poly_int64 (t);
+ return true;
+ }
+ return false;
+}
+
+/* Return true if T holds a value that can be represented as a poly_uint64
+ without loss of precision. Store the value in *VALUE if so. */
+
+inline bool
+poly_int_tree_p (const_tree t, poly_uint64_pod *value)
+{
+ if (tree_fits_poly_uint64_p (t))
+ {
+ *value = tree_to_poly_uint64 (t);
+ return true;
+ }
+ return false;
+}
+#endif // sdcpp
+
+/* From expmed.cc. Since rtl.h is included after tree.h, we can't
+ put the prototype here. Rtl.h does declare the prototype if
+ tree.h had been included. */
+
+extern tree make_tree (tree, rtx);
+
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+extern bool check_lang_type (const_tree cand, const_tree base);
+
+/* Returns true iff unqualified CAND and BASE are equivalent. */
+
+extern bool check_base_type (const_tree cand, const_tree base);
+
+/* Check whether CAND is suitable to be returned from get_qualified_type
+ (BASE, TYPE_QUALS). */
+
+extern bool check_qualified_type (const_tree, const_tree, int);
+
+/* Return a version of the TYPE, qualified as indicated by the
+ TYPE_QUALS, if one exists. If no qualified version exists yet,
+ return NULL_TREE. */
+
+extern tree get_qualified_type (tree, int);
+
+/* Like get_qualified_type, but creates the type if it does not
+ exist. This function never returns NULL_TREE. */
+
+extern tree build_qualified_type (tree, int CXX_MEM_STAT_INFO);
+
+/* Create a variant of type T with alignment ALIGN. */
+
+extern tree build_aligned_type (tree, unsigned int);
+
+/* Like build_qualified_type, but only deals with the `const' and
+ `volatile' qualifiers. This interface is retained for backwards
+ compatibility with the various front-ends; new code should use
+ build_qualified_type instead. */
+
+#define build_type_variant(TYPE, CONST_P, VOLATILE_P) \
+ build_qualified_type ((TYPE), \
+ ((CONST_P) ? TYPE_QUAL_CONST : 0) \
+ | ((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
+
+/* Make a copy of a type node. */
+
+extern tree build_distinct_type_copy (tree CXX_MEM_STAT_INFO);
+extern tree build_variant_type_copy (tree CXX_MEM_STAT_INFO);
+
+/* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
+ return a canonicalized ..._TYPE node, so that duplicates are not made.
+ How the hash code is computed is up to the caller, as long as any two
+ callers that could hash identical-looking type nodes agree. */
+
+extern hashval_t type_hash_canon_hash (tree);
+extern tree type_hash_canon (unsigned int, tree);
+
+extern tree convert (tree, tree);
+extern tree size_in_bytes_loc (location_t, const_tree);
+inline tree
+size_in_bytes (const_tree t)
+{
+ return size_in_bytes_loc (input_location, t);
+}
+
+extern HOST_WIDE_INT int_size_in_bytes (const_tree);
+extern HOST_WIDE_INT max_int_size_in_bytes (const_tree);
+extern tree bit_position (const_tree);
+extern tree byte_position (const_tree);
+extern HOST_WIDE_INT int_byte_position (const_tree);
+
+/* Type for sizes of data-type. */
+
+#define sizetype sizetype_tab[(int) stk_sizetype]
+#define bitsizetype sizetype_tab[(int) stk_bitsizetype]
+#define ssizetype sizetype_tab[(int) stk_ssizetype]
+#define sbitsizetype sizetype_tab[(int) stk_sbitsizetype]
+#define size_int(L) size_int_kind (L, stk_sizetype)
+#define ssize_int(L) size_int_kind (L, stk_ssizetype)
+#define bitsize_int(L) size_int_kind (L, stk_bitsizetype)
+#define sbitsize_int(L) size_int_kind (L, stk_sbitsizetype)
+
+/* Log2 of BITS_PER_UNIT. */
+
+#if BITS_PER_UNIT == 8
+#define LOG2_BITS_PER_UNIT 3
+#elif BITS_PER_UNIT == 16
+#define LOG2_BITS_PER_UNIT 4
+#else
+#error Unknown BITS_PER_UNIT
+#endif
+
+/* Concatenate two lists (chains of TREE_LIST nodes) X and Y
+ by making the last node in X point to Y.
+ Returns X, except if X is 0 returns Y. */
+
+extern tree chainon (tree, tree);
+
+/* Make a new TREE_LIST node from specified PURPOSE, VALUE and CHAIN. */
+
+extern tree tree_cons (tree, tree, tree CXX_MEM_STAT_INFO);
+
+/* Return the last tree node in a chain. */
+
+extern tree tree_last (tree);
+
+/* Reverse the order of elements in a chain, and return the new head. */
+
+extern tree nreverse (tree);
+
+/* Returns the length of a chain of nodes
+ (number of chain pointers to follow before reaching a null pointer). */
+
+extern int list_length (const_tree);
+
+/* Returns the first/last FIELD_DECL in a RECORD_TYPE. */
+
+extern tree first_field (const_tree) ATTRIBUTE_NONNULL (1);
+extern tree last_field (const_tree) ATTRIBUTE_NONNULL (1);
+
+/* Given an initializer INIT, return TRUE if INIT is zero or some
+ aggregate of zeros. Otherwise return FALSE. If NONZERO is not
+ null, set *NONZERO if and only if INIT is known not to be all
+ zeros. The combination of return value of false and *NONZERO
+ false implies that INIT may but need not be all zeros. Other
+ combinations indicate definitive answers. */
+
+extern bool initializer_zerop (const_tree, bool * = NULL);
+extern bool initializer_each_zero_or_onep (const_tree);
+
+extern tree vector_cst_elt (const_tree, unsigned int);
+
+/* Given a vector VEC, return its first element if all elements are
+ the same. Otherwise return NULL_TREE. */
+
+extern tree uniform_vector_p (const_tree);
+
+/* If the argument is INTEGER_CST, return it. If the argument is vector
+ with all elements the same INTEGER_CST, return that INTEGER_CST. Otherwise
+ return NULL_TREE. */
+
+extern tree uniform_integer_cst_p (tree);
+
+extern int single_nonzero_element (const_tree);
+
+/* Given a CONSTRUCTOR CTOR, return the element values as a vector. */
+
+extern vec<tree, va_gc> *ctor_to_vec (tree);
+
+/* zerop (tree x) is nonzero if X is a constant of value 0. */
+
+extern bool zerop (const_tree);
+
+/* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */
+
+extern bool integer_zerop (const_tree);
+
+/* integer_onep (tree x) is nonzero if X is an integer constant of value 1. */
+
+extern bool integer_onep (const_tree);
+
+/* integer_onep (tree x) is nonzero if X is an integer constant of value 1, or
+ a vector or complex where each part is 1. */
+
+extern bool integer_each_onep (const_tree);
+
+/* integer_all_onesp (tree x) is nonzero if X is an integer constant
+ all of whose significant bits are 1. */
+
+extern bool integer_all_onesp (const_tree);
+
+/* integer_minus_onep (tree x) is nonzero if X is an integer constant of
+ value -1. */
+
+extern bool integer_minus_onep (const_tree);
+
+/* integer_pow2p (tree x) is nonzero is X is an integer constant with
+ exactly one bit 1. */
+
+extern bool integer_pow2p (const_tree);
+
+/* Checks to see if T is a constant or a constant vector and if each element E
+ adheres to ~E + 1 == pow2 then return ~E otherwise NULL_TREE. */
+
+extern tree bitmask_inv_cst_vector_p (tree);
+
+/* integer_nonzerop (tree x) is nonzero if X is an integer constant
+ with a nonzero value. */
+
+extern bool integer_nonzerop (const_tree);
+
+/* integer_truep (tree x) is nonzero if X is an integer constant of value 1 or
+ a vector where each element is an integer constant of value -1. */
+
+extern bool integer_truep (const_tree);
+
+extern bool cst_and_fits_in_hwi (const_tree);
+extern tree num_ending_zeros (const_tree);
+
+/* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
+ value 0. */
+
+extern bool fixed_zerop (const_tree);
+
+/* staticp (tree x) is nonzero if X is a reference to data allocated
+ at a fixed address in memory. Returns the outermost data. */
+
+extern tree staticp (tree);
+
+/* save_expr (EXP) returns an expression equivalent to EXP
+ but it can be used multiple times within context CTX
+ and only evaluate EXP once. */
+
+extern tree save_expr (tree);
+
+/* Return true if T is function-invariant. */
+
+extern bool tree_invariant_p (tree);
+
+/* Look inside EXPR into any simple arithmetic operations. Return the
+ outermost non-arithmetic or non-invariant node. */
+
+extern tree skip_simple_arithmetic (tree);
+
+/* Look inside EXPR into simple arithmetic operations involving constants.
+ Return the outermost non-arithmetic or non-constant node. */
+
+extern tree skip_simple_constant_arithmetic (tree);
+
+/* Return which tree structure is used by T. */
+
+enum tree_node_structure_enum tree_node_structure (const_tree);
+
+/* Return true if EXP contains a PLACEHOLDER_EXPR, i.e. if it represents a
+ size or offset that depends on a field within a record. */
+
+extern bool contains_placeholder_p (const_tree);
+
+/* This macro calls the above function but short-circuits the common
+ case of a constant to save time. Also check for null. */
+
+#define CONTAINS_PLACEHOLDER_P(EXP) \
+ ((EXP) != 0 && ! TREE_CONSTANT (EXP) && contains_placeholder_p (EXP))
+
+/* Return true if any part of the structure of TYPE involves a PLACEHOLDER_EXPR
+ directly. This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and
+ field positions. */
+
+extern bool type_contains_placeholder_p (tree);
+
+/* Given a tree EXP, find all occurrences of references to fields
+ in a PLACEHOLDER_EXPR and place them in vector REFS without
+ duplicates. Also record VAR_DECLs and CONST_DECLs. Note that
+ we assume here that EXP contains only arithmetic expressions
+ or CALL_EXPRs with PLACEHOLDER_EXPRs occurring only in their
+ argument list. */
+
+extern void find_placeholder_in_expr (tree, vec<tree> *);
+
+/* This macro calls the above function but short-circuits the common
+ case of a constant to save time and also checks for NULL. */
+
+#define FIND_PLACEHOLDER_IN_EXPR(EXP, V) \
+do { \
+ if((EXP) && !TREE_CONSTANT (EXP)) \
+ find_placeholder_in_expr (EXP, V); \
+} while (0)
+
+/* Given a tree EXP, a FIELD_DECL F, and a replacement value R,
+ return a tree with all occurrences of references to F in a
+ PLACEHOLDER_EXPR replaced by R. Also handle VAR_DECLs and
+ CONST_DECLs. Note that we assume here that EXP contains only
+ arithmetic expressions or CALL_EXPRs with PLACEHOLDER_EXPRs
+ occurring only in their argument list. */
+
+extern tree substitute_in_expr (tree, tree, tree);
+
+/* This macro calls the above function but short-circuits the common
+ case of a constant to save time and also checks for NULL. */
+
+#define SUBSTITUTE_IN_EXPR(EXP, F, R) \
+ ((EXP) == 0 || TREE_CONSTANT (EXP) ? (EXP) : substitute_in_expr (EXP, F, R))
+
+/* Similar, but look for a PLACEHOLDER_EXPR in EXP and find a replacement
+ for it within OBJ, a tree that is an object or a chain of references. */
+
+extern tree substitute_placeholder_in_expr (tree, tree);
+
+/* This macro calls the above function but short-circuits the common
+ case of a constant to save time and also checks for NULL. */
+
+#define SUBSTITUTE_PLACEHOLDER_IN_EXPR(EXP, OBJ) \
+ ((EXP) == 0 || TREE_CONSTANT (EXP) ? (EXP) \
+ : substitute_placeholder_in_expr (EXP, OBJ))
+
+
+/* stabilize_reference (EXP) returns a reference equivalent to EXP
+ but it can be used multiple times
+ and only evaluate the subexpressions once. */
+
+extern tree stabilize_reference (tree);
+
+/* Return EXP, stripped of any conversions to wider types
+ in such a way that the result of converting to type FOR_TYPE
+ is the same as if EXP were converted to FOR_TYPE.
+ If FOR_TYPE is 0, it signifies EXP's type. */
+
+extern tree get_unwidened (tree, tree);
+
+/* Return OP or a simpler expression for a narrower value
+ which can be sign-extended or zero-extended to give back OP.
+ Store in *UNSIGNEDP_PTR either 1 if the value should be zero-extended
+ or 0 if the value should be sign-extended. */
+
+extern tree get_narrower (tree, int *);
+
+/* Return true if T is an expression that get_inner_reference handles. */
+
+static inline bool
+handled_component_p (const_tree t)
+{
+ switch (TREE_CODE (t))
+ {
+ case COMPONENT_REF:
+ case BIT_FIELD_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case VIEW_CONVERT_EXPR:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Return true T is a component with reverse storage order. */
+
+static inline bool
+reverse_storage_order_for_component_p (tree t)
+{
+ /* The storage order only applies to scalar components. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+ || POINTER_TYPE_P (TREE_TYPE (t))
+ || VECTOR_TYPE_P (TREE_TYPE (t)))
+ return false;
+
+ if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ switch (TREE_CODE (t))
+ {
+ case ARRAY_REF:
+ case COMPONENT_REF:
+ /* ??? Fortran can take COMPONENT_REF of a VOID_TYPE. */
+ /* ??? UBSan can take COMPONENT_REF of a REFERENCE_TYPE. */
+ return AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (t, 0)));
+
+ case BIT_FIELD_REF:
+ case MEM_REF:
+ return REF_REVERSE_STORAGE_ORDER (t);
+
+ case ARRAY_RANGE_REF:
+ case VIEW_CONVERT_EXPR:
+ default:
+ return false;
+ }
+}
+
+/* Return true if T is a storage order barrier, i.e. a VIEW_CONVERT_EXPR
+ that can modify the storage order of objects. Note that, even if the
+ TYPE_REVERSE_STORAGE_ORDER flag is set on both the inner type and the
+ outer type, a VIEW_CONVERT_EXPR can modify the storage order because
+ it can change the partition of the aggregate object into scalars. */
+
+static inline bool
+storage_order_barrier_p (const_tree t)
+{
+ if (TREE_CODE (t) != VIEW_CONVERT_EXPR)
+ return false;
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t)))
+ return true;
+
+ tree op = TREE_OPERAND (t, 0);
+
+ if (AGGREGATE_TYPE_P (TREE_TYPE (op))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (op)))
+ return true;
+
+ return false;
+}
+
+/* Given a DECL or TYPE, return the scope in which it was declared, or
+ NUL_TREE if there is no containing scope. */
+
+extern tree get_containing_scope (const_tree);
+
+/* Returns the ultimate TRANSLATION_UNIT_DECL context of DECL or NULL. */
+
+extern const_tree get_ultimate_context (const_tree);
+
+/* Return the FUNCTION_DECL which provides this _DECL with its context,
+ or zero if none. */
+extern tree decl_function_context (const_tree);
+
+/* Return the RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE which provides
+ this _DECL with its context, or zero if none. */
+extern tree decl_type_context (const_tree);
+
+/* Return true if EXPR is the real constant zero. */
+extern bool real_zerop (const_tree);
+
+/* Initialize the iterator I with arguments from function FNDECL */
+
+static inline void
+function_args_iter_init (function_args_iterator *i, const_tree fntype)
+{
+ i->next = TYPE_ARG_TYPES (fntype);
+}
+
+/* Return a pointer that holds the next argument if there are more arguments to
+ handle, otherwise return NULL. */
+
+static inline tree *
+function_args_iter_cond_ptr (function_args_iterator *i)
+{
+ return (i->next) ? &TREE_VALUE (i->next) : NULL;
+}
+
+/* Return the next argument if there are more arguments to handle, otherwise
+ return NULL. */
+
+static inline tree
+function_args_iter_cond (function_args_iterator *i)
+{
+ return (i->next) ? TREE_VALUE (i->next) : NULL_TREE;
+}
+
+/* Advance to the next argument. */
+static inline void
+function_args_iter_next (function_args_iterator *i)
+{
+ gcc_assert (i->next != NULL_TREE);
+ i->next = TREE_CHAIN (i->next);
+}
+
+/* Returns true if a BLOCK has a source location.
+ BLOCK_SOURCE_LOCATION is set only to inlined function entry points,
+ so the function returns true for all but the innermost and outermost
+ blocks into which an expression has been inlined. */
+
+static inline bool
+inlined_function_outer_scope_p (const_tree block)
+{
+ return LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block)) != UNKNOWN_LOCATION;
+}
+
+/* Loop over all function arguments of FNTYPE. In each iteration, PTR is set
+ to point to the next tree element. ITER is an instance of
+ function_args_iterator used to iterate the arguments. */
+#define FOREACH_FUNCTION_ARGS_PTR(FNTYPE, PTR, ITER) \
+ for (function_args_iter_init (&(ITER), (FNTYPE)); \
+ (PTR = function_args_iter_cond_ptr (&(ITER))) != NULL; \
+ function_args_iter_next (&(ITER)))
+
+/* Loop over all function arguments of FNTYPE. In each iteration, TREE is set
+ to the next tree element. ITER is an instance of function_args_iterator
+ used to iterate the arguments. */
+#define FOREACH_FUNCTION_ARGS(FNTYPE, TREE, ITER) \
+ for (function_args_iter_init (&(ITER), (FNTYPE)); \
+ (TREE = function_args_iter_cond (&(ITER))) != NULL_TREE; \
+ function_args_iter_next (&(ITER)))
+
+/* In tree.cc */
+extern unsigned crc32_unsigned_n (unsigned, unsigned, unsigned);
+extern unsigned crc32_string (unsigned, const char *);
+inline unsigned
+crc32_unsigned (unsigned chksum, unsigned value)
+{
+ return crc32_unsigned_n (chksum, value, 4);
+}
+inline unsigned
+crc32_byte (unsigned chksum, char byte)
+{
+ return crc32_unsigned_n (chksum, byte, 1);
+}
+extern void clean_symbol_name (char *);
+extern tree get_file_function_name (const char *);
+extern tree get_callee_fndecl (const_tree);
+extern combined_fn get_call_combined_fn (const_tree);
+extern int type_num_arguments (const_tree);
+extern tree type_argument_type (const_tree, unsigned) ATTRIBUTE_NONNULL (1);
+extern bool associative_tree_code (enum tree_code);
+extern bool commutative_tree_code (enum tree_code);
+extern bool commutative_ternary_tree_code (enum tree_code);
+extern bool operation_can_overflow (enum tree_code);
+extern bool operation_no_trapping_overflow (tree, enum tree_code);
+extern tree upper_bound_in_type (tree, tree);
+extern tree lower_bound_in_type (tree, tree);
+extern int operand_equal_for_phi_arg_p (const_tree, const_tree);
+extern tree create_artificial_label (location_t);
+extern const char *get_name (tree);
+extern bool stdarg_p (const_tree);
+extern bool prototype_p (const_tree);
+extern bool is_typedef_decl (const_tree x);
+extern bool typedef_variant_p (const_tree);
+extern bool auto_var_p (const_tree);
+extern bool auto_var_in_fn_p (const_tree, const_tree);
+extern tree build_low_bits_mask (tree, unsigned);
+extern bool tree_nop_conversion_p (const_tree, const_tree);
+extern tree tree_strip_nop_conversions (tree);
+extern tree tree_strip_sign_nop_conversions (tree);
+extern const_tree strip_invariant_refs (const_tree);
+extern tree lhd_gcc_personality (void);
+extern void assign_assembler_name_if_needed (tree);
+extern bool warn_deprecated_use (tree, tree);
+extern void error_unavailable_use (tree, tree);
+extern tree cache_integer_cst (tree, bool might_duplicate = false);
+extern const char *combined_fn_name (combined_fn);
+
+/* Compare and hash for any structure which begins with a canonical
+ pointer. Assumes all pointers are interchangeable, which is sort
+ of already assumed by gcc elsewhere IIRC. */
+
+static inline int
+struct_ptr_eq (const void *a, const void *b)
+{
+ const void * const * x = (const void * const *) a;
+ const void * const * y = (const void * const *) b;
+ return *x == *y;
+}
+
+static inline hashval_t
+struct_ptr_hash (const void *a)
+{
+ const void * const * x = (const void * const *) a;
+ return (intptr_t)*x >> 4;
+}
+
+/* Return nonzero if CODE is a tree code that represents a truth value. */
+static inline bool
+truth_value_p (enum tree_code code)
+{
+ return (TREE_CODE_CLASS (code) == tcc_comparison
+ || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
+ || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
+ || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
+}
+
+/* Return whether TYPE is a type suitable for an offset for
+ a POINTER_PLUS_EXPR. */
+static inline bool
+ptrofftype_p (tree type)
+{
+ return (INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) == TYPE_PRECISION (sizetype)
+ && TYPE_UNSIGNED (type) == TYPE_UNSIGNED (sizetype));
+}
+
+/* Return true if the argument is a complete type or an array
+ of unknown bound (whose type is incomplete but) whose elements
+ have complete type. */
+static inline bool
+complete_or_array_type_p (const_tree type)
+{
+ return COMPLETE_TYPE_P (type)
+ || (TREE_CODE (type) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (type)));
+}
+
+/* Return true if the value of T could be represented as a poly_widest_int. */
+
+#if 0 // sdcpp
+inline bool
+poly_int_tree_p (const_tree t)
+{
+ return (TREE_CODE (t) == INTEGER_CST || POLY_INT_CST_P (t));
+}
+
+/* Return the bit size of BIT_FIELD_REF T, in cases where it is known
+ to be a poly_uint64. (This is always true at the gimple level.) */
+
+inline poly_uint64
+bit_field_size (const_tree t)
+{
+ return tree_to_poly_uint64 (TREE_OPERAND (t, 1));
+}
+
+/* Return the starting bit offset of BIT_FIELD_REF T, in cases where it is
+ known to be a poly_uint64. (This is always true at the gimple level.) */
+
+inline poly_uint64
+bit_field_offset (const_tree t)
+{
+ return tree_to_poly_uint64 (TREE_OPERAND (t, 2));
+}
+#endif // sdcpp
+
+extern tree strip_float_extensions (tree);
+extern bool really_constant_p (const_tree);
+// sdcpp extern bool ptrdiff_tree_p (const_tree, poly_int64_pod *);
+extern bool decl_address_invariant_p (const_tree);
+extern bool decl_address_ip_invariant_p (const_tree);
+extern bool int_fits_type_p (const_tree, const_tree)
+ ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2) ATTRIBUTE_PURE;
+#ifndef GENERATOR_FILE
+extern void get_type_static_bounds (const_tree, mpz_t, mpz_t);
+#endif
+extern bool variably_modified_type_p (tree, tree);
+extern int tree_log2 (const_tree);
+extern int tree_floor_log2 (const_tree);
+extern unsigned int tree_ctz (const_tree);
+extern int simple_cst_equal (const_tree, const_tree);
+
+namespace inchash
+{
+
+extern void add_expr (const_tree, hash &, unsigned int = 0);
+
+}
+
+/* Compat version until all callers are converted. Return hash for
+ TREE with SEED. */
+static inline hashval_t iterative_hash_expr(const_tree tree, hashval_t seed)
+{
+ inchash::hash hstate (seed);
+ inchash::add_expr (tree, hstate);
+ return hstate.end ();
+}
+
+extern int compare_tree_int (const_tree, unsigned HOST_WIDE_INT);
+extern bool type_list_equal (const_tree, const_tree);
+extern bool chain_member (const_tree, const_tree);
+extern void dump_tree_statistics (void);
+extern void recompute_tree_invariant_for_addr_expr (tree);
+extern bool needs_to_live_in_memory (const_tree);
+extern tree reconstruct_complex_type (tree, tree);
+extern bool real_onep (const_tree);
+extern bool real_minus_onep (const_tree);
+extern void init_ttree (void);
+extern void build_common_tree_nodes (bool);
+extern void build_common_builtin_nodes (void);
+extern void tree_cc_finalize (void);
+extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
+extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT);
+extern tree build_range_type (tree, tree, tree);
+extern tree build_nonshared_range_type (tree, tree, tree);
+extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);
+extern HOST_WIDE_INT int_cst_value (const_tree);
+extern tree tree_block (tree);
+extern void tree_set_block (tree, tree);
+extern location_t *block_nonartificial_location (tree);
+extern location_t tree_nonartificial_location (tree);
+extern location_t tree_inlined_location (tree, bool = true);
+extern tree block_ultimate_origin (const_tree);
+// sdcpp extern tree get_binfo_at_offset (tree, poly_int64, tree);
+extern bool virtual_method_call_p (const_tree, bool = false);
+extern tree obj_type_ref_class (const_tree ref, bool = false);
+extern bool types_same_for_odr (const_tree type1, const_tree type2);
+extern bool contains_bitfld_component_ref_p (const_tree);
+extern bool block_may_fallthru (const_tree);
+extern void using_eh_for_cleanups (void);
+extern bool using_eh_for_cleanups_p (void);
+extern const char *get_tree_code_name (enum tree_code);
+extern void set_call_expr_flags (tree, int);
+extern tree walk_tree_1 (tree*, walk_tree_fn, void*, hash_set<tree>*,
+ walk_tree_lh);
+extern tree walk_tree_without_duplicates_1 (tree*, walk_tree_fn, void*,
+ walk_tree_lh);
+#define walk_tree(a,b,c,d) \
+ walk_tree_1 (a, b, c, d, NULL)
+#define walk_tree_without_duplicates(a,b,c) \
+ walk_tree_without_duplicates_1 (a, b, c, NULL)
+
+extern tree drop_tree_overflow (tree);
+
+/* Given a memory reference expression T, return its base address.
+ The base address of a memory reference expression is the main
+ object being referenced. */
+extern tree get_base_address (tree t);
+
+/* Return a tree of sizetype representing the size, in bytes, of the element
+ of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
+extern tree array_ref_element_size (tree);
+
+/* Return a typenode for the "standard" C type with a given name. */
+extern tree get_typenode_from_name (const char *);
+
+/* Return a tree representing the upper bound of the array mentioned in
+ EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
+extern tree array_ref_up_bound (tree);
+
+/* Return a tree representing the lower bound of the array mentioned in
+ EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
+extern tree array_ref_low_bound (tree);
+
+/* Returns true if REF is an array reference or a component reference
+ to an array at the end of a structure. If this is the case, the array
+ may be allocated larger than its upper bound implies. */
+extern bool array_at_struct_end_p (tree);
+
+/* Return a tree representing the offset, in bytes, of the field referenced
+ by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
+extern tree component_ref_field_offset (tree);
+
+/* Describes a "special" array member due to which component_ref_size
+ returns null. */
+enum struct special_array_member
+ {
+ none, /* Not a special array member. */
+ int_0, /* Interior array member with size zero. */
+ trail_0, /* Trailing array member with size zero. */
+ trail_1 /* Trailing array member with one element. */
+ };
+
+/* Return the size of the member referenced by the COMPONENT_REF, using
+ its initializer expression if necessary in order to determine the size
+ of an initialized flexible array member. The size might be zero for
+ an object with an uninitialized flexible array member or null if it
+ cannot be determined. */
+extern tree component_ref_size (tree, special_array_member * = NULL);
+
+extern int tree_map_base_eq (const void *, const void *);
+extern unsigned int tree_map_base_hash (const void *);
+extern int tree_map_base_marked_p (const void *);
+extern void DEBUG_FUNCTION verify_type (const_tree t);
+extern bool gimple_canonical_types_compatible_p (const_tree, const_tree,
+ bool trust_type_canonical = true);
+extern bool type_with_interoperable_signedness (const_tree);
+extern bitmap get_nonnull_args (const_tree);
+extern int get_range_pos_neg (tree);
+
+/* Return true for a valid pair of new and delete operators. */
+extern bool valid_new_delete_pair_p (tree, tree, bool * = NULL);
+
+/* Return simplified tree code of type that is used for canonical type
+ merging. */
+inline enum tree_code
+tree_code_for_canonical_type_merging (enum tree_code code)
+{
+ /* By C standard, each enumerated type shall be compatible with char,
+ a signed integer, or an unsigned integer. The choice of type is
+ implementation defined (in our case it depends on -fshort-enum).
+
+ For this reason we make no distinction between ENUMERAL_TYPE and INTEGER
+ type and compare only by their signedness and precision. */
+ if (code == ENUMERAL_TYPE)
+ return INTEGER_TYPE;
+ /* To allow inter-operability between languages having references and
+ C, we consider reference types and pointers alike. Note that this is
+ not strictly necessary for C-Fortran 2008 interoperability because
+ Fortran define C_PTR type that needs to be compatible with C pointers
+ and we handle this one as ptr_type_node. */
+ if (code == REFERENCE_TYPE)
+ return POINTER_TYPE;
+ return code;
+}
+
+/* Return ture if get_alias_set care about TYPE_CANONICAL of given type.
+ We don't define the types for pointers, arrays and vectors. The reason is
+ that pointers are handled specially: ptr_type_node accesses conflict with
+ accesses to all other pointers. This is done by alias.cc.
+ Because alias sets of arrays and vectors are the same as types of their
+ elements, we can't compute canonical type either. Otherwise we could go
+ form void *[10] to int *[10] (because they are equivalent for canonical type
+ machinery) and get wrong TBAA. */
+
+inline bool
+canonical_type_used_p (const_tree t)
+{
+ return !(POINTER_TYPE_P (t)
+ || TREE_CODE (t) == ARRAY_TYPE
+ || TREE_CODE (t) == VECTOR_TYPE);
+}
+
+/* Kinds of access to pass-by-reference arguments to functions. */
+enum access_mode
+{
+ access_none = 0,
+ access_read_only = 1,
+ access_write_only = 2,
+ access_read_write = access_read_only | access_write_only,
+ access_deferred = 4
+};
+
+#define tree_map_eq tree_map_base_eq
+extern unsigned int tree_map_hash (const void *);
+#define tree_map_marked_p tree_map_base_marked_p
+
+#define tree_decl_map_eq tree_map_base_eq
+extern unsigned int tree_decl_map_hash (const void *);
+#define tree_decl_map_marked_p tree_map_base_marked_p
+
+struct tree_decl_map_cache_hasher : ggc_cache_ptr_hash<tree_decl_map>
+{
+ static hashval_t hash (tree_decl_map *m) { return tree_decl_map_hash (m); }
+ static bool
+ equal (tree_decl_map *a, tree_decl_map *b)
+ {
+ return tree_decl_map_eq (a, b);
+ }
+
+ static int
+ keep_cache_entry (tree_decl_map *&m)
+ {
+ return ggc_marked_p (m->base.from);
+ }
+};
+
+#define tree_int_map_eq tree_map_base_eq
+#define tree_int_map_hash tree_map_base_hash
+#define tree_int_map_marked_p tree_map_base_marked_p
+
+#define tree_vec_map_eq tree_map_base_eq
+#define tree_vec_map_hash tree_decl_map_hash
+#define tree_vec_map_marked_p tree_map_base_marked_p
+
+struct tree_vec_map_cache_hasher : ggc_cache_ptr_hash<tree_vec_map>
+{
+ static hashval_t hash (tree_vec_map *m) { return DECL_UID (m->base.from); }
+
+ static bool
+ equal (tree_vec_map *a, tree_vec_map *b)
+ {
+ return a->base.from == b->base.from;
+ }
+
+ static int
+ keep_cache_entry (tree_vec_map *&m)
+ {
+ return ggc_marked_p (m->base.from);
+ }
+};
+
+/* Hasher for tree decls. Pointer equality is enough here, but the DECL_UID
+ is a better hash than the pointer value and gives a predictable traversal
+ order. Additionally it can be used across PCH save/restore. */
+struct tree_decl_hash : ggc_ptr_hash <tree_node>
+{
+ static inline hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_decl_hash::hash (tree t)
+{
+ return DECL_UID (t);
+}
+
+/* Similarly for types. Uses TYPE_UID as hash function. */
+struct tree_type_hash : ggc_ptr_hash <tree_node>
+{
+ static inline hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_type_hash::hash (tree t)
+{
+ return TYPE_UID (t);
+}
+
+/* Hash for SSA_NAMEs in the same function. Pointer equality is enough
+ here, but the SSA_NAME_VERSION is a better hash than the pointer
+ value and gives a predictable traversal order. */
+struct tree_ssa_name_hash : ggc_ptr_hash <tree_node>
+{
+ static inline hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_ssa_name_hash::hash (tree t)
+{
+ return SSA_NAME_VERSION (t);
+}
+
+/* Hasher for general trees, based on their TREE_HASH. */
+struct tree_hash : ggc_ptr_hash <tree_node>
+{
+ static hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_hash::hash (tree t)
+{
+ return TREE_HASH (t);
+}
+
+/* A hash_map of two trees for use with GTY((cache)). Garbage collection for
+ such a map will not mark keys, and will mark values if the key is already
+ marked. */
+struct tree_cache_traits
+ : simple_cache_map_traits<default_hash_traits<tree>, tree> { };
+typedef hash_map<tree,tree,tree_cache_traits> tree_cache_map;
+
+/* Similarly, but use DECL_UID as hash function rather than pointer hashing.
+ This is for hash_maps from decls to trees that need to work across PCH. */
+struct decl_tree_cache_traits
+ : simple_cache_map_traits<tree_decl_hash, tree> { };
+typedef hash_map<tree,tree,decl_tree_cache_traits> decl_tree_cache_map;
+
+/* Similarly, but use TYPE_UID as hash function rather than pointer hashing.
+ This is for hash_maps from types to trees that need to work across PCH. */
+struct type_tree_cache_traits
+ : simple_cache_map_traits<tree_type_hash, tree> { };
+typedef hash_map<tree,tree,type_tree_cache_traits> type_tree_cache_map;
+
+/* Similarly to decl_tree_cache_map, but without caching. */
+struct decl_tree_traits
+ : simple_hashmap_traits<tree_decl_hash, tree> { };
+typedef hash_map<tree,tree,decl_tree_traits> decl_tree_map;
+
+/* Initialize the abstract argument list iterator object ITER with the
+ arguments from CALL_EXPR node EXP. */
+static inline void
+init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
+{
+ iter->t = exp;
+ iter->n = call_expr_nargs (exp);
+ iter->i = 0;
+}
+
+static inline void
+init_const_call_expr_arg_iterator (const_tree exp, const_call_expr_arg_iterator *iter)
+{
+ iter->t = exp;
+ iter->n = call_expr_nargs (exp);
+ iter->i = 0;
+}
+
+/* Return the next argument from abstract argument list iterator object ITER,
+ and advance its state. Return NULL_TREE if there are no more arguments. */
+static inline tree
+next_call_expr_arg (call_expr_arg_iterator *iter)
+{
+ tree result;
+ if (iter->i >= iter->n)
+ return NULL_TREE;
+ result = CALL_EXPR_ARG (iter->t, iter->i);
+ iter->i++;
+ return result;
+}
+
+static inline const_tree
+next_const_call_expr_arg (const_call_expr_arg_iterator *iter)
+{
+ const_tree result;
+ if (iter->i >= iter->n)
+ return NULL_TREE;
+ result = CALL_EXPR_ARG (iter->t, iter->i);
+ iter->i++;
+ return result;
+}
+
+/* Initialize the abstract argument list iterator object ITER, then advance
+ past and return the first argument. Useful in for expressions, e.g.
+ for (arg = first_call_expr_arg (exp, &iter); arg;
+ arg = next_call_expr_arg (&iter)) */
+static inline tree
+first_call_expr_arg (tree exp, call_expr_arg_iterator *iter)
+{
+ init_call_expr_arg_iterator (exp, iter);
+ return next_call_expr_arg (iter);
+}
+
+static inline const_tree
+first_const_call_expr_arg (const_tree exp, const_call_expr_arg_iterator *iter)
+{
+ init_const_call_expr_arg_iterator (exp, iter);
+ return next_const_call_expr_arg (iter);
+}
+
+/* Test whether there are more arguments in abstract argument list iterator
+ ITER, without changing its state. */
+static inline bool
+more_call_expr_args_p (const call_expr_arg_iterator *iter)
+{
+ return (iter->i < iter->n);
+}
+
+/* Iterate through each argument ARG of CALL_EXPR CALL, using variable ITER
+ (of type call_expr_arg_iterator) to hold the iteration state. */
+#define FOR_EACH_CALL_EXPR_ARG(arg, iter, call) \
+ for ((arg) = first_call_expr_arg ((call), &(iter)); (arg); \
+ (arg) = next_call_expr_arg (&(iter)))
+
+#define FOR_EACH_CONST_CALL_EXPR_ARG(arg, iter, call) \
+ for ((arg) = first_const_call_expr_arg ((call), &(iter)); (arg); \
+ (arg) = next_const_call_expr_arg (&(iter)))
+
+/* Return true if tree node T is a language-specific node. */
+static inline bool
+is_lang_specific (const_tree t)
+{
+ return TREE_CODE (t) == LANG_TYPE || TREE_CODE (t) >= NUM_TREE_CODES;
+}
+
+/* Valid builtin number. */
+#define BUILTIN_VALID_P(FNCODE) \
+ (IN_RANGE ((int)FNCODE, ((int)BUILT_IN_NONE) + 1, ((int) END_BUILTINS) - 1))
+
+/* Obtain a pointer to the identifier string holding the asm name for
+ BUILTIN, a BUILT_IN code. This is handy if the target
+ mangles/overrides the function name that implements the
+ builtin. */
+#define BUILTIN_ASM_NAME_PTR(BUILTIN) \
+ (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (builtin_decl_explicit (BUILTIN))))
+
+/* Return the tree node for an explicit standard builtin function or NULL. */
+static inline tree
+builtin_decl_explicit (enum built_in_function fncode)
+{
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+
+ return builtin_info[(size_t)fncode].decl;
+}
+
+/* Return the tree node for an implicit builtin function or NULL. */
+static inline tree
+builtin_decl_implicit (enum built_in_function fncode)
+{
+ size_t uns_fncode = (size_t)fncode;
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+
+ if (!builtin_info[uns_fncode].implicit_p)
+ return NULL_TREE;
+
+ return builtin_info[uns_fncode].decl;
+}
+
+/* Set explicit builtin function nodes and whether it is an implicit
+ function. */
+
+static inline void
+set_builtin_decl (enum built_in_function fncode, tree decl, bool implicit_p)
+{
+ size_t ufncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode)
+ && (decl != NULL_TREE || !implicit_p));
+
+ builtin_info[ufncode].decl = decl;
+ builtin_info[ufncode].implicit_p = implicit_p;
+ builtin_info[ufncode].declared_p = false;
+}
+
+/* Set the implicit flag for a builtin function. */
+
+static inline void
+set_builtin_decl_implicit_p (enum built_in_function fncode, bool implicit_p)
+{
+ size_t uns_fncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode)
+ && builtin_info[uns_fncode].decl != NULL_TREE);
+
+ builtin_info[uns_fncode].implicit_p = implicit_p;
+}
+
+/* Set the declared flag for a builtin function. */
+
+static inline void
+set_builtin_decl_declared_p (enum built_in_function fncode, bool declared_p)
+{
+ size_t uns_fncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode)
+ && builtin_info[uns_fncode].decl != NULL_TREE);
+
+ builtin_info[uns_fncode].declared_p = declared_p;
+}
+
+/* Return whether the standard builtin function can be used as an explicit
+ function. */
+
+static inline bool
+builtin_decl_explicit_p (enum built_in_function fncode)
+{
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+ return (builtin_info[(size_t)fncode].decl != NULL_TREE);
+}
+
+/* Return whether the standard builtin function can be used implicitly. */
+
+static inline bool
+builtin_decl_implicit_p (enum built_in_function fncode)
+{
+ size_t uns_fncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+ return (builtin_info[uns_fncode].decl != NULL_TREE
+ && builtin_info[uns_fncode].implicit_p);
+}
+
+/* Return whether the standard builtin function was declared. */
+
+static inline bool
+builtin_decl_declared_p (enum built_in_function fncode)
+{
+ size_t uns_fncode = (size_t)fncode;
+
+ gcc_checking_assert (BUILTIN_VALID_P (fncode));
+ return (builtin_info[uns_fncode].decl != NULL_TREE
+ && builtin_info[uns_fncode].declared_p);
+}
+
+/* Determine if the function identified by FNDECL is one that
+ makes sense to match by name, for those places where we detect
+ "magic" functions by name.
+
+ Return true if FNDECL has a name and is an extern fndecl at file scope.
+ FNDECL must be a non-NULL decl.
+
+ Avoid using this, as it's generally better to use attributes rather
+ than to check for functions by name. */
+
+static inline bool
+maybe_special_function_p (const_tree fndecl)
+{
+ tree name_decl = DECL_NAME (fndecl);
+ if (name_decl
+ /* Exclude functions not at the file scope, or not `extern',
+ since they are not the magic functions we would otherwise
+ think they are. */
+ && (DECL_CONTEXT (fndecl) == NULL_TREE
+ || TREE_CODE (DECL_CONTEXT (fndecl)) == TRANSLATION_UNIT_DECL)
+ && TREE_PUBLIC (fndecl))
+ return true;
+ return false;
+}
+
+/* Return true if T (assumed to be a DECL) is a global variable.
+ A variable is considered global if its storage is not automatic. */
+
+static inline bool
+is_global_var (const_tree t)
+{
+ return (TREE_STATIC (t) || DECL_EXTERNAL (t));
+}
+
+/* Return true if VAR may be aliased. A variable is considered as
+ maybe aliased if it has its address taken by the local TU
+ or possibly by another TU and might be modified through a pointer. */
+
+static inline bool
+may_be_aliased (const_tree var)
+{
+ return (TREE_CODE (var) != CONST_DECL
+ && (TREE_PUBLIC (var)
+ || DECL_EXTERNAL (var)
+ || TREE_ADDRESSABLE (var))
+ && !((TREE_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var))
+ && (TREE_READONLY (var)
+ || (TREE_CODE (var) == VAR_DECL
+ && DECL_NONALIASED (var)))));
+}
+
+#if 0 // sdcpp
+/* Return pointer to optimization flags of FNDECL. */
+static inline struct cl_optimization *
+opts_for_fn (const_tree fndecl)
+{
+ tree fn_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+ if (fn_opts == NULL_TREE)
+ fn_opts = optimization_default_node;
+ return TREE_OPTIMIZATION (fn_opts);
+}
+
+/* Return pointer to target flags of FNDECL. */
+static inline cl_target_option *
+target_opts_for_fn (const_tree fndecl)
+{
+ tree fn_opts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (fn_opts == NULL_TREE)
+ fn_opts = target_option_default_node;
+ return fn_opts == NULL_TREE ? NULL : TREE_TARGET_OPTION (fn_opts);
+}
+#endif // sdcpp
+
+/* opt flag for function FNDECL, e.g. opts_for_fn (fndecl, optimize) is
+ the optimization level of function fndecl. */
+#define opt_for_fn(fndecl, opt) (opts_for_fn (fndecl)->x_##opt)
+
+/* For anonymous aggregate types, we need some sort of name to
+ hold on to. In practice, this should not appear, but it should
+ not be harmful if it does. Identifiers returned will be
+ IDENTIFIER_ANON_P. */
+extern tree make_anon_name ();
+
+/* The tree and const_tree overload templates. */
+namespace wi
+{
+ class unextended_tree
+ {
+ private:
+ const_tree m_t;
+
+ public:
+ unextended_tree () {}
+ unextended_tree (const_tree t) : m_t (t) {}
+
+ unsigned int get_precision () const;
+ const HOST_WIDE_INT *get_val () const;
+ unsigned int get_len () const;
+ const_tree get_tree () const { return m_t; }
+ };
+
+ template <>
+ struct int_traits <unextended_tree>
+ {
+ static const enum precision_type precision_type = VAR_PRECISION;
+ static const bool host_dependent_precision = false;
+ static const bool is_sign_extended = false;
+ };
+
+ template <int N>
+ class extended_tree
+ {
+ private:
+ const_tree m_t;
+
+ public:
+ extended_tree () {}
+ extended_tree (const_tree);
+
+ unsigned int get_precision () const;
+ const HOST_WIDE_INT *get_val () const;
+ unsigned int get_len () const;
+ const_tree get_tree () const { return m_t; }
+ };
+
+ template <int N>
+ struct int_traits <extended_tree <N> >
+ {
+ static const enum precision_type precision_type = CONST_PRECISION;
+ static const bool host_dependent_precision = false;
+ static const bool is_sign_extended = true;
+ static const unsigned int precision = N;
+ };
+
+ typedef extended_tree <WIDE_INT_MAX_PRECISION> widest_extended_tree;
+ typedef extended_tree <ADDR_MAX_PRECISION> offset_extended_tree;
+
+ typedef const generic_wide_int <widest_extended_tree> tree_to_widest_ref;
+ typedef const generic_wide_int <offset_extended_tree> tree_to_offset_ref;
+ typedef const generic_wide_int<wide_int_ref_storage<false, false> >
+ tree_to_wide_ref;
+
+ tree_to_widest_ref to_widest (const_tree);
+ tree_to_offset_ref to_offset (const_tree);
+ tree_to_wide_ref to_wide (const_tree);
+ wide_int to_wide (const_tree, unsigned int);
+
+#if 0 // sdcpp
+ typedef const poly_int <NUM_POLY_INT_COEFFS,
+ generic_wide_int <widest_extended_tree> >
+ tree_to_poly_widest_ref;
+ typedef const poly_int <NUM_POLY_INT_COEFFS,
+ generic_wide_int <offset_extended_tree> >
+ tree_to_poly_offset_ref;
+ typedef const poly_int <NUM_POLY_INT_COEFFS,
+ generic_wide_int <unextended_tree> >
+ tree_to_poly_wide_ref;
+
+ tree_to_poly_widest_ref to_poly_widest (const_tree);
+ tree_to_poly_offset_ref to_poly_offset (const_tree);
+ tree_to_poly_wide_ref to_poly_wide (const_tree);
+#endif
+
+ template <int N>
+ struct ints_for <generic_wide_int <extended_tree <N> >, CONST_PRECISION>
+ {
+ typedef generic_wide_int <extended_tree <N> > extended;
+ static extended zero (const extended &);
+ };
+
+ template <>
+ struct ints_for <generic_wide_int <unextended_tree>, VAR_PRECISION>
+ {
+ typedef generic_wide_int <unextended_tree> unextended;
+ static unextended zero (const unextended &);
+ };
+}
+
+/* Used to convert a tree to a widest2_int like this:
+ widest2_int foo = widest2_int_cst (some_tree). */
+typedef generic_wide_int <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> >
+ widest2_int_cst;
+
+/* Refer to INTEGER_CST T as though it were a widest_int.
+
+ This function gives T's actual numerical value, influenced by the
+ signedness of its type. For example, a signed byte with just the
+ top bit set would be -128 while an unsigned byte with the same
+ bit pattern would be 128.
+
+ This is the right choice when operating on groups of INTEGER_CSTs
+ that might have different signedness or precision. It is also the
+ right choice in code that specifically needs an approximation of
+ infinite-precision arithmetic instead of normal modulo arithmetic.
+
+ The approximation of infinite precision is good enough for realistic
+ numbers of additions and subtractions of INTEGER_CSTs (where
+ "realistic" includes any number less than 1 << 31) but it cannot
+ represent the result of multiplying the two largest supported
+ INTEGER_CSTs. The overflow-checking form of wi::mul provides a way
+ of multiplying two arbitrary INTEGER_CSTs and checking that the
+ result is representable as a widest_int.
+
+ Note that any overflow checking done on these values is relative to
+ the range of widest_int rather than the range of a TREE_TYPE.
+
+ Calling this function should have no overhead in release builds,
+ so it is OK to call it several times for the same tree. If it is
+ useful for readability reasons to reduce the number of calls,
+ it is more efficient to use:
+
+ wi::tree_to_widest_ref wt = wi::to_widest (t);
+
+ instead of:
+
+ widest_int wt = wi::to_widest (t). */
+
+inline wi::tree_to_widest_ref
+wi::to_widest (const_tree t)
+{
+ return t;
+}
+
+/* Refer to INTEGER_CST T as though it were an offset_int.
+
+ This function is an optimisation of wi::to_widest for cases
+ in which T is known to be a bit or byte count in the range
+ (-(2 ^ (N + BITS_PER_UNIT)), 2 ^ (N + BITS_PER_UNIT)), where N is
+ the target's address size in bits.
+
+ This is the right choice when operating on bit or byte counts as
+ untyped numbers rather than M-bit values. The wi::to_widest comments
+ about addition, subtraction and multiplication apply here: sequences
+ of 1 << 31 additions and subtractions do not induce overflow, but
+ multiplying the largest sizes might. Again,
+
+ wi::tree_to_offset_ref wt = wi::to_offset (t);
+
+ is more efficient than:
+
+ offset_int wt = wi::to_offset (t). */
+
+inline wi::tree_to_offset_ref
+wi::to_offset (const_tree t)
+{
+ return t;
+}
+
+/* Refer to INTEGER_CST T as though it were a wide_int.
+
+ In contrast to the approximation of infinite-precision numbers given
+ by wi::to_widest and wi::to_offset, this function treats T as a
+ signless collection of N bits, where N is the precision of T's type.
+ As with machine registers, signedness is determined by the operation
+ rather than the operands; for example, there is a distinction between
+ signed and unsigned division.
+
+ This is the right choice when operating on values with the same type
+ using normal modulo arithmetic. The overflow-checking forms of things
+ like wi::add check whether the result can be represented in T's type.
+
+ Calling this function should have no overhead in release builds,
+ so it is OK to call it several times for the same tree. If it is
+ useful for readability reasons to reduce the number of calls,
+ it is more efficient to use:
+
+ wi::tree_to_wide_ref wt = wi::to_wide (t);
+
+ instead of:
+
+ wide_int wt = wi::to_wide (t). */
+
+inline wi::tree_to_wide_ref
+wi::to_wide (const_tree t)
+{
+ return wi::storage_ref (&TREE_INT_CST_ELT (t, 0), TREE_INT_CST_NUNITS (t),
+ TYPE_PRECISION (TREE_TYPE (t)));
+}
+
+/* Convert INTEGER_CST T to a wide_int of precision PREC, extending or
+ truncating as necessary. When extending, use sign extension if T's
+ type is signed and zero extension if T's type is unsigned. */
+
+inline wide_int
+wi::to_wide (const_tree t, unsigned int prec)
+{
+ return wide_int::from (wi::to_wide (t), prec, TYPE_SIGN (TREE_TYPE (t)));
+}
+
+template <int N>
+inline wi::extended_tree <N>::extended_tree (const_tree t)
+ : m_t (t)
+{
+ gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (t)) <= N);
+}
+
+template <int N>
+inline unsigned int
+wi::extended_tree <N>::get_precision () const
+{
+ return N;
+}
+
+template <int N>
+inline const HOST_WIDE_INT *
+wi::extended_tree <N>::get_val () const
+{
+ return &TREE_INT_CST_ELT (m_t, 0);
+}
+
+template <int N>
+inline unsigned int
+wi::extended_tree <N>::get_len () const
+{
+ if (N == ADDR_MAX_PRECISION)
+ return TREE_INT_CST_OFFSET_NUNITS (m_t);
+ else if (N >= WIDE_INT_MAX_PRECISION)
+ return TREE_INT_CST_EXT_NUNITS (m_t);
+ else
+ /* This class is designed to be used for specific output precisions
+ and needs to be as fast as possible, so there is no fallback for
+ other casees. */
+ gcc_unreachable ();
+}
+
+inline unsigned int
+wi::unextended_tree::get_precision () const
+{
+ return TYPE_PRECISION (TREE_TYPE (m_t));
+}
+
+inline const HOST_WIDE_INT *
+wi::unextended_tree::get_val () const
+{
+ return &TREE_INT_CST_ELT (m_t, 0);
+}
+
+inline unsigned int
+wi::unextended_tree::get_len () const
+{
+ return TREE_INT_CST_NUNITS (m_t);
+}
+
+/* Return the value of a POLY_INT_CST in its native precision. */
+
+#if 0 // sdcpp
+inline wi::tree_to_poly_wide_ref
+poly_int_cst_value (const_tree x)
+{
+ poly_int <NUM_POLY_INT_COEFFS, generic_wide_int <wi::unextended_tree> > res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = POLY_INT_CST_COEFF (x, i);
+ return res;
+}
+
+/* Access INTEGER_CST or POLY_INT_CST tree T as if it were a
+ poly_widest_int. See wi::to_widest for more details. */
+
+inline wi::tree_to_poly_widest_ref
+wi::to_poly_widest (const_tree t)
+{
+ if (POLY_INT_CST_P (t))
+ {
+ poly_int <NUM_POLY_INT_COEFFS,
+ generic_wide_int <widest_extended_tree> > res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = POLY_INT_CST_COEFF (t, i);
+ return res;
+ }
+ return t;
+}
+
+/* Access INTEGER_CST or POLY_INT_CST tree T as if it were a
+ poly_offset_int. See wi::to_offset for more details. */
+
+inline wi::tree_to_poly_offset_ref
+wi::to_poly_offset (const_tree t)
+{
+ if (POLY_INT_CST_P (t))
+ {
+ poly_int <NUM_POLY_INT_COEFFS,
+ generic_wide_int <offset_extended_tree> > res;
+ for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+ res.coeffs[i] = POLY_INT_CST_COEFF (t, i);
+ return res;
+ }
+ return t;
+}
+
+/* Access INTEGER_CST or POLY_INT_CST tree T as if it were a
+ poly_wide_int. See wi::to_wide for more details. */
+
+inline wi::tree_to_poly_wide_ref
+wi::to_poly_wide (const_tree t)
+{
+ if (POLY_INT_CST_P (t))
+ return poly_int_cst_value (t);
+ return t;
+}
+#endif // sdcpp
+
+template <int N>
+inline generic_wide_int <wi::extended_tree <N> >
+wi::ints_for <generic_wide_int <wi::extended_tree <N> >,
+ wi::CONST_PRECISION>::zero (const extended &x)
+{
+ return build_zero_cst (TREE_TYPE (x.get_tree ()));
+}
+
+inline generic_wide_int <wi::unextended_tree>
+wi::ints_for <generic_wide_int <wi::unextended_tree>,
+ wi::VAR_PRECISION>::zero (const unextended &x)
+{
+ return build_zero_cst (TREE_TYPE (x.get_tree ()));
+}
+
+namespace wi
+{
+ template <typename T>
+ bool fits_to_boolean_p (const T &x, const_tree);
+
+ template <typename T>
+ bool fits_to_tree_p (const T &x, const_tree);
+
+ wide_int min_value (const_tree);
+ wide_int max_value (const_tree);
+ wide_int from_mpz (const_tree, mpz_t, bool);
+}
+
+#if 0 // sdcpp
+template <typename T>
+bool
+wi::fits_to_boolean_p (const T &x, const_tree type)
+{
+ typedef typename poly_int_traits<T>::int_type int_type;
+ return (known_eq (x, int_type (0))
+ || known_eq (x, int_type (TYPE_UNSIGNED (type) ? 1 : -1)));
+}
+#endif
+
+template <typename T>
+bool
+wi::fits_to_tree_p (const T &x, const_tree type)
+{
+ /* Non-standard boolean types can have arbitrary precision but various
+ transformations assume that they can only take values 0 and +/-1. */
+ if (TREE_CODE (type) == BOOLEAN_TYPE)
+ return fits_to_boolean_p (x, type);
+
+ if (TYPE_UNSIGNED (type))
+ return known_eq (x, zext (x, TYPE_PRECISION (type)));
+ else
+ return known_eq (x, sext (x, TYPE_PRECISION (type)));
+}
+
+/* Produce the smallest number that is represented in TYPE. The precision
+ and sign are taken from TYPE. */
+inline wide_int
+wi::min_value (const_tree type)
+{
+ return min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+}
+
+/* Produce the largest number that is represented in TYPE. The precision
+ and sign are taken from TYPE. */
+inline wide_int
+wi::max_value (const_tree type)
+{
+ return max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+}
+
+/* Return true if INTEGER_CST T1 is less than INTEGER_CST T2,
+ extending both according to their respective TYPE_SIGNs. */
+
+inline bool
+tree_int_cst_lt (const_tree t1, const_tree t2)
+{
+ return wi::to_widest (t1) < wi::to_widest (t2);
+}
+
+/* Return true if INTEGER_CST T1 is less than or equal to INTEGER_CST T2,
+ extending both according to their respective TYPE_SIGNs. */
+
+inline bool
+tree_int_cst_le (const_tree t1, const_tree t2)
+{
+ return wi::to_widest (t1) <= wi::to_widest (t2);
+}
+
+/* Returns -1 if T1 < T2, 0 if T1 == T2, and 1 if T1 > T2. T1 and T2
+ are both INTEGER_CSTs and their values are extended according to their
+ respective TYPE_SIGNs. */
+
+inline int
+tree_int_cst_compare (const_tree t1, const_tree t2)
+{
+ return wi::cmps (wi::to_widest (t1), wi::to_widest (t2));
+}
+
+/* FIXME - These declarations belong in builtins.h, expr.h and emit-rtl.h,
+ but none of these files are allowed to be included from front ends.
+ They should be split in two. One suitable for the FEs, the other suitable
+ for the BE. */
+
+/* Assign the RTX to declaration. */
+extern void set_decl_rtl (tree, rtx);
+extern bool complete_ctor_at_level_p (const_tree, HOST_WIDE_INT, const_tree);
+
+/* Given an expression EXP that is a handled_component_p,
+ look for the ultimate containing object, which is returned and specify
+ the access position and size. */
+// sdcpp extern tree get_inner_reference (tree, poly_int64_pod *, poly_int64_pod *,
+// sdcpp tree *, machine_mode *, int *, int *, int *);
+
+extern tree build_personality_function (const char *);
+
+struct GTY(()) int_n_trees_t {
+ /* These parts are initialized at runtime */
+ tree signed_type;
+ tree unsigned_type;
+};
+
+/* This is also in machmode.h */
+// sdcpp extern bool int_n_enabled_p[NUM_INT_N_ENTS];
+// sdcpp extern GTY(()) struct int_n_trees_t int_n_trees[NUM_INT_N_ENTS];
+
+/* Like bit_position, but return as an integer. It must be representable in
+ that way (since it could be a signed value, we don't have the
+ option of returning -1 like int_size_in_byte can. */
+
+inline HOST_WIDE_INT
+int_bit_position (const_tree field)
+{
+ return ((wi::to_offset (DECL_FIELD_OFFSET (field)) << LOG2_BITS_PER_UNIT)
+ + wi::to_offset (DECL_FIELD_BIT_OFFSET (field))).to_shwi ();
+}
+
+/* Return true if it makes sense to consider alias set for a type T. */
+
+inline bool
+type_with_alias_set_p (const_tree t)
+{
+ /* Function and method types are never accessed as memory locations. */
+ if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE)
+ return false;
+
+ if (COMPLETE_TYPE_P (t))
+ return true;
+
+ /* Incomplete types cannot be accessed in general except for arrays
+ where we can fetch its element despite we have no array bounds. */
+ if (TREE_CODE (t) == ARRAY_TYPE && COMPLETE_TYPE_P (TREE_TYPE (t)))
+ return true;
+
+ return false;
+}
+
+extern location_t set_block (location_t loc, tree block);
+
+extern void gt_ggc_mx (tree &);
+extern void gt_pch_nx (tree &);
+extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
+
+extern bool nonnull_arg_p (const_tree);
+extern bool is_empty_type (const_tree);
+extern bool default_is_empty_record (const_tree);
+extern bool flexible_array_type_p (const_tree);
+extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree);
+extern tree arg_size_in_bytes (const_tree);
+extern bool expr_type_first_operand_type_p (tree_code);
+
+extern location_t
+set_source_range (tree expr, location_t start, location_t finish);
+
+extern location_t
+set_source_range (tree expr, source_range src_range);
+
+#if 0 // sdcpp
+/* Return true if it makes sense to promote/demote from_type to to_type. */
+inline bool
+desired_pro_or_demotion_p (const_tree to_type, const_tree from_type)
+{
+ unsigned int to_type_precision = TYPE_PRECISION (to_type);
+
+ /* OK to promote if to_type is no bigger than word_mode. */
+ if (to_type_precision <= GET_MODE_PRECISION (word_mode))
+ return true;
+
+ /* Otherwise, allow only if narrowing or same precision conversions. */
+ return to_type_precision <= TYPE_PRECISION (from_type);
+}
+#endif
+
+/* Pointer type used to declare builtins before we have seen its real
+ declaration. */
+class builtin_structptr_type
+{
+public:
+ tree& node;
+ tree& base;
+ const char *str;
+};
+extern const builtin_structptr_type builtin_structptr_types[6];
+
+/* Return true if type T has the same precision as its underlying mode. */
+
+#if 0 // sdcpp
+inline bool
+type_has_mode_precision_p (const_tree t)
+{
+ return known_eq (TYPE_PRECISION (t), GET_MODE_PRECISION (TYPE_MODE (t)));
+}
+#endif
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function.
+
+ Note that it is different from the DECL_IS_UNDECLARED_BUILTIN
+ accessor, as this is impervious to user declaration. */
+
+inline bool
+fndecl_built_in_p (const_tree node)
+{
+ return DECL_BUILT_IN_CLASS (node) != NOT_BUILT_IN;
+}
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
+ of class KLASS. */
+
+inline bool
+fndecl_built_in_p (const_tree node, built_in_class klass)
+{
+ return fndecl_built_in_p (node) && DECL_BUILT_IN_CLASS (node) == klass;
+}
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
+ of class KLASS with name equal to NAME. */
+
+inline bool
+fndecl_built_in_p (const_tree node, unsigned int name, built_in_class klass)
+{
+ return (fndecl_built_in_p (node, klass)
+ && DECL_UNCHECKED_FUNCTION_CODE (node) == name);
+}
+
+/* Return true if a FUNCTION_DECL NODE is a GCC built-in function
+ of BUILT_IN_NORMAL class with name equal to NAME. */
+
+inline bool
+fndecl_built_in_p (const_tree node, built_in_function name)
+{
+ return (fndecl_built_in_p (node, BUILT_IN_NORMAL)
+ && DECL_FUNCTION_CODE (node) == name);
+}
+
+/* A struct for encapsulating location information about an operator
+ and the operation built from it.
+
+ m_operator_loc is the location of the operator
+ m_combined_loc is the location of the compound expression.
+
+ For example, given "a && b" the, operator location is:
+ a && b
+ ^~
+ and the combined location is:
+ a && b
+ ~~^~~~
+ Capturing this information allows for class binary_op_rich_location
+ to provide detailed information about e.g. type mismatches in binary
+ operations where enough location information is available:
+
+ arg_0 op arg_1
+ ~~~~~ ^~ ~~~~~
+ | |
+ | arg1 type
+ arg0 type
+
+ falling back to just showing the combined location:
+
+ arg_0 op arg_1
+ ~~~~~~^~~~~~~~
+
+ where it is not. */
+
+class op_location_t
+{
+public:
+ location_t m_operator_loc;
+ location_t m_combined_loc;
+
+ /* 1-argument ctor, for constructing from a combined location. */
+ op_location_t (location_t combined_loc)
+ : m_operator_loc (UNKNOWN_LOCATION), m_combined_loc (combined_loc)
+ {}
+
+ /* 2-argument ctor, for distinguishing between the operator's location
+ and the combined location. */
+ op_location_t (location_t operator_loc, location_t combined_loc)
+ : m_operator_loc (operator_loc), m_combined_loc (combined_loc)
+ {}
+
+ /* Implicitly convert back to a location_t, using the combined location. */
+ operator location_t () const { return m_combined_loc; }
+};
+#endif // sdcpp
+
+/* Code that doesn't refer to any warning. Has no effect on suppression
+ functions. */
+constexpr opt_code no_warning = opt_code ();
+/* Wildcard code that refers to all warnings. */
+constexpr opt_code all_warnings = N_OPTS;
+#if 0 // sdcpp
+#endif // sdcpp
+#if 0 // sdcpp
+
+/* Return the disposition for a warning (or all warnings by default)
+ at a location. */
+extern bool warning_suppressed_at (location_t, opt_code = all_warnings);
+/* Set the disposition for a warning (or all warnings by default)
+ at a location to disabled by default. */
+extern bool suppress_warning_at (location_t, opt_code = all_warnings,
+ bool = true);
+/* Copy warning disposition from one location to another. */
+extern void copy_warning (location_t, location_t);
+
+/* Return the disposition for a warning (or all warnings by default)
+ for an expression. */
+extern bool warning_suppressed_p (const_tree, opt_code = all_warnings);
+/* Set the disposition for a warning (or all warnings by default)
+ at a location to disabled by default. */
+extern void suppress_warning (tree, opt_code = all_warnings, bool = true)
+ ATTRIBUTE_NONNULL (1);
+/* Copy warning disposition from one expression to another. */
+extern void copy_warning (tree, const_tree);
+
+/* Return the zero-based number corresponding to the argument being
+ deallocated if FNDECL is a deallocation function or an out-of-bounds
+ value if it isn't. */
+extern unsigned fndecl_dealloc_argno (tree);
+
+/* If an expression refers to a character array or pointer declared
+ attribute nonstring, return a decl for that array or pointer and
+ if nonnull, set the second argument to the referenced enclosing
+ object or pointer. Otherwise return null. */
+extern tree get_attr_nonstring_decl (tree, tree * = NULL);
+
+extern int get_target_clone_attr_len (tree);
+
+#endif // sdcpp
+#endif /* GCC_TREE_H */
diff --git a/support/cpp/gcc/treestruct.def b/support/cpp/gcc/treestruct.def
new file mode 100644
index 000000000..cba29f7e3
--- /dev/null
+++ b/support/cpp/gcc/treestruct.def
@@ -0,0 +1,71 @@
+/* This file contains the definitions for the tree structure
+ enumeration used in GCC.
+
+Copyright (C) 2005-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/>. */
+
+/* The format of this file is
+
+ DEFTREESTRUCT(enumeration value, printable name).
+
+ Each enumeration value should correspond with a single member of
+ union tree_node.
+
+ These enumerator values are used in order to distinguish members of
+ union tree_node for garbage collection purposes, as well as
+ specifying what structures contain what other structures in the
+ tree_contains_struct array. */
+DEFTREESTRUCT(TS_BASE, "base")
+DEFTREESTRUCT(TS_TYPED, "typed")
+DEFTREESTRUCT(TS_COMMON, "common")
+DEFTREESTRUCT(TS_INT_CST, "integer cst")
+DEFTREESTRUCT(TS_POLY_INT_CST, "poly_int_cst")
+DEFTREESTRUCT(TS_REAL_CST, "real cst")
+DEFTREESTRUCT(TS_FIXED_CST, "fixed cst")
+DEFTREESTRUCT(TS_VECTOR, "vector")
+DEFTREESTRUCT(TS_STRING, "string")
+DEFTREESTRUCT(TS_COMPLEX, "complex")
+DEFTREESTRUCT(TS_IDENTIFIER, "identifier")
+DEFTREESTRUCT(TS_DECL_MINIMAL, "decl minimal")
+DEFTREESTRUCT(TS_DECL_COMMON, "decl common")
+DEFTREESTRUCT(TS_DECL_WRTL, "decl with RTL")
+DEFTREESTRUCT(TS_DECL_NON_COMMON, "decl non-common")
+DEFTREESTRUCT(TS_DECL_WITH_VIS, "decl with visibility")
+DEFTREESTRUCT(TS_FIELD_DECL, "field decl")
+DEFTREESTRUCT(TS_VAR_DECL, "var decl")
+DEFTREESTRUCT(TS_PARM_DECL, "parm decl")
+DEFTREESTRUCT(TS_LABEL_DECL, "label decl")
+DEFTREESTRUCT(TS_RESULT_DECL, "result decl")
+DEFTREESTRUCT(TS_CONST_DECL, "const decl")
+DEFTREESTRUCT(TS_TYPE_DECL, "type decl")
+DEFTREESTRUCT(TS_FUNCTION_DECL, "function decl")
+DEFTREESTRUCT(TS_TRANSLATION_UNIT_DECL, "translation-unit decl")
+DEFTREESTRUCT(TS_TYPE_COMMON, "type common")
+DEFTREESTRUCT(TS_TYPE_WITH_LANG_SPECIFIC, "type with lang-specific")
+DEFTREESTRUCT(TS_TYPE_NON_COMMON, "type non-common")
+DEFTREESTRUCT(TS_LIST, "list")
+DEFTREESTRUCT(TS_VEC, "vec")
+DEFTREESTRUCT(TS_EXP, "exp")
+DEFTREESTRUCT(TS_SSA_NAME, "ssa name")
+DEFTREESTRUCT(TS_BLOCK, "block")
+DEFTREESTRUCT(TS_BINFO, "binfo")
+DEFTREESTRUCT(TS_STATEMENT_LIST, "statement list")
+DEFTREESTRUCT(TS_CONSTRUCTOR, "constructor")
+DEFTREESTRUCT(TS_OMP_CLAUSE, "omp clause")
+DEFTREESTRUCT(TS_OPTIMIZATION, "optimization options")
+DEFTREESTRUCT(TS_TARGET_OPTION, "target options")
diff --git a/support/cpp/gcc/typed-splay-tree.h b/support/cpp/gcc/typed-splay-tree.h
new file mode 100644
index 000000000..a3c353010
--- /dev/null
+++ b/support/cpp/gcc/typed-splay-tree.h
@@ -0,0 +1,652 @@
+/* A typesafe wrapper around libiberty's splay-tree.h.
+ Copyright (C) 2015-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_TYPED_SPLAY_TREE_H
+#define GCC_TYPED_SPLAY_TREE_H
+
+/* Typesafe wrapper around libiberty's splay-tree.h. */
+template <typename KEY_TYPE, typename VALUE_TYPE>
+class typed_splay_tree
+{
+ public:
+ typedef KEY_TYPE key_type;
+ typedef VALUE_TYPE value_type;
+
+ typedef int (*compare_fn) (key_type, key_type);
+ typedef void (*delete_key_fn) (key_type);
+ typedef void (*delete_value_fn) (value_type);
+ typedef int (*foreach_fn) (key_type, value_type, void *);
+
+ typed_splay_tree (compare_fn,
+ delete_key_fn,
+ delete_value_fn);
+ ~typed_splay_tree ();
+
+ value_type lookup (key_type k);
+ value_type predecessor (key_type k);
+ value_type successor (key_type k);
+ void insert (key_type k, value_type v);
+ void remove (key_type k);
+ value_type max ();
+ value_type min ();
+ int foreach (foreach_fn, void *);
+
+ private:
+ /* Copy and assignment ops are not supported. */
+ typed_splay_tree (const typed_splay_tree &);
+ typed_splay_tree & operator = (const typed_splay_tree &);
+
+ typedef key_type splay_tree_key;
+ typedef value_type splay_tree_value;
+
+ /* The nodes in the splay tree. */
+ struct splay_tree_node_s {
+ /* The key. */
+ splay_tree_key key;
+
+ /* The value. */
+ splay_tree_value value;
+
+ /* The left and right children, respectively. */
+ splay_tree_node_s *left, *right;
+
+ /* Used as temporary value for tree traversals. */
+ splay_tree_node_s *back;
+ };
+ typedef splay_tree_node_s *splay_tree_node;
+
+ inline void KDEL (splay_tree_key);
+ inline void VDEL (splay_tree_value);
+ void splay_tree_delete_helper (splay_tree_node);
+ static inline void rotate_left (splay_tree_node *,
+ splay_tree_node, splay_tree_node);
+ static inline void rotate_right (splay_tree_node *,
+ splay_tree_node, splay_tree_node);
+ void splay_tree_splay (splay_tree_key);
+ static int splay_tree_foreach_helper (splay_tree_node,
+ foreach_fn, void*);
+ splay_tree_node splay_tree_insert (splay_tree_key, splay_tree_value);
+ void splay_tree_remove (splay_tree_key key);
+ splay_tree_node splay_tree_lookup (splay_tree_key key);
+ splay_tree_node splay_tree_predecessor (splay_tree_key);
+ splay_tree_node splay_tree_successor (splay_tree_key);
+ splay_tree_node splay_tree_max ();
+ splay_tree_node splay_tree_min ();
+
+ static value_type node_to_value (splay_tree_node node);
+
+ /* The root of the tree. */
+ splay_tree_node root;
+
+ /* The comparision function. */
+ compare_fn comp;
+
+ /* The deallocate-key function. NULL if no cleanup is necessary. */
+ delete_key_fn delete_key;
+
+ /* The deallocate-value function. NULL if no cleanup is necessary. */
+ delete_value_fn delete_value;
+};
+
+/* Constructor for typed_splay_tree <K, V>. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
+ typed_splay_tree (compare_fn compare_fn,
+ delete_key_fn delete_key_fn,
+ delete_value_fn delete_value_fn)
+{
+ root = NULL;
+ comp = compare_fn;
+ delete_key = delete_key_fn;
+ delete_value = delete_value_fn;
+}
+
+/* Destructor for typed_splay_tree <K, V>. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline typed_splay_tree<KEY_TYPE, VALUE_TYPE>::
+ ~typed_splay_tree ()
+{
+ splay_tree_delete_helper (root);
+}
+
+/* Lookup KEY, returning a value if present, and NULL
+ otherwise. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::lookup (key_type key)
+{
+ splay_tree_node node = splay_tree_lookup (key);
+ return node_to_value (node);
+}
+
+/* Return the immediate predecessor of KEY, or NULL if there is no
+ predecessor. KEY need not be present in the tree. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::predecessor (key_type key)
+{
+ splay_tree_node node = splay_tree_predecessor (key);
+ return node_to_value (node);
+}
+
+/* Return the immediate successor of KEY, or NULL if there is no
+ successor. KEY need not be present in the tree. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::successor (key_type key)
+{
+ splay_tree_node node = splay_tree_successor (key);
+ return node_to_value (node);
+}
+
+/* Insert a new node (associating KEY with VALUE). If a
+ previous node with the indicated KEY exists, its data is replaced
+ with the new value. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::insert (key_type key,
+ value_type value)
+{
+ splay_tree_insert (key, value);
+}
+
+/* Remove a node (associating KEY with VALUE). */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::remove (key_type key)
+{
+ splay_tree_remove (key);
+}
+
+/* Get the value with maximal key. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::max ()
+{
+ return node_to_value (splay_tree_max ());
+}
+
+/* Get the value with minimal key. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::min ()
+{
+ return node_to_value (splay_tree_min ());
+}
+
+/* Call OUTER_CB, passing it the OUTER_USER_DATA, for every node,
+ following an in-order traversal. If OUTER_CB ever returns a non-zero
+ value, the iteration ceases immediately, and the value is returned.
+ Otherwise, this function returns 0. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline int
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::foreach (foreach_fn foreach_fn,
+ void *user_data)
+{
+ return splay_tree_foreach_helper (root, foreach_fn, user_data);
+}
+
+/* Internal function for converting from splay_tree_node to
+ VALUE_TYPE. */
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline VALUE_TYPE
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::node_to_value (splay_tree_node node)
+{
+ if (node)
+ return node->value;
+ else
+ return 0;
+}
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::KDEL(splay_tree_key x)
+{
+ if (delete_key)
+ (*delete_key)(x);
+}
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::VDEL(splay_tree_value x)
+{
+ if (delete_value)
+ (*delete_value)(x);
+}
+
+/* Deallocate NODE (a member of SP), and all its sub-trees. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+void
+typed_splay_tree<KEY_TYPE,
+ VALUE_TYPE>::splay_tree_delete_helper (splay_tree_node node)
+{
+ splay_tree_node pending = NULL;
+ splay_tree_node active = NULL;
+
+ if (!node)
+ return;
+
+ KDEL (node->key);
+ VDEL (node->value);
+
+ /* We use the "back" field to hold the "next" pointer. */
+ node->back = pending;
+ pending = node;
+
+ /* Now, keep processing the pending list until there aren't any
+ more. This is a little more complicated than just recursing, but
+ it doesn't toast the stack for large trees. */
+
+ while (pending)
+ {
+ active = pending;
+ pending = NULL;
+ while (active)
+ {
+ splay_tree_node temp;
+
+ /* active points to a node which has its key and value
+ deallocated, we just need to process left and right. */
+
+ if (active->left)
+ {
+ KDEL (active->left->key);
+ VDEL (active->left->value);
+ active->left->back = pending;
+ pending = active->left;
+ }
+ if (active->right)
+ {
+ KDEL (active->right->key);
+ VDEL (active->right->value);
+ active->right->back = pending;
+ pending = active->right;
+ }
+
+ temp = active;
+ active = temp->back;
+ delete temp;
+ }
+ }
+}
+
+/* Rotate the edge joining the left child N with its parent P. PP is the
+ grandparents' pointer to P. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::rotate_left (splay_tree_node *pp,
+ splay_tree_node p,
+ splay_tree_node n)
+{
+ splay_tree_node tmp;
+ tmp = n->right;
+ n->right = p;
+ p->left = tmp;
+ *pp = n;
+}
+
+/* Rotate the edge joining the right child N with its parent P. PP is the
+ grandparents' pointer to P. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+inline void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::rotate_right (splay_tree_node *pp,
+ splay_tree_node p,
+ splay_tree_node n)
+{
+ splay_tree_node tmp;
+ tmp = n->left;
+ n->left = p;
+ p->right = tmp;
+ *pp = n;
+}
+
+/* Bottom up splay of key. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_splay (splay_tree_key key)
+{
+ if (root == NULL)
+ return;
+
+ do {
+ int cmp1, cmp2;
+ splay_tree_node n, c;
+
+ n = root;
+ cmp1 = (*comp) (key, n->key);
+
+ /* Found. */
+ if (cmp1 == 0)
+ return;
+
+ /* Left or right? If no child, then we're done. */
+ if (cmp1 < 0)
+ c = n->left;
+ else
+ c = n->right;
+ if (!c)
+ return;
+
+ /* Next one left or right? If found or no child, we're done
+ after one rotation. */
+ cmp2 = (*comp) (key, c->key);
+ if (cmp2 == 0
+ || (cmp2 < 0 && !c->left)
+ || (cmp2 > 0 && !c->right))
+ {
+ if (cmp1 < 0)
+ rotate_left (&root, n, c);
+ else
+ rotate_right (&root, n, c);
+ return;
+ }
+
+ /* Now we have the four cases of double-rotation. */
+ if (cmp1 < 0 && cmp2 < 0)
+ {
+ rotate_left (&n->left, c, c->left);
+ rotate_left (&root, n, n->left);
+ }
+ else if (cmp1 > 0 && cmp2 > 0)
+ {
+ rotate_right (&n->right, c, c->right);
+ rotate_right (&root, n, n->right);
+ }
+ else if (cmp1 < 0 && cmp2 > 0)
+ {
+ rotate_right (&n->left, c, c->right);
+ rotate_left (&root, n, n->left);
+ }
+ else if (cmp1 > 0 && cmp2 < 0)
+ {
+ rotate_left (&n->right, c, c->left);
+ rotate_right (&root, n, n->right);
+ }
+ } while (1);
+}
+
+/* Call FN, passing it the DATA, for every node below NODE, all of
+ which are from SP, following an in-order traversal. If FN every
+ returns a non-zero value, the iteration ceases immediately, and the
+ value is returned. Otherwise, this function returns 0. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+int
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_foreach_helper (
+ splay_tree_node node,
+ foreach_fn fn, void *data)
+{
+ int val;
+ splay_tree_node stack;
+
+ /* A non-recursive implementation is used to avoid filling the stack
+ for large trees. Splay trees are worst case O(n) in the depth of
+ the tree. */
+
+ stack = NULL;
+ val = 0;
+
+ for (;;)
+ {
+ while (node != NULL)
+ {
+ node->back = stack;
+ stack = node;
+ node = node->left;
+ }
+
+ if (stack == NULL)
+ break;
+
+ node = stack;
+ stack = stack->back;
+
+ val = (*fn) (node->key, node->value, data);
+ if (val)
+ break;
+
+ node = node->right;
+ }
+
+ return val;
+}
+
+/* Insert a new node (associating KEY with DATA) into SP. If a
+ previous node with the indicated KEY exists, its data is replaced
+ with the new value. Returns the new node. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_insert (
+ splay_tree_key key,
+ splay_tree_value value)
+{
+ int comparison = 0;
+
+ splay_tree_splay (key);
+
+ if (root)
+ comparison = (*comp)(root->key, key);
+
+ if (root && comparison == 0)
+ {
+ /* If the root of the tree already has the indicated KEY, just
+ replace the value with VALUE. */
+ VDEL(root->value);
+ root->value = value;
+ }
+ else
+ {
+ /* Create a new node, and insert it at the root. */
+ splay_tree_node node;
+
+ node = new splay_tree_node_s;
+ node->key = key;
+ node->value = value;
+
+ if (!root)
+ node->left = node->right = 0;
+ else if (comparison < 0)
+ {
+ node->left = root;
+ node->right = node->left->right;
+ node->left->right = 0;
+ }
+ else
+ {
+ node->right = root;
+ node->left = node->right->left;
+ node->right->left = 0;
+ }
+
+ root = node;
+ }
+
+ return root;
+}
+
+/* Remove KEY from SP. It is not an error if it did not exist. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+void
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_remove (splay_tree_key key)
+{
+ splay_tree_splay (key);
+
+ if (root && (*comp) (root->key, key) == 0)
+ {
+ splay_tree_node left, right;
+
+ left = root->left;
+ right = root->right;
+
+ /* Delete the root node itself. */
+ VDEL (root->value);
+ delete root;
+
+ /* One of the children is now the root. Doesn't matter much
+ which, so long as we preserve the properties of the tree. */
+ if (left)
+ {
+ root = left;
+
+ /* If there was a right child as well, hang it off the
+ right-most leaf of the left child. */
+ if (right)
+ {
+ while (left->right)
+ left = left->right;
+ left->right = right;
+ }
+ }
+ else
+ root = right;
+ }
+}
+
+/* Lookup KEY in SP, returning VALUE if present, and NULL
+ otherwise. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_lookup (splay_tree_key key)
+{
+ splay_tree_splay (key);
+
+ if (root && (*comp)(root->key, key) == 0)
+ return root;
+ else
+ return 0;
+}
+
+/* Return the node in SP with the greatest key. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_max ()
+{
+ splay_tree_node n = root;
+
+ if (!n)
+ return NULL;
+
+ while (n->right)
+ n = n->right;
+
+ return n;
+}
+
+/* Return the node in SP with the smallest key. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
+typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_min ()
+{
+ splay_tree_node n = root;
+
+ if (!n)
+ return NULL;
+
+ while (n->left)
+ n = n->left;
+
+ return n;
+}
+
+/* Return the immediate predecessor KEY, or NULL if there is no
+ predecessor. KEY need not be present in the tree. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
+typed_splay_tree<KEY_TYPE,
+ VALUE_TYPE>::splay_tree_predecessor (splay_tree_key key)
+{
+ int comparison;
+ splay_tree_node node;
+
+ /* If the tree is empty, there is certainly no predecessor. */
+ if (!root)
+ return NULL;
+
+ /* Splay the tree around KEY. That will leave either the KEY
+ itself, its predecessor, or its successor at the root. */
+ splay_tree_splay (key);
+ comparison = (*comp)(root->key, key);
+
+ /* If the predecessor is at the root, just return it. */
+ if (comparison < 0)
+ return root;
+
+ /* Otherwise, find the rightmost element of the left subtree. */
+ node = root->left;
+ if (node)
+ while (node->right)
+ node = node->right;
+
+ return node;
+}
+
+/* Return the immediate successor KEY, or NULL if there is no
+ successor. KEY need not be present in the tree. */
+
+template <typename KEY_TYPE, typename VALUE_TYPE>
+typename typed_splay_tree<KEY_TYPE, VALUE_TYPE>::splay_tree_node
+typed_splay_tree<KEY_TYPE,
+ VALUE_TYPE>::splay_tree_successor (splay_tree_key key)
+{
+ int comparison;
+ splay_tree_node node;
+
+ /* If the tree is empty, there is certainly no successor. */
+ if (!root)
+ return NULL;
+
+ /* Splay the tree around KEY. That will leave either the KEY
+ itself, its predecessor, or its successor at the root. */
+ splay_tree_splay (key);
+ comparison = (*comp)(root->key, key);
+
+ /* If the successor is at the root, just return it. */
+ if (comparison > 0)
+ return root;
+
+ /* Otherwise, find the leftmost element of the right subtree. */
+ node = root->right;
+ if (node)
+ while (node->left)
+ node = node->left;
+
+ return node;
+}
+
+#endif /* GCC_TYPED_SPLAY_TREE_H */
diff --git a/support/cpp/gcc/value-query.h b/support/cpp/gcc/value-query.h
new file mode 100644
index 000000000..78e2d1b81
--- /dev/null
+++ b/support/cpp/gcc/value-query.h
@@ -0,0 +1,149 @@
+/* Support routines for value queries.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldyh@redhat.com> and
+ Andrew Macleod <amacleod@redhat.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.
+
+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_QUERY_H
+#define GCC_QUERY_H
+
+#include "value-relation.h"
+
+// The value_query class is used by optimization passes that require
+// valueizing SSA names in terms of a tree value, but have no neeed
+// for ranges.
+//
+// value_of_expr must be provided. The default for value_on_edge and
+// value_of_stmt is to call value_of_expr.
+//
+// This implies the valuation is global in nature. If a pass can make
+// use of more specific information, it can override the other queries.
+//
+// Proper usage of the correct query in passes will enable other
+// valuation mechanisms to produce more precise results.
+
+class value_query
+{
+public:
+ value_query () { }
+ // Return the singleton expression for EXPR at a gimple statement,
+ // or NULL if none found.
+ virtual tree value_of_expr (tree expr, gimple * = NULL) = 0;
+ // Return the singleton expression for EXPR at an edge, or NULL if
+ // none found.
+ virtual tree value_on_edge (edge, tree expr);
+ // Return the singleton expression for the LHS of a gimple
+ // statement, assuming an (optional) initial value of NAME. Returns
+ // NULL if none found.
+ //
+ // Note that this method calculates the range the LHS would have
+ // *after* the statement has executed.
+ virtual tree value_of_stmt (gimple *, tree name = NULL);
+
+private:
+ DISABLE_COPY_AND_ASSIGN (value_query);
+};
+
+// The range_query class is used by optimization passes which are
+// range aware.
+//
+// range_of_expr must be provided. The default for range_on_edge and
+// range_of_stmt is to call range_of_expr. If a pass can make use of
+// more specific information, then it can override the other queries.
+//
+// The default for the value_* routines is to call the equivalent
+// range_* routines, check if the range is a singleton, and return it
+// if so.
+//
+// The get_value_range method is currently provided for compatibility
+// with vr-values. It will be deprecated when possible.
+
+class range_query : public value_query
+{
+public:
+ range_query ();
+ virtual ~range_query ();
+
+ virtual tree value_of_expr (tree expr, gimple * = NULL) OVERRIDE;
+ virtual tree value_on_edge (edge, tree expr) OVERRIDE;
+ virtual tree value_of_stmt (gimple *, tree name = NULL) OVERRIDE;
+
+ // These are the range equivalents of the value_* methods. Instead
+ // of returning a singleton, they calculate a range and return it in
+ // R. TRUE is returned on success or FALSE if no range was found.
+ //
+ // Note that range_of_expr must always return TRUE unless ranges are
+ // unsupported for EXPR's type (supports_type_p is false).
+ virtual bool range_of_expr (irange &r, tree expr, gimple * = NULL) = 0;
+ virtual bool range_on_edge (irange &r, edge, tree expr);
+ virtual bool range_of_stmt (irange &r, gimple *, tree name = NULL);
+
+ // Query if there is any relation between SSA1 and SSA2.
+ relation_kind query_relation (gimple *s, tree ssa1, tree ssa2,
+ bool get_range = true);
+ relation_kind query_relation (edge e, tree ssa1, tree ssa2,
+ bool get_range = true);
+ // If present, Access relation oracle for more advanced uses.
+ inline relation_oracle *oracle () const { return m_oracle; }
+
+ // DEPRECATED: This method is used from vr-values. The plan is to
+ // rewrite all uses of it to the above API.
+ virtual const class value_range_equiv *get_value_range (const_tree,
+ gimple * = NULL);
+ virtual void dump (FILE *);
+
+protected:
+ class value_range_equiv *allocate_value_range_equiv ();
+ void free_value_range_equiv (class value_range_equiv *);
+ bool get_tree_range (irange &r, tree expr, gimple *stmt);
+ bool get_arith_expr_range (irange &r, tree expr, gimple *stmt);
+ relation_oracle *m_oracle;
+
+private:
+ class equiv_allocator *equiv_alloc;
+};
+
+// Global ranges for SSA names using SSA_NAME_RANGE_INFO.
+
+class global_range_query : public range_query
+{
+public:
+ bool range_of_expr (irange &r, tree expr, gimple * = NULL) OVERRIDE;
+};
+
+extern global_range_query global_ranges;
+
+inline range_query *
+get_global_range_query ()
+{
+ return &global_ranges;
+}
+
+/* Returns the currently active range access class. When there is no active
+ range class, global ranges are used. Never returns null. */
+
+ATTRIBUTE_RETURNS_NONNULL inline range_query *
+get_range_query (const struct function *fun)
+{
+ return fun->x_range_query ? fun->x_range_query : &global_ranges;
+}
+
+extern value_range gimple_range_global (tree name);
+extern bool update_global_range (irange &r, tree name);
+
+#endif // GCC_QUERY_H
diff --git a/support/cpp/gcc/value-range.h b/support/cpp/gcc/value-range.h
new file mode 100644
index 000000000..82cc35ec1
--- /dev/null
+++ b/support/cpp/gcc/value-range.h
@@ -0,0 +1,715 @@
+/* Support routines for value ranges.
+ Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez <aldyh@redhat.com> and
+ Andrew Macleod <amacleod@redhat.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.
+
+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/>. */
+
+#if 0 // sdcpp ndef GCC_VALUE_RANGE_H
+#define GCC_VALUE_RANGE_H
+
+// Types of value ranges.
+enum value_range_kind
+{
+ /* Empty range. */
+ VR_UNDEFINED,
+ /* Range spans the entire domain. */
+ VR_VARYING,
+ /* Range is [MIN, MAX]. */
+ VR_RANGE,
+ /* Range is ~[MIN, MAX]. */
+ VR_ANTI_RANGE,
+ /* Range is a nice guy. */
+ VR_LAST
+};
+
+// Range of values that can be associated with an SSA_NAME.
+//
+// This is the base class without any storage.
+
+class GTY((user)) irange
+{
+ friend class irange_allocator;
+public:
+ // In-place setters.
+ void set (tree, tree, value_range_kind = VR_RANGE);
+ void set_nonzero (tree);
+ void set_zero (tree);
+ void set_varying (tree type);
+ void set_undefined ();
+
+ // Range types.
+ static bool supports_type_p (tree);
+ tree type () const;
+
+ // Iteration over sub-ranges.
+ unsigned num_pairs () const;
+ wide_int lower_bound (unsigned = 0) const;
+ wide_int upper_bound (unsigned) const;
+ wide_int upper_bound () const;
+
+ // Predicates.
+ bool zero_p () const;
+ bool nonzero_p () const;
+ bool undefined_p () const;
+ bool varying_p () const;
+ bool singleton_p (tree *result = NULL) const;
+ bool contains_p (tree) const;
+
+ // In-place operators.
+ void union_ (const irange &);
+ void intersect (const irange &);
+ void intersect (const wide_int& lb, const wide_int& ub);
+ void invert ();
+
+ // Operator overloads.
+ irange& operator= (const irange &);
+ bool operator== (const irange &) const;
+ bool operator!= (const irange &r) const { return !(*this == r); }
+
+ // Misc methods.
+ bool fits_p (const irange &r) { return m_max_ranges >= r.num_pairs (); }
+ void dump (FILE * = stderr) const;
+ void debug () const;
+
+ // Deprecated legacy public methods.
+ enum value_range_kind kind () const; // DEPRECATED
+ tree min () const; // DEPRECATED
+ tree max () const; // DEPRECATED
+ bool symbolic_p () const; // DEPRECATED
+ bool constant_p () const; // DEPRECATED
+ void normalize_symbolics (); // DEPRECATED
+ void normalize_addresses (); // DEPRECATED
+ bool may_contain_p (tree) const; // DEPRECATED
+ void set (tree); // DEPRECATED
+ bool equal_p (const irange &) const; // DEPRECATED
+ void union_ (const class irange *); // DEPRECATED
+ void intersect (const irange *); // DEPRECATED
+
+protected:
+ irange (tree *, unsigned);
+ // potential promotion to public?
+ tree tree_lower_bound (unsigned = 0) const;
+ tree tree_upper_bound (unsigned) const;
+ tree tree_upper_bound () const;
+
+ // In-place operators.
+ void irange_union (const irange &);
+ void irange_intersect (const irange &);
+ void irange_set (tree, tree);
+ void irange_set_anti_range (tree, tree);
+
+ void normalize_kind ();
+
+ bool legacy_mode_p () const;
+ bool legacy_equal_p (const irange &) const;
+ void legacy_union (irange *, const irange *);
+ void legacy_intersect (irange *, const irange *);
+ void verify_range ();
+ wide_int legacy_lower_bound (unsigned = 0) const;
+ wide_int legacy_upper_bound (unsigned) const;
+ int value_inside_range (tree) const;
+ bool maybe_anti_range () const;
+ void copy_to_legacy (const irange &);
+ void copy_legacy_to_multi_range (const irange &);
+
+private:
+ friend void gt_ggc_mx (irange *);
+ friend void gt_pch_nx (irange *);
+ friend void gt_pch_nx (irange *, gt_pointer_operator, void *);
+
+ void irange_set_1bit_anti_range (tree, tree);
+ bool varying_compatible_p () const;
+
+ unsigned char m_num_ranges;
+ unsigned char m_max_ranges;
+ ENUM_BITFIELD(value_range_kind) m_kind : 8;
+ tree *m_base;
+};
+
+// Here we describe an irange with N pairs of ranges. The storage for
+// the pairs is embedded in the class as an array.
+
+template<unsigned N>
+class GTY((user)) int_range : public irange
+{
+public:
+ int_range ();
+ int_range (tree, tree, value_range_kind = VR_RANGE);
+ int_range (tree type, const wide_int &, const wide_int &,
+ value_range_kind = VR_RANGE);
+ int_range (tree type);
+ int_range (const int_range &);
+ int_range (const irange &);
+ int_range& operator= (const int_range &);
+private:
+ template <unsigned X> friend void gt_ggc_mx (int_range<X> *);
+ template <unsigned X> friend void gt_pch_nx (int_range<X> *);
+ template <unsigned X> friend void gt_pch_nx (int_range<X> *,
+ gt_pointer_operator, void *);
+
+ // ?? These stubs are for ipa-prop.cc which use a value_range in a
+ // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &)
+ // instead of picking up the gt_ggc_mx (T *) version.
+ friend void gt_ggc_mx (int_range<1> *&);
+ friend void gt_pch_nx (int_range<1> *&);
+
+ tree m_ranges[N*2];
+};
+
+// This is a special int_range<1> with only one pair, plus
+// VR_ANTI_RANGE magic to describe slightly more than can be described
+// in one pair. It is described in the code as a "legacy range" (as
+// opposed to multi-ranges which have multiple sub-ranges). It is
+// provided for backward compatibility with code that has not been
+// converted to multi-range irange's.
+//
+// There are copy operators to seamlessly copy to/fro multi-ranges.
+typedef int_range<1> value_range;
+
+// This is an "infinite" precision irange for use in temporary
+// calculations.
+typedef int_range<255> int_range_max;
+
+// Returns true for an old-school value_range as described above.
+inline bool
+irange::legacy_mode_p () const
+{
+ return m_max_ranges == 1;
+}
+
+extern bool range_has_numeric_bounds_p (const irange *);
+extern bool ranges_from_anti_range (const value_range *,
+ value_range *, value_range *);
+extern void dump_value_range (FILE *, const irange *);
+extern bool vrp_val_is_min (const_tree);
+extern bool vrp_val_is_max (const_tree);
+extern bool vrp_operand_equal_p (const_tree, const_tree);
+
+inline value_range_kind
+irange::kind () const
+{
+ return m_kind;
+}
+
+// Number of sub-ranges in a range.
+
+inline unsigned
+irange::num_pairs () const
+{
+ if (m_kind == VR_ANTI_RANGE)
+ return constant_p () ? 2 : 1;
+ else
+ return m_num_ranges;
+}
+
+inline tree
+irange::type () const
+{
+ gcc_checking_assert (m_num_ranges > 0);
+ return TREE_TYPE (m_base[0]);
+}
+
+// Return the lower bound of a sub-range expressed as a tree. PAIR is
+// the sub-range in question.
+
+inline tree
+irange::tree_lower_bound (unsigned pair) const
+{
+ return m_base[pair * 2];
+}
+
+// Return the upper bound of a sub-range expressed as a tree. PAIR is
+// the sub-range in question.
+
+inline tree
+irange::tree_upper_bound (unsigned pair) const
+{
+ return m_base[pair * 2 + 1];
+}
+
+// Return the highest bound of a range expressed as a tree.
+
+inline tree
+irange::tree_upper_bound () const
+{
+ gcc_checking_assert (m_num_ranges);
+ return tree_upper_bound (m_num_ranges - 1);
+}
+
+inline tree
+irange::min () const
+{
+ return tree_lower_bound (0);
+}
+
+inline tree
+irange::max () const
+{
+ if (m_num_ranges)
+ return tree_upper_bound ();
+ else
+ return NULL;
+}
+
+inline bool
+irange::varying_compatible_p () const
+{
+ if (m_num_ranges != 1)
+ return false;
+
+ tree l = m_base[0];
+ tree u = m_base[1];
+ tree t = TREE_TYPE (l);
+
+ if (m_kind == VR_VARYING && t == error_mark_node)
+ return true;
+
+ unsigned prec = TYPE_PRECISION (t);
+ signop sign = TYPE_SIGN (t);
+ if (INTEGRAL_TYPE_P (t))
+ return (wi::to_wide (l) == wi::min_value (prec, sign)
+ && wi::to_wide (u) == wi::max_value (prec, sign));
+ if (POINTER_TYPE_P (t))
+ return (wi::to_wide (l) == 0
+ && wi::to_wide (u) == wi::max_value (prec, sign));
+ return true;
+}
+
+inline bool
+irange::varying_p () const
+{
+ return m_kind == VR_VARYING;
+}
+
+inline bool
+irange::undefined_p () const
+{
+ return m_kind == VR_UNDEFINED;
+}
+
+inline bool
+irange::zero_p () const
+{
+ return (m_kind == VR_RANGE && m_num_ranges == 1
+ && integer_zerop (tree_lower_bound (0))
+ && integer_zerop (tree_upper_bound (0)));
+}
+
+inline bool
+irange::nonzero_p () const
+{
+ if (undefined_p ())
+ return false;
+
+ tree zero = build_zero_cst (type ());
+ return *this == int_range<1> (zero, zero, VR_ANTI_RANGE);
+}
+
+inline bool
+irange::supports_type_p (tree type)
+{
+ if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+ return type;
+ return false;
+}
+
+inline bool
+range_includes_zero_p (const irange *vr)
+{
+ if (vr->undefined_p ())
+ return false;
+
+ if (vr->varying_p ())
+ return true;
+
+ return vr->may_contain_p (build_zero_cst (vr->type ()));
+}
+
+inline void
+gt_ggc_mx (irange *x)
+{
+ for (unsigned i = 0; i < x->m_num_ranges; ++i)
+ {
+ gt_ggc_mx (x->m_base[i * 2]);
+ gt_ggc_mx (x->m_base[i * 2 + 1]);
+ }
+}
+
+inline void
+gt_pch_nx (irange *x)
+{
+ for (unsigned i = 0; i < x->m_num_ranges; ++i)
+ {
+ gt_pch_nx (x->m_base[i * 2]);
+ gt_pch_nx (x->m_base[i * 2 + 1]);
+ }
+}
+
+inline void
+gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie)
+{
+ for (unsigned i = 0; i < x->m_num_ranges; ++i)
+ {
+ op (&x->m_base[i * 2], NULL, cookie);
+ op (&x->m_base[i * 2 + 1], NULL, cookie);
+ }
+}
+
+template<unsigned N>
+inline void
+gt_ggc_mx (int_range<N> *x)
+{
+ gt_ggc_mx ((irange *) x);
+}
+
+template<unsigned N>
+inline void
+gt_pch_nx (int_range<N> *x)
+{
+ gt_pch_nx ((irange *) x);
+}
+
+template<unsigned N>
+inline void
+gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie)
+{
+ gt_pch_nx ((irange *) x, op, cookie);
+}
+
+// Constructors for irange
+
+inline
+irange::irange (tree *base, unsigned nranges)
+{
+ m_base = base;
+ m_num_ranges = 0;
+ m_max_ranges = nranges;
+ m_kind = VR_UNDEFINED;
+}
+
+// Constructors for int_range<>.
+
+template<unsigned N>
+inline
+int_range<N>::int_range ()
+ : irange (m_ranges, N)
+{
+}
+
+template<unsigned N>
+int_range<N>::int_range (const int_range &other)
+ : irange (m_ranges, N)
+{
+ irange::operator= (other);
+}
+
+template<unsigned N>
+int_range<N>::int_range (tree min, tree max, value_range_kind kind)
+ : irange (m_ranges, N)
+{
+ irange::set (min, max, kind);
+}
+
+template<unsigned N>
+int_range<N>::int_range (tree type)
+ : irange (m_ranges, N)
+{
+ set_varying (type);
+}
+
+#if 0 // sdcpp
+template<unsigned N>
+int_range<N>::int_range (tree type, const wide_int &wmin, const wide_int &wmax,
+ value_range_kind kind)
+ : irange (m_ranges, N)
+{
+ tree min = wide_int_to_tree (type, wmin);
+ tree max = wide_int_to_tree (type, wmax);
+ set (min, max, kind);
+}
+#endif // sdcpp
+
+template<unsigned N>
+int_range<N>::int_range (const irange &other)
+ : irange (m_ranges, N)
+{
+ irange::operator= (other);
+}
+
+template<unsigned N>
+int_range<N>&
+int_range<N>::operator= (const int_range &src)
+{
+ irange::operator= (src);
+ return *this;
+}
+
+inline void
+irange::set (tree val)
+{
+ set (val, val);
+}
+
+inline void
+irange::set_undefined ()
+{
+ m_kind = VR_UNDEFINED;
+ m_num_ranges = 0;
+}
+
+#if 0 // sdcpp
+inline void
+irange::set_varying (tree type)
+{
+ m_kind = VR_VARYING;
+ m_num_ranges = 1;
+
+ if (INTEGRAL_TYPE_P (type))
+ {
+ // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
+ // min_value and max_value.
+ wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)))
+ && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type))))
+ {
+ m_base[0] = TYPE_MIN_VALUE (type);
+ m_base[1] = TYPE_MAX_VALUE (type);
+ }
+ else
+ {
+ m_base[0] = wide_int_to_tree (type, min);
+ m_base[1] = wide_int_to_tree (type, max);
+ }
+ }
+ else if (POINTER_TYPE_P (type))
+ {
+ m_base[0] = build_int_cst (type, 0);
+ m_base[1] = build_int_cst (type, -1);
+ }
+ else
+ m_base[0] = m_base[1] = error_mark_node;
+}
+#endif // sdcpp
+
+inline bool
+irange::operator== (const irange &r) const
+{
+ return equal_p (r);
+}
+
+// Return the lower bound of a sub-range. PAIR is the sub-range in
+// question.
+
+inline wide_int
+irange::lower_bound (unsigned pair) const
+{
+ if (legacy_mode_p ())
+ return legacy_lower_bound (pair);
+ gcc_checking_assert (m_num_ranges > 0);
+ gcc_checking_assert (pair + 1 <= num_pairs ());
+ return wi::to_wide (tree_lower_bound (pair));
+}
+
+// Return the upper bound of a sub-range. PAIR is the sub-range in
+// question.
+
+inline wide_int
+irange::upper_bound (unsigned pair) const
+{
+ if (legacy_mode_p ())
+ return legacy_upper_bound (pair);
+ gcc_checking_assert (m_num_ranges > 0);
+ gcc_checking_assert (pair + 1 <= num_pairs ());
+ return wi::to_wide (tree_upper_bound (pair));
+}
+
+// Return the highest bound of a range.
+
+inline wide_int
+irange::upper_bound () const
+{
+ unsigned pairs = num_pairs ();
+ gcc_checking_assert (pairs > 0);
+ return upper_bound (pairs - 1);
+}
+
+inline void
+irange::union_ (const irange &r)
+{
+ dump_flags_t m_flags = dump_flags;
+ dump_flags &= ~TDF_DETAILS;
+ irange::union_ (&r);
+ dump_flags = m_flags;
+}
+
+inline void
+irange::intersect (const irange &r)
+{
+ dump_flags_t m_flags = dump_flags;
+ dump_flags &= ~TDF_DETAILS;
+ irange::intersect (&r);
+ dump_flags = m_flags;
+}
+
+// Set value range VR to a nonzero range of type TYPE.
+
+#if 0 // sdcpp
+inline void
+irange::set_nonzero (tree type)
+{
+ tree zero = build_int_cst (type, 0);
+ if (legacy_mode_p ())
+ set (zero, zero, VR_ANTI_RANGE);
+ else
+ irange_set_anti_range (zero, zero);
+}
+
+// Set value range VR to a ZERO range of type TYPE.
+
+inline void
+irange::set_zero (tree type)
+{
+ tree z = build_int_cst (type, 0);
+ if (legacy_mode_p ())
+ set (z);
+ else
+ irange_set (z, z);
+}
+#endif // sdcpp
+
+// Normalize a range to VARYING or UNDEFINED if possible.
+
+inline void
+irange::normalize_kind ()
+{
+ if (m_num_ranges == 0)
+ m_kind = VR_UNDEFINED;
+ else if (varying_compatible_p ())
+ {
+ if (m_kind == VR_RANGE)
+ m_kind = VR_VARYING;
+ else if (m_kind == VR_ANTI_RANGE)
+ set_undefined ();
+ else
+ gcc_unreachable ();
+ }
+}
+
+// Return the maximum value for TYPE.
+
+#if 0 // sdcpp
+inline tree
+vrp_val_max (const_tree type)
+{
+ if (INTEGRAL_TYPE_P (type))
+ return TYPE_MAX_VALUE (type);
+ if (POINTER_TYPE_P (type))
+ {
+ wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
+ return wide_int_to_tree (const_cast<tree> (type), max);
+ }
+ return NULL_TREE;
+}
+#endif // sdcpp
+
+// Return the minimum value for TYPE.
+
+inline tree
+vrp_val_min (const_tree type)
+{
+ if (INTEGRAL_TYPE_P (type))
+ return TYPE_MIN_VALUE (type);
+ if (POINTER_TYPE_P (type))
+ return build_zero_cst (const_cast<tree> (type));
+ return NULL_TREE;
+}
+
+// This is the irange storage class. It is used to allocate the
+// minimum amount of storage needed for a given irange. Storage is
+// automatically freed at destruction of the storage class.
+//
+// It is meant for long term storage, as opposed to int_range_max
+// which is meant for intermediate temporary results on the stack.
+//
+// The newly allocated irange is initialized to the empty set
+// (undefined_p() is true).
+
+class irange_allocator
+{
+public:
+ irange_allocator ();
+ ~irange_allocator ();
+ // Return a new range with NUM_PAIRS.
+ irange *allocate (unsigned num_pairs);
+ // Return a copy of SRC with the minimum amount of sub-ranges needed
+ // to represent it.
+ irange *allocate (const irange &src);
+ void *get_memory (unsigned num_bytes);
+private:
+ DISABLE_COPY_AND_ASSIGN (irange_allocator);
+ struct obstack m_obstack;
+};
+
+inline
+irange_allocator::irange_allocator ()
+{
+ obstack_init (&m_obstack);
+}
+
+inline
+irange_allocator::~irange_allocator ()
+{
+ obstack_free (&m_obstack, NULL);
+}
+
+// Provide a hunk of memory from the obstack.
+inline void *
+irange_allocator::get_memory (unsigned num_bytes)
+{
+ void *r = obstack_alloc (&m_obstack, num_bytes);
+ return r;
+}
+
+// Return a new range with NUM_PAIRS.
+
+inline irange *
+irange_allocator::allocate (unsigned num_pairs)
+{
+ // Never allocate 0 pairs.
+ // Don't allocate 1 either, or we get legacy value_range's.
+ if (num_pairs < 2)
+ num_pairs = 2;
+
+ size_t nbytes = sizeof (tree) * 2 * num_pairs;
+
+ // Allocate the irange and required memory for the vector.
+ void *r = obstack_alloc (&m_obstack, sizeof (irange));
+ tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes);
+ return new (r) irange (mem, num_pairs);
+}
+
+inline irange *
+irange_allocator::allocate (const irange &src)
+{
+ irange *r = allocate (src.num_pairs ());
+ *r = src;
+ return r;
+}
+
+#endif // GCC_VALUE_RANGE_H
diff --git a/support/cpp/gcc/value-relation.h b/support/cpp/gcc/value-relation.h
new file mode 100644
index 000000000..36e4cf9e0
--- /dev/null
+++ b/support/cpp/gcc/value-relation.h
@@ -0,0 +1,245 @@
+/* Header file for the value range relational processing.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+ Contributed by Andrew MacLeod <amacleod@redhat.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.
+
+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_VALUE_RELATION_H
+#define GCC_VALUE_RELATION_H
+
+
+// This file provides access to a relation oracle which can be used to
+// maintain and query relations and equivalences between SSA_NAMES.
+//
+// The general range_query object provided in value-query.h provides
+// access to an oracle, if one is available, via the oracle() method.
+// Thre are also a couple of access routines provided, which even if there is
+// no oracle, will return the default VREL_NONE no relation.
+//
+// Typically, when a ranger object is active, there will be an oracle, and
+// any information available can be directly queried. Ranger also sets and
+// utilizes the relation information to enhance it's range calculations, this
+// is totally transparent to the client, and they are free to make queries.
+//
+//
+// relation_kind is a typedef of enum tree_code, but has restricted range
+// and a couple of extra values.
+//
+// A query is made requesting the relation between SSA1 and SSA@ in a basic
+// block, or on an edge, the possible return values are:
+//
+// EQ_EXPR, NE_EXPR, LT_EXPR, LE_EXPR, GT_EXPR, and GE_EXPR mean the same.
+// VREL_NONE : No relation between the 2 names.
+// VREL_EMPTY : Impossible relation (ie, A < B && A > B produces VREL_EMPTY.
+//
+// The oracle maintains EQ_EXPR relations with equivalency sets, so if a
+// relation comes back EQ_EXPR, it is also possible to query the set of
+// equivlaencies. These are basically bitmaps over ssa_names.
+//
+// Relations are maintained via the dominace trees and are optimized assuming
+// they are registered in dominance order. When a new relation is added, it
+// is intersected with whatever existing relation exists in the dominance tree
+// and registered at the specified block.
+
+
+// Rather than introduce a new enumerated type for relations, we can use the
+// existing tree_codes for relations, plus add a couple of #defines for
+// the other cases. These codes are arranged such that VREL_NONE is the first
+// code, and all the rest are contiguous.
+
+typedef enum tree_code relation_kind;
+
+#define VREL_NONE TRUTH_NOT_EXPR
+#define VREL_EMPTY LTGT_EXPR
+
+// General relation kind transformations.
+relation_kind relation_union (relation_kind r1, relation_kind r2);
+relation_kind relation_intersect (relation_kind r1, relation_kind r2);
+relation_kind relation_negate (relation_kind r);
+relation_kind relation_swap (relation_kind r);
+void print_relation (FILE *f, relation_kind rel);
+
+
+class relation_oracle
+{
+public:
+ virtual ~relation_oracle () { }
+ // register a relation between 2 ssa names at a stmt.
+ void register_stmt (gimple *, relation_kind, tree, tree);
+ // register a relation between 2 ssa names on an edge.
+ void register_edge (edge, relation_kind, tree, tree);
+
+ // Return equivalency set for an SSA name in a basic block.
+ virtual const_bitmap equiv_set (tree, basic_block) = 0;
+ // register a relation between 2 ssa names in a basic block.
+ virtual void register_relation (basic_block, relation_kind, tree, tree) = 0;
+ // Query for a relation between two ssa names in a basic block.
+ virtual relation_kind query_relation (basic_block, tree, tree) = 0;
+ // Query for a relation between two equivalency stes in a basic block.
+ virtual relation_kind query_relation (basic_block, const_bitmap,
+ const_bitmap) = 0;
+
+ virtual void dump (FILE *, basic_block) const = 0;
+ virtual void dump (FILE *) const = 0;
+ void debug () const;
+protected:
+ void valid_equivs (bitmap b, const_bitmap equivs, basic_block bb);
+};
+
+// This class represents an equivalency set, and contains a link to the next
+// one in the list to be searched.
+
+class equiv_chain
+{
+public:
+ bitmap m_names; // ssa-names in equiv set.
+ basic_block m_bb; // Block this belongs to
+ equiv_chain *m_next; // Next in block list.
+ void dump (FILE *f) const; // Show names in this list.
+ equiv_chain *find (unsigned ssa);
+};
+
+// The equivalency oracle maintains equivalencies using the dominator tree.
+// Equivalencies apply to an entire basic block. Equivalencies on edges
+// can be represented only on edges whose destination is a single-pred block,
+// and the equivalence is simply applied to that succesor block.
+
+class equiv_oracle : public relation_oracle
+{
+public:
+ equiv_oracle ();
+ ~equiv_oracle ();
+
+ const_bitmap equiv_set (tree ssa, basic_block bb);
+ void register_relation (basic_block bb, relation_kind k, tree ssa1,
+ tree ssa2);
+
+ relation_kind query_relation (basic_block, tree, tree);
+ relation_kind query_relation (basic_block, const_bitmap, const_bitmap);
+ void dump (FILE *f, basic_block bb) const;
+ void dump (FILE *f) const;
+
+protected:
+ bitmap_obstack m_bitmaps;
+ struct obstack m_chain_obstack;
+private:
+ bitmap m_equiv_set; // Index by ssa-name. true if an equivalence exists.
+ vec <equiv_chain *> m_equiv; // Index by BB. list of equivalences.
+ vec <bitmap> m_self_equiv; // Index by ssa-name, self equivalency set.
+
+ void limit_check (basic_block bb = NULL);
+ equiv_chain *find_equiv_block (unsigned ssa, int bb) const;
+ equiv_chain *find_equiv_dom (tree name, basic_block bb) const;
+
+ bitmap register_equiv (basic_block bb, unsigned v, equiv_chain *equiv_1);
+ bitmap register_equiv (basic_block bb, equiv_chain *equiv_1,
+ equiv_chain *equiv_2);
+ void register_initial_def (tree ssa);
+ void add_equiv_to_block (basic_block bb, bitmap equiv);
+};
+
+// Summary block header for relations.
+
+class relation_chain_head
+{
+public:
+ bitmap m_names; // ssa_names with relations in this block.
+ class relation_chain *m_head; // List of relations in block.
+ int m_num_relations; // Number of relations in block.
+ relation_kind find_relation (const_bitmap b1, const_bitmap b2) const;
+};
+
+// A relation oracle maintains a set of relations between ssa_names using the
+// dominator tree structures. Equivalencies are considered a subset of
+// a general relation and maintained by an equivalence oracle by transparently
+// passing any EQ_EXPR relations to it.
+// Relations are handled at the basic block level. All relations apply to
+// an entire block, and are thus kept in a summary index by block.
+// Similar to the equivalence oracle, edges are handled by applying the
+// relation to the destination block of the edge, but ONLY if that block
+// has a single successor. For now.
+
+class dom_oracle : public equiv_oracle
+{
+public:
+ dom_oracle ();
+ ~dom_oracle ();
+
+ void register_relation (basic_block bb, relation_kind k, tree op1, tree op2);
+
+ relation_kind query_relation (basic_block bb, tree ssa1, tree ssa2);
+ relation_kind query_relation (basic_block bb, const_bitmap b1,
+ const_bitmap b2);
+
+ void dump (FILE *f, basic_block bb) const;
+ void dump (FILE *f) const;
+private:
+ bitmap m_tmp, m_tmp2;
+ bitmap m_relation_set; // Index by ssa-name. True if a relation exists
+ vec <relation_chain_head> m_relations; // Index by BB, list of relations.
+ relation_kind find_relation_block (unsigned bb, const_bitmap b1,
+ const_bitmap b2) const;
+ relation_kind find_relation_block (int bb, unsigned v1, unsigned v2,
+ relation_chain **obj = NULL) const;
+ relation_kind find_relation_dom (basic_block bb, unsigned v1, unsigned v2) const;
+ relation_chain *set_one_relation (basic_block bb, relation_kind k, tree op1,
+ tree op2);
+ void register_transitives (basic_block, const class value_relation &);
+
+};
+
+// A path_oracle implements relations in a list. The only sense of ordering
+// is the latest registered relation is the first found during a search.
+// It can be constructed with an optional "root" oracle which will be used
+// to look up any relations not found in the list.
+// This allows the client to walk paths starting at some block and register
+// and query relations along that path, ignoring other edges.
+//
+// For registering a relation, a query if made of the root oracle if there is
+// any known relationship at block BB, and it is combined with this new
+// relation and entered in the list.
+//
+// Queries are resolved by looking first in the list, and only if nothing is
+// found is the root oracle queried at block BB.
+//
+// reset_path is used to clear all locally registered paths to initial state.
+
+class path_oracle : public relation_oracle
+{
+public:
+ path_oracle (relation_oracle *oracle = NULL);
+ ~path_oracle ();
+ const_bitmap equiv_set (tree, basic_block);
+ void register_relation (basic_block, relation_kind, tree, tree);
+ void killing_def (tree);
+ relation_kind query_relation (basic_block, tree, tree);
+ relation_kind query_relation (basic_block, const_bitmap, const_bitmap);
+ void reset_path ();
+ void set_root_oracle (relation_oracle *oracle) { m_root = oracle; }
+ void dump (FILE *, basic_block) const;
+ void dump (FILE *) const;
+private:
+ void register_equiv (basic_block bb, tree ssa1, tree ssa2);
+ equiv_chain m_equiv;
+ relation_chain_head m_relations;
+ relation_oracle *m_root;
+ bitmap m_killed_defs;
+
+ bitmap_obstack m_bitmaps;
+ struct obstack m_chain_obstack;
+};
+#endif /* GCC_VALUE_RELATION_H */
diff --git a/support/cpp/gcc/varasm.h b/support/cpp/gcc/varasm.h
new file mode 100644
index 000000000..d5d8c4e55
--- /dev/null
+++ b/support/cpp/gcc/varasm.h
@@ -0,0 +1,82 @@
+/* Declarations for varasm.h.
+ Copyright (C) 2013-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_VARASM_H
+#define GCC_VARASM_H
+
+/* The following global holds the "function name" for the code in the
+ cold section of a function, if hot/cold function splitting is enabled
+ and there was actually code that went into the cold section. A
+ pseudo function name is needed for the cold section of code for some
+ debugging tools that perform symbolization. */
+extern tree cold_function_name;
+
+extern tree tree_output_constant_def (tree);
+extern void make_decl_rtl (tree);
+extern rtx make_decl_rtl_for_debug (tree);
+extern void make_decl_one_only (tree, tree);
+extern int supports_one_only (void);
+extern void resolve_unique_section (tree, int, int);
+extern void mark_referenced (tree);
+extern void mark_decl_referenced (tree);
+extern void notice_global_symbol (tree);
+extern void set_user_assembler_name (tree, const char *);
+extern void process_pending_assemble_externals (void);
+extern bool decl_replaceable_p (tree, bool);
+extern bool decl_binds_to_current_def_p (const_tree);
+extern enum tls_model decl_default_tls_model (const_tree);
+
+/* Declare DECL to be a weak symbol. */
+extern void declare_weak (tree);
+
+/* Merge weak status. */
+extern void merge_weak (tree, tree);
+
+/* Make one symbol an alias for another. */
+extern void assemble_alias (tree, tree);
+
+/* Return nonzero if VALUE is a valid constant-valued expression
+ for use in initializing a static variable; one that can be an
+ element of a "constant" initializer.
+
+ Return null_pointer_node if the value is absolute;
+ if it is relocatable, return the variable that determines the relocation.
+ We assume that VALUE has been folded as much as possible;
+ therefore, we do not need to check for such things as
+ arithmetic-combinations of integers. */
+extern tree initializer_constant_valid_p (tree, tree, bool = false);
+
+/* Return true if VALUE is a valid constant-valued expression
+ for use in initializing a static bit-field; one that can be
+ an element of a "constant" initializer. */
+extern bool initializer_constant_valid_for_bitfield_p (tree);
+
+/* Whether a constructor CTOR is a valid static constant initializer if all
+ its elements are. This used to be internal to initializer_constant_valid_p
+ and has been exposed to let other functions like categorize_ctor_elements
+ evaluate the property while walking a constructor for other purposes. */
+extern bool constructor_static_from_elts_p (const_tree);
+
+extern void init_varasm_status (void);
+
+extern rtx assemble_static_space (unsigned HOST_WIDE_INT);
+
+extern rtx assemble_trampoline_template (void);
+
+#endif // GCC_VARASM_H
diff --git a/support/cpp/gcc/vec-perm-indices.h b/support/cpp/gcc/vec-perm-indices.h
new file mode 100644
index 000000000..e9ef80543
--- /dev/null
+++ b/support/cpp/gcc/vec-perm-indices.h
@@ -0,0 +1,153 @@
+/* A representation of vector permutation indices.
+ Copyright (C) 2017-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_VEC_PERN_INDICES_H
+#define GCC_VEC_PERN_INDICES_H 1
+
+#include "int-vector-builder.h"
+
+/* A vector_builder for building constant permutation vectors.
+ The elements do not need to be clamped to a particular range
+ of input elements. */
+typedef int_vector_builder<poly_int64> vec_perm_builder;
+
+/* This class represents a constant permutation vector, such as that used
+ as the final operand to a VEC_PERM_EXPR.
+
+ Permutation vectors select indices modulo the number of input elements,
+ and the class canonicalizes each permutation vector for a particular
+ number of input vectors and for a particular number of elements per
+ input. For example, the gimple statements:
+
+ _1 = VEC_PERM_EXPR <a, a, { 0, 2, 4, 6, 0, 2, 4, 6 }>;
+ _2 = VEC_PERM_EXPR <a, a, { 0, 2, 4, 6, 8, 10, 12, 14 }>;
+ _3 = VEC_PERM_EXPR <a, a, { 0, 2, 20, 22, 24, 2, 4, 14 }>;
+
+ effectively have only a single vector input "a". If "a" has 8
+ elements, the indices select elements modulo 8, which makes all three
+ VEC_PERM_EXPRs equivalent. The canonical form is for the indices to be
+ in the range [0, number of input elements - 1], so the class treats the
+ second and third permutation vectors as though they had been the first.
+
+ The class copes with cases in which the input and output vectors have
+ different numbers of elements. */
+class vec_perm_indices
+{
+ typedef poly_int64 element_type;
+
+public:
+ vec_perm_indices ();
+ vec_perm_indices (const vec_perm_builder &, unsigned int, poly_uint64);
+
+ void new_vector (const vec_perm_builder &, unsigned int, poly_uint64);
+ void new_expanded_vector (const vec_perm_indices &, unsigned int);
+ bool new_shrunk_vector (const vec_perm_indices &, unsigned int);
+ void rotate_inputs (int delta);
+
+ /* Return the underlying vector encoding. */
+ const vec_perm_builder &encoding () const { return m_encoding; }
+
+ /* Return the number of output elements. This is called length ()
+ so that we present a more vec-like interface. */
+ poly_uint64 length () const { return m_encoding.full_nelts (); }
+
+ /* Return the number of input vectors being permuted. */
+ unsigned int ninputs () const { return m_ninputs; }
+
+ /* Return the number of elements in each input vector. */
+ poly_uint64 nelts_per_input () const { return m_nelts_per_input; }
+
+ /* Return the total number of input elements. */
+ poly_uint64 input_nelts () const { return m_ninputs * m_nelts_per_input; }
+
+ element_type clamp (element_type) const;
+ element_type operator[] (unsigned int i) const;
+ bool series_p (unsigned int, unsigned int, element_type, element_type) const;
+ bool all_in_range_p (element_type, element_type) const;
+ bool all_from_input_p (unsigned int) const;
+
+private:
+ vec_perm_indices (const vec_perm_indices &);
+
+ vec_perm_builder m_encoding;
+ unsigned int m_ninputs;
+ poly_uint64 m_nelts_per_input;
+};
+
+bool tree_to_vec_perm_builder (vec_perm_builder *, tree);
+tree vec_perm_indices_to_tree (tree, const vec_perm_indices &);
+rtx vec_perm_indices_to_rtx (machine_mode, const vec_perm_indices &);
+
+inline
+vec_perm_indices::vec_perm_indices ()
+ : m_ninputs (0),
+ m_nelts_per_input (0)
+{
+}
+
+/* Construct a permutation vector that selects between NINPUTS vector
+ inputs that have NELTS_PER_INPUT elements each. Take the elements of
+ the new vector from ELEMENTS, clamping each one to be in range. */
+
+inline
+vec_perm_indices::vec_perm_indices (const vec_perm_builder &elements,
+ unsigned int ninputs,
+ poly_uint64 nelts_per_input)
+{
+ new_vector (elements, ninputs, nelts_per_input);
+}
+
+/* Return the canonical value for permutation vector element ELT,
+ taking into account the current number of input elements. */
+
+inline vec_perm_indices::element_type
+vec_perm_indices::clamp (element_type elt) const
+{
+ element_type limit = input_nelts (), elem_within_input;
+ HOST_WIDE_INT input;
+ if (!can_div_trunc_p (elt, limit, &input, &elem_within_input))
+ return elt;
+
+ /* Treat negative elements as counting from the end. This only matters
+ if the vector size is not a power of 2. */
+ if (known_lt (elem_within_input, 0))
+ return elem_within_input + limit;
+
+ return elem_within_input;
+}
+
+/* Return the value of vector element I, which might or might not be
+ explicitly encoded. */
+
+inline vec_perm_indices::element_type
+vec_perm_indices::operator[] (unsigned int i) const
+{
+ return clamp (m_encoding.elt (i));
+}
+
+/* Return true if the permutation vector only selects elements from
+ input I. */
+
+inline bool
+vec_perm_indices::all_from_input_p (unsigned int i) const
+{
+ return all_in_range_p (i * m_nelts_per_input, m_nelts_per_input);
+}
+
+#endif
diff --git a/support/cpp/gcc/vec.cc b/support/cpp/gcc/vec.cc
new file mode 100644
index 000000000..af4a5e5d3
--- /dev/null
+++ b/support/cpp/gcc/vec.cc
@@ -0,0 +1,595 @@
+/* Vector API for GNU compiler.
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Nathan Sidwell <nathan@codesourcery.com>
+ Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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 is compiled twice: once for the generator programs
+ once for the compiler. */
+#ifdef GENERATOR_FILE
+#include "bconfig.h"
+#else
+#include "config.h"
+#endif
+
+#include "system.h"
+#include "coretypes.h"
+#include "hash-table.h"
+#include "selftest.h"
+#ifdef GENERATOR_FILE
+#include "errors.h"
+#else
+#include "input.h"
+#include "diagnostic-core.h"
+#endif
+
+/* Vector memory usage. */
+class vec_usage: public mem_usage
+{
+public:
+ /* Default constructor. */
+ vec_usage (): m_items (0), m_items_peak (0), m_element_size (0) {}
+
+ /* Constructor. */
+ vec_usage (size_t allocated, size_t times, size_t peak,
+ size_t items, size_t items_peak, size_t element_size)
+ : mem_usage (allocated, times, peak),
+ m_items (items), m_items_peak (items_peak),
+ m_element_size (element_size) {}
+
+ /* Sum the usage with SECOND usage. */
+ vec_usage
+ operator+ (const vec_usage &second)
+ {
+ return vec_usage (m_allocated + second.m_allocated,
+ m_times + second.m_times,
+ m_peak + second.m_peak,
+ m_items + second.m_items,
+ m_items_peak + second.m_items_peak, 0);
+ }
+
+ /* Dump usage coupled to LOC location, where TOTAL is sum of all rows. */
+ inline void
+ dump (mem_location *loc, mem_usage &total) const
+ {
+ char s[4096];
+ sprintf (s, "%s:%i (%s)", loc->get_trimmed_filename (),
+ loc->m_line, loc->m_function);
+
+ s[48] = '\0';
+
+ fprintf (stderr,
+ "%-48s %10" PRIu64 PRsa (10) ":%4.1f%%" PRsa (9) "%10" PRIu64
+ ":%4.1f%%" PRsa (10) PRsa (10) "\n",
+ s,
+ (uint64_t)m_element_size,
+ SIZE_AMOUNT (m_allocated),
+ m_allocated * 100.0 / total.m_allocated,
+ SIZE_AMOUNT (m_peak), (uint64_t)m_times,
+ m_times * 100.0 / total.m_times,
+ SIZE_AMOUNT (m_items), SIZE_AMOUNT (m_items_peak));
+ }
+
+ /* Dump footer. */
+ inline void
+ dump_footer ()
+ {
+ fprintf (stderr, "%s" PRsa (64) PRsa (25) PRsa (16) "\n",
+ "Total", SIZE_AMOUNT (m_allocated),
+ SIZE_AMOUNT (m_times), SIZE_AMOUNT (m_items));
+ }
+
+ /* Dump header with NAME. */
+ static inline void
+ dump_header (const char *name)
+ {
+ fprintf (stderr, "%-48s %10s%11s%16s%10s%17s%11s\n", name, "sizeof(T)",
+ "Leak", "Peak", "Times", "Leak items", "Peak items");
+ }
+
+ /* Current number of items allocated. */
+ size_t m_items;
+ /* Peak value of number of allocated items. */
+ size_t m_items_peak;
+ /* Size of element of the vector. */
+ size_t m_element_size;
+};
+
+/* Vector memory description. */
+static mem_alloc_description <vec_usage> vec_mem_desc;
+
+/* Account the overhead. */
+
+void
+vec_prefix::register_overhead (void *ptr, size_t elements,
+ size_t element_size MEM_STAT_DECL)
+{
+ vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN, false
+ FINAL_PASS_MEM_STAT);
+ vec_usage *usage
+ = vec_mem_desc.register_instance_overhead (elements * element_size, ptr);
+ usage->m_element_size = element_size;
+ usage->m_items += elements;
+ if (usage->m_items_peak < usage->m_items)
+ usage->m_items_peak = usage->m_items;
+}
+
+/* Notice that the memory allocated for the vector has been freed. */
+
+void
+vec_prefix::release_overhead (void *ptr, size_t size, size_t elements,
+ bool in_dtor MEM_STAT_DECL)
+{
+ if (!vec_mem_desc.contains_descriptor_for_instance (ptr))
+ vec_mem_desc.register_descriptor (ptr, VEC_ORIGIN,
+ false FINAL_PASS_MEM_STAT);
+ vec_usage *usage = vec_mem_desc.release_instance_overhead (ptr, size,
+ in_dtor);
+ usage->m_items -= elements;
+}
+
+/* Calculate the number of slots to reserve a vector, making sure that
+ it is of at least DESIRED size by growing ALLOC exponentially. */
+
+unsigned
+vec_prefix::calculate_allocation_1 (unsigned alloc, unsigned desired)
+{
+ /* We must have run out of room. */
+ gcc_assert (alloc < desired);
+
+ /* Exponential growth. */
+ if (!alloc)
+ alloc = 4;
+ else if (alloc < 16)
+ /* Double when small. */
+ alloc = alloc * 2;
+ else
+ /* Grow slower when large. */
+ alloc = (alloc * 3 / 2);
+
+ /* If this is still too small, set it to the right size. */
+ if (alloc < desired)
+ alloc = desired;
+ return alloc;
+}
+
+/* Dump per-site memory statistics. */
+
+void
+dump_vec_loc_statistics (void)
+{
+ vec_mem_desc.dump (VEC_ORIGIN);
+}
+
+#if CHECKING_P
+/* Report qsort comparator CMP consistency check failure with P1, P2, P3 as
+ witness elements. */
+ATTRIBUTE_NORETURN ATTRIBUTE_COLD
+static void
+qsort_chk_error (const void *p1, const void *p2, const void *p3,
+ sort_r_cmp_fn *cmp, void *data)
+{
+ if (!p3)
+ {
+ int r1 = cmp (p1, p2, data), r2 = cmp (p2, p1, data);
+ error ("qsort comparator not anti-symmetric: %d, %d", r1, r2);
+ }
+ else if (p1 == p2)
+ {
+ int r = cmp (p1, p3, data);
+ error ("qsort comparator non-negative on sorted output: %d", r);
+ }
+ else
+ {
+ int r1 = cmp (p1, p2, data);
+ int r2 = cmp (p2, p3, data);
+ int r3 = cmp (p1, p3, data);
+ error ("qsort comparator not transitive: %d, %d, %d", r1, r2, r3);
+ }
+ internal_error ("qsort checking failed");
+}
+
+/* Verify anti-symmetry and transitivity for comparator CMP on sorted array
+ of N SIZE-sized elements pointed to by BASE. */
+void
+qsort_chk (void *base, size_t n, size_t size, sort_r_cmp_fn *cmp, void *data)
+{
+#if 0
+#define LIM(n) (n)
+#else
+ /* Limit overall time complexity to O(n log n). */
+#define LIM(n) ((n) <= 16 ? (n) : 12 + floor_log2 (n))
+#endif
+#define ELT(i) ((const char *) base + (i) * size)
+#define CMP(i, j) cmp (ELT (i), ELT (j), data)
+#define ERR2(i, j) qsort_chk_error (ELT (i), ELT (j), NULL, cmp, data)
+#define ERR3(i, j, k) qsort_chk_error (ELT (i), ELT (j), ELT (k), cmp, data)
+ size_t i1, i2, i, j;
+ /* This outer loop iterates over maximum spans [i1, i2) such that
+ elements within each span compare equal to each other. */
+ for (i1 = 0; i1 < n; i1 = i2)
+ {
+ /* Position i2 one past last element that compares equal to i1'th. */
+ for (i2 = i1 + 1; i2 < n; i2++)
+ if (CMP (i1, i2))
+ break;
+ else if (CMP (i2, i1))
+ ERR2 (i1, i2);
+ size_t lim1 = LIM (i2 - i1), lim2 = LIM (n - i2);
+ /* Verify that other pairs within current span compare equal. */
+ for (i = i1 + 1; i + 1 < i2; i++)
+ for (j = i + 1; j < i1 + lim1; j++)
+ if (CMP (i, j))
+ ERR3 (i, i1, j);
+ else if (CMP (j, i))
+ ERR2 (i, j);
+ /* Verify that elements within this span compare less than
+ elements beyond the span. */
+ for (i = i1; i < i2; i++)
+ for (j = i2; j < i2 + lim2; j++)
+ if (CMP (i, j) >= 0)
+ ERR3 (i, i1, j);
+ else if (CMP (j, i) <= 0)
+ ERR2 (i, j);
+ }
+#undef ERR3
+#undef ERR2
+#undef CMP
+#undef ELT
+#undef LIM
+}
+#endif /* #if CHECKING_P */
+
+#ifndef GENERATOR_FILE
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests. */
+
+/* Call V.safe_push for all ints from START up to, but not including LIMIT.
+ Helper function for selftests. */
+
+static void
+safe_push_range (vec <int>&v, int start, int limit)
+{
+ for (int i = start; i < limit; i++)
+ v.safe_push (i);
+}
+
+/* Verify forms of initialization. */
+
+static void
+test_init ()
+{
+ {
+ vec<int> v1{ };
+ ASSERT_EQ (0, v1.length ());
+
+ vec<int> v2 (v1);
+ ASSERT_EQ (0, v2.length ());
+ }
+
+ {
+ vec<int> v1 = vec<int>();
+ ASSERT_EQ (0, v1.length ());
+
+ vec<int> v2 = v1;
+ ASSERT_EQ (0, v2.length ());
+ }
+
+ {
+ vec<int> v1 (vNULL);
+ ASSERT_EQ (0, v1.length ());
+ v1.safe_push (1);
+
+ vec<int> v2 (v1);
+ ASSERT_EQ (1, v1.length ());
+ v2.safe_push (1);
+
+ ASSERT_EQ (2, v1.length ());
+ ASSERT_EQ (2, v2.length ());
+ v1.release ();
+ }
+}
+
+/* Verify that vec::quick_push works correctly. */
+
+static void
+test_quick_push ()
+{
+ auto_vec <int> v;
+ ASSERT_EQ (0, v.length ());
+ v.reserve (3);
+ ASSERT_EQ (0, v.length ());
+ ASSERT_TRUE (v.space (3));
+ v.quick_push (5);
+ v.quick_push (6);
+ v.quick_push (7);
+ ASSERT_EQ (3, v.length ());
+ ASSERT_EQ (5, v[0]);
+ ASSERT_EQ (6, v[1]);
+ ASSERT_EQ (7, v[2]);
+}
+
+/* Verify that vec::safe_push works correctly. */
+
+static void
+test_safe_push ()
+{
+ auto_vec <int> v;
+ ASSERT_EQ (0, v.length ());
+ v.safe_push (5);
+ v.safe_push (6);
+ v.safe_push (7);
+ ASSERT_EQ (3, v.length ());
+ ASSERT_EQ (5, v[0]);
+ ASSERT_EQ (6, v[1]);
+ ASSERT_EQ (7, v[2]);
+}
+
+/* Verify that vec::truncate works correctly. */
+
+static void
+test_truncate ()
+{
+ auto_vec <int> v;
+ ASSERT_EQ (0, v.length ());
+ safe_push_range (v, 0, 10);
+ ASSERT_EQ (10, v.length ());
+
+ v.truncate (5);
+ ASSERT_EQ (5, v.length ());
+}
+
+/* Verify that vec::safe_grow_cleared works correctly. */
+
+static void
+test_safe_grow_cleared ()
+{
+ auto_vec <int> v;
+ ASSERT_EQ (0, v.length ());
+ v.safe_grow_cleared (50, true);
+ ASSERT_EQ (50, v.length ());
+ ASSERT_EQ (0, v[0]);
+ ASSERT_EQ (0, v[49]);
+}
+
+/* Verify that vec::pop works correctly. */
+
+static void
+test_pop ()
+{
+ auto_vec <int> v;
+ safe_push_range (v, 5, 20);
+ ASSERT_EQ (15, v.length ());
+
+ int last = v.pop ();
+ ASSERT_EQ (19, last);
+ ASSERT_EQ (14, v.length ());
+}
+
+/* Verify that vec::safe_insert works correctly. */
+
+static void
+test_safe_insert ()
+{
+ auto_vec <int> v;
+ safe_push_range (v, 0, 10);
+ v.safe_insert (5, 42);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (42, v[5]);
+ ASSERT_EQ (5, v[6]);
+ ASSERT_EQ (11, v.length ());
+}
+
+/* Verify that vec::ordered_remove works correctly. */
+
+static void
+test_ordered_remove ()
+{
+ auto_vec <int> v;
+ safe_push_range (v, 0, 10);
+ v.ordered_remove (5);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (6, v[5]);
+ ASSERT_EQ (9, v.length ());
+}
+
+/* Verify that vec::ordered_remove_if works correctly. */
+
+static void
+test_ordered_remove_if (void)
+{
+ auto_vec <int> v;
+ safe_push_range (v, 0, 10);
+ unsigned ix, ix2;
+ int *elem_ptr;
+ VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr,
+ *elem_ptr == 5 || *elem_ptr == 7);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (6, v[5]);
+ ASSERT_EQ (8, v[6]);
+ ASSERT_EQ (8, v.length ());
+
+ v.truncate (0);
+ safe_push_range (v, 0, 10);
+ VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 6,
+ *elem_ptr == 5 || *elem_ptr == 7);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (6, v[5]);
+ ASSERT_EQ (7, v[6]);
+ ASSERT_EQ (9, v.length ());
+
+ v.truncate (0);
+ safe_push_range (v, 0, 10);
+ VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 0, 5,
+ *elem_ptr == 5 || *elem_ptr == 7);
+ VEC_ORDERED_REMOVE_IF_FROM_TO (v, ix, ix2, elem_ptr, 8, 10,
+ *elem_ptr == 5 || *elem_ptr == 7);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (5, v[5]);
+ ASSERT_EQ (6, v[6]);
+ ASSERT_EQ (10, v.length ());
+
+ v.truncate (0);
+ safe_push_range (v, 0, 10);
+ VEC_ORDERED_REMOVE_IF (v, ix, ix2, elem_ptr, *elem_ptr == 5);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (6, v[5]);
+ ASSERT_EQ (7, v[6]);
+ ASSERT_EQ (9, v.length ());
+}
+
+/* Verify that vec::unordered_remove works correctly. */
+
+static void
+test_unordered_remove ()
+{
+ auto_vec <int> v;
+ safe_push_range (v, 0, 10);
+ v.unordered_remove (5);
+ ASSERT_EQ (9, v.length ());
+}
+
+/* Verify that vec::block_remove works correctly. */
+
+static void
+test_block_remove ()
+{
+ auto_vec <int> v;
+ safe_push_range (v, 0, 10);
+ v.block_remove (5, 3);
+ ASSERT_EQ (3, v[3]);
+ ASSERT_EQ (4, v[4]);
+ ASSERT_EQ (8, v[5]);
+ ASSERT_EQ (9, v[6]);
+ ASSERT_EQ (7, v.length ());
+}
+
+/* Comparator for use by test_qsort. */
+
+static int
+reverse_cmp (const void *p_i, const void *p_j)
+{
+ return *(const int *)p_j - *(const int *)p_i;
+}
+
+/* Verify that vec::qsort works correctly. */
+
+static void
+test_qsort ()
+{
+ auto_vec <int> v;
+ safe_push_range (v, 0, 10);
+ v.qsort (reverse_cmp);
+ ASSERT_EQ (9, v[0]);
+ ASSERT_EQ (8, v[1]);
+ ASSERT_EQ (1, v[8]);
+ ASSERT_EQ (0, v[9]);
+ ASSERT_EQ (10, v.length ());
+}
+
+/* Verify that vec::reverse works correctly. */
+
+static void
+test_reverse ()
+{
+ /* Reversing an empty vec ought to be a no-op. */
+ {
+ auto_vec <int> v;
+ ASSERT_EQ (0, v.length ());
+ v.reverse ();
+ ASSERT_EQ (0, v.length ());
+ }
+
+ /* Verify reversing a vec with even length. */
+ {
+ auto_vec <int> v;
+ safe_push_range (v, 0, 4);
+ v.reverse ();
+ ASSERT_EQ (3, v[0]);
+ ASSERT_EQ (2, v[1]);
+ ASSERT_EQ (1, v[2]);
+ ASSERT_EQ (0, v[3]);
+ ASSERT_EQ (4, v.length ());
+ }
+
+ /* Verify reversing a vec with odd length. */
+ {
+ auto_vec <int> v;
+ safe_push_range (v, 0, 3);
+ v.reverse ();
+ ASSERT_EQ (2, v[0]);
+ ASSERT_EQ (1, v[1]);
+ ASSERT_EQ (0, v[2]);
+ ASSERT_EQ (3, v.length ());
+ }
+}
+
+/* A test class that increments a counter every time its dtor is called. */
+
+class count_dtor
+{
+ public:
+ count_dtor (int *counter) : m_counter (counter) {}
+ ~count_dtor () { (*m_counter)++; }
+
+ private:
+ int *m_counter;
+};
+
+/* Verify that auto_delete_vec deletes the elements within it. */
+
+static void
+test_auto_delete_vec ()
+{
+ int dtor_count = 0;
+ {
+ auto_delete_vec <count_dtor> v;
+ v.safe_push (new count_dtor (&dtor_count));
+ v.safe_push (new count_dtor (&dtor_count));
+ }
+ ASSERT_EQ (dtor_count, 2);
+}
+
+/* Run all of the selftests within this file. */
+
+void
+vec_cc_tests ()
+{
+ test_init ();
+ test_quick_push ();
+ test_safe_push ();
+ test_truncate ();
+ test_safe_grow_cleared ();
+ test_pop ();
+ test_safe_insert ();
+ test_ordered_remove ();
+ test_ordered_remove_if ();
+ test_unordered_remove ();
+ test_block_remove ();
+ test_qsort ();
+ test_reverse ();
+ test_auto_delete_vec ();
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+#endif /* #ifndef GENERATOR_FILE */
diff --git a/support/cpp/gcc/vec.h b/support/cpp/gcc/vec.h
new file mode 100644
index 000000000..15d28deb4
--- /dev/null
+++ b/support/cpp/gcc/vec.h
@@ -0,0 +1,2356 @@
+/* Vector API for GNU compiler.
+ Copyright (C) 2004-2022 Free Software Foundation, Inc.
+ Contributed by Nathan Sidwell <nathan@codesourcery.com>
+ Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+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_VEC_H
+#define GCC_VEC_H
+
+/* Some gen* file have no ggc support as the header file gtype-desc.h is
+ missing. Provide these definitions in case ggc.h has not been included.
+ This is not a problem because any code that runs before gengtype is built
+ will never need to use GC vectors.*/
+
+extern void ggc_free (void *);
+extern size_t ggc_round_alloc_size (size_t requested_size);
+extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
+
+/* Templated vector type and associated interfaces.
+
+ The interface functions are typesafe and use inline functions,
+ sometimes backed by out-of-line generic functions. The vectors are
+ designed to interoperate with the GTY machinery.
+
+ There are both 'index' and 'iterate' accessors. The index accessor
+ is implemented by operator[]. The iterator returns a boolean
+ iteration condition and updates the iteration variable passed by
+ reference. Because the iterator will be inlined, the address-of
+ can be optimized away.
+
+ Each operation that increases the number of active elements is
+ available in 'quick' and 'safe' variants. The former presumes that
+ there is sufficient allocated space for the operation to succeed
+ (it dies if there is not). The latter will reallocate the
+ vector, if needed. Reallocation causes an exponential increase in
+ vector size. If you know you will be adding N elements, it would
+ be more efficient to use the reserve operation before adding the
+ elements with the 'quick' operation. This will ensure there are at
+ least as many elements as you ask for, it will exponentially
+ increase if there are too few spare slots. If you want reserve a
+ specific number of slots, but do not want the exponential increase
+ (for instance, you know this is the last allocation), use the
+ reserve_exact operation. You can also create a vector of a
+ specific size from the get go.
+
+ You should prefer the push and pop operations, as they append and
+ remove from the end of the vector. If you need to remove several
+ items in one go, use the truncate operation. The insert and remove
+ operations allow you to change elements in the middle of the
+ vector. There are two remove operations, one which preserves the
+ element ordering 'ordered_remove', and one which does not
+ 'unordered_remove'. The latter function copies the end element
+ into the removed slot, rather than invoke a memmove operation. The
+ 'lower_bound' function will determine where to place an item in the
+ array using insert that will maintain sorted order.
+
+ Vectors are template types with three arguments: the type of the
+ elements in the vector, the allocation strategy, and the physical
+ layout to use
+
+ Four allocation strategies are supported:
+
+ - Heap: allocation is done using malloc/free. This is the
+ default allocation strategy.
+
+ - GC: allocation is done using ggc_alloc/ggc_free.
+
+ - GC atomic: same as GC with the exception that the elements
+ themselves are assumed to be of an atomic type that does
+ not need to be garbage collected. This means that marking
+ routines do not need to traverse the array marking the
+ individual elements. This increases the performance of
+ GC activities.
+
+ Two physical layouts are supported:
+
+ - Embedded: The vector is structured using the trailing array
+ idiom. The last member of the structure is an array of size
+ 1. When the vector is initially allocated, a single memory
+ block is created to hold the vector's control data and the
+ array of elements. These vectors cannot grow without
+ reallocation (see discussion on embeddable vectors below).
+
+ - Space efficient: The vector is structured as a pointer to an
+ embedded vector. This is the default layout. It means that
+ vectors occupy a single word of storage before initial
+ allocation. Vectors are allowed to grow (the internal
+ pointer is reallocated but the main vector instance does not
+ need to relocate).
+
+ The type, allocation and layout are specified when the vector is
+ declared.
+
+ If you need to directly manipulate a vector, then the 'address'
+ accessor will return the address of the start of the vector. Also
+ the 'space' predicate will tell you whether there is spare capacity
+ in the vector. You will not normally need to use these two functions.
+
+ Notes on the different layout strategies
+
+ * Embeddable vectors (vec<T, A, vl_embed>)
+
+ These vectors are suitable to be embedded in other data
+ structures so that they can be pre-allocated in a contiguous
+ memory block.
+
+ Embeddable vectors are implemented using the trailing array
+ idiom, thus they are not resizeable without changing the address
+ of the vector object itself. This means you cannot have
+ variables or fields of embeddable vector type -- always use a
+ pointer to a vector. The one exception is the final field of a
+ structure, which could be a vector type.
+
+ You will have to use the embedded_size & embedded_init calls to
+ create such objects, and they will not be resizeable (so the
+ 'safe' allocation variants are not available).
+
+ Properties of embeddable vectors:
+
+ - The whole vector and control data are allocated in a single
+ contiguous block. It uses the trailing-vector idiom, so
+ allocation must reserve enough space for all the elements
+ in the vector plus its control data.
+ - The vector cannot be re-allocated.
+ - The vector cannot grow nor shrink.
+ - No indirections needed for access/manipulation.
+ - It requires 2 words of storage (prior to vector allocation).
+
+
+ * Space efficient vector (vec<T, A, vl_ptr>)
+
+ These vectors can grow dynamically and are allocated together
+ with their control data. They are suited to be included in data
+ structures. Prior to initial allocation, they only take a single
+ word of storage.
+
+ These vectors are implemented as a pointer to embeddable vectors.
+ The semantics allow for this pointer to be NULL to represent
+ empty vectors. This way, empty vectors occupy minimal space in
+ the structure containing them.
+
+ Properties:
+
+ - The whole vector and control data are allocated in a single
+ contiguous block.
+ - The whole vector may be re-allocated.
+ - Vector data may grow and shrink.
+ - Access and manipulation requires a pointer test and
+ indirection.
+ - It requires 1 word of storage (prior to vector allocation).
+
+ An example of their use would be,
+
+ struct my_struct {
+ // A space-efficient vector of tree pointers in GC memory.
+ vec<tree, va_gc, vl_ptr> v;
+ };
+
+ struct my_struct *s;
+
+ if (s->v.length ()) { we have some contents }
+ s->v.safe_push (decl); // append some decl onto the end
+ for (ix = 0; s->v.iterate (ix, &elt); ix++)
+ { do something with elt }
+*/
+
+/* Support function for statistics. */
+extern void dump_vec_loc_statistics (void);
+
+/* Hashtable mapping vec addresses to descriptors. */
+extern htab_t vec_mem_usage_hash;
+
+/* Control data for vectors. This contains the number of allocated
+ and used slots inside a vector. */
+
+struct vec_prefix
+{
+ /* FIXME - These fields should be private, but we need to cater to
+ compilers that have stricter notions of PODness for types. */
+
+ /* Memory allocation support routines in vec.cc. */
+ void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
+ void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO);
+ static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
+ static unsigned calculate_allocation_1 (unsigned, unsigned);
+
+ /* Note that vec_prefix should be a base class for vec, but we use
+ offsetof() on vector fields of tree structures (e.g.,
+ tree_binfo::base_binfos), and offsetof only supports base types.
+
+ To compensate, we make vec_prefix a field inside vec and make
+ vec a friend class of vec_prefix so it can access its fields. */
+ template <typename, typename, typename> friend struct vec;
+
+ /* The allocator types also need access to our internals. */
+ friend struct va_gc;
+ friend struct va_gc_atomic;
+ friend struct va_heap;
+
+ unsigned m_alloc : 31;
+ unsigned m_using_auto_storage : 1;
+ unsigned m_num;
+};
+
+/* Calculate the number of slots to reserve a vector, making sure that
+ RESERVE slots are free. If EXACT grow exactly, otherwise grow
+ exponentially. PFX is the control data for the vector. */
+
+inline unsigned
+vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
+ bool exact)
+{
+ if (exact)
+ return (pfx ? pfx->m_num : 0) + reserve;
+ else if (!pfx)
+ return MAX (4, reserve);
+ return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
+}
+
+template<typename, typename, typename> struct vec;
+
+/* Valid vector layouts
+
+ vl_embed - Embeddable vector that uses the trailing array idiom.
+ vl_ptr - Space efficient vector that uses a pointer to an
+ embeddable vector. */
+struct vl_embed { };
+struct vl_ptr { };
+
+
+/* Types of supported allocations
+
+ va_heap - Allocation uses malloc/free.
+ va_gc - Allocation uses ggc_alloc.
+ va_gc_atomic - Same as GC, but individual elements of the array
+ do not need to be marked during collection. */
+
+/* Allocator type for heap vectors. */
+struct va_heap
+{
+ /* Heap vectors are frequently regular instances, so use the vl_ptr
+ layout for them. */
+ typedef vl_ptr default_layout;
+
+ template<typename T>
+ static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
+ CXX_MEM_STAT_INFO);
+
+ template<typename T>
+ static void release (vec<T, va_heap, vl_embed> *&);
+};
+
+
+/* Allocator for heap memory. Ensure there are at least RESERVE free
+ slots in V. If EXACT is true, grow exactly, else grow
+ exponentially. As a special case, if the vector had not been
+ allocated and RESERVE is 0, no vector will be created. */
+
+template<typename T>
+inline void
+va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
+ MEM_STAT_DECL)
+{
+ size_t elt_size = sizeof (T);
+ unsigned alloc
+ = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
+ gcc_checking_assert (alloc);
+
+ if (GATHER_STATISTICS && v)
+ v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
+ v->allocated (), false);
+
+ size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
+ unsigned nelem = v ? v->length () : 0;
+ v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
+ v->embedded_init (alloc, nelem);
+
+ if (GATHER_STATISTICS)
+ v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT);
+}
+
+
+#if GCC_VERSION >= 4007
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
+#endif
+
+/* Free the heap space allocated for vector V. */
+
+template<typename T>
+void
+va_heap::release (vec<T, va_heap, vl_embed> *&v)
+{
+ size_t elt_size = sizeof (T);
+ if (v == NULL)
+ return;
+
+ if (GATHER_STATISTICS)
+ v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
+ v->allocated (), true);
+ ::free (v);
+ v = NULL;
+}
+
+#if GCC_VERSION >= 4007
+#pragma GCC diagnostic pop
+#endif
+
+/* Allocator type for GC vectors. Notice that we need the structure
+ declaration even if GC is not enabled. */
+
+struct va_gc
+{
+ /* Use vl_embed as the default layout for GC vectors. Due to GTY
+ limitations, GC vectors must always be pointers, so it is more
+ efficient to use a pointer to the vl_embed layout, rather than
+ using a pointer to a pointer as would be the case with vl_ptr. */
+ typedef vl_embed default_layout;
+
+ template<typename T, typename A>
+ static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
+ CXX_MEM_STAT_INFO);
+
+ template<typename T, typename A>
+ static void release (vec<T, A, vl_embed> *&v);
+};
+
+
+/* Free GC memory used by V and reset V to NULL. */
+
+template<typename T, typename A>
+inline void
+va_gc::release (vec<T, A, vl_embed> *&v)
+{
+ if (v)
+ ::ggc_free (v);
+ v = NULL;
+}
+
+
+/* Allocator for GC memory. Ensure there are at least RESERVE free
+ slots in V. If EXACT is true, grow exactly, else grow
+ exponentially. As a special case, if the vector had not been
+ allocated and RESERVE is 0, no vector will be created. */
+
+template<typename T, typename A>
+void
+va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
+ MEM_STAT_DECL)
+{
+ unsigned alloc
+ = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
+ if (!alloc)
+ {
+ ::ggc_free (v);
+ v = NULL;
+ return;
+ }
+
+ /* Calculate the amount of space we want. */
+ size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
+
+ /* Ask the allocator how much space it will really give us. */
+ size = ::ggc_round_alloc_size (size);
+
+ /* Adjust the number of slots accordingly. */
+ size_t vec_offset = sizeof (vec_prefix);
+ size_t elt_size = sizeof (T);
+ alloc = (size - vec_offset) / elt_size;
+
+ /* And finally, recalculate the amount of space we ask for. */
+ size = vec_offset + alloc * elt_size;
+
+ unsigned nelem = v ? v->length () : 0;
+ v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
+ PASS_MEM_STAT));
+ v->embedded_init (alloc, nelem);
+}
+
+
+/* Allocator type for GC vectors. This is for vectors of types
+ atomics w.r.t. collection, so allocation and deallocation is
+ completely inherited from va_gc. */
+struct va_gc_atomic : va_gc
+{
+};
+
+
+/* Generic vector template. Default values for A and L indicate the
+ most commonly used strategies.
+
+ FIXME - Ideally, they would all be vl_ptr to encourage using regular
+ instances for vectors, but the existing GTY machinery is limited
+ in that it can only deal with GC objects that are pointers
+ themselves.
+
+ This means that vector operations that need to deal with
+ potentially NULL pointers, must be provided as free
+ functions (see the vec_safe_* functions above). */
+template<typename T,
+ typename A = va_heap,
+ typename L = typename A::default_layout>
+struct GTY((user)) vec
+{
+};
+
+/* Allow C++11 range-based 'for' to work directly on vec<T>*. */
+template<typename T, typename A, typename L>
+T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
+template<typename T, typename A, typename L>
+T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; }
+template<typename T, typename A, typename L>
+const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
+template<typename T, typename A, typename L>
+const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; }
+
+/* Generic vec<> debug helpers.
+
+ These need to be instantiated for each vec<TYPE> used throughout
+ the compiler like this:
+
+ DEFINE_DEBUG_VEC (TYPE)
+
+ The reason we have a debug_helper() is because GDB can't
+ disambiguate a plain call to debug(some_vec), and it must be called
+ like debug<TYPE>(some_vec). */
+
+template<typename T>
+void
+debug_helper (vec<T> &ref)
+{
+ unsigned i;
+ for (i = 0; i < ref.length (); ++i)
+ {
+ fprintf (stderr, "[%d] = ", i);
+ debug_slim (ref[i]);
+ fputc ('\n', stderr);
+ }
+}
+
+/* We need a separate va_gc variant here because default template
+ argument for functions cannot be used in c++-98. Once this
+ restriction is removed, those variant should be folded with the
+ above debug_helper. */
+
+template<typename T>
+void
+debug_helper (vec<T, va_gc> &ref)
+{
+ unsigned i;
+ for (i = 0; i < ref.length (); ++i)
+ {
+ fprintf (stderr, "[%d] = ", i);
+ debug_slim (ref[i]);
+ fputc ('\n', stderr);
+ }
+}
+
+/* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper
+ functions for a type T. */
+
+#define DEFINE_DEBUG_VEC(T) \
+ template void debug_helper (vec<T> &); \
+ template void debug_helper (vec<T, va_gc> &); \
+ /* Define the vec<T> debug functions. */ \
+ DEBUG_FUNCTION void \
+ debug (vec<T> &ref) \
+ { \
+ debug_helper <T> (ref); \
+ } \
+ DEBUG_FUNCTION void \
+ debug (vec<T> *ptr) \
+ { \
+ if (ptr) \
+ debug (*ptr); \
+ else \
+ fprintf (stderr, "<nil>\n"); \
+ } \
+ /* Define the vec<T, va_gc> debug functions. */ \
+ DEBUG_FUNCTION void \
+ debug (vec<T, va_gc> &ref) \
+ { \
+ debug_helper <T> (ref); \
+ } \
+ DEBUG_FUNCTION void \
+ debug (vec<T, va_gc> *ptr) \
+ { \
+ if (ptr) \
+ debug (*ptr); \
+ else \
+ fprintf (stderr, "<nil>\n"); \
+ }
+
+/* Default-construct N elements in DST. */
+
+template <typename T>
+inline void
+vec_default_construct (T *dst, unsigned n)
+{
+#ifdef BROKEN_VALUE_INITIALIZATION
+ /* Versions of GCC before 4.4 sometimes leave certain objects
+ uninitialized when value initialized, though if the type has
+ user defined default ctor, that ctor is invoked. As a workaround
+ perform clearing first and then the value initialization, which
+ fixes the case when value initialization doesn't initialize due to
+ the bugs and should initialize to all zeros, but still allows
+ vectors for types with user defined default ctor that initializes
+ some or all elements to non-zero. If T has no user defined
+ default ctor and some non-static data members have user defined
+ default ctors that initialize to non-zero the workaround will
+ still not work properly; in that case we just need to provide
+ user defined default ctor. */
+ memset (dst, '\0', sizeof (T) * n);
+#endif
+ for ( ; n; ++dst, --n)
+ ::new (static_cast<void*>(dst)) T ();
+}
+
+/* Copy-construct N elements in DST from *SRC. */
+
+template <typename T>
+inline void
+vec_copy_construct (T *dst, const T *src, unsigned n)
+{
+ for ( ; n; ++dst, ++src, --n)
+ ::new (static_cast<void*>(dst)) T (*src);
+}
+
+/* Type to provide zero-initialized values for vec<T, A, L>. This is
+ used to provide nil initializers for vec instances. Since vec must
+ be a trivially copyable type that can be copied by memcpy and zeroed
+ out by memset, it must have defaulted default and copy ctor and copy
+ assignment. To initialize a vec either use value initialization
+ (e.g., vec() or vec v{ };) or assign it the value vNULL. This isn't
+ needed for file-scope and function-local static vectors, which are
+ zero-initialized by default. */
+struct vnull { };
+constexpr vnull vNULL{ };
+
+
+/* Embeddable vector. These vectors are suitable to be embedded
+ in other data structures so that they can be pre-allocated in a
+ contiguous memory block.
+
+ Embeddable vectors are implemented using the trailing array idiom,
+ thus they are not resizeable without changing the address of the
+ vector object itself. This means you cannot have variables or
+ fields of embeddable vector type -- always use a pointer to a
+ vector. The one exception is the final field of a structure, which
+ could be a vector type.
+
+ You will have to use the embedded_size & embedded_init calls to
+ create such objects, and they will not be resizeable (so the 'safe'
+ allocation variants are not available).
+
+ Properties:
+
+ - The whole vector and control data are allocated in a single
+ contiguous block. It uses the trailing-vector idiom, so
+ allocation must reserve enough space for all the elements
+ in the vector plus its control data.
+ - The vector cannot be re-allocated.
+ - The vector cannot grow nor shrink.
+ - No indirections needed for access/manipulation.
+ - It requires 2 words of storage (prior to vector allocation). */
+
+template<typename T, typename A>
+struct GTY((user)) vec<T, A, vl_embed>
+{
+public:
+ unsigned allocated (void) const { return m_vecpfx.m_alloc; }
+ unsigned length (void) const { return m_vecpfx.m_num; }
+ bool is_empty (void) const { return m_vecpfx.m_num == 0; }
+ T *address (void) { return m_vecdata; }
+ const T *address (void) const { return m_vecdata; }
+ T *begin () { return address (); }
+ const T *begin () const { return address (); }
+ T *end () { return address () + length (); }
+ const T *end () const { return address () + length (); }
+ const T &operator[] (unsigned) const;
+ T &operator[] (unsigned);
+ T &last (void);
+ bool space (unsigned) const;
+ bool iterate (unsigned, T *) const;
+ bool iterate (unsigned, T **) const;
+ vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
+ void splice (const vec &);
+ void splice (const vec *src);
+ T *quick_push (const T &);
+ T &pop (void);
+ void truncate (unsigned);
+ void quick_insert (unsigned, const T &);
+ void ordered_remove (unsigned);
+ void unordered_remove (unsigned);
+ void block_remove (unsigned, unsigned);
+ void qsort (int (*) (const void *, const void *));
+ void sort (int (*) (const void *, const void *, void *), void *);
+ void stablesort (int (*) (const void *, const void *, void *), void *);
+ T *bsearch (const void *key, int (*compar)(const void *, const void *));
+ T *bsearch (const void *key,
+ int (*compar)(const void *, const void *, void *), void *);
+ unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
+ bool contains (const T &search) const;
+ static size_t embedded_size (unsigned);
+ void embedded_init (unsigned, unsigned = 0, unsigned = 0);
+ void quick_grow (unsigned len);
+ void quick_grow_cleared (unsigned len);
+
+ /* vec class can access our internal data and functions. */
+ template <typename, typename, typename> friend struct vec;
+
+ /* The allocator types also need access to our internals. */
+ friend struct va_gc;
+ friend struct va_gc_atomic;
+ friend struct va_heap;
+
+ /* FIXME - These fields should be private, but we need to cater to
+ compilers that have stricter notions of PODness for types. */
+ vec_prefix m_vecpfx;
+ T m_vecdata[1];
+};
+
+
+/* Convenience wrapper functions to use when dealing with pointers to
+ embedded vectors. Some functionality for these vectors must be
+ provided via free functions for these reasons:
+
+ 1- The pointer may be NULL (e.g., before initial allocation).
+
+ 2- When the vector needs to grow, it must be reallocated, so
+ the pointer will change its value.
+
+ Because of limitations with the current GC machinery, all vectors
+ in GC memory *must* be pointers. */
+
+
+/* If V contains no room for NELEMS elements, return false. Otherwise,
+ return true. */
+template<typename T, typename A>
+inline bool
+vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
+{
+ return v ? v->space (nelems) : nelems == 0;
+}
+
+
+/* If V is NULL, return 0. Otherwise, return V->length(). */
+template<typename T, typename A>
+inline unsigned
+vec_safe_length (const vec<T, A, vl_embed> *v)
+{
+ return v ? v->length () : 0;
+}
+
+
+/* If V is NULL, return NULL. Otherwise, return V->address(). */
+template<typename T, typename A>
+inline T *
+vec_safe_address (vec<T, A, vl_embed> *v)
+{
+ return v ? v->address () : NULL;
+}
+
+
+/* If V is NULL, return true. Otherwise, return V->is_empty(). */
+template<typename T, typename A>
+inline bool
+vec_safe_is_empty (vec<T, A, vl_embed> *v)
+{
+ return v ? v->is_empty () : true;
+}
+
+/* If V does not have space for NELEMS elements, call
+ V->reserve(NELEMS, EXACT). */
+template<typename T, typename A>
+inline bool
+vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
+ CXX_MEM_STAT_INFO)
+{
+ bool extend = nelems ? !vec_safe_space (v, nelems) : false;
+ if (extend)
+ A::reserve (v, nelems, exact PASS_MEM_STAT);
+ return extend;
+}
+
+template<typename T, typename A>
+inline bool
+vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
+ CXX_MEM_STAT_INFO)
+{
+ return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
+}
+
+
+/* Allocate GC memory for V with space for NELEMS slots. If NELEMS
+ is 0, V is initialized to NULL. */
+
+template<typename T, typename A>
+inline void
+vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
+{
+ v = NULL;
+ vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
+}
+
+
+/* Free the GC memory allocated by vector V and set it to NULL. */
+
+template<typename T, typename A>
+inline void
+vec_free (vec<T, A, vl_embed> *&v)
+{
+ A::release (v);
+}
+
+
+/* Grow V to length LEN. Allocate it, if necessary. */
+template<typename T, typename A>
+inline void
+vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len,
+ bool exact = false CXX_MEM_STAT_INFO)
+{
+ unsigned oldlen = vec_safe_length (v);
+ gcc_checking_assert (len >= oldlen);
+ vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT);
+ v->quick_grow (len);
+}
+
+
+/* If V is NULL, allocate it. Call V->safe_grow_cleared(LEN). */
+template<typename T, typename A>
+inline void
+vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len,
+ bool exact = false CXX_MEM_STAT_INFO)
+{
+ unsigned oldlen = vec_safe_length (v);
+ vec_safe_grow (v, len, exact PASS_MEM_STAT);
+ vec_default_construct (v->address () + oldlen, len - oldlen);
+}
+
+
+/* Assume V is not NULL. */
+
+template<typename T>
+inline void
+vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
+ unsigned len, bool exact = false CXX_MEM_STAT_INFO)
+{
+ v->safe_grow_cleared (len, exact PASS_MEM_STAT);
+}
+
+/* If V does not have space for NELEMS elements, call
+ V->reserve(NELEMS, EXACT). */
+
+template<typename T>
+inline bool
+vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
+ CXX_MEM_STAT_INFO)
+{
+ return v->reserve (nelems, exact);
+}
+
+
+/* If V is NULL return false, otherwise return V->iterate(IX, PTR). */
+template<typename T, typename A>
+inline bool
+vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
+{
+ if (v)
+ return v->iterate (ix, ptr);
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+template<typename T, typename A>
+inline bool
+vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
+{
+ if (v)
+ return v->iterate (ix, ptr);
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+
+/* If V has no room for one more element, reallocate it. Then call
+ V->quick_push(OBJ). */
+template<typename T, typename A>
+inline T *
+vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
+{
+ vec_safe_reserve (v, 1, false PASS_MEM_STAT);
+ return v->quick_push (obj);
+}
+
+
+/* if V has no room for one more element, reallocate it. Then call
+ V->quick_insert(IX, OBJ). */
+template<typename T, typename A>
+inline void
+vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
+ CXX_MEM_STAT_INFO)
+{
+ vec_safe_reserve (v, 1, false PASS_MEM_STAT);
+ v->quick_insert (ix, obj);
+}
+
+
+/* If V is NULL, do nothing. Otherwise, call V->truncate(SIZE). */
+template<typename T, typename A>
+inline void
+vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
+{
+ if (v)
+ v->truncate (size);
+}
+
+
+/* If SRC is not NULL, return a pointer to a copy of it. */
+template<typename T, typename A>
+inline vec<T, A, vl_embed> *
+vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
+{
+ return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL;
+}
+
+/* Copy the elements from SRC to the end of DST as if by memcpy.
+ Reallocate DST, if necessary. */
+template<typename T, typename A>
+inline void
+vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
+ CXX_MEM_STAT_INFO)
+{
+ unsigned src_len = vec_safe_length (src);
+ if (src_len)
+ {
+ vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
+ PASS_MEM_STAT);
+ dst->splice (*src);
+ }
+}
+
+/* Return true if SEARCH is an element of V. Note that this is O(N) in the
+ size of the vector and so should be used with care. */
+
+template<typename T, typename A>
+inline bool
+vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
+{
+ return v ? v->contains (search) : false;
+}
+
+/* Index into vector. Return the IX'th element. IX must be in the
+ domain of the vector. */
+
+template<typename T, typename A>
+inline const T &
+vec<T, A, vl_embed>::operator[] (unsigned ix) const
+{
+ gcc_checking_assert (ix < m_vecpfx.m_num);
+ return m_vecdata[ix];
+}
+
+template<typename T, typename A>
+inline T &
+vec<T, A, vl_embed>::operator[] (unsigned ix)
+{
+ gcc_checking_assert (ix < m_vecpfx.m_num);
+ return m_vecdata[ix];
+}
+
+
+/* Get the final element of the vector, which must not be empty. */
+
+template<typename T, typename A>
+inline T &
+vec<T, A, vl_embed>::last (void)
+{
+ gcc_checking_assert (m_vecpfx.m_num > 0);
+ return (*this)[m_vecpfx.m_num - 1];
+}
+
+
+/* If this vector has space for NELEMS additional entries, return
+ true. You usually only need to use this if you are doing your
+ own vector reallocation, for instance on an embedded vector. This
+ returns true in exactly the same circumstances that vec::reserve
+ will. */
+
+template<typename T, typename A>
+inline bool
+vec<T, A, vl_embed>::space (unsigned nelems) const
+{
+ return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
+}
+
+
+/* Return iteration condition and update PTR to point to the IX'th
+ element of this vector. Use this to iterate over the elements of a
+ vector as follows,
+
+ for (ix = 0; vec<T, A>::iterate (v, ix, &ptr); ix++)
+ continue; */
+
+template<typename T, typename A>
+inline bool
+vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
+{
+ if (ix < m_vecpfx.m_num)
+ {
+ *ptr = m_vecdata[ix];
+ return true;
+ }
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+
+/* Return iteration condition and update *PTR to point to the
+ IX'th element of this vector. Use this to iterate over the
+ elements of a vector as follows,
+
+ for (ix = 0; v->iterate (ix, &ptr); ix++)
+ continue;
+
+ This variant is for vectors of objects. */
+
+template<typename T, typename A>
+inline bool
+vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
+{
+ if (ix < m_vecpfx.m_num)
+ {
+ *ptr = CONST_CAST (T *, &m_vecdata[ix]);
+ return true;
+ }
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+
+/* Return a pointer to a copy of this vector. */
+
+template<typename T, typename A>
+inline vec<T, A, vl_embed> *
+vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
+{
+ vec<T, A, vl_embed> *new_vec = NULL;
+ unsigned len = length ();
+ if (len)
+ {
+ vec_alloc (new_vec, len PASS_MEM_STAT);
+ new_vec->embedded_init (len, len);
+ vec_copy_construct (new_vec->address (), m_vecdata, len);
+ }
+ return new_vec;
+}
+
+
+/* Copy the elements from SRC to the end of this vector as if by memcpy.
+ The vector must have sufficient headroom available. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
+{
+ unsigned len = src.length ();
+ if (len)
+ {
+ gcc_checking_assert (space (len));
+ vec_copy_construct (end (), src.address (), len);
+ m_vecpfx.m_num += len;
+ }
+}
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
+{
+ if (src)
+ splice (*src);
+}
+
+
+/* Push OBJ (a new element) onto the end of the vector. There must be
+ sufficient space in the vector. Return a pointer to the slot
+ where OBJ was inserted. */
+
+template<typename T, typename A>
+inline T *
+vec<T, A, vl_embed>::quick_push (const T &obj)
+{
+ gcc_checking_assert (space (1));
+ T *slot = &m_vecdata[m_vecpfx.m_num++];
+ *slot = obj;
+ return slot;
+}
+
+
+/* Pop and return the last element off the end of the vector. */
+
+template<typename T, typename A>
+inline T &
+vec<T, A, vl_embed>::pop (void)
+{
+ gcc_checking_assert (length () > 0);
+ return m_vecdata[--m_vecpfx.m_num];
+}
+
+
+/* Set the length of the vector to SIZE. The new length must be less
+ than or equal to the current length. This is an O(1) operation. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::truncate (unsigned size)
+{
+ gcc_checking_assert (length () >= size);
+ m_vecpfx.m_num = size;
+}
+
+
+/* Insert an element, OBJ, at the IXth position of this vector. There
+ must be sufficient space. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
+{
+ gcc_checking_assert (length () < allocated ());
+ gcc_checking_assert (ix <= length ());
+ T *slot = &m_vecdata[ix];
+ memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
+ *slot = obj;
+}
+
+
+/* Remove an element from the IXth position of this vector. Ordering of
+ remaining elements is preserved. This is an O(N) operation due to
+ memmove. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::ordered_remove (unsigned ix)
+{
+ gcc_checking_assert (ix < length ());
+ T *slot = &m_vecdata[ix];
+ memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
+}
+
+
+/* Remove elements in [START, END) from VEC for which COND holds. Ordering of
+ remaining elements is preserved. This is an O(N) operation. */
+
+#define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index, \
+ elem_ptr, start, end, cond) \
+ { \
+ gcc_assert ((end) <= (vec).length ()); \
+ for (read_index = write_index = (start); read_index < (end); \
+ ++read_index) \
+ { \
+ elem_ptr = &(vec)[read_index]; \
+ bool remove_p = (cond); \
+ if (remove_p) \
+ continue; \
+ \
+ if (read_index != write_index) \
+ (vec)[write_index] = (vec)[read_index]; \
+ \
+ write_index++; \
+ } \
+ \
+ if (read_index - write_index > 0) \
+ (vec).block_remove (write_index, read_index - write_index); \
+ }
+
+
+/* Remove elements from VEC for which COND holds. Ordering of remaining
+ elements is preserved. This is an O(N) operation. */
+
+#define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr, \
+ cond) \
+ VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index, \
+ elem_ptr, 0, (vec).length (), (cond))
+
+/* Remove an element from the IXth position of this vector. Ordering of
+ remaining elements is destroyed. This is an O(1) operation. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::unordered_remove (unsigned ix)
+{
+ gcc_checking_assert (ix < length ());
+ m_vecdata[ix] = m_vecdata[--m_vecpfx.m_num];
+}
+
+
+/* Remove LEN elements starting at the IXth. Ordering is retained.
+ This is an O(N) operation due to memmove. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
+{
+ gcc_checking_assert (ix + len <= length ());
+ T *slot = &m_vecdata[ix];
+ m_vecpfx.m_num -= len;
+ memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
+}
+
+
+/* Sort the contents of this vector with qsort. CMP is the comparison
+ function to pass to qsort. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
+{
+ if (length () > 1)
+ gcc_qsort (address (), length (), sizeof (T), cmp);
+}
+
+/* Sort the contents of this vector with qsort. CMP is the comparison
+ function to pass to qsort. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
+ void *data)
+{
+ if (length () > 1)
+ gcc_sort_r (address (), length (), sizeof (T), cmp, data);
+}
+
+/* Sort the contents of this vector with gcc_stablesort_r. CMP is the
+ comparison function to pass to qsort. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::stablesort (int (*cmp) (const void *, const void *,
+ void *), void *data)
+{
+ if (length () > 1)
+ gcc_stablesort_r (address (), length (), sizeof (T), cmp, data);
+}
+
+/* Search the contents of the sorted vector with a binary search.
+ CMP is the comparison function to pass to bsearch. */
+
+template<typename T, typename A>
+inline T *
+vec<T, A, vl_embed>::bsearch (const void *key,
+ int (*compar) (const void *, const void *))
+{
+ const void *base = this->address ();
+ size_t nmemb = this->length ();
+ size_t size = sizeof (T);
+ /* The following is a copy of glibc stdlib-bsearch.h. */
+ size_t l, u, idx;
+ const void *p;
+ int comparison;
+
+ l = 0;
+ u = nmemb;
+ while (l < u)
+ {
+ idx = (l + u) / 2;
+ p = (const void *) (((const char *) base) + (idx * size));
+ comparison = (*compar) (key, p);
+ if (comparison < 0)
+ u = idx;
+ else if (comparison > 0)
+ l = idx + 1;
+ else
+ return (T *)const_cast<void *>(p);
+ }
+
+ return NULL;
+}
+
+/* Search the contents of the sorted vector with a binary search.
+ CMP is the comparison function to pass to bsearch. */
+
+template<typename T, typename A>
+inline T *
+vec<T, A, vl_embed>::bsearch (const void *key,
+ int (*compar) (const void *, const void *,
+ void *), void *data)
+{
+ const void *base = this->address ();
+ size_t nmemb = this->length ();
+ size_t size = sizeof (T);
+ /* The following is a copy of glibc stdlib-bsearch.h. */
+ size_t l, u, idx;
+ const void *p;
+ int comparison;
+
+ l = 0;
+ u = nmemb;
+ while (l < u)
+ {
+ idx = (l + u) / 2;
+ p = (const void *) (((const char *) base) + (idx * size));
+ comparison = (*compar) (key, p, data);
+ if (comparison < 0)
+ u = idx;
+ else if (comparison > 0)
+ l = idx + 1;
+ else
+ return (T *)const_cast<void *>(p);
+ }
+
+ return NULL;
+}
+
+/* Return true if SEARCH is an element of V. Note that this is O(N) in the
+ size of the vector and so should be used with care. */
+
+template<typename T, typename A>
+inline bool
+vec<T, A, vl_embed>::contains (const T &search) const
+{
+ unsigned int len = length ();
+ for (unsigned int i = 0; i < len; i++)
+ if ((*this)[i] == search)
+ return true;
+
+ return false;
+}
+
+/* Find and return the first position in which OBJ could be inserted
+ without changing the ordering of this vector. LESSTHAN is a
+ function that returns true if the first argument is strictly less
+ than the second. */
+
+template<typename T, typename A>
+unsigned
+vec<T, A, vl_embed>::lower_bound (T obj, bool (*lessthan)(const T &, const T &))
+ const
+{
+ unsigned int len = length ();
+ unsigned int half, middle;
+ unsigned int first = 0;
+ while (len > 0)
+ {
+ half = len / 2;
+ middle = first;
+ middle += half;
+ T middle_elem = (*this)[middle];
+ if (lessthan (middle_elem, obj))
+ {
+ first = middle;
+ ++first;
+ len = len - half - 1;
+ }
+ else
+ len = half;
+ }
+ return first;
+}
+
+
+/* Return the number of bytes needed to embed an instance of an
+ embeddable vec inside another data structure.
+
+ Use these methods to determine the required size and initialization
+ of a vector V of type T embedded within another structure (as the
+ final member):
+
+ size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
+ void v->embedded_init (unsigned alloc, unsigned num);
+
+ These allow the caller to perform the memory allocation. */
+
+template<typename T, typename A>
+inline size_t
+vec<T, A, vl_embed>::embedded_size (unsigned alloc)
+{
+ struct alignas (T) U { char data[sizeof (T)]; };
+ typedef vec<U, A, vl_embed> vec_embedded;
+ typedef typename std::conditional<std::is_standard_layout<T>::value,
+ vec, vec_embedded>::type vec_stdlayout;
+ static_assert (sizeof (vec_stdlayout) == sizeof (vec), "");
+ static_assert (alignof (vec_stdlayout) == alignof (vec), "");
+ return offsetof (vec_stdlayout, m_vecdata) + alloc * sizeof (T);
+}
+
+
+/* Initialize the vector to contain room for ALLOC elements and
+ NUM active elements. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
+{
+ m_vecpfx.m_alloc = alloc;
+ m_vecpfx.m_using_auto_storage = aut;
+ m_vecpfx.m_num = num;
+}
+
+
+/* Grow the vector to a specific length. LEN must be as long or longer than
+ the current length. The new elements are uninitialized. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::quick_grow (unsigned len)
+{
+ gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
+ m_vecpfx.m_num = len;
+}
+
+
+/* Grow the vector to a specific length. LEN must be as long or longer than
+ the current length. The new elements are initialized to zero. */
+
+template<typename T, typename A>
+inline void
+vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
+{
+ unsigned oldlen = length ();
+ size_t growby = len - oldlen;
+ quick_grow (len);
+ if (growby != 0)
+ vec_default_construct (address () + oldlen, growby);
+}
+
+/* Garbage collection support for vec<T, A, vl_embed>. */
+
+template<typename T>
+void
+gt_ggc_mx (vec<T, va_gc> *v)
+{
+ extern void gt_ggc_mx (T &);
+ for (unsigned i = 0; i < v->length (); i++)
+ gt_ggc_mx ((*v)[i]);
+}
+
+template<typename T>
+void
+gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED)
+{
+ /* Nothing to do. Vectors of atomic types wrt GC do not need to
+ be traversed. */
+}
+
+
+/* PCH support for vec<T, A, vl_embed>. */
+
+template<typename T, typename A>
+void
+gt_pch_nx (vec<T, A, vl_embed> *v)
+{
+ extern void gt_pch_nx (T &);
+ for (unsigned i = 0; i < v->length (); i++)
+ gt_pch_nx ((*v)[i]);
+}
+
+template<typename T, typename A>
+void
+gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
+{
+ for (unsigned i = 0; i < v->length (); i++)
+ op (&((*v)[i]), NULL, cookie);
+}
+
+template<typename T, typename A>
+void
+gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
+{
+ extern void gt_pch_nx (T *, gt_pointer_operator, void *);
+ for (unsigned i = 0; i < v->length (); i++)
+ gt_pch_nx (&((*v)[i]), op, cookie);
+}
+
+
+/* Space efficient vector. These vectors can grow dynamically and are
+ allocated together with their control data. They are suited to be
+ included in data structures. Prior to initial allocation, they
+ only take a single word of storage.
+
+ These vectors are implemented as a pointer to an embeddable vector.
+ The semantics allow for this pointer to be NULL to represent empty
+ vectors. This way, empty vectors occupy minimal space in the
+ structure containing them.
+
+ Properties:
+
+ - The whole vector and control data are allocated in a single
+ contiguous block.
+ - The whole vector may be re-allocated.
+ - Vector data may grow and shrink.
+ - Access and manipulation requires a pointer test and
+ indirection.
+ - It requires 1 word of storage (prior to vector allocation).
+
+
+ Limitations:
+
+ These vectors must be PODs because they are stored in unions.
+ (http://en.wikipedia.org/wiki/Plain_old_data_structures).
+ As long as we use C++03, we cannot have constructors nor
+ destructors in classes that are stored in unions. */
+
+template<typename T, size_t N = 0>
+class auto_vec;
+
+template<typename T>
+struct vec<T, va_heap, vl_ptr>
+{
+public:
+ /* Default ctors to ensure triviality. Use value-initialization
+ (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized
+ instance. */
+ vec () = default;
+ vec (const vec &) = default;
+ /* Initialization from the generic vNULL. */
+ vec (vnull): m_vec () { }
+ /* Same as default ctor: vec storage must be released manually. */
+ ~vec () = default;
+
+ /* Defaulted same as copy ctor. */
+ vec& operator= (const vec &) = default;
+
+ /* Prevent implicit conversion from auto_vec. Use auto_vec::to_vec()
+ instead. */
+ template <size_t N>
+ vec (auto_vec<T, N> &) = delete;
+
+ template <size_t N>
+ void operator= (auto_vec<T, N> &) = delete;
+
+ /* Memory allocation and deallocation for the embedded vector.
+ Needed because we cannot have proper ctors/dtors defined. */
+ void create (unsigned nelems CXX_MEM_STAT_INFO);
+ void release (void);
+
+ /* Vector operations. */
+ bool exists (void) const
+ { return m_vec != NULL; }
+
+ bool is_empty (void) const
+ { return /* sdcpp m_vec ? m_vec->is_empty () : */ true; }
+
+ unsigned length (void) const
+ { return m_vec ? m_vec->length () : 0; }
+
+ T *address (void)
+ { return m_vec ? m_vec->m_vecdata : NULL; }
+
+ const T *address (void) const
+ { return m_vec ? m_vec->m_vecdata : NULL; }
+
+ T *begin () { return address (); }
+ const T *begin () const { return address (); }
+ T *end () { return begin () + length (); }
+ const T *end () const { return begin () + length (); }
+ const T &operator[] (unsigned ix) const
+ { return (*m_vec)[ix]; }
+
+ bool operator!=(const vec &other) const
+ { return !(*this == other); }
+
+ bool operator==(const vec &other) const
+ { return address () == other.address (); }
+
+ T &operator[] (unsigned ix)
+ { return (*m_vec)[ix]; }
+
+ T &last (void)
+ { return m_vec->last (); }
+
+ bool space (int nelems) const
+ { return m_vec ? m_vec->space (nelems) : nelems == 0; }
+
+ bool iterate (unsigned ix, T *p) const;
+ bool iterate (unsigned ix, T **p) const;
+ vec copy (ALONE_CXX_MEM_STAT_INFO) const;
+ bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
+ bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
+ void splice (const vec &);
+ void safe_splice (const vec & CXX_MEM_STAT_INFO);
+ T *quick_push (const T &);
+ T *safe_push (const T &CXX_MEM_STAT_INFO);
+ T &pop (void);
+ void truncate (unsigned);
+ void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO);
+ void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO);
+ void quick_grow (unsigned);
+ void quick_grow_cleared (unsigned);
+ void quick_insert (unsigned, const T &);
+ void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
+ void ordered_remove (unsigned);
+ void unordered_remove (unsigned);
+ void block_remove (unsigned, unsigned);
+ void qsort (int (*) (const void *, const void *));
+ void sort (int (*) (const void *, const void *, void *), void *);
+ void stablesort (int (*) (const void *, const void *, void *), void *);
+ T *bsearch (const void *key, int (*compar)(const void *, const void *));
+ T *bsearch (const void *key,
+ int (*compar)(const void *, const void *, void *), void *);
+ unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
+ bool contains (const T &search) const;
+ void reverse (void);
+
+ bool using_auto_storage () const;
+
+ /* FIXME - This field should be private, but we need to cater to
+ compilers that have stricter notions of PODness for types. */
+ vec<T, va_heap, vl_embed> *m_vec;
+};
+
+
+/* auto_vec is a subclass of vec that automatically manages creating and
+ releasing the internal vector. If N is non zero then it has N elements of
+ internal storage. The default is no internal storage, and you probably only
+ want to ask for internal storage for vectors on the stack because if the
+ size of the vector is larger than the internal storage that space is wasted.
+ */
+template<typename T, size_t N /* = 0 */>
+class auto_vec : public vec<T, va_heap>
+{
+public:
+ auto_vec ()
+ {
+ m_auto.embedded_init (MAX (N, 2), 0, 1);
+ this->m_vec = &m_auto;
+ }
+
+ auto_vec (size_t s CXX_MEM_STAT_INFO)
+ {
+ if (s > N)
+ {
+ this->create (s PASS_MEM_STAT);
+ return;
+ }
+
+ m_auto.embedded_init (MAX (N, 2), 0, 1);
+ this->m_vec = &m_auto;
+ }
+
+ ~auto_vec ()
+ {
+ this->release ();
+ }
+
+ /* Explicitly convert to the base class. There is no conversion
+ from a const auto_vec because a copy of the returned vec can
+ be used to modify *THIS.
+ This is a legacy function not to be used in new code. */
+ vec<T, va_heap> to_vec_legacy () {
+ return *static_cast<vec<T, va_heap> *>(this);
+ }
+
+private:
+ vec<T, va_heap, vl_embed> m_auto;
+ T m_data[MAX (N - 1, 1)];
+};
+
+/* auto_vec is a sub class of vec whose storage is released when it is
+ destroyed. */
+template<typename T>
+class auto_vec<T, 0> : public vec<T, va_heap>
+{
+public:
+ auto_vec () { this->m_vec = NULL; }
+ auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); }
+ ~auto_vec () { this->release (); }
+
+ auto_vec (vec<T, va_heap>&& r)
+ {
+ gcc_assert (!r.using_auto_storage ());
+ this->m_vec = r.m_vec;
+ r.m_vec = NULL;
+ }
+
+ auto_vec (auto_vec<T> &&r)
+ {
+ gcc_assert (!r.using_auto_storage ());
+ this->m_vec = r.m_vec;
+ r.m_vec = NULL;
+ }
+
+ auto_vec& operator= (vec<T, va_heap>&& r)
+ {
+ if (this == &r)
+ return *this;
+
+ gcc_assert (!r.using_auto_storage ());
+ this->release ();
+ this->m_vec = r.m_vec;
+ r.m_vec = NULL;
+ return *this;
+ }
+
+ auto_vec& operator= (auto_vec<T> &&r)
+ {
+ if (this == &r)
+ return *this;
+
+ gcc_assert (!r.using_auto_storage ());
+ this->release ();
+ this->m_vec = r.m_vec;
+ r.m_vec = NULL;
+ return *this;
+ }
+
+ /* Explicitly convert to the base class. There is no conversion
+ from a const auto_vec because a copy of the returned vec can
+ be used to modify *THIS.
+ This is a legacy function not to be used in new code. */
+ vec<T, va_heap> to_vec_legacy () {
+ return *static_cast<vec<T, va_heap> *>(this);
+ }
+
+ // You probably don't want to copy a vector, so these are deleted to prevent
+ // unintentional use. If you really need a copy of the vectors contents you
+ // can use copy ().
+ auto_vec(const auto_vec &) = delete;
+ auto_vec &operator= (const auto_vec &) = delete;
+};
+
+
+/* Allocate heap memory for pointer V and create the internal vector
+ with space for NELEMS elements. If NELEMS is 0, the internal
+ vector is initialized to empty. */
+
+template<typename T>
+inline void
+vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
+{
+ v = new vec<T>;
+ v->create (nelems PASS_MEM_STAT);
+}
+
+
+/* A subclass of auto_vec <char *> that frees all of its elements on
+ deletion. */
+
+class auto_string_vec : public auto_vec <char *>
+{
+ public:
+ ~auto_string_vec ();
+};
+
+/* A subclass of auto_vec <T *> that deletes all of its elements on
+ destruction.
+
+ This is a crude way for a vec to "own" the objects it points to
+ and clean up automatically.
+
+ For example, no attempt is made to delete elements when an item
+ within the vec is overwritten.
+
+ We can't rely on gnu::unique_ptr within a container,
+ since we can't rely on move semantics in C++98. */
+
+template <typename T>
+class auto_delete_vec : public auto_vec <T *>
+{
+ public:
+ auto_delete_vec () {}
+ auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
+
+ ~auto_delete_vec ();
+
+private:
+ DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
+};
+
+/* Conditionally allocate heap memory for VEC and its internal vector. */
+
+template<typename T>
+inline void
+vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
+{
+ if (!vec)
+ vec_alloc (vec, nelems PASS_MEM_STAT);
+}
+
+
+/* Free the heap memory allocated by vector V and set it to NULL. */
+
+template<typename T>
+inline void
+vec_free (vec<T> *&v)
+{
+ if (v == NULL)
+ return;
+
+ v->release ();
+ delete v;
+ v = NULL;
+}
+
+
+/* Return iteration condition and update PTR to point to the IX'th
+ element of this vector. Use this to iterate over the elements of a
+ vector as follows,
+
+ for (ix = 0; v.iterate (ix, &ptr); ix++)
+ continue; */
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
+{
+ if (m_vec)
+ return m_vec->iterate (ix, ptr);
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+
+/* Return iteration condition and update *PTR to point to the
+ IX'th element of this vector. Use this to iterate over the
+ elements of a vector as follows,
+
+ for (ix = 0; v->iterate (ix, &ptr); ix++)
+ continue;
+
+ This variant is for vectors of objects. */
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
+{
+ if (m_vec)
+ return m_vec->iterate (ix, ptr);
+ else
+ {
+ *ptr = 0;
+ return false;
+ }
+}
+
+
+/* Convenience macro for forward iteration. */
+#define FOR_EACH_VEC_ELT(V, I, P) \
+ for (I = 0; (V).iterate ((I), &(P)); ++(I))
+
+#define FOR_EACH_VEC_SAFE_ELT(V, I, P) \
+ for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
+
+/* Likewise, but start from FROM rather than 0. */
+#define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM) \
+ for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
+
+/* Convenience macro for reverse iteration. */
+#define FOR_EACH_VEC_ELT_REVERSE(V, I, P) \
+ for (I = (V).length () - 1; \
+ (V).iterate ((I), &(P)); \
+ (I)--)
+
+#define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P) \
+ for (I = vec_safe_length (V) - 1; \
+ vec_safe_iterate ((V), (I), &(P)); \
+ (I)--)
+
+/* auto_string_vec's dtor, freeing all contained strings, automatically
+ chaining up to ~auto_vec <char *>, which frees the internal buffer. */
+
+inline
+auto_string_vec::~auto_string_vec ()
+{
+ int i;
+ char *str;
+ FOR_EACH_VEC_ELT (*this, i, str)
+ free (str);
+}
+
+/* auto_delete_vec's dtor, deleting all contained items, automatically
+ chaining up to ~auto_vec <T*>, which frees the internal buffer. */
+
+template <typename T>
+inline
+auto_delete_vec<T>::~auto_delete_vec ()
+{
+ int i;
+ T *item;
+ FOR_EACH_VEC_ELT (*this, i, item)
+ delete item;
+}
+
+
+/* Return a copy of this vector. */
+
+template<typename T>
+inline vec<T, va_heap, vl_ptr>
+vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
+{
+ vec<T, va_heap, vl_ptr> new_vec{ };
+ if (length ())
+ new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
+ return new_vec;
+}
+
+
+/* Ensure that the vector has at least RESERVE slots available (if
+ EXACT is false), or exactly RESERVE slots available (if EXACT is
+ true).
+
+ This may create additional headroom if EXACT is false.
+
+ Note that this can cause the embedded vector to be reallocated.
+ Returns true iff reallocation actually occurred. */
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
+{
+ if (space (nelems))
+ return false;
+
+ /* For now play a game with va_heap::reserve to hide our auto storage if any,
+ this is necessary because it doesn't have enough information to know the
+ embedded vector is in auto storage, and so should not be freed. */
+ vec<T, va_heap, vl_embed> *oldvec = m_vec;
+ unsigned int oldsize = 0;
+ bool handle_auto_vec = m_vec && using_auto_storage ();
+ if (handle_auto_vec)
+ {
+ m_vec = NULL;
+ oldsize = oldvec->length ();
+ nelems += oldsize;
+ }
+
+ va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
+ if (handle_auto_vec)
+ {
+ vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
+ m_vec->m_vecpfx.m_num = oldsize;
+ }
+
+ return true;
+}
+
+
+/* Ensure that this vector has exactly NELEMS slots available. This
+ will not create additional headroom. Note this can cause the
+ embedded vector to be reallocated. Returns true iff reallocation
+ actually occurred. */
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
+{
+ return reserve (nelems, true PASS_MEM_STAT);
+}
+
+
+/* Create the internal vector and reserve NELEMS for it. This is
+ exactly like vec::reserve, but the internal vector is
+ unconditionally allocated from scratch. The old one, if it
+ existed, is lost. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
+{
+ m_vec = NULL;
+ if (nelems > 0)
+ reserve_exact (nelems PASS_MEM_STAT);
+}
+
+
+/* Free the memory occupied by the embedded vector. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::release (void)
+{
+ if (!m_vec)
+ return;
+
+ if (using_auto_storage ())
+ {
+ m_vec->m_vecpfx.m_num = 0;
+ return;
+ }
+
+ va_heap::release (m_vec);
+}
+
+/* Copy the elements from SRC to the end of this vector as if by memcpy.
+ SRC and this vector must be allocated with the same memory
+ allocation mechanism. This vector is assumed to have sufficient
+ headroom available. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
+{
+ if (src.length ())
+ m_vec->splice (*(src.m_vec));
+}
+
+
+/* Copy the elements in SRC to the end of this vector as if by memcpy.
+ SRC and this vector must be allocated with the same mechanism.
+ If there is not enough headroom in this vector, it will be reallocated
+ as needed. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
+ MEM_STAT_DECL)
+{
+ if (src.length ())
+ {
+ reserve_exact (src.length ());
+ splice (src);
+ }
+}
+
+
+/* Push OBJ (a new element) onto the end of the vector. There must be
+ sufficient space in the vector. Return a pointer to the slot
+ where OBJ was inserted. */
+
+template<typename T>
+inline T *
+vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
+{
+ return m_vec->quick_push (obj);
+}
+
+
+/* Push a new element OBJ onto the end of this vector. Reallocates
+ the embedded vector, if needed. Return a pointer to the slot where
+ OBJ was inserted. */
+
+template<typename T>
+inline T *
+vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
+{
+ reserve (1, false PASS_MEM_STAT);
+ return quick_push (obj);
+}
+
+
+/* Pop and return the last element off the end of the vector. */
+
+template<typename T>
+inline T &
+vec<T, va_heap, vl_ptr>::pop (void)
+{
+ return m_vec->pop ();
+}
+
+
+/* Set the length of the vector to LEN. The new length must be less
+ than or equal to the current length. This is an O(1) operation. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::truncate (unsigned size)
+{
+ if (m_vec)
+ m_vec->truncate (size);
+ else
+ gcc_checking_assert (size == 0);
+}
+
+
+/* Grow the vector to a specific length. LEN must be as long or
+ longer than the current length. The new elements are
+ uninitialized. Reallocate the internal vector, if needed. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL)
+{
+ unsigned oldlen = length ();
+ gcc_checking_assert (oldlen <= len);
+ reserve (len - oldlen, exact PASS_MEM_STAT);
+ if (m_vec)
+ m_vec->quick_grow (len);
+ else
+ gcc_checking_assert (len == 0);
+}
+
+
+/* Grow the embedded vector to a specific length. LEN must be as
+ long or longer than the current length. The new elements are
+ initialized to zero. Reallocate the internal vector, if needed. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact
+ MEM_STAT_DECL)
+{
+ unsigned oldlen = length ();
+ size_t growby = len - oldlen;
+ safe_grow (len, exact PASS_MEM_STAT);
+ if (growby != 0)
+ vec_default_construct (address () + oldlen, growby);
+}
+
+
+/* Same as vec::safe_grow but without reallocation of the internal vector.
+ If the vector cannot be extended, a runtime assertion will be triggered. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
+{
+ gcc_checking_assert (m_vec);
+ m_vec->quick_grow (len);
+}
+
+
+/* Same as vec::quick_grow_cleared but without reallocation of the
+ internal vector. If the vector cannot be extended, a runtime
+ assertion will be triggered. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
+{
+ gcc_checking_assert (m_vec);
+ m_vec->quick_grow_cleared (len);
+}
+
+
+/* Insert an element, OBJ, at the IXth position of this vector. There
+ must be sufficient space. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
+{
+ m_vec->quick_insert (ix, obj);
+}
+
+
+/* Insert an element, OBJ, at the IXth position of the vector.
+ Reallocate the embedded vector, if necessary. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
+{
+ reserve (1, false PASS_MEM_STAT);
+ quick_insert (ix, obj);
+}
+
+
+/* Remove an element from the IXth position of this vector. Ordering of
+ remaining elements is preserved. This is an O(N) operation due to
+ a memmove. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
+{
+ m_vec->ordered_remove (ix);
+}
+
+
+/* Remove an element from the IXth position of this vector. Ordering
+ of remaining elements is destroyed. This is an O(1) operation. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
+{
+ m_vec->unordered_remove (ix);
+}
+
+
+/* Remove LEN elements starting at the IXth. Ordering is retained.
+ This is an O(N) operation due to memmove. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
+{
+ m_vec->block_remove (ix, len);
+}
+
+
+/* Sort the contents of this vector with qsort. CMP is the comparison
+ function to pass to qsort. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
+{
+ if (m_vec)
+ m_vec->qsort (cmp);
+}
+
+/* Sort the contents of this vector with qsort. CMP is the comparison
+ function to pass to qsort. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
+ void *), void *data)
+{
+ if (m_vec)
+ m_vec->sort (cmp, data);
+}
+
+/* Sort the contents of this vector with gcc_stablesort_r. CMP is the
+ comparison function to pass to qsort. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::stablesort (int (*cmp) (const void *, const void *,
+ void *), void *data)
+{
+ if (m_vec)
+ m_vec->stablesort (cmp, data);
+}
+
+/* Search the contents of the sorted vector with a binary search.
+ CMP is the comparison function to pass to bsearch. */
+
+template<typename T>
+inline T *
+vec<T, va_heap, vl_ptr>::bsearch (const void *key,
+ int (*cmp) (const void *, const void *))
+{
+ if (m_vec)
+ return m_vec->bsearch (key, cmp);
+ return NULL;
+}
+
+/* Search the contents of the sorted vector with a binary search.
+ CMP is the comparison function to pass to bsearch. */
+
+template<typename T>
+inline T *
+vec<T, va_heap, vl_ptr>::bsearch (const void *key,
+ int (*cmp) (const void *, const void *,
+ void *), void *data)
+{
+ if (m_vec)
+ return m_vec->bsearch (key, cmp, data);
+ return NULL;
+}
+
+
+/* Find and return the first position in which OBJ could be inserted
+ without changing the ordering of this vector. LESSTHAN is a
+ function that returns true if the first argument is strictly less
+ than the second. */
+
+template<typename T>
+inline unsigned
+vec<T, va_heap, vl_ptr>::lower_bound (T obj,
+ bool (*lessthan)(const T &, const T &))
+ const
+{
+ return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
+}
+
+/* Return true if SEARCH is an element of V. Note that this is O(N) in the
+ size of the vector and so should be used with care. */
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::contains (const T &search) const
+{
+ return m_vec ? m_vec->contains (search) : false;
+}
+
+/* Reverse content of the vector. */
+
+template<typename T>
+inline void
+vec<T, va_heap, vl_ptr>::reverse (void)
+{
+ unsigned l = length ();
+ T *ptr = address ();
+
+ for (unsigned i = 0; i < l / 2; i++)
+ std::swap (ptr[i], ptr[l - i - 1]);
+}
+
+template<typename T>
+inline bool
+vec<T, va_heap, vl_ptr>::using_auto_storage () const
+{
+ return m_vec ? m_vec->m_vecpfx.m_using_auto_storage : false;
+}
+
+/* Release VEC and call release of all element vectors. */
+
+template<typename T>
+inline void
+release_vec_vec (vec<vec<T> > &vec)
+{
+ for (unsigned i = 0; i < vec.length (); i++)
+ vec[i].release ();
+
+ vec.release ();
+}
+
+// Provide a subset of the std::span functionality. (We can't use std::span
+// itself because it's a C++20 feature.)
+//
+// In addition, provide an invalid value that is distinct from all valid
+// sequences (including the empty sequence). This can be used to return
+// failure without having to use std::optional.
+//
+// There is no operator bool because it would be ambiguous whether it is
+// testing for a valid value or an empty sequence.
+template<typename T>
+class array_slice
+{
+ template<typename OtherT> friend class array_slice;
+
+public:
+ using value_type = T;
+ using iterator = T *;
+ using const_iterator = const T *;
+
+ array_slice () : m_base (nullptr), m_size (0) {}
+
+ template<typename OtherT>
+ array_slice (array_slice<OtherT> other)
+ : m_base (other.m_base), m_size (other.m_size) {}
+
+ array_slice (iterator base, unsigned int size)
+ : m_base (base), m_size (size) {}
+
+ template<size_t N>
+ array_slice (T (&array)[N]) : m_base (array), m_size (N) {}
+
+ template<typename OtherT>
+ array_slice (const vec<OtherT> &v)
+ : m_base (v.address ()), m_size (v.length ()) {}
+
+ iterator begin () { return m_base; }
+ iterator end () { return m_base + m_size; }
+
+ const_iterator begin () const { return m_base; }
+ const_iterator end () const { return m_base + m_size; }
+
+ value_type &front ();
+ value_type &back ();
+ value_type &operator[] (unsigned int i);
+
+ const value_type &front () const;
+ const value_type &back () const;
+ const value_type &operator[] (unsigned int i) const;
+
+ size_t size () const { return m_size; }
+ size_t size_bytes () const { return m_size * sizeof (T); }
+ bool empty () const { return m_size == 0; }
+
+ // An invalid array_slice that represents a failed operation. This is
+ // distinct from an empty slice, which is a valid result in some contexts.
+ static array_slice invalid () { return { nullptr, ~0U }; }
+
+ // True if the array is valid, false if it is an array like INVALID.
+ bool is_valid () const { return m_base || m_size == 0; }
+
+private:
+ iterator m_base;
+ unsigned int m_size;
+};
+
+template<typename T>
+inline typename array_slice<T>::value_type &
+array_slice<T>::front ()
+{
+ gcc_checking_assert (m_size);
+ return m_base[0];
+}
+
+template<typename T>
+inline const typename array_slice<T>::value_type &
+array_slice<T>::front () const
+{
+ gcc_checking_assert (m_size);
+ return m_base[0];
+}
+
+template<typename T>
+inline typename array_slice<T>::value_type &
+array_slice<T>::back ()
+{
+ gcc_checking_assert (m_size);
+ return m_base[m_size - 1];
+}
+
+template<typename T>
+inline const typename array_slice<T>::value_type &
+array_slice<T>::back () const
+{
+ gcc_checking_assert (m_size);
+ return m_base[m_size - 1];
+}
+
+template<typename T>
+inline typename array_slice<T>::value_type &
+array_slice<T>::operator[] (unsigned int i)
+{
+ gcc_checking_assert (i < m_size);
+ return m_base[i];
+}
+
+template<typename T>
+inline const typename array_slice<T>::value_type &
+array_slice<T>::operator[] (unsigned int i) const
+{
+ gcc_checking_assert (i < m_size);
+ return m_base[i];
+}
+
+template<typename T>
+array_slice<T>
+make_array_slice (T *base, unsigned int size)
+{
+ return array_slice<T> (base, size);
+}
+
+#if (GCC_VERSION >= 3000)
+# pragma GCC poison m_vec m_vecpfx m_vecdata
+#endif
+
+#endif // GCC_VEC_H
diff --git a/support/cpp/gcc/vector-builder.h b/support/cpp/gcc/vector-builder.h
new file mode 100644
index 000000000..6e917063d
--- /dev/null
+++ b/support/cpp/gcc/vector-builder.h
@@ -0,0 +1,612 @@
+/* A class for building vector constant patterns.
+ Copyright (C) 2017-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/>. */
+
+#if 0 // sdcpp ndef GCC_VECTOR_BUILDER_H
+#define GCC_VECTOR_BUILDER_H
+
+/* This class is a wrapper around auto_vec<T> for building vectors of T.
+ It aims to encode each vector as npatterns interleaved patterns,
+ where each pattern represents a sequence:
+
+ { BASE0, BASE1, BASE1 + STEP, BASE1 + STEP*2, BASE1 + STEP*3, ... }
+
+ The first three elements in each pattern provide enough information
+ to derive the other elements. If all patterns have a STEP of zero,
+ we only need to encode the first two elements in each pattern.
+ If BASE1 is also equal to BASE0 for all patterns, we only need to
+ encode the first element in each pattern. The number of encoded
+ elements per pattern is given by nelts_per_pattern.
+
+ The class can be used in two ways:
+
+ 1. It can be used to build a full image of the vector, which is then
+ canonicalized by finalize (). In this case npatterns is initially
+ the number of elements in the vector and nelts_per_pattern is
+ initially 1.
+
+ 2. It can be used to build a vector that already has a known encoding.
+ This is preferred since it is more efficient and copes with
+ variable-length vectors. finalize () then canonicalizes the encoding
+ to a simpler form if possible.
+
+ Shape is the type that specifies the number of elements in the vector
+ and (where relevant) the type of each element.
+
+ The derived class Derived provides the functionality of this class
+ for specific Ts. Derived needs to provide the following interface:
+
+ bool equal_p (T elt1, T elt2) const;
+
+ Return true if elements ELT1 and ELT2 are equal.
+
+ bool allow_steps_p () const;
+
+ Return true if a stepped representation is OK. We don't allow
+ linear series for anything other than integers, to avoid problems
+ with rounding.
+
+ bool integral_p (T elt) const;
+
+ Return true if element ELT can be interpreted as an integer.
+
+ StepType step (T elt1, T elt2) const;
+
+ Return the value of element ELT2 minus the value of element ELT1,
+ given integral_p (ELT1) && integral_p (ELT2). There is no fixed
+ choice of StepType.
+
+ T apply_step (T base, unsigned int factor, StepType step) const;
+
+ Return a vector element with the value BASE + FACTOR * STEP.
+
+ bool can_elide_p (T elt) const;
+
+ Return true if we can drop element ELT, even if the retained
+ elements are different. This is provided for TREE_OVERFLOW
+ handling.
+
+ void note_representative (T *elt1_ptr, T elt2);
+
+ Record that ELT2 is being elided, given that ELT1_PTR points to
+ the last encoded element for the containing pattern. This is
+ again provided for TREE_OVERFLOW handling.
+
+ static poly_uint64 shape_nelts (Shape shape);
+
+ Return the number of elements in SHAPE.
+
+ The class provides additional functionality for the case in which
+ T can describe a vector constant as well as an individual element.
+ This functionality requires:
+
+ static poly_uint64 nelts_of (T x);
+
+ Return the number of elements in vector constant X.
+
+ static unsigned int npatterns_of (T x);
+
+ Return the number of patterns used to encode vector constant X.
+
+ static unsigned int nelts_per_pattern_of (T x);
+
+ Return the number of elements used to encode each pattern
+ in vector constant X. */
+
+template<typename T, typename Shape, typename Derived>
+class vector_builder : public auto_vec<T, 32>
+{
+public:
+ vector_builder ();
+
+ // sdcpp poly_uint64 full_nelts () const { return m_full_nelts; }
+ unsigned int npatterns () const { return m_npatterns; }
+ unsigned int nelts_per_pattern () const { return m_nelts_per_pattern; }
+ unsigned int encoded_nelts () const;
+ bool encoded_full_vector_p () const;
+ T elt (unsigned int) const;
+ unsigned int count_dups (int, int, int) const;
+
+ bool operator == (const Derived &) const;
+ bool operator != (const Derived &x) const { return !operator == (x); }
+
+ bool new_unary_operation (Shape, T, bool);
+ bool new_binary_operation (Shape, T, T, bool);
+
+ void finalize ();
+
+ static unsigned int binary_encoded_nelts (T, T);
+
+protected:
+ // sdcpp void new_vector (poly_uint64, unsigned int, unsigned int);
+ void reshape (unsigned int, unsigned int);
+ bool repeating_sequence_p (unsigned int, unsigned int, unsigned int);
+ bool stepped_sequence_p (unsigned int, unsigned int, unsigned int);
+ bool try_npatterns (unsigned int);
+
+private:
+ vector_builder (const vector_builder &);
+ vector_builder &operator= (const vector_builder &);
+ Derived *derived () { return static_cast<Derived *> (this); }
+ const Derived *derived () const;
+
+ // sdcpp poly_uint64 m_full_nelts;
+ unsigned int m_npatterns;
+ unsigned int m_nelts_per_pattern;
+};
+
+template<typename T, typename Shape, typename Derived>
+inline const Derived *
+vector_builder<T, Shape, Derived>::derived () const
+{
+ return static_cast<const Derived *> (this);
+}
+
+template<typename T, typename Shape, typename Derived>
+inline
+vector_builder<T, Shape, Derived>::vector_builder ()
+ : // sdcpp m_full_nelts (0),
+ m_npatterns (0),
+ m_nelts_per_pattern (0)
+{}
+
+/* Return the number of elements that are explicitly encoded. The vec
+ starts with these explicitly-encoded elements and may contain additional
+ elided elements. */
+
+template<typename T, typename Shape, typename Derived>
+inline unsigned int
+vector_builder<T, Shape, Derived>::encoded_nelts () const
+{
+ return m_npatterns * m_nelts_per_pattern;
+}
+
+/* Return true if every element of the vector is explicitly encoded. */
+
+template<typename T, typename Shape, typename Derived>
+inline bool
+vector_builder<T, Shape, Derived>::encoded_full_vector_p () const
+{
+ return known_eq (m_npatterns * m_nelts_per_pattern, m_full_nelts);
+}
+
+/* Start building a vector that has FULL_NELTS elements. Initially
+ encode it using NPATTERNS patterns with NELTS_PER_PATTERN each. */
+
+template<typename T, typename Shape, typename Derived>
+void
+vector_builder<T, Shape, Derived>::new_vector (poly_uint64 full_nelts,
+ unsigned int npatterns,
+ unsigned int nelts_per_pattern)
+{
+ m_full_nelts = full_nelts;
+ m_npatterns = npatterns;
+ m_nelts_per_pattern = nelts_per_pattern;
+ this->reserve (encoded_nelts ());
+ this->truncate (0);
+}
+
+/* Return true if this vector and OTHER have the same elements and
+ are encoded in the same way. */
+
+template<typename T, typename Shape, typename Derived>
+bool
+vector_builder<T, Shape, Derived>::operator == (const Derived &other) const
+{
+ if (maybe_ne (m_full_nelts, other.m_full_nelts)
+ || m_npatterns != other.m_npatterns
+ || m_nelts_per_pattern != other.m_nelts_per_pattern)
+ return false;
+
+ unsigned int nelts = encoded_nelts ();
+ for (unsigned int i = 0; i < nelts; ++i)
+ if (!derived ()->equal_p ((*this)[i], other[i]))
+ return false;
+
+ return true;
+}
+
+/* Return the value of vector element I, which might or might not be
+ encoded explicitly. */
+
+template<typename T, typename Shape, typename Derived>
+T
+vector_builder<T, Shape, Derived>::elt (unsigned int i) const
+{
+ /* First handle elements that are already present in the underlying
+ vector, regardless of whether they're part of the encoding or not. */
+ if (i < this->length ())
+ return (*this)[i];
+
+ /* Extrapolation is only possible if the encoding has been fully
+ populated. */
+ gcc_checking_assert (encoded_nelts () <= this->length ());
+
+ /* Identify the pattern that contains element I and work out the index of
+ the last encoded element for that pattern. */
+ unsigned int pattern = i % m_npatterns;
+ unsigned int count = i / m_npatterns;
+ unsigned int final_i = encoded_nelts () - m_npatterns + pattern;
+ T final = (*this)[final_i];
+
+ /* If there are no steps, the final encoded value is the right one. */
+ if (m_nelts_per_pattern <= 2)
+ return final;
+
+ /* Otherwise work out the value from the last two encoded elements. */
+ T prev = (*this)[final_i - m_npatterns];
+ return derived ()->apply_step (final, count - 2,
+ derived ()->step (prev, final));
+}
+
+/* Try to start building a new vector of shape SHAPE that holds the result of
+ a unary operation on vector constant VEC. ALLOW_STEPPED_P is true if the
+ operation can handle stepped encodings directly, without having to expand
+ the full sequence.
+
+ Return true if the operation is possible, which it always is when
+ ALLOW_STEPPED_P is true. Leave the builder unchanged otherwise. */
+
+template<typename T, typename Shape, typename Derived>
+bool
+vector_builder<T, Shape, Derived>::new_unary_operation (Shape shape, T vec,
+ bool allow_stepped_p)
+{
+ poly_uint64 full_nelts = Derived::shape_nelts (shape);
+ gcc_assert (known_eq (full_nelts, Derived::nelts_of (vec)));
+ unsigned int npatterns = Derived::npatterns_of (vec);
+ unsigned int nelts_per_pattern = Derived::nelts_per_pattern_of (vec);
+ if (!allow_stepped_p && nelts_per_pattern > 2)
+ {
+ if (!full_nelts.is_constant ())
+ return false;
+ npatterns = full_nelts.to_constant ();
+ nelts_per_pattern = 1;
+ }
+ derived ()->new_vector (shape, npatterns, nelts_per_pattern);
+ return true;
+}
+
+/* Try to start building a new vector of shape SHAPE that holds the result of
+ a binary operation on vector constants VEC1 and VEC2. ALLOW_STEPPED_P is
+ true if the operation can handle stepped encodings directly, without
+ having to expand the full sequence.
+
+ Return true if the operation is possible. Leave the builder unchanged
+ otherwise. */
+
+template<typename T, typename Shape, typename Derived>
+bool
+vector_builder<T, Shape, Derived>::new_binary_operation (Shape shape,
+ T vec1, T vec2,
+ bool allow_stepped_p)
+{
+ poly_uint64 full_nelts = Derived::shape_nelts (shape);
+ gcc_assert (known_eq (full_nelts, Derived::nelts_of (vec1))
+ && known_eq (full_nelts, Derived::nelts_of (vec2)));
+ /* Conceptually we split the patterns in VEC1 and VEC2 until we have
+ an equal number for both. Each split pattern requires the same
+ number of elements per pattern as the original. E.g. splitting:
+
+ { 1, 2, 3, ... }
+
+ into two gives:
+
+ { 1, 3, 5, ... }
+ { 2, 4, 6, ... }
+
+ while splitting:
+
+ { 1, 0, ... }
+
+ into two gives:
+
+ { 1, 0, ... }
+ { 0, 0, ... }. */
+ unsigned int npatterns
+ = least_common_multiple (Derived::npatterns_of (vec1),
+ Derived::npatterns_of (vec2));
+ unsigned int nelts_per_pattern
+ = MAX (Derived::nelts_per_pattern_of (vec1),
+ Derived::nelts_per_pattern_of (vec2));
+ if (!allow_stepped_p && nelts_per_pattern > 2)
+ {
+ if (!full_nelts.is_constant ())
+ return false;
+ npatterns = full_nelts.to_constant ();
+ nelts_per_pattern = 1;
+ }
+ derived ()->new_vector (shape, npatterns, nelts_per_pattern);
+ return true;
+}
+
+/* Return the number of elements that the caller needs to operate on in
+ order to handle a binary operation on vector constants VEC1 and VEC2.
+ This static function is used instead of new_binary_operation if the
+ result of the operation is not a constant vector. */
+
+template<typename T, typename Shape, typename Derived>
+unsigned int
+vector_builder<T, Shape, Derived>::binary_encoded_nelts (T vec1, T vec2)
+{
+ poly_uint64 nelts = Derived::nelts_of (vec1);
+ gcc_assert (known_eq (nelts, Derived::nelts_of (vec2)));
+ /* See new_binary_operation for details. */
+ unsigned int npatterns
+ = least_common_multiple (Derived::npatterns_of (vec1),
+ Derived::npatterns_of (vec2));
+ unsigned int nelts_per_pattern
+ = MAX (Derived::nelts_per_pattern_of (vec1),
+ Derived::nelts_per_pattern_of (vec2));
+ unsigned HOST_WIDE_INT const_nelts;
+ if (nelts.is_constant (&const_nelts))
+ return MIN (npatterns * nelts_per_pattern, const_nelts);
+ return npatterns * nelts_per_pattern;
+}
+
+/* Return the number of leading duplicate elements in the range
+ [START:END:STEP]. The value is always at least 1. */
+
+template<typename T, typename Shape, typename Derived>
+unsigned int
+vector_builder<T, Shape, Derived>::count_dups (int start, int end,
+ int step) const
+{
+ gcc_assert ((end - start) % step == 0);
+
+ unsigned int ndups = 1;
+ for (int i = start + step;
+ i != end && derived ()->equal_p (elt (i), elt (start));
+ i += step)
+ ndups++;
+ return ndups;
+}
+
+/* Change the encoding to NPATTERNS patterns of NELTS_PER_PATTERN each,
+ but without changing the underlying vector. */
+
+template<typename T, typename Shape, typename Derived>
+void
+vector_builder<T, Shape, Derived>::reshape (unsigned int npatterns,
+ unsigned int nelts_per_pattern)
+{
+ unsigned int old_encoded_nelts = encoded_nelts ();
+ unsigned int new_encoded_nelts = npatterns * nelts_per_pattern;
+ gcc_checking_assert (new_encoded_nelts <= old_encoded_nelts);
+ unsigned int next = new_encoded_nelts - npatterns;
+ for (unsigned int i = new_encoded_nelts; i < old_encoded_nelts; ++i)
+ {
+ derived ()->note_representative (&(*this)[next], (*this)[i]);
+ next += 1;
+ if (next == new_encoded_nelts)
+ next -= npatterns;
+ }
+ m_npatterns = npatterns;
+ m_nelts_per_pattern = nelts_per_pattern;
+}
+
+/* Return true if elements [START, END) contain a repeating sequence of
+ STEP elements. */
+
+template<typename T, typename Shape, typename Derived>
+bool
+vector_builder<T, Shape, Derived>::repeating_sequence_p (unsigned int start,
+ unsigned int end,
+ unsigned int step)
+{
+ for (unsigned int i = start; i < end - step; ++i)
+ if (!derived ()->equal_p ((*this)[i], (*this)[i + step]))
+ return false;
+ return true;
+}
+
+/* Return true if elements [START, END) contain STEP interleaved linear
+ series. */
+
+template<typename T, typename Shape, typename Derived>
+bool
+vector_builder<T, Shape, Derived>::stepped_sequence_p (unsigned int start,
+ unsigned int end,
+ unsigned int step)
+{
+ if (!derived ()->allow_steps_p ())
+ return false;
+
+ for (unsigned int i = start + step * 2; i < end; ++i)
+ {
+ T elt1 = (*this)[i - step * 2];
+ T elt2 = (*this)[i - step];
+ T elt3 = (*this)[i];
+
+ if (!derived ()->integral_p (elt1)
+ || !derived ()->integral_p (elt2)
+ || !derived ()->integral_p (elt3))
+ return false;
+
+ if (maybe_ne (derived ()->step (elt1, elt2),
+ derived ()->step (elt2, elt3)))
+ return false;
+
+ if (!derived ()->can_elide_p (elt3))
+ return false;
+ }
+ return true;
+}
+
+/* Try to change the number of encoded patterns to NPATTERNS, returning
+ true on success. */
+
+template<typename T, typename Shape, typename Derived>
+bool
+vector_builder<T, Shape, Derived>::try_npatterns (unsigned int npatterns)
+{
+ if (m_nelts_per_pattern == 1)
+ {
+ /* See whether NPATTERNS is valid with the current 1-element-per-pattern
+ encoding. */
+ if (repeating_sequence_p (0, encoded_nelts (), npatterns))
+ {
+ reshape (npatterns, 1);
+ return true;
+ }
+
+ /* We can only increase the number of elements per pattern if all
+ elements are still encoded explicitly. */
+ if (!encoded_full_vector_p ())
+ return false;
+ }
+
+ if (m_nelts_per_pattern <= 2)
+ {
+ /* See whether NPATTERNS is valid with a 2-element-per-pattern
+ encoding. */
+ if (repeating_sequence_p (npatterns, encoded_nelts (), npatterns))
+ {
+ reshape (npatterns, 2);
+ return true;
+ }
+
+ /* We can only increase the number of elements per pattern if all
+ elements are still encoded explicitly. */
+ if (!encoded_full_vector_p ())
+ return false;
+ }
+
+ if (m_nelts_per_pattern <= 3)
+ {
+ /* See whether we have NPATTERNS interleaved linear series,
+ giving a 3-element-per-pattern encoding. */
+ if (stepped_sequence_p (npatterns, encoded_nelts (), npatterns))
+ {
+ reshape (npatterns, 3);
+ return true;
+ }
+ return false;
+ }
+
+ gcc_unreachable ();
+}
+
+/* Replace the current encoding with the canonical form. */
+
+template<typename T, typename Shape, typename Derived>
+void
+vector_builder<T, Shape, Derived>::finalize ()
+{
+ /* The encoding requires the same number of elements to come from each
+ pattern. */
+ gcc_assert (multiple_p (m_full_nelts, m_npatterns));
+
+ /* Allow the caller to build more elements than necessary. For example,
+ it's often convenient to build a stepped vector from the natural
+ encoding of three elements even if the vector itself only has two. */
+ unsigned HOST_WIDE_INT const_full_nelts;
+ if (m_full_nelts.is_constant (&const_full_nelts)
+ && const_full_nelts <= encoded_nelts ())
+ {
+ m_npatterns = const_full_nelts;
+ m_nelts_per_pattern = 1;
+ }
+
+ /* Try to whittle down the number of elements per pattern. That is:
+
+ 1. If we have stepped patterns whose steps are all 0, reduce the
+ number of elements per pattern from 3 to 2.
+
+ 2. If we have background fill values that are the same as the
+ foreground values, reduce the number of elements per pattern
+ from 2 to 1. */
+ while (m_nelts_per_pattern > 1
+ && repeating_sequence_p (encoded_nelts () - m_npatterns * 2,
+ encoded_nelts (), m_npatterns))
+ /* The last two sequences of M_NPATTERNS elements are equal,
+ so remove the last one. */
+ reshape (m_npatterns, m_nelts_per_pattern - 1);
+
+ if (pow2p_hwi (m_npatterns))
+ {
+ /* Try to halve the number of patterns while doing so gives a
+ valid pattern. This approach is linear in the number of
+ elements, whereas searcing from 1 up would be O(n*log(n)).
+
+ Each halving step tries to keep the number of elements per pattern
+ the same. If that isn't possible, and if all elements are still
+ explicitly encoded, the halving step can instead increase the number
+ of elements per pattern.
+
+ E.g. for:
+
+ { 0, 2, 3, 4, 5, 6, 7, 8 } npatterns == 8 full_nelts == 8
+
+ we first realize that the second half of the sequence is not
+ equal to the first, so we cannot maintain 1 element per pattern
+ for npatterns == 4. Instead we halve the number of patterns
+ and double the number of elements per pattern, treating this
+ as a "foreground" { 0, 2, 3, 4 } against a "background" of
+ { 5, 6, 7, 8 | 5, 6, 7, 8 ... }:
+
+ { 0, 2, 3, 4 | 5, 6, 7, 8 } npatterns == 4
+
+ Next we realize that this is *not* a foreround of { 0, 2 }
+ against a background of { 3, 4 | 3, 4 ... }, so the only
+ remaining option for reducing the number of patterns is
+ to use a foreground of { 0, 2 } against a stepped background
+ of { 1, 2 | 3, 4 | 5, 6 ... }. This is valid because we still
+ haven't elided any elements:
+
+ { 0, 2 | 3, 4 | 5, 6 } npatterns == 2
+
+ This in turn can be reduced to a foreground of { 0 } against a
+ stepped background of { 1 | 2 | 3 ... }:
+
+ { 0 | 2 | 3 } npatterns == 1
+
+ This last step would not have been possible for:
+
+ { 0, 0 | 3, 4 | 5, 6 } npatterns == 2. */
+ while ((m_npatterns & 1) == 0 && try_npatterns (m_npatterns / 2))
+ continue;
+
+ /* Builders of arbitrary fixed-length vectors can use:
+
+ new_vector (x, x, 1)
+
+ so that every element is specified explicitly. Handle cases
+ that are actually wrapping series, like { 0, 1, 2, 3, 0, 1, 2, 3 }
+ would be for 2-bit elements. We'll have treated them as
+ duplicates in the loop above. */
+ if (m_nelts_per_pattern == 1
+ && m_full_nelts.is_constant (&const_full_nelts)
+ && this->length () >= const_full_nelts
+ && (m_npatterns & 3) == 0
+ && stepped_sequence_p (m_npatterns / 4, const_full_nelts,
+ m_npatterns / 4))
+ {
+ reshape (m_npatterns / 4, 3);
+ while ((m_npatterns & 1) == 0 && try_npatterns (m_npatterns / 2))
+ continue;
+ }
+ }
+ else
+ /* For the non-power-of-2 case, do a simple search up from 1. */
+ for (unsigned int i = 1; i <= m_npatterns / 2; ++i)
+ if (m_npatterns % i == 0 && try_npatterns (i))
+ break;
+}
+
+#endif
diff --git a/support/cpp/gcc/warning-control.cc b/support/cpp/gcc/warning-control.cc
new file mode 100644
index 000000000..081c966d9
--- /dev/null
+++ b/support/cpp/gcc/warning-control.cc
@@ -0,0 +1,294 @@
+/* Functions to enable and disable individual warnings on an expression
+ and statement basis.
+
+ Copyright (C) 2021-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 "bitmap.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+
+/* Return the no-warning bit for EXPR. */
+
+static inline bool
+get_no_warning_bit (const_tree expr)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) expr;
+ return true;
+ // sdcpp return expr->base.nowarning_flag;
+}
+
+/* Return the no-warning bit for statement STMT. */
+
+static inline bool
+get_no_warning_bit (const gimple *stmt)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) stmt;
+ return true;
+ // sdcpp return stmt->no_warning;
+}
+
+/* Set the no-warning bit for EXPR to VALUE. */
+
+static inline void
+set_no_warning_bit (tree expr, bool value)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) expr;
+ (void) value;
+ // expr->base.nowarning_flag = value;
+}
+
+/* Set the no-warning bit for statement STMT to VALUE. */
+
+static inline void
+set_no_warning_bit (gimple *stmt, bool value)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) stmt;
+ (void) value;
+ // sdcpp stmt->no_warning = value;
+}
+
+/* Return EXPR location or 'UNKNOWN_LOCATION'. */
+
+static inline location_t
+get_location (const_tree expr)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) expr;
+ return location_t();
+#if 0 // sdcpp
+ if (DECL_P (expr))
+ return DECL_SOURCE_LOCATION (expr);
+ if (EXPR_P (expr))
+ return EXPR_LOCATION (expr);
+ return UNKNOWN_LOCATION;
+#endif
+}
+
+/* Return STMT location (may be 'UNKNOWN_LOCATION'). */
+
+static inline location_t
+get_location (const gimple *stmt)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) stmt;
+ return location_t();
+ // sdcpp return gimple_location (stmt);
+}
+
+/* Return the no-warning bitmap for decl/expression EXPR. */
+
+static nowarn_spec_t *
+get_nowarn_spec (const_tree expr)
+{
+ const location_t loc = get_location (expr);
+
+ if (RESERVED_LOCATION_P (loc))
+ return NULL;
+
+ if (!get_no_warning_bit (expr))
+ return NULL;
+
+ return nowarn_map ? nowarn_map->get (loc) : NULL;
+}
+
+/* Return the no-warning bitmap for statement STMT. */
+
+static nowarn_spec_t *
+get_nowarn_spec (const gimple *stmt)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) stmt;
+ return 0;
+#if 0 //sdcpp
+ const location_t loc = get_location (stmt);
+
+ if (RESERVED_LOCATION_P (loc))
+ return NULL;
+
+ if (!get_no_warning_bit (stmt))
+ return NULL;
+
+ return nowarn_map ? nowarn_map->get (loc) : NULL;
+#endif
+}
+
+/* Return true if warning OPT is suppressed for decl/expression EXPR.
+ By default tests the disposition for any warning. */
+
+bool
+warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
+{
+ const nowarn_spec_t *spec = get_nowarn_spec (expr);
+
+ if (!spec)
+ return get_no_warning_bit (expr);
+
+ const nowarn_spec_t optspec (opt);
+ bool dis = *spec & optspec;
+ gcc_assert (get_no_warning_bit (expr) || !dis);
+ return dis;
+}
+
+/* Return true if warning OPT is suppressed for statement STMT.
+ By default tests the disposition for any warning. */
+
+bool
+warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
+{
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) stmt;
+ (void) opt;
+ return true;
+#if 0
+ const nowarn_spec_t *spec = get_nowarn_spec (stmt);
+
+ if (!spec)
+ /* Fall back on the single no-warning bit. */
+ return get_no_warning_bit (stmt);
+
+ const nowarn_spec_t optspec (opt);
+ bool dis = *spec & optspec;
+ gcc_assert (get_no_warning_bit (stmt) || !dis);
+ return dis;
+#endif
+}
+
+/* Enable, or by default disable, a warning for the expression.
+ The wildcard OPT of -1 controls all warnings. */
+
+void
+suppress_warning (tree expr, opt_code opt /* = all_warnings */,
+ bool supp /* = true */)
+{
+ if (opt == no_warning)
+ return;
+
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) expr;
+ (void) supp;
+#if 0 // sdcpp
+ const location_t loc = get_location (expr);
+
+ if (!RESERVED_LOCATION_P (loc))
+ supp = suppress_warning_at (loc, opt, supp) || supp;
+ set_no_warning_bit (expr, supp);
+#endif // sdcpp
+}
+
+/* Enable, or by default disable, a warning for the statement STMT.
+ The wildcard OPT of -1 controls all warnings. */
+
+void
+suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
+ bool supp /* = true */)
+{
+ if (opt == no_warning)
+ return;
+
+ fprintf(stderr, "incomplete %s\n", __func__);
+ (void) stmt;
+ (void) supp;
+#if 0 // sdcpp
+
+ const location_t loc = get_location (stmt);
+
+ if (!RESERVED_LOCATION_P (loc))
+ supp = suppress_warning_at (loc, opt, supp) || supp;
+ set_no_warning_bit (stmt, supp);
+#endif // sdcpp
+}
+
+/* Copy the warning disposition mapping between an expression and/or
+ a statement. */
+
+template <class ToType, class FromType>
+void copy_warning (ToType to, FromType from)
+{
+ const location_t to_loc = get_location (to);
+
+ bool supp = get_no_warning_bit (from);
+
+ nowarn_spec_t *from_spec = get_nowarn_spec (from);
+ if (RESERVED_LOCATION_P (to_loc))
+ /* We cannot set no-warning dispositions for 'to', so we have no chance but
+ lose those potentially set for 'from'. */
+ ;
+ else
+ {
+ if (from_spec)
+ {
+ /* If there's an entry in the map the no-warning bit must be set. */
+ gcc_assert (supp);
+
+ gcc_checking_assert (nowarn_map);
+ nowarn_spec_t tem = *from_spec;
+ nowarn_map->put (to_loc, tem);
+ }
+ else
+ {
+ if (nowarn_map)
+ nowarn_map->remove (to_loc);
+ }
+ }
+
+ /* The no-warning bit might be set even if the map has not been consulted, or
+ otherwise if there's no entry in the map. */
+ set_no_warning_bit (to, supp);
+}
+
+/* Copy the warning disposition mapping from one expression to another. */
+
+void
+copy_warning (tree to, const_tree from)
+{
+ copy_warning<tree, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from a statement to an expression. */
+
+void
+copy_warning (tree to, const gimple *from)
+{
+ copy_warning<tree, const gimple *>(to, from);
+}
+
+/* Copy the warning disposition mapping from an expression to a statement. */
+
+void
+copy_warning (gimple *to, const_tree from)
+{
+ copy_warning<gimple *, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from one statement to another. */
+
+void
+copy_warning (gimple *to, const gimple *from)
+{
+ copy_warning<gimple *, const gimple *>(to, from);
+}